Files
mixly3-server/mixly/boards/default/micropython_esp32s3/build/lib/es8374.py

196 lines
7.7 KiB
Python

# -*- 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