rgb-led-string: Christmas tree mod after real-world testing
[tinyboard.git] / projects / step-up / pattern.c
1 #include <avr/io.h>
2 #include <stdlib.h> // for NULL
3
4 #include "lights.h"
5
6 #define N_LEDS 2
7 static unsigned char bits_left[N_LEDS];
8 static unsigned char *pattern_data[N_LEDS];
9 static unsigned char current_bit[N_LEDS];
10
11 static unsigned char off_pattern[] = {
12         0b00000000,
13 };
14
15 void led_set_pattern(unsigned char led, unsigned char bits_len,
16         unsigned char bits_start,
17         unsigned char *data)
18 {
19         if (!bits_len) {
20                 led_set_pattern(led, 8, 0, off_pattern);
21         } else {
22                 bits_left[led] = bits_len-1;
23                 current_bit[led] = bits_start;
24                 pattern_data[led] = data;
25         }
26 }
27
28 void led_set_number_pattern(unsigned char led, unsigned char num,
29         unsigned char inv)
30 {
31         static unsigned char pattern_num[] = {
32                 0b00100000, /*  10 */
33                 0b10000010, /* 8,9 */
34                 0b00001000, /*   7 */
35                 0b00100000, /*   6 */
36                 0b10000010, /* 4,5 */
37                 0b00001000, /*   3 */
38                 0b00100000, /*   2 */
39                 0b10000000, /*   1 */
40                 0b00000000,
41         };
42
43         static unsigned char pattern_invnum[] = {
44                 0b11011111, /*  10 */
45                 0b01111101, /* 8,9 */
46                 0b11110111, /*   7 */
47                 0b11011111, /*   6 */
48                 0b01111101, /* 4,5 */
49                 0b11110111, /*   3 */
50                 0b11011111, /*   2 */
51                 0b01111111, /*   1 */
52                 0b11111111,
53         };
54
55         unsigned char bits_len, bits_remaining;
56
57         if (num > 10)
58                 num = 10;
59
60         bits_len = 6*num + 12;
61         bits_remaining = 9*8 - bits_len;
62         log_byte(0x88);
63         log_byte(bits_len);
64         log_byte(bits_remaining & 7);
65         log_byte(bits_remaining >> 3);
66         log_flush();
67         led_set_pattern(led, bits_len, bits_remaining & 7,
68                 inv ? pattern_invnum + (bits_remaining >> 3)
69                     : pattern_num    + (bits_remaining >> 3));
70 }
71
72 static void inline pattern_select(unsigned char n)
73 {
74         switch(n) {
75         case 0: pwmled_pattern_select(n);
76                 break;
77         case 1: status_led_pattern_select(n);
78                 break;
79         }
80 }
81
82 static void inline led_set_mode(unsigned char n, unsigned char mode)
83 {
84         switch (n) {
85         case 0: pwmled_on_off(mode); break;
86         case 1: status_led_on_off(mode); log_byte(mode); log_flush(); break;
87         }
88 }
89
90 void patterns_next_tick()
91 {
92         unsigned char i;
93
94         for (i = 0; i < N_LEDS; i++) {
95                 if (!bits_left[i]) {
96                         pattern_select(i);
97                 } else {
98                         bits_left[i]--;
99                         current_bit[i]++;
100                         if (current_bit[i] >= 8) {
101                                 current_bit[i] = 0;
102                                 pattern_data[i]++;
103                         }
104                 }
105
106                 led_set_mode(i, *(pattern_data[i]) & (1 << (7 - current_bit[i]))
107                         ? 1 : 0);
108         }
109 }
110
111 void init_pattern()
112 {
113         unsigned char i;
114
115         for (i = 0; i < N_LEDS; i++)
116                 led_set_pattern(i, 0, 0, NULL);
117 }
118
119 void pattern_reload()
120 {
121         unsigned char i;
122
123         for (i = 0; i < N_LEDS; i++)
124                 bits_left[i] = 0;
125
126         patterns_next_tick();
127 }
128