Ver Fonte

when doing AGC reset, call Calibrate(0x7F)

1. warm sleep
2. wake to stdby
3. Calibrate(0x7F) to reset all internal blocks
4. re-apply DIO2 RF / boosted gain & register patch to make sure
everything is as it was
Wessel Nieboer há 5 meses atrás
pai
commit
a2dc2eb50c

+ 26 - 0
src/helpers/radiolib/CustomLLCC68Wrapper.h

@@ -19,4 +19,30 @@ public:
     int sf = ((CustomLLCC68 *)_radio)->spreadingFactor;
     return packetScoreInt(snr, sf, packet_len);
   }
+
+  void doResetAGC() override {
+    auto* radio = (CustomLLCC68 *)_radio;
+    radio->sleep(true);
+    radio->standby(RADIOLIB_SX126X_STANDBY_RC, true);
+    uint8_t calData = RADIOLIB_SX126X_CALIBRATE_ALL;
+    radio->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_CALIBRATE, &calData, 1, true, false);
+    radio->mod->hal->delay(5);
+    uint32_t start = millis();
+    while (radio->mod->hal->digitalRead(radio->mod->getGpio())) {
+      if (millis() - start > 50) break;
+      radio->mod->hal->yield();
+    }
+#ifdef SX126X_DIO2_AS_RF_SWITCH
+    radio->setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH);
+#endif
+#ifdef SX126X_RX_BOOSTED_GAIN
+    radio->setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN);
+#endif
+#ifdef SX126X_REGISTER_PATCH
+    uint8_t r_data = 0;
+    radio->readRegister(0x8B5, &r_data, 1);
+    r_data |= 0x01;
+    radio->writeRegister(0x8B5, &r_data, 1);
+#endif
+  }
 };

+ 26 - 0
src/helpers/radiolib/CustomSTM32WLxWrapper.h

@@ -20,4 +20,30 @@ public:
     int sf = ((CustomSTM32WLx *)_radio)->spreadingFactor;
     return packetScoreInt(snr, sf, packet_len);
   }
+
+  void doResetAGC() override {
+    auto* radio = (CustomSTM32WLx *)_radio;
+    radio->sleep(true);
+    radio->standby(RADIOLIB_SX126X_STANDBY_RC, true);
+    uint8_t calData = RADIOLIB_SX126X_CALIBRATE_ALL;
+    radio->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_CALIBRATE, &calData, 1, true, false);
+    radio->mod->hal->delay(5);
+    uint32_t start = millis();
+    while (radio->mod->hal->digitalRead(radio->mod->getGpio())) {
+      if (millis() - start > 50) break;
+      radio->mod->hal->yield();
+    }
+#ifdef SX126X_DIO2_AS_RF_SWITCH
+    radio->setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH);
+#endif
+#ifdef SX126X_RX_BOOSTED_GAIN
+    radio->setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN);
+#endif
+#ifdef SX126X_REGISTER_PATCH
+    uint8_t r_data = 0;
+    radio->readRegister(0x8B5, &r_data, 1);
+    r_data |= 0x01;
+    radio->writeRegister(0x8B5, &r_data, 1);
+#endif
+  }
 };

+ 30 - 0
src/helpers/radiolib/CustomSX1262Wrapper.h

@@ -22,4 +22,34 @@ public:
   virtual void powerOff() override {
     ((CustomSX1262 *)_radio)->sleep(false);
   }
+
+  void doResetAGC() override {
+    auto* radio = (CustomSX1262 *)_radio;
+    // Warm sleep powers down analog frontend (resets AGC gain state)
+    radio->sleep(true);
+    // Wake to STDBY_RC for calibration
+    radio->standby(RADIOLIB_SX126X_STANDBY_RC, true);
+    // Recalibrate all blocks (ADC, PLL, image, oscillators)
+    uint8_t calData = RADIOLIB_SX126X_CALIBRATE_ALL;
+    radio->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_CALIBRATE, &calData, 1, true, false);
+    radio->mod->hal->delay(5);
+    uint32_t start = millis();
+    while (radio->mod->hal->digitalRead(radio->mod->getGpio())) {
+      if (millis() - start > 50) break;
+      radio->mod->hal->yield();
+    }
+    // Re-apply RX settings that calibration may reset
+#ifdef SX126X_DIO2_AS_RF_SWITCH
+    radio->setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH);
+#endif
+#ifdef SX126X_RX_BOOSTED_GAIN
+    radio->setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN);
+#endif
+#ifdef SX126X_REGISTER_PATCH
+    uint8_t r_data = 0;
+    radio->readRegister(0x8B5, &r_data, 1);
+    r_data |= 0x01;
+    radio->writeRegister(0x8B5, &r_data, 1);
+#endif
+  }
 };

+ 26 - 0
src/helpers/radiolib/CustomSX1268Wrapper.h

@@ -19,4 +19,30 @@ public:
     int sf = ((CustomSX1268 *)_radio)->spreadingFactor;
     return packetScoreInt(snr, sf, packet_len);
   }
+
+  void doResetAGC() override {
+    auto* radio = (CustomSX1268 *)_radio;
+    radio->sleep(true);
+    radio->standby(RADIOLIB_SX126X_STANDBY_RC, true);
+    uint8_t calData = RADIOLIB_SX126X_CALIBRATE_ALL;
+    radio->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_CALIBRATE, &calData, 1, true, false);
+    radio->mod->hal->delay(5);
+    uint32_t start = millis();
+    while (radio->mod->hal->digitalRead(radio->mod->getGpio())) {
+      if (millis() - start > 50) break;
+      radio->mod->hal->yield();
+    }
+#ifdef SX126X_DIO2_AS_RF_SWITCH
+    radio->setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH);
+#endif
+#ifdef SX126X_RX_BOOSTED_GAIN
+    radio->setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN);
+#endif
+#ifdef SX126X_REGISTER_PATCH
+    uint8_t r_data = 0;
+    radio->readRegister(0x8B5, &r_data, 1);
+    r_data |= 0x01;
+    radio->writeRegister(0x8B5, &r_data, 1);
+#endif
+  }
 };

+ 5 - 5
src/helpers/radiolib/RadioLibWrappers.cpp

@@ -53,15 +53,15 @@ void RadioLibWrapper::triggerNoiseFloorCalibrate(int threshold) {
   }
 }
 
+void RadioLibWrapper::doResetAGC() {
+  _radio->sleep();  // warm sleep to reset analog frontend
+}
+
 void RadioLibWrapper::resetAGC() {
   // make sure we're not mid-receive of packet!
   if ((state & STATE_INT_READY) != 0 || isReceivingPacket()) return;
 
-  // Warm sleep powers down the entire analog frontend (including AGC), forcing a
-  // fresh gain calibration on the next startReceive().  A plain standby->startReceive
-  // cycle does NOT reset the AGC — the analog state can persist across STDBY_RC.
-  // The ~1-2 ms sleep gap is negligible vs the preamble budget (131 ms at SF11/BW250).
-  _radio->sleep();
+  doResetAGC();
   state = STATE_IDLE;   // trigger a startReceive()
 }
 

+ 1 - 0
src/helpers/radiolib/RadioLibWrappers.h

@@ -16,6 +16,7 @@ protected:
   void startRecv();
   float packetScoreInt(float snr, int sf, int packet_len);
   virtual bool isReceivingPacket() =0;
+  virtual void doResetAGC();
 
 public:
   RadioLibWrapper(PhysicalLayer& radio, mesh::MainBoard& board) : _radio(&radio), _board(&board) { n_recv = n_sent = 0; }