WM8960 Breakout - No ADC data over I2S

Hello everyone,

I am trying to setup the WM8960 (the Sparkfun breakout board) as an ADC that transmits data over I2S to an STM32F4 nulceo board, and I am having a very hard time.

I’ve copied over some (ok, a lot) of the code from Sparkfun’s W8960 Arduino library and am able to setup the codec via I2C, see the following (incomplete) PulseView session:

The codec seems to ACK, so I’m guessing that the I2C setup is OK.
Looking at the datasheet and the flow of the signal from L/RINPUT2, I think that I’ve setup all the correct register for the signal to reach the ADC.
I’ve included the full initialization code at this pastebin link.

For the I2S setup, the STM32 is configured as a Half Duplex Master Receive with a sampling rate of 48khz, for now I have a very simple polling code that issues an HAL_I2S_Receive every second and puts the data in a buffer; unfortunately the I2S_SD/ADAT signal is staying silent.

The two following oscilloscope capture show that the STM32 is outputing the correct I2S signals for Clock and WordSelect respectively (See next post for these images, I can’t put more than 1 image in this post since this account is new).

I think the clock settings I’ve set for the WM8960 are correct, given that the crystal on the breakout board is 24mhz (according to sparkfun’s schematics), I’ve set SYSCLKDIV to “Divide by 2” (to get a 12mhz SYSCLK), the rest of the clock parameters are the same as this example extracted from the datasheet (see post reply).

I’m not sure how to proceed to debug this issue further; any insight will help… I’m going a little crazy :stuck_out_tongue:

Thank you !

I2S_CK/BCL and I2S_WS/ALRC

.

Hi - I’m very interested in your project as I’ve been working to a similar goal: DSP communications experiments on a fast enough processor using the WM8960 as the ADC/DAC as it can drive audio line in/line out voltage ranges. But I was pretty sure my skills aren’t up to porting the I2C control code like you are, so my plan has been to use the Sparkfun ESP32 board I2C to configure the WM8960 , recieve and send the I2S ADC/DAC streams from a higher speed DSP processor.

Maybe this helps: I just captured the I2C traffic between the ESP32 and the WM8960 running the Example_08_I2S_Passthrough example code. I exported the logic analyzer anotation file to a text file and I will try to up load. Below is the first part of what I captured.

Here’s a link to the file: I2C capture from Ex 08

I’m thinking you could either use this to see what’s missing in your I2C commands, or perhaps easier: start with the Sparkfun example on the ESP and modify it to do what you are doing with the nucleo. When it works there, capture the I2C and compare it to what you are sending out with the nucleo. If you don’t have an ESP 32 but wanted to provide a code fragment (using the Sparkfun library calls), I could run it for you and post the capture.

If you were willing to share the code that makes the WM8960 work from the nucleo, I’d likely use it for what I’m trying to do instead of my intended somewhat complicated and cumbersome workaround.

Thanks

