mirror of
https://github.com/apache/nuttx.git
synced 2026-08-06 21:19:03 +00:00
wireless/lpwan/sx127x: fix the frequency step, the band and the LoRa only build
- The frequency step was truncated to 61 Hz, while it is FXOSC/(2**19), about 61.035 Hz. The error puts a 915 MHz channel more than 500 kHz away from the requested frequency, outside its own bandwidth. - The low or high frequency front end was left at its reset value, so a board wired for 868 or 915 MHz neither transmitted nor received. - sx127x_rx_watchdog() is only used by the FSK and OOK path but was compiled whenever receive support was on, so a LoRa only configuration failed to build with -Werror. nrf52840-dk:sx127x is such a configuration. Adds the sync word, the default bandwidth and the default spreading factor as configuration options, all defaulting to the previous behaviour, and a page for the driver under components/drivers. Assisted-by: Claude Code 4.8 Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
This commit is contained in:
parent
f37bc4546e
commit
7bda3b7c8b
10 changed files with 202 additions and 8 deletions
|
|
@ -7,4 +7,5 @@ LPWAN
|
|||
|
||||
lora_gw.rst
|
||||
sx126x.rst
|
||||
sx127x.rst
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,132 @@
|
|||
.. _sx127x:
|
||||
|
||||
=================
|
||||
SX127x LoRa radio
|
||||
=================
|
||||
|
||||
The SX127x family, which includes the SX1272 and the SX1276 found on most
|
||||
modules and development boards, is a sub-GHz transceiver doing LoRa as well
|
||||
as FSK and OOK. Unlike a concentrator it demodulates one channel at a time,
|
||||
so frequency, spreading factor and bandwidth are settings of the radio and
|
||||
not attributes of each packet.
|
||||
|
||||
The driver is enabled with ``CONFIG_LPWAN_SX127X`` and registers a character
|
||||
device, ``/dev/sx127x`` by convention.
|
||||
|
||||
Userspace API
|
||||
=============
|
||||
|
||||
Reading and writing
|
||||
-------------------
|
||||
|
||||
``write`` transmits the given bytes with the parameters currently configured.
|
||||
``read`` returns one received packet, blocking until one arrives; with
|
||||
``CONFIG_LPWAN_SX127X_RXFIFO_LEN`` the driver keeps a small queue of them, so
|
||||
a reader that falls behind loses the oldest rather than the newest.
|
||||
|
||||
Each packet is preceded by a ``struct sx127x_read_hdr_s``, which carries the
|
||||
payload length together with the received power and, in LoRa mode, the signal
|
||||
to noise ratio of that packet.
|
||||
|
||||
IOCTL commands
|
||||
--------------
|
||||
|
||||
The basic radio parameters use the common commands of
|
||||
``nuttx/wireless/ioctl.h``: ``WLIOC_SETRADIOFREQ`` and ``WLIOC_GETRADIOFREQ``
|
||||
for the frequency in Hz, ``WLIOC_SETTXPOWER`` and ``WLIOC_GETTXPOWER`` for
|
||||
the output power in dBm. Both may be further limited by the board logic.
|
||||
|
||||
The rest is in ``nuttx/wireless/lpwan/sx127x.h``:
|
||||
|
||||
* ``SX127XIOC_MODULATIONSET`` and ``SX127XIOC_MODULATIONGET`` choose between
|
||||
LoRa, FSK and OOK.
|
||||
|
||||
* ``SX127XIOC_OPMODESET`` and ``SX127XIOC_OPMODEGET`` move the radio between
|
||||
sleep, standby, transmit, receive and channel activity detection.
|
||||
|
||||
* ``SX127XIOC_SYNCWORDSET`` and ``SX127XIOC_SYNCWORDGET`` change the sync
|
||||
word, and ``SX127XIOC_PREAMBLESET`` and ``SX127XIOC_PREAMBLEGET`` the
|
||||
preamble length.
|
||||
|
||||
* ``SX127XIOC_RSSIGET`` reads the current RSSI, ``SX127XIOC_CHANSCAN`` scans
|
||||
a channel and ``SX127XIOC_RANDOMGET`` returns a random number taken from
|
||||
the noise of the receiver.
|
||||
|
||||
Note that the spreading factor, the bandwidth and the coding rate have no
|
||||
ioctl of their own yet: they come from the configuration below.
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
============================================ ==================================
|
||||
Option Meaning
|
||||
============================================ ==================================
|
||||
``LPWAN_SX127X_RFFREQ_DEFAULT`` Frequency, in Hz, at registration
|
||||
``LPWAN_SX127X_TXPOWER_DEFAULT`` Output power in dBm
|
||||
``LPWAN_SX127X_MODULATION_DEFAULT`` 1 for FSK, 2 for OOK, 3 for LoRa
|
||||
``LPWAN_SX127X_RXSUPPORT`` Build the receive path
|
||||
``LPWAN_SX127X_TXSUPPORT`` Build the transmit path
|
||||
``LPWAN_SX127X_LORA`` Build the LoRa modem
|
||||
``LPWAN_SX127X_FSKOOK`` Build the FSK and OOK modem
|
||||
``LPWAN_SX127X_LORA_SYNCWORD`` Sync word, see below
|
||||
``LPWAN_SX127X_LORA_BW_DEFAULT`` Bandwidth, 7 selects 125 kHz
|
||||
``LPWAN_SX127X_LORA_SF_DEFAULT`` Spreading factor, 6 to 12
|
||||
``LPWAN_SX127X_CRCON`` Append and check a CRC
|
||||
``LPWAN_SX127X_RXFIFO_LEN`` Packets buffered by the driver
|
||||
============================================ ==================================
|
||||
|
||||
Talking to another radio
|
||||
========================
|
||||
|
||||
Two settings decide whether two devices hear each other at all, and both are
|
||||
silent failures when they disagree:
|
||||
|
||||
* **Band.** The chip has separate low and high frequency front ends and the
|
||||
modem has to be told which one is in use. The driver derives that from the
|
||||
configured frequency, using the high band above 525 MHz.
|
||||
|
||||
* **Sync word.** ``CONFIG_LPWAN_SX127X_LORA_SYNCWORD`` defaults to 0x12, the
|
||||
private network value. A public LoRaWAN network uses 0x34, and a receiver
|
||||
configured for the other value never even detects the frame.
|
||||
|
||||
Beyond those, the spreading factor, the bandwidth and the coding rate have to
|
||||
match on both sides.
|
||||
|
||||
Two boards reach each other with the ``sx127x`` example of
|
||||
``apps/examples/sx127x_demo``. Start the receiver first, since the example
|
||||
gives up after the time given with ``-d``::
|
||||
|
||||
board A> sx127x -m 0 -f 917200000 -r -d 60
|
||||
board B> sx127x -m 0 -f 917200000 -t -p 0 -l 32 -d 30
|
||||
|
||||
The receiver prints the payload of every packet along with its signal to
|
||||
noise ratio and its received power. Keep the boards a metre or so apart: at a
|
||||
few centimetres a transmitter saturates the other receiver and the packets
|
||||
arrive with a broken CRC.
|
||||
|
||||
The same commands work against a gateway. A concentrator running the ``lora``
|
||||
command of ``apps/wireless/lora_pkt_fwd`` sends a packet with
|
||||
``lora tx 917200000 7 hello``, which any board listening on that frequency
|
||||
receives; and a board transmitting as above shows up on the gateway as an
|
||||
ordinary uplink. See :ref:`lora_gw` for the gateway side.
|
||||
|
||||
Board implementation
|
||||
====================
|
||||
|
||||
The driver is registered with ``sx127x_register``, which takes an SPI bus and
|
||||
a ``struct sx127x_lower_s``. That structure carries what the chip needs from
|
||||
the board: attaching the DIO0 interrupt, which signals the end of a
|
||||
transmission or a reception, a ``reset`` hook, and the optional
|
||||
``opmode_change``, ``freq_select`` and ``pa_select`` hooks used by boards
|
||||
whose antenna switch or power amplifier path depends on the operating mode,
|
||||
the frequency or the requested power. See
|
||||
``nuttx/wireless/lpwan/sx127x.h``.
|
||||
|
||||
Boards
|
||||
======
|
||||
|
||||
* :ref:`ST B-L072Z-LRWAN1 <b-l072z-lrwan1>`
|
||||
* :ref:`Nucleo L073RZ <nucleo-l073rz>`
|
||||
* :ref:`Nucleo F091RC <nucleo-f091rc>`
|
||||
* :ref:`nRF52840-DK <nrf52840-dk>`
|
||||
* :ref:`Heltec WiFi LoRa 32 <heltec_wifi_lora32>`
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
.. _nrf52840-dk:
|
||||
|
||||
===========
|
||||
nRF52840-DK
|
||||
===========
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
.. _nucleo-f091rc:
|
||||
|
||||
=================
|
||||
ST Nucleo F091RC
|
||||
=================
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
.. _b-l072z-lrwan1:
|
||||
|
||||
=================
|
||||
ST B-L072Z-LRWAN1
|
||||
=================
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
.. _nucleo-l073rz:
|
||||
|
||||
================
|
||||
ST Nucleo L073RZ
|
||||
================
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
.. _heltec_wifi_lora32:
|
||||
|
||||
======================
|
||||
Heltec WiFi LoRa 32 V2
|
||||
======================
|
||||
|
|
|
|||
|
|
@ -79,6 +79,29 @@ config LPWAN_SX127X_LORA_IMPHEADER
|
|||
range 0 1
|
||||
default 0
|
||||
|
||||
config LPWAN_SX127X_LORA_SYNCWORD
|
||||
hex "SX127X LORA sync word"
|
||||
default 0x12
|
||||
---help---
|
||||
Sync word written to the modem: 0x12 for a private network, 0x34
|
||||
for the public LoRaWAN network. A gateway configured for the
|
||||
public network does not even detect a frame sent with the private
|
||||
sync word, so this has to match the other end.
|
||||
|
||||
config LPWAN_SX127X_LORA_BW_DEFAULT
|
||||
int "SX127X LORA default bandwidth"
|
||||
default 0
|
||||
range 0 9
|
||||
---help---
|
||||
Bandwidth used until it is changed: 0 = 7.8 kHz, 1 = 10.4 kHz,
|
||||
2 = 15.6 kHz, 3 = 20.8 kHz, 4 = 31.2 kHz, 5 = 41.4 kHz,
|
||||
6 = 62.5 kHz, 7 = 125 kHz, 9 = 250 kHz. LoRaWAN uses 125 kHz.
|
||||
|
||||
config LPWAN_SX127X_LORA_SF_DEFAULT
|
||||
int "SX127X LORA default spreading factor"
|
||||
default 7
|
||||
range 6 12
|
||||
|
||||
endif # LPWAN_SX127X_LORA
|
||||
|
||||
config LPWAN_SX127X_FSKOOK
|
||||
|
|
|
|||
|
|
@ -130,11 +130,11 @@
|
|||
|
||||
/* Default LORA bandwidth */
|
||||
|
||||
#define SX127X_LRM_BW_DEFAULT LORA_BANDWIDTH_7P8KHZ
|
||||
#define SX127X_LRM_BW_DEFAULT CONFIG_LPWAN_SX127X_LORA_BW_DEFAULT
|
||||
|
||||
/* Default SF for LORA */
|
||||
|
||||
#define SX127X_LRM_SF_DEFAULT (7)
|
||||
#define SX127X_LRM_SF_DEFAULT CONFIG_LPWAN_SX127X_LORA_SF_DEFAULT
|
||||
|
||||
/* FSK/OOK RX/TX FIFO size (two separate FIFOs) */
|
||||
|
||||
|
|
@ -1286,7 +1286,12 @@ errout:
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* The stall watchdog is only wired into the FSK and OOK receive path, so a
|
||||
* configuration with LoRa alone must not compile it.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_LPWAN_SX127X_RXSUPPORT) && \
|
||||
defined(CONFIG_LPWAN_SX127X_FSKOOK) && \
|
||||
CONFIG_LPWAN_SX127X_RX_TIMEOUT > 0
|
||||
static void sx127x_rx_watchdog(FAR void *arg)
|
||||
{
|
||||
|
|
@ -1321,7 +1326,7 @@ static void sx127x_rx_watchdog(FAR void *arg)
|
|||
sx127x_rx_watchdog, dev,
|
||||
MSEC2TICK(dev->rx_timeout));
|
||||
}
|
||||
#endif /* CONFIG_LPWAN_SX127X_RXSUPPORT && CONFIG_LPWAN_SX127X_RX_TIMEOUT > 0 */
|
||||
#endif /* RXSUPPORT && FSKOOK && RX_TIMEOUT > 0 */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sx127x_lora_isr0_process
|
||||
|
|
@ -3875,6 +3880,22 @@ static int sx127x_frequency_set(FAR struct sx127x_dev_s *dev, uint32_t freq)
|
|||
|
||||
sx127x_writeregbyte(dev, SX127X_CMN_FRFLSB, SX127X_CMN_FRF_LSB(frf));
|
||||
|
||||
/* Tell the modem which of the two front ends the frequency belongs to.
|
||||
* The chip comes up in low frequency mode, and a board wired for the high
|
||||
* band (868 or 915 MHz) then neither transmits nor receives anything.
|
||||
*/
|
||||
|
||||
if (freq > SX127X_HFBAND_THR)
|
||||
{
|
||||
sx127x_modregbyte(dev, SX127X_CMN_OPMODE, 0,
|
||||
SX127X_CMN_OPMODE_LFMODEON);
|
||||
}
|
||||
else
|
||||
{
|
||||
sx127x_modregbyte(dev, SX127X_CMN_OPMODE,
|
||||
SX127X_CMN_OPMODE_LFMODEON, 0);
|
||||
}
|
||||
|
||||
/* Unlock SPI */
|
||||
|
||||
sx127x_unlock(dev->spi);
|
||||
|
|
|
|||
|
|
@ -181,7 +181,8 @@
|
|||
/* FSK/OOK/LORA: RF carrier frequency */
|
||||
|
||||
#define SX127X_CMN_FRF_MAX (0xffffff)
|
||||
#define SX127X_FRF_FROM_FREQ(freq) (freq/SX127X_FSTEP)
|
||||
#define SX127X_FRF_FROM_FREQ(freq) \
|
||||
((uint32_t)(((uint64_t)(freq) << SX127X_FSTEP_SHIFT) / SX127X_FXOSC))
|
||||
#define SX127X_CMN_FRF_MSB(frf) ((frf >> 16) & 0xff)
|
||||
#define SX127X_CMN_FRF_MID(frf) ((frf >> 8) & 0xff)
|
||||
#define SX127X_CMN_FRF_LSB(frf) ((frf >> 0) & 0xff)
|
||||
|
|
@ -337,7 +338,8 @@
|
|||
|
||||
#define SX127X_FOM_FDEV_MSB_MASK (0x3f)
|
||||
#define SX127X_FOM_FDEV_MAX (0x3fff)
|
||||
#define SX127X_FDEV_FROM_FREQ(freq) (freq/SX127X_FSTEP)
|
||||
#define SX127X_FDEV_FROM_FREQ(freq) \
|
||||
((uint32_t)(((uint64_t)(freq) << SX127X_FSTEP_SHIFT) / SX127X_FXOSC))
|
||||
#define SX127X_FOM_FDEV_MSB(v) ((v >> 8) & 0xff)
|
||||
#define SX127X_FOM_FDEV_LSB(v) ((v >> 0) & 0xff)
|
||||
|
||||
|
|
@ -790,7 +792,7 @@
|
|||
|
||||
/* LORA: LORA Sync Word */
|
||||
|
||||
#define SX127X_LRM_SYNCWORD_DEFAULT (0x12)
|
||||
#define SX127X_LRM_SYNCWORD_DEFAULT CONFIG_LPWAN_SX127X_LORA_SYNCWORD
|
||||
#define SX127X_LRM_SYNCWORD_LORAWAN (0x34)
|
||||
|
||||
/* Lora data rate:
|
||||
|
|
@ -810,9 +812,14 @@
|
|||
|
||||
#define SX127X_FXOSC (32000000)
|
||||
|
||||
/* FSTEP is FXOSC/(2**19) =~ 61 Hz */
|
||||
/* One step of the frequency synthesiser is FXOSC/(2**19), about 61.035 Hz.
|
||||
* It is not an integer, so the conversions below multiply first and divide
|
||||
* afterwards instead of dividing by a truncated step: rounding it down to
|
||||
* 61 Hz places a 915 MHz channel more than 500 kHz away from the requested
|
||||
* frequency, well outside the bandwidth of the channel.
|
||||
*/
|
||||
|
||||
#define SX127X_FSTEP (SX127X_FXOSC/(2<<18))
|
||||
#define SX127X_FSTEP_SHIFT (19)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data Types
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue