From 85306a3dd9bf699c609ab01b77e31f395b881b34 Mon Sep 17 00:00:00 2001 From: Andrik45719 Date: Fri, 7 Nov 2025 18:10:44 +0200 Subject: [PATCH] Refactor RadioLibInterface to support multiple instances and update related references --- src/graphics/Screen.cpp | 2 +- src/graphics/draw/DebugRenderer.cpp | 2 +- src/input/ButtonThread.cpp | 2 +- src/mesh/RadioLibInterface.cpp | 28 ++++++++++++++--------- src/mesh/RadioLibInterface.h | 2 +- src/mesh/http/ContentHandler.cpp | 6 +++-- src/modules/Telemetry/DeviceTelemetry.cpp | 12 +++++----- variants/nrf52840/t-echo/nicheGraphics.h | 2 +- 8 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 86599d5b3e..24d249f072 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1034,7 +1034,7 @@ void Screen::setFrames(FrameFocus focus) indicatorIcons.push_back(icon_compass); } #endif - if (RadioLibInterface::instance && !hiddenFrames.lora) { + if (!RadioLibInterface::instances.empty() && !hiddenFrames.lora) { fsi.positions.lora = numframes; normalFrames[numframes++] = graphics::DebugRenderer::drawLoRaFocused; indicatorIcons.push_back(icon_radio); diff --git a/src/graphics/draw/DebugRenderer.cpp b/src/graphics/draw/DebugRenderer.cpp index 60abd661e6..6bc91688a2 100644 --- a/src/graphics/draw/DebugRenderer.cpp +++ b/src/graphics/draw/DebugRenderer.cpp @@ -422,7 +422,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, // === Fourth Row: Frequency / ChanNum === char frequencyslot[35]; char freqStr[16]; - float freq = RadioLibInterface::instance->getFreq(); + float freq = RadioLibInterface::instances.front()->getFreq(); snprintf(freqStr, sizeof(freqStr), "%.3f", freq); if (config.lora.channel_num == 0) { #if defined(M5STACK_UNITC6L) diff --git a/src/input/ButtonThread.cpp b/src/input/ButtonThread.cpp index 9f53b06f4a..dd6b817b10 100644 --- a/src/input/ButtonThread.cpp +++ b/src/input/ButtonThread.cpp @@ -189,7 +189,7 @@ int32_t ButtonThread::runOnce() case BUTTON_EVENT_LONG_PRESSED: { // Ignore if: TX in progress // Uncommon T-Echo hardware bug, LoRa TX triggers touch button - if (_touchQuirk && RadioLibInterface::instance && RadioLibInterface::instance->isSending()) + if (_touchQuirk && !RadioLibInterface::instances.empty() && RadioLibInterface::instances.front()->isSending()) break; // Check if this is part of a short-press + long-press combination diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index 80e51b8bcb..0eea69f68d 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -39,7 +39,7 @@ RadioLibInterface::RadioLibInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE c RADIOLIB_PIN_TYPE busy, PhysicalLayer *_iface) : NotifiedWorkerThread("RadioIf"), module(hal, cs, irq, rst, busy), iface(_iface) { - instance = this; + instances.push_back(this); #if defined(ARCH_STM32WL) && defined(USE_SX1262) module.setCb_digitalWrite(stm32wl_emulate_digitalWrite); module.setCb_digitalRead(stm32wl_emulate_digitalRead); @@ -55,15 +55,21 @@ RadioLibInterface::RadioLibInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE c void INTERRUPT_ATTR RadioLibInterface::isrLevel0Common(PendingISR cause) { - instance->disableInterrupt(); - - BaseType_t xHigherPriorityTaskWoken; - instance->notifyFromISR(&xHigherPriorityTaskWoken, cause, true); - - /* Force a context switch if xHigherPriorityTaskWoken is now set to pdTRUE. - The macro used to do this is dependent on the port and may be called - portEND_SWITCHING_ISR. */ - YIELD_FROM_ISR(xHigherPriorityTaskWoken); + for(auto instance : instances) + { + if(digitalRead(instance->module.getIrq())) + { + instance->disableInterrupt(); + + BaseType_t xHigherPriorityTaskWoken; + instance->notifyFromISR(&xHigherPriorityTaskWoken, cause, true); + + /* Force a context switch if xHigherPriorityTaskWoken is now set to pdTRUE. + The macro used to do this is dependent on the port and may be called + portEND_SWITCHING_ISR. */ + YIELD_FROM_ISR(xHigherPriorityTaskWoken); + } + } } void INTERRUPT_ATTR RadioLibInterface::isrRxLevel0() @@ -78,7 +84,7 @@ void INTERRUPT_ATTR RadioLibInterface::isrTxLevel0() /** Our ISR code currently needs this to find our active instance */ -RadioLibInterface *RadioLibInterface::instance; +std::vector RadioLibInterface::instances; /** Could we send right now (i.e. either not actively receiving or transmitting)? */ bool RadioLibInterface::canSendImmediately() diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index 833c887108..ef99753bc6 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -100,7 +100,7 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified public: /** Our ISR code currently needs this to find our active instance */ - static RadioLibInterface *instance; + static std::vector instances; /** * Glue functions called from ISR land diff --git a/src/mesh/http/ContentHandler.cpp b/src/mesh/http/ContentHandler.cpp index 7b7ebb5956..776a245089 100644 --- a/src/mesh/http/ContentHandler.cpp +++ b/src/mesh/http/ContentHandler.cpp @@ -694,8 +694,10 @@ void handleReport(HTTPRequest *req, HTTPResponse *res) // data->radio JSONObject jsonObjRadio; - jsonObjRadio["frequency"] = new JSONValue(RadioLibInterface::instance->getFreq()); - jsonObjRadio["lora_channel"] = new JSONValue((int)RadioLibInterface::instance->getChannelNum() + 1); + if(!RadioLibInterface::instances.empty()) { + jsonObjRadio["frequency"] = new JSONValue(RadioLibInterface::instances.front()->getFreq()); + jsonObjRadio["lora_channel"] = new JSONValue((int)RadioLibInterface::instances.front()->getChannelNum() + 1); + } // collect data to inner data object JSONObject jsonObjInner; diff --git a/src/modules/Telemetry/DeviceTelemetry.cpp b/src/modules/Telemetry/DeviceTelemetry.cpp index 066b9361d6..1639c24411 100644 --- a/src/modules/Telemetry/DeviceTelemetry.cpp +++ b/src/modules/Telemetry/DeviceTelemetry.cpp @@ -117,12 +117,12 @@ meshtastic_Telemetry DeviceTelemetryModule::getLocalStatsTelemetry() telemetry.variant.local_stats.air_util_tx = airTime->utilizationTXPercent(); telemetry.variant.local_stats.num_online_nodes = numOnlineNodes; telemetry.variant.local_stats.num_total_nodes = nodeDB->getNumMeshNodes(); - if (RadioLibInterface::instance) { - telemetry.variant.local_stats.num_packets_tx = RadioLibInterface::instance->txGood; - telemetry.variant.local_stats.num_packets_rx = RadioLibInterface::instance->rxGood + RadioLibInterface::instance->rxBad; - telemetry.variant.local_stats.num_packets_rx_bad = RadioLibInterface::instance->rxBad; - telemetry.variant.local_stats.num_tx_relay = RadioLibInterface::instance->txRelay; - telemetry.variant.local_stats.num_tx_dropped = RadioLibInterface::instance->txDrop; + if (!RadioLibInterface::instances.empty()) { + telemetry.variant.local_stats.num_packets_tx = RadioLibInterface::instances.front()->txGood; + telemetry.variant.local_stats.num_packets_rx = RadioLibInterface::instances.front()->rxGood + RadioLibInterface::instances.front()->rxBad; + telemetry.variant.local_stats.num_packets_rx_bad = RadioLibInterface::instances.front()->rxBad; + telemetry.variant.local_stats.num_tx_relay = RadioLibInterface::instances.front()->txRelay; + telemetry.variant.local_stats.num_tx_dropped = RadioLibInterface::instances.front()->txDrop; } #ifdef ARCH_PORTDUINO if (SimRadio::instance) { diff --git a/variants/nrf52840/t-echo/nicheGraphics.h b/variants/nrf52840/t-echo/nicheGraphics.h index c89d816b99..f5b04f305c 100644 --- a/variants/nrf52840/t-echo/nicheGraphics.h +++ b/variants/nrf52840/t-echo/nicheGraphics.h @@ -105,7 +105,7 @@ void setupNicheGraphics() buttons->setHandlerDown(1, [inkhud, backlight]() { // Discard the button press if radio is active // Rare hardware fault: LoRa activity triggers touch button - if (!RadioLibInterface::instance || RadioLibInterface::instance->isSending()) + if (RadioLibInterface::instances.empty() || RadioLibInterface::instances.front()->isSending()) return; // Backlight on (while held)