aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spaghetti-monster/anduril.c181
-rw-r--r--spaghetti-monster/fsm-events.h22
-rw-r--r--spaghetti-monster/fsm-states.c13
-rw-r--r--spaghetti-monster/fsm-states.h3
4 files changed, 196 insertions, 23 deletions
diff --git a/spaghetti-monster/anduril.c b/spaghetti-monster/anduril.c
index 94b3139..0123ce0 100644
--- a/spaghetti-monster/anduril.c
+++ b/spaghetti-monster/anduril.c
@@ -42,18 +42,23 @@ uint8_t tempcheck_state(EventPtr event, uint16_t arg);
#endif
uint8_t lockout_state(EventPtr event, uint16_t arg);
uint8_t momentary_state(EventPtr event, uint16_t arg);
+uint8_t ramp_config_mode(EventPtr event, uint16_t arg);
+uint8_t number_entry_state(EventPtr event, uint16_t arg);
+
+// return value from number_entry_state()
+volatile uint8_t number_entry_value;
void blink_confirm(uint8_t num);
// brightness control
uint8_t memorized_level = MAX_1x7135;
// smooth vs discrete ramping
-uint8_t ramp_style = 0; // 0 = smooth, 1 = discrete
-uint8_t ramp_smooth_floor = 1;
-uint8_t ramp_smooth_ceil = MAX_LEVEL;
-uint8_t ramp_discrete_floor = 20;
-uint8_t ramp_discrete_ceil = MAX_LEVEL - 50;
-uint8_t ramp_discrete_steps = 3;
+volatile uint8_t ramp_style = 0; // 0 = smooth, 1 = discrete
+volatile uint8_t ramp_smooth_floor = 1;
+volatile uint8_t ramp_smooth_ceil = MAX_LEVEL;
+volatile uint8_t ramp_discrete_floor = 20;
+volatile uint8_t ramp_discrete_ceil = MAX_LEVEL - 50;
+volatile uint8_t ramp_discrete_steps = 3;
uint8_t ramp_discrete_step_size; // don't set this
// calculate the nearest ramp level which would be valid at the moment
@@ -211,7 +216,7 @@ uint8_t steady_state(EventPtr event, uint16_t arg) {
}
// 4 clicks: configure this ramp mode
else if (event == EV_4clicks) {
- // TODO: implement this
+ set_state(ramp_config_mode, 0);
return MISCHIEF_MANAGED;
}
// hold: change brightness (brighter)
@@ -398,6 +403,168 @@ uint8_t momentary_state(EventPtr event, uint16_t arg) {
}
+uint8_t ramp_config_mode(EventPtr event, uint16_t arg) {
+ //static uint8_t new_floor;
+ //static uint8_t new_ceil;
+ //static uint8_t new_num_steps;
+ static uint8_t config_step;
+ static uint8_t num_config_steps;
+ if (event == EV_enter_state) {
+ config_step = 0;
+ if (ramp_style) {
+ //new_floor = ramp_discrete_floor;
+ //new_ceil = ramp_discrete_ceil;
+ //new_num_steps = ramp_discrete_steps;
+ num_config_steps = 3;
+ }
+ else {
+ //new_floor = ramp_smooth_floor;
+ //new_ceil = ramp_smooth_ceil;
+ num_config_steps = 2;
+ }
+ return MISCHIEF_MANAGED;
+ }
+ // advance forward through config steps
+ else if (event == EV_tick) {
+ if (config_step < num_config_steps) {
+ //config_step ++;
+ push_state(number_entry_state, config_step + 1);
+ /*
+ switch (config_step) {
+ // set the floor value
+ case 0:
+ push_state(number_entry_state, 1);
+ break;
+ // set the ceiling value
+ case 1:
+ push_state(number_entry_state, 2);
+ break;
+ // set the number of steps (discrete ramp only)
+ case 2:
+ push_state(number_entry_state, 3);
+ break;
+ }
+ */
+ }
+ else {
+ // TODO: save_config();
+ // TODO: blink out some sort of success pattern
+ // return to steady mode
+ set_state(steady_state, memorized_level);
+ }
+ return MISCHIEF_MANAGED;
+ }
+ // an option was set (return from number_entry_state)
+ else if (event == EV_reenter_state) {
+ #if 0
+ // FIXME? this is a kludge which relies on the vars being consecutive
+ // in RAM and in the same order as declared
+ // ... and it doesn't work; it seems they're not consecutive :(
+ volatile uint8_t *dest;
+ if (ramp_style) dest = (&ramp_discrete_floor) + config_step;
+ else dest = (&ramp_smooth_floor) + config_step;
+ if (number_entry_value)
+ *dest = number_entry_value;
+ #else
+ switch (config_step) {
+ case 0:
+ if (number_entry_value) {
+ if (ramp_style) ramp_discrete_floor = number_entry_value;
+ else ramp_smooth_floor = number_entry_value;
+ }
+ break;
+ case 1:
+ if (number_entry_value) {
+ if (ramp_style) ramp_discrete_ceil = MAX_LEVEL + 1 - number_entry_value;
+ else ramp_smooth_ceil = MAX_LEVEL + 1 - number_entry_value;
+ }
+ break;
+ case 2:
+ if (number_entry_value)
+ ramp_discrete_steps = number_entry_value;
+ break;
+ }
+ #endif
+ config_step ++;
+ /* handled at next EV_tick
+ if (config_step > num_config_steps) {
+ // TODO: save_config();
+ // exit config mode
+ set_state(steady_state, memorized_level);
+ }
+ */
+ return MISCHIEF_MANAGED;
+ }
+ return EVENT_NOT_HANDLED;
+}
+
+
+uint8_t number_entry_state(EventPtr event, uint16_t arg) {
+ static uint8_t value;
+ static uint8_t blinks_left;
+ static uint8_t init_completed;
+ static uint16_t wait_ticks;
+ if (event == EV_enter_state) {
+ value = 0;
+ blinks_left = arg;
+ init_completed = 0;
+ wait_ticks = 0;
+ // TODO: blink out the 'arg' to show which option this is
+ return MISCHIEF_MANAGED;
+ }
+ else if (event == EV_tick) {
+ // blink out the option number
+ if (! init_completed) {
+ if (blinks_left) {
+ if ((arg & 31) == 10) {
+ set_level(RAMP_SIZE/4);
+ }
+ else if ((arg & 31) == 20) {
+ set_level(0);
+ }
+ else if ((arg & 31) == 31) {
+ blinks_left --;
+ }
+ }
+ else {
+ init_completed = 1;
+ wait_ticks = 0;
+ }
+ }
+ else { // buzz while waiting for a number to be entered
+ wait_ticks ++;
+ // buzz for N seconds after last event
+ if ((arg & 3) == 0) {
+ set_level(RAMP_SIZE/6);
+ }
+ else if ((arg & 3) == 2) {
+ set_level(RAMP_SIZE/8);
+ }
+ // time out after 4 seconds
+ if (wait_ticks > TICKS_PER_SECOND*4) {
+ number_entry_value = value;
+ set_level(0);
+ pop_state();
+ }
+ }
+ return MISCHIEF_MANAGED;
+ }
+ // count clicks
+ else if (event == EV_click1_release) {
+ value ++;
+ //number_entry_value = value;
+ wait_ticks = 0;
+ empty_event_sequence();
+ // flash briefly
+ set_level(RAMP_SIZE/2);
+ delay_4ms(8/2);
+ set_level(0);
+ return MISCHIEF_MANAGED;
+ }
+ return EVENT_NOT_HANDLED;
+}
+
+
uint8_t nearest_level(int16_t target) {
// bounds check
// using int16_t here saves us a bunch of logic elsewhere,
diff --git a/spaghetti-monster/fsm-events.h b/spaghetti-monster/fsm-events.h
index 114ccc4..e3edc77 100644
--- a/spaghetti-monster/fsm-events.h
+++ b/spaghetti-monster/fsm-events.h
@@ -51,17 +51,18 @@ static volatile uint16_t ticks_since_last_event = 0;
#define A_ENTER_STATE 1
#define A_LEAVE_STATE 2
-#define A_TICK 3
-#define A_PRESS 4
-#define A_HOLD 5
-#define A_RELEASE 6
-#define A_RELEASE_TIMEOUT 7
+#define A_REENTER_STATE 3
+#define A_TICK 4
+#define A_PRESS 5
+#define A_HOLD 6
+#define A_RELEASE 7
+#define A_RELEASE_TIMEOUT 8
// TODO: add events for over/under-heat conditions (with parameter for severity)
-#define A_OVERHEATING 8
-#define A_UNDERHEATING 9
+#define A_OVERHEATING 9
+#define A_UNDERHEATING 10
// TODO: add events for low voltage conditions
-#define A_VOLTAGE_LOW 10
-//#define A_VOLTAGE_CRITICAL 11
+#define A_VOLTAGE_LOW 11
+//#define A_VOLTAGE_CRITICAL 12
#define A_DEBUG 255 // test event for debugging
// Event types
@@ -74,6 +75,9 @@ Event EV_enter_state[] = {
Event EV_leave_state[] = {
A_LEAVE_STATE,
0 } ;
+Event EV_reenter_state[] = {
+ A_REENTER_STATE,
+ 0 } ;
Event EV_tick[] = {
A_TICK,
0 } ;
diff --git a/spaghetti-monster/fsm-states.c b/spaghetti-monster/fsm-states.c
index ec24dc8..2939475 100644
--- a/spaghetti-monster/fsm-states.c
+++ b/spaghetti-monster/fsm-states.c
@@ -31,13 +31,14 @@
// 255: error (not sure what this would even mean though, or what difference it would make)
// TODO: function to call stacked callbacks until one returns "handled"
-void _set_state(StatePtr new_state, uint16_t arg) {
+void _set_state(StatePtr new_state, uint16_t arg,
+ EventPtr exit_event, EventPtr enter_event) {
// call old state-exit hook (don't use stack)
- if (current_state != NULL) current_state(EV_leave_state, arg);
+ if (current_state != NULL) current_state(exit_event, arg);
// set new state
current_state = new_state;
// call new state-enter hook (don't use stack)
- if (new_state != NULL) current_state(EV_enter_state, arg);
+ if (new_state != NULL) current_state(enter_event, arg);
}
int8_t push_state(StatePtr new_state, uint16_t arg) {
@@ -46,7 +47,8 @@ int8_t push_state(StatePtr new_state, uint16_t arg) {
// new hook for non-exit recursion into child?
state_stack[state_stack_len] = new_state;
state_stack_len ++;
- _set_state(new_state, arg);
+ // FIXME: use EV_stacked_state?
+ _set_state(new_state, arg, EV_leave_state, EV_enter_state);
return state_stack_len;
} else {
// TODO: um... how is a flashlight supposed to handle a recursion depth error?
@@ -66,8 +68,7 @@ StatePtr pop_state() {
new_state = state_stack[state_stack_len-1];
}
// FIXME: what should 'arg' be?
- // FIXME: do we need a EV_reenter_state?
- _set_state(new_state, 0);
+ _set_state(new_state, 0, EV_leave_state, EV_reenter_state);
return old_state;
}
diff --git a/spaghetti-monster/fsm-states.h b/spaghetti-monster/fsm-states.h
index 0daf915..f92abba 100644
--- a/spaghetti-monster/fsm-states.h
+++ b/spaghetti-monster/fsm-states.h
@@ -35,7 +35,8 @@ volatile StatePtr current_state;
StatePtr state_stack[STATE_STACK_SIZE];
uint8_t state_stack_len = 0;
-void _set_state(StatePtr new_state, uint16_t arg);
+void _set_state(StatePtr new_state, uint16_t arg,
+ EventPtr exit_event, EventPtr enter_event);
int8_t push_state(StatePtr new_state, uint16_t arg);
StatePtr pop_state();
uint8_t set_state(StatePtr new_state, uint16_t arg);