From f10da647178b13f8153b91cca75a98e31bdeea4f Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 12 Jun 2022 22:51:18 +0200 Subject: [PATCH] M17 modulator: SMS packet + --- modems/m17/M17Modulator.h | 100 ++- plugins/channeltx/modm17/CMakeLists.txt | 10 + plugins/channeltx/modm17/m17mod.cpp | 43 +- plugins/channeltx/modm17/m17mod.h | 1 + plugins/channeltx/modm17/m17modbaseband.cpp | 4 +- plugins/channeltx/modm17/m17modbaseband.h | 1 + plugins/channeltx/modm17/m17modgui.cpp | 228 +++++- plugins/channeltx/modm17/m17modgui.h | 17 +- plugins/channeltx/modm17/m17modgui.ui | 679 +++++++++++++++++- plugins/channeltx/modm17/m17modprocessor.cpp | 99 +++ plugins/channeltx/modm17/m17modprocessor.h | 21 +- plugins/channeltx/modm17/m17modsettings.cpp | 60 +- plugins/channeltx/modm17/m17modsettings.h | 43 +- plugins/channeltx/modm17/m17modsource.cpp | 151 ++-- plugins/channeltx/modm17/m17modsource.h | 7 +- sdrbase/resources/webapi/doc/html2/index.html | 15 +- .../webapi/doc/swagger/include/M17Mod.yaml | 9 +- sdrgui/resources/res.qrc | 2 + sdrgui/resources/sms.png | Bin 0 -> 821 bytes sdrgui/resources/world.png | Bin 0 -> 7828 bytes .../sdrangel/api/swagger/include/M17Mod.yaml | 9 +- swagger/sdrangel/code/html2/index.html | 15 +- .../code/qt5/client/SWGM17ModSettings.cpp | 72 +- .../code/qt5/client/SWGM17ModSettings.h | 20 +- 24 files changed, 1432 insertions(+), 174 deletions(-) create mode 100644 plugins/channeltx/modm17/m17modprocessor.cpp create mode 100644 sdrgui/resources/sms.png create mode 100644 sdrgui/resources/world.png diff --git a/modems/m17/M17Modulator.h b/modems/m17/M17Modulator.h index 0d4e1a5c8..12fbd16af 100644 --- a/modems/m17/M17Modulator.h +++ b/modems/m17/M17Modulator.h @@ -39,6 +39,7 @@ public: using codec_frame_t = std::array; using payload_t = std::array; // Bytes in the payload of a data frame. using frame_t = std::array; // M17 frame (without sync word). + using packet_t = std::array; // Packet payload static constexpr std::array SYNC_WORD = {0x32, 0x43}; static constexpr std::array LSF_SYNC_WORD = {0x55, 0xF7}; @@ -57,6 +58,31 @@ public: return 0; } + template + static std::array bytes_to_symbols(const std::array& bytes) + { + std::array 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& 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 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 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 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 - static std::array bytes_to_symbols(const std::array& bytes) - { - std::array 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 static std::array conv_encode(std::array data) { diff --git a/plugins/channeltx/modm17/CMakeLists.txt b/plugins/channeltx/modm17/CMakeLists.txt index bf11c0d73..82d0a789a 100644 --- a/plugins/channeltx/modm17/CMakeLists.txt +++ b/plugins/channeltx/modm17/CMakeLists.txt @@ -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}) diff --git a/plugins/channeltx/modm17/m17mod.cpp b/plugins/channeltx/modm17/m17mod.cpp index c79ddd73f..47fc16675 100644 --- a/plugins/channeltx/modm17/m17mod.cpp +++ b/plugins/channeltx/modm17/m17mod.cpp @@ -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(); +} diff --git a/plugins/channeltx/modm17/m17mod.h b/plugins/channeltx/modm17/m17mod.h index 0f68030e3..a2924332b 100644 --- a/plugins/channeltx/modm17/m17mod.h +++ b/plugins/channeltx/modm17/m17mod.h @@ -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; diff --git a/plugins/channeltx/modm17/m17modbaseband.cpp b/plugins/channeltx/modm17/m17modbaseband.cpp index 685900f17..6962fc9ea 100644 --- a/plugins/channeltx/modm17/m17modbaseband.cpp +++ b/plugins/channeltx/modm17/m17modbaseband.cpp @@ -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()); diff --git a/plugins/channeltx/modm17/m17modbaseband.h b/plugins/channeltx/modm17/m17modbaseband.h index 43724cf29..9e8f2d129 100644 --- a/plugins/channeltx/modm17/m17modbaseband.h +++ b/plugins/channeltx/modm17/m17modbaseband.h @@ -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: /** diff --git a/plugins/channeltx/modm17/m17modgui.cpp b/plugins/channeltx/modm17/m17modgui.cpp index 7c7dea247..cd0492cd1 100644 --- a/plugins/channeltx/modm17/m17modgui.cpp +++ b/plugins/channeltx/modm17/m17modgui.cpp @@ -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; + } +} diff --git a/plugins/channeltx/modm17/m17modgui.h b/plugins/channeltx/modm17/m17modgui.h index a32b8a4bf..04b0e1cff 100644 --- a/plugins/channeltx/modm17/m17modgui.h +++ b/plugins/channeltx/modm17/m17modgui.h @@ -76,6 +76,7 @@ private: qint64 m_deviceCenterFrequency; int m_basebandSampleRate; bool m_doApplySettings; + bool m_fmAudioMode; M17Mod* m_m17Mod; MovingAverageUtil 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); diff --git a/plugins/channeltx/modm17/m17modgui.ui b/plugins/channeltx/modm17/m17modgui.ui index 9d9241ebd..e7a3adeaa 100644 --- a/plugins/channeltx/modm17/m17modgui.ui +++ b/plugins/channeltx/modm17/m17modgui.ui @@ -7,7 +7,7 @@ 0 0 360 - 278 + 568 @@ -40,13 +40,13 @@ M17 Modulator - + 0 0 358 - 271 + 105 @@ -286,13 +286,6 @@ - - - - Qt::Horizontal - - - @@ -364,12 +357,42 @@ + + + + + + 0 + 107 + 361 + 140 + + + + Audio + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + - FM tone modulation + Analog FM tone modulation ... @@ -424,6 +447,22 @@ + + + + + 35 + 16777215 + + + + Modulate audio as analog FM (for testing) + + + FM + + + @@ -532,13 +571,6 @@ - - - - Qt::Horizontal - - - @@ -704,6 +736,606 @@ + + + + 0 + 247 + 358 + 193 + + + + Packet + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + + Packet mode + + + PKT + + + + + + + + 0 + 0 + + + + Send packet + + + + + + + :/stream.png:/stream.png + + + + + + + Send packets in a loop + + + + + + + :/playloop.png:/playloop.png + + + + + + + + 24 + 24 + + + + Interval between packets (s) + + + 1 + + + 600 + + + 1 + + + 60 + + + + + + + Interval between packets (s) + + + 600 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Packet data + + + QTabWidget::East + + + 0 + + + + SMS data + + + + :/sms.png:/sms.png + + + + + + SMS + + + + + 0 + 10 + 307 + 120 + + + + SMS text + + + + + + APRS data + + + + :/world.png:/world.png + + + + + + APRS + + + + + 0 + 40 + 301 + 34 + + + + + + + + 0 + 0 + + + + To + + + + + + + + 0 + 0 + + + + + 100 + 0 + + + + Enter destination + + + true + + + APRS + + + 0 + + + + APRS + + + + + APZ + + + + + CQ + + + + + BEACON + + + + + CALLSIGN-SSID + + + + + + + + + 0 + 0 + + + + Via + + + + + + + + 0 + 0 + + + + Enter routing + + + true + + + + WIDE2-2 + + + + + ARISS + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 80 + 301 + 34 + + + + + + + Qt::LeftToRight + + + Data + + + + + + + Enter data to transmit. + + + + >Using SDRangel + + + 256 + + + + + + + + + 0 + 0 + 301 + 34 + + + + + + + From + + + + + + + Enter your amateur radio callsign and optionally a SSID. E.g. M7RCE or M7RCE-1 + + + MYCALL + + + 10 + + + + + + + Insert position (latitude and longitude) + + + ... + + + + :/gps.png + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + 0 + 442 + 358 + 120 + + + + Digital + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + + + 0 + 0 + + + + + 100 + 100 + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 10 + 10 + 60 + 24 + + + + + 0 + 0 + + + + + 35 + 0 + + + + + 16777215 + 16777215 + + + + Baud rate: 2.4k: NXDN48, dPMR 4.8k: DMR, D-Star, YSF, NXDN96 + + + + 4.8k + + + + + + + 10 + 40 + 21 + 28 + + + + Src + + + + + + 40 + 40 + 100 + 24 + + + + + + + 10 + 70 + 21 + 28 + + + + Dst + + + + + + 40 + 70 + 100 + 24 + + + + + + + 150 + 40 + 24 + 24 + + + + Insert position (latitude and longitude) + + + ... + + + + :/gps.png + + + + + + + 150 + 70 + 30 + 28 + + + + CAN + + + + + + 180 + 70 + 56 + 28 + + + + 255 + + + 10 + + + + + + + + @@ -723,12 +1355,23 @@ QToolButton
gui/buttonswitch.h
+ + TVScreen + QWidget +
gui/tvscreen.h
+ 1 +
LevelMeterVU QWidget
gui/levelmeter.h
1
+ + CustomTextEdit + QTextEdit +
gui/customtextedit.h
+
diff --git a/plugins/channeltx/modm17/m17modprocessor.cpp b/plugins/channeltx/modm17/m17modprocessor.cpp new file mode 100644 index 000000000..5933106a9 --- /dev/null +++ b/plugins/channeltx/modm17/m17modprocessor.cpp @@ -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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#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 preamble_bytes; + mobilinkd::M17Modulator::make_preamble(preamble_bytes); + std::array fullframe_symbols = mobilinkd::M17Modulator::bytes_to_symbols(preamble_bytes); + std::array 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 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); +} diff --git a/plugins/channeltx/modm17/m17modprocessor.h b/plugins/channeltx/modm17/m17modprocessor.h index 891fc0390..8a2ba7f32 100644 --- a/plugins/channeltx/modm17/m17modprocessor.h +++ b/plugins/channeltx/modm17/m17modprocessor.h @@ -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(); diff --git a/plugins/channeltx/modm17/m17modsettings.cpp b/plugins/channeltx/modm17/m17modsettings.cpp index 2eea4748d..b5062e2e2 100644 --- a/plugins/channeltx/modm17/m17modsettings.cpp +++ b/plugins/channeltx/modm17/m17modsettings.cpp @@ -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 diff --git a/plugins/channeltx/modm17/m17modsettings.h b/plugins/channeltx/modm17/m17modsettings.h index d0509620e..bb0ede7d2 100644 --- a/plugins/channeltx/modm17/m17modsettings.h +++ b/plugins/channeltx/modm17/m17modsettings.h @@ -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; diff --git a/plugins/channeltx/modm17/m17modsource.cpp b/plugins/channeltx/modm17/m17modsource.cpp index b124fe143..a52ad489c 100644 --- a/plugins/channeltx/modm17/m17modsource.cpp +++ b/plugins/channeltx/modm17/m17modsource.cpp @@ -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::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(&sample), sizeof(Real)); + sample *= m_settings.m_volumeFactor; + } } else { - m_ifstream->read(reinterpret_cast(&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); + } +} diff --git a/plugins/channeltx/modm17/m17modsource.h b/plugins/channeltx/modm17/m17modsource.h index 6b852b4b1..6890edc5b 100644 --- a/plugins/channeltx/modm17/m17modsource.h +++ b/plugins/channeltx/modm17/m17modsource.h @@ -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); diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index c77a093ed..0099b9d15 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -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:
- Generated 2022-06-09T22:25:54.513+02:00 + Generated 2022-06-10T22:26:56.056+02:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/M17Mod.yaml b/sdrbase/resources/webapi/doc/swagger/include/M17Mod.yaml index 5cb05b2ce..8a87ee14a 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/M17Mod.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/M17Mod.yaml @@ -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 diff --git a/sdrgui/resources/res.qrc b/sdrgui/resources/res.qrc index c62dcd600..90fe1ae90 100644 --- a/sdrgui/resources/res.qrc +++ b/sdrgui/resources/res.qrc @@ -8,6 +8,8 @@ bell_fill.png bell_gradient.png bell_line.png + world.png + sms.png ruler.png sort.png audio_mic.png diff --git a/sdrgui/resources/sms.png b/sdrgui/resources/sms.png new file mode 100644 index 0000000000000000000000000000000000000000..0f9312a9a501d84171fb0c65d0a7d3a86839bae4 GIT binary patch literal 821 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
- Generated 2022-06-09T22:25:54.513+02:00 + Generated 2022-06-10T22:26:56.056+02:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGM17ModSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGM17ModSettings.cpp index 1ff287761..db04df885 100644 --- a/swagger/sdrangel/code/qt5/client/SWGM17ModSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGM17ModSettings.cpp @@ -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){ diff --git a/swagger/sdrangel/code/qt5/client/SWGM17ModSettings.h b/swagger/sdrangel/code/qt5/client/SWGM17ModSettings.h index 2226d218b..794e6b639 100644 --- a/swagger/sdrangel/code/qt5/client/SWGM17ModSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGM17ModSettings.h @@ -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;