From 7b0e116d4ba016928766c159c21f7d50ee9c6693 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 3 Mar 2020 21:52:46 +0100 Subject: [PATCH] LoRaDemod refoctoring to ChirpChat --- ....png => ChirpChatDemod_message_binary.png} | Bin ....xcf => ChirpChatDemod_message_binary.xcf} | Bin ....png => ChirpChatDemod_message_string.png} | Bin ....xcf => ChirpChatDemod_message_string.xcf} | Bin ...payload.png => ChirpChatDemod_payload.png} | Bin ...payload.xcf => ChirpChatDemod_payload.xcf} | Bin doc/img/ChirpChatDemod_plugin.png | Bin 0 -> 102770 bytes ...d_plugin.xcf => ChirpChatDemod_plugin.xcf} | Bin 366185 -> 367596 bytes doc/img/LoRaDemod_plugin.png | Bin 102494 -> 0 bytes plugins/channelrx/CMakeLists.txt | 2 +- .../channelrx/demodchirpchat/CMakeLists.txt | 66 +++ .../chirpchatdemod.cpp} | 301 +++++++------- .../chirpchatdemod.h} | 42 +- .../chirpchatdemodbaseband.cpp} | 44 +- .../chirpchatdemodbaseband.h} | 32 +- .../chirpchatdemoddecoder.cpp} | 34 +- .../chirpchatdemoddecoder.h} | 18 +- .../chirpchatdemoddecoderascii.cpp} | 4 +- .../chirpchatdemoddecoderascii.h} | 8 +- .../chirpchatdemoddecoderlora.cpp} | 16 +- .../chirpchatdemoddecoderlora.h} | 8 +- .../chirpchatdemoddecodertty.cpp} | 8 +- .../chirpchatdemoddecodertty.h} | 8 +- .../chirpchatdemodgui.cpp} | 174 ++++---- .../chirpchatdemodgui.h} | 28 +- .../chirpchatdemodgui.ui} | 6 +- .../chirpchatdemodmsg.cpp} | 4 +- .../chirpchatdemodmsg.h} | 8 +- .../chirpchatdemodsettings.cpp} | 23 +- .../chirpchatdemodsettings.h} | 10 +- .../chirpchatdemodsink.cpp} | 96 ++--- .../chirpchatdemodsink.h} | 40 +- .../chirpchatdemodwebapiadapter.cpp} | 22 +- .../chirpchatdemodwebapiadapter.h} | 16 +- .../chirpchatplugin.cpp} | 36 +- .../chirpchatplugin.h} | 10 +- .../{demodlora => demodchirpchat}/readme.md | 40 +- plugins/channelrx/demodlora/CMakeLists.txt | 66 --- sdrbase/resources/webapi.qrc | 2 +- sdrbase/resources/webapi/doc/html2/index.html | 376 +++++++++--------- .../doc/swagger/include/ChannelSettings.yaml | 4 +- .../doc/swagger/include/ChirpChatDemod.yaml | 8 +- .../resources/webapi/doc/swagger/swagger.yaml | 4 +- sdrbase/webapi/webapirequestmapper.cpp | 10 +- .../api/swagger/include/ChannelSettings.yaml | 4 +- .../api/swagger/include/ChirpChatDemod.yaml | 173 ++++++++ swagger/sdrangel/api/swagger/swagger.yaml | 4 +- swagger/sdrangel/code/html2/index.html | 376 +++++++++--------- .../code/qt5/client/SWGChannelReport.cpp | 50 +-- .../code/qt5/client/SWGChannelReport.h | 14 +- .../code/qt5/client/SWGChannelSettings.cpp | 50 +-- .../code/qt5/client/SWGChannelSettings.h | 14 +- ...Report.cpp => SWGChirpChatDemodReport.cpp} | 96 ++--- ...emodReport.h => SWGChirpChatDemodReport.h} | 20 +- ...ings.cpp => SWGChirpChatDemodSettings.cpp} | 124 +++--- ...Settings.h => SWGChirpChatDemodSettings.h} | 20 +- .../code/qt5/client/SWGModelFactory.h | 16 +- 57 files changed, 1356 insertions(+), 1179 deletions(-) rename doc/img/{LoRaDemod_message_binary.png => ChirpChatDemod_message_binary.png} (100%) rename doc/img/{LoRaDemod_message_binary.xcf => ChirpChatDemod_message_binary.xcf} (100%) rename doc/img/{LoRaDemod_message_string.png => ChirpChatDemod_message_string.png} (100%) rename doc/img/{LoRaDemod_message_string.xcf => ChirpChatDemod_message_string.xcf} (100%) rename doc/img/{LoRaDemod_payload.png => ChirpChatDemod_payload.png} (100%) rename doc/img/{LoRaDemod_payload.xcf => ChirpChatDemod_payload.xcf} (100%) create mode 100644 doc/img/ChirpChatDemod_plugin.png rename doc/img/{LoRaDemod_plugin.xcf => ChirpChatDemod_plugin.xcf} (90%) delete mode 100644 doc/img/LoRaDemod_plugin.png create mode 100644 plugins/channelrx/demodchirpchat/CMakeLists.txt rename plugins/channelrx/{demodlora/lorademod.cpp => demodchirpchat/chirpchatdemod.cpp} (61%) rename plugins/channelrx/{demodlora/lorademod.h => demodchirpchat/chirpchatdemod.h} (89%) rename plugins/channelrx/{demodlora/lorademodbaseband.cpp => demodchirpchat/chirpchatdemodbaseband.cpp} (73%) rename plugins/channelrx/{demodlora/lorademodbaseband.h => demodchirpchat/chirpchatdemodbaseband.h} (76%) rename plugins/channelrx/{demodlora/lorademoddecoder.cpp => demodchirpchat/chirpchatdemoddecoder.cpp} (72%) rename plugins/channelrx/{demodlora/lorademoddecoder.h => demodchirpchat/chirpchatdemoddecoder.h} (89%) rename plugins/channelrx/{demodlora/lorademoddecoderascii.cpp => demodchirpchat/chirpchatdemoddecoderascii.cpp} (91%) rename plugins/channelrx/{demodlora/lorademoddecoderascii.h => demodchirpchat/chirpchatdemoddecoderascii.h} (89%) rename plugins/channelrx/{demodlora/lorademoddecoderlora.cpp => demodchirpchat/chirpchatdemoddecoderlora.cpp} (95%) rename plugins/channelrx/{demodlora/lorademoddecoderlora.h => demodchirpchat/chirpchatdemoddecoderlora.h} (98%) rename plugins/channelrx/{demodlora/lorademoddecodertty.cpp => demodchirpchat/chirpchatdemoddecodertty.cpp} (90%) rename plugins/channelrx/{demodlora/lorademoddecodertty.h => demodchirpchat/chirpchatdemoddecodertty.h} (91%) rename plugins/channelrx/{demodlora/lorademodgui.cpp => demodchirpchat/chirpchatdemodgui.cpp} (77%) rename plugins/channelrx/{demodlora/lorademodgui.h => demodchirpchat/chirpchatdemodgui.h} (85%) rename plugins/channelrx/{demodlora/lorademodgui.ui => demodchirpchat/chirpchatdemodgui.ui} (99%) rename plugins/channelrx/{demodlora/lorademodmsg.cpp => demodchirpchat/chirpchatdemodmsg.cpp} (92%) rename plugins/channelrx/{demodlora/lorademodmsg.h => demodchirpchat/chirpchatdemodmsg.h} (95%) rename plugins/channelrx/{demodlora/lorademodsettings.cpp => demodchirpchat/chirpchatdemodsettings.cpp} (91%) rename plugins/channelrx/{demodlora/lorademodsettings.h => demodchirpchat/chirpchatdemodsettings.h} (92%) rename plugins/channelrx/{demodlora/lorademodsink.cpp => demodchirpchat/chirpchatdemodsink.cpp} (83%) rename plugins/channelrx/{demodlora/lorademodsink.h => demodchirpchat/chirpchatdemodsink.h} (84%) rename plugins/channelrx/{demodlora/lorademodwebapiadapter.cpp => demodchirpchat/chirpchatdemodwebapiadapter.cpp} (71%) rename plugins/channelrx/{demodlora/lorademodwebapiadapter.h => demodchirpchat/chirpchatdemodwebapiadapter.h} (84%) rename plugins/channelrx/{demodlora/loraplugin.cpp => demodchirpchat/chirpchatplugin.cpp} (64%) rename plugins/channelrx/{demodlora/loraplugin.h => demodchirpchat/chirpchatplugin.h} (89%) rename plugins/channelrx/{demodlora => demodchirpchat}/readme.md (73%) delete mode 100644 plugins/channelrx/demodlora/CMakeLists.txt rename swagger/sdrangel/api/swagger/include/LoRaDemod.yaml => sdrbase/resources/webapi/doc/swagger/include/ChirpChatDemod.yaml (98%) create mode 100644 swagger/sdrangel/api/swagger/include/ChirpChatDemod.yaml rename swagger/sdrangel/code/qt5/client/{SWGLoRaDemodReport.cpp => SWGChirpChatDemodReport.cpp} (83%) rename swagger/sdrangel/code/qt5/client/{SWGLoRaDemodReport.h => SWGChirpChatDemodReport.h} (91%) rename swagger/sdrangel/code/qt5/client/{SWGLoRaDemodSettings.cpp => SWGChirpChatDemodSettings.cpp} (82%) rename swagger/sdrangel/code/qt5/client/{SWGLoRaDemodSettings.h => SWGChirpChatDemodSettings.h} (92%) diff --git a/doc/img/LoRaDemod_message_binary.png b/doc/img/ChirpChatDemod_message_binary.png similarity index 100% rename from doc/img/LoRaDemod_message_binary.png rename to doc/img/ChirpChatDemod_message_binary.png diff --git a/doc/img/LoRaDemod_message_binary.xcf b/doc/img/ChirpChatDemod_message_binary.xcf similarity index 100% rename from doc/img/LoRaDemod_message_binary.xcf rename to doc/img/ChirpChatDemod_message_binary.xcf diff --git a/doc/img/LoRaDemod_message_string.png b/doc/img/ChirpChatDemod_message_string.png similarity index 100% rename from doc/img/LoRaDemod_message_string.png rename to doc/img/ChirpChatDemod_message_string.png diff --git a/doc/img/LoRaDemod_message_string.xcf b/doc/img/ChirpChatDemod_message_string.xcf similarity index 100% rename from doc/img/LoRaDemod_message_string.xcf rename to doc/img/ChirpChatDemod_message_string.xcf diff --git a/doc/img/LoRaDemod_payload.png b/doc/img/ChirpChatDemod_payload.png similarity index 100% rename from doc/img/LoRaDemod_payload.png rename to doc/img/ChirpChatDemod_payload.png diff --git a/doc/img/LoRaDemod_payload.xcf b/doc/img/ChirpChatDemod_payload.xcf similarity index 100% rename from doc/img/LoRaDemod_payload.xcf rename to doc/img/ChirpChatDemod_payload.xcf diff --git a/doc/img/ChirpChatDemod_plugin.png b/doc/img/ChirpChatDemod_plugin.png new file mode 100644 index 0000000000000000000000000000000000000000..8979738bc0eb11b0235c9b7ba6f3559701ec8eb7 GIT binary patch literal 102770 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μ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 JRHD`2^nd0%AF==d delta 12147 zcmZwN4_wXX-^cOKb^a)4+43h@vn@@^nOU|dXKZE2&dfqq!WKg`?!^xg?h`{fm?EOt zZ)u2TMC_z7@r#I!EaKR1u`CX|7h`c|bH9%CnC{1}$K!dOtLt2SJLh}e-|PB*&$sKg zwpX{dO@CDd?s)ALWpNW}W)kTdBobUL(s#Lt`3aGj@gk!>5t%ViWX}5{nbSnp#)@n+ ziWEL4axhusNP@`OaUwtDi(I=XQg>98c#6`0C~A>a)RN~!WhaRGtb?fSaiR);5mlNd z>c}op=ePa#+!8V9&;}h5jJ_fk zLllj%n1%(�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 KJj)f)@%#^9bk!RG diff --git a/plugins/channelrx/CMakeLists.txt b/plugins/channelrx/CMakeLists.txt index 040371539..3b65fc952 100644 --- a/plugins/channelrx/CMakeLists.txt +++ b/plugins/channelrx/CMakeLists.txt @@ -8,7 +8,7 @@ add_subdirectory(udpsink) add_subdirectory(demodwfm) add_subdirectory(localsink) add_subdirectory(freqtracker) -add_subdirectory(demodlora) +add_subdirectory(demodchirpchat) if(LIBDSDCC_FOUND AND LIBMBE_FOUND) add_subdirectory(demoddsd) diff --git a/plugins/channelrx/demodchirpchat/CMakeLists.txt b/plugins/channelrx/demodchirpchat/CMakeLists.txt new file mode 100644 index 000000000..6f81da7a5 --- /dev/null +++ b/plugins/channelrx/demodchirpchat/CMakeLists.txt @@ -0,0 +1,66 @@ +project(chirpchat) + +set(chirpchat_SOURCES + chirpchatdemod.cpp + chirpchatdemodsettings.cpp + chirpchatdemodsink.cpp + chirpchatdemodbaseband.cpp + chirpchatplugin.cpp + chirpchatdemoddecoder.cpp + chirpchatdemoddecodertty.cpp + chirpchatdemoddecoderascii.cpp + chirpchatdemoddecoderlora.cpp + chirpchatdemodmsg.cpp +) + +set(chirpchat_HEADERS + chirpchatdemod.h + chirpchatdemodsettings.h + chirpchatdemodsink.h + chirpchatdemodbaseband.h + chirpchatdemoddecoder.h + chirpchatdemoddecodertty.h + chirpchatdemoddecoderascii.h + chirpchatdemoddecoderlora.h + chirpchatdemodmsg.h + chirpchatplugin.h +) + +include_directories( + ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client +) + +if(NOT SERVER_MODE) + set(chirpchat_SOURCES + ${chirpchat_SOURCES} + chirpchatdemodgui.cpp + chirpchatdemodgui.ui + ) + set(chirpchat_HEADERS + ${chirpchat_HEADERS} + chirpchatdemodgui.h + ) + set(TARGET_NAME demodchirpchat) + set(TARGET_LIB "Qt5::Widgets") + set(TARGET_LIB_GUI "sdrgui") + set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) +else() + set(TARGET_NAME demodchirpchatsrv) + set(TARGET_LIB "") + set(TARGET_LIB_GUI "") + set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR}) +endif() + +add_library(${TARGET_NAME} SHARED + ${chirpchat_SOURCES} +) + +target_link_libraries(${TARGET_NAME} + Qt5::Core + ${TARGET_LIB} + sdrbase + ${TARGET_LIB_GUI} + swagger +) + +install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER}) diff --git a/plugins/channelrx/demodlora/lorademod.cpp b/plugins/channelrx/demodchirpchat/chirpchatdemod.cpp similarity index 61% rename from plugins/channelrx/demodlora/lorademod.cpp rename to plugins/channelrx/demodchirpchat/chirpchatdemod.cpp index 9a27846b4..3ae35cd97 100644 --- a/plugins/channelrx/demodlora/lorademod.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatdemod.cpp @@ -33,19 +33,19 @@ #include "SWGChannelSettings.h" #include "SWGChannelReport.h" -#include "SWGLoRaDemodReport.h" +#include "SWGChirpChatDemodReport.h" -#include "lorademodmsg.h" -#include "lorademod.h" +#include "chirpchatdemodmsg.h" +#include "chirpchatdemod.h" -MESSAGE_CLASS_DEFINITION(LoRaDemod::MsgConfigureLoRaDemod, Message) -MESSAGE_CLASS_DEFINITION(LoRaDemod::MsgReportDecodeBytes, Message) -MESSAGE_CLASS_DEFINITION(LoRaDemod::MsgReportDecodeString, Message) +MESSAGE_CLASS_DEFINITION(ChirpChatDemod::MsgConfigureChirpChatDemod, Message) +MESSAGE_CLASS_DEFINITION(ChirpChatDemod::MsgReportDecodeBytes, Message) +MESSAGE_CLASS_DEFINITION(ChirpChatDemod::MsgReportDecodeString, Message) -const QString LoRaDemod::m_channelIdURI = "sdrangel.channel.lorademod"; -const QString LoRaDemod::m_channelId = "LoRaDemod"; +const QString ChirpChatDemod::m_channelIdURI = "sdrangel.channel.chirpchatdemod"; +const QString ChirpChatDemod::m_channelId = "ChirpChatDemod"; -LoRaDemod::LoRaDemod(DeviceAPI* deviceAPI) : +ChirpChatDemod::ChirpChatDemod(DeviceAPI* deviceAPI) : ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSink), m_deviceAPI(deviceAPI), m_basebandSampleRate(0), @@ -67,7 +67,7 @@ LoRaDemod::LoRaDemod(DeviceAPI* deviceAPI) : setObjectName(m_channelId); m_thread = new QThread(this); - m_basebandSink = new LoRaDemodBaseband(); + m_basebandSink = new ChirpChatDemodBaseband(); m_basebandSink->setDecoderMessageQueue(getInputMessageQueue()); // Decoder held on the main thread m_basebandSink->moveToThread(m_thread); @@ -77,7 +77,7 @@ LoRaDemod::LoRaDemod(DeviceAPI* deviceAPI) : m_deviceAPI->addChannelSinkAPI(this); } -LoRaDemod::~LoRaDemod() +ChirpChatDemod::~ChirpChatDemod() { m_deviceAPI->removeChannelSinkAPI(this); m_deviceAPI->removeChannelSink(this); @@ -85,20 +85,20 @@ LoRaDemod::~LoRaDemod() delete m_thread; } -uint32_t LoRaDemod::getNumberOfDeviceStreams() const +uint32_t ChirpChatDemod::getNumberOfDeviceStreams() const { return m_deviceAPI->getNbSourceStreams(); } -void LoRaDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool pO) +void ChirpChatDemod::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool pO) { (void) pO; m_basebandSink->feed(begin, end); } -void LoRaDemod::start() +void ChirpChatDemod::start() { - qDebug() << "LoRaDemod::start"; + qDebug() << "ChirpChatDemod::start"; if (m_basebandSampleRate != 0) { m_basebandSink->setBasebandSampleRate(m_basebandSampleRate); @@ -108,33 +108,33 @@ void LoRaDemod::start() m_thread->start(); } -void LoRaDemod::stop() +void ChirpChatDemod::stop() { - qDebug() << "LoRaDemod::stop"; + qDebug() << "ChirpChatDemod::stop"; m_thread->exit(); m_thread->wait(); } -bool LoRaDemod::handleMessage(const Message& cmd) +bool ChirpChatDemod::handleMessage(const Message& cmd) { - if (MsgConfigureLoRaDemod::match(cmd)) + if (MsgConfigureChirpChatDemod::match(cmd)) { - qDebug() << "LoRaDemod::handleMessage: MsgConfigureLoRaDemod"; - MsgConfigureLoRaDemod& cfg = (MsgConfigureLoRaDemod&) cmd; - LoRaDemodSettings settings = cfg.getSettings(); + qDebug() << "ChirpChatDemod::handleMessage: MsgConfigureChirpChatDemod"; + MsgConfigureChirpChatDemod& cfg = (MsgConfigureChirpChatDemod&) cmd; + ChirpChatDemodSettings settings = cfg.getSettings(); applySettings(settings, cfg.getForce()); return true; } - else if (LoRaDemodMsg::MsgDecodeSymbols::match(cmd)) + else if (ChirpChatDemodMsg::MsgDecodeSymbols::match(cmd)) { - qDebug() << "LoRaDemod::handleMessage: MsgDecodeSymbols"; - LoRaDemodMsg::MsgDecodeSymbols& msg = (LoRaDemodMsg::MsgDecodeSymbols&) cmd; + qDebug() << "ChirpChatDemod::handleMessage: MsgDecodeSymbols"; + ChirpChatDemodMsg::MsgDecodeSymbols& msg = (ChirpChatDemodMsg::MsgDecodeSymbols&) cmd; m_lastMsgSignalDb = msg.getSingalDb(); m_lastMsgNoiseDb = msg.getNoiseDb(); m_lastMsgSyncWord = msg.getSyncWord(); - if (m_settings.m_codingScheme == LoRaDemodSettings::CodingLoRa) + if (m_settings.m_codingScheme == ChirpChatDemodSettings::CodingLoRa) { m_decoder.decodeSymbols(msg.getSymbols(), m_lastMsgBytes); QDateTime dt = QDateTime::currentDateTime(); @@ -182,13 +182,13 @@ bool LoRaDemod::handleMessage(const Message& cmd) if (m_settings.m_autoNbSymbolsMax) { - LoRaDemodSettings settings = m_settings; + ChirpChatDemodSettings settings = m_settings; settings.m_nbSymbolsMax = m_lastMsgNbSymbols; applySettings(settings); if (getMessageQueueToGUI()) // forward to GUI if any { - MsgConfigureLoRaDemod *msgToGUI = MsgConfigureLoRaDemod::create(settings, false); + MsgConfigureChirpChatDemod *msgToGUI = MsgConfigureChirpChatDemod::create(settings, false); getMessageQueueToGUI()->push(msgToGUI); } } @@ -224,7 +224,7 @@ bool LoRaDemod::handleMessage(const Message& cmd) m_basebandSampleRate = notif.getSampleRate(); // Forward to the sink DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy - qDebug() << "LoRaDemod::handleMessage: DSPSignalNotification: m_basebandSampleRate: " << m_basebandSampleRate; + qDebug() << "ChirpChatDemod::handleMessage: DSPSignalNotification: m_basebandSampleRate: " << m_basebandSampleRate; m_basebandSink->getInputMessageQueue()->push(rep); if (getMessageQueueToGUI()) @@ -241,31 +241,31 @@ bool LoRaDemod::handleMessage(const Message& cmd) } } -QByteArray LoRaDemod::serialize() const +QByteArray ChirpChatDemod::serialize() const { return m_settings.serialize(); } -bool LoRaDemod::deserialize(const QByteArray& data) +bool ChirpChatDemod::deserialize(const QByteArray& data) { if (m_settings.deserialize(data)) { - MsgConfigureLoRaDemod *msg = MsgConfigureLoRaDemod::create(m_settings, true); + MsgConfigureChirpChatDemod *msg = MsgConfigureChirpChatDemod::create(m_settings, true); m_inputMessageQueue.push(msg); return true; } else { m_settings.resetToDefaults(); - MsgConfigureLoRaDemod *msg = MsgConfigureLoRaDemod::create(m_settings, true); + MsgConfigureChirpChatDemod *msg = MsgConfigureChirpChatDemod::create(m_settings, true); m_inputMessageQueue.push(msg); return false; } } -void LoRaDemod::applySettings(const LoRaDemodSettings& settings, bool force) +void ChirpChatDemod::applySettings(const ChirpChatDemodSettings& settings, bool force) { - qDebug() << "LoRaDemod::applySettings:" + qDebug() << "ChirpChatDemod::applySettings:" << " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset << " m_bandwidthIndex: " << settings.m_bandwidthIndex << " m_spreadFactor: " << settings.m_spreadFactor @@ -383,7 +383,8 @@ void LoRaDemod::applySettings(const LoRaDemodSettings& settings, bool force) reverseAPIKeys.append("streamIndex"); } - LoRaDemodBaseband::MsgConfigureLoRaDemodBaseband *msg = LoRaDemodBaseband::MsgConfigureLoRaDemodBaseband::create(settings, force); + ChirpChatDemodBaseband::MsgConfigureChirpChatDemodBaseband *msg = + ChirpChatDemodBaseband::MsgConfigureChirpChatDemodBaseband::create(settings, force); m_basebandSink->getInputMessageQueue()->push(msg); if (settings.m_useReverseAPI) @@ -399,34 +400,34 @@ void LoRaDemod::applySettings(const LoRaDemodSettings& settings, bool force) m_settings = settings; } -int LoRaDemod::webapiSettingsGet( +int ChirpChatDemod::webapiSettingsGet( SWGSDRangel::SWGChannelSettings& response, QString& errorMessage) { (void) errorMessage; - response.setLoRaDemodSettings(new SWGSDRangel::SWGLoRaDemodSettings()); - response.getLoRaDemodSettings()->init(); + response.setChirpChatDemodSettings(new SWGSDRangel::SWGChirpChatDemodSettings()); + response.getChirpChatDemodSettings()->init(); webapiFormatChannelSettings(response, m_settings); return 200; } -int LoRaDemod::webapiSettingsPutPatch( +int ChirpChatDemod::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, QString& errorMessage) { (void) errorMessage; - LoRaDemodSettings settings = m_settings; + ChirpChatDemodSettings settings = m_settings; webapiUpdateChannelSettings(settings, channelSettingsKeys, response); - MsgConfigureLoRaDemod *msg = MsgConfigureLoRaDemod::create(settings, force); + MsgConfigureChirpChatDemod *msg = MsgConfigureChirpChatDemod::create(settings, force); m_inputMessageQueue.push(msg); if (m_guiMessageQueue) // forward to GUI if any { - MsgConfigureLoRaDemod *msgToGUI = MsgConfigureLoRaDemod::create(settings, force); + MsgConfigureChirpChatDemod *msgToGUI = MsgConfigureChirpChatDemod::create(settings, force); m_guiMessageQueue->push(msgToGUI); } @@ -435,167 +436,167 @@ int LoRaDemod::webapiSettingsPutPatch( return 200; } -void LoRaDemod::webapiUpdateChannelSettings( - LoRaDemodSettings& settings, +void ChirpChatDemod::webapiUpdateChannelSettings( + ChirpChatDemodSettings& settings, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response) { if (channelSettingsKeys.contains("inputFrequencyOffset")) { - settings.m_inputFrequencyOffset = response.getLoRaDemodSettings()->getInputFrequencyOffset(); + settings.m_inputFrequencyOffset = response.getChirpChatDemodSettings()->getInputFrequencyOffset(); } if (channelSettingsKeys.contains("bandwidthIndex")) { - settings.m_bandwidthIndex = response.getLoRaDemodSettings()->getBandwidthIndex(); + settings.m_bandwidthIndex = response.getChirpChatDemodSettings()->getBandwidthIndex(); } if (channelSettingsKeys.contains("spreadFactor")) { - settings.m_spreadFactor = response.getLoRaDemodSettings()->getSpreadFactor(); + settings.m_spreadFactor = response.getChirpChatDemodSettings()->getSpreadFactor(); } if (channelSettingsKeys.contains("deBits")) { - settings.m_deBits = response.getLoRaDemodSettings()->getDeBits(); + settings.m_deBits = response.getChirpChatDemodSettings()->getDeBits(); } if (channelSettingsKeys.contains("codingScheme")) { - settings.m_codingScheme = (LoRaDemodSettings::CodingScheme) response.getLoRaDemodSettings()->getCodingScheme(); + settings.m_codingScheme = (ChirpChatDemodSettings::CodingScheme) response.getChirpChatDemodSettings()->getCodingScheme(); } if (channelSettingsKeys.contains("decodeActive")) { - settings.m_decodeActive = response.getLoRaDemodSettings()->getDecodeActive() != 0; + settings.m_decodeActive = response.getChirpChatDemodSettings()->getDecodeActive() != 0; } if (channelSettingsKeys.contains("eomSquelchTenths")) { - settings.m_eomSquelchTenths = response.getLoRaDemodSettings()->getEomSquelchTenths(); + settings.m_eomSquelchTenths = response.getChirpChatDemodSettings()->getEomSquelchTenths(); } if (channelSettingsKeys.contains("nbSymbolsMax")) { - settings.m_nbSymbolsMax = response.getLoRaDemodSettings()->getNbSymbolsMax(); + settings.m_nbSymbolsMax = response.getChirpChatDemodSettings()->getNbSymbolsMax(); } if (channelSettingsKeys.contains("autoNbSymbolsMax")) { - settings.m_autoNbSymbolsMax = response.getLoRaDemodSettings()->getAutoNbSymbolsMax() != 0; + settings.m_autoNbSymbolsMax = response.getChirpChatDemodSettings()->getAutoNbSymbolsMax() != 0; } if (channelSettingsKeys.contains("preambleChirps")) { - settings.m_preambleChirps = response.getLoRaDemodSettings()->getPreambleChirps(); + settings.m_preambleChirps = response.getChirpChatDemodSettings()->getPreambleChirps(); } if (channelSettingsKeys.contains("nbParityBits")) { - settings.m_nbParityBits = response.getLoRaDemodSettings()->getNbParityBits(); + settings.m_nbParityBits = response.getChirpChatDemodSettings()->getNbParityBits(); } if (channelSettingsKeys.contains("packetLength")) { - settings.m_packetLength = response.getLoRaDemodSettings()->getPacketLength(); + settings.m_packetLength = response.getChirpChatDemodSettings()->getPacketLength(); } if (channelSettingsKeys.contains("hasCRC")) { - settings.m_hasCRC = response.getLoRaDemodSettings()->getHasCrc() != 0; + settings.m_hasCRC = response.getChirpChatDemodSettings()->getHasCrc() != 0; } if (channelSettingsKeys.contains("hasHeader")) { - settings.m_hasHeader = response.getLoRaDemodSettings()->getHasHeader() != 0; + settings.m_hasHeader = response.getChirpChatDemodSettings()->getHasHeader() != 0; } if (channelSettingsKeys.contains("sendViaUDP")) { - settings.m_sendViaUDP = response.getLoRaDemodSettings()->getSendViaUdp() != 0; + settings.m_sendViaUDP = response.getChirpChatDemodSettings()->getSendViaUdp() != 0; } if (channelSettingsKeys.contains("udpAddress")) { - settings.m_udpAddress = *response.getLoRaDemodSettings()->getUdpAddress(); + settings.m_udpAddress = *response.getChirpChatDemodSettings()->getUdpAddress(); } if (channelSettingsKeys.contains("udpPort")) { - uint16_t port = response.getLoRaDemodSettings()->getUdpPort(); + uint16_t port = response.getChirpChatDemodSettings()->getUdpPort(); settings.m_udpPort = port < 1024 ? 1024 : port > 65535 ? 65535 : port; } if (channelSettingsKeys.contains("rgbColor")) { - settings.m_rgbColor = response.getLoRaDemodSettings()->getRgbColor(); + settings.m_rgbColor = response.getChirpChatDemodSettings()->getRgbColor(); } if (channelSettingsKeys.contains("title")) { - settings.m_title = *response.getLoRaDemodSettings()->getTitle(); + settings.m_title = *response.getChirpChatDemodSettings()->getTitle(); } if (channelSettingsKeys.contains("streamIndex")) { - settings.m_streamIndex = response.getLoRaDemodSettings()->getStreamIndex(); + settings.m_streamIndex = response.getChirpChatDemodSettings()->getStreamIndex(); } if (channelSettingsKeys.contains("useReverseAPI")) { - settings.m_useReverseAPI = response.getLoRaDemodSettings()->getUseReverseApi() != 0; + settings.m_useReverseAPI = response.getChirpChatDemodSettings()->getUseReverseApi() != 0; } if (channelSettingsKeys.contains("reverseAPIAddress")) { - settings.m_reverseAPIAddress = *response.getLoRaDemodSettings()->getReverseApiAddress(); + settings.m_reverseAPIAddress = *response.getChirpChatDemodSettings()->getReverseApiAddress(); } if (channelSettingsKeys.contains("reverseAPIPort")) { - settings.m_reverseAPIPort = response.getLoRaDemodSettings()->getReverseApiPort(); + settings.m_reverseAPIPort = response.getChirpChatDemodSettings()->getReverseApiPort(); } if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) { - settings.m_reverseAPIDeviceIndex = response.getLoRaDemodSettings()->getReverseApiDeviceIndex(); + settings.m_reverseAPIDeviceIndex = response.getChirpChatDemodSettings()->getReverseApiDeviceIndex(); } if (channelSettingsKeys.contains("reverseAPIChannelIndex")) { - settings.m_reverseAPIChannelIndex = response.getLoRaDemodSettings()->getReverseApiChannelIndex(); + settings.m_reverseAPIChannelIndex = response.getChirpChatDemodSettings()->getReverseApiChannelIndex(); } } -int LoRaDemod::webapiReportGet( +int ChirpChatDemod::webapiReportGet( SWGSDRangel::SWGChannelReport& response, QString& errorMessage) { (void) errorMessage; - response.setLoRaDemodReport(new SWGSDRangel::SWGLoRaDemodReport()); - response.getLoRaDemodReport()->init(); + response.setChirpChatDemodReport(new SWGSDRangel::SWGChirpChatDemodReport()); + response.getChirpChatDemodReport()->init(); webapiFormatChannelReport(response); return 200; } -void LoRaDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const LoRaDemodSettings& settings) +void ChirpChatDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const ChirpChatDemodSettings& settings) { - response.getLoRaDemodSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset); - response.getLoRaDemodSettings()->setBandwidthIndex(settings.m_bandwidthIndex); - response.getLoRaDemodSettings()->setSpreadFactor(settings.m_spreadFactor); - response.getLoRaDemodSettings()->setDeBits(settings.m_deBits); - response.getLoRaDemodSettings()->setCodingScheme((int) settings.m_codingScheme); - response.getLoRaDemodSettings()->setDecodeActive(settings.m_decodeActive ? 1 : 0); - response.getLoRaDemodSettings()->setEomSquelchTenths(settings.m_eomSquelchTenths); - response.getLoRaDemodSettings()->setNbSymbolsMax(settings.m_nbSymbolsMax); - response.getLoRaDemodSettings()->setAutoNbSymbolsMax(settings.m_autoNbSymbolsMax ? 1 : 0); - response.getLoRaDemodSettings()->setPreambleChirps(settings.m_preambleChirps); - response.getLoRaDemodSettings()->setNbParityBits(settings.m_nbParityBits); - response.getLoRaDemodSettings()->setHasCrc(settings.m_hasCRC ? 1 : 0); - response.getLoRaDemodSettings()->setHasHeader(settings.m_hasHeader ? 1 : 0); - response.getLoRaDemodSettings()->setSendViaUdp(settings.m_sendViaUDP ? 1 : 0); + response.getChirpChatDemodSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset); + response.getChirpChatDemodSettings()->setBandwidthIndex(settings.m_bandwidthIndex); + response.getChirpChatDemodSettings()->setSpreadFactor(settings.m_spreadFactor); + response.getChirpChatDemodSettings()->setDeBits(settings.m_deBits); + response.getChirpChatDemodSettings()->setCodingScheme((int) settings.m_codingScheme); + response.getChirpChatDemodSettings()->setDecodeActive(settings.m_decodeActive ? 1 : 0); + response.getChirpChatDemodSettings()->setEomSquelchTenths(settings.m_eomSquelchTenths); + response.getChirpChatDemodSettings()->setNbSymbolsMax(settings.m_nbSymbolsMax); + response.getChirpChatDemodSettings()->setAutoNbSymbolsMax(settings.m_autoNbSymbolsMax ? 1 : 0); + response.getChirpChatDemodSettings()->setPreambleChirps(settings.m_preambleChirps); + response.getChirpChatDemodSettings()->setNbParityBits(settings.m_nbParityBits); + response.getChirpChatDemodSettings()->setHasCrc(settings.m_hasCRC ? 1 : 0); + response.getChirpChatDemodSettings()->setHasHeader(settings.m_hasHeader ? 1 : 0); + response.getChirpChatDemodSettings()->setSendViaUdp(settings.m_sendViaUDP ? 1 : 0); - if (response.getLoRaDemodSettings()->getUdpAddress()) { - *response.getLoRaDemodSettings()->getUdpAddress() = settings.m_udpAddress; + if (response.getChirpChatDemodSettings()->getUdpAddress()) { + *response.getChirpChatDemodSettings()->getUdpAddress() = settings.m_udpAddress; } else { - response.getLoRaDemodSettings()->setUdpAddress(new QString(settings.m_udpAddress)); + response.getChirpChatDemodSettings()->setUdpAddress(new QString(settings.m_udpAddress)); } - response.getLoRaDemodSettings()->setUdpPort(settings.m_udpPort); - response.getLoRaDemodSettings()->setRgbColor(settings.m_rgbColor); + response.getChirpChatDemodSettings()->setUdpPort(settings.m_udpPort); + response.getChirpChatDemodSettings()->setRgbColor(settings.m_rgbColor); - if (response.getLoRaDemodSettings()->getTitle()) { - *response.getLoRaDemodSettings()->getTitle() = settings.m_title; + if (response.getChirpChatDemodSettings()->getTitle()) { + *response.getChirpChatDemodSettings()->getTitle() = settings.m_title; } else { - response.getLoRaDemodSettings()->setTitle(new QString(settings.m_title)); + response.getChirpChatDemodSettings()->setTitle(new QString(settings.m_title)); } - response.getLoRaDemodSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); + response.getChirpChatDemodSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0); - if (response.getLoRaDemodSettings()->getReverseApiAddress()) { - *response.getLoRaDemodSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress; + if (response.getChirpChatDemodSettings()->getReverseApiAddress()) { + *response.getChirpChatDemodSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress; } else { - response.getLoRaDemodSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress)); + response.getChirpChatDemodSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress)); } - response.getLoRaDemodSettings()->setReverseApiPort(settings.m_reverseAPIPort); - response.getLoRaDemodSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex); - response.getLoRaDemodSettings()->setReverseApiChannelIndex(settings.m_reverseAPIChannelIndex); + response.getChirpChatDemodSettings()->setReverseApiPort(settings.m_reverseAPIPort); + response.getChirpChatDemodSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex); + response.getChirpChatDemodSettings()->setReverseApiChannelIndex(settings.m_reverseAPIChannelIndex); } -void LoRaDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) +void ChirpChatDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response) { - response.getLoRaDemodReport()->setChannelPowerDb(CalcDb::dbPower(getTotalPower())); - response.getLoRaDemodReport()->setSignalPowerDb(m_lastMsgSignalDb); - response.getLoRaDemodReport()->setNoisePowerDb(CalcDb::dbPower(getCurrentNoiseLevel())); - response.getLoRaDemodReport()->setSnrPowerDb(m_lastMsgSignalDb - m_lastMsgNoiseDb); - response.getLoRaDemodReport()->setChannelSampleRate(m_basebandSink->getChannelSampleRate()); - response.getLoRaDemodReport()->setHasCrc(m_lastMsgHasCRC); - response.getLoRaDemodReport()->setNbParityBits(m_lastMsgNbParityBits); - response.getLoRaDemodReport()->setPacketLength(m_lastMsgPacketLength); - response.getLoRaDemodReport()->setNbSymbols(m_lastMsgNbSymbols); - response.getLoRaDemodReport()->setNbCodewords(m_lastMsgNbCodewords); - response.getLoRaDemodReport()->setHeaderParityStatus(m_lastMsgHeaderParityStatus); - response.getLoRaDemodReport()->setHeaderCrcStatus(m_lastMsgHeaderCRC); - response.getLoRaDemodReport()->setPayloadParityStatus(m_lastMsgPayloadParityStatus); - response.getLoRaDemodReport()->setPayloadCrcStatus(m_lastMsgPayloadCRC); - response.getLoRaDemodReport()->setMessageTimestamp(new QString(m_lastMsgTimestamp)); - response.getLoRaDemodReport()->setMessageString(new QString(m_lastMsgString)); + response.getChirpChatDemodReport()->setChannelPowerDb(CalcDb::dbPower(getTotalPower())); + response.getChirpChatDemodReport()->setSignalPowerDb(m_lastMsgSignalDb); + response.getChirpChatDemodReport()->setNoisePowerDb(CalcDb::dbPower(getCurrentNoiseLevel())); + response.getChirpChatDemodReport()->setSnrPowerDb(m_lastMsgSignalDb - m_lastMsgNoiseDb); + response.getChirpChatDemodReport()->setChannelSampleRate(m_basebandSink->getChannelSampleRate()); + response.getChirpChatDemodReport()->setHasCrc(m_lastMsgHasCRC); + response.getChirpChatDemodReport()->setNbParityBits(m_lastMsgNbParityBits); + response.getChirpChatDemodReport()->setPacketLength(m_lastMsgPacketLength); + response.getChirpChatDemodReport()->setNbSymbols(m_lastMsgNbSymbols); + response.getChirpChatDemodReport()->setNbCodewords(m_lastMsgNbCodewords); + response.getChirpChatDemodReport()->setHeaderParityStatus(m_lastMsgHeaderParityStatus); + response.getChirpChatDemodReport()->setHeaderCrcStatus(m_lastMsgHeaderCRC); + response.getChirpChatDemodReport()->setPayloadParityStatus(m_lastMsgPayloadParityStatus); + response.getChirpChatDemodReport()->setPayloadCrcStatus(m_lastMsgPayloadCRC); + response.getChirpChatDemodReport()->setMessageTimestamp(new QString(m_lastMsgTimestamp)); + response.getChirpChatDemodReport()->setMessageString(new QString(m_lastMsgString)); - response.getLoRaDemodReport()->setMessageBytes(new QList); - QList *bytesStr = response.getLoRaDemodReport()->getMessageBytes(); + response.getChirpChatDemodReport()->setMessageBytes(new QList); + QList *bytesStr = response.getChirpChatDemodReport()->getMessageBytes(); for (QByteArray::const_iterator it = m_lastMsgBytes.begin(); it != m_lastMsgBytes.end(); ++it) { @@ -604,71 +605,71 @@ void LoRaDemod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& respons } } -void LoRaDemod::webapiReverseSendSettings(QList& channelSettingsKeys, const LoRaDemodSettings& settings, bool force) +void ChirpChatDemod::webapiReverseSendSettings(QList& channelSettingsKeys, const ChirpChatDemodSettings& settings, bool force) { SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings(); swgChannelSettings->setDirection(1); // single source (Tx) swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet()); swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex()); - swgChannelSettings->setChannelType(new QString("LoRaMod")); - swgChannelSettings->setLoRaModSettings(new SWGSDRangel::SWGLoRaModSettings()); - SWGSDRangel::SWGLoRaDemodSettings *swgLoRaDemodSettings = swgChannelSettings->getLoRaDemodSettings(); + swgChannelSettings->setChannelType(new QString("ChirpChatDemod")); + swgChannelSettings->setChirpChatDemodSettings(new SWGSDRangel::SWGChirpChatDemodSettings()); + SWGSDRangel::SWGChirpChatDemodSettings *swgChirpChatDemodSettings = swgChannelSettings->getChirpChatDemodSettings(); // transfer data that has been modified. When force is on transfer all data except reverse API data if (channelSettingsKeys.contains("inputFrequencyOffset") || force) { - swgLoRaDemodSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset); + swgChirpChatDemodSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset); } if (channelSettingsKeys.contains("bandwidthIndex") || force) { - swgLoRaDemodSettings->setBandwidthIndex(settings.m_bandwidthIndex); + swgChirpChatDemodSettings->setBandwidthIndex(settings.m_bandwidthIndex); } if (channelSettingsKeys.contains("spreadFactor") || force) { - swgLoRaDemodSettings->setSpreadFactor(settings.m_spreadFactor); + swgChirpChatDemodSettings->setSpreadFactor(settings.m_spreadFactor); } if (channelSettingsKeys.contains("deBits") || force) { - swgLoRaDemodSettings->setDeBits(settings.m_deBits); + swgChirpChatDemodSettings->setDeBits(settings.m_deBits); } if (channelSettingsKeys.contains("codingScheme") || force) { - swgLoRaDemodSettings->setCodingScheme((int) settings.m_codingScheme); + swgChirpChatDemodSettings->setCodingScheme((int) settings.m_codingScheme); } if (channelSettingsKeys.contains("decodeActive") || force) { - swgLoRaDemodSettings->setDecodeActive(settings.m_decodeActive ? 1 : 0); + swgChirpChatDemodSettings->setDecodeActive(settings.m_decodeActive ? 1 : 0); } if (channelSettingsKeys.contains("eomSquelchTenths") || force) { - swgLoRaDemodSettings->setEomSquelchTenths(settings.m_eomSquelchTenths); + swgChirpChatDemodSettings->setEomSquelchTenths(settings.m_eomSquelchTenths); } if (channelSettingsKeys.contains("nbSymbolsMax") || force) { - swgLoRaDemodSettings->setNbSymbolsMax(settings.m_nbSymbolsMax); + swgChirpChatDemodSettings->setNbSymbolsMax(settings.m_nbSymbolsMax); } if (channelSettingsKeys.contains("autoNbSymbolsMax") || force) { - swgLoRaDemodSettings->setAutoNbSymbolsMax(settings.m_nbSymbolsMax ? 1 : 0); + swgChirpChatDemodSettings->setAutoNbSymbolsMax(settings.m_nbSymbolsMax ? 1 : 0); } if (channelSettingsKeys.contains("preambleChirps") || force) { - swgLoRaDemodSettings->setPreambleChirps(settings.m_preambleChirps); + swgChirpChatDemodSettings->setPreambleChirps(settings.m_preambleChirps); } if (channelSettingsKeys.contains("nbParityBits") || force) { - swgLoRaDemodSettings->setNbParityBits(settings.m_nbParityBits); + swgChirpChatDemodSettings->setNbParityBits(settings.m_nbParityBits); } if (channelSettingsKeys.contains("hasCRC") || force) { - swgLoRaDemodSettings->setHasCrc(settings.m_hasCRC ? 1 : 0); + swgChirpChatDemodSettings->setHasCrc(settings.m_hasCRC ? 1 : 0); } if (channelSettingsKeys.contains("hasHeader") || force) { - swgLoRaDemodSettings->setHasHeader(settings.m_hasHeader ? 1 : 0); + swgChirpChatDemodSettings->setHasHeader(settings.m_hasHeader ? 1 : 0); } if (channelSettingsKeys.contains("sendViaUDP") || force) { - swgLoRaDemodSettings->setSendViaUdp(settings.m_sendViaUDP ? 1 : 0); + swgChirpChatDemodSettings->setSendViaUdp(settings.m_sendViaUDP ? 1 : 0); } if (channelSettingsKeys.contains("udpAddress") || force) { - swgLoRaDemodSettings->setUdpAddress(new QString(settings.m_udpAddress)); + swgChirpChatDemodSettings->setUdpAddress(new QString(settings.m_udpAddress)); } if (channelSettingsKeys.contains("updPort") || force) { - swgLoRaDemodSettings->setUdpPort(settings.m_udpPort); + swgChirpChatDemodSettings->setUdpPort(settings.m_udpPort); } if (channelSettingsKeys.contains("rgbColor") || force) { - swgLoRaDemodSettings->setRgbColor(settings.m_rgbColor); + swgChirpChatDemodSettings->setRgbColor(settings.m_rgbColor); } if (channelSettingsKeys.contains("title") || force) { - swgLoRaDemodSettings->setTitle(new QString(settings.m_title)); + swgChirpChatDemodSettings->setTitle(new QString(settings.m_title)); } QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings") @@ -691,13 +692,13 @@ void LoRaDemod::webapiReverseSendSettings(QList& channelSettingsKeys, c delete swgChannelSettings; } -void LoRaDemod::networkManagerFinished(QNetworkReply *reply) +void ChirpChatDemod::networkManagerFinished(QNetworkReply *reply) { QNetworkReply::NetworkError replyError = reply->error(); if (replyError) { - qWarning() << "LoRaDemod::networkManagerFinished:" + qWarning() << "ChirpChatDemod::networkManagerFinished:" << " error(" << (int) replyError << "): " << replyError << ": " << reply->errorString(); @@ -706,23 +707,23 @@ void LoRaDemod::networkManagerFinished(QNetworkReply *reply) { QString answer = reply->readAll(); answer.chop(1); // remove last \n - qDebug("LoRaDemod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); + qDebug("ChirpChatDemod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); } reply->deleteLater(); } -bool LoRaDemod::getDemodActive() const +bool ChirpChatDemod::getDemodActive() const { return m_basebandSink->getDemodActive(); } -double LoRaDemod::getCurrentNoiseLevel() const +double ChirpChatDemod::getCurrentNoiseLevel() const { return m_basebandSink->getCurrentNoiseLevel(); } -double LoRaDemod::getTotalPower() const +double ChirpChatDemod::getTotalPower() const { return m_basebandSink->getTotalPower(); } diff --git a/plugins/channelrx/demodlora/lorademod.h b/plugins/channelrx/demodchirpchat/chirpchatdemod.h similarity index 89% rename from plugins/channelrx/demodlora/lorademod.h rename to plugins/channelrx/demodchirpchat/chirpchatdemod.h index ba9c078a3..88270d2ee 100644 --- a/plugins/channelrx/demodlora/lorademod.h +++ b/plugins/channelrx/demodchirpchat/chirpchatdemod.h @@ -17,8 +17,8 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDE_LORADEMOD_H -#define INCLUDE_LORADEMOD_H +#ifndef INCLUDE_CHIRPCHATDEMOD_H +#define INCLUDE_CHIRPCHATDEMOD_H #include @@ -29,33 +29,33 @@ #include "util/message.h" #include "util/udpsinkutil.h" -#include "lorademodbaseband.h" -#include "lorademoddecoder.h" +#include "chirpchatdemodbaseband.h" +#include "chirpchatdemoddecoder.h" class QNetworkAccessManager; class QNetworkReply; class DeviceAPI; class QThread; -class LoRaDemod : public BasebandSampleSink, public ChannelAPI { +class ChirpChatDemod : public BasebandSampleSink, public ChannelAPI { public: - class MsgConfigureLoRaDemod : public Message { + class MsgConfigureChirpChatDemod : public Message { MESSAGE_CLASS_DECLARATION public: - const LoRaDemodSettings& getSettings() const { return m_settings; } + const ChirpChatDemodSettings& getSettings() const { return m_settings; } bool getForce() const { return m_force; } - static MsgConfigureLoRaDemod* create(const LoRaDemodSettings& settings, bool force) + static MsgConfigureChirpChatDemod* create(const ChirpChatDemodSettings& settings, bool force) { - return new MsgConfigureLoRaDemod(settings, force); + return new MsgConfigureChirpChatDemod(settings, force); } private: - LoRaDemodSettings m_settings; + ChirpChatDemodSettings m_settings; bool m_force; - MsgConfigureLoRaDemod(const LoRaDemodSettings& settings, bool force) : + MsgConfigureChirpChatDemod(const ChirpChatDemodSettings& settings, bool force) : Message(), m_settings(settings), m_force(force) @@ -197,8 +197,8 @@ public: { } }; - LoRaDemod(DeviceAPI* deviceAPI); - virtual ~LoRaDemod(); + ChirpChatDemod(DeviceAPI* deviceAPI); + virtual ~ChirpChatDemod(); virtual void destroy() { delete this; } void setSpectrumSink(BasebandSampleSink* sampleSink) { m_basebandSink->setSpectrumSink(sampleSink); } @@ -240,10 +240,10 @@ public: static void webapiFormatChannelSettings( SWGSDRangel::SWGChannelSettings& response, - const LoRaDemodSettings& settings); + const ChirpChatDemodSettings& settings); static void webapiUpdateChannelSettings( - LoRaDemodSettings& settings, + ChirpChatDemodSettings& settings, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response); @@ -259,9 +259,9 @@ public: private: DeviceAPI *m_deviceAPI; QThread *m_thread; - LoRaDemodBaseband* m_basebandSink; - LoRaDemodDecoder m_decoder; - LoRaDemodSettings m_settings; + ChirpChatDemodBaseband* m_basebandSink; + ChirpChatDemodDecoder m_decoder; + ChirpChatDemodSettings m_settings; int m_basebandSampleRate; //!< stored from device message used when starting baseband sink float m_lastMsgSignalDb; float m_lastMsgNoiseDb; @@ -284,12 +284,12 @@ private: QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; - void applySettings(const LoRaDemodSettings& settings, bool force = false); + void applySettings(const ChirpChatDemodSettings& settings, bool force = false); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); - void webapiReverseSendSettings(QList& channelSettingsKeys, const LoRaDemodSettings& settings, bool force); + void webapiReverseSendSettings(QList& channelSettingsKeys, const ChirpChatDemodSettings& settings, bool force); private slots: void networkManagerFinished(QNetworkReply *reply); }; -#endif // INCLUDE_LORADEMOD_H +#endif // INCLUDE_CHIRPCHATDEMOD_H diff --git a/plugins/channelrx/demodlora/lorademodbaseband.cpp b/plugins/channelrx/demodchirpchat/chirpchatdemodbaseband.cpp similarity index 73% rename from plugins/channelrx/demodlora/lorademodbaseband.cpp rename to plugins/channelrx/demodchirpchat/chirpchatdemodbaseband.cpp index 467dc6c27..125f22588 100644 --- a/plugins/channelrx/demodlora/lorademodbaseband.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodbaseband.cpp @@ -21,45 +21,45 @@ #include "dsp/dspcommands.h" #include "dsp/downchannelizer.h" -#include "lorademodbaseband.h" +#include "chirpchatdemodbaseband.h" -MESSAGE_CLASS_DEFINITION(LoRaDemodBaseband::MsgConfigureLoRaDemodBaseband, Message) +MESSAGE_CLASS_DEFINITION(ChirpChatDemodBaseband::MsgConfigureChirpChatDemodBaseband, Message) -LoRaDemodBaseband::LoRaDemodBaseband() : +ChirpChatDemodBaseband::ChirpChatDemodBaseband() : m_mutex(QMutex::Recursive) { m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(48000)); m_channelizer = new DownChannelizer(&m_sink); - qDebug("LoRaDemodBaseband::LoRaDemodBaseband"); + qDebug("ChirpChatDemodBaseband::ChirpChatDemodBaseband"); QObject::connect( &m_sampleFifo, &SampleSinkFifo::dataReady, this, - &LoRaDemodBaseband::handleData, + &ChirpChatDemodBaseband::handleData, Qt::QueuedConnection ); connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); } -LoRaDemodBaseband::~LoRaDemodBaseband() +ChirpChatDemodBaseband::~ChirpChatDemodBaseband() { delete m_channelizer; } -void LoRaDemodBaseband::reset() +void ChirpChatDemodBaseband::reset() { QMutexLocker mutexLocker(&m_mutex); m_sampleFifo.reset(); } -void LoRaDemodBaseband::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end) +void ChirpChatDemodBaseband::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end) { m_sampleFifo.write(begin, end); } -void LoRaDemodBaseband::handleData() +void ChirpChatDemodBaseband::handleData() { QMutexLocker mutexLocker(&m_mutex); @@ -86,7 +86,7 @@ void LoRaDemodBaseband::handleData() } } -void LoRaDemodBaseband::handleInputMessages() +void ChirpChatDemodBaseband::handleInputMessages() { Message* message; @@ -98,13 +98,13 @@ void LoRaDemodBaseband::handleInputMessages() } } -bool LoRaDemodBaseband::handleMessage(const Message& cmd) +bool ChirpChatDemodBaseband::handleMessage(const Message& cmd) { - if (MsgConfigureLoRaDemodBaseband::match(cmd)) + if (MsgConfigureChirpChatDemodBaseband::match(cmd)) { QMutexLocker mutexLocker(&m_mutex); - MsgConfigureLoRaDemodBaseband& cfg = (MsgConfigureLoRaDemodBaseband&) cmd; - qDebug() << "LoRaDemodBaseband::handleMessage: MsgConfigureLoRaDemodBaseband"; + MsgConfigureChirpChatDemodBaseband& cfg = (MsgConfigureChirpChatDemodBaseband&) cmd; + qDebug() << "ChirpChatDemodBaseband::handleMessage: MsgConfigureChirpChatDemodBaseband"; applySettings(cfg.getSettings(), cfg.getForce()); @@ -114,12 +114,12 @@ bool LoRaDemodBaseband::handleMessage(const Message& cmd) { QMutexLocker mutexLocker(&m_mutex); DSPSignalNotification& notif = (DSPSignalNotification&) cmd; - qDebug() << "LoRaDemodBaseband::handleMessage: DSPSignalNotification: basebandSampleRate: " << notif.getSampleRate(); + qDebug() << "ChirpChatDemodBaseband::handleMessage: DSPSignalNotification: basebandSampleRate: " << notif.getSampleRate(); m_sampleFifo.setSize(SampleSinkFifo::getSizePolicy(notif.getSampleRate())); m_channelizer->setBasebandSampleRate(notif.getSampleRate()); m_sink.applyChannelSettings( m_channelizer->getChannelSampleRate(), - LoRaDemodSettings::bandwidths[m_settings.m_bandwidthIndex], + ChirpChatDemodSettings::bandwidths[m_settings.m_bandwidthIndex], m_channelizer->getChannelFrequencyOffset() ); @@ -131,18 +131,18 @@ bool LoRaDemodBaseband::handleMessage(const Message& cmd) } } -void LoRaDemodBaseband::applySettings(const LoRaDemodSettings& settings, bool force) +void ChirpChatDemodBaseband::applySettings(const ChirpChatDemodSettings& settings, bool force) { if ((settings.m_bandwidthIndex != m_settings.m_bandwidthIndex) || (settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) { m_channelizer->setChannelization( - LoRaDemodSettings::bandwidths[settings.m_bandwidthIndex]*LoRaDemodSettings::oversampling, + ChirpChatDemodSettings::bandwidths[settings.m_bandwidthIndex]*ChirpChatDemodSettings::oversampling, settings.m_inputFrequencyOffset ); m_sink.applyChannelSettings( m_channelizer->getChannelSampleRate(), - LoRaDemodSettings::bandwidths[settings.m_bandwidthIndex], + ChirpChatDemodSettings::bandwidths[settings.m_bandwidthIndex], m_channelizer->getChannelFrequencyOffset() ); } @@ -152,18 +152,18 @@ void LoRaDemodBaseband::applySettings(const LoRaDemodSettings& settings, bool fo m_settings = settings; } -int LoRaDemodBaseband::getChannelSampleRate() const +int ChirpChatDemodBaseband::getChannelSampleRate() const { return m_channelizer->getChannelSampleRate(); } -void LoRaDemodBaseband::setBasebandSampleRate(int sampleRate) +void ChirpChatDemodBaseband::setBasebandSampleRate(int sampleRate) { m_channelizer->setBasebandSampleRate(sampleRate); m_sink.applyChannelSettings( m_channelizer->getChannelSampleRate(), - LoRaDemodSettings::bandwidths[m_settings.m_bandwidthIndex], + ChirpChatDemodSettings::bandwidths[m_settings.m_bandwidthIndex], m_channelizer->getChannelFrequencyOffset() ); } diff --git a/plugins/channelrx/demodlora/lorademodbaseband.h b/plugins/channelrx/demodchirpchat/chirpchatdemodbaseband.h similarity index 76% rename from plugins/channelrx/demodlora/lorademodbaseband.h rename to plugins/channelrx/demodchirpchat/chirpchatdemodbaseband.h index 0766dca45..fc7bf8182 100644 --- a/plugins/channelrx/demodlora/lorademodbaseband.h +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodbaseband.h @@ -15,8 +15,8 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDE_LORADEMODBASEBAND_H -#define INCLUDE_LORADEMODBASEBAND_H +#ifndef INCLUDE_CHIRPCHATDEMODBASEBAND_H +#define INCLUDE_CHIRPCHATDEMODBASEBAND_H #include #include @@ -25,39 +25,39 @@ #include "util/message.h" #include "util/messagequeue.h" -#include "lorademodsink.h" +#include "chirpchatdemodsink.h" class DownChannelizer; -class LoRaDemodBaseband : public QObject +class ChirpChatDemodBaseband : public QObject { Q_OBJECT public: - class MsgConfigureLoRaDemodBaseband : public Message { + class MsgConfigureChirpChatDemodBaseband : public Message { MESSAGE_CLASS_DECLARATION public: - const LoRaDemodSettings& getSettings() const { return m_settings; } + const ChirpChatDemodSettings& getSettings() const { return m_settings; } bool getForce() const { return m_force; } - static MsgConfigureLoRaDemodBaseband* create(const LoRaDemodSettings& settings, bool force) + static MsgConfigureChirpChatDemodBaseband* create(const ChirpChatDemodSettings& settings, bool force) { - return new MsgConfigureLoRaDemodBaseband(settings, force); + return new MsgConfigureChirpChatDemodBaseband(settings, force); } private: - LoRaDemodSettings m_settings; + ChirpChatDemodSettings m_settings; bool m_force; - MsgConfigureLoRaDemodBaseband(const LoRaDemodSettings& settings, bool force) : + MsgConfigureChirpChatDemodBaseband(const ChirpChatDemodSettings& settings, bool force) : Message(), m_settings(settings), m_force(force) { } }; - LoRaDemodBaseband(); - ~LoRaDemodBaseband(); + ChirpChatDemodBaseband(); + ~ChirpChatDemodBaseband(); void reset(); void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end); MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication @@ -72,17 +72,17 @@ public: private: SampleSinkFifo m_sampleFifo; DownChannelizer *m_channelizer; - LoRaDemodSink m_sink; + ChirpChatDemodSink m_sink; MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication - LoRaDemodSettings m_settings; + ChirpChatDemodSettings m_settings; QMutex m_mutex; bool handleMessage(const Message& cmd); - void applySettings(const LoRaDemodSettings& settings, bool force = false); + void applySettings(const ChirpChatDemodSettings& settings, bool force = false); private slots: void handleInputMessages(); void handleData(); //!< Handle data when samples have to be processed }; -#endif // INCLUDE_LORADEMODBASEBAND_H +#endif // INCLUDE_CHIRPCHATDEMODBASEBAND_H diff --git a/plugins/channelrx/demodlora/lorademoddecoder.cpp b/plugins/channelrx/demodchirpchat/chirpchatdemoddecoder.cpp similarity index 72% rename from plugins/channelrx/demodlora/lorademoddecoder.cpp rename to plugins/channelrx/demodchirpchat/chirpchatdemoddecoder.cpp index e9d46cb38..7551c43fc 100644 --- a/plugins/channelrx/demodlora/lorademoddecoder.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatdemoddecoder.cpp @@ -15,23 +15,23 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include "lorademoddecoder.h" -#include "lorademoddecodertty.h" -#include "lorademoddecoderascii.h" -#include "lorademoddecoderlora.h" +#include "chirpchatdemoddecoder.h" +#include "chirpchatdemoddecodertty.h" +#include "chirpchatdemoddecoderascii.h" +#include "chirpchatdemoddecoderlora.h" -LoRaDemodDecoder::LoRaDemodDecoder() : - m_codingScheme(LoRaDemodSettings::CodingTTY), +ChirpChatDemodDecoder::ChirpChatDemodDecoder() : + m_codingScheme(ChirpChatDemodSettings::CodingTTY), m_nbSymbolBits(5), m_nbParityBits(1), m_hasCRC(true), m_hasHeader(true) {} -LoRaDemodDecoder::~LoRaDemodDecoder() +ChirpChatDemodDecoder::~ChirpChatDemodDecoder() {} -void LoRaDemodDecoder::setNbSymbolBits(unsigned int spreadFactor, unsigned int deBits) +void ChirpChatDemodDecoder::setNbSymbolBits(unsigned int spreadFactor, unsigned int deBits) { m_spreadFactor = spreadFactor; @@ -44,18 +44,18 @@ void LoRaDemodDecoder::setNbSymbolBits(unsigned int spreadFactor, unsigned int d m_nbSymbolBits = m_spreadFactor - m_deBits; } -void LoRaDemodDecoder::decodeSymbols(const std::vector& symbols, QString& str) +void ChirpChatDemodDecoder::decodeSymbols(const std::vector& symbols, QString& str) { switch(m_codingScheme) { - case LoRaDemodSettings::CodingTTY: + case ChirpChatDemodSettings::CodingTTY: if (m_nbSymbolBits == 5) { - LoRaDemodDecoderTTY::decodeSymbols(symbols, str); + ChirpChatDemodDecoderTTY::decodeSymbols(symbols, str); } break; - case LoRaDemodSettings::CodingASCII: + case ChirpChatDemodSettings::CodingASCII: if (m_nbSymbolBits == 5) { - LoRaDemodDecoderASCII::decodeSymbols(symbols, str); + ChirpChatDemodDecoderASCII::decodeSymbols(symbols, str); } break; default: @@ -63,14 +63,14 @@ void LoRaDemodDecoder::decodeSymbols(const std::vector& symbols, } } -void LoRaDemodDecoder::decodeSymbols(const std::vector& symbols, QByteArray& bytes) +void ChirpChatDemodDecoder::decodeSymbols(const std::vector& symbols, QByteArray& bytes) { switch(m_codingScheme) { - case LoRaDemodSettings::CodingLoRa: + case ChirpChatDemodSettings::CodingLoRa: if (m_nbSymbolBits >= 5) { - LoRaDemodDecoderLoRa::decodeBytes( + ChirpChatDemodDecoderLoRa::decodeBytes( bytes, symbols, m_nbSymbolBits, @@ -84,7 +84,7 @@ void LoRaDemodDecoder::decodeSymbols(const std::vector& symbols, m_payloadParityStatus, m_payloadCRCStatus ); - LoRaDemodDecoderLoRa::getCodingMetrics( + ChirpChatDemodDecoderLoRa::getCodingMetrics( m_nbSymbolBits, m_nbParityBits, m_packetLength, diff --git a/plugins/channelrx/demodlora/lorademoddecoder.h b/plugins/channelrx/demodchirpchat/chirpchatdemoddecoder.h similarity index 89% rename from plugins/channelrx/demodlora/lorademoddecoder.h rename to plugins/channelrx/demodchirpchat/chirpchatdemoddecoder.h index ffe79a88e..194690787 100644 --- a/plugins/channelrx/demodlora/lorademoddecoder.h +++ b/plugins/channelrx/demodchirpchat/chirpchatdemoddecoder.h @@ -15,19 +15,19 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDE_LORADEMODDECODER_H -#define INCLUDE_LORADEMODDECODER_H +#ifndef INCLUDE_CHIRPCHATDEMODDECODER_H +#define INCLUDE_CHIRPCHATDEMODDECODER_H #include -#include "lorademodsettings.h" +#include "chirpchatdemodsettings.h" -class LoRaDemodDecoder +class ChirpChatDemodDecoder { public: - LoRaDemodDecoder(); - ~LoRaDemodDecoder(); + ChirpChatDemodDecoder(); + ~ChirpChatDemodDecoder(); - void setCodingScheme(LoRaDemodSettings::CodingScheme codingScheme) { m_codingScheme = codingScheme; } + void setCodingScheme(ChirpChatDemodSettings::CodingScheme codingScheme) { m_codingScheme = codingScheme; } void setNbSymbolBits(unsigned int spreadFactor, unsigned int deBits); void setLoRaParityBits(unsigned int parityBits) { m_nbParityBits = parityBits; } void setLoRaHasHeader(bool hasHeader) { m_hasHeader = hasHeader; } @@ -47,7 +47,7 @@ public: bool getPayloadCRCStatus() const { return m_payloadCRCStatus; } private: - LoRaDemodSettings::CodingScheme m_codingScheme; + ChirpChatDemodSettings::CodingScheme m_codingScheme; unsigned int m_spreadFactor; unsigned int m_deBits; unsigned int m_nbSymbolBits; @@ -65,4 +65,4 @@ private: bool m_payloadCRCStatus; }; -#endif // INCLUDE_LORADEMODDECODER_H +#endif // INCLUDE_CHIRPCHATDEMODDECODER_H diff --git a/plugins/channelrx/demodlora/lorademoddecoderascii.cpp b/plugins/channelrx/demodchirpchat/chirpchatdemoddecoderascii.cpp similarity index 91% rename from plugins/channelrx/demodlora/lorademoddecoderascii.cpp rename to plugins/channelrx/demodchirpchat/chirpchatdemoddecoderascii.cpp index f70043fbe..a46424c0a 100644 --- a/plugins/channelrx/demodlora/lorademoddecoderascii.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatdemoddecoderascii.cpp @@ -15,9 +15,9 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include "lorademoddecoderascii.h" +#include "chirpchatdemoddecoderascii.h" -void LoRaDemodDecoderASCII::decodeSymbols(const std::vector& symbols, QString& str) +void ChirpChatDemodDecoderASCII::decodeSymbols(const std::vector& symbols, QString& str) { std::vector::const_iterator it = symbols.begin(); QByteArray bytes; diff --git a/plugins/channelrx/demodlora/lorademoddecoderascii.h b/plugins/channelrx/demodchirpchat/chirpchatdemoddecoderascii.h similarity index 89% rename from plugins/channelrx/demodlora/lorademoddecoderascii.h rename to plugins/channelrx/demodchirpchat/chirpchatdemoddecoderascii.h index a014dd94f..29df80541 100644 --- a/plugins/channelrx/demodlora/lorademoddecoderascii.h +++ b/plugins/channelrx/demodchirpchat/chirpchatdemoddecoderascii.h @@ -15,16 +15,16 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDE_LORADEMODDECODERASCII_H -#define INCLUDE_LORADEMODDECODERASCII_H +#ifndef INCLUDE_CHIRPCHATDEMODDECODERASCII_H +#define INCLUDE_CHIRPCHATDEMODDECODERASCII_H #include #include -class LoRaDemodDecoderASCII +class ChirpChatDemodDecoderASCII { public: static void decodeSymbols(const std::vector& symbols, QString& str); }; -#endif // INCLUDE_LORADEMODDECODERASCII_H +#endif // INCLUDE_CHIRPCHATDEMODDECODERASCII_H diff --git a/plugins/channelrx/demodlora/lorademoddecoderlora.cpp b/plugins/channelrx/demodchirpchat/chirpchatdemoddecoderlora.cpp similarity index 95% rename from plugins/channelrx/demodlora/lorademoddecoderlora.cpp rename to plugins/channelrx/demodchirpchat/chirpchatdemoddecoderlora.cpp index 530ba599a..19aa9e3d5 100644 --- a/plugins/channelrx/demodlora/lorademoddecoderlora.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatdemoddecoderlora.cpp @@ -17,9 +17,9 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include "lorademoddecoderlora.h" +#include "chirpchatdemoddecoderlora.h" -void LoRaDemodDecoderLoRa::decodeHeader( +void ChirpChatDemodDecoderLoRa::decodeHeader( const std::vector& inSymbols, unsigned int nbSymbolBits, bool& hasCRC, @@ -96,7 +96,7 @@ void LoRaDemodDecoderLoRa::decodeHeader( packetLength = bytes[0]; } -void LoRaDemodDecoderLoRa::decodeBytes( +void ChirpChatDemodDecoderLoRa::decodeBytes( QByteArray& inBytes, const std::vector& inSymbols, unsigned int nbSymbolBits, @@ -114,7 +114,7 @@ void LoRaDemodDecoderLoRa::decodeBytes( // need at least a header (8 symbols of 8 bit codewords) whether an actual header is sent or not if (inSymbols.size() < headerSymbols) { - qDebug("LoRaDemodDecoderLoRa::decodeBytes: need at least %u symbols for header", headerSymbols); + qDebug("ChirpChatDemodDecoderLoRa::decodeBytes: need at least %u symbols for header", headerSymbols); earlyEOM = true; return; } @@ -136,12 +136,12 @@ void LoRaDemodDecoderLoRa::decodeBytes( ); } - qDebug("LoRaDemodDecoderLoRa::decodeBytes: crc: %s nbParityBits: %u packetLength: %u", + qDebug("ChirpChatDemodDecoderLoRa::decodeBytes: crc: %s nbParityBits: %u packetLength: %u", hasCRC ? "on": "off", nbParityBits, packetLength); if (nbParityBits > 4) { - qDebug("LoRaDemodDecoderLoRa::decodeBytes: invalid parity bits in header: %u", nbParityBits); + qDebug("ChirpChatDemodDecoderLoRa::decodeBytes: invalid parity bits in header: %u", nbParityBits); return; } @@ -222,7 +222,7 @@ void LoRaDemodDecoderLoRa::decodeBytes( if (dataLength > bytes.size()) { - qDebug("LoRaDemodDecoderLoRa::decodeBytes: not enough data %lu vs %u", bytes.size(), dataLength); + qDebug("ChirpChatDemodDecoderLoRa::decodeBytes: not enough data %lu vs %u", bytes.size(), dataLength); earlyEOM = true; return; } @@ -352,7 +352,7 @@ void LoRaDemodDecoderLoRa::decodeBytes( std::copy(bytes.data() + dOfs, bytes.data() + dOfs + dataLength, inBytes.data()); } -void LoRaDemodDecoderLoRa::getCodingMetrics( +void ChirpChatDemodDecoderLoRa::getCodingMetrics( unsigned int nbSymbolBits, unsigned int nbParityBits, unsigned int packetLength, diff --git a/plugins/channelrx/demodlora/lorademoddecoderlora.h b/plugins/channelrx/demodchirpchat/chirpchatdemoddecoderlora.h similarity index 98% rename from plugins/channelrx/demodlora/lorademoddecoderlora.h rename to plugins/channelrx/demodchirpchat/chirpchatdemoddecoderlora.h index 3f1bf4d84..25926f9a2 100644 --- a/plugins/channelrx/demodlora/lorademoddecoderlora.h +++ b/plugins/channelrx/demodchirpchat/chirpchatdemoddecoderlora.h @@ -17,13 +17,13 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDE_LORADEMODDECODERLORA_H -#define INCLUDE_LORADEMODDECODERLORA_H +#ifndef INCLUDE_CHIRPCHATDEMODDECODERLORA_H +#define INCLUDE_CHIRPCHATDEMODDECODERLORA_H #include #include -class LoRaDemodDecoderLoRa +class ChirpChatDemodDecoderLoRa { public: enum ParityStatus @@ -354,4 +354,4 @@ private: } }; -#endif // INCLUDE_LORADEMODDECODERLORA_H +#endif // INCLUDE_CHIRPCHATDEMODDECODERLORA_H diff --git a/plugins/channelrx/demodlora/lorademoddecodertty.cpp b/plugins/channelrx/demodchirpchat/chirpchatdemoddecodertty.cpp similarity index 90% rename from plugins/channelrx/demodlora/lorademoddecodertty.cpp rename to plugins/channelrx/demodchirpchat/chirpchatdemoddecodertty.cpp index 277a8ca95..6c746f624 100644 --- a/plugins/channelrx/demodlora/lorademoddecodertty.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatdemoddecodertty.cpp @@ -15,23 +15,23 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include "lorademoddecodertty.h" +#include "chirpchatdemoddecodertty.h" -const char LoRaDemodDecoderTTY::ttyLetters[32] = { +const char ChirpChatDemodDecoderTTY::ttyLetters[32] = { '\0', 'E', '\n', 'A', ' ', 'S', 'I', 'U', '\r', 'D', 'R', 'J', 'N', 'F', 'C', 'K', 'T', 'Z', 'L', 'W', 'H', 'Y', 'P', 'Q', 'O', 'B', 'G', ' ', 'M', 'X', 'V', ' ' }; -const char LoRaDemodDecoderTTY::ttyFigures[32] = { // U.S. standard +const char ChirpChatDemodDecoderTTY::ttyFigures[32] = { // U.S. standard '\0', '3', '\n', '-', ' ', '\a', '8', '7', '\r', '$', '4', '\'', ',', '!', ':', '(', '5', '"', ')', '2', '#', '6', '0', '1', '9', '?', '&', ' ', '.', '/', ';', ' ' }; -void LoRaDemodDecoderTTY::decodeSymbols(const std::vector& symbols, QString& str) +void ChirpChatDemodDecoderTTY::decodeSymbols(const std::vector& symbols, QString& str) { std::vector::const_iterator it = symbols.begin(); QByteArray bytes; diff --git a/plugins/channelrx/demodlora/lorademoddecodertty.h b/plugins/channelrx/demodchirpchat/chirpchatdemoddecodertty.h similarity index 91% rename from plugins/channelrx/demodlora/lorademoddecodertty.h rename to plugins/channelrx/demodchirpchat/chirpchatdemoddecodertty.h index 349491d3c..469afcadf 100644 --- a/plugins/channelrx/demodlora/lorademoddecodertty.h +++ b/plugins/channelrx/demodchirpchat/chirpchatdemoddecodertty.h @@ -15,13 +15,13 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDE_LORADEMODDECODERTTY_H -#define INCLUDE_LORADEMODDECODERTTY_H +#ifndef INCLUDE_CHIRPCHATDEMODDECODERTTY_H +#define INCLUDE_CHIRPCHATDEMODDECODERTTY_H #include #include -class LoRaDemodDecoderTTY +class ChirpChatDemodDecoderTTY { public: static void decodeSymbols(const std::vector& symbols, QString& str); @@ -39,4 +39,4 @@ private: static const char figuresTag = 0x1b; }; -#endif // INCLUDE_LORADEMODDECODERTTY_H \ No newline at end of file +#endif // INCLUDE_CHIRPCHATDEMODDECODERTTY_H \ No newline at end of file diff --git a/plugins/channelrx/demodlora/lorademodgui.cpp b/plugins/channelrx/demodchirpchat/chirpchatdemodgui.cpp similarity index 77% rename from plugins/channelrx/demodlora/lorademodgui.cpp rename to plugins/channelrx/demodchirpchat/chirpchatdemodgui.cpp index 9f43ddd1b..36bb245ba 100644 --- a/plugins/channelrx/demodlora/lorademodgui.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodgui.cpp @@ -19,7 +19,7 @@ #include #include -#include "ui_lorademodgui.h" +#include "ui_chirpchatdemodgui.h" #include "dsp/spectrumvis.h" #include "dsp/dspengine.h" #include "dsp/dspcommands.h" @@ -32,53 +32,53 @@ #include "util/db.h" #include "mainwindow.h" -#include "lorademod.h" -#include "lorademodgui.h" +#include "chirpchatdemod.h" +#include "chirpchatdemodgui.h" -LoRaDemodGUI* LoRaDemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) +ChirpChatDemodGUI* ChirpChatDemodGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) { - LoRaDemodGUI* gui = new LoRaDemodGUI(pluginAPI, deviceUISet, rxChannel); + ChirpChatDemodGUI* gui = new ChirpChatDemodGUI(pluginAPI, deviceUISet, rxChannel); return gui; } -void LoRaDemodGUI::destroy() +void ChirpChatDemodGUI::destroy() { delete this; } -void LoRaDemodGUI::setName(const QString& name) +void ChirpChatDemodGUI::setName(const QString& name) { setObjectName(name); } -QString LoRaDemodGUI::getName() const +QString ChirpChatDemodGUI::getName() const { return objectName(); } -qint64 LoRaDemodGUI::getCenterFrequency() const { +qint64 ChirpChatDemodGUI::getCenterFrequency() const { return m_channelMarker.getCenterFrequency(); } -void LoRaDemodGUI::setCenterFrequency(qint64 centerFrequency) +void ChirpChatDemodGUI::setCenterFrequency(qint64 centerFrequency) { m_channelMarker.setCenterFrequency(centerFrequency); applySettings(); } -void LoRaDemodGUI::resetToDefaults() +void ChirpChatDemodGUI::resetToDefaults() { m_settings.resetToDefaults(); displaySettings(); applySettings(true); } -QByteArray LoRaDemodGUI::serialize() const +QByteArray ChirpChatDemodGUI::serialize() const { return m_settings.serialize(); } -bool LoRaDemodGUI::deserialize(const QByteArray& data) +bool ChirpChatDemodGUI::deserialize(const QByteArray& data) { resetLoRaStatus(); @@ -95,13 +95,13 @@ bool LoRaDemodGUI::deserialize(const QByteArray& data) } } -bool LoRaDemodGUI::handleMessage(const Message& message) +bool ChirpChatDemodGUI::handleMessage(const Message& message) { if (DSPSignalNotification::match(message)) { DSPSignalNotification& notif = (DSPSignalNotification&) message; int basebandSampleRate = notif.getSampleRate(); - qDebug() << "LoRaDemodGUI::handleMessage: DSPSignalNotification: m_basebandSampleRate: " << basebandSampleRate; + qDebug() << "ChirpChatDemodGUI::handleMessage: DSPSignalNotification: m_basebandSampleRate: " << basebandSampleRate; if (basebandSampleRate != m_basebandSampleRate) { @@ -111,27 +111,27 @@ bool LoRaDemodGUI::handleMessage(const Message& message) return true; } - else if (LoRaDemod::MsgReportDecodeBytes::match(message)) + else if (ChirpChatDemod::MsgReportDecodeBytes::match(message)) { - if (m_settings.m_codingScheme == LoRaDemodSettings::CodingLoRa) { + if (m_settings.m_codingScheme == ChirpChatDemodSettings::CodingLoRa) { showLoRaMessage(message); } return true; } - else if (LoRaDemod::MsgReportDecodeString::match(message)) + else if (ChirpChatDemod::MsgReportDecodeString::match(message)) { - if ((m_settings.m_codingScheme == LoRaDemodSettings::CodingASCII) - || (m_settings.m_codingScheme == LoRaDemodSettings::CodingTTY)) { + if ((m_settings.m_codingScheme == ChirpChatDemodSettings::CodingASCII) + || (m_settings.m_codingScheme == ChirpChatDemodSettings::CodingTTY)) { showTextMessage(message); } return true; } - else if (LoRaDemod::MsgConfigureLoRaDemod::match(message)) + else if (ChirpChatDemod::MsgConfigureChirpChatDemod::match(message)) { - qDebug("LoRaDemod::handleMessage: NFMDemod::MsgConfigureLoRaDemod"); - const LoRaDemod::MsgConfigureLoRaDemod& cfg = (LoRaDemod::MsgConfigureLoRaDemod&) message; + qDebug("ChirpChatDemodGUI::handleMessage: NFMDemod::MsgConfigureChirpChatDemod"); + const ChirpChatDemod::MsgConfigureChirpChatDemod& cfg = (ChirpChatDemod::MsgConfigureChirpChatDemod&) message; m_settings = cfg.getSettings(); blockApplySettings(true); displaySettings(); @@ -145,7 +145,7 @@ bool LoRaDemodGUI::handleMessage(const Message& message) } } -void LoRaDemodGUI::handleInputMessages() +void ChirpChatDemodGUI::handleInputMessages() { Message* message; @@ -157,36 +157,36 @@ void LoRaDemodGUI::handleInputMessages() } } -void LoRaDemodGUI::channelMarkerChangedByCursor() +void ChirpChatDemodGUI::channelMarkerChangedByCursor() { ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency()); m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency(); applySettings(); } -void LoRaDemodGUI::on_deltaFrequency_changed(qint64 value) +void ChirpChatDemodGUI::on_deltaFrequency_changed(qint64 value) { m_channelMarker.setCenterFrequency(value); m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency(); applySettings(); } -void LoRaDemodGUI::channelMarkerHighlightedByCursor() +void ChirpChatDemodGUI::channelMarkerHighlightedByCursor() { setHighlighted(m_channelMarker.getHighlighted()); } -void LoRaDemodGUI::on_BW_valueChanged(int value) +void ChirpChatDemodGUI::on_BW_valueChanged(int value) { if (value < 0) { m_settings.m_bandwidthIndex = 0; - } else if (value < LoRaDemodSettings::nbBandwidths) { + } else if (value < ChirpChatDemodSettings::nbBandwidths) { m_settings.m_bandwidthIndex = value; } else { - m_settings.m_bandwidthIndex = LoRaDemodSettings::nbBandwidths - 1; + m_settings.m_bandwidthIndex = ChirpChatDemodSettings::nbBandwidths - 1; } - int thisBW = LoRaDemodSettings::bandwidths[value]; + int thisBW = ChirpChatDemodSettings::bandwidths[value]; ui->BWText->setText(QString("%1 Hz").arg(thisBW)); m_channelMarker.setBandwidth(thisBW); ui->glSpectrum->setSampleRate(thisBW); @@ -195,7 +195,7 @@ void LoRaDemodGUI::on_BW_valueChanged(int value) applySettings(); } -void LoRaDemodGUI::on_Spread_valueChanged(int value) +void ChirpChatDemodGUI::on_Spread_valueChanged(int value) { m_settings.m_spreadFactor = value; ui->SpreadText->setText(tr("%1").arg(value)); @@ -204,65 +204,65 @@ void LoRaDemodGUI::on_Spread_valueChanged(int value) applySettings(); } -void LoRaDemodGUI::on_deBits_valueChanged(int value) +void ChirpChatDemodGUI::on_deBits_valueChanged(int value) { m_settings.m_deBits = value; ui->deBitsText->setText(tr("%1").arg(m_settings.m_deBits)); applySettings(); } -void LoRaDemodGUI::on_preambleChirps_valueChanged(int value) +void ChirpChatDemodGUI::on_preambleChirps_valueChanged(int value) { m_settings.m_preambleChirps = value; ui->preambleChirpsText->setText(tr("%1").arg(m_settings.m_preambleChirps)); applySettings(); } -void LoRaDemodGUI::on_scheme_currentIndexChanged(int index) +void ChirpChatDemodGUI::on_scheme_currentIndexChanged(int index) { - m_settings.m_codingScheme = (LoRaDemodSettings::CodingScheme) index; + m_settings.m_codingScheme = (ChirpChatDemodSettings::CodingScheme) index; - if (m_settings.m_codingScheme != LoRaDemodSettings::CodingLoRa) { + if (m_settings.m_codingScheme != ChirpChatDemodSettings::CodingLoRa) { resetLoRaStatus(); } applySettings(); } -void LoRaDemodGUI::on_mute_toggled(bool checked) +void ChirpChatDemodGUI::on_mute_toggled(bool checked) { m_settings.m_decodeActive = !checked; applySettings(); } -void LoRaDemodGUI::on_clear_clicked(bool checked) +void ChirpChatDemodGUI::on_clear_clicked(bool checked) { (void) checked; ui->messageText->clear(); ui->hexText->clear(); } -void LoRaDemodGUI::on_eomSquelch_valueChanged(int value) +void ChirpChatDemodGUI::on_eomSquelch_valueChanged(int value) { m_settings.m_eomSquelchTenths = value; displaySquelch(); applySettings(); } -void LoRaDemodGUI::on_messageLength_valueChanged(int value) +void ChirpChatDemodGUI::on_messageLength_valueChanged(int value) { m_settings.m_nbSymbolsMax = value; ui->messageLengthText->setText(tr("%1").arg(m_settings.m_nbSymbolsMax)); applySettings(); } -void LoRaDemodGUI::on_messageLengthAuto_stateChanged(int state) +void ChirpChatDemodGUI::on_messageLengthAuto_stateChanged(int state) { m_settings.m_autoNbSymbolsMax = (state == Qt::Checked); applySettings(); } -void LoRaDemodGUI::on_header_stateChanged(int state) +void ChirpChatDemodGUI::on_header_stateChanged(int state) { m_settings.m_hasHeader = (state == Qt::Checked); @@ -283,39 +283,39 @@ void LoRaDemodGUI::on_header_stateChanged(int state) applySettings(); } -void LoRaDemodGUI::on_fecParity_valueChanged(int value) +void ChirpChatDemodGUI::on_fecParity_valueChanged(int value) { m_settings.m_nbParityBits = value; ui->fecParityText->setText(tr("%1").arg(m_settings.m_nbParityBits)); applySettings(); } -void LoRaDemodGUI::on_crc_stateChanged(int state) +void ChirpChatDemodGUI::on_crc_stateChanged(int state) { m_settings.m_hasCRC = (state == Qt::Checked); applySettings(); } -void LoRaDemodGUI::on_packetLength_valueChanged(int value) +void ChirpChatDemodGUI::on_packetLength_valueChanged(int value) { m_settings.m_packetLength = value; ui->packetLengthText->setText(tr("%1").arg(m_settings.m_packetLength)); applySettings(); } -void LoRaDemodGUI::on_udpSend_stateChanged(int state) +void ChirpChatDemodGUI::on_udpSend_stateChanged(int state) { m_settings.m_sendViaUDP = (state == Qt::Checked); applySettings(); } -void LoRaDemodGUI::on_udpAddress_editingFinished() +void ChirpChatDemodGUI::on_udpAddress_editingFinished() { m_settings.m_udpAddress = ui->udpAddress->text(); applySettings(); } -void LoRaDemodGUI::on_udpPort_editingFinished() +void ChirpChatDemodGUI::on_udpPort_editingFinished() { bool ok; quint16 udpPort = ui->udpPort->text().toInt(&ok); @@ -329,13 +329,13 @@ void LoRaDemodGUI::on_udpPort_editingFinished() applySettings(); } -void LoRaDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) +void ChirpChatDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) { (void) widget; (void) rollDown; } -void LoRaDemodGUI::onMenuDialogCalled(const QPoint &p) +void ChirpChatDemodGUI::onMenuDialogCalled(const QPoint &p) { if (m_contextMenuType == ContextMenuChannelSettings) { @@ -365,7 +365,7 @@ void LoRaDemodGUI::onMenuDialogCalled(const QPoint &p) else if ((m_contextMenuType == ContextMenuStreamSettings) && (m_deviceUISet->m_deviceMIMOEngine)) { DeviceStreamSelectionDialog dialog(this); - dialog.setNumberOfStreams(m_LoRaDemod->getNumberOfDeviceStreams()); + dialog.setNumberOfStreams(m_chirpChatDemod->getNumberOfDeviceStreams()); dialog.setStreamIndex(m_settings.m_streamIndex); dialog.move(p); dialog.exec(); @@ -380,9 +380,9 @@ void LoRaDemodGUI::onMenuDialogCalled(const QPoint &p) resetContextMenuType(); } -LoRaDemodGUI::LoRaDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent) : +ChirpChatDemodGUI::ChirpChatDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent) : RollupWidget(parent), - ui(new Ui::LoRaDemodGUI), + ui(new Ui::ChirpChatDemodGUI), m_pluginAPI(pluginAPI), m_deviceUISet(deviceUISet), m_channelMarker(this), @@ -396,9 +396,9 @@ LoRaDemodGUI::LoRaDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseb connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &))); m_spectrumVis = new SpectrumVis(SDR_RX_SCALEF, ui->glSpectrum); - m_LoRaDemod = (LoRaDemod*) rxChannel; //new LoRaDemod(m_deviceUISet->m_deviceSourceAPI); - m_LoRaDemod->setSpectrumSink(m_spectrumVis); - m_LoRaDemod->setMessageQueueToGUI(getInputMessageQueue()); + m_chirpChatDemod = (ChirpChatDemod*) rxChannel; + m_chirpChatDemod->setSpectrumSink(m_spectrumVis); + m_chirpChatDemod->setMessageQueueToGUI(getInputMessageQueue()); connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick())); @@ -419,7 +419,7 @@ LoRaDemodGUI::LoRaDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseb connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor())); connect(&m_channelMarker, SIGNAL(highlightedByCursor()), this, SLOT(channelMarkerHighlightedByCursor())); - m_deviceUISet->registerRxChannelInstance(LoRaDemod::m_channelIdURI, this); + m_deviceUISet->registerRxChannelInstance(ChirpChatDemod::m_channelIdURI, this); m_deviceUISet->addChannelMarker(&m_channelMarker); m_deviceUISet->addRollupWidget(this); @@ -436,32 +436,32 @@ LoRaDemodGUI::LoRaDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseb applySettings(true); } -LoRaDemodGUI::~LoRaDemodGUI() +ChirpChatDemodGUI::~ChirpChatDemodGUI() { m_deviceUISet->removeRxChannelInstance(this); - delete m_LoRaDemod; // TODO: check this: when the GUI closes it has to delete the demodulator + delete m_chirpChatDemod; // TODO: check this: when the GUI closes it has to delete the demodulator delete m_spectrumVis; delete ui; } -void LoRaDemodGUI::blockApplySettings(bool block) +void ChirpChatDemodGUI::blockApplySettings(bool block) { m_doApplySettings = !block; } -void LoRaDemodGUI::applySettings(bool force) +void ChirpChatDemodGUI::applySettings(bool force) { if (m_doApplySettings) { setTitleColor(m_channelMarker.getColor()); - LoRaDemod::MsgConfigureLoRaDemod* message = LoRaDemod::MsgConfigureLoRaDemod::create( m_settings, force); - m_LoRaDemod->getInputMessageQueue()->push(message); + ChirpChatDemod::MsgConfigureChirpChatDemod* message = ChirpChatDemod::MsgConfigureChirpChatDemod::create( m_settings, force); + m_chirpChatDemod->getInputMessageQueue()->push(message); } } -void LoRaDemodGUI::displaySettings() +void ChirpChatDemodGUI::displaySettings() { - int thisBW = LoRaDemodSettings::bandwidths[m_settings.m_bandwidthIndex]; + int thisBW = ChirpChatDemodSettings::bandwidths[m_settings.m_bandwidthIndex]; m_channelMarker.blockSignals(true); m_channelMarker.setTitle(m_settings.m_title); @@ -512,7 +512,7 @@ void LoRaDemodGUI::displaySettings() blockApplySettings(false); } -void LoRaDemodGUI::displayStreamIndex() +void ChirpChatDemodGUI::displayStreamIndex() { if (m_deviceUISet->m_deviceMIMOEngine) { setStreamIndicator(tr("%1").arg(m_settings.m_streamIndex)); @@ -521,7 +521,7 @@ void LoRaDemodGUI::displayStreamIndex() } } -void LoRaDemodGUI::displaySquelch() +void ChirpChatDemodGUI::displaySquelch() { ui->eomSquelch->setValue(m_settings.m_eomSquelchTenths); @@ -532,7 +532,7 @@ void LoRaDemodGUI::displaySquelch() } } -void LoRaDemodGUI::displayLoRaStatus(int headerParityStatus, bool headerCRCStatus, int payloadParityStatus, bool payloadCRCStatus) +void ChirpChatDemodGUI::displayLoRaStatus(int headerParityStatus, bool headerCRCStatus, int payloadParityStatus, bool payloadCRCStatus) { if (m_settings.m_hasHeader && (headerParityStatus == (int) ParityOK)) { ui->headerHammingStatus->setStyleSheet("QLabel { background-color : green; }"); @@ -569,7 +569,7 @@ void LoRaDemodGUI::displayLoRaStatus(int headerParityStatus, bool headerCRCStatu } } -void LoRaDemodGUI::resetLoRaStatus() +void ChirpChatDemodGUI::resetLoRaStatus() { ui->headerHammingStatus->setStyleSheet("QLabel { background:rgb(79,79,79); }"); ui->headerCRCStatus->setStyleSheet("QLabel { background:rgb(79,79,79); }"); @@ -579,26 +579,26 @@ void LoRaDemodGUI::resetLoRaStatus() ui->nbCodewordsText->setText("---"); } -void LoRaDemodGUI::setBandwidths() +void ChirpChatDemodGUI::setBandwidths() { - int maxBandwidth = m_basebandSampleRate/LoRaDemodSettings::oversampling; + int maxBandwidth = m_basebandSampleRate/ChirpChatDemodSettings::oversampling; int maxIndex = 0; - for (; (maxIndex < LoRaDemodSettings::nbBandwidths) && (LoRaDemodSettings::bandwidths[maxIndex] <= maxBandwidth); maxIndex++) + for (; (maxIndex < ChirpChatDemodSettings::nbBandwidths) && (ChirpChatDemodSettings::bandwidths[maxIndex] <= maxBandwidth); maxIndex++) {} if (maxIndex != 0) { - qDebug("LoRaDemodGUI::setBandwidths: avl: %d max: %d", maxBandwidth, LoRaDemodSettings::bandwidths[maxIndex-1]); + qDebug("ChirpChatDemodGUI::setBandwidths: avl: %d max: %d", maxBandwidth, ChirpChatDemodSettings::bandwidths[maxIndex-1]); ui->BW->setMaximum(maxIndex - 1); int index = ui->BW->value(); - ui->BWText->setText(QString("%1 Hz").arg(LoRaDemodSettings::bandwidths[index])); + ui->BWText->setText(QString("%1 Hz").arg(ChirpChatDemodSettings::bandwidths[index])); } } -void LoRaDemodGUI::showLoRaMessage(const Message& message) +void ChirpChatDemodGUI::showLoRaMessage(const Message& message) { - const LoRaDemod::MsgReportDecodeBytes& msg = (LoRaDemod::MsgReportDecodeBytes&) message; + const ChirpChatDemod::MsgReportDecodeBytes& msg = (ChirpChatDemod::MsgReportDecodeBytes&) message; QByteArray bytes = msg.getBytes(); QString syncWordStr((tr("%1").arg(msg.getSyncWord(), 2, 16, QChar('0')))); @@ -666,9 +666,9 @@ void LoRaDemodGUI::showLoRaMessage(const Message& message) ui->nbCodewordsText->setText(tr("%1").arg(msg.getNbCodewords())); } -void LoRaDemodGUI::showTextMessage(const Message& message) +void ChirpChatDemodGUI::showTextMessage(const Message& message) { - const LoRaDemod::MsgReportDecodeString& msg = (LoRaDemod::MsgReportDecodeString&) message; + const ChirpChatDemod::MsgReportDecodeString& msg = (ChirpChatDemod::MsgReportDecodeString&) message; QDateTime dt = QDateTime::currentDateTime(); QString dateStr = dt.toString("HH:mm:ss"); @@ -686,7 +686,7 @@ void LoRaDemodGUI::showTextMessage(const Message& message) displayStatus(status); } -void LoRaDemodGUI::displayText(const QString& header, const QString& text) +void ChirpChatDemodGUI::displayText(const QString& header, const QString& text) { QTextCursor cursor = ui->messageText->textCursor(); cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); @@ -697,7 +697,7 @@ void LoRaDemodGUI::displayText(const QString& header, const QString& text) ui->messageText->verticalScrollBar()->setValue(ui->messageText->verticalScrollBar()->maximum()); } -void LoRaDemodGUI::displayBytes(const QString& header, const QByteArray& bytes) +void ChirpChatDemodGUI::displayBytes(const QString& header, const QByteArray& bytes) { QTextCursor cursor = ui->hexText->textCursor(); cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); @@ -732,7 +732,7 @@ void LoRaDemodGUI::displayBytes(const QString& header, const QByteArray& bytes) ui->hexText->verticalScrollBar()->setValue(ui->hexText->verticalScrollBar()->maximum()); } -void LoRaDemodGUI::displayStatus(const QString& status) +void ChirpChatDemodGUI::displayStatus(const QString& status) { QTextCursor cursor = ui->hexText->textCursor(); cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); @@ -745,7 +745,7 @@ void LoRaDemodGUI::displayStatus(const QString& status) ui->hexText->verticalScrollBar()->setValue(ui->hexText->verticalScrollBar()->maximum()); } -QString LoRaDemodGUI::getParityStr(int parityStatus) +QString ChirpChatDemodGUI::getParityStr(int parityStatus) { if (parityStatus == (int) ParityError) { return "err"; @@ -758,7 +758,7 @@ QString LoRaDemodGUI::getParityStr(int parityStatus) } } -void LoRaDemodGUI::tick() +void ChirpChatDemodGUI::tick() { if (m_tickCount < 10) { @@ -768,10 +768,10 @@ void LoRaDemodGUI::tick() { m_tickCount = 0; - ui->nText->setText(tr("%1").arg(CalcDb::dbPower(m_LoRaDemod->getCurrentNoiseLevel()), 0, 'f', 1)); - ui->channelPower->setText(tr("%1 dB").arg(CalcDb::dbPower(m_LoRaDemod->getTotalPower()), 0, 'f', 1)); + ui->nText->setText(tr("%1").arg(CalcDb::dbPower(m_chirpChatDemod->getCurrentNoiseLevel()), 0, 'f', 1)); + ui->channelPower->setText(tr("%1 dB").arg(CalcDb::dbPower(m_chirpChatDemod->getTotalPower()), 0, 'f', 1)); - if (m_LoRaDemod->getDemodActive()) { + if (m_chirpChatDemod->getDemodActive()) { ui->mute->setStyleSheet("QToolButton { background-color : green; }"); } else { ui->mute->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); diff --git a/plugins/channelrx/demodlora/lorademodgui.h b/plugins/channelrx/demodchirpchat/chirpchatdemodgui.h similarity index 85% rename from plugins/channelrx/demodlora/lorademodgui.h rename to plugins/channelrx/demodchirpchat/chirpchatdemodgui.h index cd4ec3eaa..dac83c6ad 100644 --- a/plugins/channelrx/demodlora/lorademodgui.h +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodgui.h @@ -15,31 +15,31 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDE_LoRaDEMODGUI_H -#define INCLUDE_LoRaDEMODGUI_H +#ifndef INCLUDE_CHIRPCHATDEMODGUI_H +#define INCLUDE_CHIRPCHATDEMODGUI_H #include #include "gui/rollupwidget.h" #include "dsp/channelmarker.h" #include "util/messagequeue.h" -#include "lorademodsettings.h" +#include "chirpchatdemodsettings.h" class PluginAPI; class DeviceUISet; -class LoRaDemod; +class ChirpChatDemod; class SpectrumVis; class BasebandSampleSink; namespace Ui { - class LoRaDemodGUI; + class ChirpChatDemodGUI; } -class LoRaDemodGUI : public RollupWidget, public PluginInstanceGUI { +class ChirpChatDemodGUI : public RollupWidget, public PluginInstanceGUI { Q_OBJECT public: - static LoRaDemodGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceAPI, BasebandSampleSink *rxChannel); + static ChirpChatDemodGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceAPI, BasebandSampleSink *rxChannel); virtual void destroy(); void setName(const QString& name); @@ -80,7 +80,7 @@ private slots: void tick(); private: - enum ParityStatus // matches LoRa decoder status + enum ParityStatus // matches decoder status { ParityUndefined, ParityError, @@ -88,21 +88,21 @@ private: ParityOK }; - Ui::LoRaDemodGUI* ui; + Ui::ChirpChatDemodGUI* ui; PluginAPI* m_pluginAPI; DeviceUISet* m_deviceUISet; ChannelMarker m_channelMarker; - LoRaDemodSettings m_settings; + ChirpChatDemodSettings m_settings; int m_basebandSampleRate; bool m_doApplySettings; - LoRaDemod* m_LoRaDemod; + ChirpChatDemod* m_chirpChatDemod; SpectrumVis* m_spectrumVis; MessageQueue m_inputMessageQueue; unsigned int m_tickCount; - explicit LoRaDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0); - virtual ~LoRaDemodGUI(); + explicit ChirpChatDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0); + virtual ~ChirpChatDemodGUI(); void blockApplySettings(bool block); void applySettings(bool force = false); @@ -120,4 +120,4 @@ private: void resetLoRaStatus(); }; -#endif // INCLUDE_LoRaDEMODGUI_H +#endif // INCLUDE_CHIRPCHATDEMODGUI_H diff --git a/plugins/channelrx/demodlora/lorademodgui.ui b/plugins/channelrx/demodchirpchat/chirpchatdemodgui.ui similarity index 99% rename from plugins/channelrx/demodlora/lorademodgui.ui rename to plugins/channelrx/demodchirpchat/chirpchatdemodgui.ui index 5e82d66d2..6309d0ec1 100644 --- a/plugins/channelrx/demodlora/lorademodgui.ui +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodgui.ui @@ -1,7 +1,7 @@ - LoRaDemodGUI - + ChirpChatDemodGUI + 0 @@ -23,7 +23,7 @@ - LoRa Demodulator + ChirpChat Demodulator diff --git a/plugins/channelrx/demodlora/lorademodmsg.cpp b/plugins/channelrx/demodchirpchat/chirpchatdemodmsg.cpp similarity index 92% rename from plugins/channelrx/demodlora/lorademodmsg.cpp rename to plugins/channelrx/demodchirpchat/chirpchatdemodmsg.cpp index 458d89238..4e5603ca3 100644 --- a/plugins/channelrx/demodlora/lorademodmsg.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodmsg.cpp @@ -15,6 +15,6 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include "lorademodmsg.h" +#include "chirpchatdemodmsg.h" -MESSAGE_CLASS_DEFINITION(LoRaDemodMsg::MsgDecodeSymbols, Message) +MESSAGE_CLASS_DEFINITION(ChirpChatDemodMsg::MsgDecodeSymbols, Message) diff --git a/plugins/channelrx/demodlora/lorademodmsg.h b/plugins/channelrx/demodchirpchat/chirpchatdemodmsg.h similarity index 95% rename from plugins/channelrx/demodlora/lorademodmsg.h rename to plugins/channelrx/demodchirpchat/chirpchatdemodmsg.h index 7088225dd..5f8fba50a 100644 --- a/plugins/channelrx/demodlora/lorademodmsg.h +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodmsg.h @@ -15,13 +15,13 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDE_LORADEMODMSG_H -#define INCLUDE_LORADEMODMSG_H +#ifndef INCLUDE_CHIRPCHATDEMODMSG_H +#define INCLUDE_CHIRPCHATDEMODMSG_H #include #include "util/message.h" -namespace LoRaDemodMsg +namespace ChirpChatDemodMsg { class MsgDecodeSymbols : public Message { MESSAGE_CLASS_DECLARATION @@ -76,4 +76,4 @@ namespace LoRaDemodMsg }; } -#endif // INCLUDE_LORADEMODMSG_H +#endif // INCLUDE_CHIRPCHATDEMODMSG_H diff --git a/plugins/channelrx/demodlora/lorademodsettings.cpp b/plugins/channelrx/demodchirpchat/chirpchatdemodsettings.cpp similarity index 91% rename from plugins/channelrx/demodlora/lorademodsettings.cpp rename to plugins/channelrx/demodchirpchat/chirpchatdemodsettings.cpp index da1376185..61f0ba013 100644 --- a/plugins/channelrx/demodlora/lorademodsettings.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodsettings.cpp @@ -15,16 +15,15 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include "lorademodsettings.h" - #include #include "dsp/dspengine.h" #include "util/simpleserializer.h" #include "settings/serializable.h" -#include "lorademodsettings.h" -const int LoRaDemodSettings::bandwidths[] = { +#include "chirpchatdemodsettings.h" + +const int ChirpChatDemodSettings::bandwidths[] = { 2604, // 333k / 128 3125, // 400k / 128 3906, // 500k / 128 @@ -50,10 +49,10 @@ const int LoRaDemodSettings::bandwidths[] = { 400000, // 400k / 1 500000 // 500k / 1 }; -const int LoRaDemodSettings::nbBandwidths = 3*8; -const int LoRaDemodSettings::oversampling = 2; +const int ChirpChatDemodSettings::nbBandwidths = 3*8; +const int ChirpChatDemodSettings::oversampling = 2; -LoRaDemodSettings::LoRaDemodSettings() : +ChirpChatDemodSettings::ChirpChatDemodSettings() : m_inputFrequencyOffset(0), m_channelMarker(0), m_spectrumGUI(0) @@ -61,7 +60,7 @@ LoRaDemodSettings::LoRaDemodSettings() : resetToDefaults(); } -void LoRaDemodSettings::resetToDefaults() +void ChirpChatDemodSettings::resetToDefaults() { m_bandwidthIndex = 5; m_spreadFactor = 7; @@ -79,7 +78,7 @@ void LoRaDemodSettings::resetToDefaults() m_udpAddress = "127.0.0.1"; m_udpPort = 9999; m_rgbColor = QColor(255, 0, 255).rgb(); - m_title = "LoRa Demodulator"; + m_title = "ChirpChat Demodulator"; m_streamIndex = 0; m_useReverseAPI = false; m_reverseAPIAddress = "127.0.0.1"; @@ -88,7 +87,7 @@ void LoRaDemodSettings::resetToDefaults() m_reverseAPIChannelIndex = 0; } -QByteArray LoRaDemodSettings::serialize() const +QByteArray ChirpChatDemodSettings::serialize() const { SimpleSerializer s(1); s.writeS32(1, m_inputFrequencyOffset); @@ -127,7 +126,7 @@ QByteArray LoRaDemodSettings::serialize() const return s.final(); } -bool LoRaDemodSettings::deserialize(const QByteArray& data) +bool ChirpChatDemodSettings::deserialize(const QByteArray& data) { SimpleDeserializer d(data); @@ -157,7 +156,7 @@ bool LoRaDemodSettings::deserialize(const QByteArray& data) m_channelMarker->deserialize(bytetmp); } - d.readString(6, &m_title, "LoRa Demodulator"); + d.readString(6, &m_title, "ChirpChat Demodulator"); d.readS32(7, &m_deBits, 0); d.readS32(8, &tmp); m_codingScheme = (CodingScheme) tmp; diff --git a/plugins/channelrx/demodlora/lorademodsettings.h b/plugins/channelrx/demodchirpchat/chirpchatdemodsettings.h similarity index 92% rename from plugins/channelrx/demodlora/lorademodsettings.h rename to plugins/channelrx/demodchirpchat/chirpchatdemodsettings.h index 0c012bc9d..1b685cae4 100644 --- a/plugins/channelrx/demodlora/lorademodsettings.h +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodsettings.h @@ -16,8 +16,8 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#ifndef PLUGINS_CHANNELRX_DEMODLORA_LORADEMODSETTINGS_H_ -#define PLUGINS_CHANNELRX_DEMODLORA_LORADEMODSETTINGS_H_ +#ifndef PLUGINS_CHANNELRX_DEMODCHIRPCHAT_CHIRPCHATDEMODSETTINGS_H_ +#define PLUGINS_CHANNELRX_DEMODCHIRPCHAT_CHIRPCHATDEMODSETTINGS_H_ #include #include @@ -26,7 +26,7 @@ class Serializable; -struct LoRaDemodSettings +struct ChirpChatDemodSettings { enum CodingScheme { @@ -68,7 +68,7 @@ struct LoRaDemodSettings static const int nbBandwidths; static const int oversampling; - LoRaDemodSettings(); + ChirpChatDemodSettings(); void resetToDefaults(); void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; } void setSpectrumGUI(Serializable *spectrumGUI) { m_spectrumGUI = spectrumGUI; } @@ -78,4 +78,4 @@ struct LoRaDemodSettings -#endif /* PLUGINS_CHANNELRX_DEMODLORA_LORADEMODSETTINGS_H_ */ +#endif /* PLUGINS_CHANNELRX_DEMODCHIRPCHAT_CHIRPCHATDEMODSETTINGS_H_ */ diff --git a/plugins/channelrx/demodlora/lorademodsink.cpp b/plugins/channelrx/demodchirpchat/chirpchatdemodsink.cpp similarity index 83% rename from plugins/channelrx/demodlora/lorademodsink.cpp rename to plugins/channelrx/demodchirpchat/chirpchatdemodsink.cpp index d5c95dae5..8c99c70a1 100644 --- a/plugins/channelrx/demodlora/lorademodsink.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodsink.cpp @@ -24,10 +24,10 @@ #include "dsp/fftengine.h" #include "util/db.h" -#include "lorademodmsg.h" -#include "lorademodsink.h" +#include "chirpchatdemodmsg.h" +#include "chirpchatdemodsink.h" -LoRaDemodSink::LoRaDemodSink() : +ChirpChatDemodSink::ChirpChatDemodSink() : m_decodeMsg(nullptr), m_decoderMsgQueue(nullptr), m_spectrumSink(nullptr), @@ -37,7 +37,7 @@ LoRaDemodSink::LoRaDemodSink() : m_spectrumLine(nullptr) { m_demodActive = false; - m_bandwidth = LoRaDemodSettings::bandwidths[0]; + m_bandwidth = ChirpChatDemodSettings::bandwidths[0]; m_channelSampleRate = 96000; m_channelFrequencyOffset = 0; m_nco.setFreq(m_channelFrequencyOffset, m_channelSampleRate); @@ -45,7 +45,7 @@ LoRaDemodSink::LoRaDemodSink() : m_interpolatorDistance = (Real) m_channelSampleRate / (Real) m_bandwidth; m_sampleDistanceRemain = 0; - m_state = LoRaStateReset; + m_state = ChirpChatStateReset; m_chirp = 0; m_chirp0 = 0; @@ -55,7 +55,7 @@ LoRaDemodSink::LoRaDemodSink() : initSF(m_settings.m_spreadFactor, m_settings.m_deBits); } -LoRaDemodSink::~LoRaDemodSink() +ChirpChatDemodSink::~ChirpChatDemodSink() { delete m_fft; delete m_fftSFD; @@ -65,7 +65,7 @@ LoRaDemodSink::~LoRaDemodSink() delete[] m_spectrumLine; } -void LoRaDemodSink::initSF(unsigned int sf, unsigned int deBits) +void ChirpChatDemodSink::initSF(unsigned int sf, unsigned int deBits) { if (m_downChirps) { delete[] m_downChirps; @@ -85,7 +85,7 @@ void LoRaDemodSink::initSF(unsigned int sf, unsigned int deBits) m_fftLength = m_nbSymbols; m_fft->configure(m_fftInterpolation*m_fftLength, false); m_fftSFD->configure(m_fftInterpolation*m_fftLength, false); - m_state = LoRaStateReset; + m_state = ChirpChatStateReset; m_sfdSkip = m_fftLength / 4; m_fftWindow.create(FFTWindow::Function::Kaiser, m_fftLength); m_fftWindow.setKaiserAlpha(M_PI); @@ -112,7 +112,7 @@ void LoRaDemodSink::initSF(unsigned int sf, unsigned int deBits) std::copy(m_upChirps, m_upChirps+m_fftLength, m_upChirps+m_fftLength); } -void LoRaDemodSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end) +void ChirpChatDemodSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end) { int newangle; Complex ci; @@ -130,16 +130,16 @@ void LoRaDemodSink::feed(const SampleVector::const_iterator& begin, const Sample } } -void LoRaDemodSink::processSample(const Complex& ci) +void ChirpChatDemodSink::processSample(const Complex& ci) { - if (m_state == LoRaStateReset) // start over + if (m_state == ChirpChatStateReset) // start over { m_demodActive = false; reset(); std::queue().swap(m_magsqQueue); // this clears the queue - m_state = LoRaStateDetectPreamble; + m_state = ChirpChatStateDetectPreamble; } - else if (m_state == LoRaStateDetectPreamble) // look for preamble + else if (m_state == ChirpChatStateDetectPreamble) // look for preamble { m_fft->in()[m_fftCounter++] = ci * m_downChirps[m_chirp]; // de-chirp the up ramp @@ -189,12 +189,12 @@ void LoRaDemodSink::processSample(const Complex& ci) m_spectrumSink->feed(m_spectrumBuffer, m_nbSymbols); } - qDebug("LoRaDemodSink::processSample: preamble found: %u|%f", m_argMaxHistory[0], magsq); + qDebug("ChirpChatDemodSink::processSample: preamble found: %u|%f", m_argMaxHistory[0], magsq); m_chirp = m_argMaxHistory[0]; m_fftCounter = m_chirp; m_chirp0 = 0; m_chirpCount = 0; - m_state = LoRaStatePreambleResyc; + m_state = ChirpChatStatePreambleResyc; } else { @@ -203,7 +203,7 @@ void LoRaDemodSink::processSample(const Complex& ci) } } } - else if (m_state == LoRaStatePreambleResyc) + else if (m_state == ChirpChatStatePreambleResyc) { m_fftCounter++; @@ -215,10 +215,10 @@ void LoRaDemodSink::processSample(const Complex& ci) m_fftCounter = 0; m_demodActive = true; - m_state = LoRaStatePreamble; + m_state = ChirpChatStatePreamble; } } - else if (m_state == LoRaStatePreamble) // preamble found look for SFD start + else if (m_state == ChirpChatStatePreamble) // preamble found look for SFD start { m_fft->in()[m_fftCounter] = ci * m_downChirps[m_chirp]; // de-chirp the up ramp m_fftSFD->in()[m_fftCounter] = ci * m_upChirps[m_chirp]; // de-chiro the down ramp @@ -267,14 +267,14 @@ void LoRaDemodSink::processSample(const Complex& ci) if (m_chirpCount < 3) // too early { - m_state = LoRaStateReset; - qDebug("LoRaDemodSink::processSample: SFD search: signal drop is too early"); + m_state = ChirpChatStateReset; + qDebug("ChirpChatDemodSink::processSample: SFD search: signal drop is too early"); } else { m_syncWord = round(m_preambleHistory[m_chirpCount-2] / 8.0); m_syncWord += 16 * round(m_preambleHistory[m_chirpCount-3] / 8.0); - qDebug("LoRaDemodSink::processSample: SFD found: up: %4u|%11.6f - down: %4u|%11.6f sync: %x", imax, magsq, imaxSFD, magsqSFD, m_syncWord); + qDebug("ChirpChatDemodSink::processSample: SFD found: up: %4u|%11.6f - down: %4u|%11.6f sync: %x", imax, magsq, imaxSFD, magsqSFD, m_syncWord); int sadj = 0; int nadj = 0; @@ -289,19 +289,19 @@ void LoRaDemodSink::processSample(const Complex& ci) zadj = nadj == 0 ? 0 : sadj / nadj; zadj = zadj < -(sfdSkip/2) ? -(sfdSkip/2) : zadj > sfdSkip/2 ? sfdSkip/2 : zadj; - qDebug("LoRaDemodSink::processSample: zero adjust: %d (%d)", zadj, nadj); + qDebug("ChirpChatDemodSink::processSample: zero adjust: %d (%d)", zadj, nadj); m_sfdSkipCounter = 0; m_fftCounter = m_fftLength - m_sfdSkip + zadj; m_chirp += zadj; - m_state = LoRaStateSkipSFD; //LoRaStateSlideSFD; + m_state = ChirpChatStateSkipSFD; //ChirpChatStateSlideSFD; } } else if (m_chirpCount > (m_settings.m_preambleChirps - m_requiredPreambleChirps + 2)) // SFD missed start over { - qDebug("LoRaDemodSink::processSample: SFD search: number of possible chirps exceeded"); + qDebug("ChirpChatDemodSink::processSample: SFD search: number of possible chirps exceeded"); m_magsqTotalAvg(magsqTotal); - m_state = LoRaStateReset; + m_state = ChirpChatStateReset; } else { @@ -309,13 +309,13 @@ void LoRaDemodSink::processSample(const Complex& ci) m_spectrumSink->feed(m_spectrumBuffer, m_nbSymbols); } - qDebug("LoRaDemodSink::processSample: SFD search: up: %4u|%11.6f - down: %4u|%11.6f", imax, magsq, imaxSFD, magsqSFD); + qDebug("ChirpChatDemodSink::processSample: SFD search: up: %4u|%11.6f - down: %4u|%11.6f", imax, magsq, imaxSFD, magsqSFD); m_magsqTotalAvg(magsqTotal); m_magsqOnAvg(magsq); } } } - else if (m_state == LoRaStateSkipSFD) // Just skip SFD + else if (m_state == ChirpChatStateSkipSFD) // Just skip SFD { m_fftCounter++; @@ -326,19 +326,19 @@ void LoRaDemodSink::processSample(const Complex& ci) if (m_sfdSkipCounter == m_sfdFourths) // 1.25 SFD chips left { - qDebug("LoRaDemodSink::processSample: SFD skipped"); + qDebug("ChirpChatDemodSink::processSample: SFD skipped"); m_chirp = m_chirp0; m_fftCounter = 0; m_chirpCount = 0; int correction = 0; m_magsqMax = 0.0; - m_decodeMsg = LoRaDemodMsg::MsgDecodeSymbols::create(); + m_decodeMsg = ChirpChatDemodMsg::MsgDecodeSymbols::create(); m_decodeMsg->setSyncWord(m_syncWord); - m_state = LoRaStateReadPayload; + m_state = ChirpChatStateReadPayload; } } } - else if (m_state == LoRaStateReadPayload) + else if (m_state == ChirpChatStateReadPayload) { m_fft->in()[m_fftCounter] = ci * m_downChirps[m_chirp]; // de-chirp the up ramp m_fftCounter++; @@ -379,14 +379,14 @@ void LoRaDemodSink::processSample(const Complex& ci) || (m_settings.m_eomSquelchTenths == 121) // max - disable squelch || ((m_settings.m_eomSquelchTenths*magsq)/10.0 > m_magsqMax)) { - qDebug("LoRaDemodSink::processSample: symbol %02u: %4u|%11.6f", m_chirpCount, symbol, magsq); + qDebug("ChirpChatDemodSink::processSample: symbol %02u: %4u|%11.6f", m_chirpCount, symbol, magsq); m_magsqOnAvg(magsq); m_chirpCount++; if (m_chirpCount > m_settings.m_nbSymbolsMax) { - qDebug("LoRaDemodSink::processSample: message length exceeded"); - m_state = LoRaStateReset; + qDebug("ChirpChatDemodSink::processSample: message length exceeded"); + m_state = ChirpChatStateReset; m_decodeMsg->setSignalDb(CalcDb::dbPower(m_magsqOnAvg.asDouble() / (1<setNoiseDb(CalcDb::dbPower(m_magsqOffAvg.asDouble() / (1<popSymbol(); // last symbol is garbage m_decodeMsg->setSignalDb(CalcDb::dbPower(m_magsqOnAvg.asDouble() / (1<setNoiseDb(CalcDb::dbPower(m_magsqOffAvg.asDouble() / (1< intSize/2) { return u - intSize; @@ -552,7 +552,7 @@ int LoRaDemodSink::toSigned(int u, int intSize) } } -unsigned int LoRaDemodSink::evalSymbol(unsigned int rawSymbol) +unsigned int ChirpChatDemodSink::evalSymbol(unsigned int rawSymbol) { unsigned int spread = m_fftInterpolation * (1<. // /////////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDE_LORADEMODSINK_H -#define INCLUDE_LORADEMODSINK_H +#ifndef INCLUDE_CHIRPCHATDEMODSINK_H +#define INCLUDE_CHIRPCHATDEMODSINK_H #include #include @@ -28,19 +28,19 @@ #include "util/message.h" #include "util/movingaverage.h" -#include "lorademodsettings.h" +#include "chirpchatdemodsettings.h" class BasebandSampleSink; class FFTEngine; -namespace LoRaDemodMsg { +namespace ChirpChatDemodMsg { class MsgDecodeSymbols; } class MessageQueue; -class LoRaDemodSink : public ChannelSampleSink { +class ChirpChatDemodSink : public ChannelSampleSink { public: - LoRaDemodSink(); - ~LoRaDemodSink(); + ChirpChatDemodSink(); + ~ChirpChatDemodSink(); virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end); @@ -48,26 +48,26 @@ public: void setDecoderMessageQueue(MessageQueue *messageQueue) { m_decoderMsgQueue = messageQueue; } void setSpectrumSink(BasebandSampleSink* spectrumSink) { m_spectrumSink = spectrumSink; } void applyChannelSettings(int channelSampleRate, int bandwidth, int channelFrequencyOffset, bool force = false); - void applySettings(const LoRaDemodSettings& settings, bool force = false); + void applySettings(const ChirpChatDemodSettings& settings, bool force = false); double getCurrentNoiseLevel() const { return m_magsqOffAvg.instantAverage() / (1<init(); - LoRaDemod::webapiFormatChannelSettings(response, m_settings); + response.setChirpChatDemodSettings(new SWGSDRangel::SWGChirpChatDemodSettings()); + response.getChirpChatDemodSettings()->init(); + ChirpChatDemod::webapiFormatChannelSettings(response, m_settings); return 200; } -int LoRaDemodWebAPIAdapter::webapiSettingsPutPatch( +int ChirpChatDemodWebAPIAdapter::webapiSettingsPutPatch( bool force, const QStringList& channelSettingsKeys, SWGSDRangel::SWGChannelSettings& response, QString& errorMessage) { (void) errorMessage; - LoRaDemod::webapiUpdateChannelSettings(m_settings, channelSettingsKeys, response); - LoRaDemod::webapiFormatChannelSettings(response, m_settings); + ChirpChatDemod::webapiUpdateChannelSettings(m_settings, channelSettingsKeys, response); + ChirpChatDemod::webapiFormatChannelSettings(response, m_settings); return 200; } diff --git a/plugins/channelrx/demodlora/lorademodwebapiadapter.h b/plugins/channelrx/demodchirpchat/chirpchatdemodwebapiadapter.h similarity index 84% rename from plugins/channelrx/demodlora/lorademodwebapiadapter.h rename to plugins/channelrx/demodchirpchat/chirpchatdemodwebapiadapter.h index ac36d123f..aa29a24d7 100644 --- a/plugins/channelrx/demodlora/lorademodwebapiadapter.h +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodwebapiadapter.h @@ -15,19 +15,19 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDE_LORADEMOD_WEBAPIADAPTER_H -#define INCLUDE_LORADEMOD_WEBAPIADAPTER_H +#ifndef INCLUDE_CHIRPCHATDEMOD_WEBAPIADAPTER_H +#define INCLUDE_CHIRPCHATDEMOD_WEBAPIADAPTER_H #include "channel/channelwebapiadapter.h" -#include "lorademodsettings.h" +#include "chirpchatdemodsettings.h" /** * Standalone API adapter only for the settings */ -class LoRaDemodWebAPIAdapter : public ChannelWebAPIAdapter { +class ChirpChatDemodWebAPIAdapter : public ChannelWebAPIAdapter { public: - LoRaDemodWebAPIAdapter(); - virtual ~LoRaDemodWebAPIAdapter(); + ChirpChatDemodWebAPIAdapter(); + virtual ~ChirpChatDemodWebAPIAdapter(); virtual QByteArray serialize() const { return m_settings.serialize(); } virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); } @@ -43,7 +43,7 @@ public: QString& errorMessage); private: - LoRaDemodSettings m_settings; + ChirpChatDemodSettings m_settings; }; -#endif // INCLUDE_LORAMOD_WEBAPIADAPTER_H +#endif // INCLUDE_CHIRPCHATDEMOD_WEBAPIADAPTER_H diff --git a/plugins/channelrx/demodlora/loraplugin.cpp b/plugins/channelrx/demodchirpchat/chirpchatplugin.cpp similarity index 64% rename from plugins/channelrx/demodlora/loraplugin.cpp rename to plugins/channelrx/demodchirpchat/chirpchatplugin.cpp index 0ed5c1cf0..54f079fc4 100644 --- a/plugins/channelrx/demodlora/loraplugin.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatplugin.cpp @@ -18,62 +18,62 @@ #include #include "plugin/pluginapi.h" -#include "loraplugin.h" +#include "chirpchatplugin.h" #ifndef SERVER_MODE -#include "lorademodgui.h" +#include "chirpchatdemodgui.h" #endif -#include "lorademod.h" +#include "chirpchatdemod.h" -const PluginDescriptor LoRaPlugin::m_pluginDescriptor = { - LoRaDemod::m_channelId, - QString("LoRa Demodulator"), - QString("5.2.0"), +const PluginDescriptor ChirpChatPlugin::m_pluginDescriptor = { + ChirpChatDemod::m_channelId, + QString("ChirpChat Demodulator"), + QString("5.3.0"), QString("(c) Edouard Griffiths, F4EXB"), QString("https://github.com/f4exb/sdrangel"), true, QString("https://github.com/f4exb/sdrangel") }; -LoRaPlugin::LoRaPlugin(QObject* parent) : +ChirpChatPlugin::ChirpChatPlugin(QObject* parent) : QObject(parent), m_pluginAPI(nullptr) { } -const PluginDescriptor& LoRaPlugin::getPluginDescriptor() const +const PluginDescriptor& ChirpChatPlugin::getPluginDescriptor() const { return m_pluginDescriptor; } -void LoRaPlugin::initPlugin(PluginAPI* pluginAPI) +void ChirpChatPlugin::initPlugin(PluginAPI* pluginAPI) { m_pluginAPI = pluginAPI; // register demodulator - m_pluginAPI->registerRxChannel(LoRaDemod::m_channelIdURI, LoRaDemod::m_channelId, this); + m_pluginAPI->registerRxChannel(ChirpChatDemod::m_channelIdURI, ChirpChatDemod::m_channelId, this); } #ifdef SERVER_MODE -PluginInstanceGUI* LoRaPlugin::createRxChannelGUI( +PluginInstanceGUI* ChirpChatPlugin::createRxChannelGUI( DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) const { return 0; } #else -PluginInstanceGUI* LoRaPlugin::createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) const +PluginInstanceGUI* ChirpChatPlugin::createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel) const { - return LoRaDemodGUI::create(m_pluginAPI, deviceUISet, rxChannel); + return ChirpChatDemodGUI::create(m_pluginAPI, deviceUISet, rxChannel); } #endif -BasebandSampleSink* LoRaPlugin::createRxChannelBS(DeviceAPI *deviceAPI) const +BasebandSampleSink* ChirpChatPlugin::createRxChannelBS(DeviceAPI *deviceAPI) const { - return new LoRaDemod(deviceAPI); + return new ChirpChatDemod(deviceAPI); } -ChannelAPI* LoRaPlugin::createRxChannelCS(DeviceAPI *deviceAPI) const +ChannelAPI* ChirpChatPlugin::createRxChannelCS(DeviceAPI *deviceAPI) const { - return new LoRaDemod(deviceAPI); + return new ChirpChatDemod(deviceAPI); } diff --git a/plugins/channelrx/demodlora/loraplugin.h b/plugins/channelrx/demodchirpchat/chirpchatplugin.h similarity index 89% rename from plugins/channelrx/demodlora/loraplugin.h rename to plugins/channelrx/demodchirpchat/chirpchatplugin.h index 0111339d5..b720af1f3 100644 --- a/plugins/channelrx/demodlora/loraplugin.h +++ b/plugins/channelrx/demodchirpchat/chirpchatplugin.h @@ -15,8 +15,8 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#ifndef INCLUDE_LoRaPLUGIN_H -#define INCLUDE_LoRaPLUGIN_H +#ifndef INCLUDE_CHIRPCHATPLUGIN_H +#define INCLUDE_CHIRPCHATPLUGIN_H #include #include "plugin/plugininterface.h" @@ -24,13 +24,13 @@ class DeviceUISet; class BasebandSampleSink; -class LoRaPlugin : public QObject, PluginInterface { +class ChirpChatPlugin : public QObject, PluginInterface { Q_OBJECT Q_INTERFACES(PluginInterface) - Q_PLUGIN_METADATA(IID "sdrangel.channel.lorademod") + Q_PLUGIN_METADATA(IID "sdrangel.channel.chirpchatdemod") public: - explicit LoRaPlugin(QObject* parent = nullptr); + explicit ChirpChatPlugin(QObject* parent = nullptr); const PluginDescriptor& getPluginDescriptor() const; void initPlugin(PluginAPI* pluginAPI); diff --git a/plugins/channelrx/demodlora/readme.md b/plugins/channelrx/demodchirpchat/readme.md similarity index 73% rename from plugins/channelrx/demodlora/readme.md rename to plugins/channelrx/demodchirpchat/readme.md index a7b3ebdaa..4747f9cb7 100644 --- a/plugins/channelrx/demodlora/readme.md +++ b/plugins/channelrx/demodchirpchat/readme.md @@ -1,21 +1,25 @@ -

LoRa demodulator plugin

+

ChirpChat demodulator plugin

Introduction

-This plugin can be used to demodulate and decode LoRa transmissions. +This plugin can be used to demodulate and decode transmissions based on Chirp Spread Spectrum (CSS). The basic idea is to transform each symbol of a MFSK modulation to an ascending frequency ramp shifted in time. It could equally be a descending ramp but this one is reserved to detect a break in the preamble sequence (synchronization). This plugin has been designed to work in conjunction with the ChirpChat modulator plugin that should be used ideally on the transmission side. + +It has clearly been inspired by the LoRa technique but is designed for experimentation and extension to other protocols mostly inspired by amateur radio techniques using chirp modulation to transmit symbols. Thanks to the MFSK to chirp translation it is possible to adapt any MFSK based mode. + +LoRa is a property of Semtech and the details of the protocol are not made public. However a LoRa compatible protocol has been implemented based on the reverse engineering performed by the community. It is mainly based on the work done in https://github.com/myriadrf/LoRa-SDR. You can find more information about LoRa and chirp modulation here: - To get an idea of what is LoRa: [here](https://www.link-labs.com/blog/what-is-lora) - A detailed inspection of LoRa modulation and protocol: [here](https://static1.squarespace.com/static/54cecce7e4b054df1848b5f9/t/57489e6e07eaa0105215dc6c/1464376943218/Reversing-Lora-Knight.pdf) -This plugin has been designed to work in conjunction with the LoRa modulator plugin. However it can receive transmissions from the RN2483 module when the Distance Enhancement is engaged (4 FFT bins per symbol) which happens with spread factors 11 and 12. Il is very difficult in general to get good decodes when only one FFT bin is used by symbol. It has not been tested with Semtech SX127x hardware. +Transmissions from the RN2483 module with the Distance Enhancement feature (spread factors 11 and 12) could be successfully received. It has not been tested with Semtech SX127x hardware. This LoRa decoder is designed for experimentation. For production grade applications it is recommended to use dedicated hardware instead. -This plugin is designed to experiment with chirp modulation and LoRa technique. It does not replace dedicated hardware for production grade links. +Modulation characteristics from LoRa have been augmented with more bandwidths and FFT bin collations (DE factor). Plain TTY and ASCII have also been added and there are plans to add some more complex typically amateur radio MFSK based modes like JT65. Note: this plugin is available in version 5 only (since 5.2.0).

Interface

-![LoRa Demodulator plugin GUI](../../../doc/img/LoRaDemod_plugin.png) +![ChirpChat Demodulator plugin GUI](../../../doc/img/ChirpChatDemod_plugin.png)

1: Frequency shift from center frequency of reception

@@ -23,11 +27,11 @@ Use the wheels to adjust the frequency shift in Hz from the center frequency of

2: De-chirped channel power

-This is the total power in the FFT of the de-chirped signal in dB. When no LoRa signal is detected this corresponds to the power received in the bandwidth (3). It will show a significant increase in presence of a LoRa signal that can be detected. +This is the total power in the FFT of the de-chirped signal in dB. When no ChirpChat signal is detected this corresponds to the power received in the bandwidth (3). It will show a significant increase in presence of a ChirpChat signal that can be detected.

3: Bandwidth

-This is the bandwidth of the LoRa signal. AS per LoRa specs the signal sweeps between the lower and the upper frequency of this bandwidth. The sample rate of the LoRa signal in seconds is exactly one over this bandwidth in Hertz. +This is the bandwidth of the ChirpChat signal. Similarly to LoRa the signal sweeps between the lower and the upper frequency of this bandwidth. The sample rate of the ChirpChat signal in seconds is exactly one over this bandwidth in Hertz. In the LoRa standard there are 2 base bandwidths: 500 and 333.333 kHz. A 400 kHz base has been added. Possible bandwidths are obtained by a division of these base bandwidths by a power of two from 1 to 64. An extra divisor of 128 is provided to achieve smaller bandwidths that can fit in a SSB channel. @@ -58,7 +62,7 @@ Thus available bandwidths are: - **3125** (400000 / 128) Hz not in LoRa standard - **2604** (333333 / 128) Hz not in LoRa standard -The LoRa signal is oversampled by two therefore it needs a baseband of at least twice the bandwidth. This drives the maximum value on the slider automatically. +The ChirpChat signal is oversampled by two therefore it needs a baseband of at least twice the bandwidth. This drives the maximum value on the slider automatically.

4: De-chirped noise maximum power

@@ -76,19 +80,19 @@ Decode errors are very likely to happen when this value falls below 4 dB.

7: Spread Factor

-This is the Spread Factor parameter of the LoRa signal. This is the log2 of the FFT size used over the bandwidth (3). The number of symbols is 2SF-DE where SF is the spread factor and DE the Distance Enhancement factor (8) +This is the Spread Factor parameter of the ChirpChat signal. This is the log2 of the FFT size used over the bandwidth (3). The number of symbols is 2SF-DE where SF is the spread factor and DE the Distance Enhancement factor (8)

8: Distance Enhancement factor

-The LoRa standard specifies 0 (no DE) or 2 (DE active). The present range is extended to all values between 0 and 4 bits. +The LoRa standard specifies 0 (no DE) or 2 (DE active). The ChirpChat DE range is extended to all values between 0 and 4 bits. This is the log2 of the number of FFT bins used for one symbol. Extending the numbe of FFT bins per symbol decreases the probabilty to detect the wrong symbol as an adjacent bin. It can also overcome frequency drift on long messages. -In practice it is difficult to make correct decodes if only one FFT bin is used to code one symbol (DE=0). +In practice it is difficult to make correct decodes if only one FFT bin is used to code one symbol (DE=0) therefore it is recommended to use a DE factor of 2 or more. With medium SNR DE=1 can still achieve good results.

A: Payload controls and indicators

-![LoRa Demodulator payload controls](../../../doc/img/LoRaDemod_payload.png) +![ChirpChat Demodulator payload controls](../../../doc/img/ChirpChatDemod_payload.png)

A.1: Coding scheme

@@ -185,7 +189,7 @@ This is where the messages formatted as strings are displayed. Use the sweep ico The format of a message line is the following: -![LoRa Demodulator message string window](../../../doc/img/LoRaDemod_message_string.png) +![ChirpChat Demodulator message string window](../../../doc/img/ChirpChatDemod_message_string.png) - 1: Timestamp in HH:MM:SS format - 2: Sync word @@ -195,7 +199,7 @@ The format of a message line is the following: This is to display the message payload as hex formatted bytes with mesasge status. -![LoRa Demodulator message bytes window](../../../doc/img/LoRaDemod_message_binary.png) +![ChirpChat Demodulator message bytes window](../../../doc/img/ChirpChatDemod_message_binary.png)

11.1: Timestamp in HH:NN:SS format

@@ -265,13 +269,13 @@ This is the UDP address and port to where the decoded message is sent when (12)

B: De-chirped spectrum

-This is the spectrum of the de-chirped signal when a LoRa signal can be decoded. +This is the spectrum of the de-chirped signal when a ChirpChat signal can be decoded. -The frequency span corresponds to the bandwidth of the LoRa signal (3). Default FFT size is 2SF where SF is the spread factor (7). +The frequency span corresponds to the bandwidth of the ChirpChat signal (3). Default FFT size is 2SF where SF is the spread factor (7). -Sequences of successful LoRa signal demodulation are separated by blank lines (genreated with a string of high value bins). +Sequences of successful ChirpChat signal demodulation are separated by blank lines (genreated with a string of high value bins). Controls are the usual controls of spectrum displays with the following restrictions: - - The window type is non operating because the FFT analysis of the LoRa signal is always done with a Kaiser window + - The window type is non operating because the FFT analysis of the ChirpChat signal is always done with a Kaiser window - The FFT size can be changed however it is set to 2SF where SF is the spread factor and thus displays correctly diff --git a/plugins/channelrx/demodlora/CMakeLists.txt b/plugins/channelrx/demodlora/CMakeLists.txt deleted file mode 100644 index 4e84ae514..000000000 --- a/plugins/channelrx/demodlora/CMakeLists.txt +++ /dev/null @@ -1,66 +0,0 @@ -project(lora) - -set(lora_SOURCES - lorademod.cpp - lorademodsettings.cpp - lorademodsink.cpp - lorademodbaseband.cpp - loraplugin.cpp - lorademoddecoder.cpp - lorademoddecodertty.cpp - lorademoddecoderascii.cpp - lorademoddecoderlora.cpp - lorademodmsg.cpp -) - -set(lora_HEADERS - lorademod.h - lorademodsettings.h - lorademodsink.h - lorademodbaseband.h - lorademoddecoder.h - lorademoddecodertty.h - lorademoddecoderascii.h - lorademoddecoderlora.h - lorademodmsg.h - loraplugin.h -) - -include_directories( - ${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client -) - -if(NOT SERVER_MODE) - set(lora_SOURCES - ${lora_SOURCES} - lorademodgui.cpp - lorademodgui.ui - ) - set(lora_HEADERS - ${lora_HEADERS} - lorademodgui.h - ) - set(TARGET_NAME demodlora) - set(TARGET_LIB "Qt5::Widgets") - set(TARGET_LIB_GUI "sdrgui") - set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) -else() - set(TARGET_NAME demodlorasrv) - set(TARGET_LIB "") - set(TARGET_LIB_GUI "") - set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR}) -endif() - -add_library(${TARGET_NAME} SHARED - ${lora_SOURCES} -) - -target_link_libraries(${TARGET_NAME} - Qt5::Core - ${TARGET_LIB} - sdrbase - ${TARGET_LIB_GUI} - swagger -) - -install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER}) diff --git a/sdrbase/resources/webapi.qrc b/sdrbase/resources/webapi.qrc index 861389134..44f85c0c3 100644 --- a/sdrbase/resources/webapi.qrc +++ b/sdrbase/resources/webapi.qrc @@ -15,6 +15,7 @@ webapi/doc/swagger/include/BladeRF2.yaml webapi/doc/swagger/include/ChannelAnalyzer.yaml webapi/doc/swagger/include/ChannelSettings.yaml + webapi/doc/swagger/include/ChirpChatDemod.yaml webapi/doc/swagger/include/Command.yaml webapi/doc/swagger/include/CWKeyer.yaml webapi/doc/swagger/include/DATVDemod.yaml @@ -36,7 +37,6 @@ webapi/doc/swagger/include/KiwiSDR.yaml webapi/doc/swagger/include/LocalInput.yaml webapi/doc/swagger/include/LocalOutput.yaml - webapi/doc/swagger/include/LoRaDemod.yaml webapi/doc/swagger/include/LoRaMod.yaml webapi/doc/swagger/include/NFMDemod.yaml webapi/doc/swagger/include/NFMMod.yaml diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 47d5086ff..512727d6f 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -2169,6 +2169,9 @@ margin-bottom: 20px; "BFMDemodReport" : { "$ref" : "#/definitions/BFMDemodReport" }, + "ChirpChatDemodReport" : { + "$ref" : "#/definitions/ChirpChatDemodReport" + }, "DSDDemodReport" : { "$ref" : "#/definitions/DSDDemodReport" }, @@ -2184,9 +2187,6 @@ margin-bottom: 20px; "FreqTrackerReport" : { "$ref" : "#/definitions/FreqTrackerReport" }, - "LoRaDemodReport" : { - "$ref" : "#/definitions/LoRaDemodReport" - }, "LoRaModReport" : { "$ref" : "#/definitions/LoRaModReport" }, @@ -2261,6 +2261,9 @@ margin-bottom: 20px; "ChannelAnalyzerSettings" : { "$ref" : "#/definitions/ChannelAnalyzerSettings" }, + "ChirpChatDemodSettings" : { + "$ref" : "#/definitions/ChirpChatDemodSettings" + }, "DATVDemodSettings" : { "$ref" : "#/definitions/DATVDemodSettings" }, @@ -2282,9 +2285,6 @@ margin-bottom: 20px; "InterferometerSettings" : { "$ref" : "#/definitions/InterferometerSettings" }, - "LoRaDemodSettings" : { - "$ref" : "#/definitions/LoRaDemodSettings" - }, "LoRaModSettings" : { "$ref" : "#/definitions/LoRaModSettings" }, @@ -2343,6 +2343,187 @@ margin-bottom: 20px; } }, "description" : "All channels detailed information" +}; + defs.ChirpChatDemodReport = { + "properties" : { + "channelPowerDB" : { + "type" : "number", + "format" : "float", + "description" : "current de-chirped total channel power (dB)" + }, + "noisePowerDB" : { + "type" : "number", + "format" : "float", + "description" : "current de-chirped noise argmax power (dB)" + }, + "signalPowerDB" : { + "type" : "number", + "format" : "float", + "description" : "last message de-chirped signal argmax power (dB)" + }, + "snrPowerDB" : { + "type" : "number", + "format" : "float", + "description" : "last message de-chirped signal to noise ratio power (dB)" + }, + "channelSampleRate" : { + "type" : "integer" + }, + "syncWord" : { + "type" : "integer", + "description" : "2 bytes sync word (0..65535)" + }, + "hasCRC" : { + "type" : "integer", + "description" : "boolean 1 if payload CRC is present else 0 (LoRa)" + }, + "nbParityBits" : { + "type" : "integer", + "description" : "Hamming FEC parity bits (LoRa)" + }, + "packetLength" : { + "type" : "integer", + "description" : "Packet length in number of bytes (LoRa)" + }, + "nbSymbols" : { + "type" : "integer", + "description" : "Number of symbols in the payload with header and CRC (LoRa)" + }, + "nbCodewords" : { + "type" : "integer", + "description" : "Number of codewords in the payload with header and CRC (LoRa)" + }, + "headerParityStatus" : { + "type" : "integer", + "description" : "Header FEC parity status:\n * 0 - Undefined\n * 1 - Uncorrectable error\n * 2 - Corrected error\n * 3 - OK\n" + }, + "headerCRCStatus" : { + "type" : "integer", + "description" : "header CRC check status. Boolean 1 if OK else 0" + }, + "payloadParityStatus" : { + "type" : "integer", + "description" : "Payload FEC parity status:\n * 0 - Undefined\n * 1 - Uncorrectable error\n * 2 - Corrected error\n * 3 - OK\n" + }, + "payloadCRCStatus" : { + "type" : "integer", + "description" : "payload CRC check status. Boolean 1 if OK else 0" + }, + "messageTimestamp" : { + "type" : "string", + "description" : "timestamp of the last decoded message" + }, + "messageString" : { + "type" : "string", + "description" : "string representation of the last decoded message" + }, + "messageBytes" : { + "type" : "array", + "description" : "bytes of the last decoded message as an array of hex string represented bytes (00..FF)", + "items" : { + "type" : "string" + } + } + }, + "description" : "ChirpChatDemod" +}; + defs.ChirpChatDemodSettings = { + "properties" : { + "inputFrequencyOffset" : { + "type" : "integer", + "format" : "int64" + }, + "bandwidthIndex" : { + "type" : "integer", + "description" : "standard bandwidths index:\n * 0 - 2604 Hz (333333 / 128)\n * 1 - 3125 Hz (400000 / 128)\n * 2 - 3906 Hz (500000 / 128)\n * 3 - 5208 Hz (333333 / 64)\n * 4 - 6250 Hz (400000 / 64)\n * 5 - 7813 Hz (500000 / 64)\n * 6 - 10417 Hz (333333 / 32)\n * 7 - 12500 Hz (400000 / 32)\n * 8 - 15625 Hz (500000 / 32)\n * 9 - 20833 Hz (333333 / 16)\n * 10 - 25000 Hz (400000 / 16)\n * 11 - 31250 Hz (500000 / 16)\n * 12 - 41667 Hz (333333 / 8)\n * 13 - 50000 Hz (400000 / 8)\n * 14 - 62500 Hz (500000 / 8)\n * 15 - 83333 Hz (333333 / 4)\n * 16 - 100000 Hz (400000 / 4)\n * 17 - 125000 Hz (500000 / 4)\n * 18 - 166667 Hz (333333 / 2)\n * 19 - 200000 Hz (400000 / 2)\n * 20 - 250000 Hz (500000 / 2)\n * 21 - 333333 Hz (333333 / 1)\n * 22 - 400000 Hz (400000 / 1)\n * 23 - 500000 Hz (500000 / 1)\n" + }, + "spreadFactor" : { + "type" : "integer" + }, + "deBits" : { + "type" : "integer", + "description" : "Low data rate optmize (DE) bits i.e. nb of FFT bins per effective symbol" + }, + "codingScheme" : { + "type" : "integer", + "description" : "message encoding scheme (LoRaModSettings::CodingScheme):\n * 0 - LoRa\n * 1 - Plain ASCII (7 bit)\n * 2 - Teletype (5 bit Baudot) a.k.a TTY\n" + }, + "decodeActive" : { + "type" : "integer", + "description" : "boolean 1 to activate 0 to de-activate decoder" + }, + "eomSquelchTenths" : { + "type" : "integer", + "description" : "argmax squared magnitude is compared between current multiplied by this factor and maximum during decoding. This value is divided by 10" + }, + "nbSymbolsMax" : { + "type" : "integer", + "description" : "expected maximum number of symbols in a payload" + }, + "autoNbSymbolsMax" : { + "type" : "integer", + "description" : "adjust maximum number of symbols in a payload to the value just received (LoRa)" + }, + "preambleChirps" : { + "type" : "integer", + "description" : "Number of expected preamble chirps" + }, + "nbParityBits" : { + "type" : "integer", + "description" : "Hamming FEC parity bits (LoRa)" + }, + "packetLength" : { + "type" : "integer", + "description" : "expected packet length in number of bytes (LoRa)" + }, + "hasCRC" : { + "type" : "integer", + "description" : "Payload has CRC (LoRa)" + }, + "hasHeader" : { + "type" : "integer", + "description" : "Header present before actual payload (LoRa)" + }, + "sendViaUDP" : { + "type" : "integer", + "description" : "boolean 1 to send decoded message via UDP else 0" + }, + "udpAddress" : { + "type" : "string", + "description" : "UDP destination udpAddress" + }, + "udpPort" : { + "type" : "integer", + "description" : "UDP destination properties" + }, + "rgbColor" : { + "type" : "integer" + }, + "title" : { + "type" : "string" + }, + "streamIndex" : { + "type" : "integer", + "description" : "MIMO channel. Not relevant when connected to SI (single Rx)." + }, + "useReverseAPI" : { + "type" : "integer", + "description" : "Synchronize with reverse API (1 for yes, 0 for no)" + }, + "reverseAPIAddress" : { + "type" : "string" + }, + "reverseAPIPort" : { + "type" : "integer" + }, + "reverseAPIDeviceIndex" : { + "type" : "integer" + }, + "reverseAPIChannelIndex" : { + "type" : "integer" + } + }, + "description" : "ChirpChatDemod" }; defs.Command = { "properties" : { @@ -4385,187 +4566,6 @@ margin-bottom: 20px; } }, "description" : "LimeSDR" -}; - defs.LoRaDemodReport = { - "properties" : { - "channelPowerDB" : { - "type" : "number", - "format" : "float", - "description" : "current de-chirped total channel power (dB)" - }, - "noisePowerDB" : { - "type" : "number", - "format" : "float", - "description" : "current de-chirped noise argmax power (dB)" - }, - "signalPowerDB" : { - "type" : "number", - "format" : "float", - "description" : "last message de-chirped signal argmax power (dB)" - }, - "snrPowerDB" : { - "type" : "number", - "format" : "float", - "description" : "last message de-chirped signal to noise ratio power (dB)" - }, - "channelSampleRate" : { - "type" : "integer" - }, - "syncWord" : { - "type" : "integer", - "description" : "2 bytes sync word (0..65535)" - }, - "hasCRC" : { - "type" : "integer", - "description" : "boolean 1 if payload CRC is present else 0 (LoRa)" - }, - "nbParityBits" : { - "type" : "integer", - "description" : "Hamming FEC parity bits (LoRa)" - }, - "packetLength" : { - "type" : "integer", - "description" : "Packet length in number of bytes (LoRa)" - }, - "nbSymbols" : { - "type" : "integer", - "description" : "Number of symbols in the payload with header and CRC (LoRa)" - }, - "nbCodewords" : { - "type" : "integer", - "description" : "Number of codewords in the payload with header and CRC (LoRa)" - }, - "headerParityStatus" : { - "type" : "integer", - "description" : "Header FEC parity status:\n * 0 - Undefined\n * 1 - Uncorrectable error\n * 2 - Corrected error\n * 3 - OK\n" - }, - "headerCRCStatus" : { - "type" : "integer", - "description" : "header CRC check status. Boolean 1 if OK else 0" - }, - "payloadParityStatus" : { - "type" : "integer", - "description" : "Payload FEC parity status:\n * 0 - Undefined\n * 1 - Uncorrectable error\n * 2 - Corrected error\n * 3 - OK\n" - }, - "payloadCRCStatus" : { - "type" : "integer", - "description" : "payload CRC check status. Boolean 1 if OK else 0" - }, - "messageTimestamp" : { - "type" : "string", - "description" : "timestamp of the last decoded message" - }, - "messageString" : { - "type" : "string", - "description" : "string representation of the last decoded message" - }, - "messageBytes" : { - "type" : "array", - "description" : "bytes of the last decoded message as an array of hex string represented bytes (00..FF)", - "items" : { - "type" : "string" - } - } - }, - "description" : "LoRaDemod" -}; - defs.LoRaDemodSettings = { - "properties" : { - "inputFrequencyOffset" : { - "type" : "integer", - "format" : "int64" - }, - "bandwidthIndex" : { - "type" : "integer", - "description" : "standard bandwidths index:\n * 0 - 2604 Hz (333333 / 128)\n * 1 - 3125 Hz (400000 / 128)\n * 2 - 3906 Hz (500000 / 128)\n * 3 - 5208 Hz (333333 / 64)\n * 4 - 6250 Hz (400000 / 64)\n * 5 - 7813 Hz (500000 / 64)\n * 6 - 10417 Hz (333333 / 32)\n * 7 - 12500 Hz (400000 / 32)\n * 8 - 15625 Hz (500000 / 32)\n * 9 - 20833 Hz (333333 / 16)\n * 10 - 25000 Hz (400000 / 16)\n * 11 - 31250 Hz (500000 / 16)\n * 12 - 41667 Hz (333333 / 8)\n * 13 - 50000 Hz (400000 / 8)\n * 14 - 62500 Hz (500000 / 8)\n * 15 - 83333 Hz (333333 / 4)\n * 16 - 100000 Hz (400000 / 4)\n * 17 - 125000 Hz (500000 / 4)\n * 18 - 166667 Hz (333333 / 2)\n * 19 - 200000 Hz (400000 / 2)\n * 20 - 250000 Hz (500000 / 2)\n * 21 - 333333 Hz (333333 / 1)\n * 22 - 400000 Hz (400000 / 1)\n * 23 - 500000 Hz (500000 / 1)\n" - }, - "spreadFactor" : { - "type" : "integer" - }, - "deBits" : { - "type" : "integer", - "description" : "Low data rate optmize (DE) bits i.e. nb of FFT bins per effective symbol" - }, - "codingScheme" : { - "type" : "integer", - "description" : "message encoding scheme (LoRaModSettings::CodingScheme):\n * 0 - LoRa\n * 1 - Plain ASCII (7 bit)\n * 2 - Teletype (5 bit Baudot) a.k.a TTY\n" - }, - "decodeActive" : { - "type" : "integer", - "description" : "boolean 1 to activate 0 to de-activate decoder" - }, - "eomSquelchTenths" : { - "type" : "integer", - "description" : "argmax squared magnitude is compared between current multiplied by this factor and maximum during decoding. This value is divided by 10" - }, - "nbSymbolsMax" : { - "type" : "integer", - "description" : "expected maximum number of symbols in a payload" - }, - "autoNbSymbolsMax" : { - "type" : "integer", - "description" : "adjust maximum number of symbols in a payload to the value just received (LoRa)" - }, - "preambleChirps" : { - "type" : "integer", - "description" : "Number of expected preamble chirps" - }, - "nbParityBits" : { - "type" : "integer", - "description" : "Hamming FEC parity bits (LoRa)" - }, - "packetLength" : { - "type" : "integer", - "description" : "expected packet length in number of bytes (LoRa)" - }, - "hasCRC" : { - "type" : "integer", - "description" : "Payload has CRC (LoRa)" - }, - "hasHeader" : { - "type" : "integer", - "description" : "Header present before actual payload (LoRa)" - }, - "sendViaUDP" : { - "type" : "integer", - "description" : "boolean 1 to send decoded message via UDP else 0" - }, - "udpAddress" : { - "type" : "string", - "description" : "UDP destination udpAddress" - }, - "udpPort" : { - "type" : "integer", - "description" : "UDP destination properties" - }, - "rgbColor" : { - "type" : "integer" - }, - "title" : { - "type" : "string" - }, - "streamIndex" : { - "type" : "integer", - "description" : "MIMO channel. Not relevant when connected to SI (single Rx)." - }, - "useReverseAPI" : { - "type" : "integer", - "description" : "Synchronize with reverse API (1 for yes, 0 for no)" - }, - "reverseAPIAddress" : { - "type" : "string" - }, - "reverseAPIPort" : { - "type" : "integer" - }, - "reverseAPIDeviceIndex" : { - "type" : "integer" - }, - "reverseAPIChannelIndex" : { - "type" : "integer" - } - }, - "description" : "LoRaDemod" }; defs.LoRaModReport = { "properties" : { @@ -32618,7 +32618,7 @@ except ApiException as e:
- Generated 2020-02-25T14:33:44.826+01:00 + Generated 2020-03-03T20:19:50.511+01:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/ChannelSettings.yaml b/sdrbase/resources/webapi/doc/swagger/include/ChannelSettings.yaml index 57410e97a..f0a622e78 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/ChannelSettings.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/ChannelSettings.yaml @@ -31,6 +31,8 @@ ChannelSettings: $ref: "/doc/swagger/include/BFMDemod.yaml#/BFMDemodSettings" ChannelAnalyzerSettings: $ref: "/doc/swagger/include/ChannelAnalyzer.yaml#/ChannelAnalyzerSettings" + ChirpChatDemodSettings: + $ref: "/doc/swagger/include/ChirpChatDemod.yaml#/ChirpChatDemodSettings" DATVDemodSettings: $ref: "/doc/swagger/include/DATVDemod.yaml#/DATVDemodSettings" DSDDemodSettings: @@ -45,8 +47,6 @@ ChannelSettings: $ref: "/doc/swagger/include/FreqTracker.yaml#/FreqTrackerSettings" InterferometerSettings: $ref: "/doc/swagger/include/Interferometer.yaml#/InterferometerSettings" - LoRaDemodSettings: - $ref: "/doc/swagger/include/LoRaDemod.yaml#/LoRaDemodSettings" LoRaModSettings: $ref: "/doc/swagger/include/LoRaMod.yaml#/LoRaModSettings" NFMDemodSettings: diff --git a/swagger/sdrangel/api/swagger/include/LoRaDemod.yaml b/sdrbase/resources/webapi/doc/swagger/include/ChirpChatDemod.yaml similarity index 98% rename from swagger/sdrangel/api/swagger/include/LoRaDemod.yaml rename to sdrbase/resources/webapi/doc/swagger/include/ChirpChatDemod.yaml index 7f91f480c..7194cf866 100644 --- a/swagger/sdrangel/api/swagger/include/LoRaDemod.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/ChirpChatDemod.yaml @@ -1,5 +1,5 @@ -LoRaDemodSettings: - description: LoRaDemod +ChirpChatDemodSettings: + description: ChirpChatDemod properties: inputFrequencyOffset: type: integer @@ -99,8 +99,8 @@ LoRaDemodSettings: reverseAPIChannelIndex: type: integer -LoRaDemodReport: - description: LoRaDemod +ChirpChatDemodReport: + description: ChirpChatDemod properties: channelPowerDB: description: current de-chirped total channel power (dB) diff --git a/sdrbase/resources/webapi/doc/swagger/swagger.yaml b/sdrbase/resources/webapi/doc/swagger/swagger.yaml index 3538f004c..6a94d4dc6 100644 --- a/sdrbase/resources/webapi/doc/swagger/swagger.yaml +++ b/sdrbase/resources/webapi/doc/swagger/swagger.yaml @@ -2262,6 +2262,8 @@ definitions: $ref: "/doc/swagger/include/ATVMod.yaml#/ATVModReport" BFMDemodReport: $ref: "/doc/swagger/include/BFMDemod.yaml#/BFMDemodReport" + ChirpChatDemodReport: + $ref: "/doc/swagger/include/ChirpChatDemod.yaml#/ChirpChatDemodReport" DSDDemodReport: $ref: "/doc/swagger/include/DSDDemod.yaml#/DSDDemodReport" FileSourceReport: @@ -2272,8 +2274,6 @@ definitions: $ref: "/doc/swagger/include/FreeDVMod.yaml#/FreeDVModReport" FreqTrackerReport: $ref: "/doc/swagger/include/FreqTracker.yaml#/FreqTrackerReport" - LoRaDemodReport: - $ref: "/doc/swagger/include/LoRaDemod.yaml#/LoRaDemodReport" LoRaModReport: $ref: "/doc/swagger/include/LoRaMod.yaml#/LoRaModReport" NFMDemodReport: diff --git a/sdrbase/webapi/webapirequestmapper.cpp b/sdrbase/webapi/webapirequestmapper.cpp index 50a50abcf..7bef3af39 100644 --- a/sdrbase/webapi/webapirequestmapper.cpp +++ b/sdrbase/webapi/webapirequestmapper.cpp @@ -59,6 +59,7 @@ const QMap WebAPIRequestMapper::m_channelURIToSettingsKey = { {"sdrangel.channel.chanalyzer", "ChannelAnalyzerSettings"}, {"sdrangel.channel.chanalyzerng", "ChannelAnalyzerSettings"}, // remap {"org.f4exb.sdrangelove.channel.chanalyzer", "ChannelAnalyzerSettings"}, // remap + {"sdrangel.channel.chirpchatdemod", "ChirpChatDemodSettings"}, {"sdrangel.channel.demodatv", "ATVDemodSettings"}, {"sdrangel.channel.demoddatv", "DATVDemodSettings"}, {"sdrangel.channel.dsddemod", "DSDDemodSettings"}, @@ -72,7 +73,6 @@ const QMap WebAPIRequestMapper::m_channelURIToSettingsKey = { {"sdrangel.demod.localsink", "LocalSinkSettings"}, {"sdrangel.channel.localsink", "LocalSinkSettings"}, // remap {"sdrangel.channel.localsource", "LocalSourceSettings"}, - {"sdrangel.channel.lorademod", "LoRaDemodSettings"}, {"sdrangel.channel.modlora", "LoRaModSettings"}, {"sdrangel.demod.remotesink", "RemoteSinkSettings"}, {"sdrangel.channeltx.remotesource", "RemoteSourceSettings"}, @@ -138,6 +138,7 @@ const QMap WebAPIRequestMapper::m_channelTypeToSettingsKey = { {"ATVMod", "ATVModSettings"}, {"BFMDemod", "BFMDemodSettings"}, {"ChannelAnalyzer", "ChannelAnalyzerSettings"}, + {"ChirpChatDemod", "ChirpChatDemodSettings"}, {"DATVDemod", "DATVDemodSettings"}, {"DSDDemod", "DSDDemodSettings"}, {"FileSource", "FileSourceSettings"}, @@ -148,7 +149,6 @@ const QMap WebAPIRequestMapper::m_channelTypeToSettingsKey = { {"NFMMod", "NFMModSettings"}, {"LocalSink", "LocalSinkSettings"}, {"LocalSource", "LocalSourceSettings"}, - {"LoRaDemod", "LoRaDemodSettings"}, {"LoRaMod", "LoRaModSettings"}, {"RemoteSink", "RemoteSinkSettings"}, {"RemoteSource", "RemoteSourceSettings"}, @@ -2915,10 +2915,10 @@ bool WebAPIRequestMapper::getChannel( channelSettings->setLocalSourceSettings(new SWGSDRangel::SWGLocalSourceSettings()); channelSettings->getLocalSourceSettings()->fromJsonObject(settingsJsonObject); } - else if (channelSettingsKey == "LoRaDemodSettings") + else if (channelSettingsKey == "ChirpChatDemodSettings") { - channelSettings->setLoRaDemodSettings(new SWGSDRangel::SWGLoRaDemodSettings()); - channelSettings->getLoRaDemodSettings()->fromJsonObject(settingsJsonObject); + channelSettings->setChirpChatDemodSettings(new SWGSDRangel::SWGChirpChatDemodSettings()); + channelSettings->getChirpChatDemodSettings()->fromJsonObject(settingsJsonObject); } else if (channelSettingsKey == "LoRaModSettings") { diff --git a/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml b/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml index c983aa1b6..a5ba9d963 100644 --- a/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml +++ b/swagger/sdrangel/api/swagger/include/ChannelSettings.yaml @@ -31,6 +31,8 @@ ChannelSettings: $ref: "http://localhost:8081/api/swagger/include/BFMDemod.yaml#/BFMDemodSettings" ChannelAnalyzerSettings: $ref: "http://localhost:8081/api/swagger/include/ChannelAnalyzer.yaml#/ChannelAnalyzerSettings" + ChirpChatDemodSettings: + $ref: "http://localhost:8081/api/swagger/include/ChirpChatDemod.yaml#/ChirpChatDemodSettings" DATVDemodSettings: $ref: "http://localhost:8081/api/swagger/include/DATVDemod.yaml#/DATVDemodSettings" DSDDemodSettings: @@ -45,8 +47,6 @@ ChannelSettings: $ref: "http://localhost:8081/api/swagger/include/FreqTracker.yaml#/FreqTrackerSettings" InterferometerSettings: $ref: "http://localhost:8081/api/swagger/include/Interferometer.yaml#/InterferometerSettings" - LoRaDemodSettings: - $ref: "http://localhost:8081/api/swagger/include/LoRaDemod.yaml#/LoRaDemodSettings" LoRaModSettings: $ref: "http://localhost:8081/api/swagger/include/LoRaMod.yaml#/LoRaModSettings" NFMDemodSettings: diff --git a/swagger/sdrangel/api/swagger/include/ChirpChatDemod.yaml b/swagger/sdrangel/api/swagger/include/ChirpChatDemod.yaml new file mode 100644 index 000000000..7194cf866 --- /dev/null +++ b/swagger/sdrangel/api/swagger/include/ChirpChatDemod.yaml @@ -0,0 +1,173 @@ +ChirpChatDemodSettings: + description: ChirpChatDemod + properties: + inputFrequencyOffset: + type: integer + format: int64 + bandwidthIndex: + type: integer + description: > + standard bandwidths index: + * 0 - 2604 Hz (333333 / 128) + * 1 - 3125 Hz (400000 / 128) + * 2 - 3906 Hz (500000 / 128) + * 3 - 5208 Hz (333333 / 64) + * 4 - 6250 Hz (400000 / 64) + * 5 - 7813 Hz (500000 / 64) + * 6 - 10417 Hz (333333 / 32) + * 7 - 12500 Hz (400000 / 32) + * 8 - 15625 Hz (500000 / 32) + * 9 - 20833 Hz (333333 / 16) + * 10 - 25000 Hz (400000 / 16) + * 11 - 31250 Hz (500000 / 16) + * 12 - 41667 Hz (333333 / 8) + * 13 - 50000 Hz (400000 / 8) + * 14 - 62500 Hz (500000 / 8) + * 15 - 83333 Hz (333333 / 4) + * 16 - 100000 Hz (400000 / 4) + * 17 - 125000 Hz (500000 / 4) + * 18 - 166667 Hz (333333 / 2) + * 19 - 200000 Hz (400000 / 2) + * 20 - 250000 Hz (500000 / 2) + * 21 - 333333 Hz (333333 / 1) + * 22 - 400000 Hz (400000 / 1) + * 23 - 500000 Hz (500000 / 1) + spreadFactor: + type: integer + deBits: + description: Low data rate optmize (DE) bits i.e. nb of FFT bins per effective symbol + type: integer + codingScheme: + type: integer + description: > + message encoding scheme (LoRaModSettings::CodingScheme): + * 0 - LoRa + * 1 - Plain ASCII (7 bit) + * 2 - Teletype (5 bit Baudot) a.k.a TTY + decodeActive: + description: boolean 1 to activate 0 to de-activate decoder + type: integer + eomSquelchTenths: + description: argmax squared magnitude is compared between current multiplied by this factor and maximum during decoding. This value is divided by 10 + type: integer + nbSymbolsMax: + description: expected maximum number of symbols in a payload + type: integer + autoNbSymbolsMax: + description: adjust maximum number of symbols in a payload to the value just received (LoRa) + type: integer + preambleChirps: + description: Number of expected preamble chirps + type: integer + nbParityBits: + description: Hamming FEC parity bits (LoRa) + type: integer + packetLength: + description: expected packet length in number of bytes (LoRa) + type: integer + hasCRC: + description: Payload has CRC (LoRa) + type: integer + hasHeader: + description: Header present before actual payload (LoRa) + type: integer + sendViaUDP: + description: boolean 1 to send decoded message via UDP else 0 + type: integer + udpAddress: + description: UDP destination udpAddress + type: string + udpPort: + description: UDP destination properties + type: integer + rgbColor: + type: integer + title: + type: string + streamIndex: + description: MIMO channel. Not relevant when connected to SI (single Rx). + type: integer + useReverseAPI: + description: Synchronize with reverse API (1 for yes, 0 for no) + type: integer + reverseAPIAddress: + type: string + reverseAPIPort: + type: integer + reverseAPIDeviceIndex: + type: integer + reverseAPIChannelIndex: + type: integer + +ChirpChatDemodReport: + description: ChirpChatDemod + properties: + channelPowerDB: + description: current de-chirped total channel power (dB) + type: number + format: float + noisePowerDB: + description: current de-chirped noise argmax power (dB) + type: number + format: float + signalPowerDB: + description: last message de-chirped signal argmax power (dB) + type: number + format: float + snrPowerDB: + description: last message de-chirped signal to noise ratio power (dB) + type: number + format: float + channelSampleRate: + type: integer + syncWord: + description: 2 bytes sync word (0..65535) + type: integer + hasCRC: + description: boolean 1 if payload CRC is present else 0 (LoRa) + type: integer + nbParityBits: + description: Hamming FEC parity bits (LoRa) + type: integer + packetLength: + description: Packet length in number of bytes (LoRa) + type: integer + nbSymbols: + description: Number of symbols in the payload with header and CRC (LoRa) + type: integer + nbCodewords: + description: Number of codewords in the payload with header and CRC (LoRa) + type: integer + headerParityStatus: + type: integer + description: > + Header FEC parity status: + * 0 - Undefined + * 1 - Uncorrectable error + * 2 - Corrected error + * 3 - OK + headerCRCStatus: + description: header CRC check status. Boolean 1 if OK else 0 + type: integer + payloadParityStatus: + type: integer + description: > + Payload FEC parity status: + * 0 - Undefined + * 1 - Uncorrectable error + * 2 - Corrected error + * 3 - OK + payloadCRCStatus: + description: payload CRC check status. Boolean 1 if OK else 0 + type: integer + messageTimestamp: + description: timestamp of the last decoded message + type: string + messageString: + description: string representation of the last decoded message + type: string + messageBytes: + description: bytes of the last decoded message as an array of hex string represented bytes (00..FF) + type: array + items: + type: string diff --git a/swagger/sdrangel/api/swagger/swagger.yaml b/swagger/sdrangel/api/swagger/swagger.yaml index e0743ca66..eeabb05da 100644 --- a/swagger/sdrangel/api/swagger/swagger.yaml +++ b/swagger/sdrangel/api/swagger/swagger.yaml @@ -2262,6 +2262,8 @@ definitions: $ref: "http://localhost:8081/api/swagger/include/ATVMod.yaml#/ATVModReport" BFMDemodReport: $ref: "http://localhost:8081/api/swagger/include/BFMDemod.yaml#/BFMDemodReport" + ChirpChatDemodReport: + $ref: "http://localhost:8081/api/swagger/include/ChirpChatDemod.yaml#/ChirpChatDemodReport" DSDDemodReport: $ref: "http://localhost:8081/api/swagger/include/DSDDemod.yaml#/DSDDemodReport" FileSourceReport: @@ -2272,8 +2274,6 @@ definitions: $ref: "http://localhost:8081/api/swagger/include/FreeDVMod.yaml#/FreeDVModReport" FreqTrackerReport: $ref: "http://localhost:8081/api/swagger/include/FreqTracker.yaml#/FreqTrackerReport" - LoRaDemodReport: - $ref: "http://localhost:8081/api/swagger/include/LoRaDemod.yaml#/LoRaDemodReport" LoRaModReport: $ref: "http://localhost:8081/api/swagger/include/LoRaMod.yaml#/LoRaModReport" NFMDemodReport: diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 47d5086ff..512727d6f 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -2169,6 +2169,9 @@ margin-bottom: 20px; "BFMDemodReport" : { "$ref" : "#/definitions/BFMDemodReport" }, + "ChirpChatDemodReport" : { + "$ref" : "#/definitions/ChirpChatDemodReport" + }, "DSDDemodReport" : { "$ref" : "#/definitions/DSDDemodReport" }, @@ -2184,9 +2187,6 @@ margin-bottom: 20px; "FreqTrackerReport" : { "$ref" : "#/definitions/FreqTrackerReport" }, - "LoRaDemodReport" : { - "$ref" : "#/definitions/LoRaDemodReport" - }, "LoRaModReport" : { "$ref" : "#/definitions/LoRaModReport" }, @@ -2261,6 +2261,9 @@ margin-bottom: 20px; "ChannelAnalyzerSettings" : { "$ref" : "#/definitions/ChannelAnalyzerSettings" }, + "ChirpChatDemodSettings" : { + "$ref" : "#/definitions/ChirpChatDemodSettings" + }, "DATVDemodSettings" : { "$ref" : "#/definitions/DATVDemodSettings" }, @@ -2282,9 +2285,6 @@ margin-bottom: 20px; "InterferometerSettings" : { "$ref" : "#/definitions/InterferometerSettings" }, - "LoRaDemodSettings" : { - "$ref" : "#/definitions/LoRaDemodSettings" - }, "LoRaModSettings" : { "$ref" : "#/definitions/LoRaModSettings" }, @@ -2343,6 +2343,187 @@ margin-bottom: 20px; } }, "description" : "All channels detailed information" +}; + defs.ChirpChatDemodReport = { + "properties" : { + "channelPowerDB" : { + "type" : "number", + "format" : "float", + "description" : "current de-chirped total channel power (dB)" + }, + "noisePowerDB" : { + "type" : "number", + "format" : "float", + "description" : "current de-chirped noise argmax power (dB)" + }, + "signalPowerDB" : { + "type" : "number", + "format" : "float", + "description" : "last message de-chirped signal argmax power (dB)" + }, + "snrPowerDB" : { + "type" : "number", + "format" : "float", + "description" : "last message de-chirped signal to noise ratio power (dB)" + }, + "channelSampleRate" : { + "type" : "integer" + }, + "syncWord" : { + "type" : "integer", + "description" : "2 bytes sync word (0..65535)" + }, + "hasCRC" : { + "type" : "integer", + "description" : "boolean 1 if payload CRC is present else 0 (LoRa)" + }, + "nbParityBits" : { + "type" : "integer", + "description" : "Hamming FEC parity bits (LoRa)" + }, + "packetLength" : { + "type" : "integer", + "description" : "Packet length in number of bytes (LoRa)" + }, + "nbSymbols" : { + "type" : "integer", + "description" : "Number of symbols in the payload with header and CRC (LoRa)" + }, + "nbCodewords" : { + "type" : "integer", + "description" : "Number of codewords in the payload with header and CRC (LoRa)" + }, + "headerParityStatus" : { + "type" : "integer", + "description" : "Header FEC parity status:\n * 0 - Undefined\n * 1 - Uncorrectable error\n * 2 - Corrected error\n * 3 - OK\n" + }, + "headerCRCStatus" : { + "type" : "integer", + "description" : "header CRC check status. Boolean 1 if OK else 0" + }, + "payloadParityStatus" : { + "type" : "integer", + "description" : "Payload FEC parity status:\n * 0 - Undefined\n * 1 - Uncorrectable error\n * 2 - Corrected error\n * 3 - OK\n" + }, + "payloadCRCStatus" : { + "type" : "integer", + "description" : "payload CRC check status. Boolean 1 if OK else 0" + }, + "messageTimestamp" : { + "type" : "string", + "description" : "timestamp of the last decoded message" + }, + "messageString" : { + "type" : "string", + "description" : "string representation of the last decoded message" + }, + "messageBytes" : { + "type" : "array", + "description" : "bytes of the last decoded message as an array of hex string represented bytes (00..FF)", + "items" : { + "type" : "string" + } + } + }, + "description" : "ChirpChatDemod" +}; + defs.ChirpChatDemodSettings = { + "properties" : { + "inputFrequencyOffset" : { + "type" : "integer", + "format" : "int64" + }, + "bandwidthIndex" : { + "type" : "integer", + "description" : "standard bandwidths index:\n * 0 - 2604 Hz (333333 / 128)\n * 1 - 3125 Hz (400000 / 128)\n * 2 - 3906 Hz (500000 / 128)\n * 3 - 5208 Hz (333333 / 64)\n * 4 - 6250 Hz (400000 / 64)\n * 5 - 7813 Hz (500000 / 64)\n * 6 - 10417 Hz (333333 / 32)\n * 7 - 12500 Hz (400000 / 32)\n * 8 - 15625 Hz (500000 / 32)\n * 9 - 20833 Hz (333333 / 16)\n * 10 - 25000 Hz (400000 / 16)\n * 11 - 31250 Hz (500000 / 16)\n * 12 - 41667 Hz (333333 / 8)\n * 13 - 50000 Hz (400000 / 8)\n * 14 - 62500 Hz (500000 / 8)\n * 15 - 83333 Hz (333333 / 4)\n * 16 - 100000 Hz (400000 / 4)\n * 17 - 125000 Hz (500000 / 4)\n * 18 - 166667 Hz (333333 / 2)\n * 19 - 200000 Hz (400000 / 2)\n * 20 - 250000 Hz (500000 / 2)\n * 21 - 333333 Hz (333333 / 1)\n * 22 - 400000 Hz (400000 / 1)\n * 23 - 500000 Hz (500000 / 1)\n" + }, + "spreadFactor" : { + "type" : "integer" + }, + "deBits" : { + "type" : "integer", + "description" : "Low data rate optmize (DE) bits i.e. nb of FFT bins per effective symbol" + }, + "codingScheme" : { + "type" : "integer", + "description" : "message encoding scheme (LoRaModSettings::CodingScheme):\n * 0 - LoRa\n * 1 - Plain ASCII (7 bit)\n * 2 - Teletype (5 bit Baudot) a.k.a TTY\n" + }, + "decodeActive" : { + "type" : "integer", + "description" : "boolean 1 to activate 0 to de-activate decoder" + }, + "eomSquelchTenths" : { + "type" : "integer", + "description" : "argmax squared magnitude is compared between current multiplied by this factor and maximum during decoding. This value is divided by 10" + }, + "nbSymbolsMax" : { + "type" : "integer", + "description" : "expected maximum number of symbols in a payload" + }, + "autoNbSymbolsMax" : { + "type" : "integer", + "description" : "adjust maximum number of symbols in a payload to the value just received (LoRa)" + }, + "preambleChirps" : { + "type" : "integer", + "description" : "Number of expected preamble chirps" + }, + "nbParityBits" : { + "type" : "integer", + "description" : "Hamming FEC parity bits (LoRa)" + }, + "packetLength" : { + "type" : "integer", + "description" : "expected packet length in number of bytes (LoRa)" + }, + "hasCRC" : { + "type" : "integer", + "description" : "Payload has CRC (LoRa)" + }, + "hasHeader" : { + "type" : "integer", + "description" : "Header present before actual payload (LoRa)" + }, + "sendViaUDP" : { + "type" : "integer", + "description" : "boolean 1 to send decoded message via UDP else 0" + }, + "udpAddress" : { + "type" : "string", + "description" : "UDP destination udpAddress" + }, + "udpPort" : { + "type" : "integer", + "description" : "UDP destination properties" + }, + "rgbColor" : { + "type" : "integer" + }, + "title" : { + "type" : "string" + }, + "streamIndex" : { + "type" : "integer", + "description" : "MIMO channel. Not relevant when connected to SI (single Rx)." + }, + "useReverseAPI" : { + "type" : "integer", + "description" : "Synchronize with reverse API (1 for yes, 0 for no)" + }, + "reverseAPIAddress" : { + "type" : "string" + }, + "reverseAPIPort" : { + "type" : "integer" + }, + "reverseAPIDeviceIndex" : { + "type" : "integer" + }, + "reverseAPIChannelIndex" : { + "type" : "integer" + } + }, + "description" : "ChirpChatDemod" }; defs.Command = { "properties" : { @@ -4385,187 +4566,6 @@ margin-bottom: 20px; } }, "description" : "LimeSDR" -}; - defs.LoRaDemodReport = { - "properties" : { - "channelPowerDB" : { - "type" : "number", - "format" : "float", - "description" : "current de-chirped total channel power (dB)" - }, - "noisePowerDB" : { - "type" : "number", - "format" : "float", - "description" : "current de-chirped noise argmax power (dB)" - }, - "signalPowerDB" : { - "type" : "number", - "format" : "float", - "description" : "last message de-chirped signal argmax power (dB)" - }, - "snrPowerDB" : { - "type" : "number", - "format" : "float", - "description" : "last message de-chirped signal to noise ratio power (dB)" - }, - "channelSampleRate" : { - "type" : "integer" - }, - "syncWord" : { - "type" : "integer", - "description" : "2 bytes sync word (0..65535)" - }, - "hasCRC" : { - "type" : "integer", - "description" : "boolean 1 if payload CRC is present else 0 (LoRa)" - }, - "nbParityBits" : { - "type" : "integer", - "description" : "Hamming FEC parity bits (LoRa)" - }, - "packetLength" : { - "type" : "integer", - "description" : "Packet length in number of bytes (LoRa)" - }, - "nbSymbols" : { - "type" : "integer", - "description" : "Number of symbols in the payload with header and CRC (LoRa)" - }, - "nbCodewords" : { - "type" : "integer", - "description" : "Number of codewords in the payload with header and CRC (LoRa)" - }, - "headerParityStatus" : { - "type" : "integer", - "description" : "Header FEC parity status:\n * 0 - Undefined\n * 1 - Uncorrectable error\n * 2 - Corrected error\n * 3 - OK\n" - }, - "headerCRCStatus" : { - "type" : "integer", - "description" : "header CRC check status. Boolean 1 if OK else 0" - }, - "payloadParityStatus" : { - "type" : "integer", - "description" : "Payload FEC parity status:\n * 0 - Undefined\n * 1 - Uncorrectable error\n * 2 - Corrected error\n * 3 - OK\n" - }, - "payloadCRCStatus" : { - "type" : "integer", - "description" : "payload CRC check status. Boolean 1 if OK else 0" - }, - "messageTimestamp" : { - "type" : "string", - "description" : "timestamp of the last decoded message" - }, - "messageString" : { - "type" : "string", - "description" : "string representation of the last decoded message" - }, - "messageBytes" : { - "type" : "array", - "description" : "bytes of the last decoded message as an array of hex string represented bytes (00..FF)", - "items" : { - "type" : "string" - } - } - }, - "description" : "LoRaDemod" -}; - defs.LoRaDemodSettings = { - "properties" : { - "inputFrequencyOffset" : { - "type" : "integer", - "format" : "int64" - }, - "bandwidthIndex" : { - "type" : "integer", - "description" : "standard bandwidths index:\n * 0 - 2604 Hz (333333 / 128)\n * 1 - 3125 Hz (400000 / 128)\n * 2 - 3906 Hz (500000 / 128)\n * 3 - 5208 Hz (333333 / 64)\n * 4 - 6250 Hz (400000 / 64)\n * 5 - 7813 Hz (500000 / 64)\n * 6 - 10417 Hz (333333 / 32)\n * 7 - 12500 Hz (400000 / 32)\n * 8 - 15625 Hz (500000 / 32)\n * 9 - 20833 Hz (333333 / 16)\n * 10 - 25000 Hz (400000 / 16)\n * 11 - 31250 Hz (500000 / 16)\n * 12 - 41667 Hz (333333 / 8)\n * 13 - 50000 Hz (400000 / 8)\n * 14 - 62500 Hz (500000 / 8)\n * 15 - 83333 Hz (333333 / 4)\n * 16 - 100000 Hz (400000 / 4)\n * 17 - 125000 Hz (500000 / 4)\n * 18 - 166667 Hz (333333 / 2)\n * 19 - 200000 Hz (400000 / 2)\n * 20 - 250000 Hz (500000 / 2)\n * 21 - 333333 Hz (333333 / 1)\n * 22 - 400000 Hz (400000 / 1)\n * 23 - 500000 Hz (500000 / 1)\n" - }, - "spreadFactor" : { - "type" : "integer" - }, - "deBits" : { - "type" : "integer", - "description" : "Low data rate optmize (DE) bits i.e. nb of FFT bins per effective symbol" - }, - "codingScheme" : { - "type" : "integer", - "description" : "message encoding scheme (LoRaModSettings::CodingScheme):\n * 0 - LoRa\n * 1 - Plain ASCII (7 bit)\n * 2 - Teletype (5 bit Baudot) a.k.a TTY\n" - }, - "decodeActive" : { - "type" : "integer", - "description" : "boolean 1 to activate 0 to de-activate decoder" - }, - "eomSquelchTenths" : { - "type" : "integer", - "description" : "argmax squared magnitude is compared between current multiplied by this factor and maximum during decoding. This value is divided by 10" - }, - "nbSymbolsMax" : { - "type" : "integer", - "description" : "expected maximum number of symbols in a payload" - }, - "autoNbSymbolsMax" : { - "type" : "integer", - "description" : "adjust maximum number of symbols in a payload to the value just received (LoRa)" - }, - "preambleChirps" : { - "type" : "integer", - "description" : "Number of expected preamble chirps" - }, - "nbParityBits" : { - "type" : "integer", - "description" : "Hamming FEC parity bits (LoRa)" - }, - "packetLength" : { - "type" : "integer", - "description" : "expected packet length in number of bytes (LoRa)" - }, - "hasCRC" : { - "type" : "integer", - "description" : "Payload has CRC (LoRa)" - }, - "hasHeader" : { - "type" : "integer", - "description" : "Header present before actual payload (LoRa)" - }, - "sendViaUDP" : { - "type" : "integer", - "description" : "boolean 1 to send decoded message via UDP else 0" - }, - "udpAddress" : { - "type" : "string", - "description" : "UDP destination udpAddress" - }, - "udpPort" : { - "type" : "integer", - "description" : "UDP destination properties" - }, - "rgbColor" : { - "type" : "integer" - }, - "title" : { - "type" : "string" - }, - "streamIndex" : { - "type" : "integer", - "description" : "MIMO channel. Not relevant when connected to SI (single Rx)." - }, - "useReverseAPI" : { - "type" : "integer", - "description" : "Synchronize with reverse API (1 for yes, 0 for no)" - }, - "reverseAPIAddress" : { - "type" : "string" - }, - "reverseAPIPort" : { - "type" : "integer" - }, - "reverseAPIDeviceIndex" : { - "type" : "integer" - }, - "reverseAPIChannelIndex" : { - "type" : "integer" - } - }, - "description" : "LoRaDemod" }; defs.LoRaModReport = { "properties" : { @@ -32618,7 +32618,7 @@ except ApiException as e:
- Generated 2020-02-25T14:33:44.826+01:00 + Generated 2020-03-03T20:19:50.511+01:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGChannelReport.cpp b/swagger/sdrangel/code/qt5/client/SWGChannelReport.cpp index ced31d4dd..f3f20c34c 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChannelReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGChannelReport.cpp @@ -40,6 +40,8 @@ SWGChannelReport::SWGChannelReport() { m_atv_mod_report_isSet = false; bfm_demod_report = nullptr; m_bfm_demod_report_isSet = false; + chirp_chat_demod_report = nullptr; + m_chirp_chat_demod_report_isSet = false; dsd_demod_report = nullptr; m_dsd_demod_report_isSet = false; file_source_report = nullptr; @@ -50,8 +52,6 @@ SWGChannelReport::SWGChannelReport() { m_free_dv_mod_report_isSet = false; freq_tracker_report = nullptr; m_freq_tracker_report_isSet = false; - lo_ra_demod_report = nullptr; - m_lo_ra_demod_report_isSet = false; lo_ra_mod_report = nullptr; m_lo_ra_mod_report_isSet = false; nfm_demod_report = nullptr; @@ -92,6 +92,8 @@ SWGChannelReport::init() { m_atv_mod_report_isSet = false; bfm_demod_report = new SWGBFMDemodReport(); m_bfm_demod_report_isSet = false; + chirp_chat_demod_report = new SWGChirpChatDemodReport(); + m_chirp_chat_demod_report_isSet = false; dsd_demod_report = new SWGDSDDemodReport(); m_dsd_demod_report_isSet = false; file_source_report = new SWGFileSourceReport(); @@ -102,8 +104,6 @@ SWGChannelReport::init() { m_free_dv_mod_report_isSet = false; freq_tracker_report = new SWGFreqTrackerReport(); m_freq_tracker_report_isSet = false; - lo_ra_demod_report = new SWGLoRaDemodReport(); - m_lo_ra_demod_report_isSet = false; lo_ra_mod_report = new SWGLoRaModReport(); m_lo_ra_mod_report_isSet = false; nfm_demod_report = new SWGNFMDemodReport(); @@ -144,6 +144,9 @@ SWGChannelReport::cleanup() { if(bfm_demod_report != nullptr) { delete bfm_demod_report; } + if(chirp_chat_demod_report != nullptr) { + delete chirp_chat_demod_report; + } if(dsd_demod_report != nullptr) { delete dsd_demod_report; } @@ -159,9 +162,6 @@ SWGChannelReport::cleanup() { if(freq_tracker_report != nullptr) { delete freq_tracker_report; } - if(lo_ra_demod_report != nullptr) { - delete lo_ra_demod_report; - } if(lo_ra_mod_report != nullptr) { delete lo_ra_mod_report; } @@ -217,6 +217,8 @@ SWGChannelReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&bfm_demod_report, pJson["BFMDemodReport"], "SWGBFMDemodReport", "SWGBFMDemodReport"); + ::SWGSDRangel::setValue(&chirp_chat_demod_report, pJson["ChirpChatDemodReport"], "SWGChirpChatDemodReport", "SWGChirpChatDemodReport"); + ::SWGSDRangel::setValue(&dsd_demod_report, pJson["DSDDemodReport"], "SWGDSDDemodReport", "SWGDSDDemodReport"); ::SWGSDRangel::setValue(&file_source_report, pJson["FileSourceReport"], "SWGFileSourceReport", "SWGFileSourceReport"); @@ -227,8 +229,6 @@ SWGChannelReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&freq_tracker_report, pJson["FreqTrackerReport"], "SWGFreqTrackerReport", "SWGFreqTrackerReport"); - ::SWGSDRangel::setValue(&lo_ra_demod_report, pJson["LoRaDemodReport"], "SWGLoRaDemodReport", "SWGLoRaDemodReport"); - ::SWGSDRangel::setValue(&lo_ra_mod_report, pJson["LoRaModReport"], "SWGLoRaModReport", "SWGLoRaModReport"); ::SWGSDRangel::setValue(&nfm_demod_report, pJson["NFMDemodReport"], "SWGNFMDemodReport", "SWGNFMDemodReport"); @@ -283,6 +283,9 @@ SWGChannelReport::asJsonObject() { if((bfm_demod_report != nullptr) && (bfm_demod_report->isSet())){ toJsonValue(QString("BFMDemodReport"), bfm_demod_report, obj, QString("SWGBFMDemodReport")); } + if((chirp_chat_demod_report != nullptr) && (chirp_chat_demod_report->isSet())){ + toJsonValue(QString("ChirpChatDemodReport"), chirp_chat_demod_report, obj, QString("SWGChirpChatDemodReport")); + } if((dsd_demod_report != nullptr) && (dsd_demod_report->isSet())){ toJsonValue(QString("DSDDemodReport"), dsd_demod_report, obj, QString("SWGDSDDemodReport")); } @@ -298,9 +301,6 @@ SWGChannelReport::asJsonObject() { if((freq_tracker_report != nullptr) && (freq_tracker_report->isSet())){ toJsonValue(QString("FreqTrackerReport"), freq_tracker_report, obj, QString("SWGFreqTrackerReport")); } - if((lo_ra_demod_report != nullptr) && (lo_ra_demod_report->isSet())){ - toJsonValue(QString("LoRaDemodReport"), lo_ra_demod_report, obj, QString("SWGLoRaDemodReport")); - } if((lo_ra_mod_report != nullptr) && (lo_ra_mod_report->isSet())){ toJsonValue(QString("LoRaModReport"), lo_ra_mod_report, obj, QString("SWGLoRaModReport")); } @@ -395,6 +395,16 @@ SWGChannelReport::setBfmDemodReport(SWGBFMDemodReport* bfm_demod_report) { this->m_bfm_demod_report_isSet = true; } +SWGChirpChatDemodReport* +SWGChannelReport::getChirpChatDemodReport() { + return chirp_chat_demod_report; +} +void +SWGChannelReport::setChirpChatDemodReport(SWGChirpChatDemodReport* chirp_chat_demod_report) { + this->chirp_chat_demod_report = chirp_chat_demod_report; + this->m_chirp_chat_demod_report_isSet = true; +} + SWGDSDDemodReport* SWGChannelReport::getDsdDemodReport() { return dsd_demod_report; @@ -445,16 +455,6 @@ SWGChannelReport::setFreqTrackerReport(SWGFreqTrackerReport* freq_tracker_report this->m_freq_tracker_report_isSet = true; } -SWGLoRaDemodReport* -SWGChannelReport::getLoRaDemodReport() { - return lo_ra_demod_report; -} -void -SWGChannelReport::setLoRaDemodReport(SWGLoRaDemodReport* lo_ra_demod_report) { - this->lo_ra_demod_report = lo_ra_demod_report; - this->m_lo_ra_demod_report_isSet = true; -} - SWGLoRaModReport* SWGChannelReport::getLoRaModReport() { return lo_ra_mod_report; @@ -578,6 +578,9 @@ SWGChannelReport::isSet(){ if(bfm_demod_report && bfm_demod_report->isSet()){ isObjectUpdated = true; break; } + if(chirp_chat_demod_report && chirp_chat_demod_report->isSet()){ + isObjectUpdated = true; break; + } if(dsd_demod_report && dsd_demod_report->isSet()){ isObjectUpdated = true; break; } @@ -593,9 +596,6 @@ SWGChannelReport::isSet(){ if(freq_tracker_report && freq_tracker_report->isSet()){ isObjectUpdated = true; break; } - if(lo_ra_demod_report && lo_ra_demod_report->isSet()){ - isObjectUpdated = true; break; - } if(lo_ra_mod_report && lo_ra_mod_report->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGChannelReport.h b/swagger/sdrangel/code/qt5/client/SWGChannelReport.h index c1407a65f..5757bd601 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChannelReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGChannelReport.h @@ -26,12 +26,12 @@ #include "SWGAMModReport.h" #include "SWGATVModReport.h" #include "SWGBFMDemodReport.h" +#include "SWGChirpChatDemodReport.h" #include "SWGDSDDemodReport.h" #include "SWGFileSourceReport.h" #include "SWGFreeDVDemodReport.h" #include "SWGFreeDVModReport.h" #include "SWGFreqTrackerReport.h" -#include "SWGLoRaDemodReport.h" #include "SWGLoRaModReport.h" #include "SWGNFMDemodReport.h" #include "SWGNFMModReport.h" @@ -80,6 +80,9 @@ public: SWGBFMDemodReport* getBfmDemodReport(); void setBfmDemodReport(SWGBFMDemodReport* bfm_demod_report); + SWGChirpChatDemodReport* getChirpChatDemodReport(); + void setChirpChatDemodReport(SWGChirpChatDemodReport* chirp_chat_demod_report); + SWGDSDDemodReport* getDsdDemodReport(); void setDsdDemodReport(SWGDSDDemodReport* dsd_demod_report); @@ -95,9 +98,6 @@ public: SWGFreqTrackerReport* getFreqTrackerReport(); void setFreqTrackerReport(SWGFreqTrackerReport* freq_tracker_report); - SWGLoRaDemodReport* getLoRaDemodReport(); - void setLoRaDemodReport(SWGLoRaDemodReport* lo_ra_demod_report); - SWGLoRaModReport* getLoRaModReport(); void setLoRaModReport(SWGLoRaModReport* lo_ra_mod_report); @@ -150,6 +150,9 @@ private: SWGBFMDemodReport* bfm_demod_report; bool m_bfm_demod_report_isSet; + SWGChirpChatDemodReport* chirp_chat_demod_report; + bool m_chirp_chat_demod_report_isSet; + SWGDSDDemodReport* dsd_demod_report; bool m_dsd_demod_report_isSet; @@ -165,9 +168,6 @@ private: SWGFreqTrackerReport* freq_tracker_report; bool m_freq_tracker_report_isSet; - SWGLoRaDemodReport* lo_ra_demod_report; - bool m_lo_ra_demod_report_isSet; - SWGLoRaModReport* lo_ra_mod_report; bool m_lo_ra_mod_report_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp index fc1443d9f..0c21c1132 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.cpp @@ -50,6 +50,8 @@ SWGChannelSettings::SWGChannelSettings() { m_bfm_demod_settings_isSet = false; channel_analyzer_settings = nullptr; m_channel_analyzer_settings_isSet = false; + chirp_chat_demod_settings = nullptr; + m_chirp_chat_demod_settings_isSet = false; datv_demod_settings = nullptr; m_datv_demod_settings_isSet = false; dsd_demod_settings = nullptr; @@ -64,8 +66,6 @@ SWGChannelSettings::SWGChannelSettings() { m_freq_tracker_settings_isSet = false; interferometer_settings = nullptr; m_interferometer_settings_isSet = false; - lo_ra_demod_settings = nullptr; - m_lo_ra_demod_settings_isSet = false; lo_ra_mod_settings = nullptr; m_lo_ra_mod_settings_isSet = false; nfm_demod_settings = nullptr; @@ -122,6 +122,8 @@ SWGChannelSettings::init() { m_bfm_demod_settings_isSet = false; channel_analyzer_settings = new SWGChannelAnalyzerSettings(); m_channel_analyzer_settings_isSet = false; + chirp_chat_demod_settings = new SWGChirpChatDemodSettings(); + m_chirp_chat_demod_settings_isSet = false; datv_demod_settings = new SWGDATVDemodSettings(); m_datv_demod_settings_isSet = false; dsd_demod_settings = new SWGDSDDemodSettings(); @@ -136,8 +138,6 @@ SWGChannelSettings::init() { m_freq_tracker_settings_isSet = false; interferometer_settings = new SWGInterferometerSettings(); m_interferometer_settings_isSet = false; - lo_ra_demod_settings = new SWGLoRaDemodSettings(); - m_lo_ra_demod_settings_isSet = false; lo_ra_mod_settings = new SWGLoRaModSettings(); m_lo_ra_mod_settings_isSet = false; nfm_demod_settings = new SWGNFMDemodSettings(); @@ -195,6 +195,9 @@ SWGChannelSettings::cleanup() { if(channel_analyzer_settings != nullptr) { delete channel_analyzer_settings; } + if(chirp_chat_demod_settings != nullptr) { + delete chirp_chat_demod_settings; + } if(datv_demod_settings != nullptr) { delete datv_demod_settings; } @@ -216,9 +219,6 @@ SWGChannelSettings::cleanup() { if(interferometer_settings != nullptr) { delete interferometer_settings; } - if(lo_ra_demod_settings != nullptr) { - delete lo_ra_demod_settings; - } if(lo_ra_mod_settings != nullptr) { delete lo_ra_mod_settings; } @@ -293,6 +293,8 @@ SWGChannelSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&channel_analyzer_settings, pJson["ChannelAnalyzerSettings"], "SWGChannelAnalyzerSettings", "SWGChannelAnalyzerSettings"); + ::SWGSDRangel::setValue(&chirp_chat_demod_settings, pJson["ChirpChatDemodSettings"], "SWGChirpChatDemodSettings", "SWGChirpChatDemodSettings"); + ::SWGSDRangel::setValue(&datv_demod_settings, pJson["DATVDemodSettings"], "SWGDATVDemodSettings", "SWGDATVDemodSettings"); ::SWGSDRangel::setValue(&dsd_demod_settings, pJson["DSDDemodSettings"], "SWGDSDDemodSettings", "SWGDSDDemodSettings"); @@ -307,8 +309,6 @@ SWGChannelSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&interferometer_settings, pJson["InterferometerSettings"], "SWGInterferometerSettings", "SWGInterferometerSettings"); - ::SWGSDRangel::setValue(&lo_ra_demod_settings, pJson["LoRaDemodSettings"], "SWGLoRaDemodSettings", "SWGLoRaDemodSettings"); - ::SWGSDRangel::setValue(&lo_ra_mod_settings, pJson["LoRaModSettings"], "SWGLoRaModSettings", "SWGLoRaModSettings"); ::SWGSDRangel::setValue(&nfm_demod_settings, pJson["NFMDemodSettings"], "SWGNFMDemodSettings", "SWGNFMDemodSettings"); @@ -384,6 +384,9 @@ SWGChannelSettings::asJsonObject() { if((channel_analyzer_settings != nullptr) && (channel_analyzer_settings->isSet())){ toJsonValue(QString("ChannelAnalyzerSettings"), channel_analyzer_settings, obj, QString("SWGChannelAnalyzerSettings")); } + if((chirp_chat_demod_settings != nullptr) && (chirp_chat_demod_settings->isSet())){ + toJsonValue(QString("ChirpChatDemodSettings"), chirp_chat_demod_settings, obj, QString("SWGChirpChatDemodSettings")); + } if((datv_demod_settings != nullptr) && (datv_demod_settings->isSet())){ toJsonValue(QString("DATVDemodSettings"), datv_demod_settings, obj, QString("SWGDATVDemodSettings")); } @@ -405,9 +408,6 @@ SWGChannelSettings::asJsonObject() { if((interferometer_settings != nullptr) && (interferometer_settings->isSet())){ toJsonValue(QString("InterferometerSettings"), interferometer_settings, obj, QString("SWGInterferometerSettings")); } - if((lo_ra_demod_settings != nullptr) && (lo_ra_demod_settings->isSet())){ - toJsonValue(QString("LoRaDemodSettings"), lo_ra_demod_settings, obj, QString("SWGLoRaDemodSettings")); - } if((lo_ra_mod_settings != nullptr) && (lo_ra_mod_settings->isSet())){ toJsonValue(QString("LoRaModSettings"), lo_ra_mod_settings, obj, QString("SWGLoRaModSettings")); } @@ -561,6 +561,16 @@ SWGChannelSettings::setChannelAnalyzerSettings(SWGChannelAnalyzerSettings* chann this->m_channel_analyzer_settings_isSet = true; } +SWGChirpChatDemodSettings* +SWGChannelSettings::getChirpChatDemodSettings() { + return chirp_chat_demod_settings; +} +void +SWGChannelSettings::setChirpChatDemodSettings(SWGChirpChatDemodSettings* chirp_chat_demod_settings) { + this->chirp_chat_demod_settings = chirp_chat_demod_settings; + this->m_chirp_chat_demod_settings_isSet = true; +} + SWGDATVDemodSettings* SWGChannelSettings::getDatvDemodSettings() { return datv_demod_settings; @@ -631,16 +641,6 @@ SWGChannelSettings::setInterferometerSettings(SWGInterferometerSettings* interfe this->m_interferometer_settings_isSet = true; } -SWGLoRaDemodSettings* -SWGChannelSettings::getLoRaDemodSettings() { - return lo_ra_demod_settings; -} -void -SWGChannelSettings::setLoRaDemodSettings(SWGLoRaDemodSettings* lo_ra_demod_settings) { - this->lo_ra_demod_settings = lo_ra_demod_settings; - this->m_lo_ra_demod_settings_isSet = true; -} - SWGLoRaModSettings* SWGChannelSettings::getLoRaModSettings() { return lo_ra_mod_settings; @@ -809,6 +809,9 @@ SWGChannelSettings::isSet(){ if(channel_analyzer_settings && channel_analyzer_settings->isSet()){ isObjectUpdated = true; break; } + if(chirp_chat_demod_settings && chirp_chat_demod_settings->isSet()){ + isObjectUpdated = true; break; + } if(datv_demod_settings && datv_demod_settings->isSet()){ isObjectUpdated = true; break; } @@ -830,9 +833,6 @@ SWGChannelSettings::isSet(){ if(interferometer_settings && interferometer_settings->isSet()){ isObjectUpdated = true; break; } - if(lo_ra_demod_settings && lo_ra_demod_settings->isSet()){ - isObjectUpdated = true; break; - } if(lo_ra_mod_settings && lo_ra_mod_settings->isSet()){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h index 1ee6a096e..630f99bef 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGChannelSettings.h @@ -29,6 +29,7 @@ #include "SWGBFMDemodSettings.h" #include "SWGBeamSteeringCWModSettings.h" #include "SWGChannelAnalyzerSettings.h" +#include "SWGChirpChatDemodSettings.h" #include "SWGDATVDemodSettings.h" #include "SWGDSDDemodSettings.h" #include "SWGFileSourceSettings.h" @@ -36,7 +37,6 @@ #include "SWGFreeDVModSettings.h" #include "SWGFreqTrackerSettings.h" #include "SWGInterferometerSettings.h" -#include "SWGLoRaDemodSettings.h" #include "SWGLoRaModSettings.h" #include "SWGLocalSinkSettings.h" #include "SWGLocalSourceSettings.h" @@ -103,6 +103,9 @@ public: SWGChannelAnalyzerSettings* getChannelAnalyzerSettings(); void setChannelAnalyzerSettings(SWGChannelAnalyzerSettings* channel_analyzer_settings); + SWGChirpChatDemodSettings* getChirpChatDemodSettings(); + void setChirpChatDemodSettings(SWGChirpChatDemodSettings* chirp_chat_demod_settings); + SWGDATVDemodSettings* getDatvDemodSettings(); void setDatvDemodSettings(SWGDATVDemodSettings* datv_demod_settings); @@ -124,9 +127,6 @@ public: SWGInterferometerSettings* getInterferometerSettings(); void setInterferometerSettings(SWGInterferometerSettings* interferometer_settings); - SWGLoRaDemodSettings* getLoRaDemodSettings(); - void setLoRaDemodSettings(SWGLoRaDemodSettings* lo_ra_demod_settings); - SWGLoRaModSettings* getLoRaModSettings(); void setLoRaModSettings(SWGLoRaModSettings* lo_ra_mod_settings); @@ -203,6 +203,9 @@ private: SWGChannelAnalyzerSettings* channel_analyzer_settings; bool m_channel_analyzer_settings_isSet; + SWGChirpChatDemodSettings* chirp_chat_demod_settings; + bool m_chirp_chat_demod_settings_isSet; + SWGDATVDemodSettings* datv_demod_settings; bool m_datv_demod_settings_isSet; @@ -224,9 +227,6 @@ private: SWGInterferometerSettings* interferometer_settings; bool m_interferometer_settings_isSet; - SWGLoRaDemodSettings* lo_ra_demod_settings; - bool m_lo_ra_demod_settings_isSet; - SWGLoRaModSettings* lo_ra_mod_settings; bool m_lo_ra_mod_settings_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGLoRaDemodReport.cpp b/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodReport.cpp similarity index 83% rename from swagger/sdrangel/code/qt5/client/SWGLoRaDemodReport.cpp rename to swagger/sdrangel/code/qt5/client/SWGChirpChatDemodReport.cpp index d0d1a3750..23fd8b490 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLoRaDemodReport.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodReport.cpp @@ -11,7 +11,7 @@ */ -#include "SWGLoRaDemodReport.h" +#include "SWGChirpChatDemodReport.h" #include "SWGHelpers.h" @@ -22,12 +22,12 @@ namespace SWGSDRangel { -SWGLoRaDemodReport::SWGLoRaDemodReport(QString* json) { +SWGChirpChatDemodReport::SWGChirpChatDemodReport(QString* json) { init(); this->fromJson(*json); } -SWGLoRaDemodReport::SWGLoRaDemodReport() { +SWGChirpChatDemodReport::SWGChirpChatDemodReport() { channel_power_db = 0.0f; m_channel_power_db_isSet = false; noise_power_db = 0.0f; @@ -66,12 +66,12 @@ SWGLoRaDemodReport::SWGLoRaDemodReport() { m_message_bytes_isSet = false; } -SWGLoRaDemodReport::~SWGLoRaDemodReport() { +SWGChirpChatDemodReport::~SWGChirpChatDemodReport() { this->cleanup(); } void -SWGLoRaDemodReport::init() { +SWGChirpChatDemodReport::init() { channel_power_db = 0.0f; m_channel_power_db_isSet = false; noise_power_db = 0.0f; @@ -111,7 +111,7 @@ SWGLoRaDemodReport::init() { } void -SWGLoRaDemodReport::cleanup() { +SWGChirpChatDemodReport::cleanup() { @@ -142,8 +142,8 @@ SWGLoRaDemodReport::cleanup() { } } -SWGLoRaDemodReport* -SWGLoRaDemodReport::fromJson(QString &json) { +SWGChirpChatDemodReport* +SWGChirpChatDemodReport::fromJson(QString &json) { QByteArray array (json.toStdString().c_str()); QJsonDocument doc = QJsonDocument::fromJson(array); QJsonObject jsonObject = doc.object(); @@ -152,7 +152,7 @@ SWGLoRaDemodReport::fromJson(QString &json) { } void -SWGLoRaDemodReport::fromJsonObject(QJsonObject &pJson) { +SWGChirpChatDemodReport::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&channel_power_db, pJson["channelPowerDB"], "float", ""); ::SWGSDRangel::setValue(&noise_power_db, pJson["noisePowerDB"], "float", ""); @@ -192,7 +192,7 @@ SWGLoRaDemodReport::fromJsonObject(QJsonObject &pJson) { } QString -SWGLoRaDemodReport::asJson () +SWGChirpChatDemodReport::asJson () { QJsonObject* obj = this->asJsonObject(); @@ -203,7 +203,7 @@ SWGLoRaDemodReport::asJson () } QJsonObject* -SWGLoRaDemodReport::asJsonObject() { +SWGChirpChatDemodReport::asJsonObject() { QJsonObject* obj = new QJsonObject(); if(m_channel_power_db_isSet){ obj->insert("channelPowerDB", QJsonValue(channel_power_db)); @@ -264,188 +264,188 @@ SWGLoRaDemodReport::asJsonObject() { } float -SWGLoRaDemodReport::getChannelPowerDb() { +SWGChirpChatDemodReport::getChannelPowerDb() { return channel_power_db; } void -SWGLoRaDemodReport::setChannelPowerDb(float channel_power_db) { +SWGChirpChatDemodReport::setChannelPowerDb(float channel_power_db) { this->channel_power_db = channel_power_db; this->m_channel_power_db_isSet = true; } float -SWGLoRaDemodReport::getNoisePowerDb() { +SWGChirpChatDemodReport::getNoisePowerDb() { return noise_power_db; } void -SWGLoRaDemodReport::setNoisePowerDb(float noise_power_db) { +SWGChirpChatDemodReport::setNoisePowerDb(float noise_power_db) { this->noise_power_db = noise_power_db; this->m_noise_power_db_isSet = true; } float -SWGLoRaDemodReport::getSignalPowerDb() { +SWGChirpChatDemodReport::getSignalPowerDb() { return signal_power_db; } void -SWGLoRaDemodReport::setSignalPowerDb(float signal_power_db) { +SWGChirpChatDemodReport::setSignalPowerDb(float signal_power_db) { this->signal_power_db = signal_power_db; this->m_signal_power_db_isSet = true; } float -SWGLoRaDemodReport::getSnrPowerDb() { +SWGChirpChatDemodReport::getSnrPowerDb() { return snr_power_db; } void -SWGLoRaDemodReport::setSnrPowerDb(float snr_power_db) { +SWGChirpChatDemodReport::setSnrPowerDb(float snr_power_db) { this->snr_power_db = snr_power_db; this->m_snr_power_db_isSet = true; } qint32 -SWGLoRaDemodReport::getChannelSampleRate() { +SWGChirpChatDemodReport::getChannelSampleRate() { return channel_sample_rate; } void -SWGLoRaDemodReport::setChannelSampleRate(qint32 channel_sample_rate) { +SWGChirpChatDemodReport::setChannelSampleRate(qint32 channel_sample_rate) { this->channel_sample_rate = channel_sample_rate; this->m_channel_sample_rate_isSet = true; } qint32 -SWGLoRaDemodReport::getSyncWord() { +SWGChirpChatDemodReport::getSyncWord() { return sync_word; } void -SWGLoRaDemodReport::setSyncWord(qint32 sync_word) { +SWGChirpChatDemodReport::setSyncWord(qint32 sync_word) { this->sync_word = sync_word; this->m_sync_word_isSet = true; } qint32 -SWGLoRaDemodReport::getHasCrc() { +SWGChirpChatDemodReport::getHasCrc() { return has_crc; } void -SWGLoRaDemodReport::setHasCrc(qint32 has_crc) { +SWGChirpChatDemodReport::setHasCrc(qint32 has_crc) { this->has_crc = has_crc; this->m_has_crc_isSet = true; } qint32 -SWGLoRaDemodReport::getNbParityBits() { +SWGChirpChatDemodReport::getNbParityBits() { return nb_parity_bits; } void -SWGLoRaDemodReport::setNbParityBits(qint32 nb_parity_bits) { +SWGChirpChatDemodReport::setNbParityBits(qint32 nb_parity_bits) { this->nb_parity_bits = nb_parity_bits; this->m_nb_parity_bits_isSet = true; } qint32 -SWGLoRaDemodReport::getPacketLength() { +SWGChirpChatDemodReport::getPacketLength() { return packet_length; } void -SWGLoRaDemodReport::setPacketLength(qint32 packet_length) { +SWGChirpChatDemodReport::setPacketLength(qint32 packet_length) { this->packet_length = packet_length; this->m_packet_length_isSet = true; } qint32 -SWGLoRaDemodReport::getNbSymbols() { +SWGChirpChatDemodReport::getNbSymbols() { return nb_symbols; } void -SWGLoRaDemodReport::setNbSymbols(qint32 nb_symbols) { +SWGChirpChatDemodReport::setNbSymbols(qint32 nb_symbols) { this->nb_symbols = nb_symbols; this->m_nb_symbols_isSet = true; } qint32 -SWGLoRaDemodReport::getNbCodewords() { +SWGChirpChatDemodReport::getNbCodewords() { return nb_codewords; } void -SWGLoRaDemodReport::setNbCodewords(qint32 nb_codewords) { +SWGChirpChatDemodReport::setNbCodewords(qint32 nb_codewords) { this->nb_codewords = nb_codewords; this->m_nb_codewords_isSet = true; } qint32 -SWGLoRaDemodReport::getHeaderParityStatus() { +SWGChirpChatDemodReport::getHeaderParityStatus() { return header_parity_status; } void -SWGLoRaDemodReport::setHeaderParityStatus(qint32 header_parity_status) { +SWGChirpChatDemodReport::setHeaderParityStatus(qint32 header_parity_status) { this->header_parity_status = header_parity_status; this->m_header_parity_status_isSet = true; } qint32 -SWGLoRaDemodReport::getHeaderCrcStatus() { +SWGChirpChatDemodReport::getHeaderCrcStatus() { return header_crc_status; } void -SWGLoRaDemodReport::setHeaderCrcStatus(qint32 header_crc_status) { +SWGChirpChatDemodReport::setHeaderCrcStatus(qint32 header_crc_status) { this->header_crc_status = header_crc_status; this->m_header_crc_status_isSet = true; } qint32 -SWGLoRaDemodReport::getPayloadParityStatus() { +SWGChirpChatDemodReport::getPayloadParityStatus() { return payload_parity_status; } void -SWGLoRaDemodReport::setPayloadParityStatus(qint32 payload_parity_status) { +SWGChirpChatDemodReport::setPayloadParityStatus(qint32 payload_parity_status) { this->payload_parity_status = payload_parity_status; this->m_payload_parity_status_isSet = true; } qint32 -SWGLoRaDemodReport::getPayloadCrcStatus() { +SWGChirpChatDemodReport::getPayloadCrcStatus() { return payload_crc_status; } void -SWGLoRaDemodReport::setPayloadCrcStatus(qint32 payload_crc_status) { +SWGChirpChatDemodReport::setPayloadCrcStatus(qint32 payload_crc_status) { this->payload_crc_status = payload_crc_status; this->m_payload_crc_status_isSet = true; } QString* -SWGLoRaDemodReport::getMessageTimestamp() { +SWGChirpChatDemodReport::getMessageTimestamp() { return message_timestamp; } void -SWGLoRaDemodReport::setMessageTimestamp(QString* message_timestamp) { +SWGChirpChatDemodReport::setMessageTimestamp(QString* message_timestamp) { this->message_timestamp = message_timestamp; this->m_message_timestamp_isSet = true; } QString* -SWGLoRaDemodReport::getMessageString() { +SWGChirpChatDemodReport::getMessageString() { return message_string; } void -SWGLoRaDemodReport::setMessageString(QString* message_string) { +SWGChirpChatDemodReport::setMessageString(QString* message_string) { this->message_string = message_string; this->m_message_string_isSet = true; } QList* -SWGLoRaDemodReport::getMessageBytes() { +SWGChirpChatDemodReport::getMessageBytes() { return message_bytes; } void -SWGLoRaDemodReport::setMessageBytes(QList* message_bytes) { +SWGChirpChatDemodReport::setMessageBytes(QList* message_bytes) { this->message_bytes = message_bytes; this->m_message_bytes_isSet = true; } bool -SWGLoRaDemodReport::isSet(){ +SWGChirpChatDemodReport::isSet(){ bool isObjectUpdated = false; do{ if(m_channel_power_db_isSet){ diff --git a/swagger/sdrangel/code/qt5/client/SWGLoRaDemodReport.h b/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodReport.h similarity index 91% rename from swagger/sdrangel/code/qt5/client/SWGLoRaDemodReport.h rename to swagger/sdrangel/code/qt5/client/SWGChirpChatDemodReport.h index e722c16f6..80aca73b6 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLoRaDemodReport.h +++ b/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodReport.h @@ -11,13 +11,13 @@ */ /* - * SWGLoRaDemodReport.h + * SWGChirpChatDemodReport.h * - * LoRaDemod + * ChirpChatDemod */ -#ifndef SWGLoRaDemodReport_H_ -#define SWGLoRaDemodReport_H_ +#ifndef SWGChirpChatDemodReport_H_ +#define SWGChirpChatDemodReport_H_ #include @@ -30,18 +30,18 @@ namespace SWGSDRangel { -class SWG_API SWGLoRaDemodReport: public SWGObject { +class SWG_API SWGChirpChatDemodReport: public SWGObject { public: - SWGLoRaDemodReport(); - SWGLoRaDemodReport(QString* json); - virtual ~SWGLoRaDemodReport(); + SWGChirpChatDemodReport(); + SWGChirpChatDemodReport(QString* json); + virtual ~SWGChirpChatDemodReport(); void init(); void cleanup(); virtual QString asJson () override; virtual QJsonObject* asJsonObject() override; virtual void fromJsonObject(QJsonObject &json) override; - virtual SWGLoRaDemodReport* fromJson(QString &jsonString) override; + virtual SWGChirpChatDemodReport* fromJson(QString &jsonString) override; float getChannelPowerDb(); void setChannelPowerDb(float channel_power_db); @@ -159,4 +159,4 @@ private: } -#endif /* SWGLoRaDemodReport_H_ */ +#endif /* SWGChirpChatDemodReport_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGLoRaDemodSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodSettings.cpp similarity index 82% rename from swagger/sdrangel/code/qt5/client/SWGLoRaDemodSettings.cpp rename to swagger/sdrangel/code/qt5/client/SWGChirpChatDemodSettings.cpp index 419390cfa..8e83be20b 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLoRaDemodSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodSettings.cpp @@ -11,7 +11,7 @@ */ -#include "SWGLoRaDemodSettings.h" +#include "SWGChirpChatDemodSettings.h" #include "SWGHelpers.h" @@ -22,12 +22,12 @@ namespace SWGSDRangel { -SWGLoRaDemodSettings::SWGLoRaDemodSettings(QString* json) { +SWGChirpChatDemodSettings::SWGChirpChatDemodSettings(QString* json) { init(); this->fromJson(*json); } -SWGLoRaDemodSettings::SWGLoRaDemodSettings() { +SWGChirpChatDemodSettings::SWGChirpChatDemodSettings() { input_frequency_offset = 0L; m_input_frequency_offset_isSet = false; bandwidth_index = 0; @@ -80,12 +80,12 @@ SWGLoRaDemodSettings::SWGLoRaDemodSettings() { m_reverse_api_channel_index_isSet = false; } -SWGLoRaDemodSettings::~SWGLoRaDemodSettings() { +SWGChirpChatDemodSettings::~SWGChirpChatDemodSettings() { this->cleanup(); } void -SWGLoRaDemodSettings::init() { +SWGChirpChatDemodSettings::init() { input_frequency_offset = 0L; m_input_frequency_offset_isSet = false; bandwidth_index = 0; @@ -139,7 +139,7 @@ SWGLoRaDemodSettings::init() { } void -SWGLoRaDemodSettings::cleanup() { +SWGChirpChatDemodSettings::cleanup() { @@ -173,8 +173,8 @@ SWGLoRaDemodSettings::cleanup() { } -SWGLoRaDemodSettings* -SWGLoRaDemodSettings::fromJson(QString &json) { +SWGChirpChatDemodSettings* +SWGChirpChatDemodSettings::fromJson(QString &json) { QByteArray array (json.toStdString().c_str()); QJsonDocument doc = QJsonDocument::fromJson(array); QJsonObject jsonObject = doc.object(); @@ -183,7 +183,7 @@ SWGLoRaDemodSettings::fromJson(QString &json) { } void -SWGLoRaDemodSettings::fromJsonObject(QJsonObject &pJson) { +SWGChirpChatDemodSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&input_frequency_offset, pJson["inputFrequencyOffset"], "qint64", ""); ::SWGSDRangel::setValue(&bandwidth_index, pJson["bandwidthIndex"], "qint32", ""); @@ -237,7 +237,7 @@ SWGLoRaDemodSettings::fromJsonObject(QJsonObject &pJson) { } QString -SWGLoRaDemodSettings::asJson () +SWGChirpChatDemodSettings::asJson () { QJsonObject* obj = this->asJsonObject(); @@ -248,7 +248,7 @@ SWGLoRaDemodSettings::asJson () } QJsonObject* -SWGLoRaDemodSettings::asJsonObject() { +SWGChirpChatDemodSettings::asJsonObject() { QJsonObject* obj = new QJsonObject(); if(m_input_frequency_offset_isSet){ obj->insert("inputFrequencyOffset", QJsonValue(input_frequency_offset)); @@ -330,258 +330,258 @@ SWGLoRaDemodSettings::asJsonObject() { } qint64 -SWGLoRaDemodSettings::getInputFrequencyOffset() { +SWGChirpChatDemodSettings::getInputFrequencyOffset() { return input_frequency_offset; } void -SWGLoRaDemodSettings::setInputFrequencyOffset(qint64 input_frequency_offset) { +SWGChirpChatDemodSettings::setInputFrequencyOffset(qint64 input_frequency_offset) { this->input_frequency_offset = input_frequency_offset; this->m_input_frequency_offset_isSet = true; } qint32 -SWGLoRaDemodSettings::getBandwidthIndex() { +SWGChirpChatDemodSettings::getBandwidthIndex() { return bandwidth_index; } void -SWGLoRaDemodSettings::setBandwidthIndex(qint32 bandwidth_index) { +SWGChirpChatDemodSettings::setBandwidthIndex(qint32 bandwidth_index) { this->bandwidth_index = bandwidth_index; this->m_bandwidth_index_isSet = true; } qint32 -SWGLoRaDemodSettings::getSpreadFactor() { +SWGChirpChatDemodSettings::getSpreadFactor() { return spread_factor; } void -SWGLoRaDemodSettings::setSpreadFactor(qint32 spread_factor) { +SWGChirpChatDemodSettings::setSpreadFactor(qint32 spread_factor) { this->spread_factor = spread_factor; this->m_spread_factor_isSet = true; } qint32 -SWGLoRaDemodSettings::getDeBits() { +SWGChirpChatDemodSettings::getDeBits() { return de_bits; } void -SWGLoRaDemodSettings::setDeBits(qint32 de_bits) { +SWGChirpChatDemodSettings::setDeBits(qint32 de_bits) { this->de_bits = de_bits; this->m_de_bits_isSet = true; } qint32 -SWGLoRaDemodSettings::getCodingScheme() { +SWGChirpChatDemodSettings::getCodingScheme() { return coding_scheme; } void -SWGLoRaDemodSettings::setCodingScheme(qint32 coding_scheme) { +SWGChirpChatDemodSettings::setCodingScheme(qint32 coding_scheme) { this->coding_scheme = coding_scheme; this->m_coding_scheme_isSet = true; } qint32 -SWGLoRaDemodSettings::getDecodeActive() { +SWGChirpChatDemodSettings::getDecodeActive() { return decode_active; } void -SWGLoRaDemodSettings::setDecodeActive(qint32 decode_active) { +SWGChirpChatDemodSettings::setDecodeActive(qint32 decode_active) { this->decode_active = decode_active; this->m_decode_active_isSet = true; } qint32 -SWGLoRaDemodSettings::getEomSquelchTenths() { +SWGChirpChatDemodSettings::getEomSquelchTenths() { return eom_squelch_tenths; } void -SWGLoRaDemodSettings::setEomSquelchTenths(qint32 eom_squelch_tenths) { +SWGChirpChatDemodSettings::setEomSquelchTenths(qint32 eom_squelch_tenths) { this->eom_squelch_tenths = eom_squelch_tenths; this->m_eom_squelch_tenths_isSet = true; } qint32 -SWGLoRaDemodSettings::getNbSymbolsMax() { +SWGChirpChatDemodSettings::getNbSymbolsMax() { return nb_symbols_max; } void -SWGLoRaDemodSettings::setNbSymbolsMax(qint32 nb_symbols_max) { +SWGChirpChatDemodSettings::setNbSymbolsMax(qint32 nb_symbols_max) { this->nb_symbols_max = nb_symbols_max; this->m_nb_symbols_max_isSet = true; } qint32 -SWGLoRaDemodSettings::getAutoNbSymbolsMax() { +SWGChirpChatDemodSettings::getAutoNbSymbolsMax() { return auto_nb_symbols_max; } void -SWGLoRaDemodSettings::setAutoNbSymbolsMax(qint32 auto_nb_symbols_max) { +SWGChirpChatDemodSettings::setAutoNbSymbolsMax(qint32 auto_nb_symbols_max) { this->auto_nb_symbols_max = auto_nb_symbols_max; this->m_auto_nb_symbols_max_isSet = true; } qint32 -SWGLoRaDemodSettings::getPreambleChirps() { +SWGChirpChatDemodSettings::getPreambleChirps() { return preamble_chirps; } void -SWGLoRaDemodSettings::setPreambleChirps(qint32 preamble_chirps) { +SWGChirpChatDemodSettings::setPreambleChirps(qint32 preamble_chirps) { this->preamble_chirps = preamble_chirps; this->m_preamble_chirps_isSet = true; } qint32 -SWGLoRaDemodSettings::getNbParityBits() { +SWGChirpChatDemodSettings::getNbParityBits() { return nb_parity_bits; } void -SWGLoRaDemodSettings::setNbParityBits(qint32 nb_parity_bits) { +SWGChirpChatDemodSettings::setNbParityBits(qint32 nb_parity_bits) { this->nb_parity_bits = nb_parity_bits; this->m_nb_parity_bits_isSet = true; } qint32 -SWGLoRaDemodSettings::getPacketLength() { +SWGChirpChatDemodSettings::getPacketLength() { return packet_length; } void -SWGLoRaDemodSettings::setPacketLength(qint32 packet_length) { +SWGChirpChatDemodSettings::setPacketLength(qint32 packet_length) { this->packet_length = packet_length; this->m_packet_length_isSet = true; } qint32 -SWGLoRaDemodSettings::getHasCrc() { +SWGChirpChatDemodSettings::getHasCrc() { return has_crc; } void -SWGLoRaDemodSettings::setHasCrc(qint32 has_crc) { +SWGChirpChatDemodSettings::setHasCrc(qint32 has_crc) { this->has_crc = has_crc; this->m_has_crc_isSet = true; } qint32 -SWGLoRaDemodSettings::getHasHeader() { +SWGChirpChatDemodSettings::getHasHeader() { return has_header; } void -SWGLoRaDemodSettings::setHasHeader(qint32 has_header) { +SWGChirpChatDemodSettings::setHasHeader(qint32 has_header) { this->has_header = has_header; this->m_has_header_isSet = true; } qint32 -SWGLoRaDemodSettings::getSendViaUdp() { +SWGChirpChatDemodSettings::getSendViaUdp() { return send_via_udp; } void -SWGLoRaDemodSettings::setSendViaUdp(qint32 send_via_udp) { +SWGChirpChatDemodSettings::setSendViaUdp(qint32 send_via_udp) { this->send_via_udp = send_via_udp; this->m_send_via_udp_isSet = true; } QString* -SWGLoRaDemodSettings::getUdpAddress() { +SWGChirpChatDemodSettings::getUdpAddress() { return udp_address; } void -SWGLoRaDemodSettings::setUdpAddress(QString* udp_address) { +SWGChirpChatDemodSettings::setUdpAddress(QString* udp_address) { this->udp_address = udp_address; this->m_udp_address_isSet = true; } qint32 -SWGLoRaDemodSettings::getUdpPort() { +SWGChirpChatDemodSettings::getUdpPort() { return udp_port; } void -SWGLoRaDemodSettings::setUdpPort(qint32 udp_port) { +SWGChirpChatDemodSettings::setUdpPort(qint32 udp_port) { this->udp_port = udp_port; this->m_udp_port_isSet = true; } qint32 -SWGLoRaDemodSettings::getRgbColor() { +SWGChirpChatDemodSettings::getRgbColor() { return rgb_color; } void -SWGLoRaDemodSettings::setRgbColor(qint32 rgb_color) { +SWGChirpChatDemodSettings::setRgbColor(qint32 rgb_color) { this->rgb_color = rgb_color; this->m_rgb_color_isSet = true; } QString* -SWGLoRaDemodSettings::getTitle() { +SWGChirpChatDemodSettings::getTitle() { return title; } void -SWGLoRaDemodSettings::setTitle(QString* title) { +SWGChirpChatDemodSettings::setTitle(QString* title) { this->title = title; this->m_title_isSet = true; } qint32 -SWGLoRaDemodSettings::getStreamIndex() { +SWGChirpChatDemodSettings::getStreamIndex() { return stream_index; } void -SWGLoRaDemodSettings::setStreamIndex(qint32 stream_index) { +SWGChirpChatDemodSettings::setStreamIndex(qint32 stream_index) { this->stream_index = stream_index; this->m_stream_index_isSet = true; } qint32 -SWGLoRaDemodSettings::getUseReverseApi() { +SWGChirpChatDemodSettings::getUseReverseApi() { return use_reverse_api; } void -SWGLoRaDemodSettings::setUseReverseApi(qint32 use_reverse_api) { +SWGChirpChatDemodSettings::setUseReverseApi(qint32 use_reverse_api) { this->use_reverse_api = use_reverse_api; this->m_use_reverse_api_isSet = true; } QString* -SWGLoRaDemodSettings::getReverseApiAddress() { +SWGChirpChatDemodSettings::getReverseApiAddress() { return reverse_api_address; } void -SWGLoRaDemodSettings::setReverseApiAddress(QString* reverse_api_address) { +SWGChirpChatDemodSettings::setReverseApiAddress(QString* reverse_api_address) { this->reverse_api_address = reverse_api_address; this->m_reverse_api_address_isSet = true; } qint32 -SWGLoRaDemodSettings::getReverseApiPort() { +SWGChirpChatDemodSettings::getReverseApiPort() { return reverse_api_port; } void -SWGLoRaDemodSettings::setReverseApiPort(qint32 reverse_api_port) { +SWGChirpChatDemodSettings::setReverseApiPort(qint32 reverse_api_port) { this->reverse_api_port = reverse_api_port; this->m_reverse_api_port_isSet = true; } qint32 -SWGLoRaDemodSettings::getReverseApiDeviceIndex() { +SWGChirpChatDemodSettings::getReverseApiDeviceIndex() { return reverse_api_device_index; } void -SWGLoRaDemodSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) { +SWGChirpChatDemodSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) { this->reverse_api_device_index = reverse_api_device_index; this->m_reverse_api_device_index_isSet = true; } qint32 -SWGLoRaDemodSettings::getReverseApiChannelIndex() { +SWGChirpChatDemodSettings::getReverseApiChannelIndex() { return reverse_api_channel_index; } void -SWGLoRaDemodSettings::setReverseApiChannelIndex(qint32 reverse_api_channel_index) { +SWGChirpChatDemodSettings::setReverseApiChannelIndex(qint32 reverse_api_channel_index) { this->reverse_api_channel_index = reverse_api_channel_index; this->m_reverse_api_channel_index_isSet = true; } bool -SWGLoRaDemodSettings::isSet(){ +SWGChirpChatDemodSettings::isSet(){ bool isObjectUpdated = false; do{ if(m_input_frequency_offset_isSet){ diff --git a/swagger/sdrangel/code/qt5/client/SWGLoRaDemodSettings.h b/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodSettings.h similarity index 92% rename from swagger/sdrangel/code/qt5/client/SWGLoRaDemodSettings.h rename to swagger/sdrangel/code/qt5/client/SWGChirpChatDemodSettings.h index fb3a36e28..8fc74cb27 100644 --- a/swagger/sdrangel/code/qt5/client/SWGLoRaDemodSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodSettings.h @@ -11,13 +11,13 @@ */ /* - * SWGLoRaDemodSettings.h + * SWGChirpChatDemodSettings.h * - * LoRaDemod + * ChirpChatDemod */ -#ifndef SWGLoRaDemodSettings_H_ -#define SWGLoRaDemodSettings_H_ +#ifndef SWGChirpChatDemodSettings_H_ +#define SWGChirpChatDemodSettings_H_ #include @@ -29,18 +29,18 @@ namespace SWGSDRangel { -class SWG_API SWGLoRaDemodSettings: public SWGObject { +class SWG_API SWGChirpChatDemodSettings: public SWGObject { public: - SWGLoRaDemodSettings(); - SWGLoRaDemodSettings(QString* json); - virtual ~SWGLoRaDemodSettings(); + SWGChirpChatDemodSettings(); + SWGChirpChatDemodSettings(QString* json); + virtual ~SWGChirpChatDemodSettings(); void init(); void cleanup(); virtual QString asJson () override; virtual QJsonObject* asJsonObject() override; virtual void fromJsonObject(QJsonObject &json) override; - virtual SWGLoRaDemodSettings* fromJson(QString &jsonString) override; + virtual SWGChirpChatDemodSettings* fromJson(QString &jsonString) override; qint64 getInputFrequencyOffset(); void setInputFrequencyOffset(qint64 input_frequency_offset); @@ -200,4 +200,4 @@ private: } -#endif /* SWGLoRaDemodSettings_H_ */ +#endif /* SWGChirpChatDemodSettings_H_ */ diff --git a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h index f6cc4b579..abf2db718 100644 --- a/swagger/sdrangel/code/qt5/client/SWGModelFactory.h +++ b/swagger/sdrangel/code/qt5/client/SWGModelFactory.h @@ -51,6 +51,8 @@ #include "SWGChannelReport.h" #include "SWGChannelSettings.h" #include "SWGChannelsDetail.h" +#include "SWGChirpChatDemodReport.h" +#include "SWGChirpChatDemodSettings.h" #include "SWGCommand.h" #include "SWGComplex.h" #include "SWGDATVDemodSettings.h" @@ -101,8 +103,6 @@ #include "SWGLimeSdrInputSettings.h" #include "SWGLimeSdrOutputReport.h" #include "SWGLimeSdrOutputSettings.h" -#include "SWGLoRaDemodReport.h" -#include "SWGLoRaDemodSettings.h" #include "SWGLoRaModReport.h" #include "SWGLoRaModSettings.h" #include "SWGLocalInputReport.h" @@ -293,6 +293,12 @@ namespace SWGSDRangel { if(QString("SWGChannelsDetail").compare(type) == 0) { return new SWGChannelsDetail(); } + if(QString("SWGChirpChatDemodReport").compare(type) == 0) { + return new SWGChirpChatDemodReport(); + } + if(QString("SWGChirpChatDemodSettings").compare(type) == 0) { + return new SWGChirpChatDemodSettings(); + } if(QString("SWGCommand").compare(type) == 0) { return new SWGCommand(); } @@ -443,12 +449,6 @@ namespace SWGSDRangel { if(QString("SWGLimeSdrOutputSettings").compare(type) == 0) { return new SWGLimeSdrOutputSettings(); } - if(QString("SWGLoRaDemodReport").compare(type) == 0) { - return new SWGLoRaDemodReport(); - } - if(QString("SWGLoRaDemodSettings").compare(type) == 0) { - return new SWGLoRaDemodSettings(); - } if(QString("SWGLoRaModReport").compare(type) == 0) { return new SWGLoRaModReport(); }