AGC reset on interval

This commit is contained in:
Ben Meadors
2025-09-26 06:05:23 -05:00
parent 9980c56d81
commit c89cc1da44
6 changed files with 70 additions and 1 deletions

View File

@@ -181,6 +181,9 @@ template <typename T> bool LR11x0Interface<T>::reconfigure()
err = lora.setOutputPower(power);
assert(err == RADIOLIB_ERR_NONE);
// Initialize AGC/AFC reset timing (30 second interval)
nextAgcResetMs = millis() + THIRY_SECONDS_MS;
startReceive(); // restart receiving
return RADIOLIB_ERR_NONE;

View File

@@ -248,6 +248,9 @@ bool RF95Interface::reconfigure()
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING);
// Initialize AGC reset timing
nextAgcResetMs = millis() + 30000;
startReceive(); // restart receiving
return RADIOLIB_ERR_NONE;

View File

@@ -37,7 +37,7 @@ void LockingArduinoHal::spiTransfer(uint8_t *out, size_t len, uint8_t *in)
RadioLibInterface::RadioLibInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
RADIOLIB_PIN_TYPE busy, PhysicalLayer *_iface)
: NotifiedWorkerThread("RadioIf"), module(hal, cs, irq, rst, busy), iface(_iface)
: NotifiedWorkerThread("RadioIf"), module(hal, cs, irq, rst, busy), iface(_iface), nextAgcResetMs(0)
{
instance = this;
#if defined(ARCH_STM32WL) && defined(USE_SX1262)
@@ -245,6 +245,9 @@ currently active.
*/
void RadioLibInterface::onNotify(uint32_t notification)
{
// Check for AGC reset before processing notifications
checkAndPerformAgcReset();
switch (notification) {
case ISR_TX:
handleTransmitInterrupt();
@@ -553,3 +556,45 @@ bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
return res == RADIOLIB_ERR_NONE;
}
}
void RadioLibInterface::checkAndPerformAgcReset()
{
// Use a sensible default of 30 seconds for AGC/AFC reset
// Based on MeshCore's approach and SX126x datasheet recommendations
static const uint32_t AGC_RESET_INTERVAL_MS = 30 * 1000U;
uint32_t now = millis();
// Add debug info on first call or when nextAgcResetMs is not set
static bool first_call = true;
if (first_call || nextAgcResetMs == 0) {
LOG_DEBUG("AGC reset: now=%u, nextAgcResetMs=%u, first_call=%d", now, nextAgcResetMs, first_call);
first_call = false;
if (nextAgcResetMs == 0) {
// Initialize if not set by reconfigure()
nextAgcResetMs = now + AGC_RESET_INTERVAL_MS;
LOG_DEBUG("AGC reset initialized to %u", nextAgcResetMs);
}
}
if (now < nextAgcResetMs) {
return; // Not time yet
}
// Only reset if we're not actively sending, receiving, or processing packets
if (isSending() || isActivelyReceiving() || isReceiving) {
// Postpone reset by a short delay to avoid interfering with active operations
nextAgcResetMs = now + 1000; // Retry in 1 second
LOG_DEBUG("AGC reset postponed - radio busy");
return;
}
LOG_INFO("Performing AGC/AFC reset via startReceive()");
// Use MeshCore's approach: issue startReceive() to reset AGC/AFC
// This is cleaner than direct register manipulation and works across all radio types
startReceive();
// Schedule next reset
nextAgcResetMs = now + AGC_RESET_INTERVAL_MS;
}

View File

@@ -16,6 +16,8 @@
#define RADIOLIB_PIN_TYPE uint32_t
#define THIRY_SECONDS_MS 30000
// In addition to the default Rx flags, we need the PREAMBLE_DETECTED flag to detect whether we are actively receiving
#define MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS (RADIOLIB_IRQ_RX_DEFAULT_FLAGS | (1 << RADIOLIB_IRQ_PREAMBLE_DETECTED))
@@ -181,8 +183,18 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
protected:
uint32_t activeReceiveStart = 0;
/** Track when we should next perform an AGC/AFC reset */
uint32_t nextAgcResetMs = 0;
bool receiveDetected(uint16_t irq, ulong syncWordHeaderValidFlag, ulong preambleDetectedFlag);
/**
* Perform AGC/AFC reset by issuing a startReceive() call if enough time has passed
* and we're not currently receiving or transmitting.
* Based on MeshCore's approach of using RadioLib startReceive() to reset AGC.
*/
void checkAndPerformAgcReset();
/** Do any hardware setup needed on entry into send configuration for the radio.
* Subclasses can customize, but must also call this base method */
virtual void configHardwareForSend();

View File

@@ -228,6 +228,9 @@ template <typename T> bool SX126xInterface<T>::reconfigure()
LOG_ERROR("SX126X setOutputPower %s%d", radioLibErr, err);
assert(err == RADIOLIB_ERR_NONE);
// Initialize AGC/AFC reset timing (30 second interval)
nextAgcResetMs = millis() + THIRY_SECONDS_MS;
startReceive(); // restart receiving
return RADIOLIB_ERR_NONE;

View File

@@ -150,6 +150,9 @@ template <typename T> bool SX128xInterface<T>::reconfigure()
LOG_ERROR("SX128X setOutputPower %s%d", radioLibErr, err);
assert(err == RADIOLIB_ERR_NONE);
// Initialize AGC/AFC reset timing (30 second interval)
nextAgcResetMs = millis() + THIRY_SECONDS_MS;
startReceive(); // restart receiving
return RADIOLIB_ERR_NONE;