]> www.fi.muni.cz Git - tinyboard.git/blobdiff - projects/step-up/pattern.c
Experimental step-up driver for chain of 5630 LEDs.
[tinyboard.git] / projects / step-up / pattern.c
index 3336b5812b485da884bc9c52c4b9ce0cf054b810..44c6d1a4a58106163a5f039f8a833c96a9560886 100644 (file)
 #include "lights.h"
 
 #define N_LEDS 2
-static unsigned char led_counters[N_LEDS];
-static pattern_t *led_patterns[N_LEDS];
-
-static pattern_t pattern_num[] = {
-       { 0, 0x5 },
-       { 1, 0x1 }, /* 10 */
-       { 0, 0x5 },
-       { 1, 0x1 }, /*  9 */
-       { 0, 0x5 },
-       { 1, 0x1 }, /*  8 */
-       { 0, 0x5 },
-       { 1, 0x1 }, /*  7 */
-       { 0, 0x5 },
-       { 1, 0x1 }, /*  6 */
-       { 0, 0x5 },
-       { 1, 0x1 }, /*  5 */
-       { 0, 0x5 },
-       { 1, 0x1 }, /*  4 */
-       { 0, 0x5 },
-       { 1, 0x1 }, /*  3 */
-       { 0, 0x5 },
-       { 1, 0x1 }, /*  2 */
-       { 0, 0x5 },
-       { 1, 0x1 }, /*  1 */
-       { 0, 0xF },
-       PATTERN_END
-};
-
-static pattern_t pattern_invnum[] = {
-       { 1, 0x5 },
-       { 0, 0x1 }, /* 10 */
-       { 1, 0x5 },
-       { 0, 0x1 }, /*  9 */
-       { 1, 0x5 },
-       { 0, 0x1 }, /*  8 */
-       { 1, 0x5 },
-       { 0, 0x1 }, /*  7 */
-       { 1, 0x5 },
-       { 0, 0x1 }, /*  6 */
-       { 1, 0x5 },
-       { 0, 0x1 }, /*  5 */
-       { 1, 0x5 },
-       { 0, 0x1 }, /*  4 */
-       { 1, 0x5 },
-       { 0, 0x1 }, /*  3 */
-       { 1, 0x5 },
-       { 0, 0x1 }, /*  2 */
-       { 1, 0x5 },
-       { 0, 0x1 }, /*  1 */
-       { 1, 0xF },
-       PATTERN_END
-};
+static unsigned char bits_left[N_LEDS];
+static unsigned char *pattern_data[N_LEDS];
+static unsigned char current_bit[N_LEDS];
 
