LED Matrix driver for T4.0 using FlexIO parallel out, FlexPWM, DMA, & SmartLED shield


For a little while, I've been working on adapting the SmartMatrix library to Teensy 4.0 so I can drive a bunch of these Jumbotron-type LED matrices. Teensy 4.0 is attractive for this application since the T3.6 can only drive a screen of about 64x128 pixels due to memory and speed limitations; the T4.0 should be capable of at least twice as many pixels. I've made some good progress and thought I'd share something.
This is not a full port yet but it's a proof of concept that shows a way to drive the matrix using the T4.0's hardware peripherals, specifically FlexIO, FlexPWM, and DMA. In brief, these matrices are driven using 6 data pins, a clock pin, an OE pin, and a latch pin. They do not have any internal LED PWM drivers, so each LED is inherently capable of only displaying fully saturated R/G/B/C/M/Y/W. To get more colors, you have to modulate the LEDs directly by switching pixels on and off really fast! Only two rows are driven at any one time (one in the upper and one in the lower half), so to display a full image it is necessary to quickly loop through all the rows. There are pins for row addressing, but the Pixelmatix SmartLED Shield V4 (designed for T3.2) conveniently provides a way to multiplex the data and address pins together, while also providing the needed 5V level shifting. I opted to keep that shield for T4.0 (with the help of some jumper wires to connect the right Teensy pins). See this Github for the code (with comments) and jumper wire details.
On T3.x, the SmartMatrix library uses DMA to write 8 bits to a GPIO port connected to the data and clock signals. T4.0 doesn't have a configuration of GPIO pins that makes this convenient, but I found a group of 6 pins on FlexIO2 that can be driven in parallel (and don't conflict with the SmartLED shield), and FlexIO can also generate the needed clock signal in hardware. There aren't many examples of FlexIO out there, but I was inspired by Ward's TriantaduoWS2811 demo to give this a try. I can explain a bit more about how it works if anyone is interested.
To display more colors, I adapted the technique from SmartMatrix which uses Binary Code Modulation by quickly flashing each row of pixels over and over, with different timings to represent the individual bits in the binary representation of the color intensity values. (The MSB time is twice as long as the next bit, etc.) This really deserves a detailed writeup... Anyway, I figured out how to do that on T4.0 with FlexPWM triggering a DMA transfer that changes the next frequency and duty cycle of the Latch and OE signals, and then links to the DMA transfer feeding the FlexIO for data output. Everything happens without taxing the CPU, except for a data processing interrupt. For the 32x64 pixel demo, the row update cycle happens at a rate of up to 300 kHz and the full matrix can display 12 bit colors at 580 frames per second. The image shows what the LED panel looks like displaying a "T4" demo image. It's hard to take photos of these LED panels. It looks awesome in person (and super bright)!
Next steps are to implement SmartMatrix's remaining features (such as the more sophisticated buffering, and the ability to define a screen made up of multiple matrices tiled together) and get this working with the other components of the library.


For a little while, I've been working on adapting the SmartMatrix library to Teensy 4.0 so I can drive a bunch of these Jumbotron-type LED matrices. Teensy 4.0 is attractive for this application since the T3.6 can only drive a screen of about 64x128 pixels due to memory and speed limitations; the T4.0 should be capable of at least twice as many pixels. I've made some good progress and thought I'd share something.
This is not a full port yet but it's a proof of concept that shows a way to drive the matrix using the T4.0's hardware peripherals, specifically FlexIO, FlexPWM, and DMA. In brief, these matrices are driven using 6 data pins, a clock pin, an OE pin, and a latch pin. They do not have any internal LED PWM drivers, so each LED is inherently capable of only displaying fully saturated R/G/B/C/M/Y/W. To get more colors, you have to modulate the LEDs directly by switching pixels on and off really fast! Only two rows are driven at any one time (one in the upper and one in the lower half), so to display a full image it is necessary to quickly loop through all the rows. There are pins for row addressing, but the Pixelmatix SmartLED Shield V4 (designed for T3.2) conveniently provides a way to multiplex the data and address pins together, while also providing the needed 5V level shifting. I opted to keep that shield for T4.0 (with the help of some jumper wires to connect the right Teensy pins). See this Github for the code (with comments) and jumper wire details.
On T3.x, the SmartMatrix library uses DMA to write 8 bits to a GPIO port connected to the data and clock signals. T4.0 doesn't have a configuration of GPIO pins that makes this convenient, but I found a group of 6 pins on FlexIO2 that can be driven in parallel (and don't conflict with the SmartLED shield), and FlexIO can also generate the needed clock signal in hardware. There aren't many examples of FlexIO out there, but I was inspired by Ward's TriantaduoWS2811 demo to give this a try. I can explain a bit more about how it works if anyone is interested.
To display more colors, I adapted the technique from SmartMatrix which uses Binary Code Modulation by quickly flashing each row of pixels over and over, with different timings to represent the individual bits in the binary representation of the color intensity values. (The MSB time is twice as long as the next bit, etc.) This really deserves a detailed writeup... Anyway, I figured out how to do that on T4.0 with FlexPWM triggering a DMA transfer that changes the next frequency and duty cycle of the Latch and OE signals, and then links to the DMA transfer feeding the FlexIO for data output. Everything happens without taxing the CPU, except for a data processing interrupt. For the 32x64 pixel demo, the row update cycle happens at a rate of up to 300 kHz and the full matrix can display 12 bit colors at 580 frames per second. The image shows what the LED panel looks like displaying a "T4" demo image. It's hard to take photos of these LED panels. It looks awesome in person (and super bright)!
Next steps are to implement SmartMatrix's remaining features (such as the more sophisticated buffering, and the ability to define a screen made up of multiple matrices tiled together) and get this working with the other components of the library.