17336029-17337717 I²C: Address/Data: Address write: 1A
17335787-17335787 I²C: Address/Data: Start
17337717-17337958 I²C: Address/Data: Write
17337964-17338205 I²C: Address/Data: ACK
17338330-17338330 I²C: Address/Data: Stop
17340008-17340008 I²C: Address/Data: Start
17340249-17341938 I²C: Address/Data: Address write: 1A
17341938-17342179 I²C: Address/Data: Write
17342193-17342434 I²C: Address/Data: ACK
17342435-17344364 I²C: Address/Data: Data write: 1E
17344365-17344606 I²C: Address/Data: ACK
17344606-17346537 I²C: Address/Data: Data write: 80
17346541-17346783 I²C: Address/Data: ACK
17346907-17346907 I²C: Address/Data: Stop
17349345-17349345 I²C: Address/Data: Start
17349587-17351276 I²C: Address/Data: Address write: 1A
17351276-17351518 I²C: Address/Data: Write
17351531-17351773 I²C: Address/Data: ACK
17351772-17353703 I²C: Address/Data: Data write: 32
17353702-17353944 I²C: Address/Data: ACK
17353943-17355873 I²C: Address/Data: Data write: 40
17355878-17356119 I²C: Address/Data: ACK
17356245-17356245 I²C: Address/Data: Stop
17357433-17357433 I²C: Address/Data: Start
17357674-17359363 I²C: Address/Data: Address write: 1A
17359363-17359604 I²C: Address/Data: Write
17359618-17359859 I²C: Address/Data: ACK
17359860-17361789 I²C: Address/Data: Data write: 32
17361790-17362031 I²C: Address/Data: ACK
17362031-17363962 I²C: Address/Data: Data write: C0
17363966-17364208 I²C: Address/Data: ACK
17364332-17364332 I²C: Address/Data: Stop
17365460-17365460 I²C: Address/Data: Start
17365702-17367391 I²C: Address/Data: Address write: 1A
17367391-17367633 I²C: Address/Data: Write
17367646-17367888 I²C: Address/Data: ACK
17367887-17369818 I²C: Address/Data: Data write: 5E
17369817-17370059 I²C: Address/Data: ACK
17370058-17371988 I²C: Address/Data: Data write: 20
17371993-17372234 I²C: Address/Data: ACK
17372360-17372360 I²C: Address/Data: Stop
17373456-17373456 I²C: Address/Data: Start
17373698-17375387 I²C: Address/Data: Address write: 1A
17375387-17375629 I²C: Address/Data: Write
17375642-17375884 I²C: Address/Data: ACK
17375883-17377814 I²C: Address/Data: Data write: 5E
17377813-17378055 I²C: Address/Data: ACK
17378054-17379984 I²C: Address/Data: Data write: 30
17379989-17380230 I²C: Address/Data: ACK
17380356-17380356 I²C: Address/Data: Stop

Hi !

Since my first post I have been able to configure the WM8960 using an ESP32 dev board using the examples from Sparkfun, I hear sound and get I2S data.

Did the capture using a logic analyzer and was planning on comparing them with my STM32 version like you suggested.

Taking a closer look at the code and the datasheet… I missed a very crucial point… Typical I2C uses 8 bit register address and 8 bit of data, the WM8960 works differently, the register addresses are actually 7 bits and the register data is 9 bits !!! So looking at the annotations of the logic analyser in pulseview is pretty much useless with the I2C decoder.

I’m looking into how to write Pulseview decoders to have nicer annotations for the WM8960 “protocol”, will keep you posted if that comes to fruition, still pondering whether it’s worth the effort.

Bottom line, I modified the code to shift the address data bits correctly and it’s now working ! At least the I2C part, will look into I2S very soon, but I guess it should also work now.

I will post the link to my code in this thread when I push it!

I got it working !

I pushed the code on Github over here, tagged i2s-working; I’m not proud of this yet, it’s very messy as I was trying to make things work.

This code doesn’t do much except setup the WM8960 via I2C, and read (polling, no interrupts or DMA) data over I2S populating the adcData variable, if you setup a Live Expression in STM32CubeIDE and start a debugging session you will see the data in adcData dance around when music is playing.

To summarize, the issues I initially had were (they are now solved):

  • Not RTFM, and thinking the register addresses were 8 bits and the data 8 bits. When in reality the address is 7 bits and the data 9 bits; some bit shifting magic is required to fit the 9th bit in the register’s address (i2s expects 8/8)
  • Had a typo in my code where I was referencing the wrong register when trying to enable the ADC…

That’s really great news! It would never have occurred to me that the I2C address and data would be other than 8 bits. I did see PulseView allows custom decoders to be installed. That would be a great addition to the tool.

And thank you for putting the code on github! I’ve already cloned it and plan to use it. Very cool.

As to what to do with the ADC data when it comes in: There is a very nice video on using an STMF4 board to read the ADCs in over I2S, implement some filtering, sample by sample, and output the resulting signals to the DACs over I2S. There’s also a repo on github. I’ve ported the code for the board I’m getting, and the whole approach is very clearly written and elegant, and has high performance. I suspect I will go for a lower update rate and fewer bits to allow more time per sample for processing, but maybe it’s fast enough without that!

Here’s the link to the video. There’s a link to the repo in text below the video in youtube:

[#5] IIR Filters - Audio DSP On STM32 with I2S (24 Bit / 96 kHz)

Thanks for the video, Phil’s Lab on YouTube also has some great DSP stm32 stuff.

I’m now fighting with the codec to get the DAC working… seems like our projects have very similar goals, send me your discord handle (or other) over on this address: sparkfun20240917@mailinator.com if you want to exchange more directly on this.

Cheers!