Initial commit

This commit is contained in:
2018-04-13 20:26:33 +02:00
parent 6f842a9a1c
commit 4bdda383f5
10 changed files with 834 additions and 12 deletions

410
FrameBuffer.cpp Normal file
View File

@@ -0,0 +1,410 @@
/*
* Copyright (c) 2018, Lionel Adrien Sambuc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <Arduino.h>
#include <MsTimer2.h>
#include "FrameBuffer.h"
/* All the code assumes dimensions are below 127, as signed chars are used to
* store positions and indices. */
#define MAX_X 4
#define MAX_Y 4
#define MAX_Z 4
#define BRIGHTNESS_LEVELS 16
#define BRIGHTNESS_MAX 256
// Positions (x,y) to pin, same for all layers.
static char position2pin[MAX_X][MAX_Y] = {
{13, 12, 11, 10},
{ 9, 8, 7, 6},
{ 5, 4, 3, 2},
{ 1, 0, A5, A4}
};
// z-coordinate position to pin.
static char layer[MAX_Z] = { A0, A1, A2, A3 };
static unsigned char font[][4][4] = {
// a
{
{0,0,0,0},
{1,1,1,0},
{1,0,1,0},
{1,1,1,1},
},
// b
{
{1,0,0,0},
{1,1,1,0},
{1,0,1,0},
{1,1,1,0},
},
// c
{
{0,0,0,0},
{1,1,1,0},
{1,0,0,0},
{1,1,1,0},
},
// d
{
{0,0,1,0},
{1,1,1,0},
{1,0,1,0},
{1,1,1,0},
},
// e
{
{1,1,1,0},
{1,1,1,0},
{1,0,0,0},
{1,1,1,0},
},
// f
{
{1,1,1,0},
{1,0,0,0},
{1,1,0,0},
{1,0,0,0},
},
// g
{
{1,1,1,1},
{1,0,0,0},
{1,0,1,1},
{1,1,1,1},
},
// h
{
{1,0,0,0},
{1,0,0,0},
{1,1,1,0},
{1,0,1,0},
},
// i
{
{0,1,0,0},
{0,0,0,0},
{0,1,0,0},
{0,1,0,0},
},
// j
{
{0,0,1,0},
{0,0,1,0},
{1,0,1,0},
{1,1,1,0},
},
// k
{
{1,0,0,0},
{1,0,1,0},
{1,1,0,0},
{1,0,1,0},
},
// l
{
{0,1,0,0},
{0,1,0,0},
{0,1,0,0},
{0,1,1,0},
},
// M
{
{1,0,0,1},
{1,1,1,1},
{1,0,0,1},
{1,0,0,1},
},
// n
{
{0,0,0,0},
{1,0,1,1},
{0,1,0,1},
{0,1,0,1},
},
// o
{
{0,0,0,0},
{1,1,1,0},
{1,0,1,0},
{1,1,1,0},
},
// p
{
{1,1,1,0},
{1,0,1,0},
{1,1,1,0},
{1,0,0,0},
},
// q
{
{1,1,1,0},
{1,0,1,0},
{1,1,1,0},
{0,0,1,0},
},
// r
{
{1,1,1,0},
{1,0,1,0},
{1,1,1,0},
{1,0,0,1},
},
// s
{
{1,1,1,0},
{0,1,0,0},
{0,0,1,0},
{1,1,1,0},
},
// T
{
{1,1,1,0},
{0,1,0,0},
{0,1,0,0},
{0,1,0,0},
},
// u
{
{0,0,0,0},
{1,0,1,0},
{1,0,1,0},
{1,1,1,0},
},
// v
{
{0,0,0,0},
{1,0,1,0},
{1,0,1,0},
{0,1,0,0},
},
// Ww
{
{1,0,0,1},
{1,0,0,1},
{1,1,1,1},
{1,0,0,1},
},
// x
{
{0,0,0,0},
{1,0,1,0},
{1,1,1,0},
{1,0,1,0},
},
// y
{
{0,0,0,0},
{1,0,1,0},
{0,1,0,0},
{0,1,0,0},
},
// z
{
{1,1,1,1},
{0,0,1,0},
{0,1,0,0},
{1,1,1,1},
}
};
#define FRAMEBUFFER_POINTERS 1 /* Either 1 (Enabled) or 0 (disabled) */
#if FRAMEBUFFER_POINTERS
struct Frame frames[2];
struct FrameBuffer {
unsigned char intensity = 0;
Frame *front = &frames[0];
Frame *back = &frames[1];
} FrameBuffer;
#else
struct FrameBuffer {
unsigned char visible = 0;
unsigned char intensity = 0;
Frame frames[2];
} FrameBuffer;
#endif
extern char position2pin[MAX_X][MAX_Y];
extern char layer[MAX_Z];
void FrameBufferSwitch(void) {
#if FRAMEBUFFER_POINTERS
Frame * t = FrameBuffer.back;
FrameBuffer.back = FrameBuffer.front;
FrameBuffer.front = t;
#else
FrameBuffer.visible = (FrameBuffer.visible + 1) & 0x1;
#endif
}
Frame *FrameBufferGetFront(void) {
#if FRAMEBUFFER_POINTERS
return FrameBuffer.front;
#else
return &FrameBuffer.frames[FrameBuffer.visible];
#endif
}
Frame *FrameBufferGetBack(void) {
#if FRAMEBUFFER_POINTERS
return FrameBuffer.back;
#else
return &FrameBuffer.frames[(FrameBuffer.visible + 1) & 0x1];
#endif
}
void FrameBufferWrite(char x, char y, char z, unsigned char val) {
FrameBufferGetBack()->data[x][y][z] = val;
}
static void letter(char l, char brightness) {
memset(FrameBufferGetBack(), 0, FRAME_SIZE());
for (char x = 0; x < MAX_X; x++) {
for (char y = 0; y < MAX_Y; y++) {
FrameBufferGetBack()->data[3][y][3-x] =
font[l - 'a'][x][y] * brightness;
}
}
FrameBufferSwitch();
delay(200);
}
void printAllSymbols() {
for(char c = 0; c < sizeof(font)/sizeof(font[0]); c++) {
letter(c+'a', 127);
delay(500);
}
}
void FrameBufferWriteStr(char * str, const short delayPerLetter,
const unsigned char brightness) {
unsigned char *c = str;
while(*c != 0) {
if (*c == ' ') {
memset(FrameBufferGetBack(), 0, FRAME_SIZE());
FrameBufferSwitch();
} else {
letter(*c, brightness);
}
delay(delayPerLetter);
// Make sure there is a white space between font
memset(FrameBufferGetBack(), 0, FRAME_SIZE());
FrameBufferSwitch();
delay(delayPerLetter/4);
c++;
}
}
void FrameBufferRefresh(void) {
Frame *f = FrameBufferGetFront();
#if BRIGHTNESS_INCREMENT
FrameBuffer.intensity =
(FrameBuffer.intensity + BRIGHTNESS_INCREMENT) % BRIGHTNESS_MAX;
#else
FrameBuffer.intensity = 128;
#endif
#if DEBUG_FB_REFRESH
static int timeStartRefresh = micros();
static int timeLastRefresh = 0;
#endif
for (char z = 0; z < MAX_Z; z++) {
// 1. Set up the layer leds to be turned on / off
for (char x = 0; x < MAX_X; x++) {
for (char y = 0; y < MAX_Y; y++) {
if (f->data[x][y][z] > FrameBuffer.intensity) {
digitalWrite(position2pin[x][y], HIGH);
} else {
digitalWrite(position2pin[x][y], LOW);
}
}
}
// 2. Turn the power on on the layer
digitalWrite(layer[z], LOW);
// Let it display
#if BRIGHTNESS_LEVELS
delayMicroseconds(FRAME_PERIOD / (MAX_Z * BRIGHTNESS_LEVELS));
#else
delayMicroseconds(FRAME_PERIOD / MAX_Z);
#endif
// 3. Turn the power off on the layer
digitalWrite(layer[z], HIGH);
}
#if DEBUG_FB_REFRESH
Serial.print("Time Since last refresh: ");
Serial.println((timeStartRefresh - timeLastRefresh), DEC);
timeLastRefresh = micros();
Serial.print("Period Refresh Time: ");
Serial.println((timeLastRefresh - timeStartRefresh), DEC);
#endif
}
void FrameBufferInit(void) {
// Setting rows to ouput
for (char x = 0; x < MAX_X; x++) {
for (char y = 0; y < MAX_Y; y++) {
pinMode(position2pin[x][y], OUTPUT);
digitalWrite(position2pin[x][y], LOW);
}
}
// Setting layers to output
for (char z = 0; z < MAX_Z; z++) {
pinMode(layer[z], OUTPUT);
digitalWrite(layer[z], HIGH);
}
// Initialize FrameBuffers
memset(FrameBufferGetFront(), 0, FRAME_SIZE());
memset(FrameBufferGetBack(), 0, FRAME_SIZE());
#if BRIGHTNESS_LEVELS
MsTimer2::set(FRAME_PERIOD / (1000 * BRIGHTNESS_LEVELS),
FrameBufferRefresh);
#else
MsTimer2::set(FRAME_PERIOD / (1000), FrameBufferRefresh);
#endif
MsTimer2::start();
}

