hwconfig failsafe and duty cycle 10/6->10/4 (tests showed better reception)

This commit is contained in:
liquidraver
2026-05-05 10:46:58 +02:00
parent 9a1569c511
commit ee2990fd16
11 changed files with 938 additions and 912 deletions
+78 -76
View File
@@ -1,76 +1,78 @@
/*
* SPDX-License-Identifier: Apache-2.0
* LR1110 hardware hooks for LoRaRadioBase.
*/
#include "LR1110Radio.h"
#include <zephyr/kernel.h>
/* LR11xx driver extension API */
extern "C" {
#include "lr11xx_lora.h"
}
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(lr1110_radio, CONFIG_ZEPHCORE_LORA_LOG_LEVEL);
namespace mesh {
K_THREAD_STACK_DEFINE(lr11xx_tx_wait_stack, TX_WAIT_THREAD_STACK_SIZE);
LR1110Radio::LR1110Radio(const struct device *lora_dev, MainBoard &board,
NodePrefs *prefs)
: LoRaRadioBase(lora_dev, board, prefs)
{
}
void LR1110Radio::begin()
{
startTxThread(lr11xx_tx_wait_stack,
K_THREAD_STACK_SIZEOF(lr11xx_tx_wait_stack));
LoRaRadioBase::begin();
}
/* ── Hardware primitives ──────────────────────────────────────────────── */
void LR1110Radio::hwConfigure(const struct lora_modem_config &cfg)
{
int ret = lora_config(_dev, const_cast<struct lora_modem_config *>(&cfg));
if (ret < 0) {
LOG_ERR("lora_config failed: %d", ret);
}
}
void LR1110Radio::hwCancelReceive()
{
lora_recv_async(_dev, NULL, NULL);
}
int LR1110Radio::hwSendAsync(uint8_t *buf, uint32_t len,
struct k_poll_signal *sig)
{
return lora_send_async(_dev, buf, len, sig);
}
int16_t LR1110Radio::hwGetCurrentRSSI()
{
return lr11xx_get_rssi_inst(_dev);
}
bool LR1110Radio::hwIsPreambleDetected()
{
return lr11xx_is_receiving(_dev);
}
void LR1110Radio::hwSetRxBoost(bool enable)
{
lr11xx_set_rx_boost(_dev, enable);
}
void LR1110Radio::hwResetAGC()
{
/* Warm sleep → Calibrate(ALL) → re-calibrate image → re-apply RX boost */
lr11xx_reset_agc(_dev);
}
} /* namespace mesh */
/*
* SPDX-License-Identifier: Apache-2.0
* LR1110 hardware hooks for LoRaRadioBase.
*/
#include "LR1110Radio.h"
#include <zephyr/kernel.h>
/* LR11xx driver extension API */
extern "C" {
#include "lr11xx_lora.h"
}
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(lr1110_radio, CONFIG_ZEPHCORE_LORA_LOG_LEVEL);
namespace mesh {
K_THREAD_STACK_DEFINE(lr11xx_tx_wait_stack, TX_WAIT_THREAD_STACK_SIZE);
LR1110Radio::LR1110Radio(const struct device *lora_dev, MainBoard &board,
NodePrefs *prefs)
: LoRaRadioBase(lora_dev, board, prefs)
{
}
void LR1110Radio::begin()
{
startTxThread(lr11xx_tx_wait_stack,
K_THREAD_STACK_SIZEOF(lr11xx_tx_wait_stack));
LoRaRadioBase::begin();
}
/* ── Hardware primitives ──────────────────────────────────────────────── */
bool LR1110Radio::hwConfigure(const struct lora_modem_config &cfg)
{
int ret = lora_config(_dev, const_cast<struct lora_modem_config *>(&cfg));
if (ret < 0) {
LOG_ERR("lora_config failed: %d", ret);
return false;
}
return true;
}
void LR1110Radio::hwCancelReceive()
{
lora_recv_async(_dev, NULL, NULL);
}
int LR1110Radio::hwSendAsync(uint8_t *buf, uint32_t len,
struct k_poll_signal *sig)
{
return lora_send_async(_dev, buf, len, sig);
}
int16_t LR1110Radio::hwGetCurrentRSSI()
{
return lr11xx_get_rssi_inst(_dev);
}
bool LR1110Radio::hwIsPreambleDetected()
{
return lr11xx_is_receiving(_dev);
}
void LR1110Radio::hwSetRxBoost(bool enable)
{
lr11xx_set_rx_boost(_dev, enable);
}
void LR1110Radio::hwResetAGC()
{
/* Warm sleep → Calibrate(ALL) → re-calibrate image → re-apply RX boost */
lr11xx_reset_agc(_dev);
}
} /* namespace mesh */
+33 -33
View File
@@ -1,33 +1,33 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore Radio adapter for LR1110/LR1120/LR1121 using Zephyr LoRa driver
*
* Thin wrapper around LoRaRadioBase — only hardware-specific hooks.
*/
#pragma once
#include "LoRaRadioBase.h"
namespace mesh {
class LR1110Radio : public LoRaRadioBase {
public:
LR1110Radio(const struct device *lora_dev, MainBoard &board,
NodePrefs *prefs = nullptr);
void begin() override;
protected:
/* Hardware primitives */
void hwConfigure(const struct lora_modem_config &cfg) override;
void hwCancelReceive() override;
int hwSendAsync(uint8_t *buf, uint32_t len,
struct k_poll_signal *sig) override;
int16_t hwGetCurrentRSSI() override;
bool hwIsPreambleDetected() override;
void hwSetRxBoost(bool enable) override;
void hwResetAGC() override;
};
} /* namespace mesh */
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore Radio adapter for LR1110/LR1120/LR1121 using Zephyr LoRa driver
*
* Thin wrapper around LoRaRadioBase — only hardware-specific hooks.
*/
#pragma once
#include "LoRaRadioBase.h"
namespace mesh {
class LR1110Radio : public LoRaRadioBase {
public:
LR1110Radio(const struct device *lora_dev, MainBoard &board,
NodePrefs *prefs = nullptr);
void begin() override;
protected:
/* Hardware primitives */
bool hwConfigure(const struct lora_modem_config &cfg) override;
void hwCancelReceive() override;
int hwSendAsync(uint8_t *buf, uint32_t len,
struct k_poll_signal *sig) override;
int16_t hwGetCurrentRSSI() override;
bool hwIsPreambleDetected() override;
void hwSetRxBoost(bool enable) override;
void hwResetAGC() override;
};
} /* namespace mesh */
+77 -75
View File
@@ -1,75 +1,77 @@
/*
* SPDX-License-Identifier: Apache-2.0
* LR2021 hardware hooks for LoRaRadioBase.
*/
#include "LR2021Radio.h"
#include <zephyr/kernel.h>
/* LR20xx driver extension API */
extern "C" {
#include "lr20xx_lora.h"
}
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(lr2021_radio, CONFIG_ZEPHCORE_LORA_LOG_LEVEL);
namespace mesh {
K_THREAD_STACK_DEFINE(lr20xx_tx_wait_stack, TX_WAIT_THREAD_STACK_SIZE);
LR2021Radio::LR2021Radio(const struct device *lora_dev, MainBoard &board,
NodePrefs *prefs)
: LoRaRadioBase(lora_dev, board, prefs)
{
}
void LR2021Radio::begin()
{
startTxThread(lr20xx_tx_wait_stack,
K_THREAD_STACK_SIZEOF(lr20xx_tx_wait_stack));
LoRaRadioBase::begin();
}
/* ── Hardware primitives ──────────────────────────────────────────────── */
void LR2021Radio::hwConfigure(const struct lora_modem_config &cfg)
{
int ret = lora_config(_dev, const_cast<struct lora_modem_config *>(&cfg));
if (ret < 0) {
LOG_ERR("lora_config failed: %d", ret);
}
}
void LR2021Radio::hwCancelReceive()
{
lora_recv_async(_dev, NULL, NULL);
}
int LR2021Radio::hwSendAsync(uint8_t *buf, uint32_t len,
struct k_poll_signal *sig)
{
return lora_send_async(_dev, buf, len, sig);
}
int16_t LR2021Radio::hwGetCurrentRSSI()
{
return lr20xx_get_rssi_inst(_dev);
}
bool LR2021Radio::hwIsPreambleDetected()
{
return lr20xx_is_receiving(_dev);
}
void LR2021Radio::hwSetRxBoost(bool enable)
{
lr20xx_set_rx_boost(_dev, enable);
}
void LR2021Radio::hwResetAGC()
{
lr20xx_reset_agc(_dev);
}
} /* namespace mesh */
/*
* SPDX-License-Identifier: Apache-2.0
* LR2021 hardware hooks for LoRaRadioBase.
*/
#include "LR2021Radio.h"
#include <zephyr/kernel.h>
/* LR20xx driver extension API */
extern "C" {
#include "lr20xx_lora.h"
}
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(lr2021_radio, CONFIG_ZEPHCORE_LORA_LOG_LEVEL);
namespace mesh {
K_THREAD_STACK_DEFINE(lr20xx_tx_wait_stack, TX_WAIT_THREAD_STACK_SIZE);
LR2021Radio::LR2021Radio(const struct device *lora_dev, MainBoard &board,
NodePrefs *prefs)
: LoRaRadioBase(lora_dev, board, prefs)
{
}
void LR2021Radio::begin()
{
startTxThread(lr20xx_tx_wait_stack,
K_THREAD_STACK_SIZEOF(lr20xx_tx_wait_stack));
LoRaRadioBase::begin();
}
/* ── Hardware primitives ──────────────────────────────────────────────── */
bool LR2021Radio::hwConfigure(const struct lora_modem_config &cfg)
{
int ret = lora_config(_dev, const_cast<struct lora_modem_config *>(&cfg));
if (ret < 0) {
LOG_ERR("lora_config failed: %d", ret);
return false;
}
return true;
}
void LR2021Radio::hwCancelReceive()
{
lora_recv_async(_dev, NULL, NULL);
}
int LR2021Radio::hwSendAsync(uint8_t *buf, uint32_t len,
struct k_poll_signal *sig)
{
return lora_send_async(_dev, buf, len, sig);
}
int16_t LR2021Radio::hwGetCurrentRSSI()
{
return lr20xx_get_rssi_inst(_dev);
}
bool LR2021Radio::hwIsPreambleDetected()
{
return lr20xx_is_receiving(_dev);
}
void LR2021Radio::hwSetRxBoost(bool enable)
{
lr20xx_set_rx_boost(_dev, enable);
}
void LR2021Radio::hwResetAGC()
{
lr20xx_reset_agc(_dev);
}
} /* namespace mesh */
+33 -33
View File
@@ -1,33 +1,33 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore Radio adapter for LR2021 using Zephyr LoRa driver
*
* Thin wrapper around LoRaRadioBase — only hardware-specific hooks.
*/
#pragma once
#include "LoRaRadioBase.h"
namespace mesh {
class LR2021Radio : public LoRaRadioBase {
public:
LR2021Radio(const struct device *lora_dev, MainBoard &board,
NodePrefs *prefs = nullptr);
void begin() override;
protected:
/* Hardware primitives */
void hwConfigure(const struct lora_modem_config &cfg) override;
void hwCancelReceive() override;
int hwSendAsync(uint8_t *buf, uint32_t len,
struct k_poll_signal *sig) override;
int16_t hwGetCurrentRSSI() override;
bool hwIsPreambleDetected() override;
void hwSetRxBoost(bool enable) override;
void hwResetAGC() override;
};
} /* namespace mesh */
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore Radio adapter for LR2021 using Zephyr LoRa driver
*
* Thin wrapper around LoRaRadioBase — only hardware-specific hooks.
*/
#pragma once
#include "LoRaRadioBase.h"
namespace mesh {
class LR2021Radio : public LoRaRadioBase {
public:
LR2021Radio(const struct device *lora_dev, MainBoard &board,
NodePrefs *prefs = nullptr);
void begin() override;
protected:
/* Hardware primitives */
bool hwConfigure(const struct lora_modem_config &cfg) override;
void hwCancelReceive() override;
int hwSendAsync(uint8_t *buf, uint32_t len,
struct k_poll_signal *sig) override;
int16_t hwGetCurrentRSSI() override;
bool hwIsPreambleDetected() override;
void hwSetRxBoost(bool enable) override;
void hwResetAGC() override;
};
} /* namespace mesh */
+13 -7
View File
@@ -24,7 +24,7 @@ static uint16_t preambleLengthForSF(uint8_t sf)
}
static constexpr uint16_t RX_DUTY_RX_SYMBOLS = 10;
static constexpr uint16_t RX_DUTY_SLEEP_SYMBOLS = 6;
static constexpr uint16_t RX_DUTY_SLEEP_SYMBOLS = 4;
/* ── Constructor ─────────────────────────────────────────────── */
@@ -306,9 +306,12 @@ void LoRaRadioBase::configureRx()
cfg.frequency, (int)cfg.bandwidth, (int)cfg.datarate,
(int)cfg.coding_rate, cfg.tx_power);
hwConfigure(cfg);
_last_cfg = cfg;
_config_cached = true;
if (hwConfigure(cfg)) {
_last_cfg = cfg;
_config_cached = true;
} else {
_config_cached = false;
}
}
void LoRaRadioBase::configureTx()
@@ -331,9 +334,12 @@ void LoRaRadioBase::configureTx()
return;
}
hwConfigure(cfg);
_last_cfg = cfg;
_config_cached = true;
if (hwConfigure(cfg)) {
_last_cfg = cfg;
_config_cached = true;
} else {
_config_cached = false;
}
}
/* ── Lifecycle ────────────────────────────────────────────────────────── */
+1 -1
View File
@@ -97,7 +97,7 @@ public:
protected:
/* ── Hardware primitives — subclass MUST implement ─────────── */
virtual void hwConfigure(const struct lora_modem_config &cfg) = 0;
virtual bool hwConfigure(const struct lora_modem_config &cfg) = 0;
virtual void hwCancelReceive() = 0;
virtual int hwSendAsync(uint8_t *buf, uint32_t len,
struct k_poll_signal *sig) = 0;
+3 -1
View File
@@ -40,12 +40,14 @@ void SX126xRadio::begin()
/* ── Hardware primitives ──────────────────────────────────────────────── */
void SX126xRadio::hwConfigure(const struct lora_modem_config &cfg)
bool SX126xRadio::hwConfigure(const struct lora_modem_config &cfg)
{
int ret = lora_config(_dev, const_cast<struct lora_modem_config *>(&cfg));
if (ret < 0) {
LOG_ERR("lora_config failed: %d", ret);
return false;
}
return true;
}
void SX126xRadio::hwCancelReceive()
+1 -1
View File
@@ -22,7 +22,7 @@ public:
protected:
/* Hardware primitives */
void hwConfigure(const struct lora_modem_config &cfg) override;
bool hwConfigure(const struct lora_modem_config &cfg) override;
void hwCancelReceive() override;
int hwSendAsync(uint8_t *buf, uint32_t len,
struct k_poll_signal *sig) override;
+114 -112
View File
@@ -1,112 +1,114 @@
/*
* SPDX-License-Identifier: Apache-2.0
* SX127x hardware hooks for LoRaRadioBase — Zephyr loramac-node driver.
*
* The SX127x driver (loramac-node/sx127x.c) exposes only the standard
* Zephyr LoRa API. Chip-specific features that the SX126x native driver
* provides via sx126x_ext.h are not available here:
*
* hwGetCurrentRSSI() — returns -80 dBm sentinel (no hardware path)
* hwIsPreambleDetected()— always false (no preamble-detect IRQ exposed)
* hwSetRxBoost() — no-op (SX127x has no RX boost register)
* hwResetAGC() — no-op (loramac-node manages AGC internally)
* hwIsChipBusy() — inherited false (no BUSY pin on SX127x)
*
* Everything else (configure, send, receive) uses the standard API.
*/
#include "SX127xRadio.h"
#include <zephyr/kernel.h>
#include <zephyr/drivers/lora.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(sx127x_radio, CONFIG_ZEPHCORE_LORA_LOG_LEVEL);
namespace mesh {
K_THREAD_STACK_DEFINE(sx127x_tx_wait_stack, TX_WAIT_THREAD_STACK_SIZE);
SX127xRadio::SX127xRadio(const struct device *lora_dev, MainBoard &board,
NodePrefs *prefs)
: LoRaRadioBase(lora_dev, board, prefs)
{
/* SX127x has no RX boost feature — start with boost disabled */
_rx_boost_enabled = false;
/* loramac-node requires full lora_config() on every TX/RX direction
* change — Radio.SetTxConfig() and Radio.SetRxConfig() configure
* completely disjoint internal state in the loramac-node library. */
_loramac_node = true;
}
void SX127xRadio::begin()
{
startTxThread(sx127x_tx_wait_stack,
K_THREAD_STACK_SIZEOF(sx127x_tx_wait_stack));
LoRaRadioBase::begin();
}
/* ── Hardware primitives ──────────────────────────────────────────────── */
void SX127xRadio::hwConfigure(const struct lora_modem_config &cfg)
{
int ret = lora_config(_dev, const_cast<struct lora_modem_config *>(&cfg));
if (ret < 0) {
LOG_ERR("lora_config failed: %d", ret);
}
}
void SX127xRadio::hwCancelReceive()
{
lora_recv_async(_dev, NULL, NULL);
}
int SX127xRadio::hwSendAsync(uint8_t *buf, uint32_t len,
struct k_poll_signal *sig)
{
return lora_send_async(_dev, buf, len, sig);
}
int16_t SX127xRadio::hwGetCurrentRSSI()
{
/* SX127x loramac-node driver does not expose an instantaneous RSSI
* function via the standard Zephyr API. Return a plausible noise-floor
* sentinel so LoRaRadioBase::triggerNoiseFloorCalibrate() converges
* to a reasonable value rather than being seeded with garbage. */
return -80;
}
bool SX127xRadio::hwIsPreambleDetected()
{
/* No preamble-detect IRQ accessible through the standard Zephyr LoRa
* API for the loramac-node driver. Returning false means TX will
* not abort for an in-progress preamble — acceptable on SX127x. */
return false;
}
void SX127xRadio::hwSetRxBoost(bool enable)
{
/* SX127x does not have a dedicated RX boost / high-sensitivity mode
* switch. Sensitivity is controlled via lora_config tx_power and
* the DTS power-amplifier-output property. Nothing to do here. */
ARG_UNUSED(enable);
}
void SX127xRadio::hwResetAGC()
{
/* The loramac-node SX127x driver manages AGC recalibration internally
* (RadioSetRxConfig re-programs all gain registers on every RX config
* call). No explicit AGC reset is needed or possible via the standard
* API. */
}
void SX127xRadio::resetAGC()
{
/* hwResetAGC() is a no-op, so skip the base-class resetAGC() entirely.
* The base class calls startReceive() after hwResetAGC(), but the
* loramac-node modem mutex (STATE_BUSY during async RX) causes
* lora_recv_async() to return -EBUSY, setting _in_recv_mode = 0 and
* corrupting the state machine. The loramac-node driver self-manages
* AGC, so nothing needs to happen here. */
}
} /* namespace mesh */
/*
* SPDX-License-Identifier: Apache-2.0
* SX127x hardware hooks for LoRaRadioBase — Zephyr loramac-node driver.
*
* The SX127x driver (loramac-node/sx127x.c) exposes only the standard
* Zephyr LoRa API. Chip-specific features that the SX126x native driver
* provides via sx126x_ext.h are not available here:
*
* hwGetCurrentRSSI() — returns -80 dBm sentinel (no hardware path)
* hwIsPreambleDetected()— always false (no preamble-detect IRQ exposed)
* hwSetRxBoost() — no-op (SX127x has no RX boost register)
* hwResetAGC() — no-op (loramac-node manages AGC internally)
* hwIsChipBusy() — inherited false (no BUSY pin on SX127x)
*
* Everything else (configure, send, receive) uses the standard API.
*/
#include "SX127xRadio.h"
#include <zephyr/kernel.h>
#include <zephyr/drivers/lora.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(sx127x_radio, CONFIG_ZEPHCORE_LORA_LOG_LEVEL);
namespace mesh {
K_THREAD_STACK_DEFINE(sx127x_tx_wait_stack, TX_WAIT_THREAD_STACK_SIZE);
SX127xRadio::SX127xRadio(const struct device *lora_dev, MainBoard &board,
NodePrefs *prefs)
: LoRaRadioBase(lora_dev, board, prefs)
{
/* SX127x has no RX boost feature — start with boost disabled */
_rx_boost_enabled = false;
/* loramac-node requires full lora_config() on every TX/RX direction
* change — Radio.SetTxConfig() and Radio.SetRxConfig() configure
* completely disjoint internal state in the loramac-node library. */
_loramac_node = true;
}
void SX127xRadio::begin()
{
startTxThread(sx127x_tx_wait_stack,
K_THREAD_STACK_SIZEOF(sx127x_tx_wait_stack));
LoRaRadioBase::begin();
}
/* ── Hardware primitives ──────────────────────────────────────────────── */
bool SX127xRadio::hwConfigure(const struct lora_modem_config &cfg)
{
int ret = lora_config(_dev, const_cast<struct lora_modem_config *>(&cfg));
if (ret < 0) {
LOG_ERR("lora_config failed: %d", ret);
return false;
}
return true;
}
void SX127xRadio::hwCancelReceive()
{
lora_recv_async(_dev, NULL, NULL);
}
int SX127xRadio::hwSendAsync(uint8_t *buf, uint32_t len,
struct k_poll_signal *sig)
{
return lora_send_async(_dev, buf, len, sig);
}
int16_t SX127xRadio::hwGetCurrentRSSI()
{
/* SX127x loramac-node driver does not expose an instantaneous RSSI
* function via the standard Zephyr API. Return a plausible noise-floor
* sentinel so LoRaRadioBase::triggerNoiseFloorCalibrate() converges
* to a reasonable value rather than being seeded with garbage. */
return -80;
}
bool SX127xRadio::hwIsPreambleDetected()
{
/* No preamble-detect IRQ accessible through the standard Zephyr LoRa
* API for the loramac-node driver. Returning false means TX will
* not abort for an in-progress preamble — acceptable on SX127x. */
return false;
}
void SX127xRadio::hwSetRxBoost(bool enable)
{
/* SX127x does not have a dedicated RX boost / high-sensitivity mode
* switch. Sensitivity is controlled via lora_config tx_power and
* the DTS power-amplifier-output property. Nothing to do here. */
ARG_UNUSED(enable);
}
void SX127xRadio::hwResetAGC()
{
/* The loramac-node SX127x driver manages AGC recalibration internally
* (RadioSetRxConfig re-programs all gain registers on every RX config
* call). No explicit AGC reset is needed or possible via the standard
* API. */
}
void SX127xRadio::resetAGC()
{
/* hwResetAGC() is a no-op, so skip the base-class resetAGC() entirely.
* The base class calls startReceive() after hwResetAGC(), but the
* loramac-node modem mutex (STATE_BUSY during async RX) causes
* lora_recv_async() to return -EBUSY, setting _in_recv_mode = 0 and
* corrupting the state machine. The loramac-node driver self-manages
* AGC, so nothing needs to happen here. */
}
} /* namespace mesh */
+56 -56
View File
@@ -1,56 +1,56 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore Radio adapter for SX127x (SX1272/SX1276/SX1278) using Zephyr loramac-node driver.
*
* The SX127x loramac-node driver supports the standard Zephyr LoRa API
* (lora_config, lora_send_async, lora_recv_async) but has no extension
* API for instantaneous RSSI, preamble detection, or RX boost.
* Those features are stubbed out below.
*/
#pragma once
#include "LoRaRadioBase.h"
namespace mesh {
class SX127xRadio : public LoRaRadioBase {
public:
SX127xRadio(const struct device *lora_dev, MainBoard &board,
NodePrefs *prefs = nullptr);
void begin() override;
protected:
/* Hardware primitives */
void hwConfigure(const struct lora_modem_config &cfg) override;
void hwCancelReceive() override;
int hwSendAsync(uint8_t *buf, uint32_t len,
struct k_poll_signal *sig) override;
/* SX127x via loramac-node has no instantaneous RSSI API.
* Returns a fixed sentinel (-80 dBm) — noise floor calibration
* will converge on this value rather than the real noise floor. */
int16_t hwGetCurrentRSSI() override;
/* SX127x has no preamble-detected IRQ accessible via standard API.
* Always returns false — TX will not abort for a detected preamble. */
bool hwIsPreambleDetected() override;
/* SX127x has no RX boost / LNA gain switch via standard API. No-op. */
void hwSetRxBoost(bool enable) override;
/* SX127x loramac-node driver manages AGC automatically. No-op. */
void hwResetAGC() override;
/* Override public resetAGC(): hwResetAGC() is a no-op, and the
* loramac-node modem mutex makes the base-class startReceive() call
* fail with -EBUSY (modem STATE_BUSY during async RX), which would
* set _in_recv_mode = 0 and corrupt the state machine. */
void resetAGC() override;
/* SX127x has no BUSY pin. Default (false) from base is correct. */
/* bool hwIsChipBusy() — inherited, returns false */
};
} /* namespace mesh */
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore Radio adapter for SX127x (SX1272/SX1276/SX1278) using Zephyr loramac-node driver.
*
* The SX127x loramac-node driver supports the standard Zephyr LoRa API
* (lora_config, lora_send_async, lora_recv_async) but has no extension
* API for instantaneous RSSI, preamble detection, or RX boost.
* Those features are stubbed out below.
*/
#pragma once
#include "LoRaRadioBase.h"
namespace mesh {
class SX127xRadio : public LoRaRadioBase {
public:
SX127xRadio(const struct device *lora_dev, MainBoard &board,
NodePrefs *prefs = nullptr);
void begin() override;
protected:
/* Hardware primitives */
bool hwConfigure(const struct lora_modem_config &cfg) override;
void hwCancelReceive() override;
int hwSendAsync(uint8_t *buf, uint32_t len,
struct k_poll_signal *sig) override;
/* SX127x via loramac-node has no instantaneous RSSI API.
* Returns a fixed sentinel (-80 dBm) — noise floor calibration
* will converge on this value rather than the real noise floor. */
int16_t hwGetCurrentRSSI() override;
/* SX127x has no preamble-detected IRQ accessible via standard API.
* Always returns false — TX will not abort for a detected preamble. */
bool hwIsPreambleDetected() override;
/* SX127x has no RX boost / LNA gain switch via standard API. No-op. */
void hwSetRxBoost(bool enable) override;
/* SX127x loramac-node driver manages AGC automatically. No-op. */
void hwResetAGC() override;
/* Override public resetAGC(): hwResetAGC() is a no-op, and the
* loramac-node modem mutex makes the base-class startReceive() call
* fail with -EBUSY (modem STATE_BUSY during async RX), which would
* set _in_recv_mode = 0 and corrupt the state machine. */
void resetAGC() override;
/* SX127x has no BUSY pin. Default (false) from base is correct. */
/* bool hwIsChipBusy() — inherited, returns false */
};
} /* namespace mesh */
File diff suppressed because it is too large Load Diff