adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.11k stars 1.22k forks source link

Add MCK (MCLK) audio timing output to I2S #2643

Open Dar-Scott opened 4 years ago

Dar-Scott commented 4 years ago

CircuitPython does not implement MCK out for I2S, digital audio, which is fine for audio DACs that create their own. However, other audio DACs require this clock. MCK out should be implemented.

Dar-Scott commented 4 years ago

Names: The I2S signals are SCK (BCK), WS (LRCK) and SD. There is also an optional MCK constrained to a multiple of WS. The SAM D5x/E5x Family Data Sheet uses the names SCK, FS, SDO/SDI and MCK, respectively. The STM32 data sheet uses the names CK, FS, SD and MCK.

Need: Many audio codecs and DACs need an MCK. The following are a few 3.3V+5V audio DACs that need an MCK. WM8741 CS4398 AK4495EQ/SEQ PCM1792

Next: Implementability on CircuitPython boards. API considerations. Related enhancements and quirks.

Noob: There is no reason to assume I know a lot about this.

Dar-Scott commented 4 years ago

The needs for MCK frequencies are particular multiples of the WS (LRCK) frequency, typically 256. Some DACs have a fixed multiple. Some DACs can handle several multiples. For 16-bit samples, the Cirrus Logic CS4398 can take 64x, 96x, or any multiple of those up to 1152x.

MCK must be derived from the same clock source as SCK (BCK) but does not have to have any definite phase relationship with it. That is, it can't drift off. Implementations typically derive both MCK and the other I2S clocks from the same source. That source is typically created with a PLL with divider/multiplier to be useful for common sample rates.

An alternative approach would be to use a fixed MCK frequency and then change the multiplier as needed.

There might need to be some flexibility in when the MCK is running, depending of the what DACs are part of initial testing.

Dar-Scott commented 4 years ago

Implementability: I think pins are available for MCK on a couple Feather Express boards.

Dar-Scott commented 4 years ago

API: Here are a couple approaches.

Both add an optional MCK pin assignment to audiobusio.I2SOut() with a default of None.

  1. Add optional frequency (Hz) to audiobusio.I2SOut() which is required if an MCK pin is not None. Typically, this will have values like 12_288_000, which can be the default value. This would be output even when there is no audio playing. This approach does not change the API for play(), except for a reminder of playing at a rate with the appropriate MCK:LRCK ratio.
  2. Add an optional MCK factor(MCK:LRCK ratio) to play() with a default value of None or 256.
Dar-Scott commented 4 years ago

Related: This is related to these possible enhancements:

This is related to reported pops and buffer starvation.

Dar-Scott commented 4 years ago

You may light your flaming arrows now.

dhalbert commented 1 year ago

MCLK support was added to mimxrt10xx in #8291.