First of all: the hardware. I'm not even gonna draw up a schematic here: just take an Olinuxino Nano (or any other iMX233-based board on which you can free up the LCD bus pins) and connect every LCD data line (usually referred to as LCD_Dx) to the Din of a WS2811-based LED-strip. Power the LED-strips and the Olinuxino using a 5V power supply and you should be good. Officially, the WS2811 needs a 5V signal to work while the iMX233 only outputs 3.3V, but in practice the WS2811 seems happy with it. When in doubt, you may want to add some level-conversion logic.

Here's my implementation. As you can see, I only connected 4 short LED-strips, but the full 16-bit bus is available on the Olinuxino pins, so I could have connected 12 strips more. Also, the length of the strips was purely defined by what I had on my hands and not indicative for what the hardware can do:

Now. onto the software. I'm using the latest 3.13-rc4 Linux kernel for this: see these instructions on the steps needed to build it. I couldn't use the built kernel as is: it didn't have the drivers for the video hardware enabled. That means I would have to rummage around in the kernel. There actually is a sort-of howto for adding a LCD to a linuxino, from which I've glanced a thing or two, but it's for an older kernel so half of the instructions won't work anymore.

Modern arm kernels have all the hardware dependencies defined in the device tree section. Ideally, those files perfectly define the hardware the kernel is going to run on, allowing the kernel to load the right drivers and attach them to the right peripherials, making everything work automatically. So, to add support for the specific flavour of framebuffer I needed, I only had to modify two files. The main iMX233 dts file didn't have an 16-bit LCD interface defined yet, so I added that to arch/arm/boot/dts/imx23.dtsi. Then, I needed to define the lcdif specifics in arch/arm/boot/dts/imx23-olinuxino.dts: I added a definition for the lcdif that uses the 16-bit mode, plus a display mode of 360x256 pixels with a dotclock of exactly 4MHz. You can grab a patch to do those things for you; please apply it after where the instructions tell you to apply i2c support patch. Note: this patch also disables the i2c bus because some of its pins overlap with the LCD-controller pins. You also need to configure the kernel to add support for the iMXs framebuffer: grab my kernel config as an example.

The way this patch configures the video hardware isn't completely ideal: it seems either the Linux driver or the hardware itself refuses to have a front porch or hsync length of zero. That means the minimum value for those is one, meaning after every line of pixels, we get 0.5uS where we can't output data and the LCD bus is forced to all-zeroes. This messes up the timing a little bit. Fortunately, there's a workaround. It seems the time between sending the last bit of a led and the first bit of the next led isn't critical: there can be up to 20 cycles (5uS) before the LED-strip gets confused. I've chosen 360 pixels as the width of a line in the framebuffer The amount of pixels needed to set one led is 24 bit * 5 pixels for one bit = 120 pixels, so a single line will contain exactly the data needed for three LEDs. That means the 2 hsync/frontporch pixels will be exactly in the bit of datastream where the timing doesn't matter that much, making everything work anyway.

Now, all is left is a program to push the right bits into the framebuffer. I've written a small proof-of-concept program that pushes an animation to the LEDs. The animation is restricted to the physical LEDs I have but the routines that handle the data conversion from LED-colors to WS28110-signals assume there are 16 strips of 600 leds each connected to it. Even with the burden of generating signals for almost ten thousand LEDs, the program still gets framerates of 30fps, and this can probably be improved even more.

« Prev 3 Next »

© 2006-2022 Sprite_tm - Contact