From 66dcf910bd4744d8ced56cb9586aa937a1a2d4c5 Mon Sep 17 00:00:00 2001
From: vg <vgm+dev@devys.org>
Date: Tue, 7 Jul 2020 16:24:01 +0200
Subject: first commit

---
 cube_gl/Makefile        |  14 +
 cube_gl/effect.cpp      | 776 ++++++++++++++++++++++++++++++++++++++++++++++++
 cube_gl/effect.h        |  26 ++
 cube_gl/font.cpp        | 109 +++++++
 cube_gl/font.h          |  13 +
 cube_gl/ledcube.cpp     | 522 ++++++++++++++++++++++++++++++++
 cube_gl/ledcube.cpp.bak | 155 ++++++++++
 7 files changed, 1615 insertions(+)
 create mode 100644 cube_gl/Makefile
 create mode 100644 cube_gl/effect.cpp
 create mode 100644 cube_gl/effect.h
 create mode 100644 cube_gl/font.cpp
 create mode 100644 cube_gl/font.h
 create mode 100644 cube_gl/ledcube.cpp
 create mode 100644 cube_gl/ledcube.cpp.bak

(limited to 'cube_gl')

diff --git a/cube_gl/Makefile b/cube_gl/Makefile
new file mode 100644
index 0000000..7c21b70
--- /dev/null
+++ b/cube_gl/Makefile
@@ -0,0 +1,14 @@
+CFLAGS=`pkg-config glu --cflags` `sdl-config --cflags` -lglut -ansi -Wall -m32
+LIBS=`pkg-config glu --libs` `sdl-config --libs`
+OBJS=ledcube.o effect.o font.o
+
+%.o:%.cpp
+	g++ $(CFLAGS) -o $@ -c $<
+
+all: ledcube
+
+clean:
+	rm -f ledcube $(OBJS)
+
+ledcube: $(OBJS)
+	g++ $(CFLAGS) $(LIBS) $(OBJS) -o $@
diff --git a/cube_gl/effect.cpp b/cube_gl/effect.cpp
new file mode 100644
index 0000000..4288fa0
--- /dev/null
+++ b/cube_gl/effect.cpp
@@ -0,0 +1,776 @@
+
+#include "effect.h"
+#include "font.h"
+#include <SDL.h>
+#include <cassert>
+#include <cmath>
+
+#define CUBE_SIZE 8
+#define CUBE_BYTES CUBE_SIZE*CUBE_SIZE
+#define AXIS_Z 2
+#define AXIS_Y 1
+#define AXIS_X 0
+
+unsigned char leds[8][8];
+volatile bool led_change = false;
+
+//unsigned char pow2[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+//const unsigned char pow2[8] = {128, 64, 32, 16, 8, 4, 2, 1};
+
+/*****************************************************************************
+ * ACCESSORS
+ *****************************************************************************/
+
+unsigned char inrange(int x, int y, int z)
+{
+    if (x >= 0 && x < CUBE_SIZE && y >= 0 && y < CUBE_SIZE && z >= 0 && z < CUBE_SIZE)
+    {
+        return 1;
+    } else
+    {
+        // One of the coordinates was outside the cube.
+        return 0;
+    }
+}
+
+bool get_led(unsigned char x, unsigned char y, unsigned char z)
+{
+    /*
+    assert(x >= 0 && x <= 7);
+    assert(y >= 0 && y <= 7);
+    assert(z >= 0 && z <= 7);
+    */
+
+    if (inrange(x, y, z)) {
+        return leds[y][z] & (1 << x);
+    }
+
+    return false;
+}
+
+void set_led(unsigned char x, unsigned char y, unsigned char z, bool on)
+{
+
+    if (!inrange(x, y, z)) {
+        return;
+    }
+
+    /*
+    assert(x >= 0 && x <= 7);
+    assert(y >= 0 && y <= 7);
+    assert(z >= 0 && z <= 7);
+    */
+
+    if (on) {
+        leds[y][z] |= ((unsigned char)1) << x;
+    }
+    else {
+        leds[y][z] &= ~(((unsigned char)1) << x);
+    }
+}
+
+void clear_led()
+{
+    memset(leds, 0, sizeof(leds));
+}
+
+void set_voxel(int x, int y, int z)
+{
+    set_led(x, y, z, true);
+}
+
+void clr_voxel(int x, int y, int z)
+{
+    set_led(x, y, z, false);
+}
+
+void fill(char val)
+{
+    memset(leds, val, sizeof(leds));
+}
+
+void delay(unsigned t)
+{
+    led_change = true;
+    SDL_Delay(t);
+}
+
+/*****************************************************************************
+ * EFFECTS
+ *****************************************************************************/
+
+void test_effect()
+{
+    static int active_layer = 0;
+
+    for (int k = 0; k < 8; ++k) {
+        //std::cout << "boo" << std::endl;
+        for (int j = 0; j < 8; ++j) {
+            //std::cout << "boo2" << std::endl;
+            if (k == active_layer) {
+                //std::cerr << "active" << std::endl;
+                leds[j][k] = 0xFF;
+            }
+            else leds[j][k] = 0;
+        }
+    }
+    ++active_layer;
+    if (active_layer >= 8) {
+        active_layer = 0;
+    }
+}
+
+
+void sendvoxels_z(int x, int y, int z, int delay)
+{
+    assert(z == 0 || z == 7);
+
+    if (z == 7) {
+        for (int i = 0; i < 7; ++i) {
+            set_led(x, y, i, false);
+            set_led(x, y, i+1, true);
+            led_change = true;
+            SDL_Delay(delay);
+        }
+    }
+    else {
+        for(int i = 6; i >= 0; --i) {
+            set_led(x, y, i + 1, false);
+            set_led(x, y, i, true);
+            led_change = true;
+            SDL_Delay(delay);
+        }
+    }
+}
+
+
+void sendvoxels_random_z_effect(int maxiters,
+        int delay, /* speed of movement */
+        int wait) /* delay between 2 movement */
+{
+    clear_led(); // clear the cube
+    for (int j = 0; j < 8; ++j) {
+        for (int i = 0; i < 8; ++i) {
+            if (rand()%2) {
+                set_led(i, j, 0, true);
+            }
+            else {
+                set_led(i, j, 7, true);
+            }
+        }
+    }
+
+    int previous_x = 0, previous_y = 0;
+    for (int n = 0; n < maxiters ; ++n ) {
+        int x = rand()%8, y = rand()%8;
+
+        if (previous_x == x && previous_y == y) {
+            --n;
+            continue;
+        }
+
+        if (get_led(x, y, 0)) {
+            sendvoxels_z(x, y, 7, delay);
+        }
+        else if (get_led(x, y, 7)) {
+            sendvoxels_z(x, y, 0, delay);
+        }
+        SDL_Delay(wait);
+    }
+
+}
+
+void rain_effect(int iterations)
+{
+
+    for (int i = 0; i < iterations ; ++i) {
+
+        // clear layer 7
+        for (int j = 0 ; j < 8; ++j) {
+            leds[j][7] = 0;
+        }
+
+        // place pixels at random x and y coord at layer 7
+        int n = rand()%4;
+        for (int i2 = 0; i2 < n; ++i2) {
+            set_led(rand()%8, rand()%8, 7, 1);
+        }
+
+        led_change = true;
+        SDL_Delay(90);
+
+        // shift down
+        for (int k = 0; k < 7; ++k) {
+            for (int j = 0 ; j < 8; ++j) {
+                leds[j][k] = leds[j][k+1];
+            }
+        }
+    }
+}
+
+void set_plane(int axis, unsigned char index, bool on = true)
+{
+    switch(axis) {
+        case 0: // X
+            for (int k = 0; k < 8; ++k) {
+                for (int j = 0; j < 8; ++j) {
+                    set_led(index, j, k, on);
+                }
+            }
+            break;
+        case 1: // Y
+            for (int k = 0; k < 8; ++k) {
+                for (int i = 0; i < 8; ++i) {
+                    set_led(i, index, k, on);
+                }
+            }
+            break;
+        case 2: // Z
+            for (int j = 0; j < 8; ++j) {
+                for (int i = 0; i < 8; ++i) {
+                    set_led(i, j, index, on);
+                }
+            }
+            break;
+        default:
+            assert(false);
+    }
+}
+
+void planboing(int plane, int speed)
+{
+    for (int i = 0; i < 8; ++i) {
+        clear_led(); // clear cube
+        set_plane(plane, i);
+        led_change = true;
+        SDL_Delay(speed);
+    }
+    for (int i = 7; i >= 0; --i) {
+        clear_led(); // clear cube
+        set_plane(plane, i);
+        led_change = true;
+        SDL_Delay(speed);
+    }
+}
+
+// Shift the entire contents of the cube along an axis
+// This is great for effects where you want to draw something
+// on one side of the cube and have it flow towards the other
+// side. Like rain flowing down the Z axiz.
+void shift (char axis, int direction)
+{
+    int i, x ,y;
+    int ii, iii;
+    //int state;
+
+    for (i = 0; i < CUBE_SIZE; i++) {
+        if (direction == -1) {
+            ii = i;
+        }
+        else {
+            ii = (7-i);
+        }
+
+
+        for (x = 0; x < CUBE_SIZE; x++)
+        {
+            for (y = 0; y < CUBE_SIZE; y++)
+            {
+                if (direction == -1)
+                {
+                    iii = ii+1;
+                } else
+                {
+                    iii = ii-1;
+                }
+
+                if (axis == 2)
+                {
+                    set_led(x, y, ii, get_led(x, y, iii));
+                    //state = get_led(x,y,iii);
+                    //set_led(x,y,ii,state?false:true);
+                }
+
+                if (axis == 1)
+                {
+                    set_led(x, ii, y, get_led(x, iii, y));
+                    //state = get_led(x,iii,y);
+                    //altervoxel(x,ii,y,state);
+                    //set_led(x,ii,y,state?false:true);
+                }
+
+                if (axis == 0)
+                {
+                    set_led(ii, y, x, get_led(iii, y, x));
+                    //state = get_led(iii,y,x);
+                    //set_led(ii,y,x,state?false:true);
+                }
+            }
+        }
+    }
+
+    if (direction == -1) {
+        i = 7;
+    }
+    else {
+        i = 0;
+    }
+
+    /*
+    for (x = 0; x < CUBE_SIZE; x++) {
+        for (y = 0; y < CUBE_SIZE; y++) {
+            if (axis == AXIS_Z) set_led(x,y,i, false);
+            if (axis == AXIS_Y) set_led(x,i,y, false);
+            if (axis == AXIS_X) set_led(i,y,x, false);
+        }
+    }
+
+    */
+    set_plane(axis, i, false);
+}
+
+
+// Flips a byte 180 degrees.
+// MSB becomes LSB, LSB becomes MSB.
+char flipbyte (char byte)
+{
+    char flop = 0x00;
+
+    flop = (flop & 0b11111110) | (0b00000001 & (byte >> 7));
+    flop = (flop & 0b11111101) | (0b00000010 & (byte >> 5));
+    flop = (flop & 0b11111011) | (0b00000100 & (byte >> 3));
+    flop = (flop & 0b11110111) | (0b00001000 & (byte >> 1));
+    flop = (flop & 0b11101111) | (0b00010000 & (byte << 1));
+    flop = (flop & 0b11011111) | (0b00100000 & (byte << 3));
+    flop = (flop & 0b10111111) | (0b01000000 & (byte << 5));
+    flop = (flop & 0b01111111) | (0b10000000 & (byte << 7));
+    return flop;
+}
+
+// Flip the cube 180 degrees along the y axis.
+void mirror_y (void)
+{
+    unsigned char buffer[CUBE_SIZE][CUBE_SIZE];
+    unsigned char x,y,z;
+
+    memcpy(buffer, leds, CUBE_BYTES); // copy the current cube into a buffer.
+
+    //fill(0x00);
+    clear_led();
+    for (z=0; z<CUBE_SIZE; z++)
+    {
+        for (y=0; y<CUBE_SIZE; y++)
+        {
+            for (x=0; x<CUBE_SIZE; x++)
+            {
+                if (buffer[y][z] & (0x01 << x))
+                    set_led(x,CUBE_SIZE-1-y,z,true);
+            }
+        }
+    }
+
+}
+
+// Flip the cube 180 degrees along the x axis
+void mirror_x (void)
+{
+    unsigned char buffer[CUBE_SIZE][CUBE_SIZE];
+    unsigned char y,z;
+
+    memcpy(buffer, leds, CUBE_BYTES); // copy the current cube into a buffer.
+
+    //fill(0x00);
+    clear_led();
+
+    for (z=0; z<CUBE_SIZE; z++)
+    {
+        for (y=0; y<CUBE_SIZE; y++)
+        {
+            // This will break with different buffer sizes..
+            leds[y][z] = flipbyte(buffer[y][z]);
+        }
+    }
+}
+
+// flip the cube 180 degrees along the z axis
+void mirror_z (void)
+{
+    unsigned char buffer[CUBE_SIZE][CUBE_SIZE];
+    unsigned char z, y;
+
+    memcpy(buffer, leds, CUBE_BYTES); // copy the current cube into a buffer.
+
+    for (y=0; y<CUBE_SIZE; y++)
+    {
+        for (z=0; z<CUBE_SIZE; z++)
+        {
+            leds[y][CUBE_SIZE-1-z] = buffer[y][z];
+        }
+    }
+}
+
+
+// Makes sure x1 is alwas smaller than x2
+// This is usefull for functions that uses for loops,
+// to avoid infinite loops
+void argorder(int ix1, int ix2, int *ox1, int *ox2)
+{
+    if (ix1>ix2)
+    {
+        int tmp;
+        tmp = ix1;
+        ix1= ix2;
+        ix2 = tmp;
+    }
+    *ox1 = ix1;
+    *ox2 = ix2;
+}
+
+// Returns a byte with a row of 1's drawn in it.
+// byteline(2,5) gives 0b00111100
+char byteline (int start, int end)
+{
+    return ((0xff<<start) & ~(0xff<<(end+1)));
+}
+
+
+// Draw a wireframe box. This only draws the corners and edges,
+// no walls.
+void box_wireframe(
+        int x1, int y1, int z1,
+        int x2, int y2, int z2)
+{
+
+    int iy;
+    int iz;
+
+    argorder(x1, x2, &x1, &x2);
+    argorder(y1, y2, &y1, &y2);
+    argorder(z1, z2, &z1, &z2);
+
+    // Lines along X axis
+    leds[y1][z1] = byteline(x1,x2);
+    leds[y2][z1] = byteline(x1,x2);
+    leds[y1][z2] = byteline(x1,x2);
+    leds[y2][z2] = byteline(x1,x2);
+
+    // Lines along Y axis
+    for (iy=y1;iy<=y2;iy++)
+    {
+        set_led(x1,iy,z1, true);
+        set_led(x1,iy,z2, true);
+        set_led(x2,iy,z1, true);
+        set_led(x2,iy,z2, true);
+    }
+
+    // Lines along Z axis
+    for (iz=z1;iz<=z2;iz++)
+    {
+        set_led(x1,y1,iz, true);
+        set_led(x1,y2,iz, true);
+        set_led(x2,y1,iz, true);
+        set_led(x2,y2,iz, true);
+    }
+}
+
+void box_shrink_grow_effect(int iterations, int rot, int flip, int delay)
+{
+    for (int it = 0; it < iterations ; ++it) {
+        for (int it2 = 0; it2 < 16; ++it2) {
+            int xyz = it2 > 7 ? it2 - 8: 7 - it2;
+
+            clear_led();
+
+            box_wireframe(0, 0, 0, xyz, xyz, xyz);
+
+            if (flip > 0) mirror_z();
+            if (rot == 1 || rot == 3) mirror_y();
+            if (rot == 2 || rot == 3) mirror_x();
+
+            led_change = true;
+            SDL_Delay(delay);
+        }
+    }
+}
+
+void effect_box_woopwoop (int delay, int grow)
+{
+    int i,ii;
+
+    //fill(0x00);
+    clear_led();
+    for (i=0;i<4;i++)
+    {
+        ii = i;
+        if (grow > 0)
+            ii = 3-i;
+
+        box_wireframe(4+ii,4+ii,4+ii,3-ii,3-ii,3-ii);
+        led_change = true;
+        SDL_Delay(delay);
+        clear_led();
+        //delay_ms(delay);
+        //fill(0x00);
+    }
+}
+
+void draw_positions_axis (char axis, unsigned char positions[64], int invert)
+{
+    int x, y, p;
+
+    //fill(0x00);
+    clear_led();
+
+    for (x=0; x<8; x++)
+    {
+        for (y=0; y<8; y++)
+        {
+            if (invert)
+            {
+                p = (7-positions[(x*8)+y]);
+            } else
+            {
+                p = positions[(x*8)+y];
+            }
+
+            //if (axis == AXIS_Z)
+            if (axis == 2)
+                set_led(x,y,p, true);
+
+            if (axis == 1)
+                set_led(x,p,y, true);
+
+            if (axis == 0)
+                set_led(p,y,x, true);
+        }
+    }
+
+}
+
+
+
+void effect_axis_updown_randsuspend(char axis,
+        int delay, int sleep, int invert)
+{
+    unsigned char positions[64];
+    unsigned char destinations[64];
+
+    int i,px;
+
+    // Set 64 random positions
+    for (i=0; i<64; i++)
+    {
+        positions[i] = 0; // Set all starting positions to 0
+        destinations[i] = rand()%8;
+    }
+
+    // Loop 8 times to allow destination 7 to reach all the way
+    for (i=0; i<8; i++)
+    {
+        // For every iteration, move all position one step closer to their destination
+        for (px=0; px<64; px++)
+        {
+            if (positions[px]<destinations[px])
+            {
+                positions[px]++;
+            }
+        }
+        // Draw the positions and take a nap
+        draw_positions_axis (axis, positions,invert);
+        led_change = true;
+        SDL_Delay(delay);
+        //delay_ms(delay);
+    }
+
+    // Set all destinations to 7 (opposite from the side they started out)
+    for (i=0; i<64; i++)
+    {
+        destinations[i] = 7;
+    }
+
+    // Suspend the positions in mid-air for a while
+    //delay_ms(sleep);
+    SDL_Delay(sleep);
+
+    // Then do the same thing one more time
+    for (i=0; i<8; i++)
+    {
+        for (px=0; px<64; px++)
+        {
+            if (positions[px]<destinations[px])
+            {
+                positions[px]++;
+            }
+            if (positions[px]>destinations[px])
+            {
+                positions[px]--;
+            }
+        }
+        draw_positions_axis (axis, positions,invert);
+        led_change = true;
+        SDL_Delay(delay);
+        //delay_ms(delay);
+    }
+}
+
+void effect_stringfly2(const char* str)
+{
+    //int x,y,i;
+    unsigned char x,y,i;
+    unsigned char chr[5];
+    int delay = 80;
+
+    clear_led();
+
+    while (*str)
+    {
+        font_getchar(*str++, chr);
+
+        // Put a character on the back of the cube
+        for (x = 0; x < 5; x++)
+        {
+            for (y = 0; y < 8; y++)
+            {
+                if ((chr[x] & (0x80>>y)))
+                {
+                    //setvoxel(7,x+2,y);
+                    //set_led(7,x+2,y);
+                    set_led(x+2, 7, y);
+                }
+            }
+        }
+
+        //led_change = true;
+        //SDL_Delay(1000);
+        //clear_led();
+        //continue;
+
+        // Shift the entire contents of the cube forward by 6 steps
+        // before placing the next character
+        for (i = 0; i<6; i++)
+        {
+            led_change = true;
+            //delay_ms(1000);
+            //SDL_Delay(1000);
+            SDL_Delay(delay);
+            //shift(AXIS_X,-1);
+            shift(1,-1);
+            //set_plane(1, 7, false);
+        }
+    }
+
+    //return;
+    // Shift the last character out of the cube.
+    for (i = 0; i<8; i++)
+    {
+        led_change = true;
+        SDL_Delay(delay);
+        //delay_ms(1000);
+        //shift(AXIS_X,-1);
+        shift(1,-1);
+    }
+}
+
+float distance2d (float x1, float y1, float x2, float y2)
+{
+    float dist;
+    dist = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
+
+    return dist;
+}
+
+float distance3d (float x1, float y1, float z1, float x2, float y2, float z2)
+{
+    float dist;
+    dist = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2));
+
+    return dist;
+}
+
+
+
+
+// Display a sine wave running out from the center of the cube.
+void ripples (int iterations, int delay)
+{
+    float distance, height, ripple_interval;
+    int x,y,i;
+
+    clear_led();
+    //fill(0x00);
+
+    for (i=0;i<iterations;i++)
+    {
+        for (x=0;x<8;x++)
+        {
+            for (y=0;y<8;y++)
+            {
+                distance = distance2d(3.5,3.5,x,y)/9.899495*8;
+                //distance = distance2d(3.5,3.5,x,y);
+                ripple_interval =1.3;
+                height = 4+sin(distance/ripple_interval+(float) i/50)*4;
+
+                //setvoxel(x,y,(int) height);
+                set_led(x,y,(int) height);
+            }
+        }
+        //delay_ms(delay);
+        led_change = true;
+        SDL_Delay(delay);
+        //fill(0x00);
+        clear_led();
+    }
+}
+
+
+
+/*****************************************************************************
+ * EFFECT LAUNCHER
+ *****************************************************************************/
+
+void launch_effect(int effect)
+{
+    switch(effect) {
+        case 0: rain_effect(100); break;
+        case 1: sendvoxels_random_z_effect(20, 50, 100); break;
+        case 2:
+                break;
+        case 3:
+                break;
+        case 4:
+                break;
+        case 5: ripples(1000, 50); break;
+        case 6:
+            for (int i = 0; i < 8; ++i) {
+                box_shrink_grow_effect(1, i%4, i & 0x4, 50);
+            }
+            effect_box_woopwoop(80, 0);
+            effect_box_woopwoop(80, 1);
+            effect_box_woopwoop(80, 0);
+            effect_box_woopwoop(80, 1);
+            break;
+        case 7:
+            for (int i = 0; i < 6; ++i) {
+                planboing(i%3, 50);
+            }
+            break;
+        case 9:
+            effect_axis_updown_randsuspend(2, 55, 100, 0);
+            effect_axis_updown_randsuspend(2, 55, 100, 1);
+            effect_axis_updown_randsuspend(2, 55, 100, 0);
+            effect_axis_updown_randsuspend(2, 55, 100, 1);
+            effect_axis_updown_randsuspend(0, 55, 100, 0);
+            effect_axis_updown_randsuspend(0, 55, 100, 1);
+            effect_axis_updown_randsuspend(1, 55, 100, 0);
+            effect_axis_updown_randsuspend(1, 55, 100, 1);
+            break;
+        case 12:
+            //clear_led();
+            //set_led(0, 0, 7);
+            //SDL_Delay(1000);
+            effect_stringfly2("Vive Lyly");
+            break;
+        default:
+            break;
+    }
+}
diff --git a/cube_gl/effect.h b/cube_gl/effect.h
new file mode 100644
index 0000000..90319d1
--- /dev/null
+++ b/cube_gl/effect.h
@@ -0,0 +1,26 @@
+#ifndef __EFFECT_H__
+#define __EFFECT_H__
+
+const int TOTAL_EFFECTS = 27;
+
+extern unsigned char leds[8][8];
+extern volatile bool led_change;
+
+bool get_led(unsigned char x, unsigned char y, unsigned char z);
+void set_led(unsigned char x, unsigned char y, unsigned char z, bool on = true);
+void clear_led();
+
+void rain_effect(int iterations);
+
+void planboing(int plane, int speed);
+
+void sendvoxels_random_z_effect(int maxiters,
+        int delay, /* speed of movement */
+        int wait); /* delay between 2 movement */
+
+void box_shrink_grow_effect(int iterations, int rotation, int flip, int delay);
+void effect_box_woopwoop (int delay, int grow);
+
+void launch_effect(int effect);
+
+#endif
diff --git a/cube_gl/font.cpp b/cube_gl/font.cpp
new file mode 100644
index 0000000..f48e4af
--- /dev/null
+++ b/cube_gl/font.cpp
@@ -0,0 +1,109 @@
+#include "font.h"
+//#include <avr/eeprom.h>
+
+volatile const unsigned char font[455] /*EEMEM*/ = {
+	0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0x5f,0x00,0x00,	//  !
+	0x00,0x03,0x00,0x03,0x00,0x14,0x7f,0x14,0x7f,0x14,	// "#
+	0x24,0x2a,0x7f,0x2a,0x12,0x23,0x13,0x08,0x64,0x62,	// $%
+	0x36,0x49,0x55,0x22,0x50,0x00,0x05,0x03,0x00,0x00,	// &'
+	0x00,0x1c,0x22,0x41,0x00,0x00,0x41,0x22,0x1c,0x00,	// ()
+	0x14,0x08,0x3e,0x08,0x14,0x08,0x08,0x3e,0x08,0x08,	// *+
+	0x00,0x50,0x30,0x00,0x00,0x08,0x08,0x08,0x08,0x08,	// ,-
+	0x00,0x60,0x60,0x00,0x00,0x20,0x10,0x08,0x04,0x02,	// ./
+	0x3e,0x51,0x49,0x45,0x3e,0x00,0x42,0x7f,0x40,0x00,	// 01
+	0x42,0x61,0x51,0x49,0x46,0x21,0x41,0x45,0x4b,0x31,	// 23
+	0x18,0x14,0x12,0x7f,0x10,0x27,0x45,0x45,0x45,0x39,	// 45
+	0x3c,0x4a,0x49,0x49,0x30,0x01,0x71,0x09,0x05,0x03,	// 67
+	0x36,0x49,0x49,0x49,0x36,0x06,0x49,0x49,0x29,0x1e,	// 89
+	0x00,0x36,0x36,0x00,0x00,0x00,0x56,0x36,0x00,0x00,	// :;
+	0x08,0x14,0x22,0x41,0x00,0x14,0x14,0x14,0x14,0x14,	// <=
+	0x00,0x41,0x22,0x14,0x08,0x02,0x01,0x51,0x09,0x06,	// >?
+	0x32,0x49,0x79,0x41,0x3e,0x7e,0x11,0x11,0x11,0x7e,	// @A
+	0x7f,0x49,0x49,0x49,0x36,0x3e,0x41,0x41,0x41,0x22,	// BC
+	0x7f,0x41,0x41,0x22,0x1c,0x7f,0x49,0x49,0x49,0x41,	// DE
+	0x7f,0x09,0x09,0x09,0x01,0x3e,0x41,0x49,0x49,0x7a,	// FG
+	0x7f,0x08,0x08,0x08,0x7f,0x00,0x41,0x7f,0x41,0x00,	// HI
+	0x20,0x40,0x41,0x3f,0x01,0x7f,0x08,0x14,0x22,0x41,	// JK
+	0x7f,0x40,0x40,0x40,0x40,0x7f,0x02,0x0c,0x02,0x7f,	// LM
+	0x7f,0x04,0x08,0x10,0x7f,0x3e,0x41,0x41,0x41,0x3e,	// NO
+	0x7f,0x09,0x09,0x09,0x06,0x3e,0x41,0x51,0x21,0x5e,	// PQ
+	0x7f,0x09,0x19,0x29,0x46,0x46,0x49,0x49,0x49,0x31,	// RS
+	0x01,0x01,0x7f,0x01,0x01,0x3f,0x40,0x40,0x40,0x3f,	// TU
+	0x1f,0x20,0x40,0x20,0x1f,0x3f,0x40,0x38,0x40,0x3f,	// VW
+	0x63,0x14,0x08,0x14,0x63,0x07,0x08,0x70,0x08,0x07,	// XY
+	0x61,0x51,0x49,0x45,0x43,0x00,0x7f,0x41,0x41,0x00,	// Z[
+	0x02,0x04,0x08,0x10,0x20,0x00,0x41,0x41,0x7f,0x00,	// \]
+	0x04,0x02,0x01,0x02,0x04,0x40,0x40,0x40,0x40,0x40,	// ^_
+	0x00,0x01,0x02,0x04,0x00,0x20,0x54,0x54,0x54,0x78,	// `a
+	0x7f,0x48,0x44,0x44,0x38,0x38,0x44,0x44,0x44,0x20,	// bc
+	0x38,0x44,0x44,0x48,0x7f,0x38,0x54,0x54,0x54,0x18,	// de
+	0x08,0x7e,0x09,0x01,0x02,0x0c,0x52,0x52,0x52,0x3e,	// fg
+	0x7f,0x08,0x04,0x04,0x78,0x00,0x44,0x7d,0x40,0x00,	// hi
+	0x20,0x40,0x44,0x3d,0x00,0x7f,0x10,0x28,0x44,0x00,	// jk
+	0x00,0x41,0x7f,0x40,0x00,0x7c,0x04,0x18,0x04,0x78,	// lm
+	0x7c,0x08,0x04,0x04,0x78,0x38,0x44,0x44,0x44,0x38,	// no
+	0x7c,0x14,0x14,0x14,0x08,0x08,0x14,0x14,0x18,0x7c,	// pq
+	0x7c,0x08,0x04,0x04,0x08,0x48,0x54,0x54,0x54,0x20,	// rs
+	0x04,0x3f,0x44,0x40,0x20,0x3c,0x40,0x40,0x20,0x7c,	// tu
+	0x1c,0x20,0x40,0x20,0x1c,0x3c,0x40,0x30,0x40,0x3c,	// vw
+	0x44,0x28,0x10,0x28,0x44,0x0c,0x50,0x50,0x50,0x3c,	// xy
+	0x44,0x64,0x54,0x4c,0x44				// z
+};
+
+
+volatile const unsigned char bitmaps[6][8] /*EEMEM*/ = {
+	{0xc3,0xc3,0x00,0x18,0x18,0x81,0xff,0x7e}, // smiley 3 small
+	{0x3c,0x42,0x81,0x81,0xc3,0x24,0xa5,0xe7}, // Omega
+	{0x00,0x04,0x06,0xff,0xff,0x06,0x04,0x00},  // Arrow
+	{0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81}, // X
+	{0xBD,0xA1,0xA1,0xB9,0xA1,0xA1,0xA1,0x00}, // ifi
+	{0xEF,0x48,0x4B,0x49,0x4F,0x00,0x00,0x00} // TG
+};
+
+const unsigned char paths[44] /*PROGMEM */= {0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x67,0x57,0x47,0x37,0x27,0x17,
+0x04,0x03,0x12,0x21,0x30,0x40,0x51,0x62,0x73,0x74,0x65,0x56,0x47,0x37,0x26,0x15}; // circle, len 16, offset 28
+
+/*
+void font_getpath (unsigned char path, unsigned char *destination, int length)
+{
+	int i;
+	int offset = 0;
+	
+	if (path == 1)
+		offset=28;
+	
+	for (i = 0; i < length; i++)
+		destination[i] = pgm_read_byte(&paths[i+offset]);
+}
+*/
+
+void font_getchar (char chr, unsigned char dst[5])
+{
+	//uint8_t i;
+    unsigned char i;
+	chr -= 32; // our bitmap font starts at ascii char 32.
+	
+    for (i = 0; i < 5; i++)
+		//dst[i] = (unsigned char)eeprom_read_byte((uint8_t*)&font[(chr*5)+i]);
+		dst[i] = font[(chr*5)+i];
+}
+
+/*
+void font_getbitmap (char bitmap, unsigned char dst[8])
+{
+	int i;
+	
+    for (i = 0; i < 8; i++)
+		dst[i] = (unsigned char)eeprom_read_byte((uint8_t*)&bitmaps[(uint8_t)bitmap][(uint8_t)i]);
+	
+}
+
+unsigned char font_getbitmappixel ( char bitmap, char x, char y)
+{
+	uint8_t tmp = eeprom_read_byte((uint8_t*)&bitmaps[(uint8_t)bitmap][(uint8_t)x]);
+	return (tmp >> y) & 0x01;
+}
+
+*/
+
+
diff --git a/cube_gl/font.h b/cube_gl/font.h
new file mode 100644
index 0000000..536801e
--- /dev/null
+++ b/cube_gl/font.h
@@ -0,0 +1,13 @@
+#ifndef FONT_H
+#define FONT_H
+
+//#include <avr/pgmspace.h>
+
+void font_getchar (char chr, unsigned char dst[5]);
+//void font_getpath (unsigned char path, unsigned char *destination, int length);
+//void font_getbitmap (char bitmap, unsigned char dst[8]);
+//unsigned char font_getbitmappixel ( char bitmap, char x, char y);
+
+
+
+#endif
diff --git a/cube_gl/ledcube.cpp b/cube_gl/ledcube.cpp
new file mode 100644
index 0000000..91c869c
--- /dev/null
+++ b/cube_gl/ledcube.cpp
@@ -0,0 +1,522 @@
+/*
+* Copyright 2010 - Jean-Baptiste Fasquel
+* ISTIA - Angers university
+* Jean-Baptiste.Fasquel@univ-angers.fr
+*/
+//#include "stdafx.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+#include <math.h>
+#include <GL/glut.h>
+
+#include <string.h>
+#include <strings.h>
+#include <time.h>
+
+#include "effect.h"
+
+#include <SDL.h>
+#include <SDL_thread.h>
+
+volatile bool thread_must_quit = false;
+//unsigned char pow2[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+//const unsigned char pow2[8] = {128, 64, 32, 16, 8, 4, 2, 1};
+
+const float ViewedPointX = 0.0;
+const float ViewedPointY = 0.0;
+const float ViewedPointZ = 0.0;
+
+const float CurrentViewUpX = 0;
+const float CurrentViewUpY = 1;
+const float CurrentViewUpZ = 0;
+
+float CurrentCameraPosX;
+float CurrentCameraPosY;
+float CurrentCameraPosZ;
+
+int nbCaseX = 10;
+int nbCaseZ = 10;
+
+// 3.14159
+const float CPI = M_PI;
+const float C2PI = 2*CPI;
+
+float current_angle = CPI/2;
+float current_angle2 = 0;//CPI/2;
+const float angle_delta = 0.2;
+float dist = 20;
+const float dist_delta = 1;
+
+enum direction_en {
+    D_LEFT,
+    D_RIGHT
+};
+
+void update_camera()
+{
+    //CurrentCameraPosX =  dist * cosf(current_angle);
+    //CurrentCameraPosZ = dist * sinf(current_angle);
+
+    CurrentCameraPosX = dist*cosf(current_angle)*cosf(current_angle2);
+    CurrentCameraPosZ = dist*sinf(current_angle)*cosf(current_angle2);
+    CurrentCameraPosY = dist*sinf(current_angle2); //* cosf(current_angle);
+
+    //CurrentCameraPosX = dist*sinf(current_angle)*sinf(current_angle2);
+    //CurrentCameraPosZ = dist*sinf(current_angle)*cosf(current_angle2);
+    //CurrentCameraPosY = dist*cosf(current_angle2);
+
+    //glRotatef(current_angle, 0, 0, 1);
+    //glRotatef(current_angle2, 0, 1, 0);
+    glutPostRedisplay();
+}
+
+void rotate_camera(direction_en dir)
+{
+    switch(dir) {
+        case D_LEFT:
+            current_angle += angle_delta;
+            break;
+        case D_RIGHT:
+            current_angle -= angle_delta;
+            break;
+    }
+    if (current_angle > C2PI) {
+        current_angle -= C2PI;
+    }
+    else if (current_angle < -C2PI) {
+        current_angle += C2PI;
+    }
+}
+
+/// Draw axis
+void drawAxis()
+{
+    glDisable(GL_LIGHTING);
+    glLineWidth(1);
+    glBegin(GL_LINES);
+        //(0,x) en rouge
+        glColor3d(1,0,0);
+        glVertex3i(0,0,0);
+        glVertex3i(1,0,0);
+        //(O,y) en vert
+        glColor3d(0,1,0);
+        glVertex3i(0,0,0);
+        glVertex3i(0,1,0);
+        //(O,z) en bleu
+        glColor3d(0,0,1);
+        glVertex3i(0,0,0);
+        glVertex3i(0,0,1);
+    glEnd();
+    glEnable(GL_LIGHTING);
+}
+
+/// DrawQuad
+void drawQuad()
+{
+    glBegin(GL_QUADS);
+        glVertex3f(0.0,0.0,0.0);
+        glVertex3f(0.0,0.0,1.0);
+        glVertex3f(1.0,0.0,1.0);
+        glVertex3f(1.0,0.0,0.0);
+    glEnd();
+}
+
+/// DrawDamier
+void drawDamier()
+{
+    float black[3]={0.0,0.0,0.0};
+    float white[3]={1.0,1.0,1.0};
+    for( int i = -nbCaseX ; i <= nbCaseX ; i++ )
+    {
+        for( int k = -nbCaseZ ; k <= nbCaseZ ; k++ )
+        {
+            int c=pow((float)(-1),i+k); // (-1)^{i+k}
+            c < 0 ? glColor3fv(white) : glColor3fv(black); ;
+            glPushMatrix();
+            glTranslatef((GLfloat )i,0.0,(GLfloat )k);
+            drawQuad();
+            glPopMatrix();
+        }
+    }
+}
+
+float led_size = 0.1;
+float led_spacing = 1.4;
+
+void draw_led(bool on)
+{
+    glPushMatrix();
+    //glTranslatef(4, 0, 4);
+    //glTranslatef(0.05,0.05,0.05);
+    //glColor3f(on?1.0:0.3, 0.2, 0.2);
+    glColor4f(on?1.0:0.5, on?0.6:0.4, on?0.6:0.4, on?1:0.3);
+    glutSolidCube(led_size);
+    glPopMatrix();
+}
+
+void draw_ledcube()
+{
+    glPushMatrix();
+
+    float translate_size = -led_spacing*8/2;
+    glTranslatef(translate_size, translate_size, -translate_size);
+
+    for (int k = 0; k < 8; ++k) {
+        glPushMatrix();
+        for (int j = 0; j < 8; ++j) {
+            glPushMatrix();
+            for (int i = 0; i < 8; ++i) {
+                //draw_led((i+j*k)%2);
+                //draw_led(leds[j][k] & pow2[i]);
+                //if (i == j && j == k && k == 0) draw_led(true); else
+                draw_led(get_led(i, j, k));
+                glTranslatef(led_spacing, 0, 0);
+            }
+            glPopMatrix();
+            glTranslatef(0, 0, -led_spacing);
+        }
+        glPopMatrix();
+        glTranslatef(0, led_spacing, 0);
+    }
+
+    glPopMatrix();
+}
+
+///(Re)Configure la caméra et affiche le contenu de la scène
+void Displayfct()
+{
+    glClearColor(0,0,0,0); // selectionne la couleur noire (qui est celle par défaut)
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    //Model view pour définir la caméra
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();   // Restaure la matrice de modélisation-visualisation
+
+    //glRotatef(current_angle, 0, 1, 0);
+    //glRotatef(current_angle2, 1, 0, 1);
+
+    gluLookAt(CurrentCameraPosX, CurrentCameraPosY , CurrentCameraPosZ,
+            ViewedPointX, ViewedPointY, ViewedPointZ, CurrentViewUpX,
+            CurrentViewUpY, CurrentViewUpZ);
+    //Draw axis
+    //drawAxis();
+    //Draw damier
+    //drawDamier();
+    //Draw ilot
+    //drawIlot();
+
+    // draw led cube
+    draw_ledcube();
+
+    //vide tous les buffers et exécute toutes les commandes en attente
+    //glFlush();
+    glutSwapBuffers();
+}
+///Invoqué pour le changement de taille de la fenêtre avant le Displayfct()
+void ReshapeFunc(int w,int h)
+{
+    //printf("ReshapeFunc: %d, %d\n",w,h);
+    glViewport(0,0,w,h); // Ajustement de la taille de la fenêtre
+    glMatrixMode(GL_PROJECTION); // Choisit la matrice de projection
+    glLoadIdentity();
+    glFrustum(-1.,1.,-1.,1.,1.,40.);
+}
+
+void animation(int x)
+{
+    ((void)x);
+
+    //test_effect(); // 100 ms
+    //rain_effect(); // 100 ms
+    //plane_effect(); // 50ms
+
+    if (led_change) {
+        led_change = false;
+        glutPostRedisplay();
+    }
+
+    glutTimerFunc(40, animation, 0);
+}
+
+void IdleFunct()
+{
+    static int nbRedisplay = 0 ;
+
+    //Pour éviter de surcharger la machine pendant trop longtemps
+    if( nbRedisplay < 100 ) {
+        rotate_camera(D_RIGHT);
+        update_camera();
+        nbRedisplay = 0;
+    }
+    else {
+        ++nbRedisplay ;
+    }
+}
+
+///Gère les menus
+void MainMenuCallBack(int selection)
+{
+    static bool idle_active = false;
+    static bool light0_active = true;
+    static bool light1_active = true;
+    switch(selection)
+    {
+        case 0:
+            if (idle_active) {
+                idle_active = false;
+                glutIdleFunc(0);
+            }
+            else {
+                idle_active = true;
+                glutIdleFunc(IdleFunct);
+            }
+            break;
+        case 1 :
+            thread_must_quit = true;
+            exit(0);
+            break;
+        case 2 : /* toggle light 0 */
+            if (light0_active) {
+                glDisable(GL_LIGHT0);
+                light0_active = false;
+            }
+            else {
+                glEnable(GL_LIGHT0);
+                light0_active = true;
+            }
+            glutPostRedisplay();
+            break;
+        case 3 : /* toggle light 1 */
+            if (light1_active) {
+                glDisable(GL_LIGHT1);
+                light1_active = false;
+            }
+            else {
+                glEnable(GL_LIGHT1);
+                light1_active = true;
+            }
+            glutPostRedisplay();
+            break;
+        default:
+            return;
+            break;
+    }
+}
+
+void initgl()
+{
+    glClearColor(0.0,0.0,0.0,0.0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glShadeModel(GL_SMOOTH) ; //en GL_FLAT: on voit les détails de la sphère
+    glEnable(GL_DEPTH_TEST) ;
+
+    glEnable(GL_LIGHTING);
+    glEnable(GL_COLOR_MATERIAL); //sinon, pas de couleurs
+
+    ///Light0
+    GLfloat lightColor0[4]      = {1.0,1.0,0.5,1.0};
+    glLightfv(GL_LIGHT0,GL_AMBIENT,lightColor0);
+    GLfloat lightPos0[4] = {1.0,0.0,1.0,0.0};
+    glLightfv(GL_LIGHT0,GL_POSITION,lightPos0);
+    glEnable(GL_LIGHT0) ;
+
+    ///Light1
+    GLfloat lightColor1[4]      = {0.5,1.0,1.0,1.0};
+    glLightfv(GL_LIGHT1,GL_AMBIENT,lightColor1);
+    GLfloat lightPos1[4] = {-1.0,0.0,1.0,0.0};
+    glLightfv(GL_LIGHT1,GL_POSITION,lightPos1);
+    glEnable(GL_LIGHT1) ;
+
+    //CurrentCameraPosX =  dist * cosf(current_angle);
+    //CurrentCameraPosZ = dist * sinf(current_angle);
+
+
+    glEnable(GL_BLEND); // activation blending pour la transparence
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    /*
+    for (int i = 0; i < 8; ++i) {
+        for (int j = 0; j < 8; ++j) {
+            leds[i][j] = 0xF0;
+        }
+    }
+    */
+
+    srand(time(0));
+    animation(0);
+    update_camera();
+}
+
+void keyboardfunc(unsigned char key, int x, int y)
+{
+    if (key == 0x1b || key == 'q' || key == 'Q') {
+        thread_must_quit = true;
+        exit(0);
+    }
+}
+
+void specialfunc(int key, int x, int y)
+{
+    switch(key) {
+        case GLUT_KEY_UP:
+            dist -= dist_delta;
+            break;
+        case GLUT_KEY_DOWN:
+            dist += dist_delta;
+            break;
+        case GLUT_KEY_LEFT:
+            rotate_camera(D_LEFT);
+            break;
+        case GLUT_KEY_RIGHT:
+            rotate_camera(D_RIGHT);
+            break;
+    }
+
+    if (dist < 1) {
+        dist = 1;
+    }
+
+    update_camera();
+}
+
+bool mouse_update_camera = false;
+int mouse_x;
+int mouse_y;
+
+#if !defined(GLUT_WHEEL_UP)
+#  define GLUT_WHEEL_UP   3
+#  define GLUT_WHEEL_DOWN 4
+#endif
+
+void mousefunc(int button, int state, int x, int y)
+{
+    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
+        mouse_x = x;
+        mouse_y = y;
+        mouse_update_camera = true;
+    }
+    else if (button == GLUT_WHEEL_UP && state == GLUT_UP) {
+        dist -= dist_delta;
+        update_camera();
+    }
+    else if (button == GLUT_WHEEL_DOWN && state == GLUT_UP) {
+        dist += dist_delta;
+        update_camera();
+    }
+    else {
+        //std::cerr << "button : " << button << std::endl;
+        mouse_update_camera = false;
+    }
+}
+
+void motionfunc(int x, int y)
+{
+    if (mouse_update_camera) {
+        int diff_x = x - mouse_x;
+        int diff_y = y - mouse_y;
+        mouse_x = x;
+        mouse_y = y;
+        //std::cout << mouse_x - x << " " << mouse_y - y << std::endl;
+
+        float scale_factor = 0.05;
+
+        current_angle  += diff_x * scale_factor;
+        current_angle2 += diff_y * scale_factor;
+
+        if (current_angle2 >= CPI/2) {
+            current_angle2 = CPI/2 - 0.0001;
+        }
+        else if(current_angle2 <= -CPI/2) {
+            current_angle2 = - CPI/2 + 0.0001;
+        }
+
+        //CurrentCameraPosY += diff_y * 0.2;
+        //CurrentCameraPosY += diff_y * 0.2;
+        update_camera();
+    }
+}
+
+SDL_Thread* thread = 0;
+void sdl_exit_thread()
+{
+    if (thread) {
+        ;
+        //SDL_WaitThread(thread, 0);
+    }
+}
+
+int thread_func(void* unused)
+{
+    ((void)unused);
+    while (!thread_must_quit) {
+        launch_effect(rand()%TOTAL_EFFECTS);
+        //launch_effect(12);
+
+        //rain_effect(1000);
+        //for (int i = 0; i < 6; ++i) {
+        //    //planboing(i%3, 50);
+        //}
+        ////sendvoxels_random_z_effect(1000, 50, 100);
+        //for (int i = 0; i < 8; ++i) {
+        //    box_shrink_grow_effect(1, i%4, i & 0x4, 50);
+        //}
+        //effect_box_woopwoop(80, 0);
+        //effect_box_woopwoop(80, 1);
+        //effect_box_woopwoop(80, 0);
+        //effect_box_woopwoop(80, 1);
+        //SDL_Delay(40);
+    }
+    return 0;
+}
+
+int main(int argc,char **argv)
+{
+    //Initialisation de la fenêtre
+    glutInit(&argc,argv);
+    glutInitWindowPosition(100,100);
+    glutInitWindowSize(400,400);
+    glutInitDisplayMode(GLUT_RGBA |GLUT_DOUBLE | GLUT_DEPTH);
+    glutCreateWindow("TD1");
+
+    if (SDL_Init(SDL_INIT_TIMER) < 0) {
+        std::cerr << "Error: " << SDL_GetError() << std::endl;
+        exit(1);
+    }
+    atexit(SDL_Quit);
+
+    //Initialisation d'opengl
+    initgl();
+
+    //Menu
+    glutCreateMenu(MainMenuCallBack);
+    glutAddMenuEntry("Toggle animation", 0);
+    glutAddMenuEntry("Toggle light 0", 2);
+    glutAddMenuEntry("Toggle light 1", 3);
+    glutAddMenuEntry("Quitter",1);
+    glutAttachMenu(GLUT_RIGHT_BUTTON);
+
+    //Callbacks
+    glutDisplayFunc(Displayfct);
+    glutReshapeFunc(ReshapeFunc);
+    glutSpecialFunc(specialfunc);
+    glutKeyboardFunc(keyboardfunc);
+    glutMouseFunc(mousefunc);
+    glutMotionFunc(motionfunc);
+
+
+    // thread
+    thread = SDL_CreateThread(thread_func, 0);
+    if (!thread) {
+        std::cerr << "Error creating thread : " << SDL_GetError() << std::endl;
+        exit(1);
+    }
+    atexit(sdl_exit_thread);
+
+    //Infinite loop
+    glutMainLoop();
+
+    thread_must_quit = true;
+
+    return 0;
+}
diff --git a/cube_gl/ledcube.cpp.bak b/cube_gl/ledcube.cpp.bak
new file mode 100644
index 0000000..2fd6bd7
--- /dev/null
+++ b/cube_gl/ledcube.cpp.bak
@@ -0,0 +1,155 @@
+#include <GL/gl.h>
+#include <GL/glut.h>
+#include <stdlib.h>
+#include <math.h>
+
+//angle of rotation
+float xpos = 0, ypos = 0, zpos = 0, xrot = 0, yrot = 0, angle=0.0;
+
+float lastx, lasty;
+
+//positions of the cubes
+float positionz[10];
+float positionx[10];
+
+void cubepositions (void) { //set the positions of the cubes
+
+    for (int i=0;i<10;i++)
+    {
+        positionz[i] = rand()%5 + 5;
+        positionx[i] = rand()%5 + 5;
+    }
+}
+
+//draw the cube
+void cube (void) {
+    for (int i=0;i<10;i++)
+    {
+        glPushMatrix();
+        glTranslated(-positionx[i + 1] * 10, 0, -positionz[i + 1] *
+                10); //translate the cube
+        glutSolidCube(2); //draw the cube
+        glPopMatrix();
+    }
+}
+
+void init (void) {
+    cubepositions();
+}
+
+void enable (void) {
+    glEnable (GL_DEPTH_TEST); //enable the depth testing
+    glEnable (GL_LIGHTING); //enable the lighting
+    glEnable (GL_LIGHT0); //enable LIGHT0, our Diffuse Light
+    glShadeModel (GL_SMOOTH); //set the shader to smooth shader
+
+}
+
+void camera (void) {
+    glRotatef(xrot,1.0,0.0,0.0);  //rotate our camera on teh x-axis (left and right)
+    glRotatef(yrot,0.0,1.0,0.0);  //rotate our camera on the y-axis (up and down)
+    glTranslated(-xpos,-ypos,-zpos); //translate the screen to the position of our camera
+}
+
+void display (void) {
+    glClearColor (1.0,0.0,0.0,1.0); //clear the screen to black
+    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear the color buffer and the depth buffer
+    glLoadIdentity();
+    camera();
+    enable();
+    cube(); //call the cube drawing function
+    glutSwapBuffers(); //swap the buffers
+    angle++; //increase the angle
+}
+
+void reshape (int w, int h) {
+    glViewport (0, 0, (GLsizei)w, (GLsizei)h); //set the viewport to the current window specifications
+    glMatrixMode (GL_PROJECTION); //set the matrix to projection
+
+    glLoadIdentity ();
+    gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 1000.0); //set the perspective (angle of sight, width, height, , depth)
+    glMatrixMode (GL_MODELVIEW); //set the matrix back to model
+
+}
+
+void keyboard (unsigned char key, int x, int y) {
+    if (key=='q')
+    {
+        xrot += 1;
+        if (xrot >360) xrot -= 360;
+    }
+
+    if (key=='z')
+    {
+        xrot -= 1;
+        if (xrot < -360) xrot += 360;
+    }
+
+    if (key=='w')
+    {
+        float xrotrad, yrotrad;
+        yrotrad = (yrot / 180 * 3.141592654f);
+        xrotrad = (xrot / 180 * 3.141592654f);
+        xpos += float(sin(yrotrad)) ;
+        zpos -= float(cos(yrotrad)) ;
+        ypos -= float(sin(xrotrad)) ;
+    }
+
+    if (key=='s')
+    {
+        float xrotrad, yrotrad;
+        yrotrad = (yrot / 180 * 3.141592654f);
+        xrotrad = (xrot / 180 * 3.141592654f);
+        xpos -= float(sin(yrotrad));
+        zpos += float(cos(yrotrad)) ;
+        ypos += float(sin(xrotrad));
+    }
+
+    if (key=='d')
+    {
+        float yrotrad;
+        yrotrad = (yrot / 180 * 3.141592654f);
+        xpos += float(cos(yrotrad)) * 0.2;
+        zpos += float(sin(yrotrad)) * 0.2;
+    }
+
+    if (key=='a')
+    {
+        float yrotrad;
+        yrotrad = (yrot / 180 * 3.141592654f);
+        xpos -= float(cos(yrotrad)) * 0.2;
+        zpos -= float(sin(yrotrad)) * 0.2;
+    }
+
+    if (key==27)
+    {
+        exit(0);
+    }
+}
+
+void mouseMovement(int x, int y) {
+    int diffx=x-lastx; //check the difference between the current x and the last x position
+    int diffy=y-lasty; //check the difference between the current y and the last y position
+    lastx=x; //set lastx to the current x position
+    lasty=y; //set lasty to the current y position
+    xrot += (float) diffy; //set the xrot to xrot with the addition of the difference in the y position
+    yrot += (float) diffx;    //set the xrot to yrot with the addition of the difference in the x position
+}
+
+int main (int argc, char **argv) {
+    glutInit (&argc, argv);
+    glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH);
+    glutInitWindowSize (500, 500);
+    glutInitWindowPosition (100, 100);
+    glutCreateWindow ("A basic OpenGL Window");
+    init ();
+    glutDisplayFunc (display);
+    glutIdleFunc (display);
+    glutReshapeFunc (reshape);
+    glutPassiveMotionFunc(mouseMovement); //check for mouse movement
+    glutKeyboardFunc (keyboard);
+    glutMainLoop ();
+    return 0;
+}
+
+
-- 
cgit v1.2.3