/* Name: main.c * Author: Toshi Nagata * Copyright: 2011 (c) Toshi Nagata * License: Modified BSD License * * ATtiny2313V * PB7, PB4, PB1: Blue with 100 ohm * PB6, PB3, PB0: Green with 100 ohm * PB5, PB2, (PD6): Red with 220 ohm * Cathode -> GND */ #include #include #include #include #define PMAX 2048 // Color change // Walk on the surface {x=1,y>=0,z>=0}, {x>=0,y=1,z>=0}, {x>=0,y>=0,z=1} unsigned char colors[9] = {255, 255, 0, 0, 0, 255, 255, 0, 0}; signed char dcol[9] = {0, 1, 3, 1, 3, 0, 2, 5, 0}; volatile unsigned char pwm[9] = {255, 255, 0, 0, 0, 255, 255, 0, 0}; // Brightness change // Linear back-and-forth move between -PMAX to PMAX*2, and // limit the qunatity within [0, PMAX] short pulser[3] = {-PMAX, -PMAX, -PMAX}; signed char dpulser[3] = {13, 11, 5}; // Timer for PWM output // Output i is 0 when timer >= pwm[i], 1 otherwise volatile unsigned char timer = 0; // Scaler for color change unsigned char scaler = 0; // Table for converting amplitude to PWM strength // (to make brightness change smoother) PROGMEM prog_uchar table[256] = { 0,1,1,2,2,3,4,4,5,5,6,7,7,8,8,9, 10,10,11,12,12,13,13,14,15,15,16,17,17,18,19,19, 20,21,21,22,23,23,24,25,25,26,27,27,28,29,29,30, 31,32,32,33,34,34,35,36,37,37,38,39,39,40,41,42, 42,43,44,45,45,46,47,48,48,49,50,51,52,52,53,54, 55,56,56,57,58,59,60,60,61,62,63,64,65,65,66,67, 68,69,70,70,71,72,73,74,75,76,77,77,78,79,80,81, 82,83,84,85,85,86,87,88,89,90,91,92,93,94,95,96, 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112, 113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128, 129,131,132,133,134,135,136,137,138,139,141,142,143,144,145,146, 147,149,150,151,152,153,154,156,157,158,159,160,162,163,164,165, 166,168,169,170,171,173,174,175,177,178,179,180,182,183,184,186, 187,188,189,191,192,193,195,196,197,199,200,202,203,204,206,207, 208,210,211,213,214,216,217,218,220,221,223,224,226,227,229,230, 232,233,235,236,238,239,241,242,244,245,247,248,250,251,253,255, }; void setup() { cli(); // Disable interrupt DDRB = 0b11111111; // PB0-PB4 for output DDRD = 0b01111000; // PD3-PD6 for output // Set up Timer // Disable all timer interrupts TIMSK = 0b00000000; // WGM0/1/2 = 0 ... normal timer mode (not CTC, not PWM) // Clock source = IO clock, no prescale TCCR0A = 0b00000000; TCCR0B = 0b00000001; // Reset and start timer interrupt for timer 0 overflow TCNT0 = 0; TIMSK = (1< timer) m1 |= 128; if (pwm[1] > timer) m1 |= 64; if (pwm[2] > timer) m1 |= 32; if (pwm[3] > timer) m1 |= 16; if (pwm[4] > timer) m1 |= 8; if (pwm[5] > timer) m1 |= 4; if (pwm[6] > timer) m1 |= 2; if (pwm[7] > timer) m1 |= 1; PORTB = m1; m1 = 0; if (pwm[8] > timer) m1 = 64; PORTD = m1; } void loop() { int c; unsigned char i, j = 0; scaler++; if (scaler == 17) { scaler = 0; for (i = 0; i < 9; i++) { c = (int)colors[i] + (int)dcol[i]; if (c < 0) { c = -c; dcol[i] = -dcol[i]; } else if (c > 255) { signed char dc; c = 255; dc = -dcol[i]; i -= j; if (dcol[i] == 0) { dcol[i] = dc; } else if (dcol[i + 1] == 0) { dcol[i + 1] = dc; } else { dcol[i + 2] = dc; } i += j; dcol[i] = 0; } colors[i] = c; j++; if (j == 3) j = 0; } } for (i = 0; i < 3; i++) { c = pulser[i] + dpulser[i]; if (c > PMAX * 2 || c < -PMAX) { dpulser[i] = -dpulser[i]; } pulser[i] = c; if (c < 0) c = 0; else if (c > PMAX) c = PMAX; c /= (PMAX / 128); for (j = 0; j < 3; j++) { pwm[i * 3 + j] = pgm_read_byte(table + ((int)colors[i * 3 + j] * c) / 128); } } _delay_ms(6); } int main() { setup(); while (1) { loop(); } return 0; /* Not reached */ }