← index #8527Issue #1165
Related · high · value 0.196
QUERY · ISSUE

ESP32: Support I2S-driven ADC sampling

openby oclykeopened 2022-04-13updated 2024-07-24
port-esp32

The ESP32 I2S peripheral supports an interesting feature: it can be used to push ADC samples into DMA memory. Currently the ESP32 I2S interface does not allow configuration of the peripheral in this way, though it would only require a little effort.

There is not much configuration available. Besides sample rate and number of bits (already included in the I2S module)

  • which ADC peripheral to use
  • which ADC channel to use

Proposal:

  • create a class similar to the I2S class called I2SADC for the ESP32 port
  • leverage most of the existing code (machine_i2s_init_helper) for initialization of this new class

Any thoughts? I really would like to see support for this and so will begin work on a PR asap.

CANDIDATE · ISSUE

stmhal: I2S class for pyb module (RFC)

closedby blmorrisopened 2015-03-19updated 2022-03-30
port-stm32

I am beginning to work on a new class to support I2S (Inter-IC-Sound) in uPy. I am admittedly in over my head but now making some steady progress - using spi.c as a model I have managed to create a skeleton I2S class that - seems to - successfully initialize the SPI2 / I2S2 peripheral in I2S mode with a hard-coded list of pins corresponding to those used on my DSP-amplifier board. It does not yet initialize any clock parameters or implement any data transfer functions.
I would like to get some early feedback because the usage pattern (and therefore the API) for I2S is going to be significantly different from SPI even though they are based on the same peripheral hardware in the STM32F4xx processors, and I would like to avoid implementing anything that is too ugly or awkward to merge into the project.

To illustrate the difference between I2S and SPI usage, here are some tasks that I expect to implement with I2S (all of which we can currently do at some level with firmware developed in C, but uPy will give us more flexibility to develop advanced applications.)

  • Read audio data (.wav file or other format) from SD card and send data stream via I2S to audio codec chip, (possibly implementing sample-rate conversion on the way.)
  • Record audio data from same codec chip to SD
  • Receive data from codec, apply filtering, and concurrently send back out to codec for playback.
  • Send test signal to codec for playback and concurrently receive data from a microphone via the codec for room acoustic analysis.

All of these cases imply that the I2S data transfer gets set up and runs indefinitely, unlike the data bursts usually seen in SPI - DMA is probably even more critical here than for SPI. Also, it is important to note that only instances 2 and 3 of the SPI hardware support I2S, so it doesn't neatly map to the X,Y position scheme of the pyboard. On the pyboard, as well as my own board, SPI/I2S3 are all but inaccessible due to conflict with the SD card and LED's. On the other hand, the only common platform for most others to easily use I2S with uPy is the STM32FDISCOVERY board, which has a codec available on I2S3.

My initial proposal for the API would be to initialize I2S with a list of pins rather than an instance or position number (necessary for me because the pins used for I2S on my own board are not the same as the SPI2 pins on the pyboard.) The list would have the form [clock, word_select, tx_pin, rx_pin]. The init function will check that each pin is valid for the function designated by its position, it will check that all pins are members of the same I2S instance (2 or 3) and check that the I2S instance is available and not already in use by an existing SPI object (this last check may not be strictly necessary). The only other required parameter will be whether it is a master or slave, and the clock configuration parameters if it is a master. All other parameters will be defined by kwargs set to some reasonable defaults - probably the ones used by my own project ;-)
The list of pins will implicitly determine whether I2S operates in simplex or duplex mode (if either rx_pin or tx_pin == 0 then that direction is omitted.) Likewise, the position of the pin name in the list determines which of the data pins is an input and which is an output.
I'm still trying to decide whether to pass in a list of pin objects or simply pin descriptor strings (i.e. wether to pass pyb.Pin.cpu.B10 or just 'B10')

I'm going to have more questions along the way so I would hope to keep this ticket open for discussion.
-Bryan

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied