/* 2008 - robert:aT:spitzenpfeil_d*t:org --- V4 */ #define __spi_clock 13 // SCK - hardware SPI #define __spi_latch 10 #define __spi_data 11 // MOSI - hardware SPI #define __spi_data_in 12 // MISO - hardware SPI (unused) #define __display_enable 9 #define __button 7 #define __led 4 #define __rows 8 #define __max_row __rows-1 #define __leds_per_row 8 #define __max_led __leds_per_row-1 #define __brightness_levels 28 // 0...15 above 32 is bad for ISR #define __max_brightness __brightness_levels-1 #define __fade_delay 4 #define __TIMER1_MAX 0xFFFF // 16 bit CTR #define __TIMER1_CNT 0x0130 // 32 levels --> 0x0130; 38 --> 0x0157 (flicker) #include #include byte brightness_red[__leds_per_row][__rows]; byte brightness_green[__leds_per_row][__rows]; byte brightness_blue[__leds_per_row][__rows]; ISR(TIMER1_OVF_vect) { TCNT1 = __TIMER1_MAX - __TIMER1_CNT; byte cycle; digitalWrite(__display_enable,LOW); // enable display inside ISR for(cycle = 0; cycle < __max_brightness; cycle++) { byte led; byte row = B00000000; // row: current source. on when (1) byte red; // current sinker when on (0) byte green; // current sinker when on (0) byte blue; // current sinker when on (0) for(row = 0; row <= __max_row; row++) { red = B11111111; // off green = B11111111; // off blue = B11111111; // off for(led = 0; led <= __max_led; led++) { if(cycle < brightness_red[row][led]) { red &= ~(1< __max_row) || (led > __max_led) ) { return; } brightness_red[row][led] = red; } void set_led_green(byte row, byte led, byte green) { if( (row > __max_row) || (led > __max_led) ) { return; } brightness_green[row][led] = green; } void set_led_blue(byte row, byte led, byte blue) { if( (row > __max_row) || (led > __max_led) ) { return; } brightness_blue[row][led] = blue; } void set_led_rgb(byte row, byte led, byte red, byte green, byte blue) { set_led_red(row,led,red); set_led_green(row,led,green); set_led_blue(row,led,blue); } void set_row_rgb(byte row, byte red, byte green, byte blue) { byte ctr1; for(ctr1 = 0; ctr1 <= __max_led; ctr1++) { set_led_rgb(row,ctr1,red,green,blue); } } void set_column_rgb(byte column, byte red, byte green, byte blue) { byte ctr1; for(ctr1 = 0; ctr1 <= __max_row; ctr1++) { set_led_rgb(ctr1,column,red,green,blue); } } void set_tbar_rgb(byte toprow, byte red, byte green, byte blue) { byte ctr1; set_matrix_rgb(0,0,0); for(ctr1 = 0; ctr1 <= toprow; ctr1++) { set_row_rgb(ctr1,red,green,blue); } } void set_matrix_rgb(byte red, byte green, byte blue) { byte ctr1; byte ctr2; for(ctr2 = 0; ctr2 <= __max_row; ctr2++) { for(ctr1 = 0; ctr1 <= __max_led; ctr1++) { set_led_rgb(ctr2,ctr1,red,green,blue); } } } void set_hue_bar(byte topled, byte column, byte bottomhue, byte tophue) { byte ctr1; float delta = (float)((tophue-bottomhue))/7.0; /* HSV: 0..360, here mapped to 0..255 --> 1.41 */ set_column_rgb(column,0,0,0); for(ctr1 = 0; ctr1 <= topled; ctr1++) { set_led_hue(ctr1,column,(delta*float(ctr1)+(float)(bottomhue))*1.41); } } void set_led_hue(byte row, byte led, int hue) { // see wikipeda: HSV float S=100.0,V=100.0,s=S/100.0,v=V/100.0,h_i,f,p,q,t,R,G,B; hue = hue%360; h_i = hue/60; f = (float)(hue)/60.0 - h_i; p = v*(1-s); q = v*(1-s*f); t = v*(1-s*(1-f)); if ( h_i == 0 ) { R = v; G = t; B = p; } else if ( h_i == 1 ) { R = q; G = v; B = p; } else if ( h_i == 2 ) { R = p; G = v; B = t; } else if ( h_i == 3 ) { R = p; G = q; B = v; } else if ( h_i == 4 ) { R = t; G = p; B = v; } else { R = v; G = p; B = q; } set_led_rgb(row,led,byte(R*(float)(__max_brightness)),byte(G*(float)(__max_brightness)),byte(B*(float)(__max_brightness))); } void setup_hardware_spi(void) { byte clr; // spi prescaler: // SPI2X SPR1 SPR0 // 0 0 0 fosc/4 // 0 0 1 fosc/16 // 0 1 0 fosc/64 // 0 1 1 fosc/128 // 1 0 0 fosc/2 // 1 0 1 fosc/8 // 1 1 0 fosc/32 // 1 1 1 fosc/64 SPCR |= ( (1<