diff --git a/doc/img/ChirpChatDemod_plugin.png b/doc/img/ChirpChatDemod_plugin.png index b005db7b2..ac354518b 100644 Binary files a/doc/img/ChirpChatDemod_plugin.png and b/doc/img/ChirpChatDemod_plugin.png differ diff --git a/doc/img/ChirpChatDemod_plugin.xcf b/doc/img/ChirpChatDemod_plugin.xcf index e504be01f..fd8f6f1b8 100644 Binary files a/doc/img/ChirpChatDemod_plugin.xcf and b/doc/img/ChirpChatDemod_plugin.xcf differ diff --git a/doc/img/ChirpChatMod_plugin.png b/doc/img/ChirpChatMod_plugin.png index 2665e4873..bf6665ff2 100644 Binary files a/doc/img/ChirpChatMod_plugin.png and b/doc/img/ChirpChatMod_plugin.png differ diff --git a/doc/img/ChirpChatMod_plugin.xcf b/doc/img/ChirpChatMod_plugin.xcf index 7baf945be..65144d6be 100644 Binary files a/doc/img/ChirpChatMod_plugin.xcf and b/doc/img/ChirpChatMod_plugin.xcf differ diff --git a/plugins/channelrx/demodchirpchat/chirpchatdemod.cpp b/plugins/channelrx/demodchirpchat/chirpchatdemod.cpp index 38ad95c8f..f00ee2ea4 100644 --- a/plugins/channelrx/demodchirpchat/chirpchatdemod.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatdemod.cpp @@ -432,6 +432,14 @@ void ChirpChatDemod::applySettings(const ChirpChatDemodSettings& settings, bool << " m_sendViaUDP: " << settings.m_sendViaUDP << " m_udpAddress: " << settings.m_udpAddress << " m_udpPort: " << settings.m_udpPort + << " m_decodeActive: " << settings.m_decodeActive + << " m_eomSquelchTenths: " << settings.m_eomSquelchTenths + << " m_nbSymbolsMax: " << settings.m_nbSymbolsMax + << " m_preambleChirps: " << settings.m_preambleChirps + << " m_streamIndex: " << settings.m_streamIndex + << " m_useReverseAPI: " << settings.m_useReverseAPI + << " m_fftWindow: " << settings.m_fftWindow + << " m_invertRamps: " << settings.m_invertRamps << " m_rgbColor: " << settings.m_rgbColor << " m_title: " << settings.m_title << " force: " << force; @@ -533,6 +541,9 @@ void ChirpChatDemod::applySettings(const ChirpChatDemodSettings& settings, bool if ((settings.m_autoNbSymbolsMax != m_settings.m_autoNbSymbolsMax) || force) { reverseAPIKeys.append("autoNbSymbolsMax"); } + if ((settings.m_invertRamps != m_settings.m_invertRamps) || force) { + reverseAPIKeys.append("invertRamps"); + } if ((settings.m_udpAddress != m_settings.m_udpAddress) || force) { @@ -694,6 +705,9 @@ void ChirpChatDemod::webapiUpdateChannelSettings( uint16_t port = response.getChirpChatDemodSettings()->getUdpPort(); settings.m_udpPort = port < 1024 ? 1024 : port; } + if (channelSettingsKeys.contains("invertRamps")) { + settings.m_invertRamps = response.getChirpChatDemodSettings()->getInvertRamps() != 0; + } if (channelSettingsKeys.contains("rgbColor")) { settings.m_rgbColor = response.getChirpChatDemodSettings()->getRgbColor(); } @@ -757,6 +771,7 @@ void ChirpChatDemod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings response.getChirpChatDemodSettings()->setHasCrc(settings.m_hasCRC ? 1 : 0); response.getChirpChatDemodSettings()->setHasHeader(settings.m_hasHeader ? 1 : 0); response.getChirpChatDemodSettings()->setSendViaUdp(settings.m_sendViaUDP ? 1 : 0); + response.getChirpChatDemodSettings()->setInvertRamps(settings.m_invertRamps ? 1 : 0); if (response.getChirpChatDemodSettings()->getUdpAddress()) { *response.getChirpChatDemodSettings()->getUdpAddress() = settings.m_udpAddress; @@ -978,6 +993,9 @@ void ChirpChatDemod::webapiFormatChannelSettings( if (channelSettingsKeys.contains("updPort") || force) { swgChirpChatDemodSettings->setUdpPort(settings.m_udpPort); } + if (channelSettingsKeys.contains("invertRamps") || force) { + swgChirpChatDemodSettings->setInvertRamps(settings.m_invertRamps ? 1 : 0); + } if (channelSettingsKeys.contains("rgbColor") || force) { swgChirpChatDemodSettings->setRgbColor(settings.m_rgbColor); } diff --git a/plugins/channelrx/demodchirpchat/chirpchatdemodgui.cpp b/plugins/channelrx/demodchirpchat/chirpchatdemodgui.cpp index ceaada06e..0d4ce30a6 100644 --- a/plugins/channelrx/demodchirpchat/chirpchatdemodgui.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodgui.cpp @@ -338,6 +338,12 @@ void ChirpChatDemodGUI::on_udpPort_editingFinished() applySettings(); } +void ChirpChatDemodGUI::on_invertRamps_stateChanged(int state) +{ + m_settings.m_invertRamps = (state == Qt::Checked); + applySettings(); +} + void ChirpChatDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) { (void) widget; @@ -529,6 +535,7 @@ void ChirpChatDemodGUI::displaySettings() } ui->messageLengthAuto->setChecked(m_settings.m_autoNbSymbolsMax); + ui->invertRamps->setChecked(m_settings.m_invertRamps); displaySquelch(); updateIndexLabel(); @@ -854,6 +861,7 @@ void ChirpChatDemodGUI::makeUIConnections() QObject::connect(ui->udpSend, &QCheckBox::stateChanged, this, &ChirpChatDemodGUI::on_udpSend_stateChanged); QObject::connect(ui->udpAddress, &QLineEdit::editingFinished, this, &ChirpChatDemodGUI::on_udpAddress_editingFinished); QObject::connect(ui->udpPort, &QLineEdit::editingFinished, this, &ChirpChatDemodGUI::on_udpPort_editingFinished); + QObject::connect(ui->invertRamps, &QCheckBox::stateChanged, this, &ChirpChatDemodGUI::on_invertRamps_stateChanged); } void ChirpChatDemodGUI::updateAbsoluteCenterFrequency() diff --git a/plugins/channelrx/demodchirpchat/chirpchatdemodgui.h b/plugins/channelrx/demodchirpchat/chirpchatdemodgui.h index 277ae430c..0d3830158 100644 --- a/plugins/channelrx/demodchirpchat/chirpchatdemodgui.h +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodgui.h @@ -82,6 +82,7 @@ private slots: void on_udpSend_stateChanged(int state); void on_udpAddress_editingFinished(); void on_udpPort_editingFinished(); + void on_invertRamps_stateChanged(int state); void onWidgetRolled(QWidget* widget, bool rollDown); void onMenuDialogCalled(const QPoint& p); void channelMarkerHighlightedByCursor(); diff --git a/plugins/channelrx/demodchirpchat/chirpchatdemodgui.ui b/plugins/channelrx/demodchirpchat/chirpchatdemodgui.ui index d750cc76d..17534c6d3 100644 --- a/plugins/channelrx/demodchirpchat/chirpchatdemodgui.ui +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodgui.ui @@ -526,6 +526,23 @@ + + + + Qt::Vertical + + + + + + + Invert preamble, SFD and payload ramps + + + Inv + + + diff --git a/plugins/channelrx/demodchirpchat/chirpchatdemodsettings.cpp b/plugins/channelrx/demodchirpchat/chirpchatdemodsettings.cpp index 0c6a95dc5..fec2de46b 100644 --- a/plugins/channelrx/demodchirpchat/chirpchatdemodsettings.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodsettings.cpp @@ -80,6 +80,7 @@ void ChirpChatDemodSettings::resetToDefaults() m_hasCRC = true; m_hasHeader = true; m_sendViaUDP = false; + m_invertRamps = false; m_udpAddress = "127.0.0.1"; m_udpPort = 9999; m_rgbColor = QColor(255, 0, 255).rgb(); @@ -121,6 +122,7 @@ QByteArray ChirpChatDemodSettings::serialize() const s.writeBool(15, m_hasHeader); s.writeU32(17, m_preambleChirps); s.writeS32(18, (int) m_fftWindow); + s.writeBool(19, m_invertRamps); s.writeBool(20, m_useReverseAPI); s.writeString(21, m_reverseAPIAddress); s.writeU32(22, m_reverseAPIPort); @@ -188,6 +190,7 @@ bool ChirpChatDemodSettings::deserialize(const QByteArray& data) d.readU32(17, &m_preambleChirps, 8); d.readS32(18, &tmp, (int) FFTWindow::Rectangle); m_fftWindow = (FFTWindow::Function) tmp; + d.readBool(19, &m_invertRamps, false); d.readBool(20, &m_useReverseAPI, false); d.readString(21, &m_reverseAPIAddress, "127.0.0.1"); d.readU32(22, &utmp, 0); @@ -232,6 +235,113 @@ bool ChirpChatDemodSettings::deserialize(const QByteArray& data) } } +void ChirpChatDemodSettings::applySettings(const QStringList& settingsKeys, const ChirpChatDemodSettings& settings) +{ + if (settingsKeys.contains("inputFrequencyOffset")) + m_inputFrequencyOffset = settings.m_inputFrequencyOffset; + if (settingsKeys.contains("bandwidthIndex")) + m_bandwidthIndex = settings.m_bandwidthIndex; + if (settingsKeys.contains("spreadFactor")) + m_spreadFactor = settings.m_spreadFactor; + if (settingsKeys.contains("deBits")) + m_deBits = settings.m_deBits; + if (settingsKeys.contains("fftWindow")) + m_fftWindow = settings.m_fftWindow; + if (settingsKeys.contains("codingScheme")) + m_codingScheme = settings.m_codingScheme; + if (settingsKeys.contains("decodeActive")) + m_decodeActive = settings.m_decodeActive; + if (settingsKeys.contains("eomSquelchTenths")) + m_eomSquelchTenths = settings.m_eomSquelchTenths; + if (settingsKeys.contains("nbSymbolsMax")) + m_nbSymbolsMax = settings.m_nbSymbolsMax; + if (settingsKeys.contains("preambleChirps")) + m_preambleChirps = settings.m_preambleChirps; + if (settingsKeys.contains("nbParityBits")) + m_nbParityBits = settings.m_nbParityBits; + if (settingsKeys.contains("packetLength")) + m_packetLength = settings.m_packetLength; + if (settingsKeys.contains("hasCRC")) + m_hasCRC = settings.m_hasCRC; + if (settingsKeys.contains("hasHeader")) + m_hasHeader = settings.m_hasHeader; + if (settingsKeys.contains("sendViaUDP")) + m_sendViaUDP = settings.m_sendViaUDP; + if (settingsKeys.contains("invertRamps")) + m_invertRamps = settings.m_invertRamps; + if (settingsKeys.contains("udpAddress")) + m_udpAddress = settings.m_udpAddress; + if (settingsKeys.contains("udpPort")) + m_udpPort = settings.m_udpPort; + if (settingsKeys.contains("useReverseAPI")) + m_useReverseAPI = settings.m_useReverseAPI; + if (settingsKeys.contains("reverseAPIAddress")) + m_reverseAPIAddress = settings.m_reverseAPIAddress; + if (settingsKeys.contains("reverseAPIPort")) + m_reverseAPIPort = settings.m_reverseAPIPort; + if (settingsKeys.contains("reverseAPIDeviceIndex")) + m_reverseAPIDeviceIndex = settings.m_reverseAPIDeviceIndex; + if (settingsKeys.contains("reverseAPIChannelIndex")) + m_reverseAPIChannelIndex = settings.m_reverseAPIChannelIndex; + if (settingsKeys.contains("streamIndex")) + m_streamIndex = settings.m_streamIndex; +} + +QString ChirpChatDemodSettings::getDebugString(const QStringList& settingsKeys, bool force) const +{ + QString debug; + + if (force || settingsKeys.contains("inputFrequencyOffset")) + debug += QString("InputFrequencyOffset: %1 ").arg(m_inputFrequencyOffset); + if (force || settingsKeys.contains("bandwidthIndex")) + debug += QString("BandwidthIndex: %1 ").arg(m_bandwidthIndex); + if (force || settingsKeys.contains("spreadFactor")) + debug += QString("SpreadFactor: %1 ").arg(m_spreadFactor); + if (force || settingsKeys.contains("deBits")) + debug += QString("DEBits: %1 ").arg(m_deBits); + if (force || settingsKeys.contains("fftWindow")) + debug += QString("FFTWindow: %1 ").arg((int) m_fftWindow); + if (force || settingsKeys.contains("codingScheme")) + debug += QString("CodingScheme: %1 ").arg((int) m_codingScheme); + if (force || settingsKeys.contains("decodeActive")) + debug += QString("DecodeActive: %1 ").arg(m_decodeActive); + if (force || settingsKeys.contains("eomSquelchTenths")) + debug += QString("EOMSquelchTenths: %1 ").arg(m_eomSquelchTenths); + if (force || settingsKeys.contains("nbSymbolsMax")) + debug += QString("NbSymbolsMax: %1 ").arg(m_nbSymbolsMax); + if (force || settingsKeys.contains("preambleChirps")) + debug += QString("PreambleChirps: %1 ").arg(m_preambleChirps); + if (force || settingsKeys.contains("nbParityBits")) + debug += QString("NbParityBits: %1 ").arg(m_nbParityBits); + if (force || settingsKeys.contains("packetLength")) + debug += QString("PacketLength: %1 ").arg(m_packetLength); + if (force || settingsKeys.contains("hasCRC")) + debug += QString("HasCRC: %1 ").arg(m_hasCRC); + if (force || settingsKeys.contains("hasHeader")) + debug += QString("HasHeader: %1 ").arg(m_hasHeader); + if (force || settingsKeys.contains("sendViaUDP")) + debug += QString("SendViaUDP: %1 ").arg(m_sendViaUDP); + if (force || settingsKeys.contains("invertRamps")) + debug += QString("InvertRamps: %1 ").arg(m_invertRamps); + if (force || settingsKeys.contains("udpAddress")) + debug += QString("UDPAddress: %1 ").arg(m_udpAddress); + if (force || settingsKeys.contains("udpPort")) + debug += QString("UDPPort: %1 ").arg(m_udpPort); + if (force || settingsKeys.contains("useReverseAPI")) + debug += QString("UseReverseAPI: %1 ").arg(m_useReverseAPI); + if (force || settingsKeys.contains("reverseAPIAddress")) + debug += QString("ReverseAPIAddress: %1 ").arg(m_reverseAPIAddress); + if (force || settingsKeys.contains("reverseAPIPort")) + debug += QString("ReverseAPIPort: %1 ").arg(m_reverseAPIPort); + if (force || settingsKeys.contains("reverseAPIDeviceIndex")) + debug += QString("ReverseAPIDeviceIndex: %1 ").arg(m_reverseAPIDeviceIndex); + if (force || settingsKeys.contains("reverseAPIChannelIndex")) + debug += QString("ReverseAPIChannelIndex: %1 ").arg(m_reverseAPIChannelIndex); + if (force || settingsKeys.contains("streamIndex")) + debug += QString("StreamIndex: %1 ").arg(m_streamIndex); + return debug; +} + unsigned int ChirpChatDemodSettings::getNbSFDFourths() const { switch (m_codingScheme) diff --git a/plugins/channelrx/demodchirpchat/chirpchatdemodsettings.h b/plugins/channelrx/demodchirpchat/chirpchatdemodsettings.h index 2f21bc48d..ea5c6fbff 100644 --- a/plugins/channelrx/demodchirpchat/chirpchatdemodsettings.h +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodsettings.h @@ -65,6 +65,7 @@ struct ChirpChatDemodSettings bool m_hasCRC; //!< Payload has CRC (LoRa) bool m_hasHeader; //!< Header present before actual payload (LoRa) bool m_sendViaUDP; //!< Send decoded message via UDP + bool m_invertRamps; //!< Invert chirp ramps vs standard LoRa (up/down/up is standard) QString m_udpAddress; //!< UDP address where to send message uint16_t m_udpPort; //!< UDP port where to send message uint32_t m_rgbColor; @@ -96,6 +97,8 @@ struct ChirpChatDemodSettings bool hasSyncWord() const; //!< Only LoRa has a syncword (for the moment) QByteArray serialize() const; bool deserialize(const QByteArray& data); + void applySettings(const QStringList& settingsKeys, const ChirpChatDemodSettings& settings); + QString getDebugString(const QStringList& settingsKeys, bool force=false) const; }; diff --git a/plugins/channelrx/demodchirpchat/chirpchatdemodsink.cpp b/plugins/channelrx/demodchirpchat/chirpchatdemodsink.cpp index 0c7c1ab85..2a56df3cf 100644 --- a/plugins/channelrx/demodchirpchat/chirpchatdemodsink.cpp +++ b/plugins/channelrx/demodchirpchat/chirpchatdemodsink.cpp @@ -158,7 +158,7 @@ void ChirpChatDemodSink::processSample(const Complex& ci) } else if (m_state == ChirpChatStateDetectPreamble) // look for preamble { - m_fft->in()[m_fftCounter++] = ci * m_downChirps[m_chirp]; // de-chirp the up ramp + m_fft->in()[m_fftCounter++] = ci * (m_settings.m_invertRamps ? m_upChirps[m_chirp] : m_downChirps[m_chirp]); // de-chirp the preamble ramp if (m_fftCounter == m_fftLength) { @@ -178,6 +178,11 @@ void ChirpChatDemodSink::processSample(const Complex& ci) m_fftInterpolation ) / m_fftInterpolation; + // When ramps are inverted, FFT output interpretation is reversed + if (m_settings.m_invertRamps) { + imax = (m_nbSymbols - imax) % m_nbSymbols; + } + if (m_magsqQueue.size() > m_settings.m_preambleChirps) { m_magsqQueue.pop(); } @@ -246,8 +251,8 @@ void ChirpChatDemodSink::processSample(const Complex& ci) } 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-chirp the down ramp + m_fft->in()[m_fftCounter] = ci * (m_settings.m_invertRamps ? m_upChirps[m_chirp] : m_downChirps[m_chirp]); // de-chirp the preamble ramp + m_fftSFD->in()[m_fftCounter] = ci * (m_settings.m_invertRamps ? m_downChirps[m_chirp] : m_upChirps[m_chirp]); // de-chirp the SFD ramp m_fftCounter++; if (m_fftCounter == m_fftLength) @@ -284,6 +289,11 @@ void ChirpChatDemodSink::processSample(const Complex& ci) m_fftInterpolation ) / m_fftInterpolation; + // When ramps are inverted, FFT output interpretation is reversed + if (m_settings.m_invertRamps) { + imax = (m_nbSymbols - imax) % m_nbSymbols; + } + m_preambleHistory[m_chirpCount] = imax; m_chirpCount++; double preDrop = magsqPre - magsqSFD; @@ -374,7 +384,7 @@ void ChirpChatDemodSink::processSample(const Complex& ci) } else if (m_state == ChirpChatStateReadPayload) { - m_fft->in()[m_fftCounter] = ci * m_downChirps[m_chirp]; // de-chirp the up ramp + m_fft->in()[m_fftCounter] = ci * (m_settings.m_invertRamps ? m_upChirps[m_chirp] : m_downChirps[m_chirp]); // de-chirp the payload ramp m_fftCounter++; if (m_fftCounter == m_fftLength) @@ -438,6 +448,11 @@ void ChirpChatDemodSink::processSample(const Complex& ci) ); } + // When ramps are inverted, FFT output interpretation is reversed + if (m_settings.m_invertRamps) { + imax = (m_nbSymbols * m_fftInterpolation - imax) % (m_nbSymbols * m_fftInterpolation); + } + symbol = evalSymbol(imax) % m_nbSymbolsEff; m_decodeMsg->pushBackSymbol(symbol); } diff --git a/plugins/channelrx/demodchirpchat/readme.md b/plugins/channelrx/demodchirpchat/readme.md index f1e8a2004..756c48673 100644 --- a/plugins/channelrx/demodchirpchat/readme.md +++ b/plugins/channelrx/demodchirpchat/readme.md @@ -120,6 +120,12 @@ In practice it is difficult to make correct decodes if only one FFT bin is used This is the number of chirps expected in the preamble and has to be agreed between the transmitter and receiver. +

15: Invert chirp ramps

+ +The LoRa standard is up-chirps for the preamble, down-chirps for the SFD and up-chirps for the payload. + +When you check this option it inverts the direction of the chirps thus becoming down-chirps for the preamble, up-chirps for the SFD and down-chirps for the payload. +

A: Payload controls and indicators

![ChirpChat Demodulator payload controls](../../../doc/img/ChirpChatDemod_payload.png) @@ -284,3 +290,43 @@ Controls are the usual controls of spectrum displays with the following restrict - The window type is non operating because the FFT window is chosen by (7) - The FFT size can be changed however it is set to 2SF where SF is the spread factor and thus displays correctly + + +

Common LoRa settings

+ +CR is the code rate and translates to FEC according to the following table + +| CR | FEC | +| --- | --- | +| 4/5 | 1 | +| 4/6 | 2 | +| 4/7 | 3 | +| 4/8 | 4 | + +When DE is on set DE to 2 else 0 + +

Generic

+ +| Use Case | SF | CR | BW (kHz) | DE Enabled? | Notes | +| --------------------- | --------- | ------- | -------- | ----------- | ----------------------------------------------------------- | +| High rate/short range | SF7 | 4/5 | 500 | Off | Fastest, urban/close devices | +| Balanced/general IoT | SF7–SF9 | 4/5–4/6 | 125–250 | Off | TTN default, good for gateways | +| Long range/rural | SF10–SF12 | 4/6–4/8 | 125 | On | Max sensitivity (-137 dBm), slow airtime | +| Extreme range | SF12 | 4/8 | 125 | On | Best for weak signals, long packets | + +

Meshtastic

+ +

Quick facts

+ + - Uses 0x2B sync byte + - In Europe the default channel is centered on 869.525 MHz + +

Presets table

+ +| Preset | SF | CR | BW (kHz) | DE? | Use Case | +| ------------------- | -- | ---- | -------- | --- | ---------------------------------------------------- | +| LONG_FAST (default) | 11 | 4/8 | 250 | On | Long range, moderate speed | +| MEDIUM_SLOW | 10 | 4/7 | 250 | On | Balanced range/reliability​ | +| SHORT_FAST | 9 | 4/7 | 250 | Off | Urban/short hops, faster​ | +| SHORT_TURBO | 7 | 4/5 | 500 | Off | Max speed, shortest range (region-limited)​ | +| LONG_SLOW | 12 | 4/8 | 125 | On | Extreme range, slowest meshtastic​ | diff --git a/plugins/channeltx/modchirpchat/chirpchatmod.cpp b/plugins/channeltx/modchirpchat/chirpchatmod.cpp index a8d74f9cf..7c6aa96d5 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmod.cpp +++ b/plugins/channeltx/modchirpchat/chirpchatmod.cpp @@ -186,6 +186,21 @@ void ChirpChatMod::applySettings(const ChirpChatModSettings& settings, bool forc << " m_73message: " << settings.m_73Message << " m_qsoTextMessage: " << settings.m_qsoTextMessage << " m_textMessage: " << settings.m_textMessage + << " m_bytesMessage: " << settings.m_bytesMessage.toHex() + << " m_spreadFactor: " << settings.m_spreadFactor + << " m_deBits: " << settings.m_deBits + << " m_codingScheme: " << settings.m_codingScheme + << " m_nbParityBits: " << settings.m_nbParityBits + << " m_hasCRC: " << settings.m_hasCRC + << " m_hasHeader: " << settings.m_hasHeader + << " m_messageType: " << settings.m_messageType + << " m_preambleChirps: " << settings.m_preambleChirps + << " m_quietMillis: " << settings.m_quietMillis + << " m_messageRepeat: " << settings.m_messageRepeat + << " m_udpEnabled: " << settings.m_udpEnabled + << " m_udpAddress: " << settings.m_udpAddress + << " m_udpPort: " << settings.m_udpPort + << " m_invertRamps: " << settings.m_invertRamps << " m_useReverseAPI: " << settings.m_useReverseAPI << " m_reverseAPIAddress: " << settings.m_reverseAPIAddress << " m_reverseAPIAddress: " << settings.m_reverseAPIPort @@ -273,6 +288,15 @@ void ChirpChatMod::applySettings(const ChirpChatModSettings& settings, bool forc if ((settings.m_bytesMessage != m_settings.m_bytesMessage) || force) { reverseAPIKeys.append("bytesMessage"); } + if ((settings.m_preambleChirps != m_settings.m_preambleChirps) || force) { + reverseAPIKeys.append("preambleChirps"); + } + if ((settings.m_quietMillis != m_settings.m_quietMillis) || force) { + reverseAPIKeys.append("quietMillis"); + } + if ((settings.m_invertRamps != m_settings.m_invertRamps) || force) { + reverseAPIKeys.append("invertRamps"); + } ChirpChatModBaseband::MsgConfigureChirpChatModPayload *payloadMsg = nullptr; std::vector symbols; @@ -552,6 +576,9 @@ void ChirpChatMod::webapiUpdateChannelSettings( if (channelSettingsKeys.contains("udpPort")) { settings.m_udpPort = response.getChirpChatModSettings()->getUdpPort(); } + if (channelSettingsKeys.contains("invertRamps")) { + settings.m_invertRamps = response.getChirpChatModSettings()->getInvertRamps(); + } if (channelSettingsKeys.contains("rgbColor")) { settings.m_rgbColor = response.getChirpChatModSettings()->getRgbColor(); } @@ -703,6 +730,7 @@ void ChirpChatMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response.getChirpChatModSettings()->setUdpEnabled(settings.m_udpEnabled); response.getChirpChatModSettings()->setUdpAddress(new QString(settings.m_udpAddress)); response.getChirpChatModSettings()->setUdpPort(settings.m_udpPort); + response.getChirpChatModSettings()->setInvertRamps(settings.m_invertRamps ? 1 : 0); response.getChirpChatModSettings()->setRgbColor(settings.m_rgbColor); @@ -935,6 +963,9 @@ void ChirpChatMod::webapiFormatChannelSettings( if (channelSettingsKeys.contains("udpPort") || force) { swgChirpChatModSettings->setUdpPort(settings.m_udpPort); } + if (channelSettingsKeys.contains("invertRamps") || force) { + swgChirpChatModSettings->setInvertRamps(settings.m_invertRamps ? 1 : 0); + } if (channelSettingsKeys.contains("rgbColor") || force) { swgChirpChatModSettings->setRgbColor(settings.m_rgbColor); diff --git a/plugins/channeltx/modchirpchat/chirpchatmodgui.cpp b/plugins/channeltx/modchirpchat/chirpchatmodgui.cpp index deb422120..07e2f0e07 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodgui.cpp +++ b/plugins/channeltx/modchirpchat/chirpchatmodgui.cpp @@ -359,6 +359,12 @@ void ChirpChatModGUI::on_udpPort_editingFinished() applySettings(); } +void ChirpChatModGUI::on_invertRamps_stateChanged(int state) +{ + m_settings.m_invertRamps = (state == Qt::Checked); + applySettings(); +} + void ChirpChatModGUI::onWidgetRolled(QWidget* widget, bool rollDown) { (void) widget; @@ -541,6 +547,7 @@ void ChirpChatModGUI::displaySettings() ui->udpEnabled->setChecked(m_settings.m_udpEnabled); ui->udpAddress->setText(m_settings.m_udpAddress); ui->udpPort->setText(QString::number(m_settings.m_udpPort)); + ui->invertRamps->setChecked(m_settings.m_invertRamps); getRollupContents()->restoreState(m_rollupState); updateAbsoluteCenterFrequency(); blockApplySettings(false); @@ -658,6 +665,7 @@ void ChirpChatModGUI::makeUIConnections() QObject::connect(ui->udpEnabled, &QCheckBox::clicked, this, &ChirpChatModGUI::on_udpEnabled_clicked); QObject::connect(ui->udpAddress, &QLineEdit::editingFinished, this, &ChirpChatModGUI::on_udpAddress_editingFinished); QObject::connect(ui->udpPort, &QLineEdit::editingFinished, this, &ChirpChatModGUI::on_udpPort_editingFinished); + QObject::connect(ui->invertRamps, &QCheckBox::stateChanged, this, &ChirpChatModGUI::on_invertRamps_stateChanged); } void ChirpChatModGUI::updateAbsoluteCenterFrequency() diff --git a/plugins/channeltx/modchirpchat/chirpchatmodgui.h b/plugins/channeltx/modchirpchat/chirpchatmodgui.h index 8e32a1022..8fecb7762 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodgui.h +++ b/plugins/channeltx/modchirpchat/chirpchatmodgui.h @@ -123,6 +123,7 @@ private slots: void on_udpEnabled_clicked(bool checked); void on_udpAddress_editingFinished(); void on_udpPort_editingFinished(); + void on_invertRamps_stateChanged(int state); void onWidgetRolled(QWidget* widget, bool rollDown); void onMenuDialogCalled(const QPoint& p); void tick(); diff --git a/plugins/channeltx/modchirpchat/chirpchatmodgui.ui b/plugins/channeltx/modchirpchat/chirpchatmodgui.ui index 333f0bba8..ebaee5883 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodgui.ui +++ b/plugins/channeltx/modchirpchat/chirpchatmodgui.ui @@ -215,6 +215,23 @@
+ + + + Qt::Vertical + + + + + + + Invert preamble, SFD and payload ramps + + + Inv + + + diff --git a/plugins/channeltx/modchirpchat/chirpchatmodsettings.cpp b/plugins/channeltx/modchirpchat/chirpchatmodsettings.cpp index 3b8a95a68..6e641172f 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodsettings.cpp +++ b/plugins/channeltx/modchirpchat/chirpchatmodsettings.cpp @@ -88,6 +88,7 @@ void ChirpChatModSettings::resetToDefaults() m_udpEnabled = false; m_udpAddress = "127.0.0.1"; m_udpPort = 9998; + m_invertRamps = false; m_rgbColor = QColor(255, 0, 255).rgb(); m_title = "ChirpChat Modulator"; m_streamIndex = 0; @@ -169,11 +170,7 @@ QByteArray ChirpChatModSettings::serialize() const s.writeU32(9, m_syncWord); s.writeU32(10, m_preambleChirps); s.writeS32(11, m_quietMillis); - s.writeBool(12, m_useReverseAPI); - s.writeString(13, m_reverseAPIAddress); - s.writeU32(14, m_reverseAPIPort); - s.writeU32(15, m_reverseAPIDeviceIndex); - s.writeU32(16, m_reverseAPIChannelIndex); + s.writeBool(12, m_invertRamps); s.writeString(20, m_beaconMessage); s.writeString(21, m_cqMessage); s.writeString(22, m_replyMessage); @@ -250,19 +247,7 @@ bool ChirpChatModSettings::deserialize(const QByteArray& data) d.readU32(10, &m_preambleChirps, 8); d.readS32(11, &m_quietMillis, 1000); d.readBool(11, &m_useReverseAPI, false); - d.readString(12, &m_reverseAPIAddress, "127.0.0.1"); - d.readU32(13, &utmp, 0); - - if ((utmp > 1023) && (utmp < 65535)) { - m_reverseAPIPort = utmp; - } else { - m_reverseAPIPort = 8888; - } - - d.readU32(14, &utmp, 0); - m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp; - d.readU32(15, &utmp, 0); - m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp; + d.readBool(12, &m_invertRamps, false); d.readString(20, &m_beaconMessage, "VVV DE %1 %2"); d.readString(21, &m_cqMessage, "CQ DE %1 %2"); d.readString(22, &m_replyMessage, "%2 %1 %3"); @@ -327,3 +312,181 @@ bool ChirpChatModSettings::deserialize(const QByteArray& data) return false; } } + +void ChirpChatModSettings::applySettings(const QStringList& settingsKeys, const ChirpChatModSettings& settings) +{ + if (settingsKeys.contains("inputFrequencyOffset")) + m_inputFrequencyOffset = settings.m_inputFrequencyOffset; + if (settingsKeys.contains("bandwidthIndex")) + m_bandwidthIndex = settings.m_bandwidthIndex; + if (settingsKeys.contains("spreadFactor")) + m_spreadFactor = settings.m_spreadFactor; + if (settingsKeys.contains("deBits")) + m_deBits = settings.m_deBits; + if (settingsKeys.contains("codingScheme")) + m_codingScheme = settings.m_codingScheme; + if (settingsKeys.contains("preambleChirps")) + m_preambleChirps = settings.m_preambleChirps; + if (settingsKeys.contains("quietMillis")) + m_quietMillis = settings.m_quietMillis; + if (settingsKeys.contains("invertRamps")) + m_invertRamps = settings.m_invertRamps; + if (settingsKeys.contains("syncWord")) + m_syncWord = settings.m_syncWord; + if (settingsKeys.contains("channelMute")) + m_channelMute = settings.m_channelMute; + if (settingsKeys.contains("title")) + m_title = settings.m_title; + if (settingsKeys.contains("udpEnabled")) + m_udpEnabled = settings.m_udpEnabled; + if (settingsKeys.contains("udpAddress")) + m_udpAddress = settings.m_udpAddress; + if (settingsKeys.contains("udpPort")) + m_udpPort = settings.m_udpPort; + if (settingsKeys.contains("streamIndex")) + m_streamIndex = settings.m_streamIndex; + if (settingsKeys.contains("useReverseAPI")) + m_useReverseAPI = settings.m_useReverseAPI; + if (settingsKeys.contains("reverseAPIAddress")) + m_reverseAPIAddress = settings.m_reverseAPIAddress; + if (settingsKeys.contains("reverseAPIPort")) + m_reverseAPIPort = settings.m_reverseAPIPort; + if (settingsKeys.contains("reverseAPIDeviceIndex")) + m_reverseAPIDeviceIndex = settings.m_reverseAPIDeviceIndex; + if (settingsKeys.contains("reverseAPIChannelIndex")) + m_reverseAPIChannelIndex = settings.m_reverseAPIChannelIndex; + if (settingsKeys.contains("workspaceIndex")) + m_workspaceIndex = settings.m_workspaceIndex; + if (settingsKeys.contains("geometryBytes")) + m_geometryBytes = settings.m_geometryBytes; + if (settingsKeys.contains("hidden")) + m_hidden = settings.m_hidden; + if (settingsKeys.contains("channelMarker") && m_channelMarker && settings.m_channelMarker) + m_channelMarker->deserialize(settings.m_channelMarker->serialize()); + if (settingsKeys.contains("rollupState") && m_rollupState && settings.m_rollupState) + m_rollupState->deserialize(settings.m_rollupState->serialize()); + if (settingsKeys.contains("beaconMessage")) + m_beaconMessage = settings.m_beaconMessage; + if (settingsKeys.contains("cqMessage")) + m_cqMessage = settings.m_cqMessage; + if (settingsKeys.contains("replyMessage")) + m_replyMessage = settings.m_replyMessage; + if (settingsKeys.contains("reportMessage")) + m_reportMessage = settings.m_reportMessage; + if (settingsKeys.contains("replyReportMessage")) + m_replyReportMessage = settings.m_replyReportMessage; + if (settingsKeys.contains("rrrMessage")) + m_rrrMessage = settings.m_rrrMessage; + if (settingsKeys.contains("73Message")) + m_73Message = settings.m_73Message; + if (settingsKeys.contains("qsoTextMessage")) + m_qsoTextMessage = settings.m_qsoTextMessage; + if (settingsKeys.contains("textMessage")) + m_textMessage = settings.m_textMessage; + if (settingsKeys.contains("bytesMessage")) + m_bytesMessage = settings.m_bytesMessage; + if (settingsKeys.contains("messageType")) + m_messageType = settings.m_messageType; + if (settingsKeys.contains("nbParityBits")) + m_nbParityBits = settings.m_nbParityBits; + if (settingsKeys.contains("hasCRC")) + m_hasCRC = settings.m_hasCRC; + if (settingsKeys.contains("hasHeader")) + m_hasHeader = settings.m_hasHeader; + if (settingsKeys.contains("myCall")) + m_myCall = settings.m_myCall; + if (settingsKeys.contains("urCall")) + m_urCall = settings.m_urCall; + if (settingsKeys.contains("myLoc")) + m_myLoc = settings.m_myLoc; + if (settingsKeys.contains("myRpt")) + m_myRpt = settings.m_myRpt; + if (settingsKeys.contains("messageRepeat")) + m_messageRepeat = settings.m_messageRepeat; +} + +QString ChirpChatModSettings::getDebugString(const QStringList& settingsKeys, bool force) const +{ + QString debug; + if (settingsKeys.contains("inputFrequencyOffset") || force) + debug += QString("Input Frequency Offset: %1\n").arg(m_inputFrequencyOffset); + if (settingsKeys.contains("bandwidthIndex") || force) + debug += QString("Bandwidth Index: %1\n").arg(m_bandwidthIndex); + if (settingsKeys.contains("spreadFactor") || force) + debug += QString("Spread Factor: %1\n").arg(m_spreadFactor); + if (settingsKeys.contains("deBits") || force) + debug += QString("DE Bits: %1\n").arg(m_deBits); + if (settingsKeys.contains("codingScheme") || force) + debug += QString("Coding Scheme: %1\n").arg(m_codingScheme); + if (settingsKeys.contains("preambleChirps") || force) + debug += QString("Preamble Chirps: %1\n").arg(m_preambleChirps); + if (settingsKeys.contains("quietMillis") || force) + debug += QString("Quiet Millis: %1\n").arg(m_quietMillis); + if (settingsKeys.contains("invertRamps") || force) + debug += QString("Invert Ramps: %1\n").arg(m_invertRamps); + if (settingsKeys.contains("syncWord") || force) + debug += QString("Sync Word: %1\n").arg(m_syncWord); + if (settingsKeys.contains("channelMute") || force) + debug += QString("Channel Mute: %1\n").arg(m_channelMute); + if (settingsKeys.contains("title") || force) + debug += QString("Title: %1\n").arg(m_title); + if (settingsKeys.contains("udpEnabled") || force) + debug += QString("UDP Enabled: %1\n").arg(m_udpEnabled); + if (settingsKeys.contains("udpAddress") || force) + debug += QString("UDP Address: %1\n").arg(m_udpAddress); + if (settingsKeys.contains("udpPort") || force) + debug += QString("UDP Port: %1\n").arg(m_udpPort); + if (settingsKeys.contains("streamIndex") || force) + debug += QString("Stream Index: %1\n").arg(m_streamIndex); + if (settingsKeys.contains("useReverseAPI") || force) + debug += QString("Use Reverse API: %1\n").arg(m_useReverseAPI); + if (settingsKeys.contains("reverseAPIAddress") || force) + debug += QString("Reverse API Address: %1\n").arg(m_reverseAPIAddress); + if (settingsKeys.contains("reverseAPIPort") || force) + debug += QString("Reverse API Port: %1\n").arg(m_reverseAPIPort); + if (settingsKeys.contains("reverseAPIDeviceIndex") || force) + debug += QString("Reverse API Device Index: %1\n").arg(m_reverseAPIDeviceIndex); + if (settingsKeys.contains("reverseAPIChannelIndex") || force) + debug += QString("Reverse API Channel Index: %1\n").arg(m_reverseAPIChannelIndex); + if (settingsKeys.contains("workspaceIndex") || force) + debug += QString("Workspace Index: %1\n").arg(m_workspaceIndex); + if (settingsKeys.contains("hidden") || force) + debug += QString("Hidden: %1\n").arg(m_hidden); + if (settingsKeys.contains("beaconMessage") || force) + debug += QString("Beacon Message: %1\n").arg(m_beaconMessage); + if (settingsKeys.contains("cqMessage") || force) + debug += QString("CQ Message: %1\n").arg(m_cqMessage); + if (settingsKeys.contains("replyMessage") || force) + debug += QString("Reply Message: %1\n").arg(m_replyMessage); + if (settingsKeys.contains("reportMessage") || force) + debug += QString("Report Message: %1\n").arg(m_reportMessage); + if (settingsKeys.contains("replyReportMessage") || force) + debug += QString("Reply Report Message: %1\n").arg(m_replyReportMessage); + if (settingsKeys.contains("rrrMessage") || force) + debug += QString("RRR Message: %1\n").arg(m_rrrMessage); + if (settingsKeys.contains("73Message") || force) + debug += QString("73 Message: %1\n").arg(m_73Message); + if (settingsKeys.contains("qsoTextMessage") || force) + debug += QString("QSO Text Message: %1\n").arg(m_qsoTextMessage); + if (settingsKeys.contains("textMessage") || force) + debug += QString("Text Message: %1\n").arg(m_textMessage); + if (settingsKeys.contains("messageType") || force) + debug += QString("Message Type: %1\n").arg(m_messageType); + if (settingsKeys.contains("nbParityBits") || force) + debug += QString("Number of Parity Bits: %1\n").arg(m_nbParityBits); + if (settingsKeys.contains("hasCRC") || force) + debug += QString("Has CRC: %1\n").arg(m_hasCRC); + if (settingsKeys.contains("hasHeader") || force) + debug += QString("Has Header: %1\n").arg(m_hasHeader); + if (settingsKeys.contains("myCall") || force) + debug += QString("My Call: %1\n").arg(m_myCall); + if (settingsKeys.contains("urCall") || force) + debug += QString("UR Call: %1\n").arg(m_urCall); + if (settingsKeys.contains("myLoc") || force) + debug += QString("My Loc: %1\n").arg(m_myLoc); + if (settingsKeys.contains("myRpt") || force) + debug += QString("My Rpt: %1\n").arg(m_myRpt); + if (settingsKeys.contains("messageRepeat") || force) + debug += QString("Message Repeat: %1\n").arg(m_messageRepeat); + return debug; +} diff --git a/plugins/channeltx/modchirpchat/chirpchatmodsettings.h b/plugins/channeltx/modchirpchat/chirpchatmodsettings.h index a5c4de741..bd90f81fb 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodsettings.h +++ b/plugins/channeltx/modchirpchat/chirpchatmodsettings.h @@ -84,6 +84,7 @@ struct ChirpChatModSettings bool m_udpEnabled; QString m_udpAddress; uint16_t m_udpPort; + bool m_invertRamps; //!< Invert chirp ramps vs standard LoRa (up/down/up is standard) uint32_t m_rgbColor; QString m_title; int m_streamIndex; @@ -113,6 +114,8 @@ struct ChirpChatModSettings void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; } QByteArray serialize() const; bool deserialize(const QByteArray& data); + void applySettings(const QStringList& settingsKeys, const ChirpChatModSettings& settings); + QString getDebugString(const QStringList& settingsKeys, bool force=false) const; }; diff --git a/plugins/channeltx/modchirpchat/chirpchatmodsource.cpp b/plugins/channeltx/modchirpchat/chirpchatmodsource.cpp index 900f1b4e1..ef304f2d3 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodsource.cpp +++ b/plugins/channeltx/modchirpchat/chirpchatmodsource.cpp @@ -197,7 +197,7 @@ void ChirpChatModSource::modulateSample() } else if (m_state == ChirpChatStatePreamble) { - m_modPhasor += m_phaseIncrements[m_chirp]; // up chirps + m_modPhasor += (m_settings.m_invertRamps ? -1 : 1) * m_phaseIncrements[m_chirp]; // preamble chirps m_modSample = Complex(std::polar(0.891235351562 * SDR_TX_SCALED, m_modPhasor)); m_fftCounter++; @@ -228,7 +228,7 @@ void ChirpChatModSource::modulateSample() } else if (m_state == ChirpChatStateSyncWord) { - m_modPhasor += m_phaseIncrements[m_chirp]; // up chirps + m_modPhasor += (m_settings.m_invertRamps ? -1 : 1) * m_phaseIncrements[m_chirp]; // sync chirps same orientation as preamble m_modSample = Complex(std::polar(0.891235351562 * SDR_TX_SCALED, m_modPhasor)); m_fftCounter++; @@ -251,7 +251,7 @@ void ChirpChatModSource::modulateSample() } else if (m_state == ChirpChatStateSFD) { - m_modPhasor -= m_phaseIncrements[m_chirp]; // down chirps + m_modPhasor -= (m_settings.m_invertRamps ? -1 : 1) * m_phaseIncrements[m_chirp]; // SFD chirps m_modSample = Complex(std::polar(0.891235351562 * SDR_TX_SCALED, m_modPhasor)); m_fftCounter++; m_sampleCounter++; @@ -280,7 +280,7 @@ void ChirpChatModSource::modulateSample() } else if (m_state == ChirpChatStatePayload) { - m_modPhasor += m_phaseIncrements[m_chirp]; // up chirps + m_modPhasor += (m_settings.m_invertRamps ? -1 : 1) * m_phaseIncrements[m_chirp]; // payload chirps m_modSample = Complex(std::polar(0.891235351562 * SDR_TX_SCALED, m_modPhasor)); m_fftCounter++; diff --git a/plugins/channeltx/modchirpchat/readme.md b/plugins/channeltx/modchirpchat/readme.md index f66ec95e0..f54d12f6b 100644 --- a/plugins/channeltx/modchirpchat/readme.md +++ b/plugins/channeltx/modchirpchat/readme.md @@ -72,6 +72,12 @@ Thus available bandwidths are: The ChirpChat signal is oversampled by four therefore it needs a baseband of at least four times the bandwidth. This drives the maximum value on the slider automatically. +

16: Invert chirp ramps

+ +The LoRa standard is up-chirps for the preamble, down-chirps for the SFD and up-chirps for the payload. + +When you check this option it inverts the direction of the chirps thus becoming down-chirps for the preamble, up-chirps for the SFD and down-chirps for the payload. +

5: Spread Factor

This is the Spread Factor parameter of the ChirpChat signal. This is the log2 of the possible frequency shifts used over the bandwidth (3). The number of symbols is 2SF-DE where SF is the spread factor and DE the Distance Enhancement factor (6). diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index 56d6b80e5..44f7bff42 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -4457,7 +4457,11 @@ margin-bottom: 20px; }, "udpPort" : { "type" : "integer", - "description" : "UDP destination properties" + "description" : "UDP destination port" + }, + "invertRamps" : { + "type" : "integer", + "description" : "Invert chirp ramps\n * 0 - Normal chirp ramps (upchirps for preamble and payload)\n * 1 - Inverted chirp ramps (downchirps for preamble and payload)\n" }, "rgbColor" : { "type" : "integer" @@ -4657,6 +4661,10 @@ margin-bottom: 20px; "type" : "integer", "description" : "UDP port to listen for messages to transmit on" }, + "invertRamps" : { + "type" : "integer", + "description" : "Invert chirp ramps\n * 0 - Normal chirp ramps (upchirps for preamble and payload)\n * 1 - Inverted chirp ramps (downchirps for preamble and payload)\n" + }, "rgbColor" : { "type" : "integer" }, @@ -59832,7 +59840,7 @@ except ApiException as e:
- Generated 2026-01-10T11:16:10.140+01:00 + Generated 2026-01-24T10:44:52.632+01:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/ChirpChatDemod.yaml b/sdrbase/resources/webapi/doc/swagger/include/ChirpChatDemod.yaml index 8e6d36487..101ae8d26 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/ChirpChatDemod.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/ChirpChatDemod.yaml @@ -100,8 +100,14 @@ ChirpChatDemodSettings: description: UDP destination udpAddress type: string udpPort: - description: UDP destination properties + description: UDP destination port type: integer + invertRamps: + type: integer + description: > + Invert chirp ramps + * 0 - Normal chirp ramps (upchirps for preamble and payload) + * 1 - Inverted chirp ramps (downchirps for preamble and payload) rgbColor: type: integer title: diff --git a/sdrbase/resources/webapi/doc/swagger/include/ChirpChatMod.yaml b/sdrbase/resources/webapi/doc/swagger/include/ChirpChatMod.yaml index 3e734f63e..ced9b5310 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/ChirpChatMod.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/ChirpChatMod.yaml @@ -139,6 +139,12 @@ ChirpChatModSettings: udpPort: description: UDP port to listen for messages to transmit on type: integer + invertRamps: + type: integer + description: > + Invert chirp ramps + * 0 - Normal chirp ramps (upchirps for preamble and payload) + * 1 - Inverted chirp ramps (downchirps for preamble and payload) rgbColor: type: integer title: diff --git a/swagger/sdrangel/api/swagger/include/ChirpChatDemod.yaml b/swagger/sdrangel/api/swagger/include/ChirpChatDemod.yaml index 5cf7a58f9..b9eb085a4 100644 --- a/swagger/sdrangel/api/swagger/include/ChirpChatDemod.yaml +++ b/swagger/sdrangel/api/swagger/include/ChirpChatDemod.yaml @@ -100,8 +100,14 @@ ChirpChatDemodSettings: description: UDP destination udpAddress type: string udpPort: - description: UDP destination properties + description: UDP destination port type: integer + invertRamps: + type: integer + description: > + Invert chirp ramps + * 0 - Normal chirp ramps (upchirps for preamble and payload) + * 1 - Inverted chirp ramps (downchirps for preamble and payload) rgbColor: type: integer title: diff --git a/swagger/sdrangel/api/swagger/include/ChirpChatMod.yaml b/swagger/sdrangel/api/swagger/include/ChirpChatMod.yaml index 1568e40e1..58d14202a 100644 --- a/swagger/sdrangel/api/swagger/include/ChirpChatMod.yaml +++ b/swagger/sdrangel/api/swagger/include/ChirpChatMod.yaml @@ -139,6 +139,12 @@ ChirpChatModSettings: udpPort: description: UDP port to listen for messages to transmit on type: integer + invertRamps: + type: integer + description: > + Invert chirp ramps + * 0 - Normal chirp ramps (upchirps for preamble and payload) + * 1 - Inverted chirp ramps (downchirps for preamble and payload) rgbColor: type: integer title: diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index 56d6b80e5..44f7bff42 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -4457,7 +4457,11 @@ margin-bottom: 20px; }, "udpPort" : { "type" : "integer", - "description" : "UDP destination properties" + "description" : "UDP destination port" + }, + "invertRamps" : { + "type" : "integer", + "description" : "Invert chirp ramps\n * 0 - Normal chirp ramps (upchirps for preamble and payload)\n * 1 - Inverted chirp ramps (downchirps for preamble and payload)\n" }, "rgbColor" : { "type" : "integer" @@ -4657,6 +4661,10 @@ margin-bottom: 20px; "type" : "integer", "description" : "UDP port to listen for messages to transmit on" }, + "invertRamps" : { + "type" : "integer", + "description" : "Invert chirp ramps\n * 0 - Normal chirp ramps (upchirps for preamble and payload)\n * 1 - Inverted chirp ramps (downchirps for preamble and payload)\n" + }, "rgbColor" : { "type" : "integer" }, @@ -59832,7 +59840,7 @@ except ApiException as e:
- Generated 2026-01-10T11:16:10.140+01:00 + Generated 2026-01-24T10:44:52.632+01:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodSettings.cpp index 7a1934b10..25102d235 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodSettings.cpp @@ -66,6 +66,8 @@ SWGChirpChatDemodSettings::SWGChirpChatDemodSettings() { m_udp_address_isSet = false; udp_port = 0; m_udp_port_isSet = false; + invert_ramps = 0; + m_invert_ramps_isSet = false; rgb_color = 0; m_rgb_color_isSet = false; title = nullptr; @@ -134,6 +136,8 @@ SWGChirpChatDemodSettings::init() { m_udp_address_isSet = false; udp_port = 0; m_udp_port_isSet = false; + invert_ramps = 0; + m_invert_ramps_isSet = false; rgb_color = 0; m_rgb_color_isSet = false; title = new QString(""); @@ -182,6 +186,7 @@ SWGChirpChatDemodSettings::cleanup() { } + if(title != nullptr) { delete title; } @@ -253,6 +258,8 @@ SWGChirpChatDemodSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&udp_port, pJson["udpPort"], "qint32", ""); + ::SWGSDRangel::setValue(&invert_ramps, pJson["invertRamps"], "qint32", ""); + ::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", ""); ::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString"); @@ -348,6 +355,9 @@ SWGChirpChatDemodSettings::asJsonObject() { if(m_udp_port_isSet){ obj->insert("udpPort", QJsonValue(udp_port)); } + if(m_invert_ramps_isSet){ + obj->insert("invertRamps", QJsonValue(invert_ramps)); + } if(m_rgb_color_isSet){ obj->insert("rgbColor", QJsonValue(rgb_color)); } @@ -575,6 +585,16 @@ SWGChirpChatDemodSettings::setUdpPort(qint32 udp_port) { this->m_udp_port_isSet = true; } +qint32 +SWGChirpChatDemodSettings::getInvertRamps() { + return invert_ramps; +} +void +SWGChirpChatDemodSettings::setInvertRamps(qint32 invert_ramps) { + this->invert_ramps = invert_ramps; + this->m_invert_ramps_isSet = true; +} + qint32 SWGChirpChatDemodSettings::getRgbColor() { return rgb_color; @@ -747,6 +767,9 @@ SWGChirpChatDemodSettings::isSet(){ if(m_udp_port_isSet){ isObjectUpdated = true; break; } + if(m_invert_ramps_isSet){ + isObjectUpdated = true; break; + } if(m_rgb_color_isSet){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodSettings.h b/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodSettings.h index 0a5dab394..1409247be 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGChirpChatDemodSettings.h @@ -102,6 +102,9 @@ public: qint32 getUdpPort(); void setUdpPort(qint32 udp_port); + qint32 getInvertRamps(); + void setInvertRamps(qint32 invert_ramps); + qint32 getRgbColor(); void setRgbColor(qint32 rgb_color); @@ -196,6 +199,9 @@ private: qint32 udp_port; bool m_udp_port_isSet; + qint32 invert_ramps; + bool m_invert_ramps_isSet; + qint32 rgb_color; bool m_rgb_color_isSet; diff --git a/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.cpp index ba524de3a..9f95558fa 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.cpp @@ -90,6 +90,8 @@ SWGChirpChatModSettings::SWGChirpChatModSettings() { m_udp_address_isSet = false; udp_port = 0; m_udp_port_isSet = false; + invert_ramps = 0; + m_invert_ramps_isSet = false; rgb_color = 0; m_rgb_color_isSet = false; title = nullptr; @@ -180,6 +182,8 @@ SWGChirpChatModSettings::init() { m_udp_address_isSet = false; udp_port = 0; m_udp_port_isSet = false; + invert_ramps = 0; + m_invert_ramps_isSet = false; rgb_color = 0; m_rgb_color_isSet = false; title = new QString(""); @@ -270,6 +274,7 @@ SWGChirpChatModSettings::cleanup() { } + if(title != nullptr) { delete title; } @@ -362,6 +367,8 @@ SWGChirpChatModSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&udp_port, pJson["udpPort"], "qint32", ""); + ::SWGSDRangel::setValue(&invert_ramps, pJson["invertRamps"], "qint32", ""); + ::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", ""); ::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString"); @@ -491,6 +498,9 @@ SWGChirpChatModSettings::asJsonObject() { if(m_udp_port_isSet){ obj->insert("udpPort", QJsonValue(udp_port)); } + if(m_invert_ramps_isSet){ + obj->insert("invertRamps", QJsonValue(invert_ramps)); + } if(m_rgb_color_isSet){ obj->insert("rgbColor", QJsonValue(rgb_color)); } @@ -835,6 +845,16 @@ SWGChirpChatModSettings::setUdpPort(qint32 udp_port) { this->m_udp_port_isSet = true; } +qint32 +SWGChirpChatModSettings::getInvertRamps() { + return invert_ramps; +} +void +SWGChirpChatModSettings::setInvertRamps(qint32 invert_ramps) { + this->invert_ramps = invert_ramps; + this->m_invert_ramps_isSet = true; +} + qint32 SWGChirpChatModSettings::getRgbColor() { return rgb_color; @@ -1033,6 +1053,9 @@ SWGChirpChatModSettings::isSet(){ if(m_udp_port_isSet){ isObjectUpdated = true; break; } + if(m_invert_ramps_isSet){ + isObjectUpdated = true; break; + } if(m_rgb_color_isSet){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.h b/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.h index 15723a767..b63ee354b 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.h @@ -138,6 +138,9 @@ public: qint32 getUdpPort(); void setUdpPort(qint32 udp_port); + qint32 getInvertRamps(); + void setInvertRamps(qint32 invert_ramps); + qint32 getRgbColor(); void setRgbColor(qint32 rgb_color); @@ -265,6 +268,9 @@ private: qint32 udp_port; bool m_udp_port_isSet; + qint32 invert_ramps; + bool m_invert_ramps_isSet; + qint32 rgb_color; bool m_rgb_color_isSet;