diff options
| author | Selene ToyKeeper | 2017-08-27 19:40:40 -0600 |
|---|---|---|
| committer | Selene ToyKeeper | 2017-08-27 19:40:40 -0600 |
| commit | dce497bf15799133bf336ab46c3e39d7b0d92839 (patch) | |
| tree | 6a39b7912f046af72563c93344376e3830fe810a /spaghetti-monster | |
| parent | Reduced ROM size, simplified logic, made sure discrete ramp won't overflow ou... (diff) | |
| download | anduril-dce497bf15799133bf336ab46c3e39d7b0d92839.tar.gz anduril-dce497bf15799133bf336ab46c3e39d7b0d92839.tar.bz2 anduril-dce497bf15799133bf336ab46c3e39d7b0d92839.zip | |
Ramp config mode actually works now...
Added EV_reenter_state event to indicate an obscuring state was popped off the stack
and the underlying one is now on top again.
Diffstat (limited to 'spaghetti-monster')
| -rw-r--r-- | spaghetti-monster/anduril.c | 181 | ||||
| -rw-r--r-- | spaghetti-monster/fsm-events.h | 22 | ||||
| -rw-r--r-- | spaghetti-monster/fsm-states.c | 13 | ||||
| -rw-r--r-- | spaghetti-monster/fsm-states.h | 3 |
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); |
