Add T-Beam 1W external LNA control
This commit is contained in:
1 parent
759a35fc4f
commit
366f6ab73d
5 files changed
+106
-2
No files matched your search
@@ -156,6 +156,45 @@ class CustomSX1262 : public SX1262 {
|
||||
return _rx_ps_rf_rx_disabled;
|
||||
}
|
||||
|
||||
// Select whether a host-controlled RXEN pin is asserted in receive mode.
|
||||
// Some FEM modules (notably the LilyGo T-Beam 1W XY16P35) expose their
|
||||
// external LNA supply on RXEN while DIO2 independently selects the RF
|
||||
// switch. Swapping RadioLib's table keeps the requested state intact
|
||||
// across RX, CAD, TX, standby, and duty-cycle transitions; a one-shot
|
||||
// digitalWrite() would be overwritten on the next mode change.
|
||||
bool setExternalRxLnaEnabled(bool enabled) {
|
||||
#if defined(SX126X_RXEN)
|
||||
#if defined(SX126X_TXEN)
|
||||
static constexpr uint32_t tx_en = SX126X_TXEN;
|
||||
#else
|
||||
static constexpr uint32_t tx_en = RADIOLIB_NC;
|
||||
#endif
|
||||
|
||||
static const uint32_t pins[Module::RFSWITCH_MAX_PINS] = {
|
||||
SX126X_RXEN, tx_en, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC,
|
||||
};
|
||||
static const Module::RfSwitchMode_t lna_enabled_table[] = {
|
||||
{ Module::MODE_IDLE, { LOW, LOW } },
|
||||
{ Module::MODE_RX, { HIGH, LOW } },
|
||||
{ Module::MODE_TX, { LOW, HIGH } },
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
static const Module::RfSwitchMode_t lna_disabled_table[] = {
|
||||
{ Module::MODE_IDLE, { LOW, LOW } },
|
||||
{ Module::MODE_RX, { LOW, LOW } },
|
||||
{ Module::MODE_TX, { LOW, HIGH } },
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
this->mod->setRfSwitchTable(
|
||||
pins, enabled ? lna_enabled_table : lna_disabled_table);
|
||||
return true;
|
||||
#else
|
||||
(void)enabled;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// BUSY high means the chip is asleep (RX duty-cycle sleep window) or mid
|
||||
// command; any SPI access would stall until the chip's next listen window.
|
||||
bool isChipBusy() {
|
||||
|
||||
@@ -78,6 +78,25 @@ public:
|
||||
return ((CustomSX1262 *)_radio)->isRxPowerSavingRfRxDisabled();
|
||||
}
|
||||
|
||||
// Reconfigure through the normal bounded radio transition so RXEN is never
|
||||
// asserted while a transmission or unread packet owns the radio. The
|
||||
// selected table is then honored by every RadioLib mode transition.
|
||||
bool setExternalRxLnaEnabled(bool enabled) {
|
||||
#if defined(SX126X_RXEN)
|
||||
if (SX126X_RXEN == RADIOLIB_NC) return false;
|
||||
|
||||
uint8_t resume_rx = beginReconfigure();
|
||||
if (resume_rx > 1) return false;
|
||||
|
||||
bool success = ((CustomSX1262 *)_radio)->setExternalRxLnaEnabled(enabled);
|
||||
endReconfigure(resume_rx);
|
||||
return success;
|
||||
#else
|
||||
(void)enabled;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
int startReceiveMode() override {
|
||||
if (_rx_ps_armed) {
|
||||
@@ -118,7 +137,16 @@ protected:
|
||||
bool radioDeepInit() override {
|
||||
// std_init() re-runs RadioLib begin(), which starts with a hardware reset
|
||||
// via NRST - the only way out of a hard-locked chip (BUSY stuck high).
|
||||
return ((CustomSX1262 *)_radio)->std_init();
|
||||
bool success = ((CustomSX1262 *)_radio)->std_init();
|
||||
#if defined(TBEAM_1W)
|
||||
// std_init() restores RadioLib's default RXEN table. Reapply the T-Beam
|
||||
// 1W's persisted external-LNA selection before receive mode is re-armed.
|
||||
if (success && _board->canControlLoRaFemLna()) {
|
||||
success = ((CustomSX1262 *)_radio)->setExternalRxLnaEnabled(
|
||||
_board->isLoRaFemLnaEnabled());
|
||||
}
|
||||
#endif
|
||||
return success;
|
||||
}
|
||||
bool supportsRadioDeepInit() const override { return true; }
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "TBeam1WBoard.h"
|
||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
||||
|
||||
void TBeam1WBoard::begin() {
|
||||
ESP32Board::begin();
|
||||
@@ -9,7 +10,10 @@ void TBeam1WBoard::begin() {
|
||||
radio_powered = true;
|
||||
delay(10); // Allow radio to power up
|
||||
|
||||
// RF switch RXEN pin handled by RadioLib via setRfSwitchPins()
|
||||
// Keep the external LNA off until RadioLib deliberately enters RX. GPIO21
|
||||
// is subsequently controlled by RadioLib's target-specific RF switch table.
|
||||
pinMode(SX126X_RXEN, OUTPUT);
|
||||
digitalWrite(SX126X_RXEN, LOW);
|
||||
|
||||
// Initialize LED
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
@@ -62,6 +66,29 @@ void TBeam1WBoard::powerOff() {
|
||||
ESP32Board::powerOff();
|
||||
}
|
||||
|
||||
void TBeam1WBoard::attachRadioDriver(CustomSX1262Wrapper* driver) {
|
||||
radio_driver = driver;
|
||||
}
|
||||
|
||||
bool TBeam1WBoard::setLoRaFemLnaEnabled(bool enable) {
|
||||
if (radio_driver == nullptr || !radio_driver->setExternalRxLnaEnabled(enable)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This is the requested RX-mode state. TX and standby always force CTRL low
|
||||
// regardless of this preference, protecting both the LNA and PA paths.
|
||||
lna_enabled = enable;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TBeam1WBoard::canControlLoRaFemLna() const {
|
||||
return radio_driver != nullptr;
|
||||
}
|
||||
|
||||
bool TBeam1WBoard::isLoRaFemLnaEnabled() const {
|
||||
return lna_enabled;
|
||||
}
|
||||
|
||||
void TBeam1WBoard::setFanEnabled(bool enabled) {
|
||||
digitalWrite(FAN_CTRL_PIN, enabled ? HIGH : LOW);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <helpers/ESP32Board.h>
|
||||
#include "variant.h"
|
||||
|
||||
class CustomSX1262Wrapper;
|
||||
|
||||
// LilyGo T-Beam 1W with SX1262 + external PA (XY16P35 module)
|
||||
//
|
||||
// Power architecture (LDO is separate chip on T-Beam board, not inside XY16P35):
|
||||
@@ -30,6 +32,8 @@
|
||||
class TBeam1WBoard : public ESP32Board {
|
||||
private:
|
||||
bool radio_powered = false;
|
||||
bool lna_enabled = true;
|
||||
CustomSX1262Wrapper* radio_driver = nullptr;
|
||||
|
||||
public:
|
||||
void begin();
|
||||
@@ -39,6 +43,11 @@ public:
|
||||
const char* getManufacturerName() const override;
|
||||
void powerOff() override;
|
||||
|
||||
void attachRadioDriver(CustomSX1262Wrapper* driver);
|
||||
bool setLoRaFemLnaEnabled(bool enable) override;
|
||||
bool canControlLoRaFemLna() const override;
|
||||
bool isLoRaFemLnaEnabled() const override;
|
||||
|
||||
// Fan control methods
|
||||
void setFanEnabled(bool enabled);
|
||||
bool isFanEnabled() const;
|
||||
|
||||
@@ -36,6 +36,7 @@ bool radio_init() {
|
||||
|
||||
bool success = radio.std_init(&spi);
|
||||
if (success) {
|
||||
board.attachRadioDriver(&radio_driver);
|
||||
// T-Beam 1W has external PA requiring longer ramp time (>800us recommended)
|
||||
// RADIOLIB_SX126X_PA_RAMP_800U = 0x05
|
||||
radio.setTxParams(LORA_TX_POWER, RADIOLIB_SX126X_PA_RAMP_800U);
|
||||
|
||||
Reference in new issue
Block a user