A place users can post their projects. If you have a small project and would like your own dedicated place to post and have others chat about it then this is your spot.

User avatar
By btidey
#89546 I have made a simple clock / pulse generator for test purposes using the I2S interface.

A library creates a circular set of buffers being DMA'd out continuously.

The buffers are filled and clock dividers chosen to give a clock out that can range from 2Hz to 20MHz. The accuracy of the clock setting for any arbitrary frequency is typically better than 0.1% for values below 100KHz.

Mark space ratio can be altered and frequency tolerance can be changed to allow more flexibility on mark space.

More complex repetitive waveforms can be defined in files for output.


A web interface gives easy selection of the parameters.

The output is on GPIO03 (RX0) and can be used directly but I buffer mine through a 74LVC2G34 dual driver to give enhanced driving capability.

Details available at https://github.com/roberttidey/espI2sClockGen
You do not have the required permissions to view the files attached to this post.
User avatar
By davydnorris
#89553 This is very, very cool!!

I would love you to share what you found out about the I2S clock - there's a thread in the advanced section where we've dumped anything we find.

I am most interested in anything on the input side, as I use it for I2S mics and I want to make sure I'm getting the most accurate rate as possible.

It looks like you are using the standard I2S registers but then also using the bit patterns to output really accurate clocking? Is that correct?
User avatar
By btidey
#89562 Yes this tries to find the best combination of clock division and number of bits to represent the clock pulses required.

The I2S output side is pretty straightforward and was based on simplifying down the dma / buffer handling found in a i2s library and then adding in some routines to allow filling the buffers with data patterns.

It is slightly tedious that the 160MHz scaling is split into 2 parts of 6 bit scalers in tandem so that to get the best match to a desired bit clock you have to search over all possible combinations rather than doing a one-off calculation which a single 12 bit divider would allow. I extend the search over possible bit lengths which is effectively like having a third scaler in tandem. Fortunately the search runs pretty fast. The other slightly tricky bit is ensuring one ends up with a circular buffer that repeats exactly.

Having got into this for building a clock generator I have got interested in exploiting the I2S interface in other ways for both real input and output. I'll be looking through the advanced topic and if I have questions or something to contribute I'll put them there.
User avatar
By davydnorris
#89563 Awesome thanks.

The input side is an interesting beast because you have the divider registers and also a resolution register, and what I am still trying to work out is how the resolution register affects and is affected by everything.

I use the Invensense I2S mics, which are 24 bit resolution so in theory they drop their 24 bits into 32 bit words, and a pair will alternate L and R. So if I want 48k audio, I need a bit clock that does 64 times that and a word clock that flicks over at twice that.

The mic data sheet says that it will start transferring the moment the word clock flicks over, so in theory you supposedly don't need to wait the full 32 bits each side. But what's weird is that you set your resolution on the ESP by setting the resolution register to RES - 16, but it's only 4 bits wide, so maximum resolution is 31 bits??

What I need is time to create a little test project that runs at low enough speed to transfer the entire sample set data over so I can play with the settings and work it out