ESPHome 2026.2.1
Loading...
Searching...
No Matches
es8156.cpp
Go to the documentation of this file.
1#include "es8156.h"
2#include "es8156_const.h"
3#include "esphome/core/hal.h"
4#include "esphome/core/log.h"
5#include <cinttypes>
6
7namespace esphome {
8namespace es8156 {
9
10static const char *const TAG = "es8156";
11
12// Mark the component as failed; use only in setup
13#define ES8156_ERROR_FAILED(func) \
14 if (!(func)) { \
15 this->mark_failed(); \
16 return; \
17 }
18
20 // REG02 MODE CONFIG 1: Enable software mode for I2C control of volume/mute
21 // Bit 2: SOFT_MODE_SEL=1 (software mode enabled)
22 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG02_SCLK_MODE, 0x04));
23
24 // Analog system configuration (active-low power down bits, active-high enables)
25 // REG20 ANALOG SYSTEM: Configure analog signal path
26 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG20_ANALOG_SYS1, 0x2A));
27
28 // REG21 ANALOG SYSTEM: VSEL=0x1C (bias level ~120%), normal VREF ramp speed
29 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG21_ANALOG_SYS2, 0x3C));
30
31 // REG22 ANALOG SYSTEM: Line out mode (HPSW=0), OUT_MUTE=0 (not muted)
32 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG22_ANALOG_SYS3, 0x00));
33
34 // REG24 ANALOG SYSTEM: Low power mode for VREFBUF, HPCOM, DACVRP; DAC normal power
35 // Bits 2:0 = 0x07: LPVREFBUF=1, LPHPCOM=1, LPDACVRP=1, LPDAC=0
36 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG24_ANALOG_LP, 0x07));
37
38 // REG23 ANALOG SYSTEM: Lowest bias (IBIAS_SW=0), VMIDLVL=VDDA/2, normal impedance
39 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG23_ANALOG_SYS4, 0x00));
40
41 // Timing and interface configuration
42 // REG0A/0B TIME CONTROL: Fast state machine transitions
43 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG0A_TIME_CONTROL1, 0x01));
44 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG0B_TIME_CONTROL2, 0x01));
45
46 // REG11 SDP INTERFACE CONFIG: Default I2S format (24-bit, I2S mode)
47 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG11_DAC_SDP, 0x00));
48
49 // REG19 EQ CONTROL 1: EQ disabled (EQ_ON=0), EQ_BAND_NUM=2
50 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG19_EQ_CONTROL1, 0x20));
51
52 // REG0D P2S CONTROL: Parallel-to-serial converter settings
53 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG0D_P2S_CONTROL, 0x14));
54
55 // REG09 MISC CONTROL 2: Default settings
56 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG09_MISC_CONTROL2, 0x00));
57
58 // REG18 MISC CONTROL 3: Stereo channel routing, no inversion
59 // Bits 5:4 CHN_CROSS: 0=L→L/R→R, 1=L to both, 2=R to both, 3=swap L/R
60 // Bits 3:2: LCH_INV/RCH_INV channel inversion
61 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG18_MISC_CONTROL3, 0x00));
62
63 // REG08 CLOCK OFF: Enable all internal clocks (0x3F = all clock gates open)
64 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG08_CLOCK_ON_OFF, 0x3F));
65
66 // REG00 RESET CONTROL: Reset sequence
67 // First: RST_DIG=1 (assert digital reset)
68 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG00_RESET, 0x02));
69 // Then: CSM_ON=1 (enable chip state machine), RST_DIG=1
70 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG00_RESET, 0x03));
71
72 // REG25 ANALOG SYSTEM: Power up analog blocks
73 // VMIDSEL=2 (normal VMID operation), PDN_ANA=0, ENREFR=0, ENHPCOM=0
74 // PDN_DACVREFGEN=0, PDN_VREFBUF=0, PDN_DAC=0 (all enabled)
75 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG25_ANALOG_SYS5, 0x20));
76}
77
79 ESP_LOGCONFIG(TAG, "ES8156 Audio Codec:");
80
81 if (this->is_failed()) {
82 ESP_LOGCONFIG(TAG, " Failed to initialize");
83 return;
84 }
85}
86
87bool ES8156::set_volume(float volume) {
88 volume = clamp(volume, 0.0f, 1.0f);
89 uint8_t reg = remap<uint8_t, float>(volume, 0.0f, 1.0f, 0, 255);
90 ESP_LOGV(TAG, "Setting ES8156_REG14_VOLUME_CONTROL to %u (volume: %f)", reg, volume);
91 return this->write_byte(ES8156_REG14_VOLUME_CONTROL, reg);
92}
93
95 uint8_t reg;
96 this->read_byte(ES8156_REG14_VOLUME_CONTROL, &reg);
97 return remap<float, uint8_t>(reg, 0, 255, 0.0f, 1.0f);
98}
99
100bool ES8156::set_mute_state_(bool mute_state) {
101 uint8_t reg13;
102
103 this->is_muted_ = mute_state;
104
105 if (!this->read_byte(ES8156_REG13_DAC_MUTE, &reg13)) {
106 return false;
107 }
108
109 ESP_LOGV(TAG, "Read ES8156_REG13_DAC_MUTE: %u", reg13);
110
111 if (mute_state) {
112 reg13 |= BIT(1) | BIT(2);
113 } else {
114 reg13 &= ~(BIT(1) | BIT(2));
115 }
116
117 ESP_LOGV(TAG, "Setting ES8156_REG13_DAC_MUTE to %u (muted: %s)", reg13, YESNO(mute_state));
118 return this->write_byte(ES8156_REG13_DAC_MUTE, reg13);
119}
120
121} // namespace es8156
122} // namespace esphome
bool is_failed() const
float volume() override
Gets the current volume out from the DAC.
Definition es8156.cpp:94
void dump_config() override
Definition es8156.cpp:78
void setup() override
Definition es8156.cpp:19
bool set_mute_state_(bool mute_state)
Mutes or unmutes the DAC audio out.
Definition es8156.cpp:100
bool set_volume(float volume) override
Writes the volume out to the DAC.
Definition es8156.cpp:87
bool write_byte(uint8_t a_register, uint8_t data) const
Definition i2c.h:266
bool read_byte(uint8_t a_register, uint8_t *data)
Definition i2c.h:241
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
Definition i2c.h:153
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
T remap(U value, U min, U max, T min_out, T max_out)
Remap value from the range (min, max) to (min_out, max_out).
Definition helpers.h:443