diff --git a/lib/lib_audio/es7210/library.json b/lib/lib_audio/es7210/library.json new file mode 100644 index 000000000..27e99c11a --- /dev/null +++ b/lib/lib_audio/es7210/library.json @@ -0,0 +1,7 @@ +{ + "name": "ES7210", + "description": "Audio codec", + "keywords": "ESP8266, ESP32, MP3, AAC, WAV, MOD, FLAC, RTTTL, MIDI, I2S, DAC, Delta-Sigma, TTS", + "version": "1.0.0", + "frameworks": "Arduino" +} diff --git a/lib/lib_audio/es7210/library.properties b/lib/lib_audio/es7210/library.properties new file mode 100644 index 000000000..ffa00ca45 --- /dev/null +++ b/lib/lib_audio/es7210/library.properties @@ -0,0 +1,9 @@ +name=ES7210 +version=1.0 +author= +maintainer= +sentence=Audio fcodec for ESP32 +paragraph= +category=Signal Output +url= +architectures=esp32 diff --git a/lib/lib_audio/es7210/src/es7210.cpp b/lib/lib_audio/es7210/src/es7210.cpp new file mode 100644 index 000000000..3bf680308 --- /dev/null +++ b/lib/lib_audio/es7210/src/es7210.cpp @@ -0,0 +1,549 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2021 + * + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifdef ESP32 + +#include +#include +#include "esp_log.h" +#include "es7210.h" + + +#define I2S_DSP_MODE_A 0 +#define MCLK_DIV_FRE 256 + + +#define ES7210_MCLK_SOURCE FROM_CLOCK_DOUBLE_PIN /* In master mode, 0 : MCLK from pad 1 : MCLK from clock doubler */ +#define FROM_PAD_PIN 0 +#define FROM_CLOCK_DOUBLE_PIN 1 + + +static TwoWire *es7210wire; +static es7210_gain_value_t gain; + +/* + * Clock coefficient structer + */ +struct _coeff_div { + uint32_t mclk; /* mclk frequency */ + uint32_t lrck; /* lrck */ + uint8_t ss_ds; + uint8_t adc_div; /* adcclk divider */ + uint8_t dll; /* dll_bypass */ + uint8_t doubler; /* doubler enable */ + uint8_t osr; /* adc osr */ + uint8_t mclk_src; /* select mclk source */ + uint32_t lrck_h; /* The high 4 bits of lrck */ + uint32_t lrck_l; /* The low 8 bits of lrck */ +}; + +static const char *TAG = "ES7210"; + +static es7210_input_mics_t mic_select = (es7210_input_mics_t)(ES7210_INPUT_MIC1 | ES7210_INPUT_MIC2 | ES7210_INPUT_MIC3 | ES7210_INPUT_MIC4); + +/* Codec hifi mclk clock divider coefficients + * MEMBER REG + * mclk: 0x03 + * lrck: standard + * ss_ds: -- + * adc_div: 0x02 + * dll: 0x06 + * doubler: 0x02 + * osr: 0x07 + * mclk_src: 0x03 + * lrckh: 0x04 + * lrckl: 0x05 +*/ +static const struct _coeff_div coeff_div[] = { + //mclk lrck ss_ds adc_div dll doubler osr mclk_src lrckh lrckl + /* 8k */ + {12288000, 8000 , 0x00, 0x03, 0x01, 0x00, 0x20, 0x00, 0x06, 0x00}, + {16384000, 8000 , 0x00, 0x04, 0x01, 0x00, 0x20, 0x00, 0x08, 0x00}, + {19200000, 8000 , 0x00, 0x1e, 0x00, 0x01, 0x28, 0x00, 0x09, 0x60}, + {4096000, 8000 , 0x00, 0x01, 0x01, 0x00, 0x20, 0x00, 0x02, 0x00}, + + /* 11.025k */ + {11289600, 11025, 0x00, 0x02, 0x01, 0x00, 0x20, 0x00, 0x01, 0x00}, + + /* 12k */ + {12288000, 12000, 0x00, 0x02, 0x01, 0x00, 0x20, 0x00, 0x04, 0x00}, + {19200000, 12000, 0x00, 0x14, 0x00, 0x01, 0x28, 0x00, 0x06, 0x40}, + + /* 16k */ + {4096000, 16000, 0x00, 0x01, 0x01, 0x01, 0x20, 0x00, 0x01, 0x00}, + {19200000, 16000, 0x00, 0x0a, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x80}, + {16384000, 16000, 0x00, 0x02, 0x01, 0x00, 0x20, 0x00, 0x04, 0x00}, + {12288000, 16000, 0x00, 0x03, 0x01, 0x01, 0x20, 0x00, 0x03, 0x00}, + + /* 22.05k */ + {11289600, 22050, 0x00, 0x01, 0x01, 0x00, 0x20, 0x00, 0x02, 0x00}, + + /* 24k */ + {12288000, 24000, 0x00, 0x01, 0x01, 0x00, 0x20, 0x00, 0x02, 0x00}, + {19200000, 24000, 0x00, 0x0a, 0x00, 0x01, 0x28, 0x00, 0x03, 0x20}, + + /* 32k */ + {12288000, 32000, 0x00, 0x03, 0x00, 0x00, 0x20, 0x00, 0x01, 0x80}, + {16384000, 32000, 0x00, 0x01, 0x01, 0x00, 0x20, 0x00, 0x02, 0x00}, + {19200000, 32000, 0x00, 0x05, 0x00, 0x00, 0x1e, 0x00, 0x02, 0x58}, + + /* 44.1k */ + {11289600, 44100, 0x00, 0x01, 0x01, 0x01, 0x20, 0x00, 0x01, 0x00}, + + /* 48k */ + {12288000, 48000, 0x00, 0x01, 0x01, 0x01, 0x20, 0x00, 0x01, 0x00}, + {19200000, 48000, 0x00, 0x05, 0x00, 0x01, 0x28, 0x00, 0x01, 0x90}, + + /* 64k */ + {16384000, 64000, 0x01, 0x01, 0x01, 0x00, 0x20, 0x00, 0x01, 0x00}, + {19200000, 64000, 0x00, 0x05, 0x00, 0x01, 0x1e, 0x00, 0x01, 0x2c}, + + /* 88.2k */ + {11289600, 88200, 0x01, 0x01, 0x01, 0x01, 0x20, 0x00, 0x00, 0x80}, + + /* 96k */ + {12288000, 96000, 0x01, 0x01, 0x01, 0x01, 0x20, 0x00, 0x00, 0x80}, + {19200000, 96000, 0x01, 0x05, 0x00, 0x01, 0x28, 0x00, 0x00, 0xc8}, +}; + +static esp_err_t es7210_write_reg(uint8_t reg_addr, uint8_t data) +{ + + es7210wire->beginTransmission(ES7210_ADDR); + es7210wire->write(reg_addr); + es7210wire->write(data); + return es7210wire->endTransmission(); + +} + +static esp_err_t es7210_update_reg_bit(uint8_t reg_addr, uint8_t update_bits, uint8_t data) +{ + uint8_t regv; + regv = es7210_read_reg(reg_addr); + regv = (regv & (~update_bits)) | (update_bits & data); + return es7210_write_reg(reg_addr, regv); +} + +static int get_coeff(uint32_t mclk, uint32_t lrck) +{ + for (int i = 0; i < (sizeof(coeff_div) / sizeof(coeff_div[0])); i++) { + if (coeff_div[i].lrck == lrck && coeff_div[i].mclk == mclk) + return i; + } + return -1; +} + +int8_t get_es7210_mclk_src(void) +{ + return ES7210_MCLK_SOURCE; +} + +int es7210_read_reg(uint8_t reg_addr) +{ + uint8_t data; + es7210wire->beginTransmission(ES7210_ADDR); + es7210wire->write(reg_addr); + es7210wire->endTransmission(false); + es7210wire->requestFrom(ES7210_ADDR, (size_t)1); + data = es7210wire->read(); + return (int)data; +} + +esp_err_t es7210_config_sample(audio_hal_iface_samples_t sample) +{ + uint8_t regv; + int coeff; + int sample_fre = 0; + int mclk_fre = 0; + esp_err_t ret = ESP_OK; + switch (sample) { + case AUDIO_HAL_08K_SAMPLES: + sample_fre = 8000; + break; + case AUDIO_HAL_11K_SAMPLES: + sample_fre = 11025; + break; + case AUDIO_HAL_16K_SAMPLES: + sample_fre = 16000; + break; + case AUDIO_HAL_22K_SAMPLES: + sample_fre = 22050; + break; + case AUDIO_HAL_24K_SAMPLES: + sample_fre = 24000; + break; + case AUDIO_HAL_32K_SAMPLES: + sample_fre = 32000; + break; + case AUDIO_HAL_44K_SAMPLES: + sample_fre = 44100; + break; + case AUDIO_HAL_48K_SAMPLES: + sample_fre = 48000; + break; + default: + ESP_LOGE(TAG, "Unable to configure sample rate %dHz", sample_fre); + break; + } + mclk_fre = sample_fre * MCLK_DIV_FRE; + coeff = get_coeff(mclk_fre, sample_fre); + if (coeff < 0) { + ESP_LOGE(TAG, "Unable to configure sample rate %dHz with %dHz MCLK", sample_fre, mclk_fre); + return ESP_FAIL; + } + /* Set clock parammeters */ + if (coeff >= 0) { + /* Set adc_div & doubler & dll */ + regv = es7210_read_reg(ES7210_MAINCLK_REG02) & 0x00; + regv |= coeff_div[coeff].adc_div; + regv |= coeff_div[coeff].doubler << 6; + regv |= coeff_div[coeff].dll << 7; + ret |= es7210_write_reg(ES7210_MAINCLK_REG02, regv); + /* Set osr */ + regv = coeff_div[coeff].osr; + ret |= es7210_write_reg(ES7210_OSR_REG07, regv); + /* Set lrck */ + regv = coeff_div[coeff].lrck_h; + ret |= es7210_write_reg(ES7210_LRCK_DIVH_REG04, regv); + regv = coeff_div[coeff].lrck_l; + ret |= es7210_write_reg(ES7210_LRCK_DIVL_REG05, regv); + } + return ret; +} + +esp_err_t es7210_mic_select(es7210_input_mics_t mic) +{ + esp_err_t ret = ESP_OK; + mic_select = mic; + if (mic_select & (ES7210_INPUT_MIC1 | ES7210_INPUT_MIC2 | ES7210_INPUT_MIC3 | ES7210_INPUT_MIC4)) { + for (int i = 0; i < 4; i++) { + ret |= es7210_update_reg_bit(ES7210_MIC1_GAIN_REG43 + i, 0x10, 0x00); + } + ret |= es7210_write_reg(ES7210_MIC12_POWER_REG4B, 0xff); + ret |= es7210_write_reg(ES7210_MIC34_POWER_REG4C, 0xff); + if (mic_select & ES7210_INPUT_MIC1) { + ESP_LOGI(TAG, "Enable ES7210_INPUT_MIC1"); + ret |= es7210_update_reg_bit(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00); + ret |= es7210_write_reg(ES7210_MIC12_POWER_REG4B, 0x00); + ret |= es7210_update_reg_bit(ES7210_MIC1_GAIN_REG43, 0x10, 0x10); + } + if (mic_select & ES7210_INPUT_MIC2) { + ESP_LOGI(TAG, "Enable ES7210_INPUT_MIC2"); + ret |= es7210_update_reg_bit(ES7210_CLOCK_OFF_REG01, 0x0b, 0x00); + ret |= es7210_write_reg(ES7210_MIC12_POWER_REG4B, 0x00); + ret |= es7210_update_reg_bit(ES7210_MIC2_GAIN_REG44, 0x10, 0x10); + } + if (mic_select & ES7210_INPUT_MIC3) { + ESP_LOGI(TAG, "Enable ES7210_INPUT_MIC3"); + ret |= es7210_update_reg_bit(ES7210_CLOCK_OFF_REG01, 0x15, 0x00); + ret |= es7210_write_reg(ES7210_MIC34_POWER_REG4C, 0x00); + ret |= es7210_update_reg_bit(ES7210_MIC3_GAIN_REG45, 0x10, 0x10); + } + if (mic_select & ES7210_INPUT_MIC4) { + ESP_LOGI(TAG, "Enable ES7210_INPUT_MIC4"); + ret |= es7210_update_reg_bit(ES7210_CLOCK_OFF_REG01, 0x15, 0x00); + ret |= es7210_write_reg(ES7210_MIC34_POWER_REG4C, 0x00); + ret |= es7210_update_reg_bit(ES7210_MIC4_GAIN_REG46, 0x10, 0x10); + } + } else { + ESP_LOGE(TAG, "Microphone selection error"); + return ESP_FAIL; + } + return ret; +} + +esp_err_t es7210_adc_init(TwoWire *tw, audio_hal_codec_config_t *codec_cfg) +{ + esp_err_t ret = ESP_OK; + + es7210wire = tw; + + ret |= es7210_write_reg(ES7210_RESET_REG00, 0xff); + ret |= es7210_write_reg(ES7210_RESET_REG00, 0x41); + ret |= es7210_write_reg(ES7210_CLOCK_OFF_REG01, 0x1f); + ret |= es7210_write_reg(ES7210_TIME_CONTROL0_REG09, 0x30); /* Set chip state cycle */ + ret |= es7210_write_reg(ES7210_TIME_CONTROL1_REG0A, 0x30); /* Set power on state cycle */ + // ret |= es7210_write_reg(ES7210_ADC12_HPF2_REG23, 0x2a); /* Quick setup */ + // ret |= es7210_write_reg(ES7210_ADC12_HPF1_REG22, 0x0a); + // ret |= es7210_write_reg(ES7210_ADC34_HPF2_REG20, 0x0a); + // ret |= es7210_write_reg(ES7210_ADC34_HPF1_REG21, 0x2a); + /* Set master/slave audio interface */ + audio_hal_codec_i2s_iface_t *i2s_cfg = & (codec_cfg->i2s_iface); + switch (i2s_cfg->mode) { + case AUDIO_HAL_MODE_MASTER: /* MASTER MODE */ + ESP_LOGI(TAG, "ES7210 in Master mode"); + // ret |= es7210_update_reg_bit(ES7210_MODE_CONFIG_REG08, 0x01, 0x01); + ret |= es7210_write_reg(ES7210_MODE_CONFIG_REG08, 0x20); + /* Select clock source for internal mclk */ + switch (get_es7210_mclk_src()) { + case FROM_PAD_PIN: + ret |= es7210_update_reg_bit(ES7210_MASTER_CLK_REG03, 0x80, 0x00); + break; + case FROM_CLOCK_DOUBLE_PIN: + ret |= es7210_update_reg_bit(ES7210_MASTER_CLK_REG03, 0x80, 0x80); + break; + default: + ret |= es7210_update_reg_bit(ES7210_MASTER_CLK_REG03, 0x80, 0x00); + break; + } + break; + case AUDIO_HAL_MODE_SLAVE: /* SLAVE MODE */ + ESP_LOGI(TAG, "ES7210 in Slave mode"); + break; + default: + break; + } + ret |= es7210_write_reg(ES7210_ANALOG_REG40, 0xC3); /* Select power off analog, vdda = 3.3V, close vx20ff, VMID select 5KΩ start */ + ret |= es7210_write_reg(ES7210_MIC12_BIAS_REG41, 0x70); /* Select 2.87v */ + ret |= es7210_write_reg(ES7210_MIC34_BIAS_REG42, 0x70); /* Select 2.87v */ + ret |= es7210_write_reg(ES7210_OSR_REG07, 0x20); + ret |= es7210_write_reg(ES7210_MAINCLK_REG02, 0xc1); /* Set the frequency division coefficient and use dll except clock doubler, and need to set 0xc1 to clear the state */ + ret |= es7210_config_sample(i2s_cfg->samples); + ret |= es7210_mic_select(mic_select); + ret |= es7210_adc_set_gain_all(GAIN_0DB); + return ESP_OK; +} + +esp_err_t es7210_adc_deinit() +{ + return ESP_OK; +} + +esp_err_t es7210_config_fmt(audio_hal_iface_format_t fmt) +{ + esp_err_t ret = ESP_OK; + uint8_t adc_iface = 0; + adc_iface = es7210_read_reg(ES7210_SDP_INTERFACE1_REG11); + adc_iface &= 0xfc; + switch (fmt) { + case AUDIO_HAL_I2S_NORMAL: + ESP_LOGD(TAG, "ES7210 in I2S Format"); + adc_iface |= 0x00; + break; + case AUDIO_HAL_I2S_LEFT: + case AUDIO_HAL_I2S_RIGHT: + ESP_LOGD(TAG, "ES7210 in LJ Format"); + adc_iface |= 0x01; + break; + case AUDIO_HAL_I2S_DSP: + if (I2S_DSP_MODE_A) { + ESP_LOGD(TAG, "ES7210 in DSP-A Format"); + adc_iface |= 0x03; + } else { + ESP_LOGD(TAG, "ES7210 in DSP-B Format"); + adc_iface |= 0x13; + } + break; + default: + adc_iface &= 0xfc; + break; + } + ret |= es7210_write_reg(ES7210_SDP_INTERFACE1_REG11, adc_iface); + /* Force ADC1/2 output to SDOUT1 and ADC3/4 output to SDOUT2 */ + ret |= es7210_write_reg(ES7210_SDP_INTERFACE2_REG12, 0x00); + return ret; +} + +esp_err_t es7210_set_bits(audio_hal_iface_bits_t bits) +{ + esp_err_t ret = ESP_OK; + uint8_t adc_iface = 0; + adc_iface = es7210_read_reg(ES7210_SDP_INTERFACE1_REG11); + adc_iface &= 0x1f; + switch (bits) { + case AUDIO_HAL_BIT_LENGTH_16BITS: + adc_iface |= 0x60; + break; + case AUDIO_HAL_BIT_LENGTH_24BITS: + adc_iface |= 0x00; + break; + case AUDIO_HAL_BIT_LENGTH_32BITS: + adc_iface |= 0x80; + break; + default: + adc_iface |= 0x60; + break; + } + ret |= es7210_write_reg(ES7210_SDP_INTERFACE1_REG11, adc_iface); + return ret; +} + +esp_err_t es7210_adc_config_i2s(audio_hal_codec_mode_t mode, audio_hal_codec_i2s_iface_t *iface) +{ + esp_err_t ret = ESP_OK; + ret |= es7210_set_bits(iface->bits); + ret |= es7210_config_fmt(iface->fmt); + ret |= es7210_config_sample(iface->samples); + return ret; +} + +esp_err_t es7210_start(uint8_t clock_reg_value) +{ + esp_err_t ret = ESP_OK; + ret |= es7210_write_reg(ES7210_CLOCK_OFF_REG01, clock_reg_value); + ret |= es7210_write_reg(ES7210_POWER_DOWN_REG06, 0x00); + // ret |= es7210_write_reg(ES7210_ANALOG_REG40, 0x40); + ret |= es7210_write_reg(ES7210_MIC1_POWER_REG47, 0x00); + ret |= es7210_write_reg(ES7210_MIC2_POWER_REG48, 0x00); + ret |= es7210_write_reg(ES7210_MIC3_POWER_REG49, 0x00); + ret |= es7210_write_reg(ES7210_MIC4_POWER_REG4A, 0x00); + ret |= es7210_mic_select(mic_select); + return ret; +} + +esp_err_t es7210_stop(void) +{ + esp_err_t ret = ESP_OK; + ret |= es7210_write_reg(ES7210_MIC1_POWER_REG47, 0xff); + ret |= es7210_write_reg(ES7210_MIC2_POWER_REG48, 0xff); + ret |= es7210_write_reg(ES7210_MIC3_POWER_REG49, 0xff); + ret |= es7210_write_reg(ES7210_MIC4_POWER_REG4A, 0xff); + ret |= es7210_write_reg(ES7210_MIC12_POWER_REG4B,0xff); + ret |= es7210_write_reg(ES7210_MIC34_POWER_REG4C, 0xff); + // ret |= es7210_write_reg(ES7210_ANALOG_REG40, 0xc0); + ret |= es7210_write_reg(ES7210_CLOCK_OFF_REG01, 0x7f); + ret |= es7210_write_reg(ES7210_POWER_DOWN_REG06, 0x07); + return ret; +} + +esp_err_t es7210_adc_ctrl_state(audio_hal_codec_mode_t mode, audio_hal_ctrl_t ctrl_state) +{ + static uint8_t regv; + esp_err_t ret = ESP_OK; + // ESP_LOGW(TAG, "ES7210 only supports ADC mode"); + ret = es7210_read_reg(ES7210_CLOCK_OFF_REG01); + if ((ret != 0x7f) && (ret != 0xff)) { + regv = es7210_read_reg(ES7210_CLOCK_OFF_REG01); + } + if (ctrl_state == AUDIO_HAL_CTRL_START) { + ESP_LOGI(TAG, "The ES7210_CLOCK_OFF_REG01 value before stop is %x",regv); + ret |= es7210_start(regv); + } else { + ESP_LOGW(TAG, "The codec is about to stop"); + regv = es7210_read_reg(ES7210_CLOCK_OFF_REG01); + ret |= es7210_stop(); + } + return ESP_OK; +} + +esp_err_t es7210_adc_set_gain(es7210_input_mics_t mic_mask, es7210_gain_value_t gain) +{ + esp_err_t ret_val = ESP_OK; + + if (gain < GAIN_0DB) { + gain = GAIN_0DB; + } + + if (gain > GAIN_37_5DB) { + gain = GAIN_37_5DB; + } + + if (mic_mask & ES7210_INPUT_MIC1) { + ret_val |= es7210_update_reg_bit(ES7210_MIC1_GAIN_REG43, 0x0f, gain); + } + if (mic_mask & ES7210_INPUT_MIC2) { + ret_val |= es7210_update_reg_bit(ES7210_MIC2_GAIN_REG44, 0x0f, gain); + } + if (mic_mask & ES7210_INPUT_MIC3) { + ret_val |= es7210_update_reg_bit(ES7210_MIC3_GAIN_REG45, 0x0f, gain); + } + if (mic_mask & ES7210_INPUT_MIC4) { + ret_val |= es7210_update_reg_bit(ES7210_MIC4_GAIN_REG46, 0x0f, gain); + } + + return ret_val; +} + +esp_err_t es7210_adc_set_gain_all(es7210_gain_value_t gain) +{ + esp_err_t ret = ESP_OK; + uint32_t max_gain_vaule = 14; + if (gain < 0) { + gain = (es7210_gain_value_t) 0; + } else if (gain > max_gain_vaule) { + gain = (es7210_gain_value_t) max_gain_vaule; + } + ESP_LOGD(TAG, "SET: gain:%d", gain); + if (mic_select & ES7210_INPUT_MIC1) { + ret |= es7210_update_reg_bit(ES7210_MIC1_GAIN_REG43, 0x0f, gain); + } + if (mic_select & ES7210_INPUT_MIC2) { + ret |= es7210_update_reg_bit(ES7210_MIC2_GAIN_REG44, 0x0f, gain); + } + if (mic_select & ES7210_INPUT_MIC3) { + ret |= es7210_update_reg_bit(ES7210_MIC3_GAIN_REG45, 0x0f, gain); + } + if (mic_select & ES7210_INPUT_MIC4) { + ret |= es7210_update_reg_bit(ES7210_MIC4_GAIN_REG46, 0x0f, gain); + } + return ret; +} + +esp_err_t es7210_adc_get_gain(es7210_input_mics_t mic_mask, es7210_gain_value_t *gain) +{ + int regv = 0; + uint8_t gain_value; + if (mic_mask & ES7210_INPUT_MIC1) { + regv = es7210_read_reg(ES7210_MIC1_GAIN_REG43); + } else if (mic_mask & ES7210_INPUT_MIC2) { + regv = es7210_read_reg(ES7210_MIC2_GAIN_REG44); + } else if (mic_mask & ES7210_INPUT_MIC3) { + regv = es7210_read_reg(ES7210_MIC3_GAIN_REG45); + } else if (mic_mask & ES7210_INPUT_MIC4) { + regv = es7210_read_reg(ES7210_MIC4_GAIN_REG46); + } else { + ESP_LOGE(TAG, "No MIC selected"); + return ESP_FAIL; + } + if (regv == ESP_FAIL) { + return regv; + } + gain_value = (regv & 0x0f); /* Retain the last four bits for gain */ + *gain = (es7210_gain_value_t) gain_value; + ESP_LOGI(TAG, "GET: gain_value:%d", gain_value); + return ESP_OK; +} + +esp_err_t es7210_adc_set_volume(int volume) +{ + esp_err_t ret = ESP_OK; + ESP_LOGD(TAG, "ADC can adjust gain"); + return ret; +} + +esp_err_t es7210_set_mute(bool enable) +{ + ESP_LOGD(TAG, "ES7210 SetMute :%d", enable); + return ESP_OK; +} + +void es7210_read_all(void) +{ + for (int i = 0; i <= 0x4E; i++) { + uint8_t reg = es7210_read_reg(i); + ets_printf("REG:%02x, %02x\n", reg, i); + } +} + +#endif diff --git a/lib/lib_audio/es7210/src/es7210.h b/lib/lib_audio/es7210/src/es7210.h new file mode 100644 index 000000000..07f7e6311 --- /dev/null +++ b/lib/lib_audio/es7210/src/es7210.h @@ -0,0 +1,260 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2021 + * + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _ES7210_H +#define _ES7210_H + +#include "audio_hal.h" + + +typedef enum { + ES7210_AD1_AD0_00 = 0x40, + ES7210_AD1_AD0_01 = 0x41, + ES7210_AD1_AD0_10 = 0x42, + ES7210_AD1_AD0_11 = 0x43, +} es7210_address_t; + +/* ES7210 address*/ +#define ES7210_ADDR ES7210_AD1_AD0_00 + +#ifdef __cplusplus +extern "C" { +#endif + +#define ES7210_RESET_REG00 0x00 /* Reset control */ +#define ES7210_CLOCK_OFF_REG01 0x01 /* Used to turn off the ADC clock */ +#define ES7210_MAINCLK_REG02 0x02 /* Set ADC clock frequency division */ +#define ES7210_MASTER_CLK_REG03 0x03 /* MCLK source $ SCLK division */ +#define ES7210_LRCK_DIVH_REG04 0x04 /* lrck_divh */ +#define ES7210_LRCK_DIVL_REG05 0x05 /* lrck_divl */ +#define ES7210_POWER_DOWN_REG06 0x06 /* power down */ +#define ES7210_OSR_REG07 0x07 +#define ES7210_MODE_CONFIG_REG08 0x08 /* Set master/slave & channels */ +#define ES7210_TIME_CONTROL0_REG09 0x09 /* Set Chip intial state period*/ +#define ES7210_TIME_CONTROL1_REG0A 0x0A /* Set Power up state period */ +#define ES7210_SDP_INTERFACE1_REG11 0x11 /* Set sample & fmt */ +#define ES7210_SDP_INTERFACE2_REG12 0x12 /* Pins state */ +#define ES7210_ADC_AUTOMUTE_REG13 0x13 /* Set mute */ +#define ES7210_ADC34_MUTERANGE_REG14 0x14 /* Set mute range */ +#define ES7210_ADC34_HPF2_REG20 0x20 /* HPF */ +#define ES7210_ADC34_HPF1_REG21 0x21 +#define ES7210_ADC12_HPF1_REG22 0x22 +#define ES7210_ADC12_HPF2_REG23 0x23 +#define ES7210_ANALOG_REG40 0x40 /* ANALOG Power */ +#define ES7210_MIC12_BIAS_REG41 0x41 +#define ES7210_MIC34_BIAS_REG42 0x42 +#define ES7210_MIC1_GAIN_REG43 0x43 +#define ES7210_MIC2_GAIN_REG44 0x44 +#define ES7210_MIC3_GAIN_REG45 0x45 +#define ES7210_MIC4_GAIN_REG46 0x46 +#define ES7210_MIC1_POWER_REG47 0x47 +#define ES7210_MIC2_POWER_REG48 0x48 +#define ES7210_MIC3_POWER_REG49 0x49 +#define ES7210_MIC4_POWER_REG4A 0x4A +#define ES7210_MIC12_POWER_REG4B 0x4B /* MICBias & ADC & PGA Power */ +#define ES7210_MIC34_POWER_REG4C 0x4C + + + +typedef enum { + ES7210_INPUT_MIC1 = 0x01, + ES7210_INPUT_MIC2 = 0x02, + ES7210_INPUT_MIC3 = 0x04, + ES7210_INPUT_MIC4 = 0x08 +} es7210_input_mics_t; + +typedef enum gain_value{ + GAIN_0DB = 0, + GAIN_3DB, + GAIN_6DB, + GAIN_9DB, + GAIN_12DB, + GAIN_15DB, + GAIN_18DB, + GAIN_21DB, + GAIN_24DB, + GAIN_27DB, + GAIN_30DB, + GAIN_33DB, + GAIN_34_5DB, + GAIN_36DB, + GAIN_37_5DB, +} es7210_gain_value_t; + +/* + * @brief Initialize ES7210 ADC chip + * + * @param[in] codec_cfg: configuration of ES7210 + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t es7210_adc_init(TwoWire *tw, audio_hal_codec_config_t *codec_cfg); + +/** + * @brief Deinitialize ES7210 ADC chip + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t es7210_adc_deinit(); + +/** + * @brief Configure ES7210 ADC mode and I2S interface + * + * @param[in] mode: codec mode + * @param[in] iface: I2S config + * + * @return + * - ESP_FAIL Parameter error + * - ESP_OK Success + */ +esp_err_t es7210_adc_config_i2s(audio_hal_codec_mode_t mode, audio_hal_codec_i2s_iface_t *iface); + +/** + * @brief Control ES7210 ADC chip + * + * @param[in] mode: codec mode + * @param[in] ctrl_state: start or stop progress + * + * @return + * - ESP_FAIL Parameter error + * - ESP_OK Success + */ +esp_err_t es7210_adc_ctrl_state(audio_hal_codec_mode_t mode, audio_hal_ctrl_t ctrl_state); + +/** + * @brief Set gain of given mask + * + * @param[in] mic_mask Mask of MIC channel + * + * @param[in] gain: gain + * + * gain : value + * GAIN_0DB : 1 + * GAIN_3DB : 2 + * GAIN_6DB : 3 + * · + * · + * · + * GAIN_30DB : 10 + * GAIN_33DB : 11 + * GAIN_34_5DB : 12 + * GAIN_36DB : 13 + * GAIN_37_5DB : 14 + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t es7210_adc_set_gain(es7210_input_mics_t mic_mask, es7210_gain_value_t gain); + +/** + * @brief Set gain (Note: the enabled microphone sets the same gain) + * + * @param[in] gain: gain + * + * gain : value + * GAIN_0DB : 1 + * GAIN_3DB : 2 + * GAIN_6DB : 3 + * · + * · + * · + * GAIN_30DB : 10 + * GAIN_33DB : 11 + * GAIN_34_5DB : 12 + * GAIN_36DB : 13 + * GAIN_37_5DB : 14 + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t es7210_adc_set_gain_all(es7210_gain_value_t gain); + +/** + * @brief Get MIC gain + * + * @param mic_mask Selected MIC + * @param gain Pointer to `es7210_gain_value_t` + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t es7210_adc_get_gain(es7210_input_mics_t mic_mask, es7210_gain_value_t *gain); + +/** + * @brief Set volume + * + * @param[in] volume: volume + * + * @return + * - ESP_OK + */ +esp_err_t es7210_adc_set_volume(int volume); + +/** + * @brief Set ES7210 ADC mute status + * + * @return + * - ESP_FAIL + * - ESP_OK + */ +esp_err_t es7210_set_mute(bool enable); + +/** + * @brief Select ES7210 mic + * + * @param[in] mic: mics + * + * @return + * - ESP_FAIL + * - ESP_OK + */ +esp_err_t es7210_mic_select(es7210_input_mics_t mic); + +/** + * @brief Read regs of ES7210 + * + * @param[in] reg_addr: reg_addr + * + * @return + * - ESP_FAIL + * - ESP_OK + */ +int es7210_read_reg(uint8_t reg_addr); + +/** + * @brief Read all regs of ES7210 + */ +void es7210_read_all(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _ES7210_H_ */ diff --git a/lib/lib_audio/es8156/library.properties b/lib/lib_audio/es8156/library.properties index bd6db1442..7ff0a31b6 100644 --- a/lib/lib_audio/es8156/library.properties +++ b/lib/lib_audio/es8156/library.properties @@ -2,8 +2,8 @@ name=ES8156 version=1.0 author= maintainer= -sentence=Audio fcodec for ESP8266, ESP32 +sentence=Audio fcodec for ESP32 paragraph= category=Signal Output url= -architectures=* +architectures=esp32 diff --git a/lib/lib_audio/es8311/library.json b/lib/lib_audio/es8311/library.json new file mode 100644 index 000000000..bf1b4701b --- /dev/null +++ b/lib/lib_audio/es8311/library.json @@ -0,0 +1,7 @@ +{ + "name": "ES8311", + "description": "Audio codec", + "keywords": "ESP8266, ESP32, MP3, AAC, WAV, MOD, FLAC, RTTTL, MIDI, I2S, DAC, Delta-Sigma, TTS", + "version": "1.0.0", + "frameworks": "Arduino" +} diff --git a/lib/lib_audio/es8311/library.properties b/lib/lib_audio/es8311/library.properties new file mode 100644 index 000000000..fdbc224d2 --- /dev/null +++ b/lib/lib_audio/es8311/library.properties @@ -0,0 +1,9 @@ +name=ES8311 +version=1.0 +author= +maintainer= +sentence=Audio fcodec for ESP32 +paragraph= +category=Signal Output +url= +architectures=esp32 diff --git a/lib/lib_audio/es8311/src/es8311.cpp b/lib/lib_audio/es8311/src/es8311.cpp new file mode 100644 index 000000000..6cdc41f75 --- /dev/null +++ b/lib/lib_audio/es8311/src/es8311.cpp @@ -0,0 +1,695 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2019 + * + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifdef ESP32 + +#include +#include +#include "esp_log.h" +#include "es8311.h" + + + +/* + * to define the clock soure of MCLK + */ +#define FROM_MCLK_PIN 0 +#define FROM_SCLK_PIN 1 +#define ES8311_MCLK_SOURCE FROM_MCLK_PIN + +/* + * to define whether to reverse the clock + */ +#define INVERT_MCLK 0 // do not invert +#define INVERT_SCLK 0 + +#define IS_DMIC 0 // Is it a digital microphone + +#define MCLK_DIV_FRE 256 + +static TwoWire *es8311_wire; + + +/* + * Clock coefficient structer + */ +struct _coeff_div { + uint32_t mclk; /* mclk frequency */ + uint32_t rate; /* sample rate */ + uint8_t pre_div; /* the pre divider with range from 1 to 8 */ + uint8_t pre_multi; /* the pre multiplier with x1, x2, x4 and x8 selection */ + uint8_t adc_div; /* adcclk divider */ + uint8_t dac_div; /* dacclk divider */ + uint8_t fs_mode; /* double speed or single speed, =0, ss, =1, ds */ + uint8_t lrck_h; /* adclrck divider and daclrck divider */ + uint8_t lrck_l; + uint8_t bclk_div; /* sclk divider */ + uint8_t adc_osr; /* adc osr */ + uint8_t dac_osr; /* dac osr */ +}; + +/* codec hifi mclk clock divider coefficients */ +static const struct _coeff_div coeff_div[] = { + //mclk rate pre_div mult adc_div dac_div fs_mode lrch lrcl bckdiv osr + /* 8k */ + {12288000, 8000 , 0x06, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {18432000, 8000 , 0x03, 0x02, 0x03, 0x03, 0x00, 0x05, 0xff, 0x18, 0x10, 0x10}, + {16384000, 8000 , 0x08, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {8192000 , 8000 , 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {6144000 , 8000 , 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {4096000 , 8000 , 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {3072000 , 8000 , 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {2048000 , 8000 , 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {1536000 , 8000 , 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {1024000 , 8000 , 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + + /* 11.025k */ + {11289600, 11025, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {5644800 , 11025, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {2822400 , 11025, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {1411200 , 11025, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + + /* 12k */ + {12288000, 12000, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {6144000 , 12000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {3072000 , 12000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {1536000 , 12000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + + /* 16k */ + {12288000, 16000, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {18432000, 16000, 0x03, 0x02, 0x03, 0x03, 0x00, 0x02, 0xff, 0x0c, 0x10, 0x10}, + {16384000, 16000, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {8192000 , 16000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {6144000 , 16000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {4096000 , 16000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {3072000 , 16000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {2048000 , 16000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {1536000 , 16000, 0x03, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {1024000 , 16000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + + /* 22.05k */ + {11289600, 22050, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {5644800 , 22050, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {2822400 , 22050, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {1411200 , 22050, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + + /* 24k */ + {12288000, 24000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {18432000, 24000, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {6144000 , 24000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {3072000 , 24000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {1536000 , 24000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + + /* 32k */ + {12288000, 32000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {18432000, 32000, 0x03, 0x04, 0x03, 0x03, 0x00, 0x02, 0xff, 0x0c, 0x10, 0x10}, + {16384000, 32000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {8192000 , 32000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {6144000 , 32000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {4096000 , 32000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {3072000 , 32000, 0x03, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {2048000 , 32000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {1536000 , 32000, 0x03, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, + {1024000 , 32000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + + /* 44.1k */ + {11289600, 44100, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {5644800 , 44100, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {2822400 , 44100, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {1411200 , 44100, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + + /* 48k */ + {12288000, 48000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {18432000, 48000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {6144000 , 48000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {3072000 , 48000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {1536000 , 48000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + + /* 64k */ + {12288000, 64000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {18432000, 64000, 0x03, 0x04, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10}, + {16384000, 64000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {8192000 , 64000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {6144000 , 64000, 0x01, 0x04, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10}, + {4096000 , 64000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {3072000 , 64000, 0x01, 0x08, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10}, + {2048000 , 64000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {1536000 , 64000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0xbf, 0x03, 0x18, 0x18}, + {1024000 , 64000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, + + /* 88.2k */ + {11289600, 88200, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {5644800 , 88200, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {2822400 , 88200, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {1411200 , 88200, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, + + /* 96k */ + {12288000, 96000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {18432000, 96000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {6144000 , 96000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {3072000 , 96000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, + {1536000 , 96000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, +}; + +static const char *TAG = "DRV8311"; + +#define ES_ASSERT(a, format, b, ...) \ + if ((a) != 0) { \ + ESP_LOGE(TAG, format, ##__VA_ARGS__); \ + return b;\ + } + +static esp_err_t es8311_write_reg(uint8_t reg_addr, uint8_t data) +{ + //return i2c_bus_write_byte(i2c_handle, reg_addr, data); + es8311_wire->beginTransmission(ES8311_ADDR); + es8311_wire->write(reg_addr); + es8311_wire->write(data); + return es8311_wire->endTransmission(); + +} + +static int es8311_read_reg(uint8_t reg_addr) +{ + uint8_t data; + //i2c_bus_read_byte(i2c_handle, reg_addr, &data); + es8311_wire->beginTransmission(ES8311_ADDR); + es8311_wire->write(reg_addr); + es8311_wire->endTransmission(false); + es8311_wire->requestFrom(ES8311_ADDR, (size_t)1); + data = es8311_wire->read(); + return (int)data; +} + +/* +* look for the coefficient in coeff_div[] table +*/ +static int get_coeff(uint32_t mclk, uint32_t rate) +{ + for (int i = 0; i < (sizeof(coeff_div) / sizeof(coeff_div[0])); i++) { + if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) + return i; + } + return -1; +} + +/* +* set es8311 dac mute or not +* if mute = 0, dac un-mute +* if mute = 1, dac mute +*/ +static void es8311_mute(int mute) +{ + uint8_t regv; + regv = es8311_read_reg(ES8311_DAC_REG31) & 0x9f; + if (mute) { + es8311_write_reg(ES8311_SYSTEM_REG12, 0x02); + es8311_write_reg(ES8311_DAC_REG31, regv | 0x60); + es8311_write_reg(ES8311_DAC_REG32, 0x00); + es8311_write_reg(ES8311_DAC_REG37, 0x08); + } else { + es8311_write_reg(ES8311_DAC_REG31, regv); + es8311_write_reg(ES8311_SYSTEM_REG12, 0x00); + } +} + +/* +* set es8311 into suspend mode +*/ +static void es8311_suspend(void) +{ + ESP_LOGI(TAG, "Enter into es8311_suspend()"); + es8311_write_reg(ES8311_DAC_REG32, 0x00); + es8311_write_reg(ES8311_ADC_REG17, 0x00); + es8311_write_reg(ES8311_SYSTEM_REG0E, 0xFF); + es8311_write_reg(ES8311_SYSTEM_REG12, 0x02); + es8311_write_reg(ES8311_SYSTEM_REG14, 0x00); + es8311_write_reg(ES8311_SYSTEM_REG0D, 0xFA); + es8311_write_reg(ES8311_ADC_REG15, 0x00); + es8311_write_reg(ES8311_DAC_REG37, 0x08); + es8311_write_reg(ES8311_GP_REG45, 0x01); +} + +esp_err_t es8311_codec_init(TwoWire *tw, audio_hal_codec_config_t *codec_cfg) +{ + + es8311_wire = tw; + + uint8_t datmp, regv; + int coeff; + esp_err_t ret = ESP_OK; + + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, 0x30); + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG02, 0x00); + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG03, 0x10); + ret |= es8311_write_reg(ES8311_ADC_REG16, 0x24); + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG04, 0x10); + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG05, 0x00); + ret |= es8311_write_reg(ES8311_SYSTEM_REG0B, 0x00); + ret |= es8311_write_reg(ES8311_SYSTEM_REG0C, 0x00); + ret |= es8311_write_reg(ES8311_SYSTEM_REG10, 0x1F); + ret |= es8311_write_reg(ES8311_SYSTEM_REG11, 0x7F); + ret |= es8311_write_reg(ES8311_RESET_REG00, 0x80); + /* + * Set Codec into Master or Slave mode + */ + regv = es8311_read_reg(ES8311_RESET_REG00); + /* + * Set master/slave audio interface + */ + audio_hal_codec_i2s_iface_t *i2s_cfg = &(codec_cfg->i2s_iface); + switch (i2s_cfg->mode) { + case AUDIO_HAL_MODE_MASTER: /* MASTER MODE */ + ESP_LOGI(TAG, "ES8311 in Master mode"); + regv |= 0x40; + break; + case AUDIO_HAL_MODE_SLAVE: /* SLAVE MODE */ + ESP_LOGI(TAG, "ES8311 in Slave mode"); + regv &= 0xBF; + break; + default: + regv &= 0xBF; + } + ret |= es8311_write_reg(ES8311_RESET_REG00, regv); + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, 0x3F); + /* + * Select clock source for internal mclk + */ + + int es8311_mclk_src = ES8311_MCLK_SOURCE; + switch (es8311_mclk_src) { + case FROM_MCLK_PIN: + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); + regv &= 0x7F; + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); + break; + case FROM_SCLK_PIN: + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); + regv |= 0x80; + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); + break; + default: + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); + regv &= 0x7F; + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); + break; + } + int sample_fre = 0; + int mclk_fre = 0; + switch (i2s_cfg->samples) { + case AUDIO_HAL_08K_SAMPLES: + sample_fre = 8000; + break; + case AUDIO_HAL_11K_SAMPLES: + sample_fre = 11025; + break; + case AUDIO_HAL_16K_SAMPLES: + sample_fre = 16000; + break; + case AUDIO_HAL_22K_SAMPLES: + sample_fre = 22050; + break; + case AUDIO_HAL_24K_SAMPLES: + sample_fre = 24000; + break; + case AUDIO_HAL_32K_SAMPLES: + sample_fre = 32000; + break; + case AUDIO_HAL_44K_SAMPLES: + sample_fre = 44100; + break; + case AUDIO_HAL_48K_SAMPLES: + sample_fre = 48000; + break; + default: + ESP_LOGE(TAG, "Unable to configure sample rate %dHz", sample_fre); + break; + } + mclk_fre = sample_fre * MCLK_DIV_FRE; + coeff = get_coeff(mclk_fre, sample_fre); + if (coeff < 0) { + ESP_LOGE(TAG, "Unable to configure sample rate %dHz with %dHz MCLK", sample_fre, mclk_fre); + return ESP_FAIL; + } + /* + * Set clock parammeters + */ + if (coeff >= 0) { + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG02) & 0x07; + regv |= (coeff_div[coeff].pre_div - 1) << 5; + datmp = 0; + switch (coeff_div[coeff].pre_multi) { + case 1: + datmp = 0; + break; + case 2: + datmp = 1; + break; + case 4: + datmp = 2; + break; + case 8: + datmp = 3; + break; + default: + break; + } + + if (ES8311_MCLK_SOURCE == FROM_SCLK_PIN) { + datmp = 3; /* DIG_MCLK = LRCK * 256 = BCLK * 8 */ + } + regv |= (datmp) << 3; + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG02, regv); + + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG05) & 0x00; + regv |= (coeff_div[coeff].adc_div - 1) << 4; + regv |= (coeff_div[coeff].dac_div - 1) << 0; + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG05, regv); + + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG03) & 0x80; + regv |= coeff_div[coeff].fs_mode << 6; + regv |= coeff_div[coeff].adc_osr << 0; + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG03, regv); + + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG04) & 0x80; + regv |= coeff_div[coeff].dac_osr << 0; + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG04, regv); + + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG07) & 0xC0; + regv |= coeff_div[coeff].lrck_h << 0; + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG07, regv); + + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG08) & 0x00; + regv |= coeff_div[coeff].lrck_l << 0; + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG08, regv); + + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG06) & 0xE0; + if (coeff_div[coeff].bclk_div < 19) { + regv |= (coeff_div[coeff].bclk_div - 1) << 0; + } else { + regv |= (coeff_div[coeff].bclk_div) << 0; + } + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG06, regv); + } + + /* + * mclk inverted or not + */ + if (INVERT_MCLK) { + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); + regv |= 0x40; + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); + } else { + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); + regv &= ~(0x40); + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); + } + /* + * sclk inverted or not + */ + if (INVERT_SCLK) { + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG06); + regv |= 0x20; + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG06, regv); + } else { + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG06); + regv &= ~(0x20); + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG06, regv); + } + + ret |= es8311_write_reg(ES8311_SYSTEM_REG13, 0x10); + ret |= es8311_write_reg(ES8311_ADC_REG1B, 0x0A); + ret |= es8311_write_reg(ES8311_ADC_REG1C, 0x6A); + + return ESP_OK; +} + +esp_err_t es8311_codec_deinit() +{ + // i2c_bus_delete(i2c_handle); + return ESP_OK; +} + +esp_err_t es8311_config_fmt(es_i2s_fmt_t fmt) +{ + esp_err_t ret = ESP_OK; + uint8_t adc_iface = 0, dac_iface = 0; + dac_iface = es8311_read_reg(ES8311_SDPIN_REG09); + adc_iface = es8311_read_reg(ES8311_SDPOUT_REG0A); + switch (fmt) { + case AUDIO_HAL_I2S_NORMAL: + ESP_LOGD(TAG, "ES8311 in I2S Format"); + dac_iface &= 0xFC; + adc_iface &= 0xFC; + break; + case AUDIO_HAL_I2S_LEFT: + case AUDIO_HAL_I2S_RIGHT: + ESP_LOGD(TAG, "ES8311 in LJ Format"); + adc_iface &= 0xFC; + dac_iface &= 0xFC; + adc_iface |= 0x01; + dac_iface |= 0x01; + break; + case AUDIO_HAL_I2S_DSP: + ESP_LOGD(TAG, "ES8311 in DSP-B Format"); + adc_iface &= 0xDC; + dac_iface &= 0xDC; + adc_iface |= 0x23; + dac_iface |= 0x23; + break; + default: + dac_iface &= 0xFC; + adc_iface &= 0xFC; + break; + } + ret |= es8311_write_reg(ES8311_SDPIN_REG09, dac_iface); + ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, adc_iface); + + return ret; +} + +esp_err_t es8311_set_bits_per_sample(audio_hal_iface_bits_t bits) +{ + esp_err_t ret = ESP_OK; + uint8_t adc_iface = 0, dac_iface = 0; + dac_iface = es8311_read_reg(ES8311_SDPIN_REG09); + adc_iface = es8311_read_reg(ES8311_SDPOUT_REG0A); + switch (bits) { + case AUDIO_HAL_BIT_LENGTH_16BITS: + dac_iface |= 0x0c; + adc_iface |= 0x0c; + break; + case AUDIO_HAL_BIT_LENGTH_24BITS: + break; + case AUDIO_HAL_BIT_LENGTH_32BITS: + dac_iface |= 0x10; + adc_iface |= 0x10; + break; + default: + dac_iface |= 0x0c; + adc_iface |= 0x0c; + break; + + } + ret |= es8311_write_reg(ES8311_SDPIN_REG09, dac_iface); + ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, adc_iface); + + return ret; +} + +esp_err_t es8311_codec_config_i2s(audio_hal_codec_mode_t mode, audio_hal_codec_i2s_iface_t *iface) +{ + int ret = ESP_OK; + ret |= es8311_set_bits_per_sample(iface->bits); + ret |= es8311_config_fmt((es_i2s_fmt_t)iface->fmt); + return ret; +} + +esp_err_t es8311_codec_ctrl_state(audio_hal_codec_mode_t mode, audio_hal_ctrl_t ctrl_state) +{ + esp_err_t ret = ESP_OK; + es_module_t es_mode = ES_MODULE_MIN; + + switch (mode) { + case AUDIO_HAL_CODEC_MODE_ENCODE: + es_mode = ES_MODULE_ADC; + break; + case AUDIO_HAL_CODEC_MODE_LINE_IN: + es_mode = ES_MODULE_LINE; + break; + case AUDIO_HAL_CODEC_MODE_DECODE: + es_mode = ES_MODULE_DAC; + break; + case AUDIO_HAL_CODEC_MODE_BOTH: + es_mode = ES_MODULE_ADC_DAC; + break; + default: + es_mode = ES_MODULE_DAC; + ESP_LOGW(TAG, "Codec mode not support, default is decode mode"); + break; + } + + if (ctrl_state == AUDIO_HAL_CTRL_START) { + ret |= es8311_start(es_mode); + } else { + ESP_LOGW(TAG, "The codec is about to stop"); + ret |= es8311_stop(es_mode); + } + + return ret; +} + +esp_err_t es8311_start(es_module_t mode) +{ + esp_err_t ret = ESP_OK; + uint8_t adc_iface = 0, dac_iface = 0; + + dac_iface = es8311_read_reg(ES8311_SDPIN_REG09) & 0xBF; + adc_iface = es8311_read_reg(ES8311_SDPOUT_REG0A) & 0xBF; + adc_iface |= BIT(6); + dac_iface |= BIT(6); + + if (mode == ES_MODULE_LINE) { + ESP_LOGE(TAG, "The codec es8311 doesn't support ES_MODULE_LINE mode"); + return ESP_FAIL; + } + if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC) { + adc_iface &= ~(BIT(6)); + } + if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC) { + dac_iface &= ~(BIT(6)); + } + + ret |= es8311_write_reg(ES8311_SDPIN_REG09, dac_iface); + ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, adc_iface); + + ret |= es8311_write_reg(ES8311_ADC_REG17, 0xBF); + ret |= es8311_write_reg(ES8311_SYSTEM_REG0E, 0x02); + ret |= es8311_write_reg(ES8311_SYSTEM_REG12, 0x00); + ret |= es8311_write_reg(ES8311_SYSTEM_REG14, 0x1A); + + /* + * pdm dmic enable or disable + */ + int regv = 0; + if (IS_DMIC) { + regv = es8311_read_reg(ES8311_SYSTEM_REG14); + regv |= 0x40; + ret |= es8311_write_reg(ES8311_SYSTEM_REG14, regv); + } else { + regv = es8311_read_reg(ES8311_SYSTEM_REG14); + regv &= ~(0x40); + ret |= es8311_write_reg(ES8311_SYSTEM_REG14, regv); + } + + ret |= es8311_write_reg(ES8311_SYSTEM_REG0D, 0x01); + ret |= es8311_write_reg(ES8311_ADC_REG15, 0x40); + ret |= es8311_write_reg(ES8311_DAC_REG37, 0x48); + ret |= es8311_write_reg(ES8311_GP_REG45, 0x00); + + return ret; +} + +esp_err_t es8311_stop(es_module_t mode) +{ + esp_err_t ret = ESP_OK; + es8311_suspend(); + return ret; +} + +esp_err_t es8311_codec_set_voice_volume(int volume) +{ + esp_err_t res = ESP_OK; + if (volume < 0) { + volume = 0; + } else if (volume > 100) { + volume = 100; + } + int vol = (volume) * 2550 / 1000; + ESP_LOGD(TAG, "SET: volume:%d", vol); + es8311_write_reg(ES8311_DAC_REG32, vol); + return res; +} + +esp_err_t es8311_codec_get_voice_volume(int *volume) +{ + esp_err_t res = ESP_OK; + int regv = 0; + regv = es8311_read_reg(ES8311_DAC_REG32); + if (regv == ESP_FAIL) { + *volume = 0; + res = ESP_FAIL; + } else { + *volume = regv * 100 / 256; + } + ESP_LOGD(TAG, "GET: res:%d, volume:%d", regv, *volume); + return res; +} + +esp_err_t es8311_set_voice_mute(bool enable) +{ + ESP_LOGD(TAG, "Es8311SetVoiceMute volume:%d", enable); + es8311_mute(enable); + return ESP_OK; +} + +esp_err_t es8311_get_voice_mute(int *mute) +{ + esp_err_t res = ESP_OK; + uint8_t reg = 0; + res = es8311_read_reg(ES8311_DAC_REG31); + if (res != ESP_FAIL) { + reg = (res & 0x20) >> 5; + } + *mute = reg; + return res; +} + +esp_err_t es8311_set_mic_gain(es8311_mic_gain_t gain_db) +{ + esp_err_t res = ESP_OK; + res = es8311_write_reg(ES8311_ADC_REG16, gain_db); // MIC gain scale + return res; +} + +void es8311_read_all() +{ + for (int i = 0; i < 0x4A; i++) { + uint8_t reg = es8311_read_reg(i); + ets_printf("REG:%02x, %02x\n", reg, i); + } +} + +esp_err_t es8311_set_channel(int is_right) +{ + uint8_t reg_val = es8311_read_reg(ES8311_SDPIN_REG09); + if (is_right) { + reg_val |= 0b10000000; + } else { + reg_val &= 0b01111111; + } + return es8311_write_reg(ES8311_SDPIN_REG09, reg_val); +} + +#endif diff --git a/lib/lib_audio/es8311/src/es8311.h b/lib/lib_audio/es8311/src/es8311.h new file mode 100644 index 000000000..609357987 --- /dev/null +++ b/lib/lib_audio/es8311/src/es8311.h @@ -0,0 +1,285 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2019 + * + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _ES8311_H +#define _ES8311_H + +#include "audio_hal.h" +#include "esp_types.h" +#include "esxxx_common.h" + + +/* ES8311 address + * 0x32:CE=1;0x30:CE=0 + */ +#define ES8311_ADDR 0x18 + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ES8311_REGISTER NAME_REG_REGISTER ADDRESS + */ +#define ES8311_RESET_REG00 0x00 /*reset digital,csm,clock manager etc.*/ + +/* + * Clock Scheme Register definition + */ +#define ES8311_CLK_MANAGER_REG01 0x01 /* select clk src for mclk, enable clock for codec */ +#define ES8311_CLK_MANAGER_REG02 0x02 /* clk divider and clk multiplier */ +#define ES8311_CLK_MANAGER_REG03 0x03 /* adc fsmode and osr */ +#define ES8311_CLK_MANAGER_REG04 0x04 /* dac osr */ +#define ES8311_CLK_MANAGER_REG05 0x05 /* clk divier for adc and dac */ +#define ES8311_CLK_MANAGER_REG06 0x06 /* bclk inverter and divider */ +#define ES8311_CLK_MANAGER_REG07 0x07 /* tri-state, lrck divider */ +#define ES8311_CLK_MANAGER_REG08 0x08 /* lrck divider */ +/* + * SDP + */ +#define ES8311_SDPIN_REG09 0x09 /* dac serial digital port */ +#define ES8311_SDPOUT_REG0A 0x0A /* adc serial digital port */ +/* + * SYSTEM + */ +#define ES8311_SYSTEM_REG0B 0x0B /* system */ +#define ES8311_SYSTEM_REG0C 0x0C /* system */ +#define ES8311_SYSTEM_REG0D 0x0D /* system, power up/down */ +#define ES8311_SYSTEM_REG0E 0x0E /* system, power up/down */ +#define ES8311_SYSTEM_REG0F 0x0F /* system, low power */ +#define ES8311_SYSTEM_REG10 0x10 /* system */ +#define ES8311_SYSTEM_REG11 0x11 /* system */ +#define ES8311_SYSTEM_REG12 0x12 /* system, Enable DAC */ +#define ES8311_SYSTEM_REG13 0x13 /* system */ +#define ES8311_SYSTEM_REG14 0x14 /* system, select DMIC, select analog pga gain */ +/* + * ADC + */ +#define ES8311_ADC_REG15 0x15 /* ADC, adc ramp rate, dmic sense */ +#define ES8311_ADC_REG16 0x16 /* ADC */ +#define ES8311_ADC_REG17 0x17 /* ADC, volume */ +#define ES8311_ADC_REG18 0x18 /* ADC, alc enable and winsize */ +#define ES8311_ADC_REG19 0x19 /* ADC, alc maxlevel */ +#define ES8311_ADC_REG1A 0x1A /* ADC, alc automute */ +#define ES8311_ADC_REG1B 0x1B /* ADC, alc automute, adc hpf s1 */ +#define ES8311_ADC_REG1C 0x1C /* ADC, equalizer, hpf s2 */ +/* + * DAC + */ +#define ES8311_DAC_REG31 0x31 /* DAC, mute */ +#define ES8311_DAC_REG32 0x32 /* DAC, volume */ +#define ES8311_DAC_REG33 0x33 /* DAC, offset */ +#define ES8311_DAC_REG34 0x34 /* DAC, drc enable, drc winsize */ +#define ES8311_DAC_REG35 0x35 /* DAC, drc maxlevel, minilevel */ +#define ES8311_DAC_REG37 0x37 /* DAC, ramprate */ +/* + *GPIO + */ +#define ES8311_GPIO_REG44 0x44 /* GPIO, dac2adc for test */ +#define ES8311_GP_REG45 0x45 /* GP CONTROL */ +/* + * CHIP + */ +#define ES8311_CHD1_REGFD 0xFD /* CHIP ID1 */ +#define ES8311_CHD2_REGFE 0xFE /* CHIP ID2 */ +#define ES8311_CHVER_REGFF 0xFF /* VERSION */ +#define ES8311_CHD1_REGFD 0xFD /* CHIP ID1 */ + +#define ES8311_MAX_REGISTER 0xFF + +typedef enum { + ES8311_MIC_GAIN_MIN = -1, + ES8311_MIC_GAIN_0DB, + ES8311_MIC_GAIN_6DB, + ES8311_MIC_GAIN_12DB, + ES8311_MIC_GAIN_18DB, + ES8311_MIC_GAIN_24DB, + ES8311_MIC_GAIN_30DB, + ES8311_MIC_GAIN_36DB, + ES8311_MIC_GAIN_42DB, + ES8311_MIC_GAIN_MAX +} es8311_mic_gain_t; + +/* + * @brief Initialize ES8311 codec chip + * + * @param codec_cfg configuration of ES8311 + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t es8311_codec_init(TwoWire *tw, audio_hal_codec_config_t *codec_cfg); + +/** + * @brief Deinitialize ES8311 codec chip + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t es8311_codec_deinit(void); + +/** + * @brief Control ES8311 codec chip + * + * @param mode codec mode + * @param ctrl_state start or stop decode or encode progress + * + * @return + * - ESP_FAIL Parameter error + * - ESP_OK Success + */ +esp_err_t es8311_codec_ctrl_state(audio_hal_codec_mode_t mode, audio_hal_ctrl_t ctrl_state); + +/** + * @brief Configure ES8311 codec mode and I2S interface + * + * @param mode codec mode + * @param iface I2S config + * + * @return + * - ESP_FAIL Parameter error + * - ESP_OK Success + */ +esp_err_t es8311_codec_config_i2s(audio_hal_codec_mode_t mode, audio_hal_codec_i2s_iface_t *iface); + +/** + * @brief Configure ES8311 DAC mute or not. Basically you can use this function to mute the output or unmute + * + * @param enable enable(1) or disable(0) + * + * @return + * - ESP_FAIL Parameter error + * - ESP_OK Success + */ +esp_err_t es8311_set_voice_mute(bool enable); + +/** + * @brief Set voice volume + * + * @param volume: voice volume (0~100) + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t es8311_codec_set_voice_volume(int volume); + +/** + * @brief Get voice volume + * + * @param[out] *volume: voice volume (0~100) + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t es8311_codec_get_voice_volume(int *volume); + +/** + * @brief Configure ES8311 I2S format + * + * @param cfg: ES8388 I2S format + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t es8311_config_fmt(es_i2s_fmt_t fmt); + +/** + * @brief Configure ES8311 data sample bits + * + * @param bit_per_sample: bit number of per sample + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t es8311_set_bits_per_sample(audio_hal_iface_bits_t bits); + +/** + * @brief Start ES8311 codec chip + * + * @param mode: set ADC or DAC or both + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t es8311_start(es_module_t mode); + +/** + * @brief Stop ES8311 codec chip + * + * @param mode: set ADC or DAC or both + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t es8311_stop(es_module_t mode); + +/** + * @brief Get ES8311 DAC mute status + * + * @return + * - ESP_FAIL + * - ESP_OK + */ +esp_err_t es8311_get_voice_mute(int *mute); + +/** + * @brief Set ES8311 mic gain + * + * @param gain db of mic gain + * + * @return + * - ESP_FAIL Parameter error + * - ESP_OK Success + */ +esp_err_t es8311_set_mic_gain(es8311_mic_gain_t gain_db); + +/** + * @brief Print all ES8311 registers + * + * @return + * - void + */ +void es8311_read_all(); + +/** + * @brief + * + * @param is_right + * @return esp_err_t + */ +esp_err_t es8311_set_channel(int is_right); + +#ifdef __cplusplus +} +#endif + +#endif