Skip to content

Commit 7c594eb

Browse files
authored
Merge pull request #1743 from weebl2000/fixagcreset
fix agc reset on SX126x, SX1276 & LR11x0 chips
2 parents ba3d9e2 + 9bae9d0 commit 7c594eb

File tree

10 files changed

+89
-3
lines changed

10 files changed

+89
-3
lines changed

src/helpers/radiolib/CustomLLCC68Wrapper.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "CustomLLCC68.h"
44
#include "RadioLibWrappers.h"
5+
#include "SX126xReset.h"
56

67
class CustomLLCC68Wrapper : public RadioLibWrapper {
78
public:
@@ -19,4 +20,6 @@ class CustomLLCC68Wrapper : public RadioLibWrapper {
1920
int sf = ((CustomLLCC68 *)_radio)->spreadingFactor;
2021
return packetScoreInt(snr, sf, packet_len);
2122
}
23+
24+
void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
2225
};

src/helpers/radiolib/CustomLR1110.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ class CustomLR1110 : public LR1110 {
2020
return len;
2121
}
2222

23+
float getFreqMHz() const { return freqMHz; }
24+
2325
bool isReceiving() {
2426
uint16_t irq = getIrqStatus();
2527
bool detected = ((irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID) || (irq & RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED));

src/helpers/radiolib/CustomLR1110Wrapper.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
#include "CustomLR1110.h"
44
#include "RadioLibWrappers.h"
5+
#include "LR11x0Reset.h"
56

67
class CustomLR1110Wrapper : public RadioLibWrapper {
78
public:
89
CustomLR1110Wrapper(CustomLR1110& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
9-
bool isReceivingPacket() override {
10+
void doResetAGC() override { lr11x0ResetAGC((LR11x0 *)_radio, ((CustomLR1110 *)_radio)->getFreqMHz()); }
11+
bool isReceivingPacket() override {
1012
return ((CustomLR1110 *)_radio)->isReceiving();
1113
}
1214
float getCurrentRSSI() override {

src/helpers/radiolib/CustomSTM32WLxWrapper.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "CustomSTM32WLx.h"
44
#include "RadioLibWrappers.h"
5+
#include "SX126xReset.h"
56
#include <math.h>
67

78
class CustomSTM32WLxWrapper : public RadioLibWrapper {
@@ -20,4 +21,6 @@ class CustomSTM32WLxWrapper : public RadioLibWrapper {
2021
int sf = ((CustomSTM32WLx *)_radio)->spreadingFactor;
2122
return packetScoreInt(snr, sf, packet_len);
2223
}
24+
25+
void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
2326
};

src/helpers/radiolib/CustomSX1262Wrapper.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "CustomSX1262.h"
44
#include "RadioLibWrappers.h"
5+
#include "SX126xReset.h"
56

67
class CustomSX1262Wrapper : public RadioLibWrapper {
78
public:
@@ -22,4 +23,6 @@ class CustomSX1262Wrapper : public RadioLibWrapper {
2223
virtual void powerOff() override {
2324
((CustomSX1262 *)_radio)->sleep(false);
2425
}
26+
27+
void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
2528
};

src/helpers/radiolib/CustomSX1268Wrapper.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "CustomSX1268.h"
44
#include "RadioLibWrappers.h"
5+
#include "SX126xReset.h"
56

67
class CustomSX1268Wrapper : public RadioLibWrapper {
78
public:
@@ -19,4 +20,6 @@ class CustomSX1268Wrapper : public RadioLibWrapper {
1920
int sf = ((CustomSX1268 *)_radio)->spreadingFactor;
2021
return packetScoreInt(snr, sf, packet_len);
2122
}
23+
24+
void doResetAGC() override { sx126xResetAGC((SX126x *)_radio); }
2225
};

src/helpers/radiolib/LR11x0Reset.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
3+
#include <RadioLib.h>
4+
5+
// Full receiver reset for LR11x0-family chips (LR1110, LR1120, LR1121).
6+
// Warm sleep powers down analog, calibrate(0x3F) refreshes all calibration blocks,
7+
// then re-applies RX settings that calibration may reset.
8+
inline void lr11x0ResetAGC(LR11x0* radio, float freqMHz) {
9+
radio->sleep(true, 0);
10+
radio->standby(RADIOLIB_LR11X0_STANDBY_RC, true);
11+
12+
radio->calibrate(RADIOLIB_LR11X0_CALIBRATE_ALL);
13+
14+
// calibrate(0x3F) defaults image calibration to 902-928MHz band.
15+
// Re-calibrate for the actual operating frequency (band=4MHz matches RadioLib default).
16+
radio->calibrateImageRejection(freqMHz - 4.0f, freqMHz + 4.0f);
17+
18+
#ifdef RX_BOOSTED_GAIN
19+
radio->setRxBoostedGainMode(RX_BOOSTED_GAIN);
20+
#endif
21+
}

src/helpers/radiolib/RadioLibWrappers.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,24 @@ void RadioLibWrapper::triggerNoiseFloorCalibrate(int threshold) {
5353
}
5454
}
5555

56+
void RadioLibWrapper::doResetAGC() {
57+
_radio->sleep(); // warm sleep to reset analog frontend
58+
}
59+
5660
void RadioLibWrapper::resetAGC() {
5761
// make sure we're not mid-receive of packet!
5862
if ((state & STATE_INT_READY) != 0 || isReceivingPacket()) return;
5963

60-
// NOTE: according to higher powers, just issuing RadioLib's startReceive() will reset the AGC.
61-
// revisit this if a better impl is discovered.
64+
doResetAGC();
6265
state = STATE_IDLE; // trigger a startReceive()
66+
67+
// Reset noise floor sampling so it reconverges from scratch.
68+
// Without this, a stuck _noise_floor of -120 makes the sampling threshold
69+
// too low (-106) to accept normal samples (~-105), self-reinforcing the
70+
// stuck value even after the receiver has recovered.
71+
_noise_floor = 0;
72+
_num_floor_samples = 0;
73+
_floor_sample_sum = 0;
6374
}
6475

6576
void RadioLibWrapper::loop() {

src/helpers/radiolib/RadioLibWrappers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class RadioLibWrapper : public mesh::Radio {
1616
void startRecv();
1717
float packetScoreInt(float snr, int sf, int packet_len);
1818
virtual bool isReceivingPacket() =0;
19+
virtual void doResetAGC();
1920

2021
public:
2122
RadioLibWrapper(PhysicalLayer& radio, mesh::MainBoard& board) : _radio(&radio), _board(&board) { n_recv = n_sent = 0; }

src/helpers/radiolib/SX126xReset.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#pragma once
2+
3+
#include <RadioLib.h>
4+
5+
// Full receiver reset for all SX126x-family chips (SX1262, SX1268, LLCC68, STM32WLx).
6+
// Warm sleep powers down analog, Calibrate(0x7F) refreshes ADC/PLL/image calibration,
7+
// then re-applies RX settings that calibration may reset.
8+
inline void sx126xResetAGC(SX126x* radio) {
9+
radio->sleep(true);
10+
radio->standby(RADIOLIB_SX126X_STANDBY_RC, true);
11+
12+
uint8_t calData = RADIOLIB_SX126X_CALIBRATE_ALL;
13+
radio->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_CALIBRATE, &calData, 1, true, false);
14+
radio->mod->hal->delay(5);
15+
uint32_t start = millis();
16+
while (radio->mod->hal->digitalRead(radio->mod->getGpio())) {
17+
if (millis() - start > 50) break;
18+
radio->mod->hal->yield();
19+
}
20+
21+
// Calibrate(0x7F) defaults image calibration to 902-928MHz band.
22+
// Re-calibrate for the actual operating frequency.
23+
radio->calibrateImage(radio->freqMHz);
24+
25+
#ifdef SX126X_DIO2_AS_RF_SWITCH
26+
radio->setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH);
27+
#endif
28+
#ifdef SX126X_RX_BOOSTED_GAIN
29+
radio->setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN);
30+
#endif
31+
#ifdef SX126X_REGISTER_PATCH
32+
uint8_t r_data = 0;
33+
radio->readRegister(0x8B5, &r_data, 1);
34+
r_data |= 0x01;
35+
radio->writeRegister(0x8B5, &r_data, 1);
36+
#endif
37+
}

0 commit comments

Comments
 (0)