sc7-default-firmware/codec.py

65 lines
3.0 KiB
Python
Raw Permalink Normal View History

2023-11-03 09:47:33 -07:00
from machine import Pin, SPI, PWM, I2C, I2S, PWM, freq
import time
import rp2
import machine
import pin_defs
import pio_defs
import pio_code
## I2C bus address
ak4619_addr = const(0x10)
READ_FIFO = pio_defs.PIO0_BASE + pio_defs.RXF0_OFFSET ## 0, 0
WRITE_FIFO = pio_defs.PIO0_BASE + pio_defs.TXF1_OFFSET ## 0, 1
class Codec():
def __init__(self):
# RPi I2S doesn't have master clock -- we make one with PWM
# 125000000 / 16 = 7.8125 MHz master clock
# 250_000_000 / 16 = 7.8125 MHz master clock
self.MASTER_CLOCK_HZ = freq() // 32
# fs sample clock = MCLK / 256 = 30517.578 Hz
self.mclk = Pin(pin_defs.mclk, Pin.OUT)
self.mclk_pwm = PWM(self.mclk, freq=self.MASTER_CLOCK_HZ, duty_u16=32768)
self.bit_clock = Pin(pin_defs.bit_clock, Pin.OUT, value=0) ## fs / 32
self.lr_clock = Pin(pin_defs.lr_clock, Pin.OUT, value=0) ## fs
self.sd_in = Pin(pin_defs.sd_in, Pin.IN) ## In 3/4 (Y=L, X=R)
self.sd_out = Pin(pin_defs.sd_out, Pin.OUT, value=0) ## Out 1/2 (Y=L, X=R)
self.pdn = Pin(pin_defs.pdn, Pin.OUT, value=0) ## Power down on low
self.i2s_read_sm = rp2.StateMachine(0, pio_code.i2s_read_pio, freq=self.MASTER_CLOCK_HZ // 2, sideset_base=self.bit_clock, in_base=self.sd_in)
self.i2s_write_sm = rp2.StateMachine(1, pio_code.i2s_write_pio, freq=self.MASTER_CLOCK_HZ // 2, out_base=self.sd_out)
self.start()
def deinit(self):
self.i2s_read_sm.active(0)
self.i2s_write_sm.active(0)
self.mclk_pwm.deinit()
self.pdn.value(0)
## Manually resync the PIO state machines so they run in cycle
def start(self):
self.mclk_pwm = PWM(self.mclk, freq=self.MASTER_CLOCK_HZ, duty_u16=32768)
machine.mem32[pio_defs.PIO0_BASE] = (0b1111 << pio_defs.CLKDIV_RESTART_BIT) ## reset all clock dividers
machine.mem32[pio_defs.PIO0_BASE] = (0b1111 << pio_defs.SM_ENABLE_BIT) ## enable all simultaneously to sync up
self.config_i2c()
def config_i2c(self):
self.i2c = I2C(0, scl=Pin(pin_defs.i2c_scl), sda=Pin(pin_defs.i2c_sda), freq=400_000)
## Initialize AK4619 registers
## PDN starts 0, when goes high, enters config mode after 10 ms -- datasheet
self.pdn.value(1)
time.sleep_ms(10)
## Config for 16-bit samples & 16-bit slots
self.i2c.writeto(ak4619_addr, bytes([0x01, 0x3A])) # MSB Justified, 16 bit slot and read data on falling bit-clock
self.i2c.writeto(ak4619_addr, bytes([0x02, 0x0A])) # 16 bit data on in and out
## Config single-ended input on 3 & 4
self.i2c.writeto(ak4619_addr, bytes([0x0B, 0x05]))
## slow ADC filters -- need to look into this later?
self.i2c.writeto(ak4619_addr, bytes([0x0A, 0x22]))
self.i2c.writeto(ak4619_addr, bytes([0x0D, 0x06]))
self.i2c.writeto(ak4619_addr, bytes([0x00, 0x37])) ## Power on, release reset bit