From 0d2f27e6150ba16559981b846bad319facc61b3e Mon Sep 17 00:00:00 2001 From: pelgraine <140762863+pelgraine@users.noreply.github.com> Date: Wed, 3 Jun 2026 18:31:07 +1000 Subject: [PATCH] Here's what each does: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit target.h — declares meck_audio_route_amp() and meck_audio_codec_init() in the bridge (54-55), guarded by HAS_ES8311_AUDIO, ready for the alarm/voice paths to reuse later. target.cpp — includes ES8311.h (6) and defines both helpers where board and the codec driver are visible: route+amp (100-102), and the once-only es8311_init_44100_16bit() (108-110). Audiobookplayerscreen.h — forward-declares both (54-55); ensureI2SInit() now does route+amp and the 5-arg setPinout with MCLK on MAX (268-270); and meck_audio_codec_init() runs right after connecttoFS (1142). The Pro path is untouched. --- .../ui-new/Audiobookplayerscreen.h | 23 +++++++++++++++++++ variants/lilygo_tdeck_max/target.cpp | 21 +++++++++++++++++ variants/lilygo_tdeck_max/target.h | 9 ++++++++ 3 files changed, 53 insertions(+) diff --git a/examples/companion_radio/ui-new/Audiobookplayerscreen.h b/examples/companion_radio/ui-new/Audiobookplayerscreen.h index 98561651..dfbef1b7 100644 --- a/examples/companion_radio/ui-new/Audiobookplayerscreen.h +++ b/examples/companion_radio/ui-new/Audiobookplayerscreen.h @@ -48,6 +48,13 @@ // Forward declarations class UITask; +#ifdef HAS_ES8311_AUDIO +// Defined in target.cpp (where the board object + ES8311 driver are visible). +// Forward-declared here so this UI header doesn't need the heavy target.h. +void meck_audio_route_amp(); +void meck_audio_codec_init(); +#endif + // ============================================================================ // Configuration // ============================================================================ @@ -253,10 +260,20 @@ private: void ensureI2SInit() { if (!_i2sInitialized && _audio) { +#ifdef HAS_ES8311_AUDIO + // MAX: route to the ES8311 + enable the speaker amp, then configure I2S + // WITH MCLK (the ES8311 is clock slave and needs MCLK on BOARD_I2S_MCLK). + // The codec registers are initialised after connecttoFS starts the clocks + // (see meck_audio_codec_init() in startPlayback). + meck_audio_route_amp(); + bool ok = _audio->setPinout(BOARD_I2S_BCLK, BOARD_I2S_LRC, BOARD_I2S_DOUT, + I2S_PIN_NO_CHANGE, BOARD_I2S_MCLK); +#else bool ok = _audio->setPinout(BOARD_I2S_BCLK, BOARD_I2S_LRC, BOARD_I2S_DOUT, 0); if (!ok) { ok = _audio->setPinout(BOARD_I2S_BCLK, BOARD_I2S_LRC, BOARD_I2S_DOUT); } +#endif if (!ok) Serial.println("AB: setPinout FAILED"); _i2sInitialized = true; } @@ -1118,6 +1135,12 @@ private: // Connect to file — library parses headers asynchronously via loop() _audio->connecttoFS(SD, fullPath.c_str()); +#ifdef HAS_ES8311_AUDIO + // MAX: I2S clocks are now running, so initialise the ES8311 codec (once; + // idempotent). Without this, audiobook/music output is silent until a + // notification tone happens to bring the codec up. + meck_audio_codec_init(); +#endif _audio->setVolume(_volume); // DON'T seek immediately — the library hasn't parsed headers yet. diff --git a/variants/lilygo_tdeck_max/target.cpp b/variants/lilygo_tdeck_max/target.cpp index 6f06a995..e4d6a10b 100644 --- a/variants/lilygo_tdeck_max/target.cpp +++ b/variants/lilygo_tdeck_max/target.cpp @@ -2,6 +2,10 @@ #include "variant.h" #include "target.h" +#ifdef HAS_ES8311_AUDIO + #include "ES8311.h" // MAX: native ES8311 codec init (Arduino Wire) +#endif + TDeckProMaxBoard board; #if defined(P_LORA_SCLK) @@ -89,3 +93,20 @@ mesh::LocalIdentity radio_new_identity() { void radio_reset_agc() { radio.setRxBoostedGainMode(true); } + +#ifdef HAS_ES8311_AUDIO +// Route audio to the ES8311 and enable the speaker amp. Safe to call any time +// (just XL9555 GPIO writes); the outputs latch, so repeat calls are harmless. +void meck_audio_route_amp() { + board.selectAudioES8311(); // XL9555 AUDIO_SEL low -> ES8311 + board.amplifierEnable(); // XL9555 AMPLIFIER high -> NS4150B on +} + +// One-time ES8311 codec init. Must be called after the I2S clocks are running +// (after connecttoFS) so the codec can lock to MCLK/BCLK. Idempotent: the +// static guard means the register init runs at most once per boot. +void meck_audio_codec_init() { + static bool es8311_ready = false; + if (!es8311_ready) es8311_ready = es8311_init_44100_16bit(); +} +#endif \ No newline at end of file diff --git a/variants/lilygo_tdeck_max/target.h b/variants/lilygo_tdeck_max/target.h index 4daa7ae0..b0b10ea1 100644 --- a/variants/lilygo_tdeck_max/target.h +++ b/variants/lilygo_tdeck_max/target.h @@ -45,3 +45,12 @@ void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); void radio_set_tx_power(uint8_t dbm); mesh::LocalIdentity radio_new_identity(); void radio_reset_agc(); + +#ifdef HAS_ES8311_AUDIO +// Audio hardware bring-up (MAX/ES8311), shared across playback paths. +// route_amp: select ES8311 output + enable the speaker amp (safe any time). +// codec_init: one-time ES8311 register init; call AFTER the I2S clocks are +// running (i.e. after connecttoFS), since the codec locks to MCLK/BCLK. +void meck_audio_route_amp(); +void meck_audio_codec_init(); +#endif \ No newline at end of file