binary patterns
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Sat, 11 May 2013 22:56:05 +0000 (00:56 +0200)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Sat, 11 May 2013 22:56:05 +0000 (00:56 +0200)
We use on/off for patterns, so I have rewritten the pattern handling,
removing the pattern_t type altogether, and changed it to use
binary strings of data instead. This uses less RAM for pattern definitions.

I have also changed blink_pattern to include morse code text
(generated by morse.pl), with kids' names.

projects/step-up/control.c
projects/step-up/lights.h
projects/step-up/pattern.c

index bdfe53d..4ffb71c 100644 (file)
@@ -3,25 +3,62 @@
 
 #include "lights.h"
 
-static pattern_t on_pattern [] = {
-       { 1, 0x10 },
-       PATTERN_END
+static unsigned char on_pattern[] = {
+       /* 8 bits */
+       0b11111111,
 };
 
-static pattern_t blink_pattern[] = {
-       { 1, 0x1 },
-       { 0, 0x2 },
-       { 1, 0x1 },
-       { 0, 0x8 },
-       { 1, 0x1 },
-       { 0, 0x8 },
-       PATTERN_END
+#define IVA
+
+static unsigned char blink_pattern[] = {
+#ifdef IVA
+       /* ../...-/..-/.../-.-/.-// */
+       /* 137 bits, 19.7% on */
+       0b10000100,
+       0b00000000,
+       0b10000100,
+       0b00100001,
+       0b11000000,
+       0b00001000,
+       0b01000011,
+       0b10000000,
+       0b00010000,
+       0b10000100,
+       0b00000000,
+       0b11100001,
+       0b00001110,
+       0b00000000,
+       0b01000011,
+       0b10000000,
+       0b00000000,
+       0b00000000,
+#else /* FILIP */
+       /* ..-./../.-../../.--.// */
+       /* 124 bits, 19.4% on */
+       0b10000100,
+       0b00111000,
+       0b01000000,
+       0b00001000,
+       0b01000000,
+       0b00001000,
+       0b01110000,
+       0b10000100,
+       0b00000000,
+       0b10000100,
+       0b00000000,
+       0b10000111,
+       0b00001110,
+       0b00010000,
+       0b00000000,
+       0b00000000,
+#endif
 };
 
-static pattern_t slow_pattern[] = {
-       { 1, 0x1 },
-       { 0, 0x18 },
-       PATTERN_END
+static unsigned char slow_pattern[] = {
+       /* 24 bits */
+       0b00010000,
+       0b00000000,
+       0b00000000,
 };
 
 static unsigned char light_mode;
@@ -80,35 +117,36 @@ void long_press()
        power_down();
 }
 
-pattern_t *pwmled_pattern_select()
+void pwmled_pattern_select(unsigned char led)
 {
-       if (e.shutdown_in_progress)
-               return NULL;
-
-       if (e.battery_low)
-               return slow_pattern;
-
-       if (light_mode == 0) {
-               return slow_pattern;
+       if (e.shutdown_in_progress) {
+               led_set_pattern(led, 0, 0, NULL);
+       } else if (e.battery_low) {
+               led_set_pattern(led, 24, 0, slow_pattern);
+       } else if (light_mode == 0) {
+               led_set_pattern(led, 24, 0, slow_pattern);
        } else if (light_mode < N_PWMLED_MODES) {
-               return blink_pattern;
+#ifdef IVA
+               led_set_pattern(led, 137, 0, blink_pattern);
+#else /* FILIP */
+               led_set_pattern(led, 124, 0, blink_pattern);
+#endif
        } else {
-               return on_pattern;
+               led_set_pattern(led, 8, 0, on_pattern);
        }
 }
 
-pattern_t *status_led_pattern_select()
+void status_led_pattern_select(unsigned char led)
 {
-       if (e.shutdown_in_progress)
-               return on_pattern;
-
-       if (e.pwmled_error)
-               return number_pattern(3, 1);
-
-       if (e.battery_low)
-               return number_pattern(1, 1);
-
-       return number_pattern(battery_gauge(), 0);
+       if (e.shutdown_in_progress) {
+               led_set_pattern(led, 8, 0, on_pattern);
+       } else if (e.pwmled_error) {
+               led_set_number_pattern(led, 1, 1);
+       } else if (e.battery_low) {
+               led_set_number_pattern(led, 1, 1);
+       } else {
+               led_set_number_pattern(led, battery_gauge(), 0);
+       }
 }
 
 #if 0
index c4f5666..e3bd6e3 100644 (file)
@@ -42,16 +42,12 @@ void pwmled_set_target(unsigned char mode);
 void pwmled_on_off(unsigned char on);
 
 /* pattern.c */
-typedef struct {
-       unsigned char mode: 3;
-       unsigned char duration: 5;
-} pattern_t;
-
-#define PATTERN_END { 0, 0 }
 void init_pattern();
 void patterns_next_tick();
-void led_set_pattern(unsigned char led, pattern_t *pattern);
-pattern_t *number_pattern(unsigned char num, unsigned char inv);
+void led_set_pattern(unsigned char led, unsigned char bits_len,
+       unsigned char bits_start, unsigned char *data);
+void led_set_number_pattern(unsigned char led,
+       unsigned char num, unsigned char inv);
 void pattern_reload();
 
 /* buttons.c */
@@ -73,8 +69,8 @@ void long_press();
 void short_press();
 void brake_on();
 void brake_off();
-pattern_t *pwmled_pattern_select();
-pattern_t *status_led_pattern_select();
+void pwmled_pattern_select(unsigned char led);
+void status_led_pattern_select(unsigned char led);
 #define ERR_BATTERY 1
 #define ERR_PWMLED  2
 void set_error(unsigned char err);
index 3336b58..44c6d1a 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();
 }