Oh, whatever, I will post it here.
What I do is: I have 127 RGB LEDs connected via driver chips to the core. The communication is via IIC. Also, for each LED, there is a button. The LEDs can be set to a color, but they can also go into BLINK modus. In BLINK modus, they fade between two colors in 32 steps in a regular interval. Additionally, when the corresponding button is pressed, the LED FLASHES up in a third color, which is then faded into the normal color in a second or so. Blinking and Flashing can occur at the same time, without disturbing the blinking frequency or phase.
These are the variables I am using. Lots of unsigned char arrays, but no problems with variable memory so far.
/////////////////////////////////////////////////////////////////////////////
// Global variables
/////////////////////////////////////////////////////////////////////////////
//status register for all leds
knoepfli_led_status_t knoepfli_led_status[KNOEPFLI_LED_NUMBER];
//timer counter through all leds
unsigned char knoepfli_led_counter;
//color state arrays for all LEDs. Three separate arrays for the colors because of array size limitations on the pic
/////////////////////////////////////////////////////////////////////////////
//this array contains the current color of the LEDs, without the flash effect but with blinking
unsigned char knoepfli_led_color_now_red[KNOEPFLI_LED_NUMBER];
unsigned char knoepfli_led_color_now_green[KNOEPFLI_LED_NUMBER];
unsigned char knoepfli_led_color_now_blue[KNOEPFLI_LED_NUMBER];
//blink stuff
/////////////////////////////////////////////////////////////////////////////
//these arrays contain one of the two blinking colors for all LEDs
unsigned char knoepfli_led_color_from_red[KNOEPFLI_LED_NUMBER];
unsigned char knoepfli_led_color_from_green[KNOEPFLI_LED_NUMBER];
unsigned char knoepfli_led_color_from_blue[KNOEPFLI_LED_NUMBER];
//these arrays contain the second color for the blinking
unsigned char knoepfli_led_color_to_red[KNOEPFLI_LED_NUMBER];
unsigned char knoepfli_led_color_to_green[KNOEPFLI_LED_NUMBER];
unsigned char knoepfli_led_color_to_blue[KNOEPFLI_LED_NUMBER];
//this array contains the step counter for the blinking
unsigned char knoepfli_led_blink_counter[KNOEPFLI_LED_NUMBER];
//this array contains the direction of the step counter
//only one bit per LED is needed, but bitfields with a size of 128 do not seem to work
unsigned char knoepfli_led_blink_direction[KNOEPFLI_LED_NUMBER];
//flash stuff
/////////////////////////////////////////////////////////////////////////////
//these arrays contain the flash color of all LEDs
unsigned char knoepfli_led_color_flash_red[KNOEPFLI_LED_NUMBER];
unsigned char knoepfli_led_color_flash_green[KNOEPFLI_LED_NUMBER];
unsigned char knoepfli_led_color_flash_blue[KNOEPFLI_LED_NUMBER];
//this array contains the step counter for all LEDs for the flash
unsigned char knoepfli_led_flash_counter[KNOEPFLI_LED_NUMBER];
The next function is called periodically by Tick in the main loop. This could be improved by setting a flag in Timer and checking the flag in Tick to get regular intervals
/////////////////////////////////////////////////////////////////////////////
// Blink and Flash Handler
// Treats only one LED per call
// First determines the current color of the LED, if it is blinking
// Then additionally applies the flash color fade, if the LED is flashing
/////////////////////////////////////////////////////////////////////////////
void KNOEPFLI_Blink_and_Flash_Handler()
{
unsigned char red,green,blue,change;
// //avoid the compiler warnings about non-defined variables
// red = 0;
// green = 0;
// blue = 0;
//set change flag to false
change = 0;
if( knoepfli_led_status[knoepfli_led_counter].BLINK == 1 ) {
//the color has to be changed, set the flag
change = 1;
red = KNOEPFLI_Interpolate32( knoepfli_led_blink_counter[knoepfli_led_counter], knoepfli_led_color_from_red[knoepfli_led_counter], knoepfli_led_color_to_red[knoepfli_led_counter]);
green = KNOEPFLI_Interpolate32( knoepfli_led_blink_counter[knoepfli_led_counter], knoepfli_led_color_from_green[knoepfli_led_counter], knoepfli_led_color_to_green[knoepfli_led_counter]);
blue = KNOEPFLI_Interpolate32( knoepfli_led_blink_counter[knoepfli_led_counter], knoepfli_led_color_from_blue[knoepfli_led_counter], knoepfli_led_color_to_blue[knoepfli_led_counter]);
knoepfli_led_color_now_red[knoepfli_led_counter] = red;
knoepfli_led_color_now_green[knoepfli_led_counter] = green;
knoepfli_led_color_now_blue[knoepfli_led_counter] = blue;
if( knoepfli_led_blink_direction[knoepfli_led_counter] == 0 ) {
if( knoepfli_led_blink_counter[knoepfli_led_counter] == 32) {
knoepfli_led_blink_direction[knoepfli_led_counter] = 1;
--knoepfli_led_blink_counter[knoepfli_led_counter];
} else {
++knoepfli_led_blink_counter[knoepfli_led_counter];
};
} else {
if( knoepfli_led_blink_counter[knoepfli_led_counter] == 0) {
knoepfli_led_blink_direction[knoepfli_led_counter] = 0;
++knoepfli_led_blink_counter[knoepfli_led_counter];
} else {
--knoepfli_led_blink_counter[knoepfli_led_counter];
};
};
};
if( knoepfli_led_status[knoepfli_led_counter].FLASH == 1 ) {
//the color has to be changed, set the flag
change = 1;
red = KNOEPFLI_Interpolate32( knoepfli_led_flash_counter[knoepfli_led_counter], knoepfli_led_color_now_red[knoepfli_led_counter], knoepfli_led_color_flash_red[knoepfli_led_counter]);
green = KNOEPFLI_Interpolate32( knoepfli_led_flash_counter[knoepfli_led_counter], knoepfli_led_color_now_green[knoepfli_led_counter], knoepfli_led_color_flash_green[knoepfli_led_counter]);
blue = KNOEPFLI_Interpolate32( knoepfli_led_flash_counter[knoepfli_led_counter], knoepfli_led_color_now_blue[knoepfli_led_counter], knoepfli_led_color_flash_blue[knoepfli_led_counter]);
if( knoepfli_led_flash_counter[knoepfli_led_counter] == 0 ) {
knoepfli_led_status[knoepfli_led_counter].FLASH = 0;
} else {
--knoepfli_led_flash_counter[knoepfli_led_counter];
};
};
if( change == 1) {
//Send Brightness red
MIOS_IIC_Start(); // start IIC
MIOS_IIC_ByteSend( knoepfli_led_address_red[knoepfli_led_counter].DRIVER ); // send device address, bit #0 cleared to notify a write!!!
MIOS_IIC_ByteSend( 0x02 + knoepfli_led_address_red[knoepfli_led_counter].LED ); // select brightness register of the corresponding led, the first one is 0xa2, no autoincrement
MIOS_IIC_ByteSend( red ); // send brightness
MIOS_IIC_Stop();
//Send Brightness green
MIOS_IIC_Start(); // start IIC
MIOS_IIC_ByteSend( knoepfli_led_address_green[knoepfli_led_counter].DRIVER ); // send device address, bit #0 cleared to notify a write!!!
MIOS_IIC_ByteSend( 0x02 + knoepfli_led_address_green[knoepfli_led_counter].LED ); // select brightness register of the corresponding led, the first one is 0xa2, no autoincrement
MIOS_IIC_ByteSend( green ); // send brightness
MIOS_IIC_Stop();
//Send Brightness blue
MIOS_IIC_Start(); // start IIC
MIOS_IIC_ByteSend( knoepfli_led_address_blue[knoepfli_led_counter].DRIVER ); // send device address, bit #0 cleared to notify a write!!!
MIOS_IIC_ByteSend( 0x02 + knoepfli_led_address_blue[knoepfli_led_counter].LED ); // select brightness register of the corresponding led, the first one is 0xa2, no autoincrement
MIOS_IIC_ByteSend( blue ); // send brightness
MIOS_IIC_Stop();
};
//increase the counter for the next run of the routine
++knoepfli_led_counter;
if( knoepfli_led_counter == KNOEPFLI_LED_NUMBER ) {
knoepfli_led_counter = 0;
};
}
And this is the interpolation function, now coded in C. Assembler did not work properly, and I decided to try it in C. Maybe this leaves some room for improvement.
/////////////////////////////////////////////////////////////////////////////
// Interpolate32
// Gives back an interpolated value between value1 and value2
// The total number of steps is 33, from 0 to 32
/////////////////////////////////////////////////////////////////////////////
unsigned char KNOEPFLI_Interpolate32(unsigned char step, unsigned char value1, unsigned char value2)
{
unsigned char swap, diff;
//send out value2 if step is the max value
if( step == 32 ) {
return value2;
};
//send out value1 if step i 0
if( step == 0 ) {
return value1;
};
//invert the interpolation if value1 > value2
if( value1 > value2 ) {
//swap the values
swap = value2;
value2 = value1;
value1 = swap;
//--step because we are counting from 0 to 32, not to 31
--step;
//invert the step counter
step = ~step;
//clear the upper three bits
step &= 0x1f;
};
//get the difference
diff = value2 - value1;
//divide it through the total number of steps (>>5) and multiply it with step (gives an integer) then get the high byte,
//shift the step counter three to the left to make it 8bit, store it in PRODL
PRODL = step << 3;
//store diff in PRODH
PRODH = diff;
//do the multiplication in assembler
__asm
movf _PRODL, W
mulwf _PRODH, 0
__endasm;
//add the lower value
return value1 + PRODH;
}
Well, what do you think? Any questions will of course be answered most gladly 
ALEXander.