From b71210351999060126e1126aeecb371676651cdd Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 13 Feb 2024 16:00:05 +1100 Subject: [PATCH 1/5] lora-sx126x: Fix invalid default configuration after reset. According to the docs, only freq_khz was needed for working output. However: - Without output_power setting, no output from SX1262 antenna (theory: output routed to the SX1261 antenna). - SF,BW,etc. settings were different from the SX127x power on defaults, so modems with an identical configuration were unable to communicate. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton --- micropython/lora/lora-sx126x/lora/sx126x.py | 22 ++++++++++++--------- micropython/lora/lora/lora/modem.py | 7 ++++--- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/micropython/lora/lora-sx126x/lora/sx126x.py b/micropython/lora/lora-sx126x/lora/sx126x.py index f0cd42793..f1aa5a871 100644 --- a/micropython/lora/lora-sx126x/lora/sx126x.py +++ b/micropython/lora/lora-sx126x/lora/sx126x.py @@ -163,6 +163,9 @@ def __init__( # 0x02 is 40us, default value appears undocumented but this is the SX1276 default self._ramp_val = 0x02 + # Configure the SX126x at least once after reset + self._configured = False + if reset: # If the caller supplies a reset pin argument, reset the radio reset.init(Pin.OUT, value=0) @@ -385,22 +388,22 @@ def configure(self, lora_cfg): syncword = 0x0404 + ((syncword & 0x0F) << 4) + ((syncword & 0xF0) << 8) self._cmd(">BBH", _CMD_WRITE_REGISTER, _REG_LSYNCRH, syncword) - if "output_power" in lora_cfg: + if not self._configured or any( + key in lora_cfg for key in ("output_power", "pa_ramp_us", "tx_ant") + ): pa_config_args, self._output_power = self._get_pa_tx_params( - lora_cfg["output_power"], lora_cfg.get("tx_ant", None) + lora_cfg.get("output_power", self._output_power), lora_cfg.get("tx_ant", None) ) self._cmd("BBBBB", _CMD_SET_PA_CONFIG, *pa_config_args) - if "pa_ramp_us" in lora_cfg: - self._ramp_val = self._get_pa_ramp_val( - lora_cfg, [10, 20, 40, 80, 200, 800, 1700, 3400] - ) + if "pa_ramp_us" in lora_cfg: + self._ramp_val = self._get_pa_ramp_val( + lora_cfg, [10, 20, 40, 80, 200, 800, 1700, 3400] + ) - if "output_power" in lora_cfg or "pa_ramp_us" in lora_cfg: - # Only send the SetTxParams command if power level or PA ramp time have changed self._cmd("BBB", _CMD_SET_TX_PARAMS, self._output_power, self._ramp_val) - if any(key in lora_cfg for key in ("sf", "bw", "coding_rate")): + if not self._configured or any(key in lora_cfg for key in ("sf", "bw", "coding_rate")): if "sf" in lora_cfg: self._sf = lora_cfg["sf"] if self._sf < _CFG_SF_MIN or self._sf > _CFG_SF_MAX: @@ -441,6 +444,7 @@ def configure(self, lora_cfg): self._reg_write(_REG_RX_GAIN, 0x96 if lora_cfg["rx_boost"] else 0x94) self._check_error() + self._configured = True def _invert_workaround(self, enable): # Apply workaround for DS 15.4 Optimizing the Inverted IQ Operation diff --git a/micropython/lora/lora/lora/modem.py b/micropython/lora/lora/lora/modem.py index e71d4ec72..499712acf 100644 --- a/micropython/lora/lora/lora/modem.py +++ b/micropython/lora/lora/lora/modem.py @@ -37,10 +37,11 @@ def __init__(self, ant_sw): self._ant_sw = ant_sw self._irq_callback = None - # Common configuration settings that need to be tracked by all modem drivers - # (Note that subclasses may set these to other values in their constructors, to match - # the power-on-reset configuration of a particular modem.) + # Common configuration settings that need to be tracked by all modem drivers. # + # Where modem hardware sets different values after reset, the driver should + # set them back to these defaults (if not provided by the user), so that + # behaviour remains consistent between different modems using the same driver. self._rf_freq_hz = 0 # Needs to be set via configure() self._sf = 7 # Spreading factor self._bw_hz = 125000 # Reset value From ad6ab5a78c207cb663dfb82255798c4cfad51b5f Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 13 Feb 2024 16:01:28 +1100 Subject: [PATCH 2/5] lora-sync: Fix race with fast or failed send(). If send completes before the first call to poll_send(), the driver could get stuck in _sync_wait(). This had much less impact before rp2 port went tickless, as _sync_wait(will_irq=True) calls machine.idle() which may not wake very frequently on a tickless port. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton --- micropython/lora/lora-sync/lora/sync_modem.py | 2 +- micropython/lora/lora-sync/manifest.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/micropython/lora/lora-sync/lora/sync_modem.py b/micropython/lora/lora-sync/lora/sync_modem.py index 27c2f19d1..585ae2cb4 100644 --- a/micropython/lora/lora-sync/lora/sync_modem.py +++ b/micropython/lora/lora-sync/lora/sync_modem.py @@ -42,8 +42,8 @@ def send(self, packet, tx_at_ms=None): tx = True while tx is True: - tx = self.poll_send() self._sync_wait(will_irq) + tx = self.poll_send() return tx def recv(self, timeout_ms=None, rx_length=0xFF, rx_packet=None): diff --git a/micropython/lora/lora-sync/manifest.py b/micropython/lora/lora-sync/manifest.py index 57b9d21d8..1936a50e4 100644 --- a/micropython/lora/lora-sync/manifest.py +++ b/micropython/lora/lora-sync/manifest.py @@ -1,3 +1,3 @@ -metadata(version="0.1.0") +metadata(version="0.1.1") require("lora") package("lora") From 546284817af7840bf4e78539ca671371f9bbed23 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 13 Feb 2024 16:10:59 +1100 Subject: [PATCH 3/5] lora-sx127x: Implement missing syncword support. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton --- micropython/lora/lora-sx127x/lora/sx127x.py | 3 +++ micropython/lora/lora-sx127x/manifest.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/micropython/lora/lora-sx127x/lora/sx127x.py b/micropython/lora/lora-sx127x/lora/sx127x.py index 3f94aaf0c..0226c9696 100644 --- a/micropython/lora/lora-sx127x/lora/sx127x.py +++ b/micropython/lora/lora-sx127x/lora/sx127x.py @@ -519,6 +519,9 @@ def configure(self, lora_cfg): self._reg_update(_REG_MODEM_CONFIG3, update_mask, modem_config3) + if "syncword" in lora_cfg: + self._reg_write(_REG_SYNC_WORD, lora_cfg["syncword"]) + def _reg_write(self, reg, value): self._cs(0) if isinstance(value, int): diff --git a/micropython/lora/lora-sx127x/manifest.py b/micropython/lora/lora-sx127x/manifest.py index 57b9d21d8..1936a50e4 100644 --- a/micropython/lora/lora-sx127x/manifest.py +++ b/micropython/lora/lora-sx127x/manifest.py @@ -1,3 +1,3 @@ -metadata(version="0.1.0") +metadata(version="0.1.1") require("lora") package("lora") From 35bb7952ba480de44a88031bba2311171bea9837 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 13 Feb 2024 16:11:18 +1100 Subject: [PATCH 4/5] lora-sx126x: Fix syncword setting. Fixes issue #796. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton --- micropython/lora/lora-sx126x/lora/sx126x.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/micropython/lora/lora-sx126x/lora/sx126x.py b/micropython/lora/lora-sx126x/lora/sx126x.py index f1aa5a871..ff0263d9d 100644 --- a/micropython/lora/lora-sx126x/lora/sx126x.py +++ b/micropython/lora/lora-sx126x/lora/sx126x.py @@ -386,7 +386,7 @@ def configure(self, lora_cfg): # see # https://www.thethingsnetwork.org/forum/t/should-private-lorawan-networks-use-a-different-sync-word/34496/15 syncword = 0x0404 + ((syncword & 0x0F) << 4) + ((syncword & 0xF0) << 8) - self._cmd(">BBH", _CMD_WRITE_REGISTER, _REG_LSYNCRH, syncword) + self._cmd(">BHH", _CMD_WRITE_REGISTER, _REG_LSYNCRH, syncword) if not self._configured or any( key in lora_cfg for key in ("output_power", "pa_ramp_us", "tx_ant") From 224246531ee1d525deb087faf104d66a5d02f4c5 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 13 Feb 2024 16:27:21 +1100 Subject: [PATCH 5/5] lora-sx126x: Clean up some struct formatting. Changes are cosmetic - and maybe very minor code size - but not functional. _reg_read() was calling struct.packinto() with an incorrect number of arguments but it seems like MicroPython didn't mind, as result is correct for both versions. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton --- micropython/lora/lora-sx126x/lora/sx126x.py | 8 ++++---- micropython/lora/lora-sx126x/manifest.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/micropython/lora/lora-sx126x/lora/sx126x.py b/micropython/lora/lora-sx126x/lora/sx126x.py index ff0263d9d..eeb3bffb7 100644 --- a/micropython/lora/lora-sx126x/lora/sx126x.py +++ b/micropython/lora/lora-sx126x/lora/sx126x.py @@ -469,7 +469,7 @@ def calibrate(self): # See DS 13.1.12 Calibrate Function # calibParam 0xFE means to calibrate all blocks. - self._cmd("BBH", _CMD_SET_RX, timeout >> 16, timeout) + self._cmd(">BBH", _CMD_SET_RX, timeout >> 16, timeout) # 24 bits return self._dio1 @@ -729,10 +729,10 @@ def _cmd(self, fmt, *write_args, n_read=0, write_buf=None, read_buf=None): return res def _reg_read(self, addr): - return self._cmd("BBBB", _CMD_READ_REGISTER, addr >> 8, addr & 0xFF, n_read=1)[0] + return self._cmd(">BHB", _CMD_READ_REGISTER, addr, 0, n_read=1)[0] def _reg_write(self, addr, val): - return self._cmd("BBBB", _CMD_WRITE_REGISTER, addr >> 8, addr & 0xFF, val & 0xFF) + return self._cmd(">BHB", _CMD_WRITE_REGISTER, addr, val & 0xFF) class _SX1262(_SX126x): diff --git a/micropython/lora/lora-sx126x/manifest.py b/micropython/lora/lora-sx126x/manifest.py index 1936a50e4..177877091 100644 --- a/micropython/lora/lora-sx126x/manifest.py +++ b/micropython/lora/lora-sx126x/manifest.py @@ -1,3 +1,3 @@ -metadata(version="0.1.1") +metadata(version="0.1.2") require("lora") package("lora")