diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 12c843b7..06edec13 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -327,6 +327,9 @@ protected: uint32_t t = (_radio->getEstAirtimeFor(packet->path_len + packet->payload_len + 2) * _prefs.direct_tx_delay_factor); 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 { 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.flood_advert_interval = 3; // 3 hours _prefs.flood_max = 64; + _prefs.interference_threshold = 14; // DB } CommonCLI* getCLI() { return &_cli; } diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index dad7ce78..d46270ac 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -406,6 +406,9 @@ protected: uint32_t t = (_radio->getEstAirtimeFor(packet->path_len + packet->payload_len + 2) * _prefs.direct_tx_delay_factor); return getRNG()->nextInt(0, 6)*t; } + int getInterferenceThreshold() const override { + return _prefs.interference_threshold; + } bool allowPacketForward(const mesh::Packet* packet) override { if (_prefs.disable_fwd) return false; @@ -711,6 +714,7 @@ public: _prefs.advert_interval = 1; // default to 2 minutes for NEW installs _prefs.flood_advert_interval = 3; // 3 hours _prefs.flood_max = 64; + _prefs.interference_threshold = 14; // DB #ifdef ROOM_PASSWORD StrHelper::strncpy(_prefs.guest_password, ROOM_PASSWORD, sizeof(_prefs.guest_password)); #endif diff --git a/src/Dispatcher.cpp b/src/Dispatcher.cpp index 06c5e035..7ac5cbe3 100644 --- a/src/Dispatcher.cpp +++ b/src/Dispatcher.cpp @@ -41,7 +41,7 @@ uint32_t Dispatcher::getCADFailMaxDuration() const { void Dispatcher::loop() { if (millisHasNowPassed(next_floor_calib_time)) { - _radio->triggerNoiseFloorCalibrate(); + _radio->triggerNoiseFloorCalibrate(getInterferenceThreshold()); next_floor_calib_time = futureMillis(NOISE_FLOOR_CALIB_INTERVAL); } _radio->loop(); diff --git a/src/Dispatcher.h b/src/Dispatcher.h index 37f327e3..bce13b6b 100644 --- a/src/Dispatcher.h +++ b/src/Dispatcher.h @@ -63,7 +63,7 @@ public: virtual int getNoiseFloor() const { return 0; } - virtual void triggerNoiseFloorCalibrate() { } + virtual void triggerNoiseFloorCalibrate(int threshold) { } virtual bool isInRecvMode() const = 0; @@ -153,6 +153,7 @@ protected: virtual int calcRxDelay(float score, uint32_t air_time) const; virtual uint32_t getCADFailRetryDelay() const; virtual uint32_t getCADFailMaxDuration() const; + virtual int getInterferenceThreshold() const { return 0; } // disabled by default public: void begin(); diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 8b8296f5..baad8f40 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -56,6 +56,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { file.read(pad, 4); // 120 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->interference_threshold, sizeof(_prefs->interference_threshold)); // 126 // sanitise bad pref values _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((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->interference_threshold, sizeof(_prefs->interference_threshold)); // 126 file.close(); } @@ -176,6 +178,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch const char* config = &command[4]; if (memcmp(config, "af", 2) == 0) { 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) { sprintf(reply, "> %s", _prefs->allow_read_only ? "on" : "off"); } 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]); savePrefs(); 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) { _prefs->allow_read_only = memcmp(&config[16], "on", 2) == 0; savePrefs(); diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index 0e88c266..37402c09 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -24,6 +24,7 @@ struct NodePrefs { // persisted to file uint8_t reserved2; float bw; uint8_t flood_max; + uint8_t interference_threshold; }; class CommonCLICallbacks { diff --git a/src/helpers/RadioLibWrappers.cpp b/src/helpers/RadioLibWrappers.cpp index d7b93a2f..d37bc498 100644 --- a/src/helpers/RadioLibWrappers.cpp +++ b/src/helpers/RadioLibWrappers.cpp @@ -8,10 +8,6 @@ #define STATE_TX_DONE 4 #define STATE_INT_READY 16 -#ifndef INTERFERENCE_THRESHOLD_DB - #define INTERFERENCE_THRESHOLD_DB 14 -#endif - #define NUM_NOISE_FLOOR_SAMPLES 64 static volatile uint8_t state = STATE_IDLE; @@ -36,6 +32,7 @@ void RadioLibWrapper::begin() { } _noise_floor = 0; + _threshold = 0; // start average out some samples _num_floor_samples = 0; @@ -47,8 +44,9 @@ void RadioLibWrapper::idle() { state = STATE_IDLE; // need another startReceive() } -void RadioLibWrapper::triggerNoiseFloorCalibrate() { - if (_num_floor_samples >= NUM_NOISE_FLOOR_SAMPLES) { // ignore trigger if currently sampling +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; } @@ -58,7 +56,7 @@ void RadioLibWrapper::loop() { if (state == STATE_RX && _num_floor_samples < NUM_NOISE_FLOOR_SAMPLES) { if (!isReceivingPacket()) { 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++; _floor_sample_sum += rssi; } @@ -145,7 +143,9 @@ void RadioLibWrapper::onSendFinished() { } 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 { diff --git a/src/helpers/RadioLibWrappers.h b/src/helpers/RadioLibWrappers.h index 9ac7e72c..bb308071 100644 --- a/src/helpers/RadioLibWrappers.h +++ b/src/helpers/RadioLibWrappers.h @@ -8,7 +8,7 @@ protected: PhysicalLayer* _radio; mesh::MainBoard* _board; uint32_t n_recv, n_sent; - int16_t _noise_floor; + int16_t _noise_floor, _threshold; uint16_t _num_floor_samples; int32_t _floor_sample_sum; @@ -38,7 +38,7 @@ public: virtual float getCurrentRSSI() =0; int getNoiseFloor() const override { return _noise_floor; } - void triggerNoiseFloorCalibrate() override; + void triggerNoiseFloorCalibrate(int threshold) override; void loop() override;