]> www.fi.muni.cz Git - tinyboard.git/blobdiff - projects/rgb-led-light/main.c
New project: RGB LED lights
[tinyboard.git] / projects / rgb-led-light / main.c
diff --git a/projects/rgb-led-light/main.c b/projects/rgb-led-light/main.c
new file mode 100644 (file)
index 0000000..a89481c
--- /dev/null
@@ -0,0 +1,192 @@
+#include <avr/io.h>
+#include <util/delay.h>
+#include <avr/interrupt.h>
+
+#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;
+               }
+       }
+}
+