Hello everybody,
just registered in this forum.
I'm working on a new (and I hope better) firmware for Rainbowduino.
My goal is to have a fully functional communication protocol to handle the led as an 8x8 display.
I want also to include the support for multiple Rainbow.
I'm not sure (lack of knoledge in Arduino) if multiple Rainbow can communicate each other via I2C, while the same channel is used by Arduino to send the graphic commands to the Rainbow chain.
Here follows the code I've written during the last weekend.
It's far away to be complete. All the I2C communication part is absolutely missing.
Some code, especially the low-level control and the timer functions are derived from the actual firmware.
I'm considering the idea of rewriting (again) everything object oriented.
I've a wierd bug and I don't understand where is the problem. Unfortunately, without a debugger is very hard to find.
The bug is documented in the code.
Basically, I have to call a function (clearBuffer) during setup() to have everything working. And I really don't understand why. If you notice the compiled code size, with and without the function mentioned it varies. Why? I've no idea.
Thanks in avance for every help and collaboration.
Rainbowduino_Firmware_3_0b.pde (part I)
#include "Rainbow.h"
#include <Wire.h>
#include <avr/pgmspace.h>
extern unsigned char dots_color[8][3][8][4]; // define Two Buffs (one for Display ,the other for receive data)
extern unsigned char GammaTab[4][16]; // define the Gamma value for correct the different LED matrix
extern unsigned char ASCII_Char[62][8];
unsigned char line, level;
unsigned char g8Flag1;
byte dispGamma;
byte bufFront, bufBack, bufCurr;
unsigned char RainbowCMD[5]={0,0,0,0,0};
byte State=0;
void setup() {
_init_gfx();
_init(); // Initialize Ports, Timer and Interrupts
clearBuffer(BLACK); // <<**THE BUG** WHY? Why if I comment this line the code size reduces and nothing works?
}
void loop() {
// Display char 'A' on black
clearBuffer(0x0, 0x0, 0x0);
printChar(0, 0, 0x0, 0x8, 0xf, 'A');
swapBuffers();
/* FULL TESTING OF FUNCTIONS - UNCOMMENT TO EXECUTE
// Scroll char 'P' from left to right
int i;
for(i=-8; i<8; i++) {
clearBuffer(BLACK);
printChar(i, 0, 0x0, 0x0, 0xf, 'P');
swapBuffers();
delay(100);
}
// Plot dot-by-dot char D on yellow, then scrolls it away
clearBuffer(0x7, 0x9, 0x0);
setPixel(1,1, 0, 0, 0xf);
setPixel(2,1, 0, 0, 0xf);
setPixel(3,1, 0, 0, 0xf);
setPixel(4,2, 0, 0, 0xf);
setPixel(4,3, 0, 0, 0xf);
setPixel(4,4, 0, 0, 0xf);
setPixel(4,5, 0, 0, 0xf);
setPixel(3,6, 0, 0, 0xf);
setPixel(2,6, 0, 0, 0xf);
setPixel(1,6, 0, 0, 0xf);
setPixel(1,5, 0, 0, 0xf);
setPixel(1,4, 0, 0, 0xf);
setPixel(1,3, 0, 0, 0xf);
setPixel(1,2, 0, 0, 0xf);
for (i=0; i<10; i++) {
swapBuffers();
clearBuffer(0x7, 0x9, 0x0);
copyFrontBuffer(-1, -1);
delay(150);
}
// Cycle all the Aux buffer showing the predefined content
for(i=0; i<6; i++) {
showAuxBuffer(i);
delay(200);
}
swapBuffers();
// Cycle all the chars of predefined font
for(i='0';i<'9';i++) {
clearBuffer(0x0, 0x0, 0x0);
printChar(0, 0, 0x1, 0x4, 0xf, i);
swapBuffers();
delay(100);
}
for(i='A';i<'Z';i++) {
clearBuffer(0x0, 0x0, 0x0);
printChar(0, 0, 0x1, 0x4, 0xf, i);
swapBuffers();
delay(100);
}
for(i='a';i<'z';i++) {
clearBuffer(0x0, 0x0, 0x0);
printChar(0, 0, 0x1, 0x4, 0xf, i);
swapBuffers();
delay(100);
}
UNCOMMENT TO DO FULL TESTING */
}
/*----------------------------------------------------------------------------*/
/* DRAWING FUNCTIONS */
/*----------------------------------------------------------------------------*/
void _init_gfx() { // Init the graphic side
dispGamma = 1;
bufFront=0;
bufBack=1;
bufCurr=0;
}
void setGamma(byte g) { // Change the gamma array
if ( g < MAX_GAMMA_SETS ) {
dispGamma = g;
}
}
void setPixel(byte x, byte y, byte r, byte g, byte b) {
if ( (x>=0 && x<8) && (y>=0 && y<8) ) {
byte mask = 0xF0;
if ( !(x % 2) ) { // If x is unpair, shift four bit left color components
r = (r << 4);
g = (g << 4);
b = (b << 4);
mask = 0x0F;
}
x /= 2;
replace_dot(bufBack, x, y, bufBack, x, y, r, g, b, mask);
}
}
void printChar(int x, int y, byte r, byte g, byte b, unsigned char ASCII) { // Print a char using array ASCII_Char as font source
unsigned char idx;
byte bitmask;
int row, col;
int l;
if((ASCII > 64) && (ASCII < 91)) idx=ASCII-55; // Convert from ASCII to index of character's array
else if((ASCII > 96) && (ASCII < 123)) idx=ASCII-61;
else if((ASCII >= '0') && (ASCII <= '9')) idx=ASCII-48;
l = 0;
for (row=(7+y); row>=y; row--) {
if ( row < 8 && row >= 0 ) { // Check if row is within visible area
bitmask = pgm_read_byte(&(ASCII_Char[idx][l])); // Extract the bitmask for each line of the character
if ( x > 0 ) bitmask = (bitmask << x); // Shift the bitmask according to x-offset
else bitmask = (bitmask >> -x);
for (col=0; col<4; col++) {
if ( bitmask & B00000001 ) { // Check the first bit of the bitmask
replace_dot(bufBack, col, row, bufBack, col, row, (r << 4), (g << 4), (b << 4), 0x0F);
}
if ( bitmask & B00000010 ) { // Check the second bit of the bitmask
replace_dot(bufBack, col, row, bufBack, col, row, r, g, b, 0xF0);
}
bitmask = (bitmask >> 2); // Shift the bitmask two bits left
}
}
l++;
}
}
/* BUFFERS HANDLING */
void swapBuffers() { // Swap Front with Back buffer
bufFront = !bufFront;
bufBack = !bufBack;
while(bufCurr != bufFront) { // Wait for display to change.
delayMicroseconds(10);
}
}
void showAuxBuffer(byte n) { // Show an Auxiliary buffer
if (n < MAX_AUX_BUFFERS) {
bufFront = n+2;
while(bufCurr != bufFront) { // Wait for display to change.
delayMicroseconds(10);
}
}
}
void storeToAuxBuffer(byte n, byte buf) { // Store the Front (visible) buffer to Aux Buffer #
byte x, y;
if (n < MAX_AUX_BUFFERS) {
n+=2;
for (y=0; y<8; y++) {
for (x=0; x<4; x++) {
dots_color[n][R][y][x]=dots_color[buf][R][y][x];
dots_color[n][G][y][x]=dots_color[buf][G][y][x];
dots_color[n][B][y][x]=dots_color[buf][B][y][x];
}
}
}
}
void getFromAuxBuffer(byte n) { // Retrieve Aux Buffer # to Back (not visibile) buffer;
byte x, y;
if (n < MAX_AUX_BUFFERS) {
n+=2;
for (y=0; y<8; y++) {
for (x=0; x<4; x++) {
dots_color[bufBack][R][y][x]=dots_color[n][R][y][x];
dots_color[bufBack][G][y][x]=dots_color[n][G][y][x];
dots_color[bufBack][B][y][x]=dots_color[n][B][y][x];
}
}
}
}
void clearBuffer(byte r, byte g, byte b) { // Clear the Back buffer and fill with selected color
byte x, y;
r = r | (r << 4);
g = g | (g << 4);
b = b | (b << 4);
for (y=0; y<8; y++) {
for (x=0; x<4; x++) {
dots_color[bufBack][G][y][x]=g;
dots_color[bufBack][R][y][x]=r;
dots_color[bufBack][B][y][x]=b;
}
}
}
void copyFrontBuffer(int x, int y) { // Copy the Front buffer to the Back one, offsetting it by x and y
int row, col;
int offy, offx;
byte t0, t1, t2;
for (row=0; row<8; row++) {
offy = row-y;
if ( offy>=0 && offy<8 ) {
for (col=0; col<4; col++) {
offx = col+(x/2);
if ( offx>=0 && offx<4 ) {
if ( !(x%2) ) {
dots_color[bufBack][R][row][col]=dots_color[bufFront][R][offy][offx];
dots_color[bufBack][G][row][col]=dots_color[bufFront][G][offy][offx];
dots_color[bufBack][B][row][col]=dots_color[bufFront][B][offy][offx];
} else {
t0 = dots_color[bufFront][R][offy][offx];
t1 = dots_color[bufFront][G][offy][offx];
t2 = dots_color[bufFront][B][offy][offx];
if ( x >= 0 ) {
replace_dot(bufBack, col, row, bufBack, col, row, (t0 >> 4), (t1 >> 4), (t2 >> 4), 0xF0);
offx = col+1; // I reuse offx variable to avoid initializing a new one. This affect only the 3 lines below.
if ( offx < 4)
replace_dot(bufBack, offx, row, bufBack, offx, row, (t0 << 4), (t1 << 4), (t2 << 4), 0x0F);
} else {
replace_dot(bufBack, col, row, bufBack, col, row, (t0 << 4), (t1 << 4), (t2 << 4), 0x0F);
offx = col-1; // I reuse offx variable to avoid initializing a new one. This affect only the 3 lines below.
if ( offx >= 0)
replace_dot(bufBack, offx, row, bufBack, offx, row, (t0 >> 4), (t1 >> 4), (t2 >> 4), 0xF0);
}
}
}
}
}
}
}
void replace_dot(byte fromBuf, int fromX, int fromY, byte toBuf, int toX, int toY, byte vR, byte vG, byte vB, byte mask) {
// Replace a single dot ( 4 byte ) in toBuf buffer with the value from fromBuf buffer
dots_color[toBuf][0][toY][toX]=(vG | (dots_color[fromBuf][0][fromY][fromX] & mask));
dots_color[toBuf][1][toY][toX]=(vR | (dots_color[fromBuf][1][fromY][fromX] & mask));
dots_color[toBuf][2][toY][toX]=(vB | (dots_color[fromBuf][2][fromY][fromX] & mask));
}
cont...