aboutsummaryrefslogtreecommitdiff
path: root/spaghetti-monster
diff options
context:
space:
mode:
authorSelene ToyKeeper2017-08-27 19:40:40 -0600
committerSelene ToyKeeper2017-08-27 19:40:40 -0600
commitdce497bf15799133bf336ab46c3e39d7b0d92839 (patch)
tree6a39b7912f046af72563c93344376e3830fe810a /spaghetti-monster
parentReduced ROM size, simplified logic, made sure discrete ramp won't overflow ou... (diff)
downloadanduril-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.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);
If you find this content useful please consider a small donation via bitcoin: bitcoin:1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2?amount=0.001&message=Donation Scraping git contents via cgit is very resource intensive. The continued hosting of these git repositories is entirely financed by your bitcoin contributions. For donations of a least 1 mBTC you include your IP address in the message of your bitcoin donation. This will remove this message in the future for requests from your IP, which will significantly reduce token usage. In any case, any contributions to bitcoin address 1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2 are very welcome. Thanks in advance for you contribution to a self-sustaining ecosystem.