diff --git a/src/helpers/ui/buzzer.cpp b/src/helpers/ui/buzzer.cpp index e44e0ede..d773fd80 100644 --- a/src/helpers/ui/buzzer.cpp +++ b/src/helpers/ui/buzzer.cpp @@ -426,11 +426,22 @@ static bool i2sInstall() { } static void i2sUninstall() { i2s_channel_disable(s_tx); i2s_del_channel(s_tx); s_tx = nullptr; } static void i2sWrite(const void* src, size_t n, uint32_t ms) { + if (!s_tx) return; size_t w; i2s_channel_write(s_tx, src, n, &w, ms); } -static void i2sStop() { i2s_channel_disable(s_tx); } // clocks off -static void i2sRestart() { i2s_channel_enable(s_tx); } // auto-clear left the buffers silent +// Clocks off between sounds: a disabled channel still drives MCLK, and its +// fractional divider (160 MHz / 39 1/16) makes a comb of lines every 256 kHz +// right up the LoRa band -- 869.632 MHz sat in the EU narrow channel, ~15 dB +// over the Wio Tracker L2's noise floor. So the channel goes, the pins held +// low, and a sound makes it again. +static void i2sStop() { + if (!s_tx) return; + i2sUninstall(); + const int pins[] = { PIN_I2S_MCLK, PIN_I2S_BCK, PIN_I2S_WS, PIN_I2S_DOUT }; + for (int p : pins) { gpio_reset_pin((gpio_num_t)p); pinMode(p, OUTPUT); digitalWrite(p, LOW); } +} +static void i2sRestart() { if (!s_tx) i2sInstall(); } #else static const i2s_port_t I2S_PORT = I2S_NUM_0; static bool i2sInstall() { diff --git a/variants/wio-tracker-l2/platformio.ini b/variants/wio-tracker-l2/platformio.ini index 478b18dd..142f279d 100644 --- a/variants/wio-tracker-l2/platformio.ini +++ b/variants/wio-tracker-l2/platformio.ini @@ -29,7 +29,7 @@ build_flags = ${esp32_base.build_flags} -D P_LORA_MISO=5 -D P_LORA_MOSI=6 -D SX126X_DIO2_AS_RF_SWITCH=true - -D SX126X_DIO3_TCXO_VOLTAGE=1.8 + -D SX126X_DIO3_TCXO_VOLTAGE=3.0 ; the L2 TCXO is a 3 V part (Meshtastic PR #11960) -D SX126X_CURRENT_LIMIT=140 -D SX126X_RX_BOOSTED_GAIN=1 -D ENV_INCLUDE_GPS=1 diff --git a/variants/wio-tracker-l2/target.cpp b/variants/wio-tracker-l2/target.cpp index e5ee78bb..fa435edb 100644 --- a/variants/wio-tracker-l2/target.cpp +++ b/variants/wio-tracker-l2/target.cpp @@ -23,6 +23,7 @@ void buzzerAmpPower(bool on) { board.setSpeakerAmp(on); } #endif void L2GpsProvider::begin() { + if (_started && board.gnssPowered() && !_uart_off) return; // already running board.setGnssPower(true); // with the power-up reset if (_uart_off) { // back from stop(): the UART again Serial1.setRxBufferSize(1024); @@ -30,6 +31,20 @@ void L2GpsProvider::begin() { _uart_off = false; } MicroNMEALocationProvider::begin(); + _started = true; + _cfg_pending = true; + _cfg_rx = rxChars(); +} + +// The L76K starts with GPS + BeiDou only; GLONASS as well gives it a third +// more satellites. Sent once it has booted (NMEA arriving), again after each +// power-up (not saved in the module). +void L2GpsProvider::loop() { + MicroNMEALocationProvider::loop(); + if (_cfg_pending && rxChars() - _cfg_rx > 200) { + _cfg_pending = false; + sendSentence("$PCAS04,7"); // GPS + BeiDou + GLONASS + } } void L2GpsProvider::stop() { @@ -41,7 +56,9 @@ void L2GpsProvider::stop() { board.setGnssPower(false); } -void L2GpsProvider::reset() { board.gnssReset(); } +// The sensor manager resets right after every begin(); begin() already did +// the power-up one, and a second would restart a running receiver. +void L2GpsProvider::reset() { } bool L2GpsProvider::isEnabled() { return board.gnssPowered(); } bool radio_init() { diff --git a/variants/wio-tracker-l2/target.h b/variants/wio-tracker-l2/target.h index f493b866..27246c3e 100644 --- a/variants/wio-tracker-l2/target.h +++ b/variants/wio-tracker-l2/target.h @@ -16,15 +16,21 @@ // The L76K's power and reset lines are on the IO expander, out of the NMEA // provider's reach: begin() / stop() / reset() drive them here, so GPS off -// (Settings, duty cycling) really powers the receiver down. +// (Settings, duty cycling) really powers the receiver down. begin() on a +// running receiver does nothing: a reset there (the app setting "gps" again) +// threw away the acquisition in progress. class L2GpsProvider : public MicroNMEALocationProvider { bool _uart_off = false; + bool _started = false; // begin() ran (the boot one does the reset) + bool _cfg_pending = false; // constellations to set once the module talks + uint32_t _cfg_rx = 0; public: using MicroNMEALocationProvider::MicroNMEALocationProvider; void begin() override; void stop() override; void reset() override; bool isEnabled() override; + void loop() override; }; extern WioTrackerL2Board board;