-pattern_t off_pattern[] = {
-       { 0, 0x1 },
-       PATTERN_END
+static unsigned char off_pattern[] = {
+       0b00000000,
 };
 
-pattern_t on1_pattern[] = {
-       { 1, 1 },
-       { 0, 2 },
-       { 1, 1 },
-       { 0, 8 },
-       { 1, 1 },
-       { 0, 8 },
-       PATTERN_END
-};
-
-static void led_set_mode(unsigned char n, unsigned char mode)
+void led_set_pattern(unsigned char led, unsigned char bits_len,
+       unsigned char bits_start,
+       unsigned char *data)
 {
-       switch (n) {
-       case 0: pwmled_on_off(mode); break;
-       case 1: status_led_on_off(mode); break;
+       if (!bits_len) {
+               led_set_pattern(led, 8, 0, off_pattern);
+       } else {
+               bits_left[led] = bits_len-1;
+               current_bit[led] = bits_start;
+               pattern_data[led] = data;
        }
 }
 
-void led_set_pattern(unsigned char n, pattern_t *pattern)
+void led_set_number_pattern(unsigned char led, unsigned char num,
+       unsigned char inv)
 {
-       if (!pattern)
-               pattern = off_pattern;
-
-       led_patterns[n] = pattern;
+       static unsigned char pattern_num[] = {
+               0b00100000, /*  10 */
+               0b10000010, /* 8,9 */
+               0b00001000, /*   7 */
+               0b00100000, /*   6 */
+               0b10000010, /* 4,5 */
+               0b00001000, /*   3 */
+               0b00100000, /*   2 */
+               0b10000000, /*   1 */
+               0b00000000,
+       };
+
+       static unsigned char pattern_invnum[] = {
+               0b11011111, /*  10 */
+               0b01111101, /* 8,9 */
+               0b11110111, /*   7 */
+               0b11011111, /*   6 */
+               0b01111101, /* 4,5 */
+               0b11110111, /*   3 */
+               0b11011111, /*   2 */
+               0b01111111, /*   1 */
+               0b11111111,
+       };
+
+       unsigned char bits_len, bits_remaining;
+
+       if (num > 10)
+               num = 10;
 
-       led_counters[n] = pattern->duration;
-       led_set_mode(n, pattern->mode);
+       bits_len = 6*num + 12;
+       bits_remaining = 9*8 - bits_len;
+       log_byte(0x88);
+       log_byte(bits_len);
+       log_byte(bits_remaining & 7);
+       log_byte(bits_remaining >> 3);
+       log_flush();
+       led_set_pattern(led, bits_len, bits_remaining & 7,
+               inv ? pattern_invnum + (bits_remaining >> 3)
+                   : pattern_num    + (bits_remaining >> 3));
 }
 
-void init_pattern()
+static void inline pattern_select(unsigned char n)
 {
-       unsigned char i;
-
-       for (i = 0; i < N_LEDS; i++)
-               led_set_pattern(i, NULL);
+       switch(n) {
+       case 0: pwmled_pattern_select(n);
+               break;
+       case 1: status_led_pattern_select(n);
+               break;
+       }
 }
 
-pattern_t *number_pattern(unsigned char num, unsigned char inv)
+static void inline led_set_mode(unsigned char n, unsigned char mode)
 {
-       if (num >= 10)
-               num = 10;
-
-       if (inv) {
-               return pattern_invnum
-                       + sizeof(pattern_invnum)/sizeof(pattern_t)
-                       - 2 - 2*num;
-       } else {
-               return pattern_num
-                       + sizeof(pattern_num)/sizeof(pattern_t)
-                       - 2 - 2*num;
+       switch (n) {
+       case 0: pwmled_on_off(mode); break;
+       case 1: status_led_on_off(mode); log_byte(mode); log_flush(); break;
        }
 }
 
-static pattern_t *pattern_select(unsigned char n)
+void patterns_next_tick()
 {
-       switch(n) {
-       case 0: return pwmled_pattern_select();
-       case 1: return status_led_pattern_select();
-       default: return NULL;
+       unsigned char i;
+
+       for (i = 0; i < N_LEDS; i++) {
+               if (!bits_left[i]) {
+                       pattern_select(i);
+               } else {
+                       bits_left[i]--;
+                       current_bit[i]++;
+                       if (current_bit[i] >= 8) {
+                               current_bit[i] = 0;
+                               pattern_data[i]++;
+                       }
+               }
+
+               led_set_mode(i, *(pattern_data[i]) & (1 << (7 - current_bit[i]))
+                       ? 1 : 0);
        }
 }
 
-void pattern_reload()
+void init_pattern()
 {
        unsigned char i;
 
        for (i = 0; i < N_LEDS; i++)
-               led_set_pattern(i, pattern_select(i));
+               led_set_pattern(i, 0, 0, NULL);
 }
 
-static void inline pattern_finished(unsigned char n)
-{
-       led_patterns[n] = NULL;
-       led_set_pattern(n, pattern_select(n));
-}
-
-void patterns_next_tick()
+void pattern_reload()
 {
        unsigned char i;
 
-       for (i = 0; i < N_LEDS; i++) {
-               if (!led_patterns[i]) {
-                       pattern_finished(i);
-                       continue;
-               }
-
-               if (--led_counters[i] == 0) {
-                       pattern_t *p = led_patterns[i];
-                       p++;
-                       if (p->duration == 0) { // END
-                               /* Keep the last state, wait for others */
-                               pattern_finished(i);
-                               continue;
-                       }
-                       led_set_pattern(i, p);
-               }
+       for (i = 0; i < N_LEDS; i++)
+               bits_left[i] = 0;
 
-       }
+       patterns_next_tick();
 }