xref: /btstack/port/esp32/components/btstack/es8388.c (revision 02eb0186642e198e424594090e8b69d439591c44)
1 #include <string.h>
2 #include "esp_log.h"
3 #include "driver/gpio.h"
4 #include "es8388.h"
5 
6 #define ES8388_TAG "ES8388"
7 
8 #define ES_ASSERT(a, format, b, ...) \
9     if ((a) != 0) { \
10         ESP_LOGE(ES8388_TAG, format, ##__VA_ARGS__); \
11         return b;\
12     }
13 
14 #define LOG_8388(fmt, ...)   ESP_LOGW(ES8388_TAG, fmt, ##__VA_ARGS__)
15 
es_write_reg(uint8_t slave_addr,uint8_t reg_addr,uint8_t data)16 static int es_write_reg(uint8_t slave_addr, uint8_t reg_addr, uint8_t data)
17 {
18     int res = 0;
19     i2c_cmd_handle_t cmd = i2c_cmd_link_create();
20     res |= i2c_master_start(cmd);
21     res |= i2c_master_write_byte(cmd, slave_addr, 1 /*ACK_CHECK_EN*/);
22     res |= i2c_master_write_byte(cmd, reg_addr, 1 /*ACK_CHECK_EN*/);
23     res |= i2c_master_write_byte(cmd, data, 1 /*ACK_CHECK_EN*/);
24     res |= i2c_master_stop(cmd);
25     res |= i2c_master_cmd_begin(0, cmd, 1000 / portTICK_PERIOD_MS);
26     i2c_cmd_link_delete(cmd);
27     ES_ASSERT(res, "es8388_write_reg error", -1);
28     return res;
29 }
30 
es8388_read_reg(uint8_t reg_addr,uint8_t * pdata)31 static int es8388_read_reg(uint8_t reg_addr, uint8_t *pdata)
32 {
33     uint8_t data;
34     int res = 0;
35     i2c_cmd_handle_t cmd = i2c_cmd_link_create();
36 
37     res |= i2c_master_start(cmd);
38     res |= i2c_master_write_byte(cmd, ES8388_ADDR, 1 /*ACK_CHECK_EN*/);
39     res |= i2c_master_write_byte(cmd, reg_addr, 1 /*ACK_CHECK_EN*/);
40     res |= i2c_master_stop(cmd);
41     res |= i2c_master_cmd_begin(0, cmd, 1000 / portTICK_PERIOD_MS);
42     i2c_cmd_link_delete(cmd);
43 
44     cmd = i2c_cmd_link_create();
45     res |= i2c_master_start(cmd);
46     res |= i2c_master_write_byte(cmd, ES8388_ADDR | 0x01, 1 /*ACK_CHECK_EN*/);
47     res |= i2c_master_read_byte(cmd, &data, 0x01/*NACK_VAL*/);
48     res |= i2c_master_stop(cmd);
49     res |= i2c_master_cmd_begin(0, cmd, 1000 / portTICK_PERIOD_MS);
50     i2c_cmd_link_delete(cmd);
51 
52     ES_ASSERT(res, "es8388_read_reg error", -1);
53     *pdata = data;
54     return res;
55 }
56 
57 
i2c_init(i2c_config_t * conf,int port)58 static int i2c_init(i2c_config_t *conf, int port)
59 {
60     int res;
61 
62     res = i2c_param_config(port, conf);
63     res |= i2c_driver_install(port, conf->mode, 0, 0, 0);
64     ES_ASSERT(res, "I2cInit error", -1);
65     return res;
66 }
67 
68 
es8388_read_all_regs()69 void es8388_read_all_regs()
70 {
71     for (int i = 0; i < 50; i++) {
72         uint8_t reg = 0;
73         es8388_read_reg(i, &reg);
74         printf("%x: %x\n", i, reg);
75     }
76 }
77 
es8388_write_reg(uint8_t regAdd,uint8_t data)78 int es8388_write_reg(uint8_t regAdd, uint8_t data)
79 {
80     return es_write_reg(ES8388_ADDR, regAdd, data);
81 }
82 
83 
es8388_set_adc_dac_volume(int mode,int volume,int dot)84 static int es8388_set_adc_dac_volume(int mode, int volume, int dot)
85 {
86     int res = 0;
87     if ( volume < -96 || volume > 0 ) {
88         LOG_8388("Warning: volume < -96! or > 0!\n");
89         if (volume < -96)
90             volume = -96;
91         else
92             volume = 0;
93     }
94     dot = (dot >= 5 ? 1 : 0);
95     volume = (-volume << 1) + dot;
96     if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC) {
97         res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL8, volume);
98         res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL9, volume);  //ADC Right Volume=0db
99     }
100     if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC) {
101         res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL5, volume);
102         res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL4, volume);
103     }
104     return res;
105 }
106 
es8388_start(es_codec_module_t mode)107 int es8388_start(es_codec_module_t mode)
108 {
109     int res = 0;
110     uint8_t prev_data = 0, data = 0;
111     es8388_read_reg(ES8388_DACCONTROL21, &prev_data);
112     if (mode == ES_MODULE_LINE) {
113         res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL16, 0x09); // 0x00 audio on LIN1&RIN1,  0x09 LIN2&RIN2 by pass enable
114         res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL17, 0x50); // left DAC to left mixer enable  and  LIN signal to left mixer enable 0db  : bupass enable
115         res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL20, 0x50); // right DAC to right mixer enable  and  LIN signal to right mixer enable 0db : bupass enable
116         res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0xC0); //enable adc
117     } else {
118         res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0x80);   //enable dac
119     }
120     es8388_read_reg(ES8388_DACCONTROL21, &data);
121     if (prev_data != data) {
122         res |= es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0xF0);   //start state machine
123         // res |= es8388_write_reg(ES8388_ADDR, ES8388_CONTROL1, 0x16);
124         // res |= es8388_write_reg(ES8388_ADDR, ES8388_CONTROL2, 0x50);
125         res |= es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0x00);   //start state machine
126     }
127     if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC || mode == ES_MODULE_LINE)
128         res |= es_write_reg(ES8388_ADDR, ES8388_ADCPOWER, 0x00);   //power up adc and line in
129     //res |= es8388_set_adc_dac_volume(ES_MODULE_ADC, 0, 0);      // 0db
130     if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC || mode == ES_MODULE_LINE) {
131         res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, 0x3c);   //power up dac and line out
132         res |= es8388_set_mute(false);
133         //res |= es8388_set_adc_dac_volume(ES_MODULE_DAC, 0, 0);      // 0db
134     }
135 
136     return res;
137 }
138 
es8388_stop(es_codec_module_t mode)139 int es8388_stop(es_codec_module_t mode)
140 {
141     int res = 0;
142     if (mode == ES_MODULE_LINE) {
143         res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0x80); //enable dac
144         res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL16, 0x00); // 0x00 audio on LIN1&RIN1,  0x09 LIN2&RIN2
145         res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL17, 0x90); // only left DAC to left mixer enable 0db
146         res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL20, 0x90); // only right DAC to right mixer enable 0db
147         return res;
148     }
149     if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC) {
150         res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, 0x00);
151         res |= es8388_set_mute(true);
152         //res |= es8388_set_adc_dac_volume(ES_MODULE_DAC, -96, 5);      // 0db
153         //res |= es8388_write_reg(ES8388_ADDR, ES8388_DACPOWER, 0xC0);  //power down dac and line out
154     }
155     if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC) {
156         //res |= es8388_set_adc_dac_volume(ES_MODULE_ADC, -96, 5);      // 0db
157         res |= es_write_reg(ES8388_ADDR, ES8388_ADCPOWER, 0xFF);  //power down adc and line in
158     }
159     if (mode == ES_MODULE_ADC_DAC) {
160         res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0x9C);  //disable mclk
161 //        res |= es8388_write_reg(ES8388_ADDR, ES8388_CONTROL1, 0x00);
162 //        res |= es8388_write_reg(ES8388_ADDR, ES8388_CONTROL2, 0x58);
163 //        res |= es8388_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0xF3);  //stop state machine
164     }
165 
166     return res;
167 }
168 
169 
es8388_i2s_config_clock(es_codec_i2s_clock_t cfg)170 int es8388_i2s_config_clock(es_codec_i2s_clock_t cfg)
171 {
172     int res = 0;
173 
174     res |= es_write_reg(ES8388_ADDR, ES8388_MASTERMODE, cfg.sclk_div);
175     res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL5, cfg.lclk_div);  //ADCFsMode,singel SPEED,RATIO=256
176     res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL2, cfg.lclk_div);  //ADCFsMode,singel SPEED,RATIO=256
177 
178     return res;
179 }
180 
es8388_uninit()181 void es8388_uninit()
182 {
183     es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0xFF);  //reset and stop es8388
184     // i2c_driver_delete(cfg->i2c_port_num);
185 }
186 
es8388_init(es8388_config_t * cfg)187 int es8388_init(es8388_config_t *cfg)
188 {
189     int res = 0;
190     res = i2c_init(&cfg->i2c_cfg, cfg->i2c_port_num); // ESP32 in master mode
191     res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL3, 0x04);  // 0x04 mute/0x00 unmute&ramp;DAC unmute and  disabled digital volume control soft ramp
192     /* Chip Control and Power Management */
193     res |= es_write_reg(ES8388_ADDR, ES8388_CONTROL2, 0x50);
194     res |= es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0x00); //normal all and power up all
195     res |= es_write_reg(ES8388_ADDR, ES8388_MASTERMODE, cfg->es_mode); //CODEC IN I2S SLAVE MODE
196 
197     /* dac */
198     res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, 0xC0);  //disable DAC and disable Lout/Rout/1/2
199     res |= es_write_reg(ES8388_ADDR, ES8388_CONTROL1, 0x12);  //Enfr=0,Play&Record Mode,(0x17-both of mic&paly)
200 //    res |= es8388_write_reg(ES8388_ADDR, ES8388_CONTROL2, 0);  //LPVrefBuf=0,Pdn_ana=0
201     res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL1, 0x18);//1a 0x18:16bit iis , 0x00:24
202     res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL2, 0x02);  //DACFsMode,SINGLE SPEED; DACFsRatio,256
203     res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL16, 0x00); // 0x00 audio on LIN1&RIN1,  0x09 LIN2&RIN2
204     res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL17, 0x90); // only left DAC to left mixer enable 0db
205     res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL20, 0x90); // only right DAC to right mixer enable 0db
206     res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0x80); //set internal ADC and DAC use the same LRCK clock, ADC LRCK as internal LRCK
207     res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL23, 0x00);   //vroi=0
208     res |= es8388_set_adc_dac_volume(ES_MODULE_DAC, 0, 0);          // 0db
209     res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, cfg->dac_output);  //0x3c Enable DAC and Enable Lout/Rout/1/2
210     /* adc */
211     res |= es_write_reg(ES8388_ADDR, ES8388_ADCPOWER, 0xFF);
212     res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL1, 0x88); //0x88 MIC PGA =24DB
213     res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL2, cfg->adc_input);  //0x00 LINSEL & RINSEL, LIN1/RIN1 as ADC Input; DSSEL,use one DS Reg11; DSR, LINPUT1-RINPUT1
214     res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL3, 0x02);
215     res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL4, 0x0c); //0d 0x0c I2S-16BIT, LEFT ADC DATA = LIN1 , RIGHT ADC DATA =RIN1
216     res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL5, 0x02);  //ADCFsMode,singel SPEED,RATIO=256
217     //ALC for Microphone
218     res |= es8388_set_adc_dac_volume(ES_MODULE_ADC, 0, 0);      // 0db
219     res |= es_write_reg(ES8388_ADDR, ES8388_ADCPOWER, 0x09); //Power up ADC, Enable LIN&RIN, Power down MICBIAS, set int1lp to low power mode
220 
221     es8388_pa_power(true);
222     ESP_LOGD(ES8388_TAG, "init, out:%02x, in:%02x -> %d", cfg->dac_output, cfg->adc_input, res);
223     return res;
224 }
225 
es8388_config_fmt(es_codec_module_t mode,es_codec_i2s_fmt_t fmt)226 int es8388_config_fmt(es_codec_module_t mode, es_codec_i2s_fmt_t fmt)
227 {
228     int res = 0;
229     uint8_t reg = 0;
230     if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC) {
231         res = es8388_read_reg(ES8388_ADCCONTROL4, &reg);
232         reg = reg & 0xfc;
233         res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL4, reg | fmt);
234     }
235     if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC) {
236         res = es8388_read_reg(ES8388_DACCONTROL1, &reg);
237         reg = reg & 0xf9;
238         res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL1, reg | (fmt << 1));
239     }
240     return res;
241 }
242 
es8388_set_volume(int volume)243 int es8388_set_volume(int volume)
244 {
245     int res;
246     if (volume < 0)
247         volume = 0;
248     else if (volume > 100)
249         volume = 100;
250     volume /= 3;
251     res = es_write_reg(ES8388_ADDR, ES8388_DACCONTROL24, volume);
252     res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL25, volume);  //ADC Right Volume=0db
253     res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL26, 0);
254     res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL27, 0);
255     return res;
256 }
257 
es8388_get_volume(int * volume)258 int es8388_get_volume(int *volume)
259 {
260     int res;
261     uint8_t reg = 0;
262     res = es8388_read_reg(ES8388_DACCONTROL24, &reg);
263     if (res == ESP_FAIL) {
264         *volume = 0;
265     } else {
266         *volume = reg;
267         *volume *= 3;
268         if (*volume == 99)
269             *volume = 100;
270     }
271     return res;
272 }
273 
es8388_set_bits_per_sample(es_codec_module_t mode,es_codec_bits_len_t bitPerSample)274 int es8388_set_bits_per_sample(es_codec_module_t mode, es_codec_bits_len_t bitPerSample)
275 {
276     int res = 0;
277     uint8_t reg = 0;
278     int bits = (int)bitPerSample;
279 
280     if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC) {
281         res = es8388_read_reg(ES8388_ADCCONTROL4, &reg);
282         reg = reg & 0xe3;
283         res |=  es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL4, reg | (bits << 2));
284     }
285     if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC) {
286         res = es8388_read_reg(ES8388_DACCONTROL1, &reg);
287         reg = reg & 0xc7;
288         res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL1, reg | (bits << 3));
289     }
290     return res;
291 }
292 
es8388_set_mute(int enable)293 int es8388_set_mute(int enable)
294 {
295     int res;
296     uint8_t reg = 0;
297     res = es8388_read_reg(ES8388_DACCONTROL3, &reg);
298     reg = reg & 0xFB;
299     res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL3, reg | (((int)enable) << 2));
300     return res;
301 }
302 
es8388_get_mute(int * mute)303 int es8388_get_mute(int *mute)
304 {
305     int res = -1;
306     uint8_t reg = 0;
307     res = es8388_read_reg(ES8388_DACCONTROL3, &reg);
308     if (res == ESP_OK) {
309         reg = (reg & 0x04) >> 2;
310     }
311     *mute = reg;
312     return res;
313 }
314 
es8388_set_dac_ouput(es_codec_dac_output_t output)315 int es8388_set_dac_ouput(es_codec_dac_output_t output)
316 {
317     int res;
318     uint8_t reg = 0;
319     res = es8388_read_reg(ES8388_DACPOWER, &reg);
320     reg = reg & 0xc3;
321     res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, reg | output);
322     return res;
323 }
324 
es8388_set_adc_input(es_codec_adc_input_t input)325 int es8388_set_adc_input(es_codec_adc_input_t input)
326 {
327     int res;
328     uint8_t reg = 0;
329     res = es8388_read_reg(ES8388_ADCCONTROL2, &reg);
330     reg = reg & 0x0f;
331     res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL2, reg | input);
332     return res;
333 }
334 
es8388_set_mic_gain(es_codec_mic_gain_t gain)335 int es8388_set_mic_gain(es_codec_mic_gain_t gain)
336 {
337     if (gain == MIC_GAIN_MIN){
338         gain = MIC_GAIN_0DB;
339     }
340     if (gain == MIC_GAIN_MAX){
341         gain = MIC_GAIN_24DB;
342     }
343     int res, gain_n;
344     gain_n = (int)gain / 3;
345     res = es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL1, (gain_n << 4) | gain_n); //MIC PGA
346     return res;
347 }
348 
es8388_pa_power(bool enable)349 void es8388_pa_power(bool enable)
350 {
351     gpio_config_t  io_conf;
352     memset(&io_conf, 0, sizeof(io_conf));
353     // v4.4 - io_conf.intr_type = GPIO_PIN_INTR_DISABLE == 0
354     // v5   - io_conf.intr_type = GPIO_INTR_DISABLE     == 0
355     io_conf.mode = GPIO_MODE_OUTPUT;
356     io_conf.pin_bit_mask = 1UL << GPIO_NUM_21;
357     io_conf.pull_down_en = 0;
358     io_conf.pull_up_en = 0;
359     gpio_config(&io_conf);
360     if (enable) {
361         gpio_set_level(GPIO_NUM_21, 1);
362     } else {
363         gpio_set_level(GPIO_NUM_21, 0);
364     }
365 }
366