115
FrameBuffer.h Normal file
View File

@@ -0,0 +1,115 @@
#ifndef FRAMEBUFFER_H
#define FRAMEBUFFER_H
/*
* Copyright (c) 2018, Lionel Adrien Sambuc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* Either 1 (Enabled) or 0 (disabled) */
#define DEBUG 0
#if DEBUG
#define DEBUG_FB_REFRESH 1
#endif
/* All the code assumes dimensions are below 127, as signed chars are used to
* store positions and indices. */
#define MAX_X 4
#define MAX_Y 4
#define MAX_Z 4
#define BRIGHTNESS_LEVELS 16
#define BRIGHTNESS_MAX 256
struct Frame {
unsigned char data[MAX_X][MAX_Y][MAX_Z];
};
extern struct FrameBuffer FrameBuffer;
#define FRAME_SIZE() sizeof(struct Frame)
#if BRIGHTNESS_LEVELS
#define BRIGHTNESS_INCREMENT (BRIGHTNESS_MAX / BRIGHTNESS_LEVELS)
#define FRAME_PERIOD (40000 / BRIGHTNESS_LEVELS) /* [us] */
#else
#define FRAME_PERIOD (40000) /* [us] */
#endif
/**
* Switch the back and front buffers.
*
*/
void FrameBufferSwitch(void);
/**
* Returns the current front (visible) frame buffer
*/
Frame *FrameBufferGetFront(void);
/**
* Returns the current back (invisible) frame buffer
*/
Frame *FrameBufferGetBack(void);
/**
* Write the brightness ``val'' to the led at position (x,y,z), in the back
* buffer.
*
* In order to make the value visible, a call to FrameBufferSwitch is needed,
* once the drawing of the frame is complete.
*/
void FrameBufferWrite(char x, char y, char z, unsigned char val);
/**
* Print the string, a letter at a time, showing each for delayPerLetter time,
* with the associated brightness.
*
* This has minimal checks, only lowercase font, space and zero to terminate
* the string.
*/
void FrameBufferWriteStr(char * str, const short delayPerLetter,
const unsigned char brightness);
/**
* Print all symbols available, one after the other.
*/
void printAllSymbols(void);
/**
* Draw the front frame on the ``screen''.
*/
void FrameBufferRefresh(void);
/**
* Initialize the framebuffer, and start the timer to refresh the ``screen''.
*/
void FrameBufferInit(void);
#endif /* FRAMEBUFFER_H */

