Recall that to control each LED individually, 512 I/O ports would be needed on a microcontroller. The cube connects each anode in 64 vertical columns and all cathodes for each layer. This reduces the number of ports needed to 64+8 = 72. 72 connections is better than 512, but it is still way too many for a cost effective microcontroller. The solution is to use nine 8-bit serial-in-parallel-out shift registers. They do what they say; they take an 8 bit (1 byte) number in serial and, when told to, express that number on 8 output pins all at once. They can be chained together to act as one 72 output shift register, which is what is done for the cube.
You may have noticed that connecting the LEDs like I have makes it impossible to individually control all LEDs at the same time. For instance, turning on LEDs at position 1,1,1 and 8,8,8 also turns on 1,8,1 and 8,1,8. To get around this, the cube relies on a phenomenon called persistence of vision. When a light is flashed on and off very quickly, it appears to be on all the time. By lighting one layer of the cube at a time in succession at high speeds, the entire cube appears to be on at once.
The code theory is pretty straightforward. There is a 2 dimensional array with 64 slots containing values 0-255 which correspond to which LEDs will be turned on. In other words, it has the values in binary to send to each shift register for a given layer. There are functions throughout the program which then change the values in the array, producing animations. When rendering the cube, there is a for loop which sends out a '1' bit-shifted to the left with each increment (or 128 shifted to the right to invert the cube vertically), and a nested for loop which sends one row of the array at a time using the SPI protocol. One loop cycle may look like so:
00000001 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
In this example, the first byte sent out enables the first layer. The next 8 bytes fill each register corresponding to a column of the array, so each LED on the first layer is turned on. The loop then increments, this time starting with '00000010' followed by the next row of columns in the array and so on.
Below is a PDF of the code that I have been working on, and here is the github . For a while, I used Harry Le's code and didn't play around too much, as writing functions to produce different animations is a time intensive task. One day, I opened a blank file and decided to write my own code. I borrowed his render and shift functions, and the rest is mine. What I wrote is in no way supposed to look beautiful; it is a work in progress and I have not yet tried to optimize it.