#include #include #include #include "rgbstring.h" // #define CHRISTMAS_TREE 1 #define rgb_return(r, g, b) do { send_rgb((r), (g), (b)); return 1; } while(0) #define VERT_SIZE 47 /* RNG from ADC noise */ static unsigned char rand_pool[8], rand_pool_off, prev_bit, rand_pool_out; static void init_rng() { ADCSRA |= _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1); // enable, clk/64 ADMUX = _BV(REFS1) | _BV(MUX0) | _BV(MUX3); // 1.1V, PB5:PB5, gain 20 DIDR0 = _BV(ADC0D); ADCSRA |= _BV(ADIE) | _BV(ADSC); rand_pool_off = 0; prev_bit = 0; } static unsigned char rand() { unsigned char rv = 0; rv = rand_pool[rand_pool_out]; rand_pool_out++; if (rand_pool_out >= sizeof(rand_pool)) rand_pool_out = 0; return rv; } ISR(ADC_vect) { ADCSRA |= _BV(ADSC); if ((rand_pool_off & 1) == 0) { // first bit of the pair prev_bit = ADCW & 1; rand_pool_off++; } else { unsigned char bit = ADCW & 1; if (bit == prev_bit) { // whitening fail: try again rand_pool_off--; return; } if (bit) { rand_pool[rand_pool_off >> 4] ^= 1 << ((rand_pool_off >> 1) & 7); } rand_pool_off++; if (rand_pool_off >= 16*sizeof(rand_pool)) rand_pool_off = 0; } } static unsigned int slow_dim[] = { 255, 27, 7, 2, }; static void fill_color(unsigned char r, unsigned char g, unsigned char b) { unsigned char i; for (i = 0; i < STRIP_SIZE; i++) send_rgb(r, g, b); end_frame(); } unsigned int state; static void do_buttons() { static uint8_t prev_buttons = _BV(PB0) | _BV(PB3) | _BV(PB4); static uint16_t prev_len = 0; uint8_t buttons = PINB & (_BV(PB0) | _BV(PB3) | _BV(PB4)); if (prev_buttons == buttons) { prev_len++; return; } // was change if (prev_len < 3 || (buttons != (_BV(PB0) | _BV(PB3) | _BV(PB4)))) { prev_buttons = buttons; prev_len = 0; return; } if ((prev_buttons & _BV(PB0)) == 0) { if (state) state--; } else if ((prev_buttons & _BV(PB3)) == 0) { if (state < 5) state++; } else if ((prev_buttons & _BV(PB4)) == 0) { state = 1; } prev_buttons = buttons; prev_len = 0; } #define LED_MAX (2*STRIP_SIZE/5) #define N_COLORS 8 #define R_BIAS(x) ((x) << 3) #define G_BIAS(x) ((x) >> 1) #define B_BIAS(x) ((x) << 1) static void do_hue() { static unsigned char color, led_off; static uint16_t jiffies; unsigned char i, c0, l0; if ((jiffies++ & 0x03f) == 0) { if (++led_off >= LED_MAX) { led_off = 0; color++; if (color >= 3*N_COLORS) color = 0; } } l0 = led_off; c0 = color; for (i = 0; i < STRIP_SIZE; i++) { if (c0 < N_COLORS) { send_rgb(R_BIAS(N_COLORS-c0), G_BIAS(c0), 0); } else if (c0 < 2*N_COLORS) { send_rgb(0, G_BIAS(2*N_COLORS-c0), B_BIAS(c0-N_COLORS)); } else { send_rgb(R_BIAS(c0-2*N_COLORS), 0, B_BIAS(3*N_COLORS-c0)); } if (++l0 >= LED_MAX) { l0 = 0; c0++; if (c0 >= 3*N_COLORS) c0 = 0; } } end_frame(); } int main(void) { init_log(); init_rng(); init_serial(); _delay_ms(3000/8); // wait for a bit and then increase the CPU clock CLKPR = _BV(CLKPCE); CLKPR = 0; PORTB |= _BV(PB0) | _BV(PB3) | _BV(PB4); // pull-ups for buttons state = 2; sei(); while (1) { unsigned char i; do_buttons(); switch (state) { case 0: zero_frame(); break; case 1: i = 0; while (i < STRIP_SIZE) { send_rgb(4, 0, 0); send_rgb(4, 1, 0); send_rgb(0, 2, 0); send_rgb(0, 1, 1); send_rgb(0, 0, 2); send_rgb(4, 0, 2); i += 6; } end_frame(); break; case 2: do_hue(); break; case 3: fill_color(16, 4, 8); break; case 4: fill_color(96, 64, 64); break; case 5: fill_color(255, 255, 255); break; default: { unsigned char light; light = slow_dim[sizeof(slow_dim)/sizeof(slow_dim[0]) - state]; fill_color(4*light, light, 2*light); } break; } } }