mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 13:00:26 -04:00 
			
		
		
		
	M17 modulator: SMS packet +
This commit is contained in:
		
							parent
							
								
									dd2233f763
								
							
						
					
					
						commit
						f10da64717
					
				| @ -39,6 +39,7 @@ public: | ||||
|     using codec_frame_t = std::array<uint8_t, 16>; | ||||
|     using payload_t = std::array<uint8_t, 34>;      // Bytes in the payload of a data frame.
 | ||||
|     using frame_t = std::array<uint8_t, 46>;        // M17 frame (without sync word).
 | ||||
|     using packet_t = std::array<uint8_t, 25>;       // Packet payload
 | ||||
| 
 | ||||
|     static constexpr std::array<uint8_t, 2> SYNC_WORD = {0x32, 0x43}; | ||||
|     static constexpr std::array<uint8_t, 2> LSF_SYNC_WORD = {0x55, 0xF7}; | ||||
| @ -57,6 +58,31 @@ public: | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     template <typename T, size_t N> | ||||
|     static std::array<int8_t, N * 4> bytes_to_symbols(const std::array<T, N>& bytes) | ||||
|     { | ||||
|         std::array<int8_t, N * 4> result; | ||||
|         size_t index = 0; | ||||
| 
 | ||||
|         for (auto b : bytes) | ||||
|         { | ||||
|             for (size_t i = 0; i != 4; ++i) | ||||
|             { | ||||
|                 result[index++] = bits_to_symbol(b >> 6); | ||||
|                 b <<= 2; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     static | ||||
|     void make_preamble(std::array<uint8_t, 48>& preamble_bytes) | ||||
|     { | ||||
|         // Preamble is simple... bytes -> symbols.
 | ||||
|         preamble_bytes.fill(0x77); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Encode each LSF segment into a Golay-encoded LICH segment bitstream. | ||||
|      */ | ||||
| @ -109,7 +135,7 @@ public: | ||||
|     /**
 | ||||
|      * Construct the link setup frame and split into LICH segments. | ||||
|      */ | ||||
|     void make_link_setup(lich_t& lich, mobilinkd::M17Modulator::frame_t lsf) | ||||
|     void make_link_setup(lich_t& lich, mobilinkd::M17Modulator::frame_t lsf_frame) | ||||
|     { | ||||
|         using namespace mobilinkd; | ||||
| 
 | ||||
| @ -141,12 +167,14 @@ public: | ||||
|         } | ||||
| 
 | ||||
|         auto encoded = conv_encode(lsf); | ||||
|         auto size = puncture_bytes(encoded, lsf_frame, P1); | ||||
| 
 | ||||
|         auto size = puncture_bytes(encoded, lsf, P1); | ||||
|         assert(size == 368); | ||||
|         if (size != 368) { | ||||
|             std::cerr << "make_link_setup: incorrect size (not 368)" << size; | ||||
|         } | ||||
| 
 | ||||
|         interleaver_.interleave(lsf); | ||||
|         randomizer_(lsf); | ||||
|         interleaver_.interleave(lsf_frame); | ||||
|         randomizer_(lsf_frame); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
| @ -168,7 +196,7 @@ public: | ||||
|      * Assemble the audio frame payload by appending the frame number, encoded audio, | ||||
|      * and CRC, then convolutionally coding and puncturing the data. | ||||
|      */ | ||||
|     payload_t make_payload(uint16_t frame_number, const codec_frame_t& payload) | ||||
|     payload_t make_audio_payload(uint16_t frame_number, const codec_frame_t& payload) | ||||
|     { | ||||
|         std::array<uint8_t, 20> data;   // FN, Audio, CRC = 2 + 16 + 2;
 | ||||
|         data[0] = uint8_t((frame_number >> 8) & 0xFF); | ||||
| @ -188,7 +216,47 @@ public: | ||||
| 
 | ||||
|         payload_t punctured; | ||||
|         auto size = puncture_bytes(encoded, punctured, mobilinkd::P2); | ||||
|         assert(size == 272); | ||||
| 
 | ||||
|         if (size != 272) { | ||||
|             std::cerr << "mobilinkd::M17Modulator::make_audio_payload: incorrect size (not 272)" << size; | ||||
|         } | ||||
| 
 | ||||
|         return punctured; | ||||
|     } | ||||
| 
 | ||||
|     frame_t make_packet_frame(uint8_t packet_number, bool last_packet, packet_t packet, int packet_size) | ||||
|     { | ||||
|         std::array<uint8_t, 26> packet_assembly; | ||||
|         packet_assembly.fill(0); | ||||
|         std::copy(packet.begin(), packet.begin() + packet_size, packet_assembly.begin()); | ||||
| 
 | ||||
|         if (packet_number == 0) { | ||||
|             crc_.reset(); | ||||
|         } | ||||
| 
 | ||||
|         for (int i = 0; i < packet_size; i++) { | ||||
|             crc_(packet[i]); | ||||
|         } | ||||
| 
 | ||||
|         if (last_packet) | ||||
|         { | ||||
|             packet_assembly[25] = 0x80 | (packet_size<<2); | ||||
|             packet_assembly[packet_size]   = crc_.get_bytes()[1]; | ||||
|             packet_assembly[packet_size+1] = crc_.get_bytes()[0]; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             packet_assembly[25] = (packet_number<<2); | ||||
|         } | ||||
| 
 | ||||
|         std::array<uint8_t, 2*26+1> encoded = conv_encode(packet_assembly); | ||||
|         frame_t punctured; | ||||
|         auto size = puncture_bytes(encoded, punctured, mobilinkd::P3); | ||||
| 
 | ||||
|         if (size != 368) { | ||||
|             std::cerr << "mobilinkd::M17Modulator::make_packet_frame: incorrect size (not 368)" << size; | ||||
|         } | ||||
| 
 | ||||
|         return punctured; | ||||
|     } | ||||
| 
 | ||||
| @ -280,24 +348,6 @@ private: | ||||
|         return encoded_call; | ||||
|     } | ||||
| 
 | ||||
|     template <typename T, size_t N> | ||||
|     static std::array<int8_t, N * 4> bytes_to_symbols(const std::array<T, N>& bytes) | ||||
|     { | ||||
|         std::array<int8_t, N * 4> result; | ||||
|         size_t index = 0; | ||||
| 
 | ||||
|         for (auto b : bytes) | ||||
|         { | ||||
|             for (size_t i = 0; i != 4; ++i) | ||||
|             { | ||||
|                 result[index++] = bits_to_symbol(b >> 6); | ||||
|                 b <<= 2; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     template <typename T, size_t N> | ||||
|     static std::array<T, N * 2 + 1> conv_encode(std::array<T, N> data) | ||||
|     { | ||||
|  | ||||
| @ -4,6 +4,7 @@ set(modm17_SOURCES | ||||
|     m17mod.cpp | ||||
|     m17modbaseband.cpp | ||||
|     m17modsource.cpp | ||||
|     m17modprocessor.cpp | ||||
| 	m17modplugin.cpp | ||||
|     m17modsettings.cpp | ||||
|     m17modwebapiadapter.cpp | ||||
| @ -13,6 +14,7 @@ set(modm17_HEADERS | ||||
| 	m17mod.h | ||||
|     m17modbaseband.h | ||||
|     m17modsource.h | ||||
|     m17modprocessor.h | ||||
| 	m17modplugin.h | ||||
|     m17modsettings.h | ||||
|     m17modwebapiadapter.h | ||||
| @ -20,6 +22,8 @@ set(modm17_HEADERS | ||||
| 
 | ||||
| include_directories( | ||||
|     ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client | ||||
|     ${CODEC2_INCLUDE_DIR} | ||||
|     ${CMAKE_SOURCE_DIR}/modems | ||||
| ) | ||||
| 
 | ||||
| if(NOT SERVER_MODE) | ||||
| @ -48,12 +52,18 @@ add_library(${TARGET_NAME} SHARED | ||||
| 	${modm17_SOURCES} | ||||
| ) | ||||
| 
 | ||||
| if(CODEC2_EXTERNAL) | ||||
|     add_dependencies(${TARGET_NAME} codec2) | ||||
| endif() | ||||
| 
 | ||||
| target_link_libraries(${TARGET_NAME} | ||||
|     Qt5::Core | ||||
|     ${TARGET_LIB} | ||||
| 	sdrbase | ||||
| 	${TARGET_LIB_GUI} | ||||
|     swagger | ||||
|     ${CODEC2_LIBRARIES} | ||||
|     modems | ||||
| ) | ||||
| 
 | ||||
| install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER}) | ||||
|  | ||||
| @ -294,7 +294,9 @@ void M17Mod::applySettings(const M17ModSettings& settings, bool force) | ||||
|             << " m_toneFrequency: " << settings.m_toneFrequency | ||||
|             << " m_channelMute: " << settings.m_channelMute | ||||
|             << " m_playLoop: " << settings.m_playLoop | ||||
|             << " m_modAFInput " << settings.m_modAFInput | ||||
|             << " m_m17Mode " << settings.m_m17Mode | ||||
|             << " m_audioType " << settings.m_audioType | ||||
|             << " m_packetType " << settings.m_packetType | ||||
|             << " m_audioDeviceName: " << settings.m_audioDeviceName | ||||
|             << " m_useReverseAPI: " << settings.m_useReverseAPI | ||||
|             << " m_reverseAPIAddress: " << settings.m_reverseAPIAddress | ||||
| @ -320,8 +322,14 @@ void M17Mod::applySettings(const M17ModSettings& settings, bool force) | ||||
|     if ((settings.m_playLoop != m_settings.m_playLoop) || force) { | ||||
|         reverseAPIKeys.append("playLoop"); | ||||
|     } | ||||
|     if ((settings.m_modAFInput != m_settings.m_modAFInput) || force) { | ||||
|         reverseAPIKeys.append("modAFInput"); | ||||
|     if ((settings.m_audioType != m_settings.m_audioType) || force) { | ||||
|         reverseAPIKeys.append("audioType"); | ||||
|     } | ||||
|     if ((settings.m_packetType != m_settings.m_packetType) || force) { | ||||
|         reverseAPIKeys.append("packetType"); | ||||
|     } | ||||
|     if ((settings.m_m17Mode != m_settings.m_m17Mode) || force) { | ||||
|         reverseAPIKeys.append("m17Mode"); | ||||
|     } | ||||
|     if((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) { | ||||
|         reverseAPIKeys.append("rfBandwidth"); | ||||
| @ -470,8 +478,14 @@ void M17Mod::webapiUpdateChannelSettings( | ||||
|     if (channelSettingsKeys.contains("inputFrequencyOffset")) { | ||||
|         settings.m_inputFrequencyOffset = response.getM17ModSettings()->getInputFrequencyOffset(); | ||||
|     } | ||||
|     if (channelSettingsKeys.contains("modAFInput")) { | ||||
|         settings.m_modAFInput = (M17ModSettings::M17ModInputAF) response.getM17ModSettings()->getModAfInput(); | ||||
|     if (channelSettingsKeys.contains("m17Mode")) { | ||||
|         settings.m_m17Mode = (M17ModSettings::M17Mode) response.getM17ModSettings()->getM17Mode(); | ||||
|     } | ||||
|     if (channelSettingsKeys.contains("audioType")) { | ||||
|         settings.m_audioType = (M17ModSettings::AudioType) response.getM17ModSettings()->getAudioType(); | ||||
|     } | ||||
|     if (channelSettingsKeys.contains("packetType")) { | ||||
|         settings.m_packetType = (M17ModSettings::PacketType) response.getM17ModSettings()->getPacketType(); | ||||
|     } | ||||
|     if (channelSettingsKeys.contains("playLoop")) { | ||||
|         settings.m_playLoop = response.getM17ModSettings()->getPlayLoop() != 0; | ||||
| @ -533,7 +547,9 @@ void M17Mod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& respon | ||||
|     response.getM17ModSettings()->setChannelMute(settings.m_channelMute ? 1 : 0); | ||||
|     response.getM17ModSettings()->setFmDeviation(settings.m_fmDeviation); | ||||
|     response.getM17ModSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset); | ||||
|     response.getM17ModSettings()->setModAfInput((int) settings.m_modAFInput); | ||||
|     response.getM17ModSettings()->setM17Mode((int) settings.m_m17Mode); | ||||
|     response.getM17ModSettings()->setAudioType((int) settings.m_audioType); | ||||
|     response.getM17ModSettings()->setPacketType((int) settings.m_packetType); | ||||
|     response.getM17ModSettings()->setPlayLoop(settings.m_playLoop ? 1 : 0); | ||||
|     response.getM17ModSettings()->setRfBandwidth(settings.m_rfBandwidth); | ||||
|     response.getM17ModSettings()->setRgbColor(settings.m_rgbColor); | ||||
| @ -673,8 +689,14 @@ void M17Mod::webapiFormatChannelSettings( | ||||
|     if (channelSettingsKeys.contains("inputFrequencyOffset") || force) { | ||||
|         swgM17ModSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset); | ||||
|     } | ||||
|     if (channelSettingsKeys.contains("modAFInput") || force) { | ||||
|         swgM17ModSettings->setModAfInput((int) settings.m_modAFInput); | ||||
|     if (channelSettingsKeys.contains("m17Mode") || force) { | ||||
|         swgM17ModSettings->setM17Mode((int) settings.m_m17Mode); | ||||
|     } | ||||
|     if (channelSettingsKeys.contains("audioType") || force) { | ||||
|         swgM17ModSettings->setAudioType((int) settings.m_audioType); | ||||
|     } | ||||
|     if (channelSettingsKeys.contains("packetType") || force) { | ||||
|         swgM17ModSettings->setPacketType((int) settings.m_packetType); | ||||
|     } | ||||
|     if (channelSettingsKeys.contains("audioDeviceName") || force) { | ||||
|         swgM17ModSettings->setAudioDeviceName(new QString(settings.m_audioDeviceName)); | ||||
| @ -764,3 +786,8 @@ int M17Mod::getFeedbackAudioSampleRate() const | ||||
| { | ||||
|     return m_basebandSource->getFeedbackAudioSampleRate(); | ||||
| } | ||||
| 
 | ||||
| void M17Mod::sendPacket() | ||||
| { | ||||
|     m_basebandSource->sendPacket(); | ||||
| } | ||||
|  | ||||
| @ -233,6 +233,7 @@ public: | ||||
|     uint32_t getNumberOfDeviceStreams() const; | ||||
|     int getAudioSampleRate() const; | ||||
|     int getFeedbackAudioSampleRate() const; | ||||
|     void sendPacket(); | ||||
| 
 | ||||
|     static const char* const m_channelIdURI; | ||||
|     static const char* const m_channelId; | ||||
|  | ||||
| @ -196,12 +196,12 @@ void M17ModBaseband::applySettings(const M17ModSettings& settings, bool force) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if ((settings.m_modAFInput != m_settings.m_modAFInput) || force) | ||||
|     if ((settings.m_audioType != m_settings.m_audioType) || force) | ||||
|     { | ||||
|         AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager(); | ||||
|         int audioDeviceIndex = audioDeviceManager->getInputDeviceIndex(settings.m_audioDeviceName); | ||||
| 
 | ||||
|         if (settings.m_modAFInput == M17ModSettings::M17ModInputAudio) { | ||||
|         if (settings.m_audioType == M17ModSettings::AudioInput) { | ||||
|             audioDeviceManager->addAudioSource(getAudioFifo(), getInputMessageQueue(), audioDeviceIndex); | ||||
|         } else { | ||||
|             audioDeviceManager->removeAudioSource(getAudioFifo()); | ||||
|  | ||||
| @ -70,6 +70,7 @@ public: | ||||
|     AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); } | ||||
|     AudioFifo *getFeedbackAudioFifo() { return m_source.getFeedbackAudioFifo(); } | ||||
|     void setChannel(ChannelAPI *channel); | ||||
|     void sendPacket() { m_source.sendPacket(); } | ||||
| 
 | ||||
| signals: | ||||
| 	/**
 | ||||
|  | ||||
| @ -182,6 +182,22 @@ void M17ModGUI::on_toneFrequency_valueChanged(int value) | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::on_fmAudio_toggled(bool checked) | ||||
| { | ||||
|     m_fmAudioMode = checked; | ||||
| 
 | ||||
|     if ((checked) && (m_settings.m_m17Mode == M17ModSettings::M17Mode::M17ModeM17Audio)) | ||||
|     { | ||||
|         m_settings.m_m17Mode = M17ModSettings::M17Mode::M17ModeFMAudio; | ||||
|         applySettings(); | ||||
|     } | ||||
|     else if ((!checked) && (m_settings.m_m17Mode == M17ModSettings::M17Mode::M17ModeFMAudio)) | ||||
|     { | ||||
|         m_settings.m_m17Mode = M17ModSettings::M17Mode::M17ModeM17Audio; | ||||
|         applySettings(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::on_channelMute_toggled(bool checked) | ||||
| { | ||||
|     m_settings.m_channelMute = checked; | ||||
| @ -196,9 +212,13 @@ void M17ModGUI::on_playLoop_toggled(bool checked) | ||||
| 
 | ||||
| void M17ModGUI::on_play_toggled(bool checked) | ||||
| { | ||||
|     ui->tone->setEnabled(!checked); // release other source inputs
 | ||||
|     ui->mic->setEnabled(!checked); | ||||
|     m_settings.m_modAFInput = checked ? M17ModSettings::M17ModInputFile : M17ModSettings::M17ModInputNone; | ||||
|     m_settings.m_audioType = checked ? M17ModSettings::AudioFile : M17ModSettings::AudioNone; | ||||
|     m_settings.m_m17Mode = checked ? | ||||
|         m_fmAudioMode ? | ||||
|             M17ModSettings::M17Mode::M17ModeFMAudio | ||||
|             : M17ModSettings::M17Mode::M17ModeM17Audio | ||||
|         : M17ModSettings::M17ModeNone; | ||||
|     displayModes(); | ||||
|     applySettings(); | ||||
|     ui->navTimeSlider->setEnabled(!checked); | ||||
|     m_enableNavTime = !checked; | ||||
| @ -206,17 +226,20 @@ void M17ModGUI::on_play_toggled(bool checked) | ||||
| 
 | ||||
| void M17ModGUI::on_tone_toggled(bool checked) | ||||
| { | ||||
|     ui->play->setEnabled(!checked); // release other source inputs
 | ||||
|     ui->mic->setEnabled(!checked); | ||||
|     m_settings.m_modAFInput = checked ? M17ModSettings::M17ModInputTone : M17ModSettings::M17ModInputNone; | ||||
|     m_settings.m_m17Mode = checked ? M17ModSettings::M17ModeFMTone : M17ModSettings::M17ModeNone; | ||||
|     displayModes(); | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::on_mic_toggled(bool checked) | ||||
| { | ||||
|     ui->play->setEnabled(!checked); // release other source inputs
 | ||||
|     ui->tone->setEnabled(!checked); // release other source inputs
 | ||||
|     m_settings.m_modAFInput = checked ? M17ModSettings::M17ModInputAudio : M17ModSettings::M17ModInputNone; | ||||
|     m_settings.m_audioType = checked ? M17ModSettings::AudioInput : M17ModSettings::AudioNone; | ||||
|     m_settings.m_m17Mode = checked ? | ||||
|         m_fmAudioMode ? | ||||
|             M17ModSettings::M17Mode::M17ModeFMAudio | ||||
|             : M17ModSettings::M17Mode::M17ModeM17Audio | ||||
|         : M17ModSettings::M17ModeNone; | ||||
|     displayModes(); | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| @ -261,6 +284,66 @@ void M17ModGUI::on_showFileDialog_clicked(bool checked) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::on_packetMode_toggled(bool checked) | ||||
| { | ||||
|     m_settings.m_m17Mode = checked ? M17ModSettings::M17ModeM17Packet : M17ModSettings::M17ModeNone; | ||||
|     displayModes(); | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::on_sendPacket_clicked(bool) | ||||
| { | ||||
|     m_m17Mod->sendPacket(); | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::on_loopPacket_toggled(bool checked) | ||||
| { | ||||
|     (void) checked; | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::on_loopPacketInterval_valueChanged(int value) | ||||
| { | ||||
|     (void) value; | ||||
|     // TODO
 | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::on_packetDataWidget_currentChanged(int index) | ||||
| { | ||||
|     m_settings.m_packetType = indexToPacketType(index); | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::on_source_editingFinished() | ||||
| { | ||||
|     m_settings.m_sourceCall = ui->source->text(); | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::on_destination_editingFinished() | ||||
| { | ||||
|     m_settings.m_destCall = ui->destination->text(); | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::on_insertPosition_toggled(bool checked) | ||||
| { | ||||
|     m_settings.m_insertPosition = checked; | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::on_can_valueChanged(int value) | ||||
| { | ||||
|     m_settings.m_can = value; | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::on_smsText_editingFinished() | ||||
| { | ||||
|     m_settings.m_smsText = ui->smsText->toPlainText(); | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::configureFileName() | ||||
| { | ||||
|     qDebug() << "M17ModGUI::configureFileName: " << m_fileName.toStdString().c_str(); | ||||
| @ -333,6 +416,7 @@ M17ModGUI::M17ModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam | ||||
|     m_deviceCenterFrequency(0), | ||||
|     m_basebandSampleRate(1), | ||||
| 	m_doApplySettings(true), | ||||
|     m_fmAudioMode(false), | ||||
|     m_recordLength(0), | ||||
|     m_recordSampleRate(48000), | ||||
|     m_samplesCount(0), | ||||
| @ -447,23 +531,101 @@ void M17ModGUI::displaySettings() | ||||
|     ui->channelMute->setChecked(m_settings.m_channelMute); | ||||
|     ui->playLoop->setChecked(m_settings.m_playLoop); | ||||
| 
 | ||||
|     ui->tone->setEnabled((m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputTone) || (m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputNone)); | ||||
|     ui->mic->setEnabled((m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputAudio) || (m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputNone)); | ||||
|     ui->play->setEnabled((m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputFile) || (m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputNone)); | ||||
| 
 | ||||
|     ui->tone->setChecked(m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputTone); | ||||
|     ui->mic->setChecked(m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputAudio); | ||||
|     ui->play->setChecked(m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputFile); | ||||
|     displayModes(); | ||||
|     ui->fmAudio->setChecked(m_fmAudioMode); | ||||
|     ui->packetDataWidget->setCurrentIndex(packetTypeToIndex(m_settings.m_packetType)); | ||||
| 
 | ||||
|     ui->feedbackEnable->setChecked(m_settings.m_feedbackAudioEnable); | ||||
|     ui->feedbackVolume->setValue(roundf(m_settings.m_feedbackVolumeFactor * 100.0)); | ||||
|     ui->feedbackVolumeText->setText(QString("%1").arg(m_settings.m_feedbackVolumeFactor, 0, 'f', 2)); | ||||
| 
 | ||||
|     ui->source->setText(m_settings.m_sourceCall); | ||||
|     ui->destination->setText(m_settings.m_destCall); | ||||
|     ui->insertPosition->setChecked(m_settings.m_insertPosition); | ||||
|     ui->can->setValue(m_settings.m_can); | ||||
| 
 | ||||
|     ui->smsText->setText(m_settings.m_smsText); | ||||
| 
 | ||||
|     ui->aprsFromText->setText(m_settings.m_aprsCallsign); | ||||
|     ui->aprsData->setText(m_settings.m_aprsData); | ||||
|     ui->aprsTo->lineEdit()->setText(m_settings.m_aprsTo); | ||||
|     ui->aprsVia->lineEdit()->setText(m_settings.m_aprsVia); | ||||
| 
 | ||||
|     getRollupContents()->restoreState(m_rollupState); | ||||
|     updateAbsoluteCenterFrequency(); | ||||
|     blockApplySettings(false); | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::displayModes() | ||||
| { | ||||
|     qDebug("M17ModGUI::displayModes: m_m17Mode: %d m_audioType: %d", | ||||
|         (int) m_settings.m_m17Mode, (int) m_settings.m_audioType); | ||||
| 
 | ||||
|     if (m_settings.m_m17Mode ==  M17ModSettings::M17Mode::M17ModeM17Packet) | ||||
|     { | ||||
|         ui->packetMode->setChecked(true); | ||||
|         ui->packetMode->setEnabled(true); | ||||
|         ui->tone->setChecked(false); | ||||
|         ui->mic->setChecked(false); | ||||
|         ui->play->setChecked(false); | ||||
|         ui->tone->setEnabled(false); | ||||
|         ui->mic->setEnabled(false); | ||||
|         ui->play->setEnabled(false); | ||||
|     } | ||||
|     else if (m_settings.m_m17Mode ==  M17ModSettings::M17Mode::M17ModeFMTone) | ||||
|     { | ||||
|         ui->tone->setChecked(true); | ||||
|         ui->tone->setEnabled(true); | ||||
|         ui->packetMode->setChecked(false); | ||||
|         ui->mic->setChecked(false); | ||||
|         ui->play->setChecked(false); | ||||
|         ui->packetMode->setEnabled(false); | ||||
|         ui->mic->setEnabled(false); | ||||
|         ui->play->setEnabled(false); | ||||
|     } | ||||
|     else if ((m_settings.m_m17Mode ==  M17ModSettings::M17Mode::M17ModeFMAudio) || | ||||
|         (m_settings.m_m17Mode ==  M17ModSettings::M17Mode::M17ModeM17Audio)) | ||||
|     { | ||||
|         ui->tone->setChecked(false); | ||||
|         ui->packetMode->setChecked(false); | ||||
|         ui->tone->setEnabled(false); | ||||
|         ui->packetMode->setEnabled(false); | ||||
| 
 | ||||
|         if (m_settings.m_audioType == M17ModSettings::AudioType::AudioInput) | ||||
|         { | ||||
|             ui->mic->setChecked(true); | ||||
|             ui->mic->setEnabled(true); | ||||
|             ui->play->setChecked(false); | ||||
|             ui->play->setEnabled(false); | ||||
|         } | ||||
|         else if (m_settings.m_audioType == M17ModSettings::AudioType::AudioFile) | ||||
|         { | ||||
|             ui->play->setChecked(true); | ||||
|             ui->play->setEnabled(true); | ||||
|             ui->mic->setChecked(false); | ||||
|             ui->mic->setEnabled(false); | ||||
|         } | ||||
|         else if (m_settings.m_audioType == M17ModSettings::AudioType::AudioNone) | ||||
|         { | ||||
|             ui->mic->setChecked(false); | ||||
|             ui->play->setChecked(false); | ||||
|             ui->mic->setEnabled(true); | ||||
|             ui->play->setEnabled(true); | ||||
|         } | ||||
|     } | ||||
|     else if (m_settings.m_m17Mode == M17ModSettings::M17Mode::M17ModeNone) | ||||
|     { | ||||
|         ui->packetMode->setChecked(false); | ||||
|         ui->tone->setChecked(false); | ||||
|         ui->mic->setChecked(false); | ||||
|         ui->play->setChecked(false); | ||||
|         ui->packetMode->setEnabled(true); | ||||
|         ui->tone->setEnabled(true); | ||||
|         ui->mic->setEnabled(true); | ||||
|         ui->play->setEnabled(true); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::leaveEvent(QEvent* event) | ||||
| { | ||||
| 	m_channelMarker.setHighlighted(false); | ||||
| @ -534,7 +696,7 @@ void M17ModGUI::tick() | ||||
|         m_feedbackAudioSampleRate = feedbackAudioSampleRate; | ||||
|     } | ||||
| 
 | ||||
|     if (((++m_tickCount & 0xf) == 0) && (m_settings.m_modAFInput == M17ModSettings::M17ModInputFile)) | ||||
|     if (((++m_tickCount & 0xf) == 0) && (m_settings.m_audioType == M17ModSettings::AudioFile)) | ||||
|     { | ||||
|         M17Mod::MsgConfigureFileSourceStreamTiming* message = M17Mod::MsgConfigureFileSourceStreamTiming::create(); | ||||
|         m_m17Mod->getInputMessageQueue()->push(message); | ||||
| @ -591,9 +753,41 @@ void M17ModGUI::makeUIConnections() | ||||
|     QObject::connect(ui->showFileDialog, &QPushButton::clicked, this, &M17ModGUI::on_showFileDialog_clicked); | ||||
|     QObject::connect(ui->feedbackEnable, &QToolButton::toggled, this, &M17ModGUI::on_feedbackEnable_toggled); | ||||
|     QObject::connect(ui->feedbackVolume, &QDial::valueChanged, this, &M17ModGUI::on_feedbackVolume_valueChanged); | ||||
|     QObject::connect(ui->fmAudio, &ButtonSwitch::toggled, this, &M17ModGUI::on_fmAudio_toggled); | ||||
|     QObject::connect(ui->packetMode, &ButtonSwitch::toggled, this, &M17ModGUI::on_packetMode_toggled); | ||||
|     QObject::connect(ui->sendPacket, &QPushButton::clicked, this, &M17ModGUI::on_sendPacket_clicked); | ||||
|     QObject::connect(ui->loopPacket, &ButtonSwitch::toggled, this, &M17ModGUI::on_loopPacket_toggled); | ||||
|     QObject::connect(ui->loopPacketInterval, &QDial::valueChanged, this, &M17ModGUI::on_loopPacketInterval_valueChanged); | ||||
|     QObject::connect(ui->smsText, &CustomTextEdit::editingFinished, this, &M17ModGUI::on_smsText_editingFinished); | ||||
| } | ||||
| 
 | ||||
| void M17ModGUI::updateAbsoluteCenterFrequency() | ||||
| { | ||||
|     setStatusFrequency(m_deviceCenterFrequency + m_settings.m_inputFrequencyOffset); | ||||
| } | ||||
| 
 | ||||
| M17ModSettings::PacketType M17ModGUI::indexToPacketType(int index) | ||||
| { | ||||
|     switch(index) | ||||
|     { | ||||
|         case 0: | ||||
|             return M17ModSettings::PacketType::PacketSMS; | ||||
|         case 1: | ||||
|             return M17ModSettings::PacketType::PacketAPRS; | ||||
|         default: | ||||
|             return M17ModSettings::PacketType::PacketNone; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int M17ModGUI::packetTypeToIndex(M17ModSettings::PacketType type) | ||||
| { | ||||
|     switch(type) | ||||
|     { | ||||
|         case M17ModSettings::PacketType::PacketSMS: | ||||
|             return 0; | ||||
|         case M17ModSettings::PacketType::PacketAPRS: | ||||
|             return 1; | ||||
|         default: | ||||
|             return -1; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -76,6 +76,7 @@ private: | ||||
|     qint64 m_deviceCenterFrequency; | ||||
|     int m_basebandSampleRate; | ||||
|     bool m_doApplySettings; | ||||
|     bool m_fmAudioMode; | ||||
| 
 | ||||
|     M17Mod* m_m17Mod; | ||||
|     MovingAverageUtil<double, double, 20> m_channelPowerDbAvg; | ||||
| @ -88,7 +89,6 @@ private: | ||||
|     int m_feedbackAudioSampleRate; | ||||
|     std::size_t m_tickCount; | ||||
|     bool m_enableNavTime; | ||||
|     M17ModSettings::M17ModInputAF m_modAFInput; | ||||
|     MessageQueue m_inputMessageQueue; | ||||
|     QRegExpValidator m_dcsCodeValidator; | ||||
| 
 | ||||
| @ -98,11 +98,14 @@ private: | ||||
|     void blockApplySettings(bool block); | ||||
|     void applySettings(bool force = false); | ||||
|     void displaySettings(); | ||||
|     void displayModes(); | ||||
|     void updateWithStreamData(); | ||||
|     void updateWithStreamTime(); | ||||
|     bool handleMessage(const Message& message); | ||||
|     void makeUIConnections(); | ||||
|     void updateAbsoluteCenterFrequency(); | ||||
|     M17ModSettings::PacketType indexToPacketType(int index); | ||||
|     int packetTypeToIndex(M17ModSettings::PacketType type); | ||||
| 
 | ||||
|     void leaveEvent(QEvent*); | ||||
|     void enterEvent(QEvent*); | ||||
| @ -115,6 +118,7 @@ private slots: | ||||
|     void on_rfBW_valueChanged(int value); | ||||
|     void on_fmDev_valueChanged(int value); | ||||
|     void on_toneFrequency_valueChanged(int value); | ||||
|     void on_fmAudio_toggled(bool checked); | ||||
|     void on_volume_valueChanged(int value); | ||||
|     void on_channelMute_toggled(bool checked); | ||||
|     void on_tone_toggled(bool checked); | ||||
| @ -128,6 +132,17 @@ private slots: | ||||
|     void on_feedbackEnable_toggled(bool checked); | ||||
|     void on_feedbackVolume_valueChanged(int value); | ||||
| 
 | ||||
|     void on_packetMode_toggled(bool checked); | ||||
|     void on_sendPacket_clicked(bool checked); | ||||
|     void on_loopPacket_toggled(bool checked); | ||||
|     void on_loopPacketInterval_valueChanged(int value); | ||||
|     void on_packetDataWidget_currentChanged(int index); | ||||
|     void on_source_editingFinished(); | ||||
|     void on_destination_editingFinished(); | ||||
|     void on_insertPosition_toggled(bool checked); | ||||
|     void on_can_valueChanged(int value); | ||||
|     void on_smsText_editingFinished(); | ||||
| 
 | ||||
|     void onWidgetRolled(QWidget* widget, bool rollDown); | ||||
|     void onMenuDialogCalled(const QPoint& p); | ||||
| 
 | ||||
|  | ||||
| @ -7,7 +7,7 @@ | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>360</width> | ||||
|     <height>278</height> | ||||
|     <height>568</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="sizePolicy"> | ||||
| @ -40,13 +40,13 @@ | ||||
|   <property name="windowTitle"> | ||||
|    <string>M17 Modulator</string> | ||||
|   </property> | ||||
|   <widget class="QWidget" name="settingsContainer" native="true"> | ||||
|   <widget class="QWidget" name="aSettingsContainer" native="true"> | ||||
|    <property name="geometry"> | ||||
|     <rect> | ||||
|      <x>0</x> | ||||
|      <y>0</y> | ||||
|      <width>358</width> | ||||
|      <height>271</height> | ||||
|      <height>105</height> | ||||
|     </rect> | ||||
|    </property> | ||||
|    <property name="minimumSize"> | ||||
| @ -286,13 +286,6 @@ | ||||
|       </item> | ||||
|      </layout> | ||||
|     </item> | ||||
|     <item> | ||||
|      <widget class="Line" name="line_5"> | ||||
|       <property name="orientation"> | ||||
|        <enum>Qt::Horizontal</enum> | ||||
|       </property> | ||||
|      </widget> | ||||
|     </item> | ||||
|     <item> | ||||
|      <layout class="QHBoxLayout" name="volumeLayout"> | ||||
|       <item> | ||||
| @ -364,12 +357,42 @@ | ||||
|       </item> | ||||
|      </layout> | ||||
|     </item> | ||||
|    </layout> | ||||
|   </widget> | ||||
|   <widget class="QWidget" name="bAudioContainer" native="true"> | ||||
|    <property name="geometry"> | ||||
|     <rect> | ||||
|      <x>0</x> | ||||
|      <y>107</y> | ||||
|      <width>361</width> | ||||
|      <height>140</height> | ||||
|     </rect> | ||||
|    </property> | ||||
|    <property name="windowTitle"> | ||||
|     <string>Audio</string> | ||||
|    </property> | ||||
|    <layout class="QVBoxLayout" name="verticalLayout_2"> | ||||
|     <property name="spacing"> | ||||
|      <number>3</number> | ||||
|     </property> | ||||
|     <property name="leftMargin"> | ||||
|      <number>2</number> | ||||
|     </property> | ||||
|     <property name="topMargin"> | ||||
|      <number>2</number> | ||||
|     </property> | ||||
|     <property name="rightMargin"> | ||||
|      <number>2</number> | ||||
|     </property> | ||||
|     <property name="bottomMargin"> | ||||
|      <number>2</number> | ||||
|     </property> | ||||
|     <item> | ||||
|      <layout class="QHBoxLayout" name="recordFileSelectLayout"> | ||||
|       <item> | ||||
|        <widget class="ButtonSwitch" name="tone"> | ||||
|         <property name="toolTip"> | ||||
|          <string>FM tone modulation</string> | ||||
|          <string>Analog FM tone modulation</string> | ||||
|         </property> | ||||
|         <property name="text"> | ||||
|          <string>...</string> | ||||
| @ -424,6 +447,22 @@ | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|       <item> | ||||
|        <widget class="ButtonSwitch" name="fmAudio"> | ||||
|         <property name="maximumSize"> | ||||
|          <size> | ||||
|           <width>35</width> | ||||
|           <height>16777215</height> | ||||
|          </size> | ||||
|         </property> | ||||
|         <property name="toolTip"> | ||||
|          <string>Modulate audio as analog FM (for testing)</string> | ||||
|         </property> | ||||
|         <property name="text"> | ||||
|          <string>FM</string> | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|       <item> | ||||
|        <widget class="ButtonSwitch" name="mic"> | ||||
|         <property name="toolTip"> | ||||
| @ -532,13 +571,6 @@ | ||||
|       </item> | ||||
|      </layout> | ||||
|     </item> | ||||
|     <item> | ||||
|      <widget class="Line" name="line_4"> | ||||
|       <property name="orientation"> | ||||
|        <enum>Qt::Horizontal</enum> | ||||
|       </property> | ||||
|      </widget> | ||||
|     </item> | ||||
|     <item> | ||||
|      <layout class="QHBoxLayout" name="fileNameLayout"> | ||||
|       <item> | ||||
| @ -704,6 +736,606 @@ | ||||
|     </item> | ||||
|    </layout> | ||||
|   </widget> | ||||
|   <widget class="QWidget" name="cPacketContainer" native="true"> | ||||
|    <property name="geometry"> | ||||
|     <rect> | ||||
|      <x>0</x> | ||||
|      <y>247</y> | ||||
|      <width>358</width> | ||||
|      <height>193</height> | ||||
|     </rect> | ||||
|    </property> | ||||
|    <property name="windowTitle"> | ||||
|     <string>Packet</string> | ||||
|    </property> | ||||
|    <layout class="QVBoxLayout" name="verticalLayout_3"> | ||||
|     <property name="spacing"> | ||||
|      <number>3</number> | ||||
|     </property> | ||||
|     <property name="leftMargin"> | ||||
|      <number>2</number> | ||||
|     </property> | ||||
|     <property name="topMargin"> | ||||
|      <number>2</number> | ||||
|     </property> | ||||
|     <property name="rightMargin"> | ||||
|      <number>2</number> | ||||
|     </property> | ||||
|     <property name="bottomMargin"> | ||||
|      <number>2</number> | ||||
|     </property> | ||||
|     <item> | ||||
|      <layout class="QHBoxLayout" name="horizontalLayout"> | ||||
|       <item> | ||||
|        <widget class="ButtonSwitch" name="packetMode"> | ||||
|         <property name="toolTip"> | ||||
|          <string>Packet mode</string> | ||||
|         </property> | ||||
|         <property name="text"> | ||||
|          <string>PKT</string> | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|       <item> | ||||
|        <widget class="QPushButton" name="sendPacket"> | ||||
|         <property name="sizePolicy"> | ||||
|          <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||||
|           <horstretch>0</horstretch> | ||||
|           <verstretch>0</verstretch> | ||||
|          </sizepolicy> | ||||
|         </property> | ||||
|         <property name="toolTip"> | ||||
|          <string>Send packet</string> | ||||
|         </property> | ||||
|         <property name="text"> | ||||
|          <string/> | ||||
|         </property> | ||||
|         <property name="icon"> | ||||
|          <iconset resource="../../../sdrgui/resources/res.qrc"> | ||||
|           <normaloff>:/stream.png</normaloff>:/stream.png</iconset> | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|       <item> | ||||
|        <widget class="ButtonSwitch" name="loopPacket"> | ||||
|         <property name="toolTip"> | ||||
|          <string>Send packets in a loop</string> | ||||
|         </property> | ||||
|         <property name="text"> | ||||
|          <string/> | ||||
|         </property> | ||||
|         <property name="icon"> | ||||
|          <iconset resource="../../../sdrgui/resources/res.qrc"> | ||||
|           <normaloff>:/playloop.png</normaloff>:/playloop.png</iconset> | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|       <item> | ||||
|        <widget class="QDial" name="loopPacketInterval"> | ||||
|         <property name="maximumSize"> | ||||
|          <size> | ||||
|           <width>24</width> | ||||
|           <height>24</height> | ||||
|          </size> | ||||
|         </property> | ||||
|         <property name="toolTip"> | ||||
|          <string>Interval between packets (s)</string> | ||||
|         </property> | ||||
|         <property name="minimum"> | ||||
|          <number>1</number> | ||||
|         </property> | ||||
|         <property name="maximum"> | ||||
|          <number>600</number> | ||||
|         </property> | ||||
|         <property name="pageStep"> | ||||
|          <number>1</number> | ||||
|         </property> | ||||
|         <property name="value"> | ||||
|          <number>60</number> | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|       <item> | ||||
|        <widget class="QLabel" name="loopPacketIntervalText"> | ||||
|         <property name="toolTip"> | ||||
|          <string>Interval between packets (s)</string> | ||||
|         </property> | ||||
|         <property name="text"> | ||||
|          <string>600</string> | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|       <item> | ||||
|        <spacer name="horizontalSpacer_4"> | ||||
|         <property name="orientation"> | ||||
|          <enum>Qt::Horizontal</enum> | ||||
|         </property> | ||||
|         <property name="sizeHint" stdset="0"> | ||||
|          <size> | ||||
|           <width>40</width> | ||||
|           <height>20</height> | ||||
|          </size> | ||||
|         </property> | ||||
|        </spacer> | ||||
|       </item> | ||||
|      </layout> | ||||
|     </item> | ||||
|     <item> | ||||
|      <widget class="QTabWidget" name="packetDataWidget"> | ||||
|       <property name="toolTip"> | ||||
|        <string>Packet data</string> | ||||
|       </property> | ||||
|       <property name="tabPosition"> | ||||
|        <enum>QTabWidget::East</enum> | ||||
|       </property> | ||||
|       <property name="currentIndex"> | ||||
|        <number>0</number> | ||||
|       </property> | ||||
|       <widget class="QWidget" name="pktSMS"> | ||||
|        <property name="toolTip"> | ||||
|         <string>SMS data</string> | ||||
|        </property> | ||||
|        <attribute name="icon"> | ||||
|         <iconset resource="../../../sdrgui/resources/res.qrc"> | ||||
|          <normaloff>:/sms.png</normaloff>:/sms.png</iconset> | ||||
|        </attribute> | ||||
|        <attribute name="title"> | ||||
|         <string/> | ||||
|        </attribute> | ||||
|        <attribute name="toolTip"> | ||||
|         <string>SMS</string> | ||||
|        </attribute> | ||||
|        <widget class="CustomTextEdit" name="smsText"> | ||||
|         <property name="geometry"> | ||||
|          <rect> | ||||
|           <x>0</x> | ||||
|           <y>10</y> | ||||
|           <width>307</width> | ||||
|           <height>120</height> | ||||
|          </rect> | ||||
|         </property> | ||||
|         <property name="toolTip"> | ||||
|          <string>SMS text</string> | ||||
|         </property> | ||||
|        </widget> | ||||
|       </widget> | ||||
|       <widget class="QWidget" name="pktAPRS"> | ||||
|        <property name="toolTip"> | ||||
|         <string>APRS data</string> | ||||
|        </property> | ||||
|        <attribute name="icon"> | ||||
|         <iconset resource="../../../sdrgui/resources/res.qrc"> | ||||
|          <normaloff>:/world.png</normaloff>:/world.png</iconset> | ||||
|        </attribute> | ||||
|        <attribute name="title"> | ||||
|         <string/> | ||||
|        </attribute> | ||||
|        <attribute name="toolTip"> | ||||
|         <string>APRS</string> | ||||
|        </attribute> | ||||
|        <widget class="QWidget" name="horizontalLayoutWidget"> | ||||
|         <property name="geometry"> | ||||
|          <rect> | ||||
|           <x>0</x> | ||||
|           <y>40</y> | ||||
|           <width>301</width> | ||||
|           <height>34</height> | ||||
|          </rect> | ||||
|         </property> | ||||
|         <layout class="QHBoxLayout" name="toLayout"> | ||||
|          <item> | ||||
|           <widget class="QLabel" name="aprsToLabel"> | ||||
|            <property name="sizePolicy"> | ||||
|             <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> | ||||
|              <horstretch>0</horstretch> | ||||
|              <verstretch>0</verstretch> | ||||
|             </sizepolicy> | ||||
|            </property> | ||||
|            <property name="text"> | ||||
|             <string>To</string> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item> | ||||
|           <widget class="QComboBox" name="aprsTo"> | ||||
|            <property name="sizePolicy"> | ||||
|             <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||||
|              <horstretch>0</horstretch> | ||||
|              <verstretch>0</verstretch> | ||||
|             </sizepolicy> | ||||
|            </property> | ||||
|            <property name="minimumSize"> | ||||
|             <size> | ||||
|              <width>100</width> | ||||
|              <height>0</height> | ||||
|             </size> | ||||
|            </property> | ||||
|            <property name="toolTip"> | ||||
|             <string>Enter destination</string> | ||||
|            </property> | ||||
|            <property name="editable"> | ||||
|             <bool>true</bool> | ||||
|            </property> | ||||
|            <property name="currentText"> | ||||
|             <string>APRS</string> | ||||
|            </property> | ||||
|            <property name="currentIndex"> | ||||
|             <number>0</number> | ||||
|            </property> | ||||
|            <item> | ||||
|             <property name="text"> | ||||
|              <string>APRS</string> | ||||
|             </property> | ||||
|            </item> | ||||
|            <item> | ||||
|             <property name="text"> | ||||
|              <string>APZ</string> | ||||
|             </property> | ||||
|            </item> | ||||
|            <item> | ||||
|             <property name="text"> | ||||
|              <string>CQ</string> | ||||
|             </property> | ||||
|            </item> | ||||
|            <item> | ||||
|             <property name="text"> | ||||
|              <string>BEACON</string> | ||||
|             </property> | ||||
|            </item> | ||||
|            <item> | ||||
|             <property name="text"> | ||||
|              <string>CALLSIGN-SSID</string> | ||||
|             </property> | ||||
|            </item> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item> | ||||
|           <widget class="QLabel" name="aprsViaLabel"> | ||||
|            <property name="sizePolicy"> | ||||
|             <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> | ||||
|              <horstretch>0</horstretch> | ||||
|              <verstretch>0</verstretch> | ||||
|             </sizepolicy> | ||||
|            </property> | ||||
|            <property name="text"> | ||||
|             <string>Via</string> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item> | ||||
|           <widget class="QComboBox" name="aprsVia"> | ||||
|            <property name="sizePolicy"> | ||||
|             <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||||
|              <horstretch>0</horstretch> | ||||
|              <verstretch>0</verstretch> | ||||
|             </sizepolicy> | ||||
|            </property> | ||||
|            <property name="toolTip"> | ||||
|             <string>Enter routing</string> | ||||
|            </property> | ||||
|            <property name="editable"> | ||||
|             <bool>true</bool> | ||||
|            </property> | ||||
|            <item> | ||||
|             <property name="text"> | ||||
|              <string>WIDE2-2</string> | ||||
|             </property> | ||||
|            </item> | ||||
|            <item> | ||||
|             <property name="text"> | ||||
|              <string>ARISS</string> | ||||
|             </property> | ||||
|            </item> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item> | ||||
|           <spacer name="horizontalSpacer_5"> | ||||
|            <property name="orientation"> | ||||
|             <enum>Qt::Horizontal</enum> | ||||
|            </property> | ||||
|            <property name="sizeHint" stdset="0"> | ||||
|             <size> | ||||
|              <width>40</width> | ||||
|              <height>20</height> | ||||
|             </size> | ||||
|            </property> | ||||
|           </spacer> | ||||
|          </item> | ||||
|         </layout> | ||||
|        </widget> | ||||
|        <widget class="QWidget" name="horizontalLayoutWidget_2"> | ||||
|         <property name="geometry"> | ||||
|          <rect> | ||||
|           <x>0</x> | ||||
|           <y>80</y> | ||||
|           <width>301</width> | ||||
|           <height>34</height> | ||||
|          </rect> | ||||
|         </property> | ||||
|         <layout class="QHBoxLayout" name="aprsDataLayout"> | ||||
|          <item> | ||||
|           <widget class="QLabel" name="aprsDataLabel"> | ||||
|            <property name="layoutDirection"> | ||||
|             <enum>Qt::LeftToRight</enum> | ||||
|            </property> | ||||
|            <property name="text"> | ||||
|             <string>Data</string> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item> | ||||
|           <widget class="QLineEdit" name="aprsData"> | ||||
|            <property name="toolTip"> | ||||
|             <string>Enter data to transmit. | ||||
|             </string> | ||||
|            </property> | ||||
|            <property name="text"> | ||||
|             <string>>Using SDRangel</string> | ||||
|            </property> | ||||
|            <property name="maxLength"> | ||||
|             <number>256</number> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|         </layout> | ||||
|        </widget> | ||||
|        <widget class="QWidget" name="horizontalLayoutWidget_3"> | ||||
|         <property name="geometry"> | ||||
|          <rect> | ||||
|           <x>0</x> | ||||
|           <y>0</y> | ||||
|           <width>301</width> | ||||
|           <height>34</height> | ||||
|          </rect> | ||||
|         </property> | ||||
|         <layout class="QHBoxLayout" name="fromLayout"> | ||||
|          <item> | ||||
|           <widget class="QLabel" name="label_2"> | ||||
|            <property name="text"> | ||||
|             <string>From</string> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item> | ||||
|           <widget class="QLineEdit" name="aprsFromText"> | ||||
|            <property name="toolTip"> | ||||
|             <string>Enter your amateur radio callsign and optionally a SSID. E.g. M7RCE or M7RCE-1</string> | ||||
|            </property> | ||||
|            <property name="text"> | ||||
|             <string>MYCALL</string> | ||||
|            </property> | ||||
|            <property name="maxLength"> | ||||
|             <number>10</number> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item> | ||||
|           <widget class="ButtonSwitch" name="aprsInsertPosition"> | ||||
|            <property name="toolTip"> | ||||
|             <string>Insert position (latitude and longitude)</string> | ||||
|            </property> | ||||
|            <property name="text"> | ||||
|             <string>...</string> | ||||
|            </property> | ||||
|            <property name="icon"> | ||||
|             <iconset> | ||||
|              <normalon>:/gps.png</normalon> | ||||
|             </iconset> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item> | ||||
|           <spacer name="aprsFromLabel"> | ||||
|            <property name="orientation"> | ||||
|             <enum>Qt::Horizontal</enum> | ||||
|            </property> | ||||
|            <property name="sizeHint" stdset="0"> | ||||
|             <size> | ||||
|              <width>40</width> | ||||
|              <height>20</height> | ||||
|             </size> | ||||
|            </property> | ||||
|           </spacer> | ||||
|          </item> | ||||
|         </layout> | ||||
|        </widget> | ||||
|       </widget> | ||||
|      </widget> | ||||
|     </item> | ||||
|    </layout> | ||||
|   </widget> | ||||
|   <widget class="QWidget" name="dDigitalContainer" native="true"> | ||||
|    <property name="geometry"> | ||||
|     <rect> | ||||
|      <x>0</x> | ||||
|      <y>442</y> | ||||
|      <width>358</width> | ||||
|      <height>120</height> | ||||
|     </rect> | ||||
|    </property> | ||||
|    <property name="windowTitle"> | ||||
|     <string>Digital</string> | ||||
|    </property> | ||||
|    <layout class="QVBoxLayout" name="verticalLayout_4" stretch="0"> | ||||
|     <property name="spacing"> | ||||
|      <number>3</number> | ||||
|     </property> | ||||
|     <property name="leftMargin"> | ||||
|      <number>2</number> | ||||
|     </property> | ||||
|     <property name="topMargin"> | ||||
|      <number>2</number> | ||||
|     </property> | ||||
|     <property name="rightMargin"> | ||||
|      <number>2</number> | ||||
|     </property> | ||||
|     <property name="bottomMargin"> | ||||
|      <number>2</number> | ||||
|     </property> | ||||
|     <item> | ||||
|      <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||||
|       <item> | ||||
|        <widget class="TVScreen" name="screenTV" native="true"> | ||||
|         <property name="sizePolicy"> | ||||
|          <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> | ||||
|           <horstretch>0</horstretch> | ||||
|           <verstretch>0</verstretch> | ||||
|          </sizepolicy> | ||||
|         </property> | ||||
|         <property name="minimumSize"> | ||||
|          <size> | ||||
|           <width>100</width> | ||||
|           <height>100</height> | ||||
|          </size> | ||||
|         </property> | ||||
|        </widget> | ||||
|       </item> | ||||
|       <item> | ||||
|        <widget class="QFrame" name="frame"> | ||||
|         <property name="frameShape"> | ||||
|          <enum>QFrame::StyledPanel</enum> | ||||
|         </property> | ||||
|         <property name="frameShadow"> | ||||
|          <enum>QFrame::Raised</enum> | ||||
|         </property> | ||||
|         <widget class="QComboBox" name="baudRate"> | ||||
|          <property name="geometry"> | ||||
|           <rect> | ||||
|            <x>10</x> | ||||
|            <y>10</y> | ||||
|            <width>60</width> | ||||
|            <height>24</height> | ||||
|           </rect> | ||||
|          </property> | ||||
|          <property name="sizePolicy"> | ||||
|           <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||||
|            <horstretch>0</horstretch> | ||||
|            <verstretch>0</verstretch> | ||||
|           </sizepolicy> | ||||
|          </property> | ||||
|          <property name="minimumSize"> | ||||
|           <size> | ||||
|            <width>35</width> | ||||
|            <height>0</height> | ||||
|           </size> | ||||
|          </property> | ||||
|          <property name="maximumSize"> | ||||
|           <size> | ||||
|            <width>16777215</width> | ||||
|            <height>16777215</height> | ||||
|           </size> | ||||
|          </property> | ||||
|          <property name="toolTip"> | ||||
|           <string>Baud rate: 2.4k: NXDN48, dPMR 4.8k: DMR, D-Star, YSF, NXDN96</string> | ||||
|          </property> | ||||
|          <item> | ||||
|           <property name="text"> | ||||
|            <string>4.8k</string> | ||||
|           </property> | ||||
|          </item> | ||||
|         </widget> | ||||
|         <widget class="QLabel" name="sourceLabel"> | ||||
|          <property name="geometry"> | ||||
|           <rect> | ||||
|            <x>10</x> | ||||
|            <y>40</y> | ||||
|            <width>21</width> | ||||
|            <height>28</height> | ||||
|           </rect> | ||||
|          </property> | ||||
|          <property name="text"> | ||||
|           <string>Src</string> | ||||
|          </property> | ||||
|         </widget> | ||||
|         <widget class="QLineEdit" name="source"> | ||||
|          <property name="geometry"> | ||||
|           <rect> | ||||
|            <x>40</x> | ||||
|            <y>40</y> | ||||
|            <width>100</width> | ||||
|            <height>24</height> | ||||
|           </rect> | ||||
|          </property> | ||||
|         </widget> | ||||
|         <widget class="QLabel" name="destinationLabel"> | ||||
|          <property name="geometry"> | ||||
|           <rect> | ||||
|            <x>10</x> | ||||
|            <y>70</y> | ||||
|            <width>21</width> | ||||
|            <height>28</height> | ||||
|           </rect> | ||||
|          </property> | ||||
|          <property name="text"> | ||||
|           <string>Dst</string> | ||||
|          </property> | ||||
|         </widget> | ||||
|         <widget class="QLineEdit" name="destination"> | ||||
|          <property name="geometry"> | ||||
|           <rect> | ||||
|            <x>40</x> | ||||
|            <y>70</y> | ||||
|            <width>100</width> | ||||
|            <height>24</height> | ||||
|           </rect> | ||||
|          </property> | ||||
|         </widget> | ||||
|         <widget class="ButtonSwitch" name="insertPosition"> | ||||
|          <property name="geometry"> | ||||
|           <rect> | ||||
|            <x>150</x> | ||||
|            <y>40</y> | ||||
|            <width>24</width> | ||||
|            <height>24</height> | ||||
|           </rect> | ||||
|          </property> | ||||
|          <property name="toolTip"> | ||||
|           <string>Insert position (latitude and longitude)</string> | ||||
|          </property> | ||||
|          <property name="text"> | ||||
|           <string>...</string> | ||||
|          </property> | ||||
|          <property name="icon"> | ||||
|           <iconset> | ||||
|            <normalon>:/gps.png</normalon> | ||||
|           </iconset> | ||||
|          </property> | ||||
|         </widget> | ||||
|         <widget class="QLabel" name="destinationLabel_2"> | ||||
|          <property name="geometry"> | ||||
|           <rect> | ||||
|            <x>150</x> | ||||
|            <y>70</y> | ||||
|            <width>30</width> | ||||
|            <height>28</height> | ||||
|           </rect> | ||||
|          </property> | ||||
|          <property name="text"> | ||||
|           <string>CAN</string> | ||||
|          </property> | ||||
|         </widget> | ||||
|         <widget class="QSpinBox" name="can"> | ||||
|          <property name="geometry"> | ||||
|           <rect> | ||||
|            <x>180</x> | ||||
|            <y>70</y> | ||||
|            <width>56</width> | ||||
|            <height>28</height> | ||||
|           </rect> | ||||
|          </property> | ||||
|          <property name="maximum"> | ||||
|           <number>255</number> | ||||
|          </property> | ||||
|          <property name="value"> | ||||
|           <number>10</number> | ||||
|          </property> | ||||
|         </widget> | ||||
|        </widget> | ||||
|       </item> | ||||
|      </layout> | ||||
|     </item> | ||||
|    </layout> | ||||
|   </widget> | ||||
|  </widget> | ||||
|  <customwidgets> | ||||
|   <customwidget> | ||||
| @ -723,12 +1355,23 @@ | ||||
|    <extends>QToolButton</extends> | ||||
|    <header>gui/buttonswitch.h</header> | ||||
|   </customwidget> | ||||
|   <customwidget> | ||||
|    <class>TVScreen</class> | ||||
|    <extends>QWidget</extends> | ||||
|    <header>gui/tvscreen.h</header> | ||||
|    <container>1</container> | ||||
|   </customwidget> | ||||
|   <customwidget> | ||||
|    <class>LevelMeterVU</class> | ||||
|    <extends>QWidget</extends> | ||||
|    <header>gui/levelmeter.h</header> | ||||
|    <container>1</container> | ||||
|   </customwidget> | ||||
|   <customwidget> | ||||
|    <class>CustomTextEdit</class> | ||||
|    <extends>QTextEdit</extends> | ||||
|    <header>gui/customtextedit.h</header> | ||||
|   </customwidget> | ||||
|  </customwidgets> | ||||
|  <resources> | ||||
|   <include location="../../../sdrgui/resources/res.qrc"/> | ||||
|  | ||||
							
								
								
									
										99
									
								
								plugins/channeltx/modm17/m17modprocessor.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								plugins/channeltx/modm17/m17modprocessor.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2022 Edouard Griffiths, F4EXB                                   //
 | ||||
| //                                                                               //
 | ||||
| // This program is free software; you can redistribute it and/or modify          //
 | ||||
| // it under the terms of the GNU General Public License as published by          //
 | ||||
| // the Free Software Foundation as version 3 of the License, or                  //
 | ||||
| // (at your option) any later version.                                           //
 | ||||
| //                                                                               //
 | ||||
| // This program is distributed in the hope that it will be useful,               //
 | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of                //
 | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
 | ||||
| // GNU General Public License V3 for more details.                               //
 | ||||
| //                                                                               //
 | ||||
| // You should have received a copy of the GNU General Public License             //
 | ||||
| // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #include "m17/M17Modulator.h" | ||||
| 
 | ||||
| #include "m17modprocessor.h" | ||||
| 
 | ||||
| M17ModProcessor::M17ModProcessor() | ||||
| { | ||||
|     m_basebandFifo.setSampleSize(sizeof(int16_t), 48000); | ||||
|     connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); | ||||
| } | ||||
| 
 | ||||
| M17ModProcessor::~M17ModProcessor() | ||||
| {} | ||||
| 
 | ||||
| bool M17ModProcessor::handleMessage(const Message& cmd) | ||||
| { | ||||
|     if (MsgSendSMS::match(cmd)) | ||||
|     { | ||||
|         const MsgSendSMS& notif = (const MsgSendSMS&) cmd; | ||||
|         QByteArray packetBytes = notif.getSMSText().toUtf8(); | ||||
|         packetBytes.prepend(0x05); // SMS standard type
 | ||||
|         packetBytes.truncate(798); // Maximum packet size is 798 payload + 2 bytes CRC = 800 bytes (32*25)
 | ||||
|         processPacket(notif.getSourceCall(), notif.getDestCall(), packetBytes); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void M17ModProcessor::handleInputMessages() | ||||
| { | ||||
| 	Message* message; | ||||
| 
 | ||||
| 	while ((message = m_inputMessageQueue.pop()) != nullptr) | ||||
| 	{ | ||||
| 		if (handleMessage(*message)) { | ||||
| 			delete message; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void M17ModProcessor::processPacket(const QString& sourceCall, const QString& destCall, const QByteArray& packetBytes) | ||||
| { | ||||
|     mobilinkd::M17Modulator modulator(sourceCall.toStdString(), destCall.toStdString()); | ||||
|     // preamble
 | ||||
|     std::array<uint8_t, 48> preamble_bytes; | ||||
|     mobilinkd::M17Modulator::make_preamble(preamble_bytes); | ||||
|     std::array<int8_t, 48 * 4> fullframe_symbols = mobilinkd::M17Modulator::bytes_to_symbols(preamble_bytes); | ||||
|     std::array<int16_t, 1920> baseband = mobilinkd::M17Modulator::symbols_to_baseband(fullframe_symbols); | ||||
|     m_basebandFifo.write((const quint8*) baseband.data(), 1920); | ||||
|     // LSF
 | ||||
|     mobilinkd::M17Modulator::lich_t lichSegments; // Not used for packet
 | ||||
|     mobilinkd::M17Modulator::frame_t frame; | ||||
|     modulator.make_link_setup(lichSegments, frame); | ||||
|     std::array<int8_t, 46 * 4> frame_symbols = mobilinkd::M17Modulator::bytes_to_symbols(frame); | ||||
|     std::copy(mobilinkd::M17Modulator::LSF_SYNC_WORD.begin(), mobilinkd::M17Modulator::LSF_SYNC_WORD.end(), fullframe_symbols.begin()); | ||||
|     std::copy(frame_symbols.begin(), frame_symbols.end(), fullframe_symbols.begin()+2); | ||||
|     baseband = mobilinkd::M17Modulator::symbols_to_baseband(fullframe_symbols); | ||||
|     m_basebandFifo.write((const quint8*) baseband.data(), 1920); | ||||
|     // Packets
 | ||||
|     std::copy(mobilinkd::M17Modulator::DATA_SYNC_WORD.begin(), mobilinkd::M17Modulator::DATA_SYNC_WORD.end(), fullframe_symbols.begin()); | ||||
|     mobilinkd::M17Modulator::packet_t packet; | ||||
|     int remainderCount = packetBytes.size(); | ||||
|     int packetCount = 0; | ||||
| 
 | ||||
|     while (remainderCount > 25) | ||||
|     { | ||||
|         std::copy(packetBytes.begin() + (packetCount*25), packetBytes.begin() + ((packetCount+1)*25), packet.begin()); | ||||
|         frame = modulator.make_packet_frame(packetCount, false, packet, 25); | ||||
|         std::copy(frame_symbols.begin(), frame_symbols.end(), fullframe_symbols.begin()+2); | ||||
|         baseband = mobilinkd::M17Modulator::symbols_to_baseband(fullframe_symbols); | ||||
|         m_basebandFifo.write((const quint8*) baseband.data(), 1920); | ||||
|         remainderCount -= 25; | ||||
|         packetCount++; | ||||
|     } | ||||
| 
 | ||||
|     std::copy(packetBytes.begin() + (packetCount*25), packetBytes.begin() + (packetCount*25) + remainderCount, packet.begin()); | ||||
|     frame = modulator.make_packet_frame(packetCount, true, packet, remainderCount); | ||||
|     std::copy(frame_symbols.begin(), frame_symbols.end(), fullframe_symbols.begin()+2); | ||||
|     baseband = mobilinkd::M17Modulator::symbols_to_baseband(fullframe_symbols); | ||||
|     m_basebandFifo.write((const quint8*) baseband.data(), 1920); | ||||
| } | ||||
| @ -29,22 +29,28 @@ class M17ModProcessor : public QObject | ||||
| { | ||||
|     Q_OBJECT | ||||
| public: | ||||
|     class MsgSendPacket : public Message { | ||||
|     class MsgSendSMS : public Message { | ||||
|         MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
|     public: | ||||
|         const QByteArray& getPacket() const { return m_packet; } | ||||
|         const QString& getSourceCall() const { return m_sourceCall; } | ||||
|         const QString& getDestCall() const { return m_destCall; } | ||||
|         const QString& getSMSText() const { return m_smsText; } | ||||
| 
 | ||||
|         static MsgSendPacket* create(const QByteArray& packet) { | ||||
|             return new MsgSendPacket(packet); | ||||
|         static MsgSendSMS* create(const QString& sourceCall, const QString& destCall, const QString& smsText) { | ||||
|             return new MsgSendSMS(sourceCall, destCall, smsText); | ||||
|         } | ||||
| 
 | ||||
|     private: | ||||
|         QByteArray m_packet; | ||||
|         QString m_sourceCall; | ||||
|         QString m_destCall; | ||||
|         QString m_smsText; | ||||
| 
 | ||||
|         MsgSendPacket(const QByteArray& bytes) : | ||||
|         MsgSendSMS(const QString& sourceCall, const QString& destCall, const QString& smsText) : | ||||
|             Message(), | ||||
|             m_packet(bytes) | ||||
|             m_sourceCall(sourceCall), | ||||
|             m_destCall(destCall), | ||||
|             m_smsText(smsText) | ||||
|         { } | ||||
|     }; | ||||
| 
 | ||||
| @ -59,6 +65,7 @@ private: | ||||
|     AudioFifo m_basebandFifo; //!< Samples are 16 bit integer baseband 48 kS/s samples
 | ||||
| 
 | ||||
|     bool handleMessage(const Message& cmd); | ||||
|     void processPacket(const QString& sourceCall, const QString& destCall, const QByteArray& packetBytes); | ||||
| 
 | ||||
| private slots: | ||||
|     void handleInputMessages(); | ||||
|  | ||||
| @ -42,7 +42,9 @@ void M17ModSettings::resetToDefaults() | ||||
|     m_playLoop = false; | ||||
|     m_rgbColor = QColor(255, 0, 255).rgb(); | ||||
|     m_title = "M17 Modulator"; | ||||
|     m_modAFInput = M17ModInputAF::M17ModInputNone; | ||||
|     m_m17Mode = M17Mode::M17ModeNone; | ||||
|     m_audioType = AudioType::AudioNone; | ||||
|     m_packetType = PacketType::PacketNone; | ||||
|     m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName; | ||||
|     m_feedbackAudioDeviceName = AudioDeviceManager::m_defaultDeviceName; | ||||
|     m_feedbackVolumeFactor = 0.5f; | ||||
| @ -55,6 +57,16 @@ void M17ModSettings::resetToDefaults() | ||||
|     m_reverseAPIChannelIndex = 0; | ||||
|     m_workspaceIndex = 0; | ||||
|     m_hidden = false; | ||||
|     m_sourceCall = ""; | ||||
|     m_destCall = ""; | ||||
|     m_insertPosition = false; | ||||
|     m_can = 10; | ||||
|     m_smsText = ""; | ||||
|     m_aprsCallsign = "MYCALL"; | ||||
|     m_aprsTo = "APRS"; | ||||
|     m_aprsVia = "WIDE2-2"; | ||||
|     m_aprsData = ">Using SDRangel"; | ||||
|     m_aprsInsertPosition = 0; | ||||
| } | ||||
| 
 | ||||
| QByteArray M17ModSettings::serialize() const | ||||
| @ -67,13 +79,15 @@ QByteArray M17ModSettings::serialize() const | ||||
|     s.writeU32(5, m_rgbColor); | ||||
|     s.writeReal(6, m_toneFrequency); | ||||
|     s.writeReal(7, m_volumeFactor); | ||||
|     s.writeS32(8, (int) m_m17Mode); | ||||
|     s.writeS32(9, (int) m_audioType); | ||||
|     s.writeS32(10, (int) m_packetType); | ||||
| 
 | ||||
|     if (m_channelMarker) { | ||||
|         s.writeBlob(11, m_channelMarker->serialize()); | ||||
|     } | ||||
| 
 | ||||
|     s.writeString(12, m_title); | ||||
|     s.writeS32(13, (int) m_modAFInput); | ||||
|     s.writeString(14, m_audioDeviceName); | ||||
|     s.writeBool(15, m_useReverseAPI); | ||||
|     s.writeString(16, m_reverseAPIAddress); | ||||
| @ -93,6 +107,19 @@ QByteArray M17ModSettings::serialize() const | ||||
|     s.writeBlob(29, m_geometryBytes); | ||||
|     s.writeBool(30, m_hidden); | ||||
| 
 | ||||
|     s.writeString(40, m_sourceCall); | ||||
|     s.writeString(41, m_destCall); | ||||
|     s.writeBool(42, m_insertPosition); | ||||
|     s.writeU32(43, m_can); | ||||
| 
 | ||||
|     s.writeString(50, m_smsText); | ||||
| 
 | ||||
|     s.writeString(60, m_aprsCallsign); | ||||
|     s.writeString(61, m_aprsTo); | ||||
|     s.writeString(62, m_aprsVia); | ||||
|     s.writeString(63, m_aprsData); | ||||
|     s.writeBool(64, m_aprsInsertPosition); | ||||
| 
 | ||||
|     return s.final(); | ||||
| } | ||||
| 
 | ||||
| @ -119,7 +146,13 @@ bool M17ModSettings::deserialize(const QByteArray& data) | ||||
|         d.readU32(5, &m_rgbColor); | ||||
|         d.readReal(6, &m_toneFrequency, 1000.0); | ||||
|         d.readReal(7, &m_volumeFactor, 1.0); | ||||
|         d.readBlob(8, &bytetmp); | ||||
|         d.readS32(8, &tmp, 0); | ||||
|         m_m17Mode = tmp < 0 ? M17ModeNone : tmp > (int) M17ModeM17BERT ? M17ModeM17BERT : (M17Mode) tmp; | ||||
|         d.readS32(9, &tmp, 0); | ||||
|         m_audioType = tmp < 0 ? AudioNone : tmp > (int) AudioInput ? AudioInput : (AudioType) tmp; | ||||
|         m_packetType = tmp < 0 ? PacketNone : tmp > (int) PacketSMS ? PacketSMS : (PacketType) tmp; | ||||
| 
 | ||||
|         d.readBlob(11, &bytetmp); | ||||
| 
 | ||||
|         if (m_channelMarker) | ||||
|         { | ||||
| @ -129,13 +162,6 @@ bool M17ModSettings::deserialize(const QByteArray& data) | ||||
| 
 | ||||
|         d.readString(12, &m_title, "M17 Modulator"); | ||||
| 
 | ||||
|         d.readS32(13, &tmp, 0); | ||||
|         if ((tmp < 0) || (tmp > (int) M17ModInputAF::M17ModInputTone)) { | ||||
|             m_modAFInput = M17ModInputNone; | ||||
|         } else { | ||||
|             m_modAFInput = (M17ModInputAF) tmp; | ||||
|         } | ||||
| 
 | ||||
|         d.readString(14, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName); | ||||
|         d.readBool(15, &m_useReverseAPI, false); | ||||
|         d.readString(16, &m_reverseAPIAddress, "127.0.0.1"); | ||||
| @ -167,6 +193,20 @@ bool M17ModSettings::deserialize(const QByteArray& data) | ||||
|         d.readBlob(29, &m_geometryBytes); | ||||
|         d.readBool(30, &m_hidden, false); | ||||
| 
 | ||||
|         d.readString(40, &m_sourceCall, ""); | ||||
|         d.readString(41, &m_destCall, ""); | ||||
|         d.readBool(42, &m_insertPosition, false); | ||||
|         d.readU32(43, &utmp); | ||||
|         m_can = utmp < 255 ? utmp : 255; | ||||
| 
 | ||||
|         d.readString(50, &m_smsText, ""); | ||||
| 
 | ||||
|         d.readString(60, &m_aprsCallsign, "MYCALL"); | ||||
|         d.readString(61, &m_aprsTo, ""); | ||||
|         d.readString(62, &m_aprsVia, ""); | ||||
|         d.readString(63, &m_aprsData, ""); | ||||
|         d.readBool(64, &m_aprsInsertPosition, false); | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
|     else | ||||
|  | ||||
| @ -26,12 +26,28 @@ class Serializable; | ||||
| 
 | ||||
| struct M17ModSettings | ||||
| { | ||||
|     enum M17ModInputAF | ||||
|     enum M17Mode | ||||
|     { | ||||
|         M17ModInputNone, | ||||
|         M17ModInputFile, | ||||
|         M17ModInputAudio, | ||||
|         M17ModInputTone | ||||
|         M17ModeNone, | ||||
|         M17ModeFMTone, | ||||
|         M17ModeFMAudio, | ||||
|         M17ModeM17Audio, | ||||
|         M17ModeM17Packet, | ||||
|         M17ModeM17BERT | ||||
|     }; | ||||
| 
 | ||||
|     enum AudioType | ||||
|     { | ||||
|         AudioNone, | ||||
|         AudioFile, | ||||
|         AudioInput | ||||
|     }; | ||||
| 
 | ||||
|     enum PacketType | ||||
|     { | ||||
|         PacketNone, | ||||
|         PacketSMS, | ||||
|         PacketAPRS | ||||
|     }; | ||||
| 
 | ||||
|     qint64 m_inputFrequencyOffset; | ||||
| @ -43,7 +59,9 @@ struct M17ModSettings | ||||
|     bool m_playLoop; | ||||
|     quint32 m_rgbColor; | ||||
|     QString m_title; | ||||
|     M17ModInputAF m_modAFInput; | ||||
|     M17Mode m_m17Mode; | ||||
|     AudioType m_audioType; | ||||
|     PacketType m_packetType; | ||||
|     QString m_audioDeviceName;         //!< This is the audio device you get the audio samples from
 | ||||
|     QString m_feedbackAudioDeviceName; //!< This is the audio device you send the audio samples to for audio feedback
 | ||||
|     float m_feedbackVolumeFactor; | ||||
| @ -58,6 +76,19 @@ struct M17ModSettings | ||||
|     QByteArray m_geometryBytes; | ||||
|     bool m_hidden; | ||||
| 
 | ||||
|     QString m_sourceCall; | ||||
|     QString m_destCall; | ||||
|     bool m_insertPosition; | ||||
|     uint8_t m_can; | ||||
| 
 | ||||
|     QString m_smsText; | ||||
| 
 | ||||
|     QString m_aprsCallsign; | ||||
|     QString m_aprsTo; | ||||
|     QString m_aprsVia; | ||||
|     QString m_aprsData; | ||||
|     bool m_aprsInsertPosition; | ||||
| 
 | ||||
|     Serializable *m_channelMarker; | ||||
|     Serializable *m_rollupState; | ||||
| 
 | ||||
|  | ||||
| @ -21,6 +21,7 @@ | ||||
| #include "util/messagequeue.h" | ||||
| #include "maincore.h" | ||||
| 
 | ||||
| #include "m17modprocessor.h" | ||||
| #include "m17modsource.h" | ||||
| 
 | ||||
| const int M17ModSource::m_levelNbSamples = 480; // every 10ms
 | ||||
| @ -53,12 +54,15 @@ M17ModSource::M17ModSource() : | ||||
| 
 | ||||
| 	m_magsq = 0.0; | ||||
| 
 | ||||
|     m_processor = new M17ModProcessor(); | ||||
| 
 | ||||
|     applySettings(m_settings, true); | ||||
|     applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true); | ||||
| } | ||||
| 
 | ||||
| M17ModSource::~M17ModSource() | ||||
| { | ||||
|     delete m_processor; | ||||
| } | ||||
| 
 | ||||
| void M17ModSource::pull(SampleVector::iterator begin, unsigned int nbSamples) | ||||
| @ -140,25 +144,40 @@ void M17ModSource::pullAudio(unsigned int nbSamplesAudio) | ||||
| void M17ModSource::modulateSample() | ||||
| { | ||||
| 	Real t1, t; | ||||
|     bool carrier; | ||||
| 
 | ||||
|     pullAF(t); | ||||
|     if ((m_settings.m_m17Mode == M17ModSettings::M17ModeFMTone) || (m_settings.m_m17Mode == M17ModSettings::M17ModeFMAudio)) { | ||||
|         pullAF(t, carrier); | ||||
|     } else if (m_settings.m_m17Mode != M17ModSettings::M17ModeNone) { | ||||
|         pullM17(t, carrier); | ||||
|     } else { | ||||
|         t = 0; | ||||
|     } | ||||
| 
 | ||||
|     if (m_settings.m_feedbackAudioEnable) { | ||||
|         pushFeedback(t * m_settings.m_feedbackVolumeFactor * 16384.0f); | ||||
|     } | ||||
| 
 | ||||
|     calculateLevel(t); | ||||
|     t1 = m_lowpass.filter(t) * 1.2f; | ||||
|     if (carrier) | ||||
|     { | ||||
|         calculateLevel(t); | ||||
|         t1 = m_lowpass.filter(t) * 1.2f; | ||||
| 
 | ||||
|     m_modPhasor += (m_settings.m_fmDeviation / (float) m_audioSampleRate) * t1; | ||||
|         m_modPhasor += (m_settings.m_fmDeviation / (float) m_audioSampleRate) * t1; | ||||
| 
 | ||||
|     // limit phasor range to ]-pi,pi]
 | ||||
|     if (m_modPhasor > M_PI) { | ||||
|         m_modPhasor -= (2.0f * M_PI); | ||||
|         // limit phasor range to ]-pi,pi]
 | ||||
|         if (m_modPhasor > M_PI) { | ||||
|             m_modPhasor -= (2.0f * M_PI); | ||||
|         } | ||||
| 
 | ||||
|         m_modSample.real(cos(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF); // -1 dB
 | ||||
|         m_modSample.imag(sin(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         m_modSample.real(0.0f); | ||||
|         m_modSample.imag(0.0f); | ||||
|     } | ||||
| 
 | ||||
|     m_modSample.real(cos(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF); // -1 dB
 | ||||
|     m_modSample.imag(sin(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF); | ||||
| 
 | ||||
|     m_demodBuffer[m_demodBufferFill] = t1 * std::numeric_limits<int16_t>::max(); | ||||
|     ++m_demodBufferFill; | ||||
| @ -186,63 +205,74 @@ void M17ModSource::modulateSample() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void M17ModSource::pullAF(Real& sample) | ||||
| void M17ModSource::pullAF(Real& sample, bool& carrier) | ||||
| { | ||||
|     switch (m_settings.m_modAFInput) | ||||
|     { | ||||
|     case M17ModSettings::M17ModInputTone: | ||||
|         sample = m_toneNco.next(); | ||||
|         break; | ||||
|     case M17ModSettings::M17ModInputFile: | ||||
|         // sox f4exb_call.wav --encoding float --endian little f4exb_call.raw
 | ||||
|         // ffplay -f f32le -ar 48k -ac 1 f4exb_call.raw
 | ||||
|         if (m_ifstream && m_ifstream->is_open()) | ||||
|         { | ||||
|             if (m_ifstream->eof()) | ||||
|             { | ||||
|             	if (m_settings.m_playLoop) | ||||
|             	{ | ||||
|                     m_ifstream->clear(); | ||||
|                     m_ifstream->seekg(0, std::ios::beg); | ||||
|             	} | ||||
|             } | ||||
|     carrier = true; | ||||
| 
 | ||||
|             if (m_ifstream->eof()) | ||||
|     if (m_settings.m_m17Mode == M17ModSettings::M17ModeFMTone) | ||||
|     { | ||||
|         sample = m_toneNco.next(); | ||||
|     } | ||||
|     else if (m_settings.m_m17Mode == M17ModSettings::M17ModeFMAudio) | ||||
|     { | ||||
|         if (m_settings.m_audioType == M17ModSettings::AudioFile) | ||||
|         { | ||||
|             // sox f4exb_call.wav --encoding float --endian little f4exb_call.raw
 | ||||
|             // ffplay -f f32le -ar 48k -ac 1 f4exb_call.raw
 | ||||
|             if (m_ifstream && m_ifstream->is_open()) | ||||
|             { | ||||
|             	sample = 0.0f; | ||||
|                 if (m_ifstream->eof()) | ||||
|                 { | ||||
|                     if (m_settings.m_playLoop) | ||||
|                     { | ||||
|                         m_ifstream->clear(); | ||||
|                         m_ifstream->seekg(0, std::ios::beg); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 if (m_ifstream->eof()) | ||||
|                 { | ||||
|                     sample = 0.0f; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     m_ifstream->read(reinterpret_cast<char*>(&sample), sizeof(Real)); | ||||
|                     sample *= m_settings.m_volumeFactor; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|             	m_ifstream->read(reinterpret_cast<char*>(&sample), sizeof(Real)); | ||||
|             	sample *= m_settings.m_volumeFactor; | ||||
|                 sample = 0.0f; | ||||
|             } | ||||
|         } | ||||
|         else if (m_settings.m_audioType == M17ModSettings::AudioInput) | ||||
|         { | ||||
|             if (m_audioBufferFill < m_audioBuffer.size()) | ||||
|             { | ||||
|                 sample = ((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f) * m_settings.m_volumeFactor; | ||||
|                 m_audioBufferFill++; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 unsigned int size = m_audioBuffer.size(); | ||||
|                 qDebug("NFMModSource::pullAF: starve audio samples: size: %u", size); | ||||
|                 sample = ((m_audioBuffer[size-1].l + m_audioBuffer[size-1].r) / 65536.0f) * m_settings.m_volumeFactor; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             sample = 0.0f; | ||||
|         } | ||||
|         break; | ||||
|     case M17ModSettings::M17ModInputAudio: | ||||
|         if (m_audioBufferFill < m_audioBuffer.size()) | ||||
|         { | ||||
|             sample = ((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f) * m_settings.m_volumeFactor; | ||||
|             m_audioBufferFill++; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             unsigned int size = m_audioBuffer.size(); | ||||
|             qDebug("NFMModSource::pullAF: starve audio samples: size: %u", size); | ||||
|             sample = ((m_audioBuffer[size-1].l + m_audioBuffer[size-1].r) / 65536.0f) * m_settings.m_volumeFactor; | ||||
|         } | ||||
| 
 | ||||
|         break; | ||||
|     case M17ModSettings::M17ModInputNone: | ||||
|     default: | ||||
|         sample = 0.0f; | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void M17ModSource::pullM17(Real& sample, bool& carrier) | ||||
| { | ||||
|     // TODO
 | ||||
|     carrier = false; | ||||
|     sample = 0.0f; | ||||
| } | ||||
| 
 | ||||
| void M17ModSource::pushFeedback(Real sample) | ||||
| { | ||||
|     Complex c(sample, sample); | ||||
| @ -368,9 +398,9 @@ void M17ModSource::applySettings(const M17ModSettings& settings, bool force) | ||||
|         m_toneNco.setFreq(settings.m_toneFrequency, m_audioSampleRate); | ||||
|     } | ||||
| 
 | ||||
|     if ((settings.m_modAFInput != m_settings.m_modAFInput) || force) | ||||
|     if ((settings.m_audioType != m_settings.m_audioType) || force) | ||||
|     { | ||||
|         if (settings.m_modAFInput == M17ModSettings::M17ModInputAudio) { | ||||
|         if (settings.m_audioType == M17ModSettings::AudioInput) { | ||||
|             connect(&m_audioFifo, SIGNAL(dataReady()), this, SLOT(handleAudio())); | ||||
|         } else { | ||||
|             disconnect(&m_audioFifo, SIGNAL(dataReady()), this, SLOT(handleAudio())); | ||||
| @ -416,3 +446,16 @@ void M17ModSource::handleAudio() | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void M17ModSource::sendPacket() | ||||
| { | ||||
|     if (m_settings.m_packetType == M17ModSettings::PacketType::PacketSMS) | ||||
|     { | ||||
|         M17ModProcessor::MsgSendSMS *msg = M17ModProcessor::MsgSendSMS::create( | ||||
|             m_settings.m_sourceCall, | ||||
|             m_settings.m_destCall, | ||||
|             m_settings.m_smsText | ||||
|         ); | ||||
|         m_processor->getInputMessageQueue()->push(msg); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -37,6 +37,7 @@ | ||||
| #include "m17modsettings.h" | ||||
| 
 | ||||
| class ChannelAPI; | ||||
| class M17ModProcessor; | ||||
| 
 | ||||
| class M17ModSource : public QObject, public ChannelSampleSource | ||||
| { | ||||
| @ -67,6 +68,8 @@ public: | ||||
|     void applySettings(const M17ModSettings& settings, bool force = false); | ||||
|     void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false); | ||||
| 
 | ||||
|     void sendPacket(); | ||||
| 
 | ||||
| private: | ||||
|     int m_channelSampleRate; | ||||
|     int m_channelFrequencyOffset; | ||||
| @ -115,6 +118,7 @@ private: | ||||
|     Real m_levelSum; | ||||
| 
 | ||||
|     std::ifstream *m_ifstream; | ||||
|     M17ModProcessor *m_processor; | ||||
| 
 | ||||
|     QMutex m_mutex; | ||||
| 
 | ||||
| @ -122,7 +126,8 @@ private: | ||||
|     static const float m_preemphasis; | ||||
| 
 | ||||
|     void processOneSample(Complex& ci); | ||||
|     void pullAF(Real& sample); | ||||
|     void pullAF(Real& sample, bool& carrier); | ||||
|     void pullM17(Real& sample, bool& carrier); | ||||
|     void pullAudio(unsigned int nbSamples); | ||||
|     void pushFeedback(Real sample); | ||||
|     void calculateLevel(Real& sample); | ||||
|  | ||||
| @ -8390,8 +8390,17 @@ margin-bottom: 20px; | ||||
|     "audioDeviceName" : { | ||||
|       "type" : "string" | ||||
|     }, | ||||
|     "modAFInput" : { | ||||
|       "type" : "integer" | ||||
|     "m17Mode" : { | ||||
|       "type" : "integer", | ||||
|       "description" : "M17Mode" | ||||
|     }, | ||||
|     "audioType" : { | ||||
|       "type" : "integer", | ||||
|       "description" : "AudioType" | ||||
|     }, | ||||
|     "packetType" : { | ||||
|       "type" : "integer", | ||||
|       "description" : "PacketType" | ||||
|     }, | ||||
|     "streamIndex" : { | ||||
|       "type" : "integer", | ||||
| @ -56380,7 +56389,7 @@ except ApiException as e: | ||||
|           </div> | ||||
|           <div id="generator"> | ||||
|             <div class="content"> | ||||
|               Generated 2022-06-09T22:25:54.513+02:00 | ||||
|               Generated 2022-06-10T22:26:56.056+02:00 | ||||
|             </div> | ||||
|           </div> | ||||
|       </div> | ||||
|  | ||||
| @ -26,8 +26,15 @@ M17ModSettings: | ||||
|       type: string | ||||
|     audioDeviceName: | ||||
|       type: string | ||||
|     modAFInput: | ||||
|     m17Mode: | ||||
|       type: integer | ||||
|       description: M17Mode | ||||
|     audioType: | ||||
|       type: integer | ||||
|       description: AudioType | ||||
|     packetType: | ||||
|       type: integer | ||||
|       description: PacketType | ||||
|     streamIndex: | ||||
|       description: MIMO channel. Not relevant when connected to SI (single Rx). | ||||
|       type: integer | ||||
|  | ||||
| @ -8,6 +8,8 @@ | ||||
|     <file>bell_fill.png</file> | ||||
|     <file>bell_gradient.png</file> | ||||
|     <file>bell_line.png</file> | ||||
|     <file>world.png</file> | ||||
|     <file>sms.png</file> | ||||
|     <file>ruler.png</file> | ||||
|     <file>sort.png</file> | ||||
|     <file>audio_mic.png</file> | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								sdrgui/resources/sms.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sdrgui/resources/sms.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 821 B | 
							
								
								
									
										
											BIN
										
									
								
								sdrgui/resources/world.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sdrgui/resources/world.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 7.6 KiB | 
| @ -26,8 +26,15 @@ M17ModSettings: | ||||
|       type: string | ||||
|     audioDeviceName: | ||||
|       type: string | ||||
|     modAFInput: | ||||
|     m17Mode: | ||||
|       type: integer | ||||
|       description: M17Mode | ||||
|     audioType: | ||||
|       type: integer | ||||
|       description: AudioType | ||||
|     packetType: | ||||
|       type: integer | ||||
|       description: PacketType | ||||
|     streamIndex: | ||||
|       description: MIMO channel. Not relevant when connected to SI (single Rx). | ||||
|       type: integer | ||||
|  | ||||
| @ -8390,8 +8390,17 @@ margin-bottom: 20px; | ||||
|     "audioDeviceName" : { | ||||
|       "type" : "string" | ||||
|     }, | ||||
|     "modAFInput" : { | ||||
|       "type" : "integer" | ||||
|     "m17Mode" : { | ||||
|       "type" : "integer", | ||||
|       "description" : "M17Mode" | ||||
|     }, | ||||
|     "audioType" : { | ||||
|       "type" : "integer", | ||||
|       "description" : "AudioType" | ||||
|     }, | ||||
|     "packetType" : { | ||||
|       "type" : "integer", | ||||
|       "description" : "PacketType" | ||||
|     }, | ||||
|     "streamIndex" : { | ||||
|       "type" : "integer", | ||||
| @ -56380,7 +56389,7 @@ except ApiException as e: | ||||
|           </div> | ||||
|           <div id="generator"> | ||||
|             <div class="content"> | ||||
|               Generated 2022-06-09T22:25:54.513+02:00 | ||||
|               Generated 2022-06-10T22:26:56.056+02:00 | ||||
|             </div> | ||||
|           </div> | ||||
|       </div> | ||||
|  | ||||
| @ -48,8 +48,12 @@ SWGM17ModSettings::SWGM17ModSettings() { | ||||
|     m_title_isSet = false; | ||||
|     audio_device_name = nullptr; | ||||
|     m_audio_device_name_isSet = false; | ||||
|     mod_af_input = 0; | ||||
|     m_mod_af_input_isSet = false; | ||||
|     m17_mode = 0; | ||||
|     m_m17_mode_isSet = false; | ||||
|     audio_type = 0; | ||||
|     m_audio_type_isSet = false; | ||||
|     packet_type = 0; | ||||
|     m_packet_type_isSet = false; | ||||
|     stream_index = 0; | ||||
|     m_stream_index_isSet = false; | ||||
|     use_reverse_api = 0; | ||||
| @ -94,8 +98,12 @@ SWGM17ModSettings::init() { | ||||
|     m_title_isSet = false; | ||||
|     audio_device_name = new QString(""); | ||||
|     m_audio_device_name_isSet = false; | ||||
|     mod_af_input = 0; | ||||
|     m_mod_af_input_isSet = false; | ||||
|     m17_mode = 0; | ||||
|     m_m17_mode_isSet = false; | ||||
|     audio_type = 0; | ||||
|     m_audio_type_isSet = false; | ||||
|     packet_type = 0; | ||||
|     m_packet_type_isSet = false; | ||||
|     stream_index = 0; | ||||
|     m_stream_index_isSet = false; | ||||
|     use_reverse_api = 0; | ||||
| @ -133,6 +141,8 @@ SWGM17ModSettings::cleanup() { | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     if(reverse_api_address != nullptr) {  | ||||
|         delete reverse_api_address; | ||||
|     } | ||||
| @ -178,7 +188,11 @@ SWGM17ModSettings::fromJsonObject(QJsonObject &pJson) { | ||||
|      | ||||
|     ::SWGSDRangel::setValue(&audio_device_name, pJson["audioDeviceName"], "QString", "QString"); | ||||
|      | ||||
|     ::SWGSDRangel::setValue(&mod_af_input, pJson["modAFInput"], "qint32", ""); | ||||
|     ::SWGSDRangel::setValue(&m17_mode, pJson["m17Mode"], "qint32", ""); | ||||
|      | ||||
|     ::SWGSDRangel::setValue(&audio_type, pJson["audioType"], "qint32", ""); | ||||
|      | ||||
|     ::SWGSDRangel::setValue(&packet_type, pJson["packetType"], "qint32", ""); | ||||
|      | ||||
|     ::SWGSDRangel::setValue(&stream_index, pJson["streamIndex"], "qint32", ""); | ||||
|      | ||||
| @ -242,8 +256,14 @@ SWGM17ModSettings::asJsonObject() { | ||||
|     if(audio_device_name != nullptr && *audio_device_name != QString("")){ | ||||
|         toJsonValue(QString("audioDeviceName"), audio_device_name, obj, QString("QString")); | ||||
|     } | ||||
|     if(m_mod_af_input_isSet){ | ||||
|         obj->insert("modAFInput", QJsonValue(mod_af_input)); | ||||
|     if(m_m17_mode_isSet){ | ||||
|         obj->insert("m17Mode", QJsonValue(m17_mode)); | ||||
|     } | ||||
|     if(m_audio_type_isSet){ | ||||
|         obj->insert("audioType", QJsonValue(audio_type)); | ||||
|     } | ||||
|     if(m_packet_type_isSet){ | ||||
|         obj->insert("packetType", QJsonValue(packet_type)); | ||||
|     } | ||||
|     if(m_stream_index_isSet){ | ||||
|         obj->insert("streamIndex", QJsonValue(stream_index)); | ||||
| @ -374,13 +394,33 @@ SWGM17ModSettings::setAudioDeviceName(QString* audio_device_name) { | ||||
| } | ||||
| 
 | ||||
| qint32 | ||||
| SWGM17ModSettings::getModAfInput() { | ||||
|     return mod_af_input; | ||||
| SWGM17ModSettings::getM17Mode() { | ||||
|     return m17_mode; | ||||
| } | ||||
| void | ||||
| SWGM17ModSettings::setModAfInput(qint32 mod_af_input) { | ||||
|     this->mod_af_input = mod_af_input; | ||||
|     this->m_mod_af_input_isSet = true; | ||||
| SWGM17ModSettings::setM17Mode(qint32 m17_mode) { | ||||
|     this->m17_mode = m17_mode; | ||||
|     this->m_m17_mode_isSet = true; | ||||
| } | ||||
| 
 | ||||
| qint32 | ||||
| SWGM17ModSettings::getAudioType() { | ||||
|     return audio_type; | ||||
| } | ||||
| void | ||||
| SWGM17ModSettings::setAudioType(qint32 audio_type) { | ||||
|     this->audio_type = audio_type; | ||||
|     this->m_audio_type_isSet = true; | ||||
| } | ||||
| 
 | ||||
| qint32 | ||||
| SWGM17ModSettings::getPacketType() { | ||||
|     return packet_type; | ||||
| } | ||||
| void | ||||
| SWGM17ModSettings::setPacketType(qint32 packet_type) { | ||||
|     this->packet_type = packet_type; | ||||
|     this->m_packet_type_isSet = true; | ||||
| } | ||||
| 
 | ||||
| qint32 | ||||
| @ -498,7 +538,13 @@ SWGM17ModSettings::isSet(){ | ||||
|         if(audio_device_name && *audio_device_name != QString("")){ | ||||
|             isObjectUpdated = true; break; | ||||
|         } | ||||
|         if(m_mod_af_input_isSet){ | ||||
|         if(m_m17_mode_isSet){ | ||||
|             isObjectUpdated = true; break; | ||||
|         } | ||||
|         if(m_audio_type_isSet){ | ||||
|             isObjectUpdated = true; break; | ||||
|         } | ||||
|         if(m_packet_type_isSet){ | ||||
|             isObjectUpdated = true; break; | ||||
|         } | ||||
|         if(m_stream_index_isSet){ | ||||
|  | ||||
| @ -74,8 +74,14 @@ public: | ||||
|     QString* getAudioDeviceName(); | ||||
|     void setAudioDeviceName(QString* audio_device_name); | ||||
| 
 | ||||
|     qint32 getModAfInput(); | ||||
|     void setModAfInput(qint32 mod_af_input); | ||||
|     qint32 getM17Mode(); | ||||
|     void setM17Mode(qint32 m17_mode); | ||||
| 
 | ||||
|     qint32 getAudioType(); | ||||
|     void setAudioType(qint32 audio_type); | ||||
| 
 | ||||
|     qint32 getPacketType(); | ||||
|     void setPacketType(qint32 packet_type); | ||||
| 
 | ||||
|     qint32 getStreamIndex(); | ||||
|     void setStreamIndex(qint32 stream_index); | ||||
| @ -135,8 +141,14 @@ private: | ||||
|     QString* audio_device_name; | ||||
|     bool m_audio_device_name_isSet; | ||||
| 
 | ||||
|     qint32 mod_af_input; | ||||
|     bool m_mod_af_input_isSet; | ||||
|     qint32 m17_mode; | ||||
|     bool m_m17_mode_isSet; | ||||
| 
 | ||||
|     qint32 audio_type; | ||||
|     bool m_audio_type_isSet; | ||||
| 
 | ||||
|     qint32 packet_type; | ||||
|     bool m_packet_type_isSet; | ||||
| 
 | ||||
|     qint32 stream_index; | ||||
|     bool m_stream_index_isSet; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user