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
This commit is contained in:
@@ -19,4 +19,30 @@ public:
|
|||||||
int sf = ((CustomLLCC68 *)_radio)->spreadingFactor;
|
int sf = ((CustomLLCC68 *)_radio)->spreadingFactor;
|
||||||
return packetScoreInt(snr, sf, packet_len);
|
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
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,4 +20,30 @@ public:
|
|||||||
int sf = ((CustomSTM32WLx *)_radio)->spreadingFactor;
|
int sf = ((CustomSTM32WLx *)_radio)->spreadingFactor;
|
||||||
return packetScoreInt(snr, sf, packet_len);
|
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
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,4 +22,34 @@ public:
|
|||||||
virtual void powerOff() override {
|
virtual void powerOff() override {
|
||||||
((CustomSX1262 *)_radio)->sleep(false);
|
((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
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,4 +19,30 @@ public:
|
|||||||
int sf = ((CustomSX1268 *)_radio)->spreadingFactor;
|
int sf = ((CustomSX1268 *)_radio)->spreadingFactor;
|
||||||
return packetScoreInt(snr, sf, packet_len);
|
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
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -53,15 +53,15 @@ void RadioLibWrapper::triggerNoiseFloorCalibrate(int threshold) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RadioLibWrapper::doResetAGC() {
|
||||||
|
_radio->sleep(); // warm sleep to reset analog frontend
|
||||||
|
}
|
||||||
|
|
||||||
void RadioLibWrapper::resetAGC() {
|
void RadioLibWrapper::resetAGC() {
|
||||||
// make sure we're not mid-receive of packet!
|
// make sure we're not mid-receive of packet!
|
||||||
if ((state & STATE_INT_READY) != 0 || isReceivingPacket()) return;
|
if ((state & STATE_INT_READY) != 0 || isReceivingPacket()) return;
|
||||||
|
|
||||||
// Warm sleep powers down the entire analog frontend (including AGC), forcing a
|
doResetAGC();
|
||||||
// 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();
|
|
||||||
state = STATE_IDLE; // trigger a startReceive()
|
state = STATE_IDLE; // trigger a startReceive()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ protected:
|
|||||||
void startRecv();
|
void startRecv();
|
||||||
float packetScoreInt(float snr, int sf, int packet_len);
|
float packetScoreInt(float snr, int sf, int packet_len);
|
||||||
virtual bool isReceivingPacket() =0;
|
virtual bool isReceivingPacket() =0;
|
||||||
|
virtual void doResetAGC();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RadioLibWrapper(PhysicalLayer& radio, mesh::MainBoard& board) : _radio(&radio), _board(&board) { n_recv = n_sent = 0; }
|
RadioLibWrapper(PhysicalLayer& radio, mesh::MainBoard& board) : _radio(&radio), _board(&board) { n_recv = n_sent = 0; }
|
||||||
|
|||||||
Reference in New Issue
Block a user