LEDLightDistrict/DesignA
Contents
Overview
The goal of this design is to write either monochrome or colour images to an N by N screen, built up out of LEDs. LEDs have a brightness, so PWM is required.
To create an image it is necessary to map colour values from memory, to electronics, to a 2D surface. Each mapping must be understood, to understand how the whole approach will work. But to get a good understanding of how the electronics map the image in memory to the 2D surface, it is practical to learn how the image in memory maps to the 2D surface first.
Mapping pixels in memory to the 2D surface
monochrome
The image is stored in a basic one dimensional array.
To find a pixel's index based on its surface coordinates:
rowStartIndex = x * HEIGHT ; if( x % 2 ) relativeColumnIndex = y ; else relativeColumnIndex = HEIGHT - 1 - y ;
index = rowStartIndex + relativeColumnIndex ;
To illustrate for a 3 by 3 screen an example:
0 5 6
1 4 7
2 3 9
Where the number illustrates the position in the array.
To find (1,0) do:
rowStartIndex = 1 * HEIGHT = 3 ; relativeColumnIndex = HEIGHT - 1 - 0 = 2 index = 3 + 2 = 5 ;
Colour
The image is stored in a basic one dimensional array.
To find a subpixel's index based on its surface coordinates:
rowStartIndex = COLOUR_COUNT * x * HEIGHT ;
if( x % 2 ) relativeColumnIndex = y + subPixel ; // sub pixel is either 0 for red, 1 for green or 2 for blue else relativeColumnIndex = COLOUR_COUNT * HEIGHT - 1 - y - subPixel ; index = rowStartIndex + relativeColumnIndex ;
To illustrate for a 3 by 3 screen an example:
r 0 17 18
g 1 16 19
b 2 15 20
r 3 14 21
g 4 13 22
b 5 12 23
r 6 11 24
g 7 10 25
b 8 9 26
To find (1,0), 0 (i.e. red) do:
rowStartIndex = COLOUR_COUNT * 1 * HEIGHT = 9 ; relativeColumnIndex = COLOUR_COUNT * WIDTH - 1 - 0 = 8
index = 9 + 8 = 17 ;
Electronics, mapping pixels to screen
The pixels can be addressed through a series of shift registers, that are all connected in series. Each position in the shift register corresponds to the position in the array described above. LEDs of the right colour are attached to the concatenated shift registers in the precise order described above.
Computing PWM
frameDuration = beforeFrame - timeInMillis() ; beforeFrame = timeInMillis() ; for( i in pixelArray ) pixelHigh = ( ( timeInMillis() ) % frameDuration ) < pixelBrightness ? true : false
pushToScreen( pixelHigh ) openLatch() ;
tractability
This is a tractability computation of a colour screen with colour and 7 brightness levels per pixel:
computationCount = pixelCount * COLOURS_PER_PIXEL * brightnessLevels * frameRate pixelCount = WIDTH * HEiGHT
computationCount = 17 * 16 * 3 * 7 * 60 = 342 720
This is totally feasible.