# -*- coding: UTF-8 -*- import time from micropython import const _ES_MODULE_ADC = const(0x01) _ES_MODULE_DAC = const(0x02) _ES_MODULE_ADC_DAC = const(0x03) _ES_MODULE_LINE = const(0x04) _BIT_LENGTH_16BITS = const(0x03) _FMT_I2S_NORMAL = const(0x00) _I2S_MODE_SLAVE = const(0x00) _ADC_INPUT_LINE = const(0x01) _DAC_OUTPUT_ALL = const(0x02) _LCLK_DIV = const(256) _MCLK_DIV = const(0x04) class ES8374: def __init__(self, i2c_bus=None, i2c_addr=0x10, gain=5, pga_en=1): self.i2c_bus = i2c_bus self.i2c_addr = i2c_addr self.stop() self.init_reg(_I2S_MODE_SLAVE, ((_BIT_LENGTH_16BITS << 4) | _FMT_I2S_NORMAL), _DAC_OUTPUT_ALL, _ADC_INPUT_LINE) self.mic_gain(gain) self.pga_enable(pga_en) self.configI2SFormat(_ES_MODULE_ADC_DAC, _FMT_I2S_NORMAL) def _readReg(self, regAddr): return self.i2c_bus.readfrom_mem(self.i2c_addr, regAddr, 1)[0] def _writeReg(self, regAddr, data): self.i2c_bus.writeto_mem( self.i2c_addr, regAddr, data.to_bytes(1, 'little')) def init_reg(self, ms_mode, fmt, out_channel, in_channel): self._writeReg(0x00, 0x3F) # IC Rst start self._writeReg(0x00, 0x03) # IC Rst stop self._writeReg(0x01, 0x7F) # IC clk on # M ORG 7F self._writeReg(0x0f, (self._readReg(0x0F) & 0x7f) | (ms_mode << 7)) # CODEC IN I2S SLAVE MODE self._writeReg(0x6F, 0xA0) # pll set:mode enable self._writeReg(0x72, 0x41) # pll set:mode set self._writeReg(0x09, 0x01) # pll set:reset on ,set start self._writeReg(0x0C, 0x22) # pll set:k self._writeReg(0x0D, 0x2E) # pll set:k self._writeReg(0x0E, 0xC6) # pll set:k self._writeReg(0x0A, 0x3A) # pll set: self._writeReg(0x0B, 0x07) # pll set:n self._writeReg(0x09, 0x41) # pll set:reset off ,set stop self.i2sConfigClock() self._writeReg(0x24, 0x08) # adc set self._writeReg(0x36, 0x00) # dac set self._writeReg(0x12, 0x30) # timming set self._writeReg(0x13, 0x20) # timming set self.configI2SFormat(_ES_MODULE_ADC, fmt) self.configI2SFormat(_ES_MODULE_DAC, fmt) self._writeReg(0x21, 0x50) # adc set: SEL LIN1 CH+PGAGAIN=0DB self._writeReg(0x22, 0xFF) # adc set: PGA GAIN=0DB self._writeReg(0x21, 0x14) # adc set: SEL LIN1 CH+PGAGAIN=18DB self._writeReg(0x22, 0x55) # pga = +15db # set class d divider = 33, to avoid the high frequency tone on laudspeaker self._writeReg(0x08, 0x21) self._writeReg(0x00, 0x80) # IC START time.sleep(0.05) self._writeReg(0x25, 0x00) # ADCVOLUME on self._writeReg(0x38, 0x00) # DACVOLUME on self._writeReg(0x14, 0x8A) # IC START self._writeReg(0x15, 0x40) # IC START self._writeReg(0x1A, 0xA0) # monoout set self._writeReg(0x1B, 0x19) # monoout set self._writeReg(0x1C, 0x90) # spk set self._writeReg(0x1D, 0x01) # spk set self._writeReg(0x1F, 0x00) # spk set self._writeReg(0x1E, 0x20) # spk on self._writeReg(0x28, 0x70) # alc set 0x70 # self._writeReg(0x26, 0x4E)# alc set # self._writeReg(0x27, 0x10)# alc set # self._writeReg(0x29, 0x00)# alc set # self._writeReg(0x2B, 0x00)# alc set self._writeReg(0x25, 0x00) # ADCVOLUME on self._writeReg(0x38, 0x00) # DACVOLUME on self._writeReg(0x37, 0x30) # dac set # SEL:GPIO1=DMIC CLK OUT+SEL:GPIO2=PLL CLK OUT self._writeReg(0x6D, 0x60) self._writeReg(0x71, 0x05) # for automute setting self._writeReg(0x73, 0x70) # 0x3c Enable DAC and Enable Lout/Rout/1/2 self.configDACOutput(out_channel) # 0x00 LINSEL & RINSEL, LIN1/RIN1 as ADC Input DSSEL,use one DS Reg11 DSR, LINPUT1-RINPUT1 self.configADCInput(in_channel) self.voice_volume(95) self._writeReg(0x37, 0x00) # dac set ''' reg = self._readReg(0x1a) # disable lout reg |= 0x08 self._writeReg(0x1a, reg) reg &= 0xdf self._writeReg(0x1a, reg) self._writeReg(0x1D, 0x12) # mute speaker self._writeReg(0x1E, 0x20) # disable class d reg = self._readReg(0x15) # power up dac reg &= 0xdf self._writeReg(0x15, reg) reg = self._readReg(0x1a) # disable lout reg |= 0x20 self._writeReg(0x1a, reg) reg &= 0xf7 self._writeReg(0x1a, reg) self._writeReg(0x1D, 0x02) # mute speaker self._writeReg(0x1E, 0xa0) # disable class d self.voice_mute(0) ''' def stop(self): self.voice_mute(1) self._writeReg(0x1a, self._readReg(0x1a) | 0x08) self._writeReg(0x1a, self._readReg(0x1a) & 0xdf) self._writeReg(0x1D, 0x12) # mute speaker self._writeReg(0x1E, 0x20) # disable class d self._writeReg(0x15, self._readReg(0x15) | 0x20) self._writeReg(0x10, self._readReg(0x10) | 0xc0) self._writeReg(0x21, self._readReg(0x21) | 0xc0) def i2sConfigClock(self): self._writeReg(0x0f, (self._readReg(0x0F) & 0xe0) | _MCLK_DIV) # ADCFsMode,singel SPEED,RATIO=256 self._writeReg(0x06, _LCLK_DIV >> 8) # ADCFsMode,singel SPEED,RATIO=256 self._writeReg(0x07, _LCLK_DIV & 0xFF) def configI2SFormat(self, mode, fmt): fmt_tmp = ((fmt & 0xf0) >> 4) fmt_i2s = fmt & 0x0f if (mode == _ES_MODULE_ADC or mode == _ES_MODULE_ADC_DAC): reg = self._readReg(0x10) reg &= 0xfc self._writeReg(0x10, (reg | fmt_i2s)) self.setBitsPerSample(mode, 3) if (mode == _ES_MODULE_DAC or mode == _ES_MODULE_ADC_DAC): reg = self._readReg(0x11) reg &= 0xfc self._writeReg(0x11, (reg | fmt_i2s)) self.setBitsPerSample(mode, 3) # set Bits Per Sample def setBitsPerSample(self, mode, bit_per_smaple): bits = bit_per_smaple & 0x0f if (mode == _ES_MODULE_ADC or mode == _ES_MODULE_ADC_DAC): reg = self._readReg(0x10) reg &= 0xe3 self._writeReg(0x10, (reg | (bits << 2))) if (mode == _ES_MODULE_DAC or mode == _ES_MODULE_ADC_DAC): reg = self._readReg(0x11) reg &= 0xe3 self._writeReg(0x11, (reg | (bits << 2))) def configDACOutput(self, output): self._writeReg(0x1d, 0x02) reg = self._readReg(0x1c) # set spk mixer reg |= 0x80 self._writeReg(0x1c, reg) self._writeReg(0x1D, 0x02) # spk set self._writeReg(0x1F, 0x00) # spk set self._writeReg(0x1E, 0xA0) # spk on def configADCInput(self, input): reg = self._readReg(0x21) reg = (reg & 0xcf) | 0x24 self._writeReg(0x21, reg) def mic_volume(self, volume=None): if volume is None: return round(100 - self._readReg(0x25) * 100 / 192) else: self._writeReg(0x25, (100 - volume) * 192 // 100) def voice_volume(self, volume=None): if volume is None: return round(100 - self._readReg(0x38) * 100 / 192) else: self._writeReg(0x38, (100 - volume) * 192 // 100) def voice_mute(self, enable=None): if enable is None: return True if self._readReg(0x36) & 0x40 else False else: self._writeReg(0x36, (self._readReg(0x36) & 0xdf) | (enable << 5)) def mic_gain(self, gain): gain_n = max(min(gain, 15), 0) self._writeReg(0x22, (gain_n | (gain_n << 4))) # MIC PGA -3.5db ~ 24db def pga_enable(self, enable): self._writeReg(0x21, (self._readReg(0x21) & 0xfb) | (enable << 2)) # MIC PGA 0db or 15db