diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index effc177a..893306ed 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -337,6 +337,9 @@ protected: int getInterferenceThreshold() const override { return _prefs.interference_threshold; } + int getAGCResetInterval() const override { + return ((int)_prefs.agc_reset_interval) * 4000; // milliseconds + } 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) diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index 400b31dd..e7a91ea9 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -420,6 +420,9 @@ protected: int getInterferenceThreshold() const override { return _prefs.interference_threshold; } + int getAGCResetInterval() const override { + return ((int)_prefs.agc_reset_interval) * 4000; // milliseconds + } bool allowPacketForward(const mesh::Packet* packet) override { if (_prefs.disable_fwd) return false; diff --git a/src/Dispatcher.cpp b/src/Dispatcher.cpp index 7ac5cbe3..da34bd35 100644 --- a/src/Dispatcher.cpp +++ b/src/Dispatcher.cpp @@ -87,6 +87,14 @@ void Dispatcher::loop() { } else { return; // can't do any more radio activity until send is complete or timed out } + + // going back into receive mode now... + next_agc_reset_time = futureMillis(getAGCResetInterval()); + } + + if (millisHasNowPassed(next_agc_reset_time)) { + _radio->resetAGC(); + next_agc_reset_time = futureMillis(getAGCResetInterval()); } // check inbound (delayed) queue diff --git a/src/Dispatcher.h b/src/Dispatcher.h index bce13b6b..2200f81b 100644 --- a/src/Dispatcher.h +++ b/src/Dispatcher.h @@ -65,6 +65,8 @@ public: virtual void triggerNoiseFloorCalibrate(int threshold) { } + virtual void resetAGC() { } + virtual bool isInRecvMode() const = 0; /** @@ -116,7 +118,7 @@ class Dispatcher { unsigned long next_tx_time; unsigned long cad_busy_start; unsigned long radio_nonrx_start; - unsigned long next_floor_calib_time; + unsigned long next_floor_calib_time, next_agc_reset_time; bool prev_isrecv_mode; uint32_t n_sent_flood, n_sent_direct; uint32_t n_recv_flood, n_recv_direct; @@ -134,7 +136,7 @@ protected: { outbound = NULL; total_air_time = 0; next_tx_time = 0; cad_busy_start = 0; - next_floor_calib_time = 0; + next_floor_calib_time = next_agc_reset_time = 0; _err_flags = 0; radio_nonrx_start = 0; prev_isrecv_mode = true; @@ -154,6 +156,7 @@ protected: virtual uint32_t getCADFailRetryDelay() const; virtual uint32_t getCADFailMaxDuration() const; virtual int getInterferenceThreshold() const { return 0; } // disabled by default + virtual int getAGCResetInterval() const { return 0; } // disabled by default public: void begin(); diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index baad8f40..63e2740c 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -53,7 +53,8 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { file.read((uint8_t *) &_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114 file.read((uint8_t *) &_prefs->reserved2, sizeof(_prefs->reserved2)); // 115 file.read((uint8_t *) &_prefs->bw, sizeof(_prefs->bw)); // 116 - file.read(pad, 4); // 120 + file.read((uint8_t *) &_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval)); // 120 + file.read(pad, 3); // 121 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 @@ -107,7 +108,8 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) { file.write((uint8_t *) &_prefs->allow_read_only, sizeof(_prefs->allow_read_only)); // 114 file.write((uint8_t *) &_prefs->reserved2, sizeof(_prefs->reserved2)); // 115 file.write((uint8_t *) &_prefs->bw, sizeof(_prefs->bw)); // 116 - file.write(pad, 4); // 120 + file.write((uint8_t *) &_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval)); // 120 + file.write(pad, 3); // 121 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 @@ -180,6 +182,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch 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, "agc.reset.interval", 18) == 0) { + sprintf(reply, "> %d", ((uint32_t) _prefs->agc_reset_interval) * 4); } 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) { @@ -231,6 +235,10 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch _prefs->interference_threshold = atoi(&config[11]); savePrefs(); strcpy(reply, "OK"); + } else if (memcmp(config, "agc.reset.interval ", 19) == 0) { + _prefs->agc_reset_interval = atoi(&config[19]) / 4; + 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 37402c09..1778c715 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -25,6 +25,7 @@ struct NodePrefs { // persisted to file float bw; uint8_t flood_max; uint8_t interference_threshold; + uint8_t agc_reset_interval; // secs / 4 }; class CommonCLICallbacks { diff --git a/src/helpers/RadioLibWrappers.cpp b/src/helpers/RadioLibWrappers.cpp index 1415a864..0593451a 100644 --- a/src/helpers/RadioLibWrappers.cpp +++ b/src/helpers/RadioLibWrappers.cpp @@ -52,6 +52,15 @@ void RadioLibWrapper::triggerNoiseFloorCalibrate(int threshold) { } } +void RadioLibWrapper::resetAGC() { + // make sure we're not mid-receive of packet! + if ((state & STATE_INT_READY) != 0 || isReceivingPacket()) return; + + // NOTE: according to higher powers, just issuing RadioLib's startReceive() will reset the AGC. + // revisit this if a better impl is discovered. + state = STATE_IDLE; // trigger a startReceive() +} + void RadioLibWrapper::loop() { if (state == STATE_RX && _num_floor_samples < NUM_NOISE_FLOOR_SAMPLES) { if (!isReceivingPacket()) { diff --git a/src/helpers/RadioLibWrappers.h b/src/helpers/RadioLibWrappers.h index bb308071..25cc5358 100644 --- a/src/helpers/RadioLibWrappers.h +++ b/src/helpers/RadioLibWrappers.h @@ -39,6 +39,7 @@ public: int getNoiseFloor() const override { return _noise_floor; } void triggerNoiseFloorCalibrate(int threshold) override; + void resetAGC() override; void loop() override;