ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
es7210.cpp
Go to the documentation of this file.
1#include "es7210.h"
2#include "es7210_const.h"
3#include "esphome/core/hal.h"
4#include "esphome/core/log.h"
5#include <cinttypes>
6
7namespace esphome::es7210 {
8
9ESPHOME_LOG_TAG(TAG, "es7210");
10
11static const size_t MCLK_DIV_FRE = 256;
12
13// Mark the component as failed; use only in setup
14#define ES7210_ERROR_FAILED(func) \
15 if (!(func)) { \
16 this->mark_failed(LOG_STR("Failed to initialize")); \
17 return; \
18 }
19
20// Return false; use outside of setup
21#define ES7210_ERROR_CHECK(func) \
22 if (!(func)) { \
23 return false; \
24 }
25
27 ESP_LOGCONFIG(TAG,
28 "ES7210 audio ADC:\n"
29 " Bits Per Sample: %" PRIu8 "\n"
30 " Sample Rate: %" PRIu32 "\n"
31 " Channel Gains: %.1f dB, %.1f dB, %.1f dB, %.1f dB",
32 this->bits_per_sample_, this->sample_rate_, this->channel_gains_[0], this->channel_gains_[1],
33 this->channel_gains_[2], this->channel_gains_[3]);
34}
35
37 // Software reset
38 ES7210_ERROR_FAILED(this->write_byte(ES7210_RESET_REG00, 0xff));
39 ES7210_ERROR_FAILED(this->write_byte(ES7210_RESET_REG00, 0x32));
40 ES7210_ERROR_FAILED(this->write_byte(ES7210_CLOCK_OFF_REG01, 0x3f));
41
42 // Set initialization time when device powers up
43 ES7210_ERROR_FAILED(this->write_byte(ES7210_TIME_CONTROL0_REG09, 0x30));
44 ES7210_ERROR_FAILED(this->write_byte(ES7210_TIME_CONTROL1_REG0A, 0x30));
45
46 // Configure HFP for all ADC channels
47 ES7210_ERROR_FAILED(this->write_byte(ES7210_ADC12_HPF2_REG23, 0x2a));
48 ES7210_ERROR_FAILED(this->write_byte(ES7210_ADC12_HPF1_REG22, 0x0a));
49 ES7210_ERROR_FAILED(this->write_byte(ES7210_ADC34_HPF2_REG20, 0x0a));
50 ES7210_ERROR_FAILED(this->write_byte(ES7210_ADC34_HPF1_REG21, 0x2a));
51
52 // Secondary I2S mode settings
53 ES7210_ERROR_FAILED(this->es7210_update_reg_bit_(ES7210_MODE_CONFIG_REG08, 0x01, 0x00));
54
55 // Configure analog power
56 ES7210_ERROR_FAILED(this->write_byte(ES7210_ANALOG_REG40, 0xC3));
57
58 // Set mic bias
59 ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC12_BIAS_REG41, 0x70));
60 ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC34_BIAS_REG42, 0x70));
61
62 // Configure I2S settings, sample rate, and microphone gains
63 ES7210_ERROR_FAILED(this->configure_i2s_format_());
64 ES7210_ERROR_FAILED(this->configure_sample_rate_());
65 ES7210_ERROR_FAILED(this->configure_mic_gain_());
66
67 // Power on mics 1 through 4
68 ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC1_POWER_REG47, 0x08));
69 ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC2_POWER_REG48, 0x08));
70 ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC3_POWER_REG49, 0x08));
71 ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC4_POWER_REG4A, 0x08));
72
73 // Power down DLL
74 ES7210_ERROR_FAILED(this->write_byte(ES7210_POWER_DOWN_REG06, 0x04));
75
76 // Power on MIC1-4 bias & ADC1-4 & PGA1-4 Power
77 ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC12_POWER_REG4B, 0x0F));
78 ES7210_ERROR_FAILED(this->write_byte(ES7210_MIC34_POWER_REG4C, 0x0F));
79
80 // Enable device
81 ES7210_ERROR_FAILED(this->write_byte(ES7210_RESET_REG00, 0x71));
82 ES7210_ERROR_FAILED(this->write_byte(ES7210_RESET_REG00, 0x41));
83
84 this->setup_complete_ = true;
85}
86
87bool ES7210::set_mic_gain(float mic_gain) {
88 this->channel_gains_.fill(clamp<float>(mic_gain, ES7210_MIC_GAIN_MIN, ES7210_MIC_GAIN_MAX));
89 if (this->setup_complete_) {
90 return this->configure_mic_gain_();
91 }
92 return true;
93}
94
95bool ES7210::set_channel_gain(uint8_t channel, float gain) {
96 if (channel >= this->channel_gains_.size())
97 return false;
98 this->channel_gains_[channel] = clamp<float>(gain, ES7210_MIC_GAIN_MIN, ES7210_MIC_GAIN_MAX);
99 if (this->setup_complete_) {
100 return this->configure_mic_gain_();
101 }
102 return true;
103}
104
106 uint32_t mclk_fre = this->sample_rate_ * MCLK_DIV_FRE;
107 int coeff = -1;
108
109 for (size_t i = 0; i < (sizeof(ES7210_COEFFICIENTS) / sizeof(ES7210_COEFFICIENTS[0])); ++i) {
110 if (ES7210_COEFFICIENTS[i].lrclk == this->sample_rate_ && ES7210_COEFFICIENTS[i].mclk == mclk_fre)
111 coeff = static_cast<int>(i);
112 }
113
114 if (coeff >= 0) {
115 // Set adc_div & doubler & dll
116 uint8_t regv;
117 ES7210_ERROR_CHECK(this->read_byte(ES7210_MAINCLK_REG02, &regv));
118 regv = regv & 0x00;
119 regv |= ES7210_COEFFICIENTS[coeff].adc_div;
120 regv |= ES7210_COEFFICIENTS[coeff].doubler << 6;
121 regv |= ES7210_COEFFICIENTS[coeff].dll << 7;
122
123 ES7210_ERROR_CHECK(this->write_byte(ES7210_MAINCLK_REG02, regv));
124
125 // Set osr
126 regv = ES7210_COEFFICIENTS[coeff].osr;
127 ES7210_ERROR_CHECK(this->write_byte(ES7210_OSR_REG07, regv));
128 // Set lrck
129 regv = ES7210_COEFFICIENTS[coeff].lrck_h;
130 ES7210_ERROR_CHECK(this->write_byte(ES7210_LRCK_DIVH_REG04, regv));
131 regv = ES7210_COEFFICIENTS[coeff].lrck_l;
132 ES7210_ERROR_CHECK(this->write_byte(ES7210_LRCK_DIVL_REG05, regv));
133 } else {
134 // Invalid sample frequency
135 ESP_LOGE(TAG, "Invalid sample rate");
136 return false;
137 }
138
139 return true;
140}
141
143 for (uint8_t i = 0; i < 4; ++i) {
144 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC1_GAIN_REG43 + i, 0x10, 0x00));
145 }
146 ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC12_POWER_REG4B, 0xff));
147 ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC34_POWER_REG4C, 0xff));
148
149 // Configure mic 1
150 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00));
151 ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC12_POWER_REG4B, 0x00));
152 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC1_GAIN_REG43, 0x10, 0x10));
153 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC1_GAIN_REG43, 0x0f,
154 this->es7210_gain_reg_value_(this->channel_gains_[0])));
155
156 // Configure mic 2
157 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00));
158 ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC12_POWER_REG4B, 0x00));
159 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC2_GAIN_REG44, 0x10, 0x10));
160 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC2_GAIN_REG44, 0x0f,
161 this->es7210_gain_reg_value_(this->channel_gains_[1])));
162
163 // Configure mic 3
164 // MIC3 uses the ADC3/4 and MIC3/4 clock domains (bits 2 and 4), not the MIC1/2 domains.
165 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x15, 0x00));
166 ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC34_POWER_REG4C, 0x00));
167 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC3_GAIN_REG45, 0x10, 0x10));
168 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC3_GAIN_REG45, 0x0f,
169 this->es7210_gain_reg_value_(this->channel_gains_[2])));
170
171 // Configure mic 4
172 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_CLOCK_OFF_REG01, 0x15, 0x00));
173 ES7210_ERROR_CHECK(this->write_byte(ES7210_MIC34_POWER_REG4C, 0x00));
174 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC4_GAIN_REG46, 0x10, 0x10));
175 ES7210_ERROR_CHECK(this->es7210_update_reg_bit_(ES7210_MIC4_GAIN_REG46, 0x0f,
176 this->es7210_gain_reg_value_(this->channel_gains_[3])));
177
178 return true;
179}
180
181uint8_t ES7210::es7210_gain_reg_value_(float mic_gain) {
182 // reg: 12 - 34.5dB, 13 - 36dB, 14 - 37.5dB
183 mic_gain += 0.5f;
184 if (mic_gain <= 33.0f) {
185 return (uint8_t) (mic_gain / 3);
186 }
187 if (mic_gain < 36.0f) {
188 return 12;
189 }
190 if (mic_gain < 37.0f) {
191 return 13;
192 }
193 return 14;
194}
195
197 // Configure bits per sample
198 uint8_t reg_val = 0;
199 switch (this->bits_per_sample_) {
201 reg_val = 0x60;
202 break;
204 reg_val = 0x40;
205 break;
207 reg_val = 0x20;
208 break;
210 reg_val = 0x00;
211 break;
213 reg_val = 0x80;
214 break;
215 default:
216 return false;
217 }
218 ES7210_ERROR_CHECK(this->write_byte(ES7210_SDP_INTERFACE1_REG11, reg_val));
219
220 if (this->enable_tdm_) {
221 ES7210_ERROR_CHECK(this->write_byte(ES7210_SDP_INTERFACE2_REG12, 0x02));
222 } else {
223 // Microphones 1 and 2 output on SDOUT1, microphones 3 and 4 output on SDOUT2
224 ES7210_ERROR_CHECK(this->write_byte(ES7210_SDP_INTERFACE2_REG12, 0x00));
225 }
226
227 return true;
228}
229
230bool ES7210::es7210_update_reg_bit_(uint8_t reg_addr, uint8_t update_bits, uint8_t data) {
231 uint8_t regv;
232 ES7210_ERROR_CHECK(this->read_byte(reg_addr, &regv));
233 regv = (regv & (~update_bits)) | (update_bits & data);
234 return this->write_byte(reg_addr, regv);
235}
236
237} // namespace esphome::es7210
uint8_t es7210_gain_reg_value_(float mic_gain)
Convert floating point mic gain value to register value.
Definition es7210.cpp:181
float mic_gain() override
Returns the MIC1 gain; other channels may have different gains.
Definition es7210.h:40
bool es7210_update_reg_bit_(uint8_t reg_addr, uint8_t update_bits, uint8_t data)
Updates an I2C registry address by modifying the current state.
Definition es7210.cpp:230
void setup() override
Definition es7210.cpp:36
void dump_config() override
Definition es7210.cpp:26
uint32_t sample_rate_
Definition es7210.h:63
bool set_mic_gain(float mic_gain) override
Sets all four channel gains, replacing any configured per-channel gains.
Definition es7210.cpp:87
std::array< float, 4 > channel_gains_
Definition es7210.h:61
bool set_channel_gain(uint8_t channel, float gain)
Sets a zero-based channel gain; returns false for an invalid channel or an I2C failure.
Definition es7210.cpp:95
ES7210BitsPerSample bits_per_sample_
Definition es7210.h:62
bool write_byte(uint8_t a_register, uint8_t data) const
Definition i2c.h:312
bool read_byte(uint8_t a_register, uint8_t *data)
Definition i2c.h:272
AlsGain501 gain
ESPHOME_LOG_TAG(TAG, "es7210")
@ ES7210_BITS_PER_SAMPLE_20
Definition es7210.h:16
@ ES7210_BITS_PER_SAMPLE_18
Definition es7210.h:15
@ ES7210_BITS_PER_SAMPLE_16
Definition es7210.h:14
@ ES7210_BITS_PER_SAMPLE_32
Definition es7210.h:18
@ ES7210_BITS_PER_SAMPLE_24
Definition es7210.h:17
static void uint32_t