mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-01 20:38:19 +00:00
hwconfig failsafe and duty cycle 10/6->10/4 (tests showed better reception)
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 ────────────────────────────────────────────────────────── */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
+529
-517
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user