Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Dar-Scott opened this issue Feb 20, 2020 · 7 comments
Open

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

Dar-Scott opened this issue Feb 20, 2020 · 7 comments
Labels
Milestone

Comments

@Dar-Scott
Copy link

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
Copy link
Author

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
Copy link
Author

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
Copy link
Author

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

  • M4 RX/D0
  • STM D6 (but I2S is not ready yet)

@Dar-Scott
Copy link
Author

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
Copy link
Author

Related:
This is related to these possible enhancements:

  • Master/Slave MCK
  • Master/Slave SCK (BCK) and WS (LRCK)
  • Run idle after playing where SCK and WS continue with +0 data, where a new play() can come in without missing a beat (if the sample rate is unchanged)
  • Allow play() to queue a playable which starts at the next WS (LRCK) after the current playable (if the sample rate is unchanged).
  • Allow other bits per sample.

This is related to reported pops and buffer starvation.

@Dar-Scott
Copy link
Author

Dar-Scott commented Feb 20, 2020

You may light your flaming arrows now.

@dhalbert dhalbert added this to the Long term milestone Mar 12, 2020
@dhalbert dhalbert added the audio label Mar 12, 2020
jepler pushed a commit to jepler/circuitpython that referenced this issue Sep 14, 2022
Prior to this commit, excuting this code:

    i2c = I2C(1, I2C.CONTROLLER, dma=True)
    i2c.send(data, addr=i2c_addr)

the call to i2c.send() does not return and the board needs a reset.  This
code works when dma=False.

According to the specification, I2Cx_EV_IRQHandler should:
- Write DR to address when Start condition generated.
- Clear ADDR by reading SR2 after reading SR2 when address sent.

These processes are included in HAL_I2C_EV_IRQHandler(), however the
firmware size increses about 2KB if HAL_I2C_EV_IRQHandler is called.  This
commit adds above processes to i2c_ev_irq_handler, and increases firmware
by less than 100 bytes.

Fixes issue adafruit#2643.
@dhalbert dhalbert changed the title Add MCK audio timing output to I2S Add MCK (MCLK) audio timing output to I2S Oct 28, 2023
@dhalbert
Copy link
Collaborator

MCLK support was added to mimxrt10xx in #8291.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants