Step 60: Software: Effect 4, box shrinkgrow and woopwoop
We made two box animation functions for the LED cube. Effect_box_shrink_grow() draws a wireframe box filling the entire cube, then shrinks it down to one voxel in one of 8 corners. We call this function one time for each of the 8 corners to create a nice effect. Effect_box_woopwoop() draws a box that starts as a 8x8x8 wireframe box filling the entire cube. It then shrinks down to a 2x2x2 box at the center of the cube. Or in reverse if grow is specified.
Here is how effect_box_shrink_grow() works.
It takes four arguments, number of iterations, rotation, flip and delay. Rotation specifies rotation around the Z axis at 90 degree intervals. Flip > 0 flips the cube upside-down.
To make the function as simple as possible, it just draws a box from 0,0,0 to any point along the diagonal between 0,0,0 and 7,7,7 then uses axis mirror functions from draw.c to rotate it.
1) Enter main iteration loop.
2) Enter a for() loop going from 0 to 15.
3) Set xyz to 7-i. This makes xyz the reverse of i. We want to shrink the box first, then grow. xyz is the point along the diagonal. We just used one variable since x, y and z are all equal along this diagonal.
4) When i = 7, the box has shrunk to a 1x1x1 box, and we can't shrink it any more. If i is greater than 7, xyz is set to i-8, which makes xyz travel from 0 to 7 when i travels from 8 to 15. We did this trick to avoid having two for loops, whith one going from 7-0 and one from 0-7.
5) Blank the cube and delay a little bit to make sure the blanking is rendered on the cube. Disable the interrupt routine. We do this because the mirror functions takes a little time. Without disabling interrupts, the wireframe box would flash briefly in the original rotation before being displayed rotated.
6) Draw the wireframe box in its original rotation. side of the box is always at 0,0,0 while the other travels along the diagonal.
7) Do the rotations. If flip is greather than 0, the cube is turned upside-down. rot takes a number from 0 to 3 where 0 is 0 degrees of rotation around Z and 3 is 270 degrees. To get 270 degrees we simply mirror around X and Y.
8) Enable interrupts to display the now rotated cube.
9) Delay for a while then clear the cube.
The other function involved in the wireframe box effect is effect_box_woopwoop(). The name woopwoop just sounded natural when we first saw the effect rendered on the cube ;)
The woopwoop function only does one iteration and takes two arguments, delay and grow. If grow is greater than 0, the box starts as a 2x2x2 box and grow to a 8x8x8 box.
Here is how it works:
1) Clear the cube by filling the buffer with 0x00;
2) For()-loop from 0 to 3.
4) Set ii to i. If grow is specified we set it to 3-i to reverse it.
5) Draw a wireframe box centered along the diagonal between 0,0,0 and 7,7,7. One corner of the box uses the coordinates 4+ii on all axes, moving from 4-7. The other corner uses 3-ii on all axes, moving from 3-0.
6) Delay for a while, then clear the cube.
These two functions are used as one single effect in the effect launcher. First the shrink grow effect is called 8 times, one for each corner, then woopwoop is called four times, two shrink and grow cycles.
To launch the shrink grow function, we used a for loop with some neat bit manipulation tricks inside to avoid writing 8 lines of code.
The second argument of the shrink grow functions is the rotation, in 4 steps. We are counting from 0 to 7, so we can't simply feed i into the function. We use the modulo operator % to keep the number inside a range of 0-4. The modulo operator divides by the number specifies and returns the remainder.
The third argument is the flip. When flip = 0, the cube is not flipped. > 0 flips. We use the bitwise AND operator to only read bit 3 of i.
Bitwise operators are an absolute must to know about when working with micro controllers, but that is outside the scope of this instructable. The guys over at AVR Freaks have posted some great information about this topic. You can read more at http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=37871