]> www.fi.muni.cz Git - tinyboard.git/blobdiff - projects/led-blinker/main.c
Three-channel LED blinker
[tinyboard.git] / projects / led-blinker / main.c
diff --git a/projects/led-blinker/main.c b/projects/led-blinker/main.c
new file mode 100644 (file)
index 0000000..70491ed
--- /dev/null
@@ -0,0 +1,134 @@
+#include <avr/io.h>
+#include <util/delay.h>
+#include <avr/sleep.h>
+#include <avr/power.h>
+
+/*
+ * Overview:
+ * three LEDs:
+ * PB1/OC1A     yellow
+ * PB2          yellow
+ * PB4/OC1B     red
+ */
+
+static void init()
+{
+       DDRB |= _BV(PB1) | _BV(PB2) | _BV(PB4);
+
+       // PWM setup, use T/C 1
+       TCCR1 = _BV(CS10)       // clock at CLK/1
+               | _BV(PWM1A)    // OCR1A in PWM mode
+               | _BV(COM1A1);  // clear on compare match
+       GTCCR = _BV(PWM1B)      // OCR1B in PWM mode
+               | _BV(COM1B1); // clear on compare match)
+
+       OCR1C = 255;
+       OCR1A = 0;
+       OCR1B = 0;
+}
+
+
+static unsigned char levels[] = {
+       0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 255
+};
+#define N_LEVELS (sizeof(levels)/sizeof(levels[0]))
+
+static void led_set(unsigned char led, unsigned char val)
+{
+       switch (led) {
+       case 0:
+               OCR1A = val < N_LEVELS ? levels[val] : levels[N_LEVELS-1];
+               break;
+       case 1:
+               if (val) {
+                       PORTB |= _BV(PB2);
+               } else {
+                       PORTB &= ~_BV(PB2);
+               }
+               break;
+       case 2:
+               OCR1B = val < N_LEVELS ? levels[val] : levels[N_LEVELS-1];
+               break;
+       }
+}
+
+static unsigned char rand[] = {
+193, 33, 133, 97, 139, 225, 40, 105, 110, 238, 57, 250, 26, 221, 166, 247, 138, 23, 107, 122, 154, 33, 201, 66, 154, 78, 137, 198, 86, 232, 38, 182, 16, 198, 73, 231, 58, 114, 58, 105,
+};
+#define N_RAND (sizeof(rand)/sizeof(rand[0]))
+
+static void led0()
+{
+       static unsigned char r, l, exp;
+
+again:
+       if (l == exp) {
+               r++;
+               if (r > N_RAND-7)
+                       r = 0;
+               exp = rand[r] >> 4;
+               if (exp >= N_LEVELS-4)
+                       goto again;
+       }
+
+       if (l < exp) {
+               l++;
+       } else if (l > exp) {
+               l--;
+       }
+
+       led_set(0, l);
+}
+
+static void led1()
+{
+       static unsigned char r;
+       unsigned char exp;
+
+       led_set(1, 1);
+#if 0
+again:
+       r++;
+       if (r > N_RAND)
+               r = 0;
+       exp = rand[r];
+
+       led_set(1, ((exp >> 3) & 1) ^ ((exp >> 5) & 1));
+#endif
+}
+
+static void led2()
+{
+       static unsigned char r, l, exp;
+
+again:
+       if (l == exp) {
+               r++;
+               if (r > N_RAND)
+                       r = 0;
+               exp = rand[r] & 0xF;
+               if (exp >= N_LEVELS)
+                       goto again;
+       }
+
+       if (l < exp) {
+               l++;
+       } else if (l > exp) {
+               l--;
+       }
+
+       led_set(2, l);
+}
+
+int main(void)
+{
+       init();
+
+       while (1) {
+               led0();
+               led1();
+               led2();
+               _delay_ms(40);
+       }
+
+}