Hi everyone,
I need help creating a custom design to read audio signals from an I2S MEMS sensor by Adafruit (Adafruit I2S MEMS Microphone Breakout - SPH0645LM4H : ID 3421 : $6.95 : Adafruit Industries, Unique & fun DIY electronics and kits). If anyone can provide support, I will definitely make a tutorial, as usual, outlining the entire process
Hereās my current design:
design_I2S_receiver.pdf (74.8 KB)
Iām using a CoraZ7 board (though I think thatās not crucial information).
The PYNQ-side code is as follows:
from pynq import Overlay, allocate
import numpy as np
ol = Overlay("design_wrapper.bit")
adc_ctrl = ol.i2s_receiver_0
adc_dma = ol.axi_dma_1
N=256 * 1000
audio_input_buffer = allocate(shape=(N,), dtype=np.uint32)
adc_dma.recvchannel._align = 4
# stop I2S controller
adc_ctrl.write(0x08, 0)
# redirect all channels to the channel 0-1
CH_SEL = 1
adc_ctrl.write(0x30, CH_SEL )
adc_ctrl.write(0x34, CH_SEL )
adc_ctrl.write(0x38, CH_SEL )
adc_ctrl.write(0x3C, CH_SEL )
# I2S Timing Control (0x20)
# This register is used to set the divider value to generate the SCLK. Typically SCLK = 2*24*Fs, where 24 is the I2S data width (this value can also be 16) and Fs is the audio sampling rate.
# 200Mhz / 2 * 16 * 16000 = DIVIDER * 2 ---> DIVIDER = ( 200 mHz / 512 kHz ) / 2 ----> DIVIDER = 50
adc_ctrl.write(0x20, 50)
# start I2S controller
adc_ctrl.write(0x08, 1)
adc_dma.recvchannel.transfer(audio_input_buffer)
adc_dma.recvchannel.wait()
When I check the clock pins using an oscilloscope, I can see that they generate the correct clock signal. However, on the PYNQ side, when I try to read from the DMA, I donāt get the expected results. Specifically, I read all zeros or ārandomā values. I followed the IP documentation and tried to extract the bits from the DMA, but Iām still getting the same results. I also added this code:
audio = np.copy(audio_input_buffer)
f_audio = np.zeros(N, dtype=np.uint16)
f_audio2 = np.zeros(N, dtype=np.int32)
def extract_number(num, start_bit, end_bit):
mask = (1 << (end_bit - start_bit + 1)) - 1
extracted_number = (num >> start_bit) & mask
return extracted_number
for i in range(N):
f_audio[i] = extract_number(audio[i], 12, 27)
# convert audio word according to Adafruit documentation
for i in range(N):
if f_audio[i] == 0 or f_audio[i] == -1:
f_audio2[i] = 0
continue
__a = f_audio[i]
__a >>= 14
f_audio2[i] = __a
Does anyone have experience with this I2S IP and/or Adafruit MEMS? Have I missed something in my setup?
Also, I see that PYNQ has custom IPs for audio controlling (Audio codec controller & Audio direct), is it possible to use them for the same purposes? If yes, can you provide an example?
Thanks!