* interference threshold now stored in prefs, CLI: set/get "int.thresh"

This commit is contained in:
Scott Powell 2025-05-26 17:18:49 +10:00
parent 4593a484fb
commit b3d78ac8a7
8 changed files with 30 additions and 12 deletions

View file

@ -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; }

View file

@ -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

View file

@ -41,7 +41,7 @@ uint32_t Dispatcher::getCADFailMaxDuration() const {
void Dispatcher::loop() { void Dispatcher::loop() {
if (millisHasNowPassed(next_floor_calib_time)) { if (millisHasNowPassed(next_floor_calib_time)) {
_radio->triggerNoiseFloorCalibrate(); _radio->triggerNoiseFloorCalibrate(getInterferenceThreshold());
next_floor_calib_time = futureMillis(NOISE_FLOOR_CALIB_INTERVAL); next_floor_calib_time = futureMillis(NOISE_FLOOR_CALIB_INTERVAL);
} }
_radio->loop(); _radio->loop();

View file

@ -63,7 +63,7 @@ public:
virtual int getNoiseFloor() const { return 0; } virtual int getNoiseFloor() const { return 0; }
virtual void triggerNoiseFloorCalibrate() { } virtual void triggerNoiseFloorCalibrate(int threshold) { }
virtual bool isInRecvMode() const = 0; virtual bool isInRecvMode() const = 0;
@ -153,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();

View file

@ -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();

View file

@ -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 {

View file

@ -8,10 +8,6 @@
#define STATE_TX_DONE 4 #define STATE_TX_DONE 4
#define STATE_INT_READY 16 #define STATE_INT_READY 16
#ifndef INTERFERENCE_THRESHOLD_DB
#define INTERFERENCE_THRESHOLD_DB 14
#endif
#define NUM_NOISE_FLOOR_SAMPLES 64 #define NUM_NOISE_FLOOR_SAMPLES 64
static volatile uint8_t state = STATE_IDLE; static volatile uint8_t state = STATE_IDLE;
@ -36,6 +32,7 @@ void RadioLibWrapper::begin() {
} }
_noise_floor = 0; _noise_floor = 0;
_threshold = 0;
// start average out some samples // start average out some samples
_num_floor_samples = 0; _num_floor_samples = 0;
@ -47,8 +44,9 @@ void RadioLibWrapper::idle() {
state = STATE_IDLE; // need another startReceive() state = STATE_IDLE; // need another startReceive()
} }
void RadioLibWrapper::triggerNoiseFloorCalibrate() { void RadioLibWrapper::triggerNoiseFloorCalibrate(int threshold) {
if (_num_floor_samples >= NUM_NOISE_FLOOR_SAMPLES) { // ignore trigger if currently sampling _threshold = threshold;
if (threshold > 0 && _num_floor_samples >= NUM_NOISE_FLOOR_SAMPLES) { // ignore trigger if currently sampling
_num_floor_samples = 0; _num_floor_samples = 0;
_floor_sample_sum = 0; _floor_sample_sum = 0;
} }
@ -58,7 +56,7 @@ void RadioLibWrapper::loop() {
if (state == STATE_RX && _num_floor_samples < NUM_NOISE_FLOOR_SAMPLES) { if (state == STATE_RX && _num_floor_samples < NUM_NOISE_FLOOR_SAMPLES) {
if (!isReceivingPacket()) { if (!isReceivingPacket()) {
int rssi = getCurrentRSSI(); int rssi = getCurrentRSSI();
if (rssi < _noise_floor + INTERFERENCE_THRESHOLD_DB) { // only consider samples below current floor+THRESHOLD if (rssi < _noise_floor + _threshold) { // only consider samples below current floor+THRESHOLD
_num_floor_samples++; _num_floor_samples++;
_floor_sample_sum += rssi; _floor_sample_sum += rssi;
} }
@ -145,7 +143,9 @@ void RadioLibWrapper::onSendFinished() {
} }
bool RadioLibWrapper::isChannelActive() { bool RadioLibWrapper::isChannelActive() {
return getCurrentRSSI() > _noise_floor + INTERFERENCE_THRESHOLD_DB; return _threshold == 0
? false // interference check is disabled
: getCurrentRSSI() > _noise_floor + _threshold;
} }
float RadioLibWrapper::getLastRSSI() const { float RadioLibWrapper::getLastRSSI() const {

View file

@ -8,7 +8,7 @@ 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; int16_t _noise_floor, _threshold;
uint16_t _num_floor_samples; uint16_t _num_floor_samples;
int32_t _floor_sample_sum; int32_t _floor_sample_sum;
@ -38,7 +38,7 @@ public:
virtual float getCurrentRSSI() =0; virtual float getCurrentRSSI() =0;
int getNoiseFloor() const override { return _noise_floor; } int getNoiseFloor() const override { return _noise_floor; }
void triggerNoiseFloorCalibrate() override; void triggerNoiseFloorCalibrate(int threshold) override;
void loop() override; void loop() override;