Merge branch 'scan_exp' into dev
This commit is contained in:
@@ -79,7 +79,7 @@
|
|||||||
struct RepeaterStats {
|
struct RepeaterStats {
|
||||||
uint16_t batt_milli_volts;
|
uint16_t batt_milli_volts;
|
||||||
uint16_t curr_tx_queue_len;
|
uint16_t curr_tx_queue_len;
|
||||||
uint16_t curr_free_queue_len;
|
int16_t noise_floor;
|
||||||
int16_t last_rssi;
|
int16_t last_rssi;
|
||||||
uint32_t n_packets_recv;
|
uint32_t n_packets_recv;
|
||||||
uint32_t n_packets_sent;
|
uint32_t n_packets_sent;
|
||||||
@@ -183,7 +183,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
|
|||||||
RepeaterStats stats;
|
RepeaterStats stats;
|
||||||
stats.batt_milli_volts = board.getBattMilliVolts();
|
stats.batt_milli_volts = board.getBattMilliVolts();
|
||||||
stats.curr_tx_queue_len = _mgr->getOutboundCount(0xFFFFFFFF);
|
stats.curr_tx_queue_len = _mgr->getOutboundCount(0xFFFFFFFF);
|
||||||
stats.curr_free_queue_len = _mgr->getFreeCount();
|
stats.noise_floor = (int16_t)_radio->getNoiseFloor();
|
||||||
stats.last_rssi = (int16_t) radio_driver.getLastRSSI();
|
stats.last_rssi = (int16_t) radio_driver.getLastRSSI();
|
||||||
stats.n_packets_recv = radio_driver.getPacketsRecv();
|
stats.n_packets_recv = radio_driver.getPacketsRecv();
|
||||||
stats.n_packets_sent = radio_driver.getPacketsSent();
|
stats.n_packets_sent = radio_driver.getPacketsSent();
|
||||||
@@ -327,6 +327,9 @@ protected:
|
|||||||
uint32_t t = (_radio->getEstAirtimeFor(packet->path_len + packet->payload_len + 2) * _prefs.direct_tx_delay_factor);
|
uint32_t t = (_radio->getEstAirtimeFor(packet->path_len + packet->payload_len + 2) * _prefs.direct_tx_delay_factor);
|
||||||
return getRNG()->nextInt(0, 6)*t;
|
return getRNG()->nextInt(0, 6)*t;
|
||||||
}
|
}
|
||||||
|
int getInterferenceThreshold() const override {
|
||||||
|
return _prefs.interference_threshold;
|
||||||
|
}
|
||||||
|
|
||||||
void onAnonDataRecv(mesh::Packet* packet, uint8_t type, const mesh::Identity& sender, uint8_t* data, size_t len) override {
|
void onAnonDataRecv(mesh::Packet* packet, uint8_t type, const mesh::Identity& sender, uint8_t* data, size_t len) override {
|
||||||
if (type == PAYLOAD_TYPE_ANON_REQ) { // received an initial request by a possible admin client (unknown at this stage)
|
if (type == PAYLOAD_TYPE_ANON_REQ) { // received an initial request by a possible admin client (unknown at this stage)
|
||||||
@@ -565,6 +568,7 @@ public:
|
|||||||
_prefs.advert_interval = 1; // default to 2 minutes for NEW installs
|
_prefs.advert_interval = 1; // default to 2 minutes for NEW installs
|
||||||
_prefs.flood_advert_interval = 3; // 3 hours
|
_prefs.flood_advert_interval = 3; // 3 hours
|
||||||
_prefs.flood_max = 64;
|
_prefs.flood_max = 64;
|
||||||
|
_prefs.interference_threshold = 14; // DB
|
||||||
}
|
}
|
||||||
|
|
||||||
CommonCLI* getCLI() { return &_cli; }
|
CommonCLI* getCLI() { return &_cli; }
|
||||||
|
|||||||
@@ -406,6 +406,9 @@ protected:
|
|||||||
uint32_t t = (_radio->getEstAirtimeFor(packet->path_len + packet->payload_len + 2) * _prefs.direct_tx_delay_factor);
|
uint32_t t = (_radio->getEstAirtimeFor(packet->path_len + packet->payload_len + 2) * _prefs.direct_tx_delay_factor);
|
||||||
return getRNG()->nextInt(0, 6)*t;
|
return getRNG()->nextInt(0, 6)*t;
|
||||||
}
|
}
|
||||||
|
int getInterferenceThreshold() const override {
|
||||||
|
return _prefs.interference_threshold;
|
||||||
|
}
|
||||||
|
|
||||||
bool allowPacketForward(const mesh::Packet* packet) override {
|
bool allowPacketForward(const mesh::Packet* packet) override {
|
||||||
if (_prefs.disable_fwd) return false;
|
if (_prefs.disable_fwd) return false;
|
||||||
@@ -711,6 +714,7 @@ public:
|
|||||||
_prefs.advert_interval = 1; // default to 2 minutes for NEW installs
|
_prefs.advert_interval = 1; // default to 2 minutes for NEW installs
|
||||||
_prefs.flood_advert_interval = 3; // 3 hours
|
_prefs.flood_advert_interval = 3; // 3 hours
|
||||||
_prefs.flood_max = 64;
|
_prefs.flood_max = 64;
|
||||||
|
_prefs.interference_threshold = 14; // DB
|
||||||
#ifdef ROOM_PASSWORD
|
#ifdef ROOM_PASSWORD
|
||||||
StrHelper::strncpy(_prefs.guest_password, ROOM_PASSWORD, sizeof(_prefs.guest_password));
|
StrHelper::strncpy(_prefs.guest_password, ROOM_PASSWORD, sizeof(_prefs.guest_password));
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ namespace mesh {
|
|||||||
|
|
||||||
#define MAX_RX_DELAY_MILLIS 32000 // 32 seconds
|
#define MAX_RX_DELAY_MILLIS 32000 // 32 seconds
|
||||||
|
|
||||||
|
#ifndef NOISE_FLOOR_CALIB_INTERVAL
|
||||||
|
#define NOISE_FLOOR_CALIB_INTERVAL 2000 // 2 seconds
|
||||||
|
#endif
|
||||||
|
|
||||||
void Dispatcher::begin() {
|
void Dispatcher::begin() {
|
||||||
n_sent_flood = n_sent_direct = 0;
|
n_sent_flood = n_sent_direct = 0;
|
||||||
n_recv_flood = n_recv_direct = 0;
|
n_recv_flood = n_recv_direct = 0;
|
||||||
@@ -36,6 +40,12 @@ uint32_t Dispatcher::getCADFailMaxDuration() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Dispatcher::loop() {
|
void Dispatcher::loop() {
|
||||||
|
if (millisHasNowPassed(next_floor_calib_time)) {
|
||||||
|
_radio->triggerNoiseFloorCalibrate(getInterferenceThreshold());
|
||||||
|
next_floor_calib_time = futureMillis(NOISE_FLOOR_CALIB_INTERVAL);
|
||||||
|
}
|
||||||
|
_radio->loop();
|
||||||
|
|
||||||
// check for radio 'stuck' in mode other than Rx
|
// check for radio 'stuck' in mode other than Rx
|
||||||
bool is_recv = _radio->isInRecvMode();
|
bool is_recv = _radio->isInRecvMode();
|
||||||
if (is_recv != prev_isrecv_mode) {
|
if (is_recv != prev_isrecv_mode) {
|
||||||
|
|||||||
@@ -56,6 +56,15 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void onSendFinished() = 0;
|
virtual void onSendFinished() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief do any processing needed on each loop cycle
|
||||||
|
*/
|
||||||
|
virtual void loop() { }
|
||||||
|
|
||||||
|
virtual int getNoiseFloor() const { return 0; }
|
||||||
|
|
||||||
|
virtual void triggerNoiseFloorCalibrate(int threshold) { }
|
||||||
|
|
||||||
virtual bool isInRecvMode() const = 0;
|
virtual bool isInRecvMode() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,6 +116,7 @@ class Dispatcher {
|
|||||||
unsigned long next_tx_time;
|
unsigned long next_tx_time;
|
||||||
unsigned long cad_busy_start;
|
unsigned long cad_busy_start;
|
||||||
unsigned long radio_nonrx_start;
|
unsigned long radio_nonrx_start;
|
||||||
|
unsigned long next_floor_calib_time;
|
||||||
bool prev_isrecv_mode;
|
bool prev_isrecv_mode;
|
||||||
uint32_t n_sent_flood, n_sent_direct;
|
uint32_t n_sent_flood, n_sent_direct;
|
||||||
uint32_t n_recv_flood, n_recv_direct;
|
uint32_t n_recv_flood, n_recv_direct;
|
||||||
@@ -124,6 +134,7 @@ protected:
|
|||||||
{
|
{
|
||||||
outbound = NULL; total_air_time = 0; next_tx_time = 0;
|
outbound = NULL; total_air_time = 0; next_tx_time = 0;
|
||||||
cad_busy_start = 0;
|
cad_busy_start = 0;
|
||||||
|
next_floor_calib_time = 0;
|
||||||
_err_flags = 0;
|
_err_flags = 0;
|
||||||
radio_nonrx_start = 0;
|
radio_nonrx_start = 0;
|
||||||
prev_isrecv_mode = true;
|
prev_isrecv_mode = true;
|
||||||
@@ -142,6 +153,7 @@ protected:
|
|||||||
virtual int calcRxDelay(float score, uint32_t air_time) const;
|
virtual int calcRxDelay(float score, uint32_t air_time) const;
|
||||||
virtual uint32_t getCADFailRetryDelay() const;
|
virtual uint32_t getCADFailRetryDelay() const;
|
||||||
virtual uint32_t getCADFailMaxDuration() const;
|
virtual uint32_t getCADFailMaxDuration() const;
|
||||||
|
virtual int getInterferenceThreshold() const { return 0; } // disabled by default
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void begin();
|
void begin();
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
|||||||
file.read(pad, 4); // 120
|
file.read(pad, 4); // 120
|
||||||
file.read((uint8_t *) &_prefs->flood_max, sizeof(_prefs->flood_max)); // 124
|
file.read((uint8_t *) &_prefs->flood_max, sizeof(_prefs->flood_max)); // 124
|
||||||
file.read((uint8_t *) &_prefs->flood_advert_interval, sizeof(_prefs->flood_advert_interval)); // 125
|
file.read((uint8_t *) &_prefs->flood_advert_interval, sizeof(_prefs->flood_advert_interval)); // 125
|
||||||
|
file.read((uint8_t *) &_prefs->interference_threshold, sizeof(_prefs->interference_threshold)); // 126
|
||||||
|
|
||||||
// sanitise bad pref values
|
// sanitise bad pref values
|
||||||
_prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f);
|
_prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f);
|
||||||
@@ -109,6 +110,7 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
|
|||||||
file.write(pad, 4); // 120
|
file.write(pad, 4); // 120
|
||||||
file.write((uint8_t *) &_prefs->flood_max, sizeof(_prefs->flood_max)); // 124
|
file.write((uint8_t *) &_prefs->flood_max, sizeof(_prefs->flood_max)); // 124
|
||||||
file.write((uint8_t *) &_prefs->flood_advert_interval, sizeof(_prefs->flood_advert_interval)); // 125
|
file.write((uint8_t *) &_prefs->flood_advert_interval, sizeof(_prefs->flood_advert_interval)); // 125
|
||||||
|
file.write((uint8_t *) &_prefs->interference_threshold, sizeof(_prefs->interference_threshold)); // 126
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
@@ -176,6 +178,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||||||
const char* config = &command[4];
|
const char* config = &command[4];
|
||||||
if (memcmp(config, "af", 2) == 0) {
|
if (memcmp(config, "af", 2) == 0) {
|
||||||
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->airtime_factor));
|
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->airtime_factor));
|
||||||
|
} else if (memcmp(config, "int.thresh", 10) == 0) {
|
||||||
|
sprintf(reply, "> %d", (uint32_t) _prefs->interference_threshold);
|
||||||
} else if (memcmp(config, "allow.read.only", 15) == 0) {
|
} else if (memcmp(config, "allow.read.only", 15) == 0) {
|
||||||
sprintf(reply, "> %s", _prefs->allow_read_only ? "on" : "off");
|
sprintf(reply, "> %s", _prefs->allow_read_only ? "on" : "off");
|
||||||
} else if (memcmp(config, "flood.advert.interval", 21) == 0) {
|
} else if (memcmp(config, "flood.advert.interval", 21) == 0) {
|
||||||
@@ -223,6 +227,10 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||||||
_prefs->airtime_factor = atof(&config[3]);
|
_prefs->airtime_factor = atof(&config[3]);
|
||||||
savePrefs();
|
savePrefs();
|
||||||
strcpy(reply, "OK");
|
strcpy(reply, "OK");
|
||||||
|
} else if (memcmp(config, "int.thresh ", 11) == 0) {
|
||||||
|
_prefs->interference_threshold = atoi(&config[11]);
|
||||||
|
savePrefs();
|
||||||
|
strcpy(reply, "OK");
|
||||||
} else if (memcmp(config, "allow.read.only ", 16) == 0) {
|
} else if (memcmp(config, "allow.read.only ", 16) == 0) {
|
||||||
_prefs->allow_read_only = memcmp(&config[16], "on", 2) == 0;
|
_prefs->allow_read_only = memcmp(&config[16], "on", 2) == 0;
|
||||||
savePrefs();
|
savePrefs();
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ struct NodePrefs { // persisted to file
|
|||||||
uint8_t reserved2;
|
uint8_t reserved2;
|
||||||
float bw;
|
float bw;
|
||||||
uint8_t flood_max;
|
uint8_t flood_max;
|
||||||
|
uint8_t interference_threshold;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CommonCLICallbacks {
|
class CommonCLICallbacks {
|
||||||
|
|||||||
@@ -6,18 +6,11 @@
|
|||||||
class CustomLLCC68Wrapper : public RadioLibWrapper {
|
class CustomLLCC68Wrapper : public RadioLibWrapper {
|
||||||
public:
|
public:
|
||||||
CustomLLCC68Wrapper(CustomLLCC68& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
CustomLLCC68Wrapper(CustomLLCC68& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
||||||
bool isReceiving() override {
|
bool isReceivingPacket() override {
|
||||||
if (((CustomLLCC68 *)_radio)->isReceiving()) return true;
|
return ((CustomLLCC68 *)_radio)->isReceiving();
|
||||||
|
}
|
||||||
idle(); // put sx126x into standby
|
float getCurrentRSSI() override {
|
||||||
// do some basic CAD (blocks for ~12780 micros (on SF 10)!)
|
return ((CustomLLCC68 *)_radio)->getRSSI(false);
|
||||||
bool activity = (((CustomLLCC68 *)_radio)->scanChannel() == RADIOLIB_LORA_DETECTED);
|
|
||||||
if (activity) {
|
|
||||||
startRecv();
|
|
||||||
} else {
|
|
||||||
idle();
|
|
||||||
}
|
|
||||||
return activity;
|
|
||||||
}
|
}
|
||||||
float getLastRSSI() const override { return ((CustomLLCC68 *)_radio)->getRSSI(); }
|
float getLastRSSI() const override { return ((CustomLLCC68 *)_radio)->getRSSI(); }
|
||||||
float getLastSNR() const override { return ((CustomLLCC68 *)_radio)->getSNR(); }
|
float getLastSNR() const override { return ((CustomLLCC68 *)_radio)->getSNR(); }
|
||||||
|
|||||||
@@ -6,18 +6,13 @@
|
|||||||
class CustomLR1110Wrapper : public RadioLibWrapper {
|
class CustomLR1110Wrapper : public RadioLibWrapper {
|
||||||
public:
|
public:
|
||||||
CustomLR1110Wrapper(CustomLR1110& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
CustomLR1110Wrapper(CustomLR1110& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
||||||
bool isReceiving() override {
|
bool isReceivingPacket() override {
|
||||||
if (((CustomLR1110 *)_radio)->isReceiving()) return true;
|
return ((CustomLR1110 *)_radio)->isReceiving();
|
||||||
|
}
|
||||||
idle(); // put sx126x into standby
|
float getCurrentRSSI() override {
|
||||||
// do some basic CAD (blocks for ~12780 micros (on SF 10)!)
|
float rssi = -110;
|
||||||
bool activity = (((CustomLR1110 *)_radio)->scanChannel() == RADIOLIB_LORA_DETECTED);
|
((CustomLR1110 *)_radio)->getRssiInst(&rssi);
|
||||||
if (activity) {
|
return rssi;
|
||||||
startRecv();
|
|
||||||
} else {
|
|
||||||
idle();
|
|
||||||
}
|
|
||||||
return activity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onSendFinished() override {
|
void onSendFinished() override {
|
||||||
|
|||||||
@@ -7,18 +7,11 @@
|
|||||||
class CustomSTM32WLxWrapper : public RadioLibWrapper {
|
class CustomSTM32WLxWrapper : public RadioLibWrapper {
|
||||||
public:
|
public:
|
||||||
CustomSTM32WLxWrapper(CustomSTM32WLx& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
CustomSTM32WLxWrapper(CustomSTM32WLx& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
||||||
bool isReceiving() override {
|
bool isReceivingPacket() override {
|
||||||
if (((CustomSTM32WLx *)_radio)->isReceiving()) return true;
|
return ((CustomSTM32WLx *)_radio)->isReceiving();
|
||||||
|
}
|
||||||
idle(); // put sx126x into standby
|
float getCurrentRSSI() override {
|
||||||
// do some basic CAD (blocks for ~12780 micros (on SF 10)!)
|
return ((CustomSTM32WLx *)_radio)->getRSSI(false);
|
||||||
bool activity = (((CustomSTM32WLx *)_radio)->scanChannel() == RADIOLIB_LORA_DETECTED);
|
|
||||||
if (activity) {
|
|
||||||
startRecv();
|
|
||||||
} else {
|
|
||||||
idle();
|
|
||||||
}
|
|
||||||
return activity;
|
|
||||||
}
|
}
|
||||||
float getLastRSSI() const override { return ((CustomSTM32WLx *)_radio)->getRSSI(); }
|
float getLastRSSI() const override { return ((CustomSTM32WLx *)_radio)->getRSSI(); }
|
||||||
float getLastSNR() const override { return ((CustomSTM32WLx *)_radio)->getSNR(); }
|
float getLastSNR() const override { return ((CustomSTM32WLx *)_radio)->getSNR(); }
|
||||||
|
|||||||
@@ -2,23 +2,15 @@
|
|||||||
|
|
||||||
#include "CustomSX1262.h"
|
#include "CustomSX1262.h"
|
||||||
#include "RadioLibWrappers.h"
|
#include "RadioLibWrappers.h"
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
class CustomSX1262Wrapper : public RadioLibWrapper {
|
class CustomSX1262Wrapper : public RadioLibWrapper {
|
||||||
public:
|
public:
|
||||||
CustomSX1262Wrapper(CustomSX1262& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
CustomSX1262Wrapper(CustomSX1262& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
||||||
bool isReceiving() override {
|
bool isReceivingPacket() override {
|
||||||
if (((CustomSX1262 *)_radio)->isReceiving()) return true;
|
return ((CustomSX1262 *)_radio)->isReceiving();
|
||||||
|
}
|
||||||
idle(); // put sx126x into standby
|
float getCurrentRSSI() override {
|
||||||
// do some basic CAD (blocks for ~12780 micros (on SF 10)!)
|
return ((CustomSX1262 *)_radio)->getRSSI(false);
|
||||||
bool activity = (((CustomSX1262 *)_radio)->scanChannel() == RADIOLIB_LORA_DETECTED);
|
|
||||||
if (activity) {
|
|
||||||
startRecv();
|
|
||||||
} else {
|
|
||||||
idle();
|
|
||||||
}
|
|
||||||
return activity;
|
|
||||||
}
|
}
|
||||||
float getLastRSSI() const override { return ((CustomSX1262 *)_radio)->getRSSI(); }
|
float getLastRSSI() const override { return ((CustomSX1262 *)_radio)->getRSSI(); }
|
||||||
float getLastSNR() const override { return ((CustomSX1262 *)_radio)->getSNR(); }
|
float getLastSNR() const override { return ((CustomSX1262 *)_radio)->getSNR(); }
|
||||||
|
|||||||
@@ -6,18 +6,11 @@
|
|||||||
class CustomSX1268Wrapper : public RadioLibWrapper {
|
class CustomSX1268Wrapper : public RadioLibWrapper {
|
||||||
public:
|
public:
|
||||||
CustomSX1268Wrapper(CustomSX1268& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
CustomSX1268Wrapper(CustomSX1268& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
||||||
bool isReceiving() override {
|
bool isReceivingPacket() override {
|
||||||
if (((CustomSX1268 *)_radio)->isReceiving()) return true;
|
return ((CustomSX1268 *)_radio)->isReceiving();
|
||||||
|
}
|
||||||
idle(); // put sx126x into standby
|
float getCurrentRSSI() override {
|
||||||
// do some basic CAD (blocks for ~12780 micros (on SF 10)!)
|
return ((CustomSX1268 *)_radio)->getRSSI(false);
|
||||||
bool activity = (((CustomSX1268 *)_radio)->scanChannel() == RADIOLIB_LORA_DETECTED);
|
|
||||||
if (activity) {
|
|
||||||
startRecv();
|
|
||||||
} else {
|
|
||||||
idle();
|
|
||||||
}
|
|
||||||
return activity;
|
|
||||||
}
|
}
|
||||||
float getLastRSSI() const override { return ((CustomSX1268 *)_radio)->getRSSI(); }
|
float getLastRSSI() const override { return ((CustomSX1268 *)_radio)->getRSSI(); }
|
||||||
float getLastSNR() const override { return ((CustomSX1268 *)_radio)->getSNR(); }
|
float getLastSNR() const override { return ((CustomSX1268 *)_radio)->getSNR(); }
|
||||||
|
|||||||
@@ -6,18 +6,11 @@
|
|||||||
class CustomSX1276Wrapper : public RadioLibWrapper {
|
class CustomSX1276Wrapper : public RadioLibWrapper {
|
||||||
public:
|
public:
|
||||||
CustomSX1276Wrapper(CustomSX1276& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
CustomSX1276Wrapper(CustomSX1276& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
||||||
bool isReceiving() override {
|
bool isReceivingPacket() override {
|
||||||
if (((CustomSX1276 *)_radio)->isReceiving()) return true;
|
return ((CustomSX1276 *)_radio)->isReceiving();
|
||||||
|
}
|
||||||
idle(); // put into standby
|
float getCurrentRSSI() override {
|
||||||
// do some basic CAD (blocks for ~12780 micros (on SF 10)!)
|
return ((CustomSX1276 *)_radio)->getRSSI(false);
|
||||||
bool activity = (((CustomSX1276 *)_radio)->tryScanChannel() == RADIOLIB_PREAMBLE_DETECTED);
|
|
||||||
if (activity) {
|
|
||||||
startRecv();
|
|
||||||
} else {
|
|
||||||
idle();
|
|
||||||
}
|
|
||||||
return activity;
|
|
||||||
}
|
}
|
||||||
float getLastRSSI() const override { return ((CustomSX1276 *)_radio)->getRSSI(); }
|
float getLastRSSI() const override { return ((CustomSX1276 *)_radio)->getRSSI(); }
|
||||||
float getLastSNR() const override { return ((CustomSX1276 *)_radio)->getSNR(); }
|
float getLastSNR() const override { return ((CustomSX1276 *)_radio)->getSNR(); }
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#define STATE_TX_DONE 4
|
#define STATE_TX_DONE 4
|
||||||
#define STATE_INT_READY 16
|
#define STATE_INT_READY 16
|
||||||
|
|
||||||
|
#define NUM_NOISE_FLOOR_SAMPLES 64
|
||||||
|
|
||||||
static volatile uint8_t state = STATE_IDLE;
|
static volatile uint8_t state = STATE_IDLE;
|
||||||
|
|
||||||
// this function is called when a complete packet
|
// this function is called when a complete packet
|
||||||
@@ -28,6 +30,13 @@ void RadioLibWrapper::begin() {
|
|||||||
if (_board->getStartupReason() == BD_STARTUP_RX_PACKET) { // received a LoRa packet (while in deep sleep)
|
if (_board->getStartupReason() == BD_STARTUP_RX_PACKET) { // received a LoRa packet (while in deep sleep)
|
||||||
setFlag(); // LoRa packet is already received
|
setFlag(); // LoRa packet is already received
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_noise_floor = 0;
|
||||||
|
_threshold = 0;
|
||||||
|
|
||||||
|
// start average out some samples
|
||||||
|
_num_floor_samples = 0;
|
||||||
|
_floor_sample_sum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RadioLibWrapper::idle() {
|
void RadioLibWrapper::idle() {
|
||||||
@@ -35,6 +44,31 @@ void RadioLibWrapper::idle() {
|
|||||||
state = STATE_IDLE; // need another startReceive()
|
state = STATE_IDLE; // need another startReceive()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RadioLibWrapper::triggerNoiseFloorCalibrate(int threshold) {
|
||||||
|
_threshold = threshold;
|
||||||
|
if (threshold > 0 && _num_floor_samples >= NUM_NOISE_FLOOR_SAMPLES) { // ignore trigger if currently sampling
|
||||||
|
_num_floor_samples = 0;
|
||||||
|
_floor_sample_sum = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RadioLibWrapper::loop() {
|
||||||
|
if (state == STATE_RX && _num_floor_samples < NUM_NOISE_FLOOR_SAMPLES) {
|
||||||
|
if (!isReceivingPacket()) {
|
||||||
|
int rssi = getCurrentRSSI();
|
||||||
|
if (rssi < _noise_floor + _threshold) { // only consider samples below current floor+THRESHOLD
|
||||||
|
_num_floor_samples++;
|
||||||
|
_floor_sample_sum += rssi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (_num_floor_samples >= NUM_NOISE_FLOOR_SAMPLES && _floor_sample_sum != 0) {
|
||||||
|
_noise_floor = _floor_sample_sum / NUM_NOISE_FLOOR_SAMPLES;
|
||||||
|
_floor_sample_sum = 0;
|
||||||
|
|
||||||
|
MESH_DEBUG_PRINTLN("RadioLibWrapper: noise_floor = %d", (int)_noise_floor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RadioLibWrapper::startRecv() {
|
void RadioLibWrapper::startRecv() {
|
||||||
int err = _radio->startReceive();
|
int err = _radio->startReceive();
|
||||||
if (err == RADIOLIB_ERR_NONE) {
|
if (err == RADIOLIB_ERR_NONE) {
|
||||||
@@ -108,6 +142,12 @@ void RadioLibWrapper::onSendFinished() {
|
|||||||
state = STATE_IDLE;
|
state = STATE_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RadioLibWrapper::isChannelActive() {
|
||||||
|
return _threshold == 0
|
||||||
|
? false // interference check is disabled
|
||||||
|
: getCurrentRSSI() > _noise_floor + _threshold;
|
||||||
|
}
|
||||||
|
|
||||||
float RadioLibWrapper::getLastRSSI() const {
|
float RadioLibWrapper::getLastRSSI() const {
|
||||||
return _radio->getRSSI();
|
return _radio->getRSSI();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,14 @@ protected:
|
|||||||
PhysicalLayer* _radio;
|
PhysicalLayer* _radio;
|
||||||
mesh::MainBoard* _board;
|
mesh::MainBoard* _board;
|
||||||
uint32_t n_recv, n_sent;
|
uint32_t n_recv, n_sent;
|
||||||
|
int16_t _noise_floor, _threshold;
|
||||||
|
uint16_t _num_floor_samples;
|
||||||
|
int32_t _floor_sample_sum;
|
||||||
|
|
||||||
void idle();
|
void idle();
|
||||||
void startRecv();
|
void startRecv();
|
||||||
float packetScoreInt(float snr, int sf, int packet_len);
|
float packetScoreInt(float snr, int sf, int packet_len);
|
||||||
|
virtual bool isReceivingPacket() =0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RadioLibWrapper(PhysicalLayer& radio, mesh::MainBoard& board) : _radio(&radio), _board(&board) { n_recv = n_sent = 0; }
|
RadioLibWrapper(PhysicalLayer& radio, mesh::MainBoard& board) : _radio(&radio), _board(&board) { n_recv = n_sent = 0; }
|
||||||
@@ -23,6 +27,20 @@ public:
|
|||||||
bool isSendComplete() override;
|
bool isSendComplete() override;
|
||||||
void onSendFinished() override;
|
void onSendFinished() override;
|
||||||
bool isInRecvMode() const override;
|
bool isInRecvMode() const override;
|
||||||
|
bool isChannelActive();
|
||||||
|
|
||||||
|
bool isReceiving() override {
|
||||||
|
if (isReceivingPacket()) return true;
|
||||||
|
|
||||||
|
return isChannelActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual float getCurrentRSSI() =0;
|
||||||
|
|
||||||
|
int getNoiseFloor() const override { return _noise_floor; }
|
||||||
|
void triggerNoiseFloorCalibrate(int threshold) override;
|
||||||
|
|
||||||
|
void loop() override;
|
||||||
|
|
||||||
uint32_t getPacketsRecv() const { return n_recv; }
|
uint32_t getPacketsRecv() const { return n_recv; }
|
||||||
uint32_t getPacketsSent() const { return n_sent; }
|
uint32_t getPacketsSent() const { return n_sent; }
|
||||||
|
|||||||
Reference in New Issue
Block a user