#include "control_ES8388_F32.h" #define ES8388_REG_CHIP_CTRL1 (0x00) // Default 0000 0110 #define ES8388_REG_CHIP_CTRL1_DFLT (0x06) #define ES8388_BIT_SCPRESET (1<<7) // 1=reset registers to default #define ES8388_BIT_LRCM (1<<6) #define ES8388_BIT_DACMCLK (1<<5) #define ES8388_BIT_SAMEFS (1<<4) #define ES8388_BIT_SEQEN (1<<3) #define ES8388_BIT_ENREF (1<<2) #define ES8388_VMIDSEL_DIS (0x00) #define ES8388_VMIDSEL_50K (0x01) #define ES8388_VMIDSEL_500K (0x02) #define ES8388_VMIDSEL_5K (0x03) #define ES8388_REG_CHIP_CTRL2 (0x01) // Default 0101 1100 #define ES8388_REG_CHIP_CTRL2_DFLT (0x5C) #define ES8388_BIT_LPVCMMOD (1<<5) #define ES8388_BIT_LPVREFBUF (1<<4) #define ES8388_BIT_PDNANA (1<<3) #define ES8388_BIT_PDBIBIASGEN (1<<2) #define ES8388_BIT_VREFLO (1<<1) #define ES8388_BIT_PDBVREFBUF (1<<0) #define ES8388_REG_CHIP_PWR_MAN (0x02) // Default 1100 0011 #define ES8388_REG_CHIP_PWR_MAN_DFLT (0xC3) #define ES8388_BIT_ADC_DIGPDN (1<<7) #define ES8388_BIT_DAC_DIGPDN (1<<6) #define ES8388_BIT_ADCSTMRST (1<<5) #define ES8388_BIT_DACSTMRST (1<<4) #define ES8388_BIT_ADCDLL_PDN (1<<3) #define ES8388_BIT_DACDLL_PDN (1<<2) #define ES8388_BIT_ADCVREFPDN (1<<1) #define ES8388_BIT_DACVREFPDN (1<<0) #define ES8388_REG_ADC_PWR_MAN (0x03) // Default 1111 1100 #define ES8388_REG_ADC_PWR_MAN_DFLT (0xFC) #define ES8388_BIT_PDNAINL (1<<7) #define ES8388_BIT_PDNAINR (1<<6) #define ES8388_BIT_PDNADCL (1<<5) #define ES8388_BIT_PDNADCR (1<<4) #define ES8388_BIT_PDNMICB (1<<3) #define ES8388_BIT_PDNADCBIASG (1<<2) #define ES8388_BIT_FLASHLP (1<<1) #define ES8388_BIT_INT1LP (1<<0) #define ES8388_REG_DAC_PWR_MAN (0x04) // Default 1100 0000 #define ES8388_REG_DAC_PWR_MAN_DFLT (0xC0) #define ES8388_BIT_PDNDACL (1<<7) #define ES8388_BIT_PDNDACR (1<<6) #define ES8388_BIT_LOUT1_EN (1<<5) #define ES8388_BIT_ROUT1_EN (1<<4) #define ES8388_BIT_LOUT2_EN (1<<3) #define ES8388_BIT_ROUT2_EN (1<<2) #define ES8388_REG_CHIP_LOWPWR1 (0x05) // Default 0000 0000 #define ES8388_REG_CHIP_LOWPWR1_DFLT (0x00) #define ES8388_BIT_LPDACL (1<<7) #define ES8388_BIT_LPDACR (1<<6) #define ES8388_BIT_LPOUT1 (1<<5) #define ES8388_BIT_LPOUT2 (1<<3) #define ES8388_REG_CHIP_LOWPWR2 (0x06) // Default 0000 0000 #define ES8388_REG_CHIP_LOWPWR2_DFLT (0x00) #define ES8388_BIT_LPPGA (1<<7) #define ES8388_BIT_LPMIX (1<<6) #define ES8388_BIT_LPADCVRP (1<<1) #define ES8388_BIT_LPDACVRP (1<<0) #define ES8388_REG_ANALOG_VOLT_MAN (0x07) // Default 0111 1100 #define ES8388_REG_ANALOG_VOLT_MAN_DFLT (0x7C) #define ES8388_BIT_VSEL_MASK (0x7C) #define ES8388_REG_MASTER_MODE_CTRL (0x08) // Default 1000 0000 #define ES8388_REG_MASTER_MODE_CTRL_DFLT (0x80) #define ES8388_BIT_MSC (1<<7) #define ES8388_BIT_MCLKDIV2 (1<<6) #define ES8388_BIT_BCLKINV (1<<5) #define ES8388_BCLKDIVAUTO (0x00) #define ES8388_BCLKDIV1 (0x01) #define ES8388_BCLKDIV2 (0x02) #define ES8388_BCLKDIV3 (0x03) #define ES8388_BCLKDIV4 (0x04) #define ES8388_BCLKDIV6 (0x05) #define ES8388_BCLKDIV8 (0x06) #define ES8388_BCLKDIV9 (0x07) #define ES8388_BCLKDIV11 (0x08) #define ES8388_BCLKDIV12 (0x09) #define ES8388_BCLKDIV16 (0x0A) #define ES8388_BCLKDIV18 (0x0B) #define ES8388_BCLKDIV22 (0x0C) #define ES8388_BCLKDIV24 (0x0D) #define ES8388_BCLKDIV33 (0x0E) #define ES8388_BCLKDIV36 (0x0F) #define ES8388_BCLKDIV44 (0x10) #define ES8388_BCLKDIV48 (0x11) #define ES8388_BCLKDIV66 (0x12) #define ES8388_BCLKDIV72 (0x13) #define ES8388_BCLKDIV5 (0x14) #define ES8388_BCLKDIV10 (0x15) #define ES8388_BCLKDIV15 (0x16) #define ES8388_BCLKDIV17 (0x17) #define ES8388_BCLKDIV20 (0x18) #define ES8388_BCLKDIV25 (0x19) #define ES8388_BCLKDIV30 (0x1A) #define ES8388_BCLKDIV32 (0x1B) #define ES8388_BCLKDIV34 (0x1C) #define ES8388_BCLKDIV(x) ((x)&0x1F) #define ES8388_REG_ADC_CTRL1 (0x09) // Default 0000 0000 #define ES8388_REG_ADC_CTRL1_DFLT (0x00) #define ES8388_MICAMPL_MASK (0xF0) #define ES8388_MICAMPL_SHIFT (0x04) #define ES8388_MICAMPR_MASK (0x0F) #define ES8388_MICAMPR_SHIFT (0x00) #define ES8388_REG_ADC_CTRL2 (0x0A) // Default 0000 0000 #define ES8388_REG_ADC_CTRL2_DFLT (0x00) #define ES8388_LINSEL_MASK (0xC0) #define ES8388_LINSEL_SHIFT (0x06) #define ES8388_INPUT1 (0x00) #define ES8388_INPUT2 (0x01) #define ES8388_INPUTDIFF (0x03) #define ES8388_LINSEL(x) (((x)<begin(); ctrlBus->setClock(100000); bool reply = true; reply = writeReg(ES8388_REG_MASTER_MODE_CTRL, 0x00); // set to slave mode reply &= writeReg(ES8388_REG_CHIP_PWR_MAN, 0xF3); // power down reply &=writeReg(ES8388_REG_DAC_CTRL21, ES8388_BIT_SLRCK); // DACLRC = ADCLRC reply &=writeReg(ES8388_REG_CHIP_CTRL1, ES8388_VMIDSEL_5K | ES8388_BIT_ENREF); // 50k divider, reply &=writeReg(ES8388_REG_CHIP_CTRL2, 0x40); // low power modes off, bit6 not defined? based on default value reply &=writeReg(ES8388_REG_ADC_PWR_MAN, 0x00); // power up ADC, turn off the PDNMICB? reply &=writeReg(ES8388_REG_DAC_PWR_MAN, ES8388_BIT_LOUT1_EN | ES8388_BIT_ROUT1_EN); // enable LR1 if (reply == false) { DBG_SERIAL.println("Codec i2c error"); return false; } switch (cfg) { case ES8388_CFG_LINEIN_DIFF: writeReg(ES8388_REG_ADC_CTRL2, ES8388_LINSEL(ES8388_INPUTDIFF) | // LIN=LIN1-RIN1 (ADCCTRL3[7] DS = 0) ES8388_RINSEL(ES8388_INPUTDIFF) | // RIN=LIN2-RIN2 (DSR = 1) ES8388_BIT_DSSEL | // use different DSR settings for L and R ES8388_BIT_DSR); // DS setting for channel R break; case ES8388_CFG_LINEIN_SINGLE_ENDED: writeReg(ES8388_REG_ADC_CTRL2, ES8388_LINSEL(ES8388_INPUT1) | // LIN=LIN1-RIN1 (ADCCTRL3[7] DS = 0) ES8388_RINSEL(ES8388_INPUT1)); // RIN=LIN2-RIN2 (DSR = 1) break; default: writeReg(ES8388_REG_ADC_CTRL2, ES8388_LINSEL(ES8388_INPUT1) | // LIN=LIN1-RIN1 (ADCCTRL3[7] DS = 0) ES8388_RINSEL(ES8388_INPUT1)); // RIN=LIN2-RIN2 (DSR = 1) break; } writeReg(ES8388_REG_ADC_CTRL6, 0x00); // disable HPF // 0dB writeReg(ES8388_REG_ADC_CTRL4, ES8388_ADCWL(ES8388_ADCWL_32BIT)); // 24bit writeReg(ES8388_REG_ADC_CTRL5, ES8388_ADCFSRATIO(ES8388_FSRATIO_256)); // 256*Fs, single speed // ADC digital volume writeReg(ESP8388_LADCVOL, 0x00); // 0dB writeReg(ESP8388_RADCVOL, 0x00); // 0dB // DAC setup writeReg(ES8388_REG_DAC_CTRL1, ES8388_DACWL(ES8388_DACWL_32BIT)); // 24bit writeReg(ES8388_REG_DAC_CTRL2, ES8388_DACFSRATIO(ES8388_FSRATIO_256)); // 256*Fs single speed // DAC digital volume writeReg(ES8388_REG_DAC_CTRL4, 0x00); // 0dB writeReg(ES8388_REG_DAC_CTRL5, 0x00); // 0dB // Mixer Setup writeReg(ES8388_REG_DAC_CTRL16, ES8388_LMIXSEL(ES8388_LMIXSEL_ADCL_P) | ES8388_RMIXSEL(ES8388_RMIXSEL_ADCR_P)); writeReg(ES8388_REG_DAC_CTRL17, ES8388_BIT_LD2LO); // LDAC to left mixer enable, gain 0dB writeReg(ES8388_REG_DAC_CTRL20, ES8388_BIT_RD2RO); // RDAC to right mixer enable, gain 0dB // R L OUT volume dacGain = 0x1E; writeReg(ES8388_LOUT1VOL, dacGain); // L1 0dB writeReg(ES8388_ROUT1VOL, dacGain); // R1 0dB // optimize A/D conversion for 1/4 Vrms range optimizeConversion(0); writeReg(ES8388_REG_CHIP_PWR_MAN, 0x00); // Power up DEM and STM // ALC config // writeReg(ES8388_REG_ADC_CTRL10, ES8388_ALCSEL(ES8388_ALCSEL_LR) | // ALC OFF // ES8388_MAXGAIN(ES8388_MAXGAIN_M0_5DB) | // max gain -0.5dB // ES8388_MINGAIN(ES8388_MINGAIN_M12DB)); // min gain -12dB // writeReg(ES8388_REG_ADC_CTRL11, ES8388_ALCLVL(0x0A)); // target gain -1.5dB, hold time=0 // writeReg(ES8388_REG_ADC_CTRL12, ES8388_ALCATK(0x02) | // ALC limiter attack time 90.8us // ES8388_ALCDCY(0x01)); // ALC limiter decay time 182us // writeReg(ES8388_REG_ADC_CTRL13, ES8388_BIT_ALCMODE | ES8388_WINSIZE(0x06)); // Limiter mode, no ZC, 96*16 samples peak window // writeReg(ES8388_REG_ADC_CTRL14, 0x00); // disable noise gate //writeReg(ES8388_REG_ADC_CTRL14, ES8388_NGTH(0x1F) | ES8388_NGG(ES8388_NGG_ADCMUTE)| ES8388_BIT_NGAT_EN); // ADC PGA gain //writeReg(ES8388_REG_ADC_CTRL1, 0x00); configured = true; return true; } void AudioControlES8388_F32::optimizeConversion(uint8_t range) { uint8_t ingain[] = {0, 2, 4, 6, 8}; // 0db, 6dB, 12dB, 18dB, 24dB uint8_t outvol[] = {30, 26, 22, 18, 14}; // 0db, -6dB, -12dB, -18dB, -24dB if (range < 0) range = 0; if (range > 4) range = 4; volume(outvol[range]); setInGain(ingain[range]); } // get and set the output level (analog gain) // vol = 0-31 void AudioControlES8388_F32::volume(uint8_t vol) { if (vol > 30) vol = 30; writeReg(ES8388_REG_DAC_CTRL24, vol); // LOUT1VOL writeReg(ES8388_REG_DAC_CTRL25, vol); // ROUT1VOL } bool AudioControlES8388_F32::volume(float n) { n = constrain(n, 0.0f, 1.0f); uint8_t vol = n * 30.99f; if (vol > 30) vol = 30; writeReg(ES8388_REG_DAC_CTRL24, vol); // LOUT1VOL writeReg(ES8388_REG_DAC_CTRL25, vol); // ROUT1VOL return true; } uint8_t AudioControlES8388_F32::getOutVol() { uint8_t vol; readReg(ES8388_REG_DAC_CTRL24, &vol); return vol; } bool AudioControlES8388_F32::setInGain(uint8_t gain) { if (gain > 8) gain = 8; uint8_t temp; temp = gain << 4; temp = temp | gain; return writeReg(ES8388_REG_ADC_CTRL1, temp); } uint8_t AudioControlES8388_F32::getInGain() { uint8_t temp; readReg(ES8388_REG_ADC_CTRL1, &temp); temp = (temp & 0xF0) >> 4; return temp; } void AudioControlES8388_F32::set_noiseGate(float thres) { uint8_t thres_val = constrain(thres, 0.0f, 1.0f) * 31.99f; DBG_SERIAL.printf("Gate: %d\r\n", thres_val); writeReg(ES8388_REG_ADC_CTRL14, ES8388_NGTH(thres_val) | ES8388_NGG(ES8388_NGG_ADCMUTE)| ES8388_BIT_NGAT_EN); } // bypassed the analog input to the output, disconnect the digital i / o bool AudioControlES8388_F32::analogBypass(bool bypass) { bool res = true; if (bypass) { res = writeReg(ES8388_REG_DAC_CTRL17, ES8388_BIT_LI2LO | ES8388_LI2LOVOL(ES8388_VOL_0DB)); res &= writeReg(ES8388_REG_DAC_CTRL20, ES8388_BIT_RI2RO | ES8388_RI2ROVOL(ES8388_VOL_0DB)); } else { res = writeReg(ES8388_REG_DAC_CTRL17, ES8388_BIT_LD2LO | ES8388_LI2LOVOL(ES8388_VOL_0DB)); res &= writeReg(ES8388_REG_DAC_CTRL20, ES8388_BIT_RD2RO | ES8388_RI2ROVOL(ES8388_VOL_0DB)); } return res; } // bypassed the analog input to the output, disconnect the digital input, preserve the digital output connection bool AudioControlES8388_F32::analogSoftBypass(bool bypass) { bool res = true; if (bypass) { res &= writeReg(ES8388_REG_DAC_CTRL17, ES8388_BIT_LI2LO | // Lin in on ES8388_BIT_LD2LO | // L Dac on ES8388_LI2LOVOL(ES8388_VOL_0DB)); // Lin gain 0dB res &= writeReg(ES8388_REG_DAC_CTRL20, ES8388_BIT_RI2RO | // Rin in on ES8388_BIT_RD2RO | // R Dac on ES8388_RI2ROVOL(ES8388_VOL_0DB)); // Rin gain 0dB } else { res = writeReg(ES8388_REG_DAC_CTRL17, ES8388_BIT_LD2LO | ES8388_LI2LOVOL(ES8388_VOL_0DB)); res &= writeReg(ES8388_REG_DAC_CTRL20, ES8388_BIT_RD2RO | ES8388_RI2ROVOL(ES8388_VOL_0DB)); } return res; } bool AudioControlES8388_F32::writeReg(uint8_t addr, uint8_t val) { ctrlBus->beginTransmission(i2cAddr); ctrlBus->write(addr); ctrlBus->write(val); return ctrlBus->endTransmission() == 0; } bool AudioControlES8388_F32::readReg(uint8_t addr, uint8_t *valPtr) { ctrlBus->beginTransmission(i2cAddr); ctrlBus->write(addr); if (ctrlBus->endTransmission(false) != 0) return false; if (ctrlBus->requestFrom((int)i2cAddr, 1) < 1) return false; *valPtr = ctrlBus->read(); return true; } uint8_t AudioControlES8388_F32::modifyReg(uint8_t reg, uint8_t val, uint8_t iMask) { uint8_t val1; val1 = (readReg(reg, &val1) & (~iMask)) | val; if (!writeReg(reg, val1)) return 0; return val1; }