Commit d09c1dcb authored by Jan Kasprzak's avatar Jan Kasprzak
Browse files

binary patterns

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.
parent 8c9c1717
......@@ -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
......
......@@ -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);
......
......@@ -4,161 +4,125 @@
#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();
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment