diff --git a/doc/img/MeshstasticMod_A.png b/doc/img/MeshstasticMod_A.png
new file mode 100644
index 000000000..21d1d9ee9
Binary files /dev/null and b/doc/img/MeshstasticMod_A.png differ
diff --git a/doc/img/MeshstasticMod_A.xcf b/doc/img/MeshstasticMod_A.xcf
new file mode 100644
index 000000000..406969714
Binary files /dev/null and b/doc/img/MeshstasticMod_A.xcf differ
diff --git a/doc/img/MeshstasticMod_plugin.png b/doc/img/MeshstasticMod_plugin.png
new file mode 100644
index 000000000..669d3200e
Binary files /dev/null and b/doc/img/MeshstasticMod_plugin.png differ
diff --git a/doc/img/MeshstasticMod_plugin.xcf b/doc/img/MeshstasticMod_plugin.xcf
new file mode 100644
index 000000000..00590bd19
Binary files /dev/null and b/doc/img/MeshstasticMod_plugin.xcf differ
diff --git a/doc/img/MeshtasticDemod_RF.png b/doc/img/MeshtasticDemod_RF.png
new file mode 100644
index 000000000..eaf8cb98b
Binary files /dev/null and b/doc/img/MeshtasticDemod_RF.png differ
diff --git a/doc/img/MeshtasticDemod_RF.xcf b/doc/img/MeshtasticDemod_RF.xcf
new file mode 100644
index 000000000..9b0719a80
Binary files /dev/null and b/doc/img/MeshtasticDemod_RF.xcf differ
diff --git a/doc/img/MeshtasticDemod_controls.png b/doc/img/MeshtasticDemod_controls.png
new file mode 100644
index 000000000..bb46cdb87
Binary files /dev/null and b/doc/img/MeshtasticDemod_controls.png differ
diff --git a/doc/img/MeshtasticDemod_controls.xcf b/doc/img/MeshtasticDemod_controls.xcf
new file mode 100644
index 000000000..7f72b98db
Binary files /dev/null and b/doc/img/MeshtasticDemod_controls.xcf differ
diff --git a/doc/img/MeshtasticDemod_payload.png b/doc/img/MeshtasticDemod_payload.png
new file mode 100644
index 000000000..731767b44
Binary files /dev/null and b/doc/img/MeshtasticDemod_payload.png differ
diff --git a/doc/img/MeshtasticDemod_payload.xcf b/doc/img/MeshtasticDemod_payload.xcf
new file mode 100644
index 000000000..a620861a3
Binary files /dev/null and b/doc/img/MeshtasticDemod_payload.xcf differ
diff --git a/doc/img/MeshtasticDemod_plugin.png b/doc/img/MeshtasticDemod_plugin.png
new file mode 100644
index 000000000..4c5a36a03
Binary files /dev/null and b/doc/img/MeshtasticDemod_plugin.png differ
diff --git a/doc/img/MeshtasticDemod_plugin.xcf b/doc/img/MeshtasticDemod_plugin.xcf
new file mode 100644
index 000000000..1a0502b39
Binary files /dev/null and b/doc/img/MeshtasticDemod_plugin.xcf differ
diff --git a/doc/img/MeshtasticDemod_spectrum.png b/doc/img/MeshtasticDemod_spectrum.png
new file mode 100644
index 000000000..b6c6adb73
Binary files /dev/null and b/doc/img/MeshtasticDemod_spectrum.png differ
diff --git a/doc/img/MeshtasticDemod_spectrum.xcf b/doc/img/MeshtasticDemod_spectrum.xcf
new file mode 100644
index 000000000..c9a774f77
Binary files /dev/null and b/doc/img/MeshtasticDemod_spectrum.xcf differ
diff --git a/plugins/channelrx/demodmeshtastic/meshtasticdemodgui.cpp b/plugins/channelrx/demodmeshtastic/meshtasticdemodgui.cpp
index 6bf81a7f4..effdb4888 100644
--- a/plugins/channelrx/demodmeshtastic/meshtasticdemodgui.cpp
+++ b/plugins/channelrx/demodmeshtastic/meshtasticdemodgui.cpp
@@ -1574,7 +1574,8 @@ MeshtasticDemodGUI::MeshtasticDemodGUI(PluginAPI* pluginAPI, DeviceUISet *device
ui->packetLength->setToolTip(tr("Fixed packet length for implicit-header mode."));
ui->packetLengthLabel->setToolTip(tr("Fixed packet length for implicit header mode."));
ui->packetLengthText->setToolTip(tr("Current fixed packet length."));
- ui->invertRamps->setToolTip(tr("Invert chirp ramp direction."));
+ ui->invertRamps->setToolTip(tr("Invert chirp ramp direction. Disabled"));
+ ui->invertRamps->setEnabled(false);
ui->messageLabel->setToolTip(tr("Decoded output area."));
ui->udpSend->setToolTip(tr("Forward decoded payload bytes to UDP."));
ui->udpAddress->setToolTip(tr("Destination UDP address for forwarded payloads."));
diff --git a/plugins/channelrx/demodmeshtastic/meshtasticdemodgui.ui b/plugins/channelrx/demodmeshtastic/meshtasticdemodgui.ui
index b114c0db3..e194ad6e4 100644
--- a/plugins/channelrx/demodmeshtastic/meshtasticdemodgui.ui
+++ b/plugins/channelrx/demodmeshtastic/meshtasticdemodgui.ui
@@ -1127,12 +1127,12 @@
QTabWidget::West
-
- false
-
true
+
+ false
+
@@ -1227,19 +1227,6 @@
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
diff --git a/plugins/channelrx/demodmeshtastic/readme.md b/plugins/channelrx/demodmeshtastic/readme.md
index 486c5bc4b..39449c191 100644
--- a/plugins/channelrx/demodmeshtastic/readme.md
+++ b/plugins/channelrx/demodmeshtastic/readme.md
@@ -4,22 +4,14 @@
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 may be used in conjunction with the Meshtastic modulator plugin 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)
-⚠ Only spread factors of 11 and 12 are working in LoRa mode with the distance enhancement active (DE=2)
+This LoRa Meshtastic decoder is designed for experimentation. For production grade applications it is recommended to use dedicated hardware instead.
-Transmissions from the RN2483 module (SF=11 and SF=12 with DE=2) 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.
-
-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.
-
-In any case it is recommended to use a non zero distance enhancement factor for successful transmissions.
-
-Note: this plugin is officially supported since version 6.
+Modulation characteristics from LoRa have been augmented with more bandwidths and FFT bin collations (DE factor).
Meshtastic decode mode
@@ -77,6 +69,16 @@ The top and bottom bars of the channel window are described [here](../../../sdrg

+The interface is divided in 3 sections:
+
+- RF/demod settings
+- Payload
+- De-chirped spectrum
+
+RF/demod settings section
+
+
+
1: Frequency shift from center frequency of reception
Use the wheels to adjust the frequency shift in Hz from the center frequency of reception. Left click on a digit sets the cursor position at this digit. Right click on a digit sets all digits on the right to zero. This effectively floors value at the digit position. Wheels are moved with the mousewheel while pointing at the wheel or by selecting the wheel with the left mouse click and using the keyboard arrows. Pressing shift simultaneously moves digit by 5 and pressing control moves it by 2.
@@ -87,7 +89,7 @@ This is the total power in the FFT of the de-chirped signal in dB. When no Mesht
3: Bandwidth
-This is the bandwidth of the Meshtastic signal. Similarly to LoRa the signal sweeps between the lower and the upper frequency of this bandwidth. The sample rate of the Meshtastic signal in seconds is exactly one over this bandwidth in Hertz.
+This is the bandwidth of the Meshtastic signal. The signal sweeps between the lower and the upper frequency of this bandwidth. The sample rate of the Meshtastic 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. Extra divisor of 128 is provided to achieve smaller bandwidths that can fit in a SSB channel. Finally special divisors from a 384 kHz base are provided to allow even more narrow bandwidths.
@@ -124,39 +126,20 @@ Thus available bandwidths are:
The Meshtastic 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
+4:Noise and signal power
-This is the maximum power received in one FFT bin (the argmax bin) in dB when no signal is detected. It is averaged over 10 values.
+The first number prefixed by `N` is the maximum power received in one FFT bin (the argmax bin) in dB when no signal is detected. It is averaged over 10 values.
-5. De-chirped signal maximum power
+The second number prefixed by `S` is the maximum power received in one FFT bin (the argmax bin) in dB when a signal is detected. It is averaged over 10 values.
-This is the maximum power received in one FFT bin (the argmax bin) in dB when a signal is detected. It is averaged over 10 values.
+The last number after the slash is the de-chirped signal over noise ratio.
+The noise level reference is the noise maximum power just before the detected signal starts and the signal level the signal maximum power just before the detected signal stops. Decode errors are very likely to happen when this value falls below 4 dB.
-6: De-chirped signal over noise ratio
-
-The noise level reference is the noise maximum power just before the detected signal starts and the signal level the signal maximum power just before the detected signal stops. To get a significant reading you have to adjust correctly the number of preamble chirps (9) and the End Of Message squelch level (A.3) and/or the message length (A.4) so that signal boundaries are determined correctly.
-
-Decode errors are very likely to happen when this value falls below 4 dB.
-
-7: FFT Window
-
-A choice of FFT Windows to apply to the FFT performed on the de-chirped signal is provided. These are the same windows as those used in the spectrum display. The effect of windowing is to reduce the spill over in adjacent bins at the expense of a flatter top and fatter main lobe. When the purpose is frequency detection this is not what is desired necessarily and thus the "Rectangular" window (i.e. no window) should be chosen. However a variety of windows is provided to experiment with. Experimentally the best alternative to "Rectangular" is "Kaiser" then "Bartlett" and "Hanning". The complete list is:
-
- - **Bart**: Bartlett
- - **B-H**: 4 term Blackman-Harris
- - **FT**: Flat Top
- - **Ham**: Hamming
- - **Han**: Hanning
- - **Rec**: Rectangular (no window)
- - **Kai**: Kaiser with α = π
- - **Black**: Blackman (3 term)
- - **B-H7**: 7 term Blackman-Harris
-
-8: Spread Factor
+5: Spread Factor
This is the Spread Factor parameter of the Meshtastic 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)
-9: Distance Enhancement factor
+6: Distance Enhancement factor
The LoRa standard specifies 0 (no DE) or 2 (DE active). The Meshtastic DE range is extended to all values between 0 and 4 bits.
@@ -164,159 +147,230 @@ The LoRa standard also specifies that the LowDataRateOptimizatio flag (thus DE=2
Here this value is the log2 of the number of FFT bins used for one symbol. Extending the number of FFT bins per symbol decreases the probability to detect the wrong symbol as an adjacent bin. It can also overcome frequency or sampling time drift on long messages particularly for small bandwidths.
-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.
+7: Number of expected preamble chirps
-10: Number of expected preamble chirps
+This is the number of chirps expected in the preamble and has to be agreed between the transmitter and receiver. For Meshtastic this is conventionally set to 17.
-This is the number of chirps expected in the preamble and has to be agreed between the transmitter and receiver.
-
-15: Invert chirp ramps
+15: Invert chirp ramps (disabled)
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
+Payload section
-
+
-A.2: Start/Stop decoder
+A: Control section
+
+
+
+A.1: Meshtastic region code (frequencies)
+
+- **US**: US 902 MHz band
+- **EU_433**: European 433 MHz band
+- **EU_868**: European 868 MHz band
+- **ANZ**: Australia and New Zealand 915-928 MHz band
+- **JP**: Japan 920-923 MHz band
+- **CN**: China 470-510 MHz band
+- **KR**: South Korea 920-922 MHz band
+- **TW**: Taiwan 920-925 MHz band
+- **IN**: India 865-866 MHz band
+- **TH**: Thailand 920-925 MHz band
+- **BR_902**: Brazil 902-907 MHz band
+- **LORA_24**: LoRa 902.125 MHz
+
+A.2: Meshtastic modem preset
+
+- **LONG_FAST**: BW=250kHz SF=11, DE=0, FEC=4/5
+- **LONG_SLOW**: BW=125kHz, SF=12, DE=2, FEC=4/8
+- **LONG_MODERATE**: BW=125kHz, SF=11, DE=0, FEC=4/5
+- **LONG_TURBO**: BW=500kHz, SF=11, DE=0, FEC=4/8 (a.k.a Long Range / Turbo)
+- **MEDIUM_FAST**: BW=250kHz, SF=9, DE=0, FEC=4/5
+- **MEDIUM_SLOW**: BW=250kHz, SF=10, DE=0, FEC=4/5
+- **SHORT_FAST**: BW=250kHz, SF=7, DE=0, FEC=4/5
+- **SHORT_SLOW**: BW=250kHz, SF=8, DE=0, FEC=4/5
+- **SHORT_TURBO**: BW=500kHz, SF=7, DE=0, FEC=4/5 (a.k.a Short Range / Turbo)
+
+A.3: Channel selection
+
+Select channel within regional band. This is the Meshtastic channel number, shown as Meshtastic-style zero-based index and auto-populated for selected region/preset
+
+A.4: Apply settings
+
+Apply or reapply the preceding settings. Normally when either selection changes, the demodulator auto-applies LoRa decode parameters for the selected profile:
+
+- bandwidth
+- spread factor
+- DE bits
+- preamble length (17 on sub-GHz presets, 12 on 2.4 GHz)
+- FEC parity bits
+- header/CRC expectations
+
+If the device center frequency is known, the channel offset is also auto-centered to the selected region/preset default channel. The demodulator also attempts to auto-tune the device sample rate/decimation (when supported by the device) so effective baseband rate is suitable for the selected LoRa bandwidth.
+
+A.5: Encryption keys
+
+Opens a window to declare encryption keys. Key handling for decryption supports:
+
+- none / plaintext
+- Meshtastic shorthand keys (`default`, `simple0`..`simple10`)
+- Explicit `hex:` and `base64:` keys (has to be 16 or 32 bits)
+- Multiple keys from environment
+
+In the opened window a "Validate" button checks the above syntax. For classical LONG_FAST channels use just hex 1 specified as `default` or `simple1` (`hex:1` or `base64:AQ==` do not apply since they expect 16 or 32 bits)
+
+A.6: Auto lock
+
+Arms first and waits for on-air activity, then scans Inv + frequency offset candidates. For SF11/SF12 it also probes DE=0 and DE=2 as compatibility candidates. It scores using decode quality plus source-side intensity (demod activity + power/noise), but only auto-applies candidates with decode evidence (header/payload CRC backed); otherwise it restores baseline settings.
+
+A.7: Auto input tune
+
+when enabled, tries to set source sample-rate/decimation automatically for the selected LoRa bandwidth
+
+A.8: Start/Stop decoder
You can suspend and resume decoding activity using this button. This is useful if you want to freeze the payload content display.
-A.3: End Of Message squelch
+A.9: End Of Message squelch
-This is used to determine the end of message automatically. It can be de-activated by turning the button completely to the right (as shown on the picture). In this case it relies on the message length set with (A.4).
+This is used to determine the end of message automatically. It can be de-activated by turning the button completely to the right (as shown on the picture). In this case it relies on the message length set with (A.10).
During payload detection the maximum power value in the FFT (at argmax) Pmax is stored and compared to the current argmax power value Pi if SEOM is this squelch value the end of message is detected if SEOM × Si < Smax
-A.4: Expected message length in symbols
+A.10: Expected message length in symbols
-This is the expected number of symbols in a message. When a header is present in the payload it should match the size given in the header (A.11).
+This is the expected number of symbols in a message. When a header is present in the payload it should match the size given in the header.
-A.8: Number of FEC parity bits
+A.11: Number of FEC parity bits
-LoRa mode only. This is the number of parity bits in the Hamming code used in the FEC. The standard values are 1 to 4 for H(4,5) to H(4,8) encoding. 0 is a non-standard value to specify no FEC.
+This is the number of parity bits in the Hamming code used in the FEC and is set in the header therefore this control is disabled. The standard values are 1 to 4 for H(4,5) to H(4,8) encoding.
-This control is disabled because the value used is the one found in the header.
+A.12: Packet length
-A.10: Packet length
+This is the expected packet length in bytes without header and CRC. This control is disabled because the value used is the one found in the header.
-This is the expected packet length in bytes without header and CRC.
-
-This control is disabled because the value used is the one found in the header.
-
-A.11: Number of symbols and codewords
+A.13: Number of symbols and codewords
This is the number of symbols (left of slash) and codewords (right of slash) used for the payload including header and CRC.
-A.12: Header FEC indicator
-
-Header uses a H(4,8) FEC. The color of the indicator gives the status of header parity checks:
+A.14: Indicators
+- Header FEC indicator. The color of the indicator gives the status of header parity checks:
- **Grey**: undefined
- **Red**: unrecoverable error
- **Blue**: recovered error
- **Green**: no errors
-A.13: Header CRC indicator
-
-The header has a one byte CRC. The color of this indicator gives the CRC status:
+- Header CRC indicator. The header has a one byte CRC. The color of this indicator gives the CRC status:
- **Green**: CRC OK
- **Red**: CRC error
-A.14: Payload FEC indicator
-
-The color of the indicator gives the status of payload parity checks:
+- Payload FEC indicator. The color of the indicator gives the status of payload parity checks:
- **Grey**: undefined
- **Red**: unrecoverable error. H(4,7) cannot distinguish between recoverable and unrecoverable error. Therefore this is never displayed for H(4,7). For FT it means that LDPC decoding failed.
- **Blue**: recovered error
- **Green**: no errors
-A.15: Payload CRC indicator
-
-The payload can have a two byte CRC. The color of this indicator gives the CRC status:
+- Payload CRC indicator. The payload can have a two byte CRC. The color of this indicator gives the CRC status:
- **Grey**: No CRC
- **Green**: CRC OK
- **Red**: CRC error
-11: Clear message window
+1: Clear message window
-Use this push button to clear the message window (12)
+Use this push button to clear the message window (3) and (4)
-Live button
+2: Live button
-12: Message window
+Returns to live mode from message replay in spectrum mode
+
+3: Raw message window
This is where the message and status data are displayed. The display is text/binary mixed. The text vs binary consideration concerns the content of the message not the way it is transmitted on air that is by itself binary.
-12.a: Text messages
+Header section:
-The format of a message line is the following:
-
-
-
- - 1: Timestamp in HH:MM:SS format
- - 2: Signal level. Same as (5) for the current message
- - 3: Signal Over Noise. Same as (6) for the current message
- - 4: Start of text indicator
- - 5: Text
-
-12.b: Binary messages
-
-
-
- - 1: Timestamp in HH:NN:SS format
- - 2: Sync word. This is the sync word (byte) displayed in hex. Corresponds to (A.5) in the current message.
- - 3: De-chirped signal level. This is the de-chirped signal level in dB. Corresponds to (5) in the current message.
- - 4: De-chirped signal to noise ratio. This is the de-chirped signal to noise ratio in dB. Corresponds to (6) in the current message.
- - 5: Header FEC status. Corresponds to (A.12) indicator in the current message:
+ - Timestamp in HH:NN:SS format
+ - Sync word. This is the sync word (byte) displayed in hex.
+ - De-chirped signal level. This is the de-chirped signal level in dB.
+ - De-chirped signal to noise ratio. This is the de-chirped signal to noise ratio in dB.
+ - Header FEC status:
- **n/a**: unknown or not applicable
- **err**: unrecoverable error
- **fix**: corrected error
- **ok**: OK
- - 6: Header CRC status. Corresponds to (A.13) indicator in the current message
+ - Header CRC status:
- **ok**: CRC OK
- **err**: CRC error
- **n/a**: not applicable
- - 7: Payload FEC status. Corresponds to (A.14) indicator in the current message. If the end of message is reached before expectation then `ERR: too early` is displayed instead and no payload CRC status (next) is displayed.
+ - Payload FEC status. If the end of message is reached before expectation then `ERR: too early` is displayed instead and no payload CRC status (next) is displayed.
- **n/a**: unknown or not applicable
- **err**: unrecoverable error
- **fix**: corrected error
- **ok**: OK
- - 8: Payload CRC status. Corresponds to (A.15) indicator in the current message:
+ - Payload CRC status:
- **ok**: CRC OK
- **err**: CRC error
- **n/a**: not applicable
- - 9: Displacement at start of line. 16 bytes in 4 groups of 4 bytes are displayed per line starting with the displacement in decimal.
- - 10: Bytes group. This is a group of 4 bytes displayed as hexadecimal values. The payload is displayed with its possible CRC and without the header.
- - 11: Message as text with "TXT" as prefix indicating it is the translation of the message to character representation
-13: Send message via UDP
+Binary section:
+
+ - Displacement at start of line. 16 bytes in 4 groups of 4 bytes are displayed per line starting with the displacement in decimal.
+ - Bytes group. This is a group of 4 bytes displayed as hexadecimal values. The payload is displayed with its possible CRC and without the header.
+ - Message as text with "TXT" as prefix indicating it is the translation of the message to character representation
+
+Meshtastic section:
+
+If the message is a valid Meshtastic message a summary of content is displayed following the `TXT|MESH RX` header showing the main Meshtastic data items
+
+4: Meshtastic structured message
+
+This is a tree view with expandable sections of the Mehstastic message.
+
+In case of a simple LoRa message without Meshtastic formatting it shows `LORA_FRAME` for the type and generic LoRa information with the message content as a hexadecimal string
+
+A Meshtastic message will show the message type (or port), then expandable sections:
+
+ - header section
+ - decode section with the encoding details
+ - data section with generic data
+ - section specific to the type of message
+
+For now the following message types (ports) are decoded in this last section:
+
+ - position
+ - node info
+ - traceroute
+ - telemetry
+ - plain text
+
+5: Send message via UDP
Select to send the decoded message via UDP.
-14: UDP address and port
+6,7: UDP address and port
This is the UDP address and port to where the decoded message is sent when (12) is selected.
-B: De-chirped spectrum
+De-chirped spectrum section
+
+
This is the spectrum of the de-chirped signal when a Meshtastic signal can be decoded. Details on the spectrum view and controls can be found [here](../../../sdrgui/gui/spectrum.md)
-The frequency span corresponds to the bandwidth of the Meshtastic signal (3). Default FFT size is 2SF where SF is the spread factor (7).
+The frequency span corresponds to the bandwidth of the Meshtastic signal. Default FFT size is 2SF where SF is the spread factor.
Sequences of successful Meshtastic signal demodulation are separated by blank lines (generated 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 window is chosen by (7)
+ - The window type is always rectangular
- 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
diff --git a/plugins/channeltx/modmeshtastic/meshtasticmodgui.cpp b/plugins/channeltx/modmeshtastic/meshtasticmodgui.cpp
index 2cd1249d5..de8914959 100644
--- a/plugins/channeltx/modmeshtastic/meshtasticmodgui.cpp
+++ b/plugins/channeltx/modmeshtastic/meshtasticmodgui.cpp
@@ -731,7 +731,8 @@ MeshtasticModGUI::MeshtasticModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISe
ui->udpAddress->setToolTip(tr("UDP listen address for incoming payloads."));
ui->udpPort->setToolTip(tr("UDP listen port for incoming payloads."));
ui->udpSeparator->setToolTip(tr("UDP input controls."));
- ui->invertRamps->setToolTip(tr("Invert chirp ramp direction."));
+ ui->invertRamps->setToolTip(tr("Invert chirp ramp direction. Disabled"));
+ ui->invertRamps->setEnabled(false);
ui->channelPower->setToolTip(tr("Estimated channel output power."));
ui->timesLabel->setToolTip(tr("Estimated timing values for current LoRa frame."));
ui->timeSymbolText->setToolTip(tr("Estimated LoRa symbol time."));
@@ -953,7 +954,6 @@ void MeshtasticModGUI::makeUIConnections()
QObject::connect(ui->udpEnabled, &QCheckBox::clicked, this, &MeshtasticModGUI::on_udpEnabled_clicked);
QObject::connect(ui->udpAddress, &QLineEdit::editingFinished, this, &MeshtasticModGUI::on_udpAddress_editingFinished);
QObject::connect(ui->udpPort, &QLineEdit::editingFinished, this, &MeshtasticModGUI::on_udpPort_editingFinished);
- QObject::connect(ui->invertRamps, &QCheckBox::stateChanged, this, &MeshtasticModGUI::on_invertRamps_stateChanged);
QObject::connect(ui->meshRegion, QOverload::of(&QComboBox::currentIndexChanged), this, &MeshtasticModGUI::on_meshRegion_currentIndexChanged);
QObject::connect(ui->meshPreset, QOverload::of(&QComboBox::currentIndexChanged), this, &MeshtasticModGUI::on_meshPreset_currentIndexChanged);
QObject::connect(ui->meshChannel, QOverload::of(&QComboBox::currentIndexChanged), this, &MeshtasticModGUI::on_meshChannel_currentIndexChanged);
diff --git a/plugins/channeltx/modmeshtastic/readme.md b/plugins/channeltx/modmeshtastic/readme.md
index 8dd2b4727..1d6178223 100644
--- a/plugins/channeltx/modmeshtastic/readme.md
+++ b/plugins/channeltx/modmeshtastic/readme.md
@@ -2,18 +2,18 @@
Introduction
-This plugin can be used to code and modulate a transmission signal based the LoRa Chirp Spread Spectrum (CSS) modulation scheme with a Meshtastic payload.
+This plugin can be used to code and modulate a transmission signal based the LoRa Chirp Spread Spectrum (CSS) modulation scheme with a Meshtastic payload.
-The basic idea of the CSS modulation 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 Modmeshtastic demodulator plugin that should be used ideally on the reception side.
+The basic idea of the CSS modulation 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 Meshtastic demodulator plugin that should be used ideally on the reception side.
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 LoRa encoder is designed for experimentation. For production grade applications it is recommended to use dedicated hardware instead.
+This LoRa/Meshtastic encoder is designed for experimentation. For production grade applications it is recommended to use dedicated hardware instead.
-Modulation characteristics from LoRa have been augmented with more bandwidths and FFT bin collations (DE factor) but this should be rendered ineffective with Meshtastic presets.
+Modulation characteristics from LoRa have been augmented with more bandwidths and FFT bin collations (DE factor) outside the specifications of the Meshtastic standards that can be set with the presets.
Fixes done by Copilot (GPT 5.3 Codex) from first PR
@@ -31,30 +31,11 @@ Now a full end to end test with a Meshtastic text message works:
- ✅ Payload CRC validation passes end-to-end
- ✅ Full decode chain: preamble → sync → header → payload → message text displayed
-Meshtastic frame mode
-
-In LoRa coding mode, if the message text starts with `MESH:` the plugin will build a full Meshtastic over-the-air frame (16-byte header + protobuf `Data` payload) and encrypt it with AES-CTR when enabled.
-
-Quick example (Text mode):
-
-`MESH:from=0x11223344;to=0xffffffff;id=0x1234;key=default;port=TEXT;text=hello mesh;want_ack=1;hop_limit=3`
-
-Supported fields:
-
- - Header: `to`, `from`, `id`, `hop_limit`, `hop_start`, `want_ack`, `via_mqtt`, `next_hop`, `relay_node`
- - Data protobuf: `port`/`portnum`, `text`, `payload_hex`, `payload_base64`/`payload_b64`, `want_response`, `dest`, `source`, `request_id`, `reply_id`, `emoji`, `bitfield`
- - Crypto: `key`/`psk` (`default`, `none`, `simple0..10`, `hex:<...>`, `base64:<...>`), `encrypt` (`true|false|auto`)
-
-Notes:
-
- - If `encrypt=true` then `key` must resolve to 16 or 32 bytes.
- - If a `MESH:` command is invalid it is rejected (no payload is emitted), and an error is logged.
-
Interface
The top and bottom bars of the channel window are described [here](../../../sdrgui/channel/readme.md)
-
+
1: Frequency shift from center frequency of reception
@@ -70,19 +51,19 @@ Use this button to mute/unmute transmission.
4: Bandwidth
-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.
+This is the bandwidth of the CSS signal. The signal sweeps between the lower and the upper frequency of this bandwidth. The sample rate of the CSS 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. Extra divisor of 128 is provided to achieve smaller bandwidths that can fit in a SSB channel. Finally special divisors from a 384 kHz base are provided to allow even more narrow bandwidths.
Thus available bandwidths are:
- - **500000** (500000 / 1) Hz
+ - **500000** (500000 / 1) Hz - **Meshtastic "turbo" modes**
- **400000** (400000 / 1) Hz not in LoRa standard
- **333333** (333333 / 1) Hz
- - **250000** (500000 / 2) Hz
+ - **250000** (500000 / 2) Hz - **used by Meshtastic**
- **200000** (400000 / 2) Hz not in LoRa standard
- **166667** (333333 / 2) Hz
- - **125000** (500000 / 4) Hz
+ - **125000** (500000 / 4) Hz - **used by Meshtastic**
- **100000** (400000 / 4) Hz not in LoRa standard
- **83333** (333333 / 4) Hz
- **62500** (500000 / 8) Hz
@@ -105,21 +86,21 @@ Thus available bandwidths are:
- **488** (500000 / 1024) Hz not in LoRa standard
- **375** (384000 / 1024) Hz not in LoRa standard
-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. When using Meshtastic presets you have to make sure this condition is set yourself.
+The CSS 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. When using Meshtastic presets you have to make sure this condition is set yourself.
-16: Invert chirp ramps
+5: Invert chirp ramps (disabled)
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
+6: 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).
+This is the Spread Factor parameter of the CSS 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).
-6: Distance Enhancement factor
+7: Distance Enhancement factor
-The LoRa standard specifies 0 (no DE) or 2 (DE active). The ChirpChat range is extended to all values between 0 and 4 bits.
+The LoRa standard specifies 0 (no DE) or 2 (DE active). The CSS standard range is extended to all values between 0 and 4 bits.
The LoRa standard also specifies that the LowDataRateOptimization flag (thus DE=2 vs DE=0 here) should be set when the symbol time defined as BW / 2^SF exceeds 16 ms (See section 4.1.1.6 of the SX127x datasheet). In practice this happens for SF=11 and SF=12 and large enough bandwidths (you can do the maths).
@@ -135,56 +116,101 @@ This is the number of preamble chirps to transmit that are used for the Rx to sy
When sending a message repeatedly this is the time between the end of one transmission and the start of the next transmission.
-10: Message and encoding details
+10: Region preset
-
+Region related preset
-10.1: Modulation scheme
+- **US**: US 902 MHz band
+- **EU_433**: European 433 MHz band
+- **EU_868**: European 868 MHz band
+- **ANZ**: Australia and New Zealand 915-928 MHz band
+- **JP**: Japan 920-923 MHz band
+- **CN**: China 470-510 MHz band
+- **KR**: South Korea 920-922 MHz band
+- **TW**: Taiwan 920-925 MHz band
+- **IN**: India 865-866 MHz band
+- **TH**: Thailand 920-925 MHz band
+- **BR_902**: Brazil 902-907 MHz band
+- **LORA_24**: LoRa 902.125 MHz
- - **LoRa**: LoRa compatible for Meshtastic
+11: Preset
-10.2: Number of FEC parity bits
+- **LONG_FAST**: BW=250kHz SF=11, DE=0, FEC=4/5
+- **LONG_SLOW**: BW=125kHz, SF=12, DE=2, FEC=4/8
+- **LONG_MODERATE**: BW=125kHz, SF=11, DE=0, FEC=4/5
+- **LONG_TURBO**: BW=500kHz, SF=11, DE=0, FEC=4/8 (a.k.a Long Range / Turbo)
+- **MEDIUM_FAST**: BW=250kHz, SF=9, DE=0, FEC=4/5
+- **MEDIUM_SLOW**: BW=250kHz, SF=10, DE=0, FEC=4/5
+- **SHORT_FAST**: BW=250kHz, SF=7, DE=0, FEC=4/5
+- **SHORT_SLOW**: BW=250kHz, SF=8, DE=0, FEC=4/5
+- **SHORT_TURBO**: BW=500kHz, SF=7, DE=0, FEC=4/5 (a.k.a Short Range / Turbo)
-Each byte of the payload is split into two four bit nibbles and Hamming code of various "strength" in number of parity bits can be applied to these nibbles. The number of parity bits can vary from 1 to 4. 0 (no FEC) has been added but is not part of the LoRa original standard:
+12: Channel
- - **0**: no FEC
- - **1**: 1 bit parity thus Hamming H(4,5) applies
- - **2**: 2 bit parity thus Hamming H(4,6) applies
- - **3**: 3 bit parity thus Hamming H(4,7) applies
- - **4**: 4 bit parity thus Hamming H(4,8) applies
+Select channel within regional band
-10.9: Message selector
+13: Apply settings
-This lets you choose which pre-formatted message to send:
+Apply or re-apply the region, preset and channel settings
- - **Text**: plain text, either just text or formatted text for Meshtastic transmission (see above)
+A: Other settings
-10.11 Play current message immediately
+
-This starts playing the current selected message immediately. It may be necessary to use this button after a change of modulation and/or coding parameters.
-10.12: Number of message repetitions
+A.1: FEC ratio
-The message is repeated this number of times (use 0 for infinite). The end of one message sequence and the start of the next is separated by the delay specified with the "Idle" slidebar (9)
+- **1**: Hamming H(4,5)
+- **2**: Hamming H(4,6)
+- **3**: Hamming H(4,7)
+- **4**: Hamming H(4,8)
-10.14: Sync word
+A.2: Sync word
-This is a LoRa specific feature and is the sync word (byte) to transmit entered as a 2 nibble hexadecimal number. For Meshtastic this is 0x2B.
+Standard Meshtastic sync word is 0x2B
-11: Message text
+A.3: Play message
-This window lets you edit the message selected in (10.9). You can use `%n` placeholders that depend on the type of message selected.
+A.4: Message repetition
- - **Text**: free text message no placeholders
+Repeat message with an interval of n seconds set at (9). 0 is infinite repetion.
-13: Symbol time and message length
+14: Message and encoding details
-This is the duration of a symbol or chirp in milliseconds followed by the message length in the number of symbols
+A simple string is sent as is with the LoRa protocol. To send a Meshtastic formatted message you have to prepend it with `MESH:`
-14: Payload time
+The plugin will build a full Meshtastic over-the-air frame (16-byte header + protobuf `Data` payload) and encrypt it with AES-CTR when enabled.
-This is the duration of the message payload in milliseconds. It excludes the preamble, the sync word and synchronization (SFD) sequence.
+Quick example:
-15: Total time
+`MESH:from=0x11223344;to=0xffffffff;id=0x1234;key=default;port=TEXT;text=hello mesh;want_ack=1;hop_limit=3`
-This is the duration of the full message in milliseconds.
+Supported fields:
+
+ - Header: `to`, `from`, `id`, `hop_limit`, `hop_start`, `want_ack`, `via_mqtt`, `next_hop`, `relay_node`
+ - Data protobuf: `port`/`portnum`, `text`, `payload_hex`, `payload_base64`/`payload_b64`, `want_response`, `dest`, `source`, `request_id`, `reply_id`, `emoji`, `bitfield`
+ - Crypto: `key`/`psk` (`default`, `none`, `simple0..10`, `hex:<...>`, `base64:<...>`), `encrypt` (`true|false|auto`)
+
+Notes:
+
+ - If `encrypt=true` then `key` must resolve to 16 or 32 bytes.
+ - If a `MESH:` command is invalid it is rejected (no payload is emitted), and an error is logged.
+
+15: Bytes message
+
+Send bytes with the LoRa protocol
+
+16: Symbol time and message length
+
+- **Tsym**: Symbol time
+- **ML**: Message length in number of symbols
+- **Tpay**: Payload time
+- **Ttot**: Total on-air time
+
+17: UDP source
+
+Take message from UDP
+
+18: UDP address
+
+19: UPD port