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
Loading
Loading
Loading
Loading
+75 −37
Original line number Diff line number Diff line
@@ -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
+6 −10
Original line number Diff line number Diff line
@@ -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);
+88 −124
Original line number Diff line number Diff line
@@ -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;
	static unsigned char pattern_num[] = {
		0b00100000, /*  10 */
		0b10000010, /* 8,9 */
		0b00001000, /*   7 */
		0b00100000, /*   6 */
		0b10000010, /* 4,5 */
		0b00001000, /*   3 */
		0b00100000, /*   2 */
		0b10000000, /*   1 */
		0b00000000,
	};

	led_patterns[n] = pattern;
	static unsigned char pattern_invnum[] = {
		0b11011111, /*  10 */
		0b01111101, /* 8,9 */
		0b11110111, /*   7 */
		0b11011111, /*   6 */
		0b01111101, /* 4,5 */
		0b11110111, /*   3 */
		0b11011111, /*   2 */
		0b01111111, /*   1 */
		0b11111111,
	};

	led_counters[n] = pattern->duration;
	led_set_mode(n, pattern->mode);
}
	unsigned char bits_len, bits_remaining;

void init_pattern()
{
	unsigned char i;
	if (num > 10)
		num = 10;

	for (i = 0; i < N_LEDS; i++)
		led_set_pattern(i, NULL);
	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));
}

pattern_t *number_pattern(unsigned char num, unsigned char inv)
static void inline pattern_select(unsigned char n)
{
	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_pattern_select(n);
		break;
	case 1: status_led_pattern_select(n);
		break;
	}
}

static pattern_t *pattern_select(unsigned char n)
static void inline led_set_mode(unsigned char n, unsigned char mode)
{
	switch (n) {
	case 0: return pwmled_pattern_select();
	case 1: return status_led_pattern_select();
	default: return NULL;
	case 0: pwmled_on_off(mode); break;
	case 1: status_led_on_off(mode); log_byte(mode); log_flush(); break;
	}
}

void pattern_reload()
void patterns_next_tick()
{
	unsigned char i;

	for (i = 0; i < N_LEDS; i++)
		led_set_pattern(i, pattern_select(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]++;
			}
		}

static void inline pattern_finished(unsigned char n)
{
	led_patterns[n] = NULL;
	led_set_pattern(n, pattern_select(n));
		led_set_mode(i, *(pattern_data[i]) & (1 << (7 - current_bit[i]))
			? 1 : 0);
	}
}

void patterns_next_tick()
void init_pattern()
{
	unsigned char i;

	for (i = 0; i < N_LEDS; i++) {
		if (!led_patterns[i]) {
			pattern_finished(i);
			continue;
	for (i = 0; i < N_LEDS; i++)
		led_set_pattern(i, 0, 0, NULL);
}

		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);
		}
void pattern_reload()
{
	unsigned char i;

	}
	for (i = 0; i < N_LEDS; i++)
		bits_left[i] = 0;

	patterns_next_tick();
}