Sunday 9 June 2013

10. Demonstration Videos

Ok, now that we have built our 3D cube we will use this page to put up some videos of what we have programmed it to do.

Here is the first - it's a square drawing program...



The cube was being controlled by a PICAXE 28X2 module which is virtually completely self-contained and costs only £11.99 (and the programming editor is free although you'll have to but a programming cable).

We wrote the code in two steps - the first was a subroutine which would put a cube of lit LEDs of any defined size anywhere in the matrix that we chose.  Then we wrote a routine which simply moved it around.

More to come...

Wednesday 5 June 2013

9. And finally...The Box!



Finally, we made the plastic box that the cube sits in.  The box comes as a series of five plastic, pre-cut sheets which are covered in a semi-sticky paper.  The edges of the sheets were cut with edges of a simple interlocking tongue-and-groove style.  There was no clue as to what the sheets were made of.

Having spoken to our local model shop, we bought a small bottle of 'EMA Plastic Weld' (Dichloromethane) to stick the box together.  This is a solvent which 'wicks' into the joints between the mating surfaces of the plastic by capillary action and  'melts' the plastic, allowing to pieces to stick together.  It then quickly evaporates.

This is what we did:
  1. We checked that the sheets fitted together to form a box.  We kept the sheets 'in order' so that we knew that they would go together.
  2. We washed our hands so that we had no grease on them that would cause problems for the solvent we were going to use.
  3. We removed the paper covering from the plastic sheets.
  4. We assembled the box.  This took two pairs of hands!
  5. We got a small 'No. 2' paintbrush, dipped it in the solvent and then ran the brush along the upper seams of the box.  Having done this we held the joint together for around 30 seconds to allow it to 'set'.
  6. Having done all four of the top joints, we then VERY CAREFULLY turned the box onto each one of its side in turn, again dipping the brush into the solvent and running it along the seam.
Our cube was then finished!

One small point to note is that (conveniently) the plastic box actually sits on the printed circuit board, so it's easy to connect it to the power/computer, etc.

If you decide to make one of these cubes yourselves we hope you had as much fun as we did!

Sunday 26 May 2013

8. How to Control the Cube - Decoding the Command Format



In this section I take a look at the code that commands the system.  If you only want to use the supplied software then this won't interest you.  However, if like us you want to create your own gadget to control the cube, read on...

($ = a hexadecimal number)

Command Set

Commands always consist of one byte which tells the cube what's coming next and then one or more bytes which contain the settings information.

The command format for the cube (as far as I can decipher it) is as follows:

$F2, $xx, $xx, $xx...(1 + 64 bytes) sets the condition of the LEDs in the whole cube.  Not surprisingly, the binary form of the 64 bytes is a representation of the cube where a 0 means an LED is off and a 1 means it's on.  (See below for the way the cube is represented.)

$F3, $0x is the command to change 'Mode' where x = 0,1,2 or 3 (I haven't yet worked out what 'mode' is used for.)

$F4, $xx is the command to set the brightness where xx represents a number between $00 and $FF

$F5, $0x turns LED0 and LED1 (the four upper and four lower corner LEDs).  This works in binary so not surprisingly the combinations are:

  • $F5,$00 - All off
  • $F5,$01 - Upper on, lower off
  • $F5,$02 - Upper off, lower on
  • $F5,$03 - All on

Organisation of the Cube

The cube is arranged in such a way that each vertical column represents one byte.  Looking from above it the byte numbers are organised as follows:


To set a particular pattern on the cube, you send $F2 followed by a string of 64 bytes each of which control the LED state of a particular column.  So the first byte sets the back right column, the second sets the column to the left of it and so on.

Since a byte is made up of 8 bits then you can see that the state of each LED in that column represents the state of a bit in the byte with the most significant bit at the top.

So, to set all the LEDs off you send $F2 followed by 64 zeroes.  To set just the back right top LED on you would send $F2, $80 and then 63 zeroes.

Now let's look some examples, especially from a binary point of view:

Binary and Hex Examples (I haven't included the $ in the hex examples below)

(I have formatted the text below a little so that the 8x8x8 array appears in one block for clarity but in reality the bytes follow one another with no carriage returns, etc.)

All LEDs On:

11110010
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111

All LEDs Off:  ($

11110010
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

Front Bottom Left LED On:

11110010
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001

Front Bottom Row of LEDs On:

11110010
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000001 00000001 00000001 00000001 00000001 00000001 00000001 00000001

Top  Layer of LEDs On:

11110010
10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000
10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000
10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000
10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000
10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000
10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000
10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000
10000000 10000000 10000000 10000000 10000000 10000000 10000000 10000000

(..and this time in Hex:)

F2
80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80

Mode 3:

F3 03

...you get the idea!

One last thing...the points of the cube.  I hope you understand what I mean:

F000000H 00000000 00000000 00000000 00000000 00000000 00000000 E000000G
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
B000000D 00000000 00000000 00000000 00000000 00000000 00000000 A000000C

...where the cube looks like this:

E        F
  A       B
G       H
  C       D

...which is supposed to represent a cube with A being top front left and H as rear bottom right.  Well it makes sense to me :-)

So, if you wanted to light up all the LEDs on the plane 'FBHD' you would have to send:

11110010
11111111 00000000 00000000 00000000 00000000 00000000 00000000 00000000
11111111 00000000 00000000 00000000 00000000 00000000 00000000 00000000
11111111 00000000 00000000 00000000 00000000 00000000 00000000 00000000
11111111 00000000 00000000 00000000 00000000 00000000 00000000 00000000
11111111 00000000 00000000 00000000 00000000 00000000 00000000 00000000
11111111 00000000 00000000 00000000 00000000 00000000 00000000 00000000
11111111 00000000 00000000 00000000 00000000 00000000 00000000 00000000
11111111 00000000 00000000 00000000 00000000 00000000 00000000 00000000

...which in Hex is:

F2
FF 00 00 00 00 00 00 00
FF 00 00 00 00 00 00 00
FF 00 00 00 00 00 00 00
FF 00 00 00 00 00 00 00
FF 00 00 00 00 00 00 00
FF 00 00 00 00 00 00 00
FF 00 00 00 00 00 00 00
FF 00 00 00 00 00 00 00

...or without formatting nicely for this web page:

F2 FF 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 FF 00 00 00 00 00 00
00 FF 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 FF 00 00 00 00 00 00
00 FF 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00

...or in decimal would be:
                                                                               
242 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255
0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0

Does this all makes sense?  Add a comment if not and I'll try to make it clearer.

One Final Mystery to Clear Up
The only thing I haven't worked out yet is how to reset the cube so that it is expecting the next byte to be a command.  The way I currently achieve this is by switching it off - not much hassle but not very scientific.

One thing I have found out is that if you leave a sequence going for about 30 seconds to a minute without starting with a command it seems to realise and resets itself.

Anyway, if anyone knows how to do this properly please let me know with a comment.


>> UPDATE!!!! <<<
I have just found a Chinese PDF which has some information on controlling the cube.  The original file is located on a blog here.  I have used Google Chrome to translate it and pasted it below...sorry it's not very good but it may be of some use:




 

3D8 serial data communication protocol v1.5

aGuegu / official micro-macro 2011-08-02

This article describes the 3D8 8x8x8 LED light cube serial communication means and to provide routine.

Background Requirements: C language based microcontroller C language programming foundation.
Directory
Instruction ................................................ ....................... 1
Underlying driver module ............................................... .................... 3
Driver routines ............................................... ........................ 5
 Routine 1 - fullscreen flash ......................................... .................... 5
 Sample 2 - three-sided scanning .......................................... ................... 6
 Sample 3 - upwelling .......................................... ..................... 8



Instruction set

3D8 serial communication protocol, the default settings: Baud Rate: 115200; Parity: None; Data Bits: 8;
Each command consists of two bytes. Sent first eight (H7-H0), and then send the low 8 (L7-L0). Taking into account the efficiency of the system, as well as ease of programming, no parity bit, totaling three kinds of code format, using three start code corresponding with no end code.
Because they do not set the end of the code, it is necessary to ensure the integrity of each code is sent.

FunctionStart codeByte countFormatExample
Global Assignment0xf020xf0 + DataSend "0xf0 0x00", will set the value of all the beam 0x00, clear the screen operation.
Single beam assignment0xf130xf1 + Column + DataSend "0xf1 0x02 0xff", it will set the value of the second beam 0xff, ie two beams full bright.
Batch Assignment0xf2650xf2 + Data [0] + Data [1] + ... + Data [63]Send "0xf2 0x3f 0x3e 0x3d 0x01 0x00", assigned to the 0 upcoming 0x3f beams coming 0x3e bundle assigned to the first one, will be assigned to the first two beams 0x3d, ......, will be assigned to the 0 0x3f beam. Updated full screen.

 coordinates: right-handed coordinate system in accordance with the 3D8 up coordinate system, we can define an arbitrary system 3D8 light spot (LED) the coordinates (x, y, z). It is understood that x, y, z of the range (range) are [0, 7] is an integer domain, i.e. {0, 1, 2, 3, 4, 5, 6, 7}.


Note: The figures mentioned below, are integers.

 beam coordinate (Column, abbreviated as c): in the 3D8 system, the combination of hardware system-defined coordinate values, the value c = y * 8 + x. C can be obtained whereby the range of [0, 63]; and we also calculate the x = c% 8, y = c / 8. (Familiar programming friends will know where the "% of modulo arithmetic," / is divisible computing).
 data value (Data), which define each bundle (Column) on the display. Because there are many points simultaneously lit situation, and z in the range [0, 7], so a byte (byte) of 8 bits (bit), can be used to precisely define this state. If you require a beam only z = 0 points (0 layer, bottom) is lit, you can set the value of the Data 0x01 (0000 0001 B) (suffix B, indicates that the number is a binary number). Only if requested by a beam z = 6 points (6th floor, down from Tier 2) is lit, Data = 0x40 (0100 0000 B); if requested by the z = 0, z = 6 points at the same lit, Data = 0x41 (0100 0001 B).
 driven process:
1 after power on the motherboard, to give the host computer is powered on. Ensure that the motherboard to advance into the listening state.
(2) in the host computer program, the instruction can be one of the three or more of the combination, to achieve the assignment to one screen picture.
3 After the assignment, the motherboard internal data cache will save these values, and continue to be scanned on the LED display. PC can delay function, the control interval between two pictures.
4 cycle steps 2,3, to achieve animation effects.
 system reset system reset under the current protocol is particularly important, because the instruction may be long or short, while the motherboard and not to determine whether the connection is interrupted. So when an instruction is not sent complete, if the communication interruption occurs, the board will continue to wait for completion of the remaining commands to send. And if at this time to re-establish the connection, the motherboard will not be the first to receive a byte code as a starting judge. This leads to communication can not be normal, then you need to restart the motherboard, the PC begins sending data again before allowing communication synchronization. In short, disconnect the connection between PC and motherboard after reconnect, restart motherboard, then the host computer and then start sending data. If you are using control rods, control rods will also use the motherboard power, so in this case if the restart motherboard, motherboard and control rods will also restart. Because internal control rods containing startup delay proceedings, it makes the data before sending it, the motherboard has to advance into the listening state.

Update Notes:
V1.3 (2011-08-11): Fixed a single beam assignment command, the beam coordinates may be out of range of the bug.

V1.4 (2011-08-13): Fixed the send code is too long, dislocation caused an error and then start code system does not respond to the Bug, if the start code non 0xf0/0xf1/0xf2, the board will continue to wait to receive start code.

V1.5 (2011-11-06): Fixed a routine some bug.

Underlying driver module

/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/ / 3D8 serial communication underlying driver (Templates)
/ / PC 12C5A60S2 +22.1184 M based on an external crystal, the use of other PC, please fully understand the following procedures be modified later.
/ / AGuegu / official micro-macro 2011-11-05 weihong.guan @ gmail.com http://aguegu.net
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /

# Include <REG51.H>
# Include <intrins.h>
# Include <stdlib.h>
typedef unsigned char uint8;
typedef unsigned int uint16;

# Define LAYER_COUNT 8
# Define COLUMN_COUNT 64

/ / Delay function
void delay (uint16 a)
{
while (a -)
_nop_ ();
}

/ / Time-lapse function
void delayL (uint16 a)
{
while (a -)
delay (-1);
}

/ / Initialize the serial port: 115200 baud rate (using an external crystal frequency 22.1184M drive)
void UART_Init (void)
{
TMOD = 0x20;
SCON = 0x50;
TH1 = 0xff; TL1 = 0xff; / / set the baud rate to 115200
PCON = 0x80;
TR1 = 1;
}

/ / Send data to serial function
void UART_Send (uint8 cData)
{
SBUF = cData;
while (! TI);
TI = 0;
}

/ / According to the x, y values ​​of the value of column
uint8 funGetColumn (uint8 x, uint8 y)
{
return (8 * y + x);
}
/ / Global assignment function
void funPrintUniqueValue2Cube (uint8 cData)
{
UART_Send (0xf0); / / start code is built into the transmission function
UART_Send (cData);
}

/ / Single-bundle assignment functions
void funPrintColumn (uint8 cColumn, uint8 cData)
{
UART_Send (0xf1);
UART_Send (cColumn);
UART_Send (cData);
}

void funPrintCube (uint8 * p)
{
uint8 i;
UART_Send (0xf2);
for (i = 0; i <COLUMN_COUNT; i + +)
UART_Send (p [i]);
}
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/ / The above function as a fixed driver module, generally do not modify
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /

/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/ / Animation program segment: packaged inserted here after animation program
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /


/ / Main function
void main (void)
{
delay (-1); / / In fact, here's -1 is equivalent to 65,535, that is, the delay function can provide the maximum delay interval
delay (-1); / /
UART_Init (); / / initialize the serial port
while (1)
{

}
}
/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /

Driver routines

 Routine 1 - fullscreen flash

/ / Set the template to the main function is as follows
void main (void)
{
delay (-1);
delay (-1);

UART_Init (); / / initialize the serial port

while (1)
{
funPrintUniqueValue2Cube (0xff); / / open all shows
delayL (4);
/ / Display the length of time, you can decrease the parameter value, or increase the delay () the number of runs, changing the blinking intervals
funPrintUniqueValue2Cube (0x00); / / Close all display
delayL (4);
}
}
Tips:
 single frame display time by the delay function delay (uint16); controlled parameters (-1), then the interval is longer, if you change to 0x20, or even smaller, or even simply do not delay.Because the display is too fast imperceptible changes caused by the naked eye, but is seen fullscreen are lit. This time is not the motherboard is not running properly, but scanning too fast, leading to the naked eye can not see changes.
 Control frame (single frame display time countdown), in addition to delay function approach, of course, you can also use the timer interrupt, interested friends may wish to try. 


 Sample 2 - three-sided scanning

In the animation block Insert the following functions:
/ / Z direction by side scan
void funScanByZ (void)
{
uint8 z;
funPrintUniqueValue2Cube (0x00);
for (z = 0; z <LAYER_COUNT; z + +)
{
funPrintUniqueValue2Cube (0x01 << z);
delay (-1);
}
}

/ / X direction by side scan
void funScanByX (void)
{
uint8 x, y;
funPrintUniqueValue2Cube (0x00);
for (x = 0; x <LAYER_COUNT; x + +)
{
funPrintUniqueValue2Cube (0x00); / / if the shield this row, the function becomes gradually face lit.
/ / Because the single beam assignment does not affect the other beam values ​​occur, so in the beginning of each frame is displayed on the full screen clear the screen.
for (y = 0; y <LAYER_COUNT; y + +)
funPrintColumn (funGetColumn (x, y), 0xff);
delay (-1);
}
}

/ / Y direction by side scan
void funScanByY (void)
{
uint8 x, y;
funPrintUniqueValue2Cube (0x00);

for (y = 0; y <LAYER_COUNT; y + +)
{
funPrintUniqueValue2Cube (0x00); / / if the shield this row, the function becomes gradually face lit.
/ / Because the single beam assignment does not affect the other beam values ​​occur, so in the beginning of each frame is displayed on the full screen clear the screen.
for (x = 0; x <LAYER_COUNT; x + +)
funPrintColumn (funGetColumn (x, y), 0xff);
delay (-1);
}
}
The main function is updated to
void main (void)
{
delay (-1);
delay (-1);

UART_Init (); / / initialize the serial port

while (1)
{
/ / Sequentially scanning program running in three directions
funScanByX ();
funScanByY ();
funScanByZ ();
}
}
Tips:
 have been here on the use of a method of establishing subroutine, the animation for "package", so that the main function is clear and concise.
 In the main function while (1) loop, you can still use for, while loop to determine how the animation cycle.
 these animation functions are currently no parameters, interested friends may wish to try whether the internal delay () function parameters as a function of the parameters of the whole, so that when an external call, you can directly control the frame rate up. 

 Sample 3 - upwelling

In the animation block Insert the following functions:
void funDemoRise (uint8 * pCube)
{
uint8 i, x, y, j;

j = 0x80; / / j as a counter to calculate how many times the total rise
while (j -)
{
/ / Rising
for (i = 0; i <rand ()% 4; i + +)
{
pCube [i] << = 1;
}

/ / Bottom again with three new point lights
for (i = 0; i <3; i + +)
{
x = rand ()% 8;
y = rand ()% 8;
pCube [funGetColumn (x, y)] | = 0x01;
}

funPrintCube (pCube);
delay (0x100);
}
}
The main function to read:
void main (void)
{
uint8 pCube [COLUMN_COUNT];

delay (-1); delay (-1);

UART_Init (); / / initialize the serial port
srand (9); / / give a random seed
while (1)
{
funDemoRise (pCube);
}
}
Routine project file download link: http://aguegu.net/wordpress/wp-content/uploads/2011/11/062-3D8-Controller-Demo.zip

Tips:
 used here only batch assignment command, which is what I recommend you use the command. The basic process is that the host computer to establish an internal array, through a variety of operations, changes in the value inside the array in order to achieve the desired results, the operation is completed, use the batch assignment command, the overall output to 3D8 motherboard. Although this amount of data transferred up, you need 65 bytes, but we have made high baud transmission, imperceptible to the naked eye this time, but this design animation process, so the idea of ​​the easiest.
 here used the random function random function is the easiest to make the animation looks less stereotyped way, take advantage of it now. Rand () return value range [0,255], is to take the remainder operator% 8, which can be narrowed down to [0,7].
 bit operation, the microcontroller program, bit operations are frequently used, or used here op | and left shift operator <<. There &, >>, etc., a good refresher, the future will be used to get.
 pointer, and here I use the pointer, the traditional microcontroller program may be more accustomed to using global variables (of course, this variable is an array), but doing so will increase redundancy, sacrificing system stability, consume large amounts of system resources . In fact completely avoided, the C language textbooks turned out to see how the pointer using it. 
 pointer arithmetic, the fear is pointing, pointing, pointing to somewhere else to go, what to do in case of changes will cause the program to crash, runaway. So I added the macro definition LAYER_COUNT and COLUMN_COUNT, the array subscripts caps were clearly defined. And to make use of the pointer p [c] in such a way to call, more intuitive. (Of course, the master of it, even like to use the p + + and the like more obscure statement of ).
 on the counter j, in fact, I do not like this stuff, but it is also the easiest to control animation playback length of the overall approach. If only a single effect, do this cycle worth mentioning.However, if there are multiple animated scrolling display, you need to jump out of this mechanism. Interested friends try, using the keys and other ways to achieve it.


Welcome to participate in the exchange


3D8 light cube official QQ group: 165 068 863

Taobao link: http://item.taobao.com/item.htm?id=10959651858


References:
Video: 3D8 Light Cube 8x8x8 LED communication protocol description
http://v.youku.com/v_show/id_XMjkyNDQ0MzY0.html

Video: Using the 51 smallest single-chip system control 3D8 light cube
http://v.youku.com/v_show/id_XMzE5NzU4NTIw.html