I’m working an RGB LED controller, and have the core tech all done and ready to go. There is still work to be done with the laying out of the pcb, but all in good time.
What I don’t have is too many brilliant ideas on HOW the LED controller should behave, specifically, how it should look and respond to buttons being pressed in a way that is pleasing and pretty. So, if anyone has bright ideas on what they would like to see implemented in an LED controller, now is a great time to speak up and show me in code so it could be added. All you need is some imagination and some C skills.
First, an explanation of what you have to work with:
unsigned char button[8];
/* each one is TRUE if the button is pressed, FALSE if not pressed. Button layout is as follows:
0246
1357
If a six button stick, 6 and 7 will always be unpressed. */
unsigned char rgb[8][3]; /* arrive for the rgb data you want displayed. rgb[button][channel] where the button number
is the same as the layout above, and the channels are 0=Red, 1=Green, 2=Blue. If you want button 5 (Roundhouse)
to be brightest yellow: rgb[5][0]=0xFF;rgb[5][1]=0xFF;rgb[5][2]=0;
Remains untouched from previous display; use clearRGBdata() to clear to all zeros before working if you dont
want to deal with data from previous frame */
unsigned char scratch[100]; /*playground. Can be used for anything you want, and will remain unchanged between
frames. Will be cleared to all 0's when display mode is changed via the menu, or on power up. If you need more
but you really shouldn't */
unsigned char primarycolor[3]; /* the user can use the menu to specify two colors of their choosing as their favorites,
so routines can use these if they dont need full pallettes to deal with. primarycolor[0] is red, [1] is green, [2] is
blue. */
unsigned char secondarycolor[3]; /* 2nd favorite color */
unsigned char isSixButton; /*will be true if a six button stick, false if 8 button stick*/
And functions to play with.
void hsvtorgb(unsigned int h, unsigned char s, unsigned char v, unsigned char *r, unsigned char *g, unsigned char *b);
/* Takes HSV data and saves the equivalent RGB data where told.
'h' is the hue, a number from 0-360. 360=0=Red, 60=Yellow, 120=Green, 180=Cyan, 240=Blue, 300=Magenta
If number is >360, will be modulo'd down to 0-360.
's' is Saturation (insert Wesker joke). 0=white, 255=full color.
'v' is 'value'. 0==black, 255=full color.
r, g, and b are where the values should go. Example to set Strong (button 2) to brightest Magenta:
hsvtorgb(300, 0xFF, 0xFF, &rgb[2][0], &rgb[2][1], &rgb[2][2]);
void clearRGBdata(void); /* sets rgb[][] to all 0's. just a simple for loop */
Code should check whatever it needs to check, modify the rgb array as needed for that frame, and then exit. No waiting, no muss, no fuss. Local variables are perfectly welcome, but keep in mind they will likely be clobbered by the time the next frame rolls around, so save anything you want to save in the ‘scratch’ array so it’ll be there next frame. Don’t be afraid to go nuts though; each LED can be different colors, in a full 24 bit colorspace. There is plenty of processing time available, so math extensive formula are just fine. There is not an excess of memory though; try to avoid lengthy tables of data. Code will be executed every frame, at a very reliable 75Hz. Just to give an idea, my reading show less than 10% overhead by the interrupt routines, so you have well over 12ms of processing time available per frame at 8Mhz. Roughly 96,000 instructions. That’s a bunch.
Examples:
Pretty rainbow screensaver type from the youtube vid from last week. Button pressed have no affect in this mode.
void rainbow(void)
{
unsigned int hue;
//our current color is saved in scratch. No need to check if its all zeros (initial condition), since we can safely start
//with color 0.
hue = (scratch[0]*(unsigned int)0x100)+scratch[1];
//and loop back when we exceed 360.
if(hue>359) {hue=0;scratch[0]=0;scratch[1]=0;}
scratch[1]++;
if(scratch[1]==0)scratch[0]++;
hue++;
if(isSixButton)
{ //6 buttons, so each color is 60 degrees from the previous
hsvtorgb(hue, 0xFF, 0xFF, &rgb[0][0], &rgb[0][1], &rgb[0][2]);
hsvtorgb(hue+60, 0xFF, 0xFF, &rgb[1][0], &rgb[1][1], &rgb[1][2]);
hsvtorgb(hue+120, 0xFF, 0xFF, &rgb[2][0], &rgb[2][1], &rgb[2][2]);
hsvtorgb(hue+180, 0xFF, 0xFF, &rgb[3][0], &rgb[3][1], &rgb[3][2]);
hsvtorgb(hue+240, 0xFF, 0xFF, &rgb[4][0], &rgb[4][1], &rgb[4][2]);
hsvtorgb(hue+300, 0xFF, 0xFF, &rgb[5][0], &rgb[5][1], &rgb[5][2]);
}
else
{ //8 buttons, so each color is 45 degrees from the previous
hsvtorgb(hue, 0xFF, 0xFF, &rgb[0][0], &rgb[0][1], &rgb[0][2]);
hsvtorgb(hue+45, 0xFF, 0xFF, &rgb[1][0], &rgb[1][1], &rgb[1][2]);
hsvtorgb(hue+90, 0xFF, 0xFF, &rgb[2][0], &rgb[2][1], &rgb[2][2]);
hsvtorgb(hue+135, 0xFF, 0xFF, &rgb[3][0], &rgb[3][1], &rgb[3][2]);
hsvtorgb(hue+180, 0xFF, 0xFF, &rgb[4][0], &rgb[4][1], &rgb[4][2]);
hsvtorgb(hue+225, 0xFF, 0xFF, &rgb[5][0], &rgb[5][1], &rgb[5][2]);
hsvtorgb(hue+270, 0xFF, 0xFF, &rgb[6][0], &rgb[6][1], &rgb[6][2]);
hsvtorgb(hue+315, 0xFF, 0xFF, &rgb[7][0], &rgb[7][1], &rgb[7][2]);
}
}
/* Each time its run (each frame), the hue goes up slightly, shifting button[0] from red to orange to yellow slowly and smoothly.
Each of the other buttons move the same way, but from different starting points in the color wheel. When button[0] is red, button[4] will be blue tinted.*/
//Pressed button starts red, and shifts while held. if released, goes dark immediately.
//When repressed, continues from where it left off.
//an initialized scratch is fine since 0 is valid data. All rgb[] are written, so no need to clearRGBdata.
void color_cycle_when_held(void)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(button*)
{
hsvtorgb((scratch**2), 0xFF, 0xFF, &rgb*[0], &rgb*[1], &rgb*[2]);
scratch*++; if(scratch*>179)scratch*=0;
}
else
{
rgb*[0]=rgb*[1]=rgb*[2]=0;
}
}
}
So, what would YOU like for an RGB controller to do?