PROGRAM=lights
SRC=main.c logging.c adc.c pwm.c tmr.c pwmled.c gpio.c ambient.c pattern.c \
- buttons.c battery.c
+ buttons.c battery.c control.c
OBJ=$(SRC:.c=.o)
log_byte(ambient_zone);
log_word(ambient_val);
log_flush();
+
+ pattern_reload();
}
void ambient_adc(uint16_t adcval)
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
+#include <stdlib.h> // for NULL
#include "lights.h"
led_set_pattern(n + N_PWMLEDS, pattern);
}
-pattern_t *status_pattern_select(unsigned char n)
+unsigned char buttons_setup_in_progress()
{
- if (user_params_state) // Setup in progress
- return number_pattern(n == 0
- ? user_params_state
- : 1 + user_params[user_params_state-1]
- );
- else if (!(prev_pin & _BV(PA3)) || !(prev_pin & _BV(PA4)))
- // at least one button is pressed
- return off_pattern;
- // otherwise, an ordinary state
- if (n == 0) {
- // error led
- return number_pattern(1 + ambient_zone);
- } else {
- return jiffies > 500 ? number_pattern(2) : zero_pattern; // for now
- }
+ if (user_params_state // setup in progress ...
+ // or at least one button is pressed:
+ || !(prev_pin & _BV(PA3))
+ || !(prev_pin & _BV(PA4)))
+ return 1;
+ return 0;
}
-static void toggle_bright_mode()
+pattern_t *buttons_setup_status0_pattern_select()
{
- // TODO
+ if (user_params_state) // Setup in progress
+ return number_pattern(user_params_state, 1);
+ else
+ return NULL;
}
-static void set_panic_mode()
+pattern_t *buttons_setup_status1_pattern_select()
{
- // TODO
+ if (user_params_state) // Setup in progress
+ return number_pattern(
+ 1 + user_params[user_params_state-1],
+ 1
+ );
+ else
+ return NULL;
}
unsigned char get_user_param(unsigned char param)
if (user_params_state == 0) {
if (button == 0)
- toggle_bright_mode();
+ toggle_dim_mode();
else
set_panic_mode();
return;
}
// FIXME: notify somebody about user_params change?
- set_status_led(1, status_pattern_select(1));
+ set_status_led(1, buttons_setup_status1_pattern_select());
user_params_starttime = jiffies;
}
if (user_params_state > MAX_USER_PARAMS)
user_params_state = 1;
- set_status_led(0, status_pattern_select(0));
- set_status_led(1, status_pattern_select(1));
+ set_status_led(0, buttons_setup_status0_pattern_select());
+ set_status_led(1, buttons_setup_status1_pattern_select());
user_params_starttime = jiffies;
}
// BEWARE: pins are at _zero_ when pressed!
if (!cur && prev) { // --- just pressed ---
button_start[button] = jiffies;
- set_status_led(button, off_pattern);
+ set_status_led(button, NULL);
} else if (!cur && !prev) { // --- is still pressed ---
uint16_t duration = jiffies - button_start[button];
if (duration > 80) {
- set_status_led(button, on_pattern);
+ set_status_led(button, on1_pattern);
// acknowledge long press
}
} else if (cur && !prev) { // --- just released ---
if (duration > 6 && duration < 30) {
short_press(button);
} else if (duration > 80) {
- set_status_led(button, off_pattern);
+ set_status_led(button, NULL);
long_press(button);
}
// ignore other button-press durations
if (user_params_state && jiffies - user_params_starttime > 1000) {
user_params_state = 0;
- set_status_led(0, status_pattern_select(0));
- set_status_led(1, status_pattern_select(1));
+ set_status_led(0, buttons_setup_status0_pattern_select());
+ set_status_led(1, buttons_setup_status1_pattern_select());
}
}
--- /dev/null
+#include <inttypes.h>
+#include <stdlib.h> // for NULL
+
+#include "lights.h"
+
+static pattern_t panic_pattern[] = {
+ { 3, 1 }, // FIXME: will be 4, but let's be safe while testing
+ { 0, 1 },
+ { 3, 1 },
+ { 0, 1 },
+ { 3, 1 },
+ { 0, 1 },
+ { 3, 1 },
+ { 0, 1 },
+ { 3, 1 },
+ { 0, 1 },
+ { 3, 1 },
+ { 0, 1 },
+ { 3, 1 },
+ { 0, 1 },
+ { 3, 1 },
+ { 0, 1 },
+ { 3, 1 },
+ { 0, 1 },
+ { 3, 1 },
+ { 0, 1 },
+ { 3, 1 },
+ { 0, 1 },
+ PATTERN_END
+};
+
+pattern_t on1_pattern [] = {
+ { 1, PATTERN_FOREVER }
+};
+
+static pattern_t on2_pattern [] = {
+ { 2, PATTERN_FOREVER }
+};
+
+static pattern_t on3_pattern [] = {
+ { 3, PATTERN_FOREVER }
+};
+
+static pattern_t normal2_pattern[] = {
+ { 2, 0x1 },
+ { 0, 0x1 },
+ { 2, 0x1 },
+ { 0, 0x8 },
+ { 1, 0x1 },
+ { 0, 0x1 },
+ { 1, 0x1 },
+ { 0, 0x8 },
+ PATTERN_END
+};
+
+static pattern_t normal3_pattern[] = {
+ { 2, 0x1 },
+ { 0, 0x1 },
+ { 2, 0x1 },
+ { 0, 0x8 },
+ { 1, 0x1 },
+ { 0, 0x1 },
+ { 1, 0x1 },
+ { 0, 0x8 },
+ PATTERN_END
+};
+
+static pattern_t normal4_pattern[] = {
+ { 2, 0x1 },
+ { 0, 0x1 },
+ { 2, 0x1 },
+ { 0, 0x8 },
+ { 1, 0x1 },
+ { 0, 0x1 },
+ { 1, 0x1 },
+ { 0, 0x8 },
+ PATTERN_END
+};
+
+static pattern_t slow1_pattern[] = {
+ { 1, 0x01 },
+ { 0, 0x10 },
+ PATTERN_END
+};
+
+static pattern_t slow2_pattern[] = {
+ { 2, 0x01 },
+ { 0, 0x10 },
+ PATTERN_END
+};
+
+static pattern_t slow3_pattern[] = {
+ { 3, 0x01 },
+ { 0, 0x10 },
+ PATTERN_END
+};
+
+static unsigned char dim_mode, towbar_mode;
+
+void init_control()
+{
+ dim_mode = 0;
+ towbar_mode = 0;
+}
+
+void toggle_dim_mode()
+{
+ dim_mode = !dim_mode;
+ pattern_reload();
+}
+
+void set_panic_mode()
+{
+ if (!dim_mode)
+ led_set_pattern(0, panic_pattern);
+
+ led_set_pattern(1, panic_pattern);
+ led_set_pattern(2, panic_pattern);
+ led_set_pattern(4, panic_pattern);
+}
+
+pattern_t *pwmled0_pattern_select()
+{
+ // TODO: battery critical
+
+ if (towbar_mode)
+ return NULL;
+
+ switch (ambient_zone) {
+ case 0: return dim_mode ? NULL : on1_pattern;
+ case 1: return dim_mode ? NULL : slow2_pattern;
+ case 2: return dim_mode ? slow3_pattern : slow2_pattern;
+ case 3:
+ default: return dim_mode ? slow3_pattern : normal4_pattern;
+ }
+}
+
+pattern_t *pwmled1_pattern_select()
+{
+ // TODO: battery critical
+
+ if (towbar_mode) {
+ switch (ambient_zone) {
+ case 0:
+ case 1:
+ return dim_mode ? on2_pattern : on1_pattern;
+ case 2: return dim_mode ? NULL : on2_pattern;
+ case 3:
+ default: return dim_mode ? NULL : on3_pattern;
+ }
+ } else {
+ switch (ambient_zone) {
+ case 0: return dim_mode ? slow1_pattern : normal2_pattern;
+ case 1: return dim_mode ? slow2_pattern : normal3_pattern;
+ case 2: return dim_mode ? NULL : normal4_pattern;
+ case 3:
+ default: return NULL;
+ }
+ }
+}
+
+pattern_t *pwmled2_pattern_select()
+{
+ // TODO: battery critical
+
+ switch (ambient_zone) {
+ case 0: return dim_mode ? on2_pattern : on3_pattern;
+ case 1: return dim_mode ? slow1_pattern : normal2_pattern;
+ case 2:
+ case 3:
+ default:
+ return dim_mode ? slow2_pattern : normal3_pattern;
+ }
+}
+
+pattern_t *status_led_pattern_select()
+{
+ if (buttons_setup_in_progress())
+ return buttons_setup_status0_pattern_select();
+
+ // FIXME: do something sane
+ return number_pattern(1 + ambient_zone, 1);
+}
+
+pattern_t *illumination_led_pattern_select()
+{
+ // todo: battery critical
+
+ switch (ambient_zone) {
+ case 0: return dim_mode
+ ? number_pattern(1, 1)
+ : on1_pattern;
+ case 1: return dim_mode
+ ? number_pattern(2, 1)
+ : number_pattern(3, 1);
+ case 2: return dim_mode
+ ? number_pattern(3, 0)
+ : number_pattern(4, 0);
+ case 3:
+ default: return dim_mode
+ ? number_pattern(5, 0)
+ : number_pattern(6, 0);
+ }
+}
+
#define PATTERN_FOREVER 0x1F
#define PATTERN_END { 0, 0 }
-extern pattern_t off_pattern[];
-extern pattern_t zero_pattern[];
-extern pattern_t on_pattern[];
-extern pattern_t mode1_pattern[];
-
void init_pattern();
void patterns_next_tick();
void led_set_pattern(unsigned char led, pattern_t *pattern);
-pattern_t *number_pattern(unsigned char num);
+pattern_t *number_pattern(unsigned char num, unsigned char inv);
+void pattern_reload();
/* buttons.c */
#define MAX_USER_PARAMS 3
void susp_buttons();
void timer_check_buttons();
unsigned char get_user_param(unsigned char param);
-pattern_t *status_pattern_select(unsigned char n);
unsigned char buttons_wait_for_release();
+unsigned char buttons_setup_in_progress();
+pattern_t *buttons_setup_status0_pattern_select();
+pattern_t *buttons_setup_status1_pattern_select();
/* battery.c */
extern volatile unsigned char battery_100mv;
void battery_adc();
void init_battery();
+/* control.c */
+extern pattern_t on1_pattern[];
+
+void init_control();
+void toggle_dim_mode();
+void set_panic_mode();
+pattern_t *pwmled0_pattern_select();
+pattern_t *pwmled1_pattern_select();
+pattern_t *pwmled2_pattern_select();
+pattern_t *status_led_pattern_select();
+pattern_t *illumination_led_pattern_select();
+
/* main.c */
void power_down();
init_gpio();
init_ambient();
init_pattern();
+ init_control();
set_sleep_mode(SLEEP_MODE_IDLE);
}
#include <avr/io.h>
+#include <stdlib.h> // for NULL
#include "lights.h"
static unsigned char led_counters[N_LEDS];
static pattern_t *led_patterns[N_LEDS];
-pattern_t off_pattern[] = {
- { 0, PATTERN_FOREVER },
-};
-
-pattern_t zero_pattern[] = {
- { 0, 0x10 },
- PATTERN_END
-};
-
-pattern_t on_pattern[] = {
- { 1, PATTERN_FOREVER },
-};
-
-pattern_t blink_pattern[] = {
- { 1, 0x4 },
- { 0, 0x8 },
- PATTERN_END
-};
-
-pattern_t mode1_pattern[] = {
- { 2, 0x1 },
- { 0, 0x1 },
- { 2, 0x1 },
- { 0, 0x8 },
- { 1, 0x1 },
- { 0, 0x1 },
- { 1, 0x1 },
- { 0, 0x8 },
- PATTERN_END
-};
-
-pattern_t boot_pattern[] = {
+static pattern_t boot_pattern[] = {
{ 1, 0x6 },
{ 0, 0x6 },
{ 1, 0x3 },
PATTERN_END
};
-pattern_t pattern_num[] = {
+static pattern_t pattern_num[] = {
{ 0, 0x5 },
{ 1, 0x1 }, /* 10 */
{ 0, 0x5 },
PATTERN_END
};
-static unsigned char test_running;
+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, 0x1E },
+ PATTERN_END
+};
static void led_set_mode(unsigned char n, unsigned char mode)
{
void led_set_pattern(unsigned char n, pattern_t *pattern)
{
- if (!pattern)
- pattern = off_pattern;
-
led_patterns[n] = pattern;
+
+ if (!pattern) {
+ led_set_mode(n, 0);
+ return;
+ }
+
led_counters[n] = pattern->duration;
led_set_mode(n, pattern->mode);
}
unsigned char i;
for (i = 0; i < N_LEDS; i++)
- led_set_pattern(i, zero_pattern);
+ led_set_pattern(i, NULL);
led_set_pattern(N_PWMLEDS+1, boot_pattern);
- test_running = 0;
}
-pattern_t *number_pattern(unsigned char num)
+pattern_t *number_pattern(unsigned char num, unsigned char inv)
{
if (num >= 9)
num = 9;
- return pattern_num + sizeof(pattern_num)/sizeof(pattern_t)
- - 2 - 2*num;
+ 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;
+ }
+}
+
+static pattern_t *pattern_select(unsigned char n)
+{
+ switch(n) {
+ case 0: return pwmled0_pattern_select();
+ case 1: return pwmled1_pattern_select();
+ case 2: return pwmled2_pattern_select();
+ case 3: return status_led_pattern_select();
+ case 4: return illumination_led_pattern_select();
+ default: return NULL;
+ }
}
-static inline pattern_t *pattern_select(unsigned char n)
+void pattern_reload()
{
- if (n < N_PWMLEDS)
- return mode1_pattern;
- else if (n == 3)
- return status_pattern_select(0);
- else if (n == 4)
- return status_pattern_select(1);
- return off_pattern;
+ unsigned char i;
+
+ for (i = 0; i < N_LEDS; i++)
+ led_set_pattern(i, pattern_select(i));
}
void patterns_next_tick()
unsigned char i;
for (i = 0; i < N_LEDS; i++) {
+ if (!led_patterns[i])
+ continue;
+
if (led_counters[i] == 0) {
pattern_t *p = led_patterns[i];
p++;