I2S magic

The I2S peripheral on micro controllers is usually intended to output digital sound to a DAC. But we hackers quickly figured out that it is perfectly suitable as generic bit stream output with precisely configurable timings. So there are various implementations to control WS2812 or similar LEDs through this.

But while usually I2S is limited to a single line / bit, the ESP32s I2S takes things to the next level. It can be configured to output up to 24 bits simultaneously! And that through a quite flexible DMA engine which allows arbitrary linked lists to specify the data. So now instead of a boring audio interface we are now looking at a component which can output any predefined data sequence.

Bitstream generation

The matrix only knows two states for each pixel and color, ON and OFF, so in order to display more colors, we need to PWM.

For a color depth of N bits, each image is split into N single images, each representing a single bit of the color value. We call these 'subimages' or 'subframes'. Displaying the image is as simple as displaying all the subimages in a row. However we need to display subimages for the higher-order bits longer. Transmitting them at a lower clock may be an option, but switching the clock would require CPU intervention. So instead we use the linked list feature of the DMA engine to just display these subimages more than once for each full draw cycle. This also allows to distribute the frames evenly across the draw cycle.

Eg we have a color depth of 4 bit and want to display a value of 10, it will be transmitted as 15 slices like the following:
1 1 0 1 1 0 1 1 0 1 1 0 1 1 0
As you can see, the total sum is 10 and the 1s and 0s are spread evenly across the frame.