Restore SX1276 CW support and calibrated power sweeps
Retain the original carrier feature from PR #11 with zero-deviation FSK, board PA calibration, and LoRa restoration. Re-key after power changes without extending the timeout, and restore prior power after a failed sweep. Cover native and SX1276 transitions, failure recovery, external PA and RFO mapping; verify Linkflow repeater and Heltec V2 USB Companion builds.
This commit is contained in:
1 parent
9de1373bd9
commit
27e4a0d0db
6 files changed
+226
-14
No files matched your search
@@ -10,8 +10,12 @@
|
||||
class CustomSX1276Wrapper : public RadioLibWrapper {
|
||||
public:
|
||||
CustomSX1276Wrapper(CustomSX1276& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
|
||||
bool supportsCarrierWave() const override { return supportsRadioDeepInit(); }
|
||||
|
||||
void powerOff() { _radio->standby(); _radio->sleep(); }
|
||||
void powerOff() {
|
||||
if (isCarrierWaveActive()) setCarrierWave(0, 0);
|
||||
_radio->standby(); _radio->sleep();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool applyParams(float freq, float bw, uint8_t sf, uint8_t cr) override {
|
||||
@@ -24,6 +28,7 @@ protected:
|
||||
|
||||
public:
|
||||
bool setCodingRate(uint8_t cr) override {
|
||||
if (isCarrierWaveActive()) return false;
|
||||
return ((CustomSX1276 *)_radio)->setCodingRate(cr) == RADIOLIB_ERR_NONE;
|
||||
}
|
||||
|
||||
@@ -40,6 +45,28 @@ public:
|
||||
uint8_t getSpreadingFactor() const override { return ((CustomSX1276 *)_radio)->spreadingFactor; }
|
||||
|
||||
protected:
|
||||
int16_t enterCarrierWave() override {
|
||||
auto* radio = static_cast<CustomSX1276*>(_radio);
|
||||
// Direct TX needs FSK. Zero deviation prevents a floating DIO2 data input
|
||||
// from moving the carrier. Start at the PA_BOOST floor, while still idle;
|
||||
// user-facing power may be an external PA level, not chip drive power.
|
||||
int16_t status = radio->beginFSK(_cur_freq, 4.8, 0.0, 125.0, 2, 16, false);
|
||||
if (status != RADIOLIB_ERR_NONE) return status;
|
||||
#ifdef SX127X_CURRENT_LIMIT
|
||||
status = radio->setCurrentLimit(SX127X_CURRENT_LIMIT);
|
||||
if (status != RADIOLIB_ERR_NONE) return status;
|
||||
#endif
|
||||
status = applyCachedTxPower(_dbm_valid ? _cur_dbm : LORA_TX_POWER);
|
||||
if (status != RADIOLIB_ERR_NONE) return status;
|
||||
return radio->transmitDirect();
|
||||
}
|
||||
|
||||
bool restoreCarrierWaveModem() override {
|
||||
// Restores LoRa, runtime profile/preamble, IRQ mapping and PA calibration.
|
||||
// Shared cleanup retains the stop/retry guard if any restoration fails.
|
||||
return restoreAfterDeepInit();
|
||||
}
|
||||
|
||||
int16_t performChannelScan() override {
|
||||
return ((CustomSX1276 *)_radio)->tryScanChannel(cadScanTimeoutMillis(), *_board);
|
||||
}
|
||||
|
||||
@@ -89,6 +89,23 @@ uint32_t RadioLibWrapper::getRngSeed() {
|
||||
}
|
||||
|
||||
bool RadioLibWrapper::setTxPower(int8_t dbm) {
|
||||
if (_cw_active) {
|
||||
if (_cw_stopping) return false;
|
||||
// Permit meter sweeps through the board's normal power/PA calibration.
|
||||
// SX127x's power setter enters standby, so re-key without resetting the
|
||||
// modem or extending the original CW deadline.
|
||||
if (applyCachedTxPower(dbm) != RADIOLIB_ERR_NONE) {
|
||||
stopCarrierWave();
|
||||
return false;
|
||||
}
|
||||
if (_radio->transmitDirect() != RADIOLIB_ERR_NONE) {
|
||||
stopCarrierWave();
|
||||
return false;
|
||||
}
|
||||
_cur_dbm = dbm;
|
||||
_dbm_valid = true;
|
||||
return true;
|
||||
}
|
||||
const uint8_t resume_rx = beginReconfigure();
|
||||
if (resume_rx > 1) return false;
|
||||
|
||||
@@ -707,7 +724,7 @@ mesh::RadioParamApplyResult RadioLibWrapper::setCarrierWave(uint8_t profile, uin
|
||||
_board->setRadioTestActive(true); // service the deadline even without USB
|
||||
_board->onBeforeTransmit();
|
||||
_cw_board_tx = true;
|
||||
if (_radio->transmitDirect() != RADIOLIB_ERR_NONE) {
|
||||
if (enterCarrierWave() != RADIOLIB_ERR_NONE) {
|
||||
stopCarrierWave(); // a failed SPI result does not prove TX stayed off
|
||||
return Result::FAILED;
|
||||
}
|
||||
@@ -717,11 +734,13 @@ mesh::RadioParamApplyResult RadioLibWrapper::setCarrierWave(uint8_t profile, uin
|
||||
|
||||
bool RadioLibWrapper::stopCarrierWave() {
|
||||
_cw_stopping = true;
|
||||
// finishTransmit clears radio IRQs and enters standby on both supported
|
||||
// families. Deassert external TX even if SPI fails, then try a radio reset.
|
||||
// Deassert external TX even if SPI fails. SX127x must also rebuild its LoRa
|
||||
// modem after FSK direct mode before normal packet work can resume.
|
||||
const int16_t status = _radio->finishTransmit();
|
||||
if (_cw_board_tx) { _board->onAfterTransmit(); _cw_board_tx = false; }
|
||||
if (status != RADIOLIB_ERR_NONE && !restoreAfterDeepInit()) {
|
||||
const bool restored = status == RADIOLIB_ERR_NONE
|
||||
? restoreCarrierWaveModem() : restoreAfterDeepInit();
|
||||
if (!restored) {
|
||||
_cw_retry_at = static_cast<uint32_t>(millis()) + 100;
|
||||
return false; // hold normal work until stopping the carrier is confirmed
|
||||
}
|
||||
|
||||
@@ -157,6 +157,12 @@ protected:
|
||||
return _radio->setOutputPower(dbm);
|
||||
}
|
||||
virtual bool applyRxBoostedGainMode(bool) { return false; }
|
||||
virtual int16_t enterCarrierWave() { return _radio->transmitDirect(); }
|
||||
// Native-CW radios keep their modem. Reapply cached power in case a meter
|
||||
// sweep failed halfway through; SX127x also rebuilds its LoRa configuration.
|
||||
virtual bool restoreCarrierWaveModem() {
|
||||
return !_dbm_valid || applyCachedTxPower(_cur_dbm) == RADIOLIB_ERR_NONE;
|
||||
}
|
||||
// Dual-profile scanning already suspends RXPS. Supported radios can also
|
||||
// retain their oscillator across the intervening standby/reconfigure steps.
|
||||
// Called only at the safe scan-mode entry/exit boundary, not during a packet.
|
||||
|
||||
Reference in new issue
Block a user