Step 54Software: Low level functions
There are three main reasons for doing this.
Memory footprint
The easiest way to address each voxel would be through a three dimensional buffer array. Like this:
unsigned char cube[x][y][z]; (char means an 8 bit number, unsigned means that it's range is from 0 to 255. signed is -128 to +127)
Within this array each voxel would be represented by an integer, where 0 is off and 1 is on. In fact, you could use the entire integer and have 256 different brightness levels. We actually tried this first, but it turned out that our eBay LEDs had very little change in brightness in relation to duty cycle. The effect wasn't noticeable enough to be worth the trouble. We went for a monochrome solution. On and off.
With a monochrome cube and a three dimensional buffer, we would be wasting 7/8 of the memory used. The smallest amount of memory you can allocate is one byte (8 bits), and you only need 1 bit to represent on and off. 7 bits for each voxel would be wasted. 512*(7/8) = 448 bytes of wasted memory. Memory is scarce on micro controllers, so this is a sub-optimal solution.
Instead, we created a buffer that looks like this:
unsigned char cube[z][y];
In this buffer the X axis is represented within each of the bytes in the buffer array. This can be quite confusing to work with, which brings us to the second reason for making a library of low level drawing functions:
Code readability
Setting a voxel with the coordinates x=4, y=3, z=5 will require the following code:
cube[5][3] |= (0x01 << 4);
You can see how this could lead to some serious head scratching when trying to debug your effect code ;)
In draw.c we have made a bunch of functions that takes x,y,z as arguments and does this magic for you.
Setting the same voxel as in the example above is done with setvoxel(4,3,5), which is _a lot_ easier to read!
draw.c contains many more functions like this. Line drawing, plane drawing, box drawing, filling etc. Have a look in draw.c and familiarize yourself with the different functions.
Reusable code and code size
As you can see in draw.c, some of the functions are quite large. Writing that code over and over again inside effect functions would take up a lot of program memory. We only have 32 KB to work with. Its also boring to write the same code over and over again ;)
| « Previous Step | Download PDFView All Steps | Next Step » |





























































































![Hard Wired LED Cube: [No Programming]](http://img.instructables.com/files/deriv/FTD/SF1T/GO8DC8KW/FTDSF1TGO8DC8KW.SQUARE.jpg)















Anyway, i have code which goes like this...
resetLayer(); //function
resetLeds(); //function
PORTC &= ~(1 << latchLed) //set latch low
shiftOut(PORTC, dataLed, clockLed, 0xFFFFFFFFFFFFFFFF); //shifts out register //states
PORTC |= (1 << latchLed) //set latch high
_delay_us(50); //pauses a while
nextLayer(); //function
...
My question is, what should the delay be in microseconds for the layer switching. Thanks in advance. #iluvleds
cube[5][3] |= (0x01 << 4);
I guess I could just accept that it works but I'd really like to understand what's actually happening. I realize we're shifting 0x01 four places to the left, then I guess ORing it with cube[5][3] then assigning it to cube [5][3]. It's the OR with a 2D array that's confusing.
thanks in advance.
cube[0][0]=0x01
0x01=00000001 in binary.
In the case of the above example, we want to change the state of one bit in a byte, i.e. switch on one LED in a row without changing the rest of it. In this case it's the row 5 from the bottom and 3 from the left of the cube. In order to change the state of ONE bit in that byte, it is OR'd with (0x01<<4) which is binary 00010000 (i.e. bit 4 is set). If bit 4 in that byte is unset, then it becomes set.
still seems really wasteful with memory but i guess to compact it any more would be even harder to decipher. or maybe i just don't know that this is as compact as it can get. either way, glad i understand it now.
thanks for your help!
Thank you!
Out of 'interest'(?) my .c code now has two "cube" arrays, and a kind of hacked PWM method of driving the LEDs in the ISR code, so each LED can be at 4 states (off, dim, brighter, full-on) This makes the "rain" and "sparkle" effects very subtle. My fireworks code is pretty flashy, but not entirely finished yet.
Regards
John
http://www.instructables.com/id/Led-Cube-8x8x8/step49/Software-Introduction/
http://www.instructables.com/id/Led-Cube-8x8x8/step46/Program-the-AVR-with-test-code/
http://www.instructables.com/id/Led-Cube-8x8x8/step70/Run-the-cube-on-an-Arduino/
http://www.instructables.com/id/Led-Cube-8x8x8/step64/PC-Software-Introduction/
John