Ver Fonte

Merge pull request #1743 from weebl2000/fixagcreset

fix agc reset on SX126x, SX1276 & LR11x0 chips
ripplebiz há 5 meses atrás
pai
commit
7c594ebc50

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

@@ -2,6 +2,7 @@
 
 #include "CustomLLCC68.h"
 #include "RadioLibWrappers.h"
+#include "SX126xReset.h"
 
 class CustomLLCC68Wrapper : public RadioLibWrapper {
 public:
@@ -19,4 +20,6 @@ public:
     int sf = ((CustomLLCC68 *)_radio)->spreadingFactor;
     return packetScoreInt(snr, sf, packet_len);
   }
+
+  void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
 };

+ 2 - 0
src/helpers/radiolib/CustomLR1110.h

@@ -20,6 +20,8 @@ class CustomLR1110 : public LR1110 {
       return len;
     }
     
+    float getFreqMHz() const { return freqMHz; }
+
     bool isReceiving() {
       uint16_t irq = getIrqStatus();
       bool detected = ((irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID) || (irq & RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED));

+ 3 - 1
src/helpers/radiolib/CustomLR1110Wrapper.h

@@ -2,11 +2,13 @@
 
 #include "CustomLR1110.h"
 #include "RadioLibWrappers.h"
+#include "LR11x0Reset.h"
 
 class CustomLR1110Wrapper : public RadioLibWrapper {
 public:
   CustomLR1110Wrapper(CustomLR1110& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
-  bool isReceivingPacket() override { 
+  void doResetAGC() override { lr11x0ResetAGC((LR11x0 *)_radio, ((CustomLR1110 *)_radio)->getFreqMHz()); }
+  bool isReceivingPacket() override {
     return ((CustomLR1110 *)_radio)->isReceiving();
   }
   float getCurrentRSSI() override {

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

@@ -2,6 +2,7 @@
 
 #include "CustomSTM32WLx.h"
 #include "RadioLibWrappers.h"
+#include "SX126xReset.h"
 #include <math.h>
 
 class CustomSTM32WLxWrapper : public RadioLibWrapper {
@@ -20,4 +21,6 @@ public:
     int sf = ((CustomSTM32WLx *)_radio)->spreadingFactor;
     return packetScoreInt(snr, sf, packet_len);
   }
+
+  void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
 };

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

@@ -2,6 +2,7 @@
 
 #include "CustomSX1262.h"
 #include "RadioLibWrappers.h"
+#include "SX126xReset.h"
 
 class CustomSX1262Wrapper : public RadioLibWrapper {
 public:
@@ -22,4 +23,6 @@ public:
   virtual void powerOff() override {
     ((CustomSX1262 *)_radio)->sleep(false);
   }
+
+  void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
 };

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

@@ -2,6 +2,7 @@
 
 #include "CustomSX1268.h"
 #include "RadioLibWrappers.h"
+#include "SX126xReset.h"
 
 class CustomSX1268Wrapper : public RadioLibWrapper {
 public:
@@ -19,4 +20,6 @@ public:
     int sf = ((CustomSX1268 *)_radio)->spreadingFactor;
     return packetScoreInt(snr, sf, packet_len);
   }
+
+  void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
 };

+ 21 - 0
src/helpers/radiolib/LR11x0Reset.h

@@ -0,0 +1,21 @@
+#pragma once
+
+#include <RadioLib.h>
+
+// Full receiver reset for LR11x0-family chips (LR1110, LR1120, LR1121).
+// Warm sleep powers down analog, calibrate(0x3F) refreshes all calibration blocks,
+// then re-applies RX settings that calibration may reset.
+inline void lr11x0ResetAGC(LR11x0* radio, float freqMHz) {
+  radio->sleep(true, 0);
+  radio->standby(RADIOLIB_LR11X0_STANDBY_RC, true);
+
+  radio->calibrate(RADIOLIB_LR11X0_CALIBRATE_ALL);
+
+  // calibrate(0x3F) defaults image calibration to 902-928MHz band.
+  // Re-calibrate for the actual operating frequency (band=4MHz matches RadioLib default).
+  radio->calibrateImageRejection(freqMHz - 4.0f, freqMHz + 4.0f);
+
+#ifdef RX_BOOSTED_GAIN
+  radio->setRxBoostedGainMode(RX_BOOSTED_GAIN);
+#endif
+}

+ 13 - 2
src/helpers/radiolib/RadioLibWrappers.cpp

@@ -53,13 +53,24 @@ 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;
 
-  // NOTE: according to higher powers, just issuing RadioLib's startReceive() will reset the AGC.
-  //      revisit this if a better impl is discovered.
+  doResetAGC();
   state = STATE_IDLE;   // trigger a startReceive()
+
+  // Reset noise floor sampling so it reconverges from scratch.
+  // Without this, a stuck _noise_floor of -120 makes the sampling threshold
+  // too low (-106) to accept normal samples (~-105), self-reinforcing the
+  // stuck value even after the receiver has recovered.
+  _noise_floor = 0;
+  _num_floor_samples = 0;
+  _floor_sample_sum = 0;
 }
 
 void RadioLibWrapper::loop() {

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

+ 37 - 0
src/helpers/radiolib/SX126xReset.h

@@ -0,0 +1,37 @@
+#pragma once
+
+#include <RadioLib.h>
+
+// Full receiver reset for all SX126x-family chips (SX1262, SX1268, LLCC68, STM32WLx).
+// Warm sleep powers down analog, Calibrate(0x7F) refreshes ADC/PLL/image calibration,
+// then re-applies RX settings that calibration may reset.
+inline void sx126xResetAGC(SX126x* 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();
+  }
+
+  // Calibrate(0x7F) defaults image calibration to 902-928MHz band.
+  // Re-calibrate for the actual operating frequency.
+  radio->calibrateImage(radio->freqMHz);
+
+#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
+}