adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
MIT License
3.97k stars 1.16k forks source link

audiobusio.I2S main clock not implemented #9176

Open berkut0 opened 3 months ago

berkut0 commented 3 months ago

Hello everyone.

I'm trying to bring the WM8988 audio codec to life on my own development board. It's a bit old, but there's still a lot of it around. My main goal is to get some sound out of it. Now that I've tinkered with the I2C registers, I've got some clicking noises on reboot - I'm definitely on the right track.

But! I noticed that the WM8988 codec should be driven by the main clock, which should be around 12 MHz. Nice, I thought it would be easy to get this, as I saw this clock in the I2S circuitpython driver.

I tried setting the main_clock parameter and got: NotImplementedError: main_clock

So I have a few questions:

  1. Is there a way to get 12MHz (and above) from the I2S object for the main clock?
  2. Do I understand correctly that this is the clock I'm talking about?
  3. Is there any chance of such an implementation appearing?

bit_clock at 48000 sample rate gives 1.53MHz on the oscilloscope.

I tried to make a PWM signal on an arbitrary pin, but I assume that this can't work because the signal has to be synchronous. Or am I wrong?

I am using an RP2040-Zero board with 9.1 beta circuitpython.

berkut0 commented 3 months ago

I'm also trying to understand what could throw this exception and I suspect it might be a bug.

https://github.com/adafruit/circuitpython/blob/main/shared-bindings/audiobusio/I2SOut.c

todbot commented 3 months ago

I think main_clock is only implemented on iMXRT and ESP32. The audiobusio.I2Sout docs should reflect that.

berkut0 commented 3 months ago

Thanks, that explains it.

The audiobusio.I2Sout docs should reflect that.

Not sure where to find this.

Basically, the rest of the questions are relevant.

todbot commented 3 months ago

Not sure where to find this.

It's embedded in the C code for I2SOut.c that you linked. I found that surprising too.

berkut0 commented 3 months ago

Yeah, I noticed that too. I can't quite work out what's wrong.

How cool would it be if I could generate main_clock and use the synthio functionality on the rp2040 on my 4 channel board! For example, my board has 4 inputs! I want to try and implement a reverb or delay.

The main problem is that it's never been done before - that's my hypothesis. Maybe we can have a look at the source code and I can try to recompile it?

dhalbert commented 2 months ago

On RP2040, I2SOut is implemented with a PIO program: https://github.com/adafruit/circuitpython/blob/main/ports/raspberrypi/common-hal/audiobusio/I2SOut.c. So the main clock functionality would probably be added to that. This might be such an implementation: https://github.com/malacalypse/rp2040_i2s_example

berkut0 commented 2 months ago

For anyone who might be interested. After a while I managed to configure the chip and listen to the sound. The clock was supplied by PWM, the target frequency was 12MHz (according to the "USB mode"), but the real frequency is between 11.834 and 11.695, which seems ok. It's not necessary to have an exact frequency, I've tried different ones and they work. Probably has some effect, but not important in non-critical applications.

I feed in a 220 hertz sine wave and see a frequency spread of about 3.5 hertz on the oscilloscope. This is probably just due to frequency irregularities on the main clock. I can also see that the sine wave is not very smooth and is prone to aliasing. The conclusion is obvious - if you are designing a board with a codec, make sure you get the main clock from an external source. But it may be useful for tests.