Skip to content

Led cube

This is my first attempt of building a led cube, so I kept it small. A 3*3*3 cube is fun to play with.


It has been a long time that I’ve worked on this project. But this week I managed to take a huge leap!

At this moment, the basic software is programmed, the microcontroller has the Microchip MCHPUSB bootloader, and is connected through USB. The USB is currently only for programming the device, but it’s possible to use it also as a way to interface the cube with a computer.

The biggest problem I had, was how to store the frames in the memory. The best option (the least memory consuming) seamed to me to just store what the status of each pin should be for each layer. That results in a (3*3) * 3 = 27bit datatype, which means 32bit! I’ve got 5 bits to spare that can be used to tell how long a frame should last. The software is written in MPLAB with the C18 compiler.

The actual program consists of 2 important parts and the data.

#define total_frames  55
#pragma romdata Cube_Table_Start = 0xC00
const rom unsigned long Cube_Table[total_frames] =

Storing the data is done in an array of long constants. Each entry is 32 bits long, that’s 4 bytes.
Main Loop

        if(gogo == 0)
            LATB = portbLo;
            LATA = portaLo;
            LATB = portbLm;
            LATA = portaLm;
            LATB = portbLb;
            LATA = portaLb;
            gogo = 0;

This loop constantly display the 3 layers one after another. In between there is a small delay, to make the LEDs light up more, and to prevent ghosting. Once timer0 overflows (hardware), it generates an intterupt. This procedure sets the variable ‘gogo’ (working late at night, one isn’t very imaginative with names) and increments ‘frame’. The main loop now goes into the second case, where a new frame is loaded: longToParts(Cube_Table[frame]);


void longToParts(unsigned long allBits)
    portaLo = (unsigned char)(allBits); // 2MSB niet gebruikt -> 6 bits
    portbLo = (unsigned char)(allBits >> 6); // b0-2: kolommen, b3-5: layers, 2MSB niet gebruikt -> 3 bits
    portbLo |= 0b00111000;
    portbLo &= 0b00110111;
    portaLm = (unsigned char)(allBits >> 9); // 2MSB niet gebruikt -> 6 bits
    portbLm = (unsigned char)(allBits >> 15); // b0-2: kolommen, b3-5: layers, 2MSB niet gebruikt -> 3 bits
    portbLm |= 0b00111000;
    portbLm &= 0b00101111;
    portaLb = (unsigned char)(allBits >> 18); // 2MSB niet gebruikt -> 6 bits
    portbLb = (unsigned char)(allBits >> 24); // b0-2: kolommen, b3-5: layers, 2MSB niet gebruikt -> 3 bits
    portbLb |= 0b00111000;
    portbLb &= 0b00011111;

Here is where the bit shifting and other fun happens! Each layer is controlled by LATA and LATB, that are both 8 bit registers. That means not all the bits are used in those registers, so we have to do some masking.

Leaving most of the brains out of the microcontroller, the computer has to do a little more work while generating a new pattern. I found a nice script that was written by a student named Andrew Stock:
I had to do some modifications, but now it helps to speed up the process!

This is how it looked a couple of days ago (in the meantime I’ve added some other patterns):

Published inElectronics

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *