mirror of
https://github.com/pelgraine/Meck.git
synced 2026-07-13 13:11:04 +02:00
initial audio playback working success - fixed pin 41 guard dac issue for pro variant by guarding with has es8311 audio
This commit is contained in:
@@ -90,6 +90,9 @@
|
||||
#ifdef MECK_AUDIO_VARIANT
|
||||
#include "VoiceMessageScreen.h"
|
||||
#include "BundledSounds.h"
|
||||
#ifdef HAS_ES8311_AUDIO
|
||||
#include "ES8311.h" // MAX: native ES8311 codec init (Arduino Wire)
|
||||
#endif
|
||||
#endif
|
||||
#if defined(MECK_AUDIO_VARIANT) || defined(HAS_4G_MODEM)
|
||||
#include "NotifSounds.h"
|
||||
@@ -1850,6 +1853,22 @@ void setup() {
|
||||
board.begin();
|
||||
MESH_DEBUG_PRINTLN("setup() - board.begin() done");
|
||||
|
||||
// Initialize touch input (CST328) HERE, immediately after board.begin(),
|
||||
// while the I2C bus is freshly initialised and quiet -- mirroring LilyGo's
|
||||
// working example, which calls touch.begin() first thing. Running it later
|
||||
// (after display/radio/filesystem init) left the bus in a state where the
|
||||
// CST328 firmware-info read failed.
|
||||
#if defined(LilyGo_TDeck_Pro) && defined(HAS_TOUCHSCREEN)
|
||||
#if defined(LilyGo_TDeck_Pro_Max)
|
||||
board.touchReset(); // fresh XL9555 reset immediately before driver init
|
||||
#endif
|
||||
if (touchInput.begin(CST328_PIN_INT)) {
|
||||
MESH_DEBUG_PRINTLN("setup() - Touch input initialized");
|
||||
} else {
|
||||
MESH_DEBUG_PRINTLN("setup() - Touch input FAILED");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
DisplayDriver* disp = NULL;
|
||||
MESH_DEBUG_PRINTLN("setup() - about to call display.begin()");
|
||||
@@ -2283,14 +2302,8 @@ void setup() {
|
||||
initKeyboard();
|
||||
#endif
|
||||
|
||||
// Initialize touch input (CST328 on T-Deck Pro)
|
||||
#if defined(LilyGo_TDeck_Pro) && defined(HAS_TOUCHSCREEN)
|
||||
if (touchInput.begin(CST328_PIN_INT)) {
|
||||
MESH_DEBUG_PRINTLN("setup() - Touch input initialized");
|
||||
} else {
|
||||
MESH_DEBUG_PRINTLN("setup() - Touch input FAILED");
|
||||
}
|
||||
#endif
|
||||
// Touch input (CST328) is initialised earlier, right after board.begin(),
|
||||
// on a freshly-initialised quiet I2C bus (see setup() near board.begin()).
|
||||
|
||||
// Initialize GT911 touch (T5S3 E-Paper Pro)
|
||||
// Wire is already initialized by T5S3Board::begin(). The 4-arg begin() re-calls
|
||||
@@ -2824,7 +2837,9 @@ void loop() {
|
||||
audio->setVolume(0);
|
||||
audio->stopSong();
|
||||
delay(50);
|
||||
// digitalWrite(41, LOW);
|
||||
#ifndef HAS_ES8311_AUDIO
|
||||
digitalWrite(41, LOW);
|
||||
#endif
|
||||
notifTonePlaying = false;
|
||||
notifFadingOut = false;
|
||||
notifMuted = false;
|
||||
@@ -2868,8 +2883,36 @@ void loop() {
|
||||
// Stop any stale playback before touching DAC
|
||||
audio->stopSong();
|
||||
|
||||
// Configure I2S pins first (before DAC power)
|
||||
bool ok = audio->setPinout(BOARD_I2S_BCLK, BOARD_I2S_LRC, BOARD_I2S_DOUT, 0);
|
||||
// MAX: route audio to the ES8311 codec and enable the speaker amp.
|
||||
// NOTE: the codec REGISTER init is deferred until AFTER the I2S clocks
|
||||
// are actually running (after connecttoFS + the silence-fill loop). The
|
||||
// ES8311 appears to need live BCLK/LRCK to lock its clock tree; init'd
|
||||
// on a clockless bus it configures correctly (readback confirms) but
|
||||
// produces no output. Routing/amp are safe to set here.
|
||||
#ifdef HAS_ES8311_AUDIO
|
||||
board.selectAudioES8311(); // XL9555 AUDIO_SEL low -> ES8311
|
||||
board.amplifierEnable(); // XL9555 AMPLIFIER high -> NS4150B on
|
||||
// DIAG: read back the two routing pins to confirm they took effect
|
||||
// (AUDIO_SEL should be LOW=0 for ES8311, AMPLIFIER should be HIGH=1).
|
||||
Serial.printf("NotifTone: routing AUDIO_SEL=%d (want 0) AMP=%d (want 1)\n",
|
||||
board.xl9555_digitalRead(XL_PIN_AUDIO_SEL) ? 1 : 0,
|
||||
board.xl9555_digitalRead(XL_PIN_AMPLIFIER) ? 1 : 0);
|
||||
#endif
|
||||
|
||||
// Configure I2S pins. Mirroring Ripple, the ES8311 is driven WITH MCLK
|
||||
// (use_mclk=true), so MCLK must be generated on BOARD_I2S_MCLK. Use the
|
||||
// 5-arg setPinout: the 4th arg is DIN (data-in, unused -> no change), the
|
||||
// 5th is MCK. The earlier 4-arg call mistakenly passed MCLK as the 4th
|
||||
// (DIN) arg, so MCLK was never generated -- this passes it as MCK.
|
||||
#ifdef HAS_ES8311_AUDIO
|
||||
bool ok = audio->setPinout(BOARD_I2S_BCLK, BOARD_I2S_LRC, BOARD_I2S_DOUT,
|
||||
I2S_PIN_NO_CHANGE, BOARD_I2S_MCLK);
|
||||
Serial.printf("NotifTone: setPinout(BCLK=%d LRC=%d DOUT=%d MCK=%d) -> %s\n",
|
||||
BOARD_I2S_BCLK, BOARD_I2S_LRC, BOARD_I2S_DOUT, BOARD_I2S_MCLK,
|
||||
ok ? "ok" : "FAILED");
|
||||
#else
|
||||
bool ok = audio->setPinout(BOARD_I2S_BCLK, BOARD_I2S_LRC, BOARD_I2S_DOUT, 0);
|
||||
#endif
|
||||
if (!ok) ok = audio->setPinout(BOARD_I2S_BCLK, BOARD_I2S_LRC, BOARD_I2S_DOUT);
|
||||
|
||||
// Start playback at volume 0 (silence into DAC during power-on)
|
||||
@@ -2877,9 +2920,11 @@ void loop() {
|
||||
audio->connecttoFS(SD, file);
|
||||
|
||||
// Enable DAC amplifier and let it stabilise with silence flowing
|
||||
// pinMode(41, OUTPUT);
|
||||
// digitalWrite(41, HIGH);
|
||||
// delay(80);
|
||||
#ifndef HAS_ES8311_AUDIO
|
||||
pinMode(41, OUTPUT);
|
||||
digitalWrite(41, HIGH);
|
||||
delay(80);
|
||||
#endif
|
||||
|
||||
// Fill audio buffer with silence at volume 0 (prevents power-on pop)
|
||||
for (int i = 0; i < 30; i++) {
|
||||
@@ -2887,6 +2932,17 @@ void loop() {
|
||||
delay(2);
|
||||
}
|
||||
|
||||
// I2S clocks are now running (connecttoFS started the channel and the
|
||||
// loop above has pushed samples). NOW bring up the ES8311 over I2C, so
|
||||
// it can lock to the live BCLK/LRCK. Done once per boot.
|
||||
#ifdef HAS_ES8311_AUDIO
|
||||
static bool es8311_ready = false;
|
||||
if (!es8311_ready) {
|
||||
es8311_ready = es8311_init_44100_16bit();
|
||||
Serial.printf("NotifTone: ES8311 init (post-I2S) %s\n", es8311_ready ? "OK" : "FAILED");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Ramp volume up to max
|
||||
audio->setVolume(21);
|
||||
notifTonePlaying = true;
|
||||
|
||||
@@ -264,13 +264,17 @@ private:
|
||||
// ---- DAC power (same pattern as AudiobookPlayerScreen) ----
|
||||
|
||||
void enableDAC() {
|
||||
#ifndef HAS_ES8311_AUDIO
|
||||
pinMode(41, OUTPUT);
|
||||
digitalWrite(41, HIGH);
|
||||
delay(50);
|
||||
#endif
|
||||
}
|
||||
|
||||
void disableDAC() {
|
||||
#ifndef HAS_ES8311_AUDIO
|
||||
digitalWrite(41, LOW);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ---- Audio control for alarm ringing ----
|
||||
|
||||
@@ -219,17 +219,21 @@ private:
|
||||
// On the audio variant, this pin supplies power to the DAC circuit.
|
||||
// TDeckBoard::begin() sets it LOW ("disable modem") which starves the DAC.
|
||||
void enableDAC() {
|
||||
#ifndef HAS_ES8311_AUDIO
|
||||
pinMode(41, OUTPUT);
|
||||
digitalWrite(41, HIGH);
|
||||
if (!_dacPowered) {
|
||||
delay(50);
|
||||
}
|
||||
_dacPowered = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void disableDAC() {
|
||||
#ifndef HAS_ES8311_AUDIO
|
||||
digitalWrite(41, LOW);
|
||||
_dacPowered = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Restore an M4B file that was temporarily renamed to .m4a for playback.
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
#pragma once
|
||||
|
||||
// =============================================================================
|
||||
// ES8311.h -- Minimal self-contained ES8311 codec init for T-Deck Pro MAX
|
||||
//
|
||||
// The MAX uses an ES8311 I2C-configured audio codec (the Pro V1.1 used a
|
||||
// PCM5102A "dumb" DAC that needed no config). The ES8311 will not produce
|
||||
// sound until its registers are configured over I2C. This driver does exactly
|
||||
// that, over Arduino Wire, with no esp_codec_dev / Cpp_Bus_Driver framework.
|
||||
//
|
||||
// The register sequence and clock-coefficient table are taken from, and
|
||||
// cross-verified between, Espressif's esp_codec_dev es8311.c and LilyGo's P4
|
||||
// Cpp_Bus_Driver Es8311 -- both agree on every clock register, so the sequence
|
||||
// here is not reverse-engineered.
|
||||
//
|
||||
// Configuration (fixed for Stage 1):
|
||||
// - ES8311 in SLAVE mode (ESP32 I2S is master: drives MCLK/BCLK/LRCK)
|
||||
// - use_mclk = TRUE: a real MCLK is driven on BOARD_I2S_MCLK (GPIO38) by the
|
||||
// I2S peripheral (APLL on, auto-derived 256 * fs). This mirrors the working
|
||||
// Ripple firmware, which drives the ES8311 with MCLK on this exact platform.
|
||||
// - 44100 Hz, 16-bit, DAC (playback) only; MCLK = 256 * sample_rate
|
||||
// - Register sequence transcribed from the proven esp_codec_dev es8311.c
|
||||
// (es8311_open + es8311_set_bits_per_sample + es8311_config_sample +
|
||||
// es8311_start) for the use_mclk == true path
|
||||
//
|
||||
// Routing/amplifier (XL9555: AUDIO_SEL low, AMPLIFIER high) is handled by the
|
||||
// board class (board.selectAudioES8311(); board.amplifierEnable()), NOT here.
|
||||
//
|
||||
// I2C: the ES8311 is at 0x18 on the shared Wire bus (SDA13/SCL14), already
|
||||
// initialised by board.begin(). This driver only uses Wire, never re-inits it.
|
||||
//
|
||||
// Guard: HAS_ES8311_AUDIO
|
||||
// =============================================================================
|
||||
|
||||
#ifdef HAS_ES8311_AUDIO
|
||||
|
||||
#ifndef MECK_ES8311_H
|
||||
#define MECK_ES8311_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#include "variant.h"
|
||||
|
||||
// ES8311 register addresses (subset used here)
|
||||
#define ES8311_REG00_RESET 0x00
|
||||
#define ES8311_REG01_CLK_MANAGER 0x01
|
||||
#define ES8311_REG02_CLK_MANAGER 0x02
|
||||
#define ES8311_REG03_CLK_MANAGER 0x03
|
||||
#define ES8311_REG04_CLK_MANAGER 0x04
|
||||
#define ES8311_REG05_CLK_MANAGER 0x05
|
||||
#define ES8311_REG06_CLK_MANAGER 0x06
|
||||
#define ES8311_REG07_CLK_MANAGER 0x07
|
||||
#define ES8311_REG08_CLK_MANAGER 0x08
|
||||
#define ES8311_REG09_SDPIN 0x09
|
||||
#define ES8311_REG0A_SDPOUT 0x0A
|
||||
#define ES8311_REG0B_SYSTEM 0x0B
|
||||
#define ES8311_REG0C_SYSTEM 0x0C
|
||||
#define ES8311_REG0D_SYSTEM 0x0D
|
||||
#define ES8311_REG0E_SYSTEM 0x0E
|
||||
#define ES8311_REG10_SYSTEM 0x10
|
||||
#define ES8311_REG11_SYSTEM 0x11
|
||||
#define ES8311_REG12_SYSTEM 0x12
|
||||
#define ES8311_REG13_SYSTEM 0x13
|
||||
#define ES8311_REG14_SYSTEM 0x14
|
||||
#define ES8311_REG15_ADC 0x15
|
||||
#define ES8311_REG16_ADC 0x16
|
||||
#define ES8311_REG17_ADC 0x17
|
||||
#define ES8311_REG1B_ADC 0x1B
|
||||
#define ES8311_REG1C_ADC 0x1C
|
||||
#define ES8311_REG31_DAC 0x31
|
||||
#define ES8311_REG32_DAC 0x32
|
||||
#define ES8311_REG37_DAC 0x37
|
||||
#define ES8311_REG44_GPIO 0x44
|
||||
#define ES8311_REG45_GP 0x45
|
||||
#define ES8311_REGFD_CHIPID1 0xFD
|
||||
|
||||
#ifndef I2C_ADDR_ES8311
|
||||
#define I2C_ADDR_ES8311 0x18
|
||||
#endif
|
||||
|
||||
// --- low-level I2C register access over Wire ---
|
||||
|
||||
static inline bool es8311_write(uint8_t reg, uint8_t val) {
|
||||
Wire.beginTransmission((uint8_t)I2C_ADDR_ES8311);
|
||||
Wire.write(reg);
|
||||
Wire.write(val);
|
||||
return Wire.endTransmission() == 0;
|
||||
}
|
||||
|
||||
static inline uint8_t es8311_read(uint8_t reg) {
|
||||
Wire.beginTransmission((uint8_t)I2C_ADDR_ES8311);
|
||||
Wire.write(reg);
|
||||
if (Wire.endTransmission(false) != 0) return 0;
|
||||
if (Wire.requestFrom((uint8_t)I2C_ADDR_ES8311, (uint8_t)1) != 1) return 0;
|
||||
return Wire.read();
|
||||
}
|
||||
|
||||
// Initialise the ES8311 for 44100 Hz, 16-bit, slave mode, MCLK = 256 * fs.
|
||||
// Returns true if the chip ID read back as 0x83 (ES8311 reports ID 0x8311
|
||||
// across REGFD/REGFE; REGFD high byte is 0x83).
|
||||
static inline bool es8311_init_44100_16bit() {
|
||||
// Chip presence / ID check (REGFD should read 0x83 on ES8311)
|
||||
uint8_t id = es8311_read(ES8311_REGFD_CHIPID1);
|
||||
Serial.printf("[ES8311] chip ID REGFD = 0x%02X (expect 0x83)\n", id);
|
||||
|
||||
// ---- open(): base register setup (from esp_codec_dev es8311_open) ----
|
||||
// GPIO REG44 written twice: ES8311 first I2C write can be unreliable.
|
||||
es8311_write(ES8311_REG44_GPIO, 0x08);
|
||||
es8311_write(ES8311_REG44_GPIO, 0x08);
|
||||
|
||||
es8311_write(ES8311_REG01_CLK_MANAGER, 0x30);
|
||||
es8311_write(ES8311_REG02_CLK_MANAGER, 0x00);
|
||||
es8311_write(ES8311_REG03_CLK_MANAGER, 0x10);
|
||||
es8311_write(ES8311_REG16_ADC, 0x24);
|
||||
es8311_write(ES8311_REG04_CLK_MANAGER, 0x10);
|
||||
es8311_write(ES8311_REG05_CLK_MANAGER, 0x00);
|
||||
es8311_write(ES8311_REG0B_SYSTEM, 0x00);
|
||||
es8311_write(ES8311_REG0C_SYSTEM, 0x00);
|
||||
es8311_write(ES8311_REG10_SYSTEM, 0x1F);
|
||||
es8311_write(ES8311_REG11_SYSTEM, 0x7F);
|
||||
es8311_write(ES8311_REG00_RESET, 0x80); // CSM power up
|
||||
|
||||
// Slave mode: REG00 bit6 = 0. (read-modify-write)
|
||||
{
|
||||
uint8_t regv = es8311_read(ES8311_REG00_RESET);
|
||||
regv &= 0xBF; // slave
|
||||
es8311_write(ES8311_REG00_RESET, regv);
|
||||
}
|
||||
|
||||
// Clock source for internal MCLK (REG01), transcribed from the proven
|
||||
// esp_codec_dev es8311.c es8311_open() for use_mclk == true:
|
||||
// regv = 0x3F; use_mclk true -> regv &= 0x7F; invert_mclk false -> regv &= ~0x40
|
||||
// => REG01 = 0x3F
|
||||
// The codec uses the externally supplied MCLK (driven on GPIO38 via APLL),
|
||||
// mirroring the working Ripple firmware on this platform.
|
||||
{
|
||||
uint8_t regv = 0x3F;
|
||||
regv &= 0x7F; // use_mclk = true
|
||||
regv &= ~0x40; // mclk not inverted
|
||||
es8311_write(ES8311_REG01_CLK_MANAGER, regv);
|
||||
}
|
||||
|
||||
// SCLK not inverted (REG06)
|
||||
{
|
||||
uint8_t regv = es8311_read(ES8311_REG06_CLK_MANAGER);
|
||||
regv &= ~0x20;
|
||||
es8311_write(ES8311_REG06_CLK_MANAGER, regv);
|
||||
}
|
||||
|
||||
es8311_write(ES8311_REG13_SYSTEM, 0x10);
|
||||
es8311_write(ES8311_REG1B_ADC, 0x0A);
|
||||
es8311_write(ES8311_REG1C_ADC, 0x6A);
|
||||
// no_dac_ref == false: set internal reference signal (ADCL + DACR) -> REG44 = 0x58.
|
||||
// (es8311.c writes 0x58 here for DAC playback; the earlier 0x08 writes were the
|
||||
// I2C-noise-immunity double-write.)
|
||||
es8311_write(ES8311_REG44_GPIO, 0x58);
|
||||
|
||||
// ---- config_sample(): clock dividers, transcribed from es8311_config_sample ----
|
||||
// For use_mclk == true the driver looks up the coeff row by
|
||||
// (sample_rate * mclk_div, sample_rate) with mclk_div = 256 default, i.e. the
|
||||
// {11289600, 44100} row: pre_div=1, pre_multi=1, adc_div=1, dac_div=1,
|
||||
// fs_mode=0, lrck_h=0x00, lrck_l=0xff, bclk_div=0x04, adc_osr=0x10, dac_osr=0x10.
|
||||
// pre_multi == 1 -> datmp = 0 (the use_mclk==false datmp=3 override does NOT
|
||||
// apply here). So REG02 = (pre_div-1)<<5 | 0<<3 = 0x00.
|
||||
{
|
||||
const uint8_t pre_div = 1, pre_multi_enc = 0; // datmp=0 (pre_multi=1, use_mclk=true)
|
||||
const uint8_t adc_div = 1, dac_div = 1, fs_mode = 0;
|
||||
const uint8_t lrck_h = 0x00, lrck_l = 0xFF, bclk_div = 0x04;
|
||||
const uint8_t adc_osr = 0x10, dac_osr = 0x10;
|
||||
|
||||
uint8_t regv = es8311_read(ES8311_REG02_CLK_MANAGER);
|
||||
regv &= 0x07;
|
||||
regv |= (pre_div - 1) << 5;
|
||||
regv |= pre_multi_enc << 3;
|
||||
es8311_write(ES8311_REG02_CLK_MANAGER, regv);
|
||||
|
||||
regv = (fs_mode << 6) | adc_osr;
|
||||
es8311_write(ES8311_REG03_CLK_MANAGER, regv);
|
||||
|
||||
es8311_write(ES8311_REG04_CLK_MANAGER, dac_osr);
|
||||
|
||||
regv = ((adc_div - 1) << 4) | (dac_div - 1);
|
||||
es8311_write(ES8311_REG05_CLK_MANAGER, regv);
|
||||
|
||||
regv = es8311_read(ES8311_REG06_CLK_MANAGER);
|
||||
regv &= 0xE0;
|
||||
if (bclk_div < 19) regv |= (bclk_div - 1);
|
||||
else regv |= bclk_div;
|
||||
es8311_write(ES8311_REG06_CLK_MANAGER, regv);
|
||||
|
||||
regv = es8311_read(ES8311_REG07_CLK_MANAGER);
|
||||
regv &= 0xC0;
|
||||
regv |= lrck_h;
|
||||
es8311_write(ES8311_REG07_CLK_MANAGER, regv);
|
||||
|
||||
es8311_write(ES8311_REG08_CLK_MANAGER, lrck_l);
|
||||
}
|
||||
|
||||
// ---- format + bits per sample: 16-bit, I2S (REG09 DAC SDP) ----
|
||||
// 16-bit -> SDP word length field = 0x0C in bits [4:2]; I2S format = 0x00.
|
||||
{
|
||||
uint8_t dac_iface = es8311_read(ES8311_REG09_SDPIN);
|
||||
dac_iface &= 0xE3; // clear word-length field bits [4:2] only
|
||||
dac_iface |= (0x03 << 2); // 0x0C = 16-bit (bits [4:2] = 011)
|
||||
es8311_write(ES8311_REG09_SDPIN, dac_iface);
|
||||
}
|
||||
|
||||
// ---- start(): power up DAC path (from es8311_start, DAC mode) ----
|
||||
{
|
||||
uint8_t regv = 0x80; // CSM on
|
||||
regv &= 0xBF; // slave
|
||||
es8311_write(ES8311_REG00_RESET, regv);
|
||||
|
||||
// REG01 clock source (from es8311_start): regv=0x3F; use_mclk true -> &=0x7F;
|
||||
// invert_mclk false -> &=~0x40 => 0x3F. Re-applied here exactly as the proven
|
||||
// start sequence does, so it stays consistent with the open() write.
|
||||
{
|
||||
uint8_t r01 = 0x3F;
|
||||
r01 &= 0x7F; // use_mclk = true
|
||||
r01 &= ~0x40; // not inverted
|
||||
es8311_write(ES8311_REG01_CLK_MANAGER, r01);
|
||||
}
|
||||
|
||||
// DAC interface power on (REG09 bit6 = 0)
|
||||
uint8_t dac_iface = es8311_read(ES8311_REG09_SDPIN);
|
||||
dac_iface &= ~(1 << 6);
|
||||
es8311_write(ES8311_REG09_SDPIN, dac_iface);
|
||||
|
||||
es8311_write(ES8311_REG17_ADC, 0xBF);
|
||||
es8311_write(ES8311_REG0E_SYSTEM, 0x02);
|
||||
es8311_write(ES8311_REG12_SYSTEM, 0x00); // enable DAC
|
||||
es8311_write(ES8311_REG14_SYSTEM, 0x1A);
|
||||
es8311_write(ES8311_REG0D_SYSTEM, 0x01);
|
||||
es8311_write(ES8311_REG15_ADC, 0x40);
|
||||
es8311_write(ES8311_REG37_DAC, 0x08);
|
||||
es8311_write(ES8311_REG45_GP, 0x00);
|
||||
}
|
||||
|
||||
// Unmute DAC and set a sane default volume.
|
||||
es8311_write(ES8311_REG31_DAC, 0x00); // unmute
|
||||
es8311_write(ES8311_REG32_DAC, 0xBF); // ~0 dB (191 = 0 dB)
|
||||
|
||||
// DIAG: read back key registers to confirm the power-up/format writes landed.
|
||||
// REG00 (CSM/reset), REG01 (clock src), REG02 (clk div), REG09 (SDP/DAC iface),
|
||||
// REG0D (power up/down), REG12 (DAC enable), REG31 (DAC mute), REG32 (DAC vol).
|
||||
Serial.printf("[ES8311] readback R00=%02X R01=%02X R02=%02X R09=%02X R0D=%02X R12=%02X R31=%02X R32=%02X\n",
|
||||
es8311_read(ES8311_REG00_RESET),
|
||||
es8311_read(ES8311_REG01_CLK_MANAGER),
|
||||
es8311_read(ES8311_REG02_CLK_MANAGER),
|
||||
es8311_read(ES8311_REG09_SDPIN),
|
||||
es8311_read(ES8311_REG0D_SYSTEM),
|
||||
es8311_read(ES8311_REG12_SYSTEM),
|
||||
es8311_read(ES8311_REG31_DAC),
|
||||
es8311_read(ES8311_REG32_DAC));
|
||||
|
||||
return id == 0x83;
|
||||
}
|
||||
|
||||
// DAC volume, 0..255 (0 = mute-ish, 191 = 0 dB, 255 = +32 dB).
|
||||
static inline void es8311_set_dac_volume(uint8_t vol) {
|
||||
es8311_write(ES8311_REG32_DAC, vol);
|
||||
}
|
||||
|
||||
// Hard mute / unmute the DAC.
|
||||
static inline void es8311_set_mute(bool mute) {
|
||||
uint8_t regv = es8311_read(ES8311_REG31_DAC);
|
||||
regv &= 0x9F;
|
||||
es8311_write(ES8311_REG31_DAC, mute ? (regv | 0x60) : regv);
|
||||
}
|
||||
|
||||
#endif // MECK_ES8311_H
|
||||
#endif // HAS_ES8311_AUDIO
|
||||
@@ -218,15 +218,19 @@ private:
|
||||
|
||||
// DAC power control (same as AudiobookPlayerScreen)
|
||||
void enableDAC() {
|
||||
#ifndef HAS_ES8311_AUDIO
|
||||
pinMode(41, OUTPUT);
|
||||
digitalWrite(41, HIGH);
|
||||
if (!_dacPowered) delay(50);
|
||||
_dacPowered = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void disableDAC() {
|
||||
#ifndef HAS_ES8311_AUDIO
|
||||
digitalWrite(41, LOW);
|
||||
_dacPowered = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user