diff --git a/src/helpers/esp32/SerialBLEInterface.cpp b/src/helpers/esp32/SerialBLEInterface.cpp index eccfeca68..dcfa0e1e3 100644 --- a/src/helpers/esp32/SerialBLEInterface.cpp +++ b/src/helpers/esp32/SerialBLEInterface.cpp @@ -1,4 +1,5 @@ #include "SerialBLEInterface.h" +#include "esp_mac.h" // See the following for generating UUIDs: // https://www.uuidgenerator.net/ diff --git a/src/helpers/radiolib/CustomLR1121.h b/src/helpers/radiolib/CustomLR1121.h new file mode 100644 index 000000000..9ed33b601 --- /dev/null +++ b/src/helpers/radiolib/CustomLR1121.h @@ -0,0 +1,49 @@ +#pragma once + +#include + +class CustomLR1121 : public LR1121 { +public: + CustomLR1121(Module* mod) : LR1121(mod) { } + + int16_t setFrequency(float freq) override { + _is_24ghz = (freq >= 2400.0f); + return LR1121::setFrequency(freq); + } + + int16_t setFrequency(float freq, bool skipCalibration, float band = 4) { + _is_24ghz = (freq >= 2400.0f); + return LR1121::setFrequency(freq, skipCalibration, band); + } + + int16_t setOutputPower(int8_t power) override { + return LR1121::setOutputPower(clampTxPower(power)); + } + + int16_t setOutputPower(int8_t power, bool forceHighPower, uint32_t rampTimeUs = 48) { + return LR1121::setOutputPower(clampTxPower(power), forceHighPower, rampTimeUs); + } + + size_t getPacketLength(bool update) override { + size_t len = LR1121::getPacketLength(update); + if (len == 0 && (getIrqStatus() & RADIOLIB_LR11X0_IRQ_HEADER_ERR)) { + // Recover from sporadic shifted-packet state seen after header errors. + standby(); + } + return len; + } + + bool isReceiving() { + uint16_t irq = getIrqStatus(); + return (irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID) || + (irq & RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED); + } + +private: + bool _is_24ghz = false; + + int8_t clampTxPower(int8_t power) const { + const int8_t maxDbm = _is_24ghz ? 20 : 22; + return (power > maxDbm) ? maxDbm : power; + } +}; diff --git a/src/helpers/radiolib/CustomLR1121Wrapper.h b/src/helpers/radiolib/CustomLR1121Wrapper.h new file mode 100644 index 000000000..fa21200eb --- /dev/null +++ b/src/helpers/radiolib/CustomLR1121Wrapper.h @@ -0,0 +1,93 @@ +#pragma once + +#include "CustomLR1121.h" +#include "RadioLibWrappers.h" + +class CustomLR1121Wrapper : public RadioLibWrapper { +public: + CustomLR1121Wrapper(CustomLR1121& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { } + + int recvRaw(uint8_t* bytes, int sz) override { + int len = RadioLibWrapper::recvRaw(bytes, sz); +#if defined(ESP32) && defined(P_LORA_TX_NEOPIXEL_LED) + if (len > 0) { + _rx_led_until = millis() + RX_LED_HOLD_MILLIS; + // Don't override TX white while a transmit is in progress. + if (!_tx_active) { + setLedGreen(); + } + } +#endif + return len; + } + + bool startSendRaw(const uint8_t* bytes, int len) override { + bool ok = RadioLibWrapper::startSendRaw(bytes, len); +#if defined(ESP32) && defined(P_LORA_TX_NEOPIXEL_LED) + if (ok) { + _tx_active = true; + // Keep TX indicator deterministic (white), even if RX pulse was active. + setLedWhite(); + } +#endif + return ok; + } + + void loop() override { + RadioLibWrapper::loop(); +#if defined(ESP32) && defined(P_LORA_TX_NEOPIXEL_LED) + if (!_tx_active && _rx_led_until != 0 && millis() > _rx_led_until) { + _rx_led_until = 0; + setLedOff(); + } +#endif + } + + bool isReceivingPacket() override { + return ((CustomLR1121*)_radio)->isReceiving(); + } + + float getCurrentRSSI() override { + float rssi = -110; + ((CustomLR1121*)_radio)->getRssiInst(&rssi); + return rssi; + } + + void onSendFinished() override { + RadioLibWrapper::onSendFinished(); + ((CustomLR1121*)_radio)->setPreambleLength(16); +#if defined(ESP32) && defined(P_LORA_TX_NEOPIXEL_LED) + _tx_active = false; + if (_rx_led_until != 0 && millis() <= _rx_led_until) { + setLedGreen(); + } else { + setLedOff(); + } +#endif + } + + float getLastRSSI() const override { return ((CustomLR1121*)_radio)->getRSSI(); } + float getLastSNR() const override { return ((CustomLR1121*)_radio)->getSNR(); } + int16_t setRxBoostedGainMode(bool en) { return ((CustomLR1121*)_radio)->setRxBoostedGainMode(en); } + +private: +#if defined(ESP32) && defined(P_LORA_TX_NEOPIXEL_LED) + static constexpr uint8_t TX_LED_BRIGHTNESS = 64; + static constexpr uint8_t RX_LED_BRIGHTNESS = 64; + static constexpr uint32_t RX_LED_HOLD_MILLIS = 80; + uint32_t _rx_led_until = 0; + bool _tx_active = false; + + void setLedOff() { + neopixelWrite(P_LORA_TX_NEOPIXEL_LED, 0, 0, 0); + } + + void setLedWhite() { + neopixelWrite(P_LORA_TX_NEOPIXEL_LED, TX_LED_BRIGHTNESS, TX_LED_BRIGHTNESS, TX_LED_BRIGHTNESS); + } + + void setLedGreen() { + neopixelWrite(P_LORA_TX_NEOPIXEL_LED, 0, RX_LED_BRIGHTNESS, 0); + } +#endif +}; diff --git a/variants/m5stack_unit_c6l/platformio.ini b/variants/m5stack_unit_c6l/platformio.ini index bbfdb4a11..a2b8b0873 100644 --- a/variants/m5stack_unit_c6l/platformio.ini +++ b/variants/m5stack_unit_c6l/platformio.ini @@ -5,7 +5,7 @@ board_build.partitions = min_spiffs.csv ; get around 4mb flash limit build_flags = ${esp32c6_base.build_flags} ${sensor_base.build_flags} - -I variants/M5Stack_Unit_C6L + -I variants/m5stack_unit_c6l -D P_LORA_TX_LED=15 -D P_LORA_SCLK=20 -D P_LORA_MISO=22