2019-10-31 15:47:00 +01:00

360 lines
13 KiB
C

#include <string.h>
#include "esp_log.h"
#include "driver/gpio.h"
#include "es8388.h"
#define ES8388_TAG "ES8388"
#define ES_ASSERT(a, format, b, ...) \
if ((a) != 0) { \
ESP_LOGE(ES8388_TAG, format, ##__VA_ARGS__); \
return b;\
}
#define LOG_8388(fmt, ...) ESP_LOGW(ES8388_TAG, fmt, ##__VA_ARGS__)
static int es_write_reg(uint8_t slave_addr, uint8_t reg_addr, uint8_t data)
{
int res = 0;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
res |= i2c_master_start(cmd);
res |= i2c_master_write_byte(cmd, slave_addr, 1 /*ACK_CHECK_EN*/);
res |= i2c_master_write_byte(cmd, reg_addr, 1 /*ACK_CHECK_EN*/);
res |= i2c_master_write_byte(cmd, data, 1 /*ACK_CHECK_EN*/);
res |= i2c_master_stop(cmd);
res |= i2c_master_cmd_begin(0, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
ES_ASSERT(res, "es8388_write_reg error", -1);
return res;
}
static int es8388_read_reg(uint8_t reg_addr, uint8_t *pdata)
{
uint8_t data;
int res = 0;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
res |= i2c_master_start(cmd);
res |= i2c_master_write_byte(cmd, ES8388_ADDR, 1 /*ACK_CHECK_EN*/);
res |= i2c_master_write_byte(cmd, reg_addr, 1 /*ACK_CHECK_EN*/);
res |= i2c_master_stop(cmd);
res |= i2c_master_cmd_begin(0, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
cmd = i2c_cmd_link_create();
res |= i2c_master_start(cmd);
res |= i2c_master_write_byte(cmd, ES8388_ADDR | 0x01, 1 /*ACK_CHECK_EN*/);
res |= i2c_master_read_byte(cmd, &data, 0x01/*NACK_VAL*/);
res |= i2c_master_stop(cmd);
res |= i2c_master_cmd_begin(0, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
ES_ASSERT(res, "es8388_read_reg error", -1);
*pdata = data;
return res;
}
static int i2c_init(i2c_config_t *conf, int port)
{
int res;
res = i2c_param_config(port, conf);
res |= i2c_driver_install(port, conf->mode, 0, 0, 0);
ES_ASSERT(res, "I2cInit error", -1);
return res;
}
void es8388_read_all_regs()
{
for (int i = 0; i < 50; i++) {
uint8_t reg = 0;
es8388_read_reg(i, &reg);
ets_printf("%x: %x\n", i, reg);
}
}
int es8388_write_reg(uint8_t regAdd, uint8_t data)
{
return es_write_reg(ES8388_ADDR, regAdd, data);
}
static int es8388_set_adc_dac_volume(int mode, int volume, int dot)
{
int res = 0;
if ( volume < -96 || volume > 0 ) {
LOG_8388("Warning: volume < -96! or > 0!\n");
if (volume < -96)
volume = -96;
else
volume = 0;
}
dot = (dot >= 5 ? 1 : 0);
volume = (-volume << 1) + dot;
if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC) {
res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL8, volume);
res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL9, volume); //ADC Right Volume=0db
}
if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC) {
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL5, volume);
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL4, volume);
}
return res;
}
int es8388_start(es_codec_module_t mode)
{
int res = 0;
uint8_t prev_data = 0, data = 0;
es8388_read_reg(ES8388_DACCONTROL21, &prev_data);
if (mode == ES_MODULE_LINE) {
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL16, 0x09); // 0x00 audio on LIN1&RIN1, 0x09 LIN2&RIN2 by pass enable
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
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
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0xC0); //enable adc
} else {
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0x80); //enable dac
}
es8388_read_reg(ES8388_DACCONTROL21, &data);
if (prev_data != data) {
res |= es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0xF0); //start state machine
// res |= es8388_write_reg(ES8388_ADDR, ES8388_CONTROL1, 0x16);
// res |= es8388_write_reg(ES8388_ADDR, ES8388_CONTROL2, 0x50);
res |= es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0x00); //start state machine
}
if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC || mode == ES_MODULE_LINE)
res |= es_write_reg(ES8388_ADDR, ES8388_ADCPOWER, 0x00); //power up adc and line in
//res |= es8388_set_adc_dac_volume(ES_MODULE_ADC, 0, 0); // 0db
if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC || mode == ES_MODULE_LINE) {
res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, 0x3c); //power up dac and line out
res |= es8388_set_mute(false);
//res |= es8388_set_adc_dac_volume(ES_MODULE_DAC, 0, 0); // 0db
}
return res;
}
int es8388_stop(es_codec_module_t mode)
{
int res = 0;
if (mode == ES_MODULE_LINE) {
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0x80); //enable dac
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL16, 0x00); // 0x00 audio on LIN1&RIN1, 0x09 LIN2&RIN2
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL17, 0x90); // only left DAC to left mixer enable 0db
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL20, 0x90); // only right DAC to right mixer enable 0db
return res;
}
if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC) {
res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, 0x00);
res |= es8388_set_mute(true);
//res |= es8388_set_adc_dac_volume(ES_MODULE_DAC, -96, 5); // 0db
//res |= es8388_write_reg(ES8388_ADDR, ES8388_DACPOWER, 0xC0); //power down dac and line out
}
if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC) {
//res |= es8388_set_adc_dac_volume(ES_MODULE_ADC, -96, 5); // 0db
res |= es_write_reg(ES8388_ADDR, ES8388_ADCPOWER, 0xFF); //power down adc and line in
}
if (mode == ES_MODULE_ADC_DAC) {
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0x9C); //disable mclk
// res |= es8388_write_reg(ES8388_ADDR, ES8388_CONTROL1, 0x00);
// res |= es8388_write_reg(ES8388_ADDR, ES8388_CONTROL2, 0x58);
// res |= es8388_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0xF3); //stop state machine
}
return res;
}
int es8388_i2s_config_clock(es_codec_i2s_clock_t cfg)
{
int res = 0;
res |= es_write_reg(ES8388_ADDR, ES8388_MASTERMODE, cfg.sclk_div);
res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL5, cfg.lclk_div); //ADCFsMode,singel SPEED,RATIO=256
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL2, cfg.lclk_div); //ADCFsMode,singel SPEED,RATIO=256
return res;
}
void es8388_uninit()
{
es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0xFF); //reset and stop es8388
// i2c_driver_delete(cfg->i2c_port_num);
}
int es8388_init(es8388_config_t *cfg)
{
int res = 0;
res = i2c_init(&cfg->i2c_cfg, cfg->i2c_port_num); // ESP32 in master mode
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL3, 0x04); // 0x04 mute/0x00 unmute&ramp;DAC unmute and disabled digital volume control soft ramp
/* Chip Control and Power Management */
res |= es_write_reg(ES8388_ADDR, ES8388_CONTROL2, 0x50);
res |= es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER, 0x00); //normal all and power up all
res |= es_write_reg(ES8388_ADDR, ES8388_MASTERMODE, cfg->es_mode); //CODEC IN I2S SLAVE MODE
/* dac */
res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, 0xC0); //disable DAC and disable Lout/Rout/1/2
res |= es_write_reg(ES8388_ADDR, ES8388_CONTROL1, 0x12); //Enfr=0,Play&Record Mode,(0x17-both of mic&paly)
// res |= es8388_write_reg(ES8388_ADDR, ES8388_CONTROL2, 0); //LPVrefBuf=0,Pdn_ana=0
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL1, 0x18);//1a 0x18:16bit iis , 0x00:24
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL2, 0x02); //DACFsMode,SINGLE SPEED; DACFsRatio,256
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL16, 0x00); // 0x00 audio on LIN1&RIN1, 0x09 LIN2&RIN2
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL17, 0x90); // only left DAC to left mixer enable 0db
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL20, 0x90); // only right DAC to right mixer enable 0db
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21, 0x80); //set internal ADC and DAC use the same LRCK clock, ADC LRCK as internal LRCK
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL23, 0x00); //vroi=0
res |= es8388_set_adc_dac_volume(ES_MODULE_DAC, 0, 0); // 0db
res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, cfg->dac_output); //0x3c Enable DAC and Enable Lout/Rout/1/2
/* adc */
res |= es_write_reg(ES8388_ADDR, ES8388_ADCPOWER, 0xFF);
res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL1, 0x88); //0x88 MIC PGA =24DB
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
res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL3, 0x02);
res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL4, 0x0c); //0d 0x0c I2S-16BIT, LEFT ADC DATA = LIN1 , RIGHT ADC DATA =RIN1
res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL5, 0x02); //ADCFsMode,singel SPEED,RATIO=256
//ALC for Microphone
res |= es8388_set_adc_dac_volume(ES_MODULE_ADC, 0, 0); // 0db
res |= es_write_reg(ES8388_ADDR, ES8388_ADCPOWER, 0x09); //Power up ADC, Enable LIN&RIN, Power down MICBIAS, set int1lp to low power mode
es8388_pa_power(true);
ESP_LOGE(ES8388_TAG, "init, out:%02x, in:%02x", cfg->dac_output, cfg->adc_input);
ESP_LOGE(ES8388_TAG, "res = %d", res);
return res;
}
int es8388_config_fmt(es_codec_module_t mode, es_codec_i2s_fmt_t fmt)
{
int res = 0;
uint8_t reg = 0;
if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC) {
res = es8388_read_reg(ES8388_ADCCONTROL4, &reg);
reg = reg & 0xfc;
res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL4, reg | fmt);
}
if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC) {
res = es8388_read_reg(ES8388_DACCONTROL1, &reg);
reg = reg & 0xf9;
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL1, reg | (fmt << 1));
}
return res;
}
int es8388_set_volume(int volume)
{
int res;
if (volume < 0)
volume = 0;
else if (volume > 100)
volume = 100;
volume /= 3;
res = es_write_reg(ES8388_ADDR, ES8388_DACCONTROL24, volume);
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL25, volume); //ADC Right Volume=0db
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL26, 0);
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL27, 0);
return res;
}
int es8388_get_volume(int *volume)
{
int res;
uint8_t reg = 0;
res = es8388_read_reg(ES8388_DACCONTROL24, &reg);
if (res == ESP_FAIL) {
*volume = 0;
} else {
*volume = reg;
*volume *= 3;
if (*volume == 99)
*volume = 100;
}
return res;
}
int es8388_set_bits_per_sample(es_codec_module_t mode, es_codec_bits_len_t bitPerSample)
{
int res = 0;
uint8_t reg = 0;
int bits = (int)bitPerSample;
if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC) {
res = es8388_read_reg(ES8388_ADCCONTROL4, &reg);
reg = reg & 0xe3;
res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL4, reg | (bits << 2));
}
if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC) {
res = es8388_read_reg(ES8388_DACCONTROL1, &reg);
reg = reg & 0xc7;
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL1, reg | (bits << 3));
}
return res;
}
int es8388_set_mute(int enable)
{
int res;
uint8_t reg = 0;
res = es8388_read_reg(ES8388_DACCONTROL3, &reg);
reg = reg & 0xFB;
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL3, reg | (((int)enable) << 2));
return res;
}
int es8388_get_mute(int *mute)
{
int res = -1;
uint8_t reg = 0;
res = es8388_read_reg(ES8388_DACCONTROL3, &reg);
if (res == ESP_OK) {
reg = (reg & 0x04) >> 2;
}
*mute = reg;
return res;
}
int es8388_set_dac_ouput(int output)
{
int res;
uint8_t reg = 0;
res = es8388_read_reg(ES8388_DACPOWER, &reg);
reg = reg & 0xc3;
res |= es_write_reg(ES8388_ADDR, ES8388_DACPOWER, reg | output);
return res;
}
int es8388_set_adc_input(es_codec_adc_input_t input)
{
int res;
uint8_t reg = 0;
res = es8388_read_reg(ES8388_ADCCONTROL2, &reg);
reg = reg & 0x0f;
res |= es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL2, reg | input);
return res;
}
int es8388_set_mic_gain(es_codec_mic_gain_t gain)
{
int res, gain_n;
gain_n = (int)gain / 3;
res = es_write_reg(ES8388_ADDR, ES8388_ADCCONTROL1, gain_n); //MIC PGA
return res;
}
void es8388_pa_power(bool enable)
{
gpio_config_t io_conf;
memset(&io_conf, 0, sizeof(io_conf));
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = 1UL << GPIO_NUM_21;
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
if (enable) {
gpio_set_level(GPIO_NUM_21, 1);
} else {
gpio_set_level(GPIO_NUM_21, 0);
}
}