X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?p=tinyboard.git;a=blobdiff_plain;f=projects%2Frgb-led-light%2Fmain.c;fp=projects%2Frgb-led-light%2Fmain.c;h=a89481c2a906835409bdf9b687f556d75cc182cc;hp=0000000000000000000000000000000000000000;hb=a1f7cb553db8b485094faafcc431afff2b785736;hpb=85a869857e315a5f4b4b20dee7d44429c1d0cc1c diff --git a/projects/rgb-led-light/main.c b/projects/rgb-led-light/main.c new file mode 100644 index 0000000..a89481c --- /dev/null +++ b/projects/rgb-led-light/main.c @@ -0,0 +1,192 @@ +#include +#include +#include + +#include "rgbstring.h" + +static volatile uint16_t jiffies; + +// #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); + jiffies++; + 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; +} + +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 = 0; + + sei(); + + while (1) { + unsigned char i; + static unsigned char c = 28; + + 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: + if ((jiffies & 0x1ff) == 0) { + c++; + if (c >= 30) + c = 0; + } + + for (i = 0; i < STRIP_SIZE; i++) { + unsigned char x = c; // + i / 2; + if (x >= 30) + x %= 30; + if (x < 10) { + send_rgb(8*(10-x), x, 0); + } else if (x < 20) { + send_rgb(0, 20-x, x-10); + } else { + send_rgb(8*(x-20), 0, 30-x); + } + } + end_frame(); + break; + case 3: + fill_color(32, 4, 8); + break; + case 4: + fill_color(255, 92, 92); + 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; + } + } +} +