BIN
LEDCube.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
LEDCubeBottomWired.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

BIN
LEDCubeRessitors.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
LEDCubeWireTooBig.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
LEDCubeWired.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

20
LICENSE
View File

@@ -1,21 +1,19 @@
BSD 3-Clause License Copyright (c) 2018, Lionel Adrien Sambuc
Copyright (c) 2018, Lionel Sambuc
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this 1. Redistributions of source code must retain the above copyright notice,
list of conditions and the following disclaimer. this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, 2. Redistributions in binary form must reproduce the above copyright
this list of conditions and the following disclaimer in the documentation notice, this list of conditions and the following disclaimer in the
and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its 3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from contributors may be used to endorse or promote products derived from
this software without specific prior written permission. this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

268
LedCube.ino Normal file
View File

@@ -0,0 +1,268 @@
/*
* Copyright (c) 2018, Lionel Adrien Sambuc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This program was created from a mix of several sources for the inspiration
* on how to implement the system. I especially followed:
* http://www.instructables.com/id/4x4x4-LED-Cube-Arduino-Uno/ for the
* construction of the hardware.
*
* The main idea is to keep two memory frame (3d) buffer. In order to refresh
* those we use a handler triggered through a timer, set for a period of
* ``FRAME_PERIOD''. Every period the whole cube needs to be redrawn, but as
* we have multiplexing, this means that each layer has only a fourth of the
* frame period to be turned on for the maximum brightness. In order to
* provide multiple brightness levels, a PWM-like signal is manually
* generated, per led, per layer, by turning it on for a percentage of the
* layer time only.
*/
/* Either 1 (Enabled) or 0 (disabled) */
#define DEBUG 0
#if DEBUG
#define DEBUG_SETUP 1
#define DEBUG_LOOP 1
#endif
#include "FrameBuffer.h"
/******************************* ANIMATIONS ********************************/
/* Taken from PWMallPins.pde by Paul Badger, 2007;
* formatted by Seth Wolf, 2015 */
// Preset 256 values of a binary conversions of a sine wave
unsigned char sinewave[] = {
0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,
0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8,
0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5,
0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,
0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc,
0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3,
0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83,
0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51,
0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b,0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,
0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a,
0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08,
0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13,0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23,
0x25,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,0x38,0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c,
0x4f,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,0x67,0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c
};
/**
* Increase by steps the luminosity, then dim by steps the whole cube.
*
* Mainly useful as a test of the led cube.
*/
void levels(void) {
for(int i = 0; i < BRIGHTNESS_MAX; i++) {
memset(FrameBufferGetBack(), i, FRAME_SIZE());
FrameBufferSwitch();
delay(100);
}
for(int i = BRIGHTNESS_MAX; i >= 0; i--) {
memset(FrameBufferGetBack(), i, FRAME_SIZE());
FrameBufferSwitch();
delay(100);
}
}
/**
* Increase by steps the luminosity, then dim by steps the whole cube.
*
* Mainly useful as a test of the led cube.
*/
void testfreq(void) {
memset(FrameBufferGetBack(), 255, FRAME_SIZE());
FrameBufferSwitch();
delay(200);
memset(FrameBufferGetBack(), 1, FRAME_SIZE());
FrameBufferSwitch();
delay(200);
}
/**
* Blinks the whole cube on and off with a period `period`.
*/
void blinkWholeCube(int period /* [ms] */) {
memset(FrameBufferGetBack(), 255, FRAME_SIZE());
FrameBufferSwitch();
delay(period >> 1);
memset(FrameBufferGetBack(), 0, FRAME_SIZE());
FrameBufferSwitch();
delay(period >> 1);
}
/**
* Fade in and out following a sine curve with a period `period`.
*/
void sine(int period /* [ms] */) {
for(short int i = 0; i < BRIGHTNESS_MAX; i++) {
memset(FrameBufferGetBack()->data, sinewave[i], FRAME_SIZE());
FrameBufferSwitch();
delay(period / BRIGHTNESS_MAX);
}
}
/**
* Fade in and out following a sine curve with a period `period`, but only a
* small 2x2x2 cube in the center.
*/
void sine2(int period /* [ms] */) {
for(short int i = 0; i < BRIGHTNESS_MAX; i++) {
memset(FrameBufferGetBack(), 0, FRAME_SIZE());
for (char x = 1; x < 3; x++) {
for (char y = 1; y < 3; y++) {
for (char z = 1; z < 3; z++) {
FrameBufferGetBack()->data[x][y][z] = sinewave[i];
}
}
}
FrameBufferSwitch();
delay(period / BRIGHTNESS_MAX);
}
}
/**
* Fade in and out following a sine curve with a period `period` the entire
* cube, but with the center 2x2x2 cube dephased by 180°.
*/
void sine3(int period /* [ms] */) {
for(int i = 0; i < 256; i++) {
memset(FrameBufferGetBack()->data, 0, FRAME_SIZE());
for (char x = 1; x < 3; x++) {
for (char y = 1; y < 3; y++) {
for (char z = 1; z < 3; z++) {
FrameBufferGetBack()->data[x][y][z] = sinewave[i];
}
}
}
for (char x = 0; x < MAX_X; x++) {
for (char y = 0; y < MAX_Y; y++) {
for (char z = 0; z < MAX_Z; z++) {
if ( ((x == 0) || (x == 3))
||((y == 0) || (y == 3))
||((z == 0) || (z == 3))) {
FrameBufferGetBack()->data[x][y][z] = sinewave[(i+128)%256];
}
}
}
}
FrameBufferSwitch();
delay(period / BRIGHTNESS_MAX);
}
}
/**
* Random rain drpos fall to the bottom of the cube
*/
void randomRain() {
for (char a = MAX_Z; a > 0; a--) {
// animation of 4 steps, requiring computing 4 full frames
for (char x = 0; x < MAX_X; x++) {
for (char y = 0; y < MAX_Y; y++) {
FrameBufferGetBack()->data[x][y][3] = (random(0, 4) == 0) ? 1 : random(0, BRIGHTNESS_MAX);
FrameBufferGetBack()->data[x][y][2] = FrameBufferGetFront()->data[x][y][3];
FrameBufferGetBack()->data[x][y][1] = FrameBufferGetFront()->data[x][y][2];
FrameBufferGetBack()->data[x][y][0] = FrameBufferGetFront()->data[x][y][1];
}
}
FrameBufferSwitch();
delay(500);
}
}
/********************************** BODY ***********************************/
void setup()
{
#if DEBUG_SETUP
static long timeStartSetup = micros();
#endif
// Seeding random for random pattern
randomSeed(analogRead(10));
#if DEBUG
Serial.begin(9600);
Serial.println("\nSetup DONE");
#endif
FrameBufferInit();
#if DEBUG_SETUP
Serial.print("Setup Time: ");
Serial.println((micros() - timeStartSetup), DEC);
#endif
}
void loop() {
static char a = -1;
#if DEBUG_LOOP
static long timeStartLoop = micros();
#endif
a = ((a+1) % 9);
for (int j = 0; j < 10; j++) {
switch(a) {
case 0: sine2(2000); break;
case 1: randomRain(); break;
case 2: sine3(2000); break;
case 3: blinkWholeCube(1000); break;
case 4: sine(2000); break;
case 5: printAllSymbols(); break;
case 6: FrameBufferWriteStr("hello world", 250, 255);
delay(1000);
break;
case 7: testfreq(); break;
case 8: levels(); break;
default: break;
}
}
#if DEBUG_LOOP
Serial.print("Loop Time: ");
Serial.println((micros() - timeStartLoop), DEC);
#endif
}

View File

@@ -1,2 +1,33 @@
# LedCube # LedCube
Arduino Sketch for a LED cubes Arduino Sketch for LED cubes
The following sketch is currently split into a (3D) FrameBuffer implementation and the main "Sketch", which contains a couple of simple animations.
The goal is for the FrameBuffer implementation to grow and allow in the future to support multi-color leds, as well as bigger LED Cubes.
It is implemented in such away to allow for now about 16 levels of brightness
## Hardware
1. Arduino UNO
2. a home-made LED cube :)
To be improved for the next model:
* Use thinner wiring cables, this has unnecessarily complicated the soldering job
* Improve my soldering technic oO
### Led Cube alone.
![Image](LEDCube.jpg)
### Bottom, before wiring.
![Image](LEDCubeRessitors.jpg)
### Bottom after wiring.
![Image](LEDCubeBottomWired.jpg)
### My wiring cables where too big, AWG 18, which is about the same width as the hole pitch of my board.
![Image](LEDCubeWireTooBig.jpg)
### Led Cube wired to the Arduino UNO
![Image](LEDCubeWired.jpg)