hannabox/lib/ESP32-audioI2S/examples/ES8311/es8311.cpp

317 lines
13 KiB
C++

/*
ES8311 - An ES8311 Codec driver library for Arduino
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
examples:
//one I2C bus: (default behaviour)
ES8311 es;
es.begin(sda, scl);
//two I2C busses:
TwoWire i2cBusOne = TwoWire(0);
TwoWire i2cBusTwo = TwoWire(1);
ES8311 es(&i2cBusOne);
i2cBusOne.begin(sda, scl, 400000);
*/
#include "es8311.h"
/* 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, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{18432000, 8000, 0x03, 0x01, 0x03, 0x03, 0x00, 0x05, 0xff, 0x18, 0x10, 0x10},
{16384000, 8000, 0x08, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{8192000, 8000, 0x04, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{6144000, 8000, 0x03, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{4096000, 8000, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{3072000, 8000, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{2048000, 8000, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1536000, 8000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1024000, 8000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
/* 11.025k */
{11289600, 11025, 0x04, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{5644800, 11025, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{2822400, 11025, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1411200, 11025, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
/* 12k */
{12288000, 12000, 0x04, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{6144000, 12000, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{3072000, 12000, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1536000, 12000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
/* 16k */
{12288000, 16000, 0x03, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{18432000, 16000, 0x03, 0x01, 0x03, 0x03, 0x00, 0x02, 0xff, 0x0c, 0x10, 0x10},
{16384000, 16000, 0x04, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{8192000, 16000, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{6144000, 16000, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{4096000, 16000, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{3072000, 16000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{2048000, 16000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1536000, 16000, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1024000, 16000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
/* 22.05k */
{11289600, 22050, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{5644800, 22050, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{2822400, 22050, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1411200, 22050, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{705600, 22050, 0x01, 0x03, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
/* 24k */
{12288000, 24000, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{18432000, 24000, 0x03, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{6144000, 24000, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{3072000, 24000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1536000, 24000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
/* 32k */
{12288000, 32000, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{18432000, 32000, 0x03, 0x02, 0x03, 0x03, 0x00, 0x02, 0xff, 0x0c, 0x10, 0x10},
{16384000, 32000, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{8192000, 32000, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{6144000, 32000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{4096000, 32000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{3072000, 32000, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{2048000, 32000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1536000, 32000, 0x03, 0x03, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10},
{1024000, 32000, 0x01, 0x03, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
/* 44.1k */
{11289600, 44100, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{5644800, 44100, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{2822400, 44100, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1411200, 44100, 0x01, 0x03, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
/* 48k */
{12288000, 48000, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{18432000, 48000, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{6144000, 48000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{3072000, 48000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1536000, 48000, 0x01, 0x03, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
/* 64k */
{12288000, 64000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{18432000, 64000, 0x03, 0x02, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10},
{16384000, 64000, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{8192000, 64000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{6144000, 64000, 0x01, 0x02, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10},
{4096000, 64000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{3072000, 64000, 0x01, 0x03, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10},
{2048000, 64000, 0x01, 0x03, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1536000, 64000, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00, 0xbf, 0x03, 0x18, 0x18},
{1024000, 64000, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10},
/* 88.2k */
{11289600, 88200, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{5644800, 88200, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{2822400, 88200, 0x01, 0x03, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1411200, 88200, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10},
/* 96k */
{12288000, 96000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{18432000, 96000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{6144000, 96000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{3072000, 96000, 0x01, 0x03, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10},
{1536000, 96000, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10},
};
ES8311::ES8311(TwoWire *TwoWireInstance){
_TwoWireInstance = TwoWireInstance;
}
ES8311::~ES8311(){
if (_TwoWireInstance != NULL) {
_TwoWireInstance->end();
}
}
/*
* look for the coefficient in coeff_div[] table
*/
int ES8311::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;
}
bool ES8311::begin(int32_t sda, int32_t scl, uint32_t frequency) {
bool ok = true;
uint8_t reg = 0;
if((sda >= 0) && (scl >= 0)){
ok = _TwoWireInstance->begin(sda, scl, frequency);
_TwoWireInstance->beginTransmission(ES8311_ADDR);
ok = (Wire.endTransmission() == 0);
if(!ok) {
_TwoWireInstance->end();
log_e("ES8311 not found"); return false;
}
}
else {
log_e("Invalid SDA/SCL pins");
return false;
}
ok |= WriteReg(0x00, 0x1F); // Reset
vTaskDelay(20 / portTICK_PERIOD_MS);
ok |= WriteReg(0x00, 0x00); // Release reset
ok |= WriteReg(0x00, 0x80); // Power on
ok |= WriteReg(0x01, 0x3F); // Enable all clocks
reg = ReadReg(0x06);
reg &= ~BIT(5); // SCLK (BCLK) pin not inverted
ok |= WriteReg(0x06, reg); //
ok |= setSampleRate(ES8311_SAMPLE_RATE48); // default
ok |= setBitsPerSample(ES8311_BITS_PER_SAMPLE16); // default
ok |= WriteReg(0x0D, 0x01); // Power up analog circuitry
ok |= WriteReg(0x0E, 0x02); // Enable analog PGA, enable ADC modulator
ok |= WriteReg(0x12, 0x00); // Power-up DAC
ok |= WriteReg(0x13, 0x10); // Enable output to HP drive
ok |= WriteReg(0x1C, 0x6A); // ADC Equalizer bypass, cancel DC offset in digital domain
ok |= WriteReg(0x37, 0x08); // Bypass DAC equalizer
return ok;
}
bool ES8311::setVolume(uint8_t volume){ // 0...100
if (volume > 100) {volume = 100;}
int reg32;
if (volume == 0) {reg32 = 0;}
else { reg32 = ((volume) * 256 / 100) - 1;}
return WriteReg(0x32, reg32);
}
uint8_t ES8311::getVolume(){
uint8_t reg32 = ReadReg(0x32);
uint8_t volume;
if (reg32 == 0) {
volume = 0;
} else {
volume = ((reg32 * 100) / 256) + 1;
}
return volume;
}
bool ES8311::setSampleRate(uint32_t sample_rate){
uint8_t reg = 0;
bool ok = true;
_mclk_hz = sample_rate * 256; // default MCLK frequency
if(sample_rate > 64000) _mclk_hz /= 2;
int coeff = get_coeff(_mclk_hz, sample_rate);
if (coeff < 0) {log_e("Invalid sample rate %i", sample_rate); return false;}
const struct _coeff_div *const selected_coeff = &coeff_div[coeff];
reg = ReadReg(0x02);
reg |= (selected_coeff->pre_div - 1) << 5;
reg |= selected_coeff->pre_multi << 3;
ok |= WriteReg(0x02, reg); // Set pre_div and pre_multi
const uint8_t reg03 = (selected_coeff->fs_mode << 6) | selected_coeff->adc_osr;
ok |= WriteReg(0x03, reg03); // Set fs_mode and adc_osr
ok |= WriteReg(0x04, selected_coeff->dac_osr); // Set dac_osr
const uint8_t reg05 = ((selected_coeff->adc_div - 1) << 4) | (selected_coeff->dac_div - 1);
ok |= WriteReg(0x05, reg05); // Set adc_div and dac_div
reg = ReadReg(0x06);
reg &= 0xE0;
if (selected_coeff->bclk_div < 19) {reg |= (selected_coeff->bclk_div - 1) << 0;}
else { reg |= (selected_coeff->bclk_div) << 0;}
ok |= WriteReg(0x06, reg); // Set bclk_div
reg = ReadReg(0x07);
reg &= 0xC0;
reg |= selected_coeff->lrck_h << 0;
ok |= WriteReg(0x07, reg); // Set lrck_h
ok |= WriteReg(0x08, selected_coeff->lrck_l); // Set lrck_l
return ok;
}
bool ES8311::setBitsPerSample(uint8_t bps){
uint8_t reg09 = ReadReg(0x09);
uint8_t reg0A = ReadReg(0x0A);
switch (bps) {
case 16: reg09 |= (3 << 2); reg0A |= (3 << 2); break;
case 18: reg09 |= (2 << 2); reg0A |= (2 << 2); break;
case 20: reg09 |= (1 << 2); reg0A |= (1 << 2); break;
case 24: reg09 |= (0 << 2); reg0A |= (0 << 2); break;
case 32: reg09 |= (4 << 2); reg0A |= (4 << 2); break;
default: return false; // Invalid bits per sample
}
bool ok = WriteReg(0x09, reg09);
ok |= WriteReg(0x0A, reg0A);
return ok;
}
bool ES8311::enableMicrophone(bool enable){
uint8_t reg = 0x1A; // enable analog MIC and max PGA gain
if (enable) {
reg |= BIT(6);
}
bool ok = WriteReg(0x17, 0xC8); // ADC_VOLUME
ok |= WriteReg(0x14, reg); // Enable MIC
return ok;
}
bool ES8311::setMicrophoneGain(uint8_t gain){ // 0...7
uint8_t reg = ReadReg(0x16);
reg &= 0xF8; // Clear gain bits
if (gain > 7) {gain = 7;}
reg |= gain; // Set gain bits
bool ok = WriteReg(0x16, gain); // ADC_VOLUME
return ok;
}
uint8_t ES8311::getMicrophoneGain(){
uint8_t reg = ReadReg(0x16);
return (reg & 0x07); // Get gain bits
}
bool ES8311::WriteReg(uint8_t reg, uint8_t val){
_TwoWireInstance->beginTransmission(ES8311_ADDR);
_TwoWireInstance->write(reg);
_TwoWireInstance->write(val);
return _TwoWireInstance->endTransmission() == 0;
}
uint8_t ES8311::ReadReg(uint8_t reg){
_TwoWireInstance->beginTransmission(ES8311_ADDR);
_TwoWireInstance->write(reg);
_TwoWireInstance->endTransmission(false);
uint8_t val = 0u;
_TwoWireInstance->requestFrom(uint16_t(ES8311_ADDR), (uint8_t)1, true);
if(_TwoWireInstance->available() >= 1){
val = _TwoWireInstance->read();
}
_TwoWireInstance->endTransmission();
return val;
}
void ES8311::read_all(){
for (uint8_t i = 0; i < 0x4A; i++) {
Serial.printf("0x%02X: 0x%02X\n", i, ReadReg(i));
}
}