diff options
| -rw-r--r-- | spaghetti-monster/baton.c | 2 | ||||
| -rw-r--r-- | spaghetti-monster/fsm-events.c | 23 | ||||
| -rw-r--r-- | spaghetti-monster/fsm-events.h | 3 | ||||
| -rw-r--r-- | spaghetti-monster/fsm-main.c | 7 | ||||
| -rw-r--r-- | spaghetti-monster/momentary.c | 3 | ||||
| -rw-r--r-- | spaghetti-monster/ramping-ui.c | 77 | ||||
| -rw-r--r-- | spaghetti-monster/spaghetti-monster.h | 4 |
7 files changed, 84 insertions, 35 deletions
diff --git a/spaghetti-monster/baton.c b/spaghetti-monster/baton.c index 6b694e4..2489f4e 100644 --- a/spaghetti-monster/baton.c +++ b/spaghetti-monster/baton.c @@ -226,3 +226,5 @@ void setup() { push_state(off_state, 0); } + +void loop() { } diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index 6dda236..4831df6 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -99,6 +99,29 @@ void delete_first_emission() { emissions[i].arg = 0; } +void process_emissions() { + while (emissions[0].event != NULL) { + emit_now(emissions[0].event, emissions[0].arg); + delete_first_emission(); + } +} + +// like delay_ms, except it aborts on state change +// return value: +// 0: state changed +// 1: normal completion +uint8_t nice_delay_ms(uint16_t ms) { + StatePtr old_state = current_state; + while(ms-- > 0) { + _delay_loop_2(BOGOMIPS*98/100); + process_emissions(); + if (old_state != current_state) { + return 0; // state changed; abort + } + } + return 1; +} + // Call stacked callbacks for the given event until one handles it. uint8_t emit_now(EventPtr event, uint16_t arg) { for(int8_t i=state_stack_len-1; i>=0; i--) { diff --git a/spaghetti-monster/fsm-events.h b/spaghetti-monster/fsm-events.h index 246a4ee..a14d7aa 100644 --- a/spaghetti-monster/fsm-events.h +++ b/spaghetti-monster/fsm-events.h @@ -209,9 +209,12 @@ volatile Emission emissions[EMISSION_QUEUE_LEN]; void append_emission(EventPtr event, uint16_t arg); void delete_first_emission(); +void process_emissions(); //#define emit_now emit uint8_t emit_now(EventPtr event, uint16_t arg); void emit(EventPtr event, uint16_t arg); void emit_current_event(uint16_t arg); +uint8_t nice_delay_ms(uint16_t ms); + #endif diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index 2faaeda..1a0c425 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -97,10 +97,9 @@ int main() { // TODO: check voltage? // TODO: check temperature? // if event queue not empty, process and pop first item in queue? - if (emissions[0].event != NULL) { - emit_now(emissions[0].event, emissions[0].arg); - delete_first_emission(); - } + process_emissions(); + + loop(); } } diff --git a/spaghetti-monster/momentary.c b/spaghetti-monster/momentary.c index 23cc359..fc26db3 100644 --- a/spaghetti-monster/momentary.c +++ b/spaghetti-monster/momentary.c @@ -75,3 +75,6 @@ void setup() { debug_blink(2); push_state(momentary_state, 0); } + +void loop() { } + diff --git a/spaghetti-monster/ramping-ui.c b/spaghetti-monster/ramping-ui.c index 6eeb3b0..256c4cf 100644 --- a/spaghetti-monster/ramping-ui.c +++ b/spaghetti-monster/ramping-ui.c @@ -31,7 +31,7 @@ // FSM states uint8_t off_state(EventPtr event, uint16_t arg); uint8_t steady_state(EventPtr event, uint16_t arg); -uint8_t party_strobe_state(EventPtr event, uint16_t arg); +uint8_t strobe_state(EventPtr event, uint16_t arg); // brightness control uint8_t memorized_level = MAX_1x7135; @@ -43,6 +43,11 @@ uint8_t ramp_step_size = 1; uint8_t target_level = 0; #endif +// strobe timing +volatile uint8_t strobe_delay = 67; +volatile uint8_t strobe_type = 0; // 0 == party strobe, 1 == tactical strobe + + uint8_t off_state(EventPtr event, uint16_t arg) { // turn emitter off when entering state if (event == EV_enter_state) { @@ -74,7 +79,7 @@ uint8_t off_state(EventPtr event, uint16_t arg) { } // 3 clicks: strobe mode else if (event == EV_3clicks) { - set_state(party_strobe_state, 255); + set_state(strobe_state, 0); return 0; } // hold: go to lowest level @@ -90,7 +95,7 @@ uint8_t off_state(EventPtr event, uint16_t arg) { set_state(steady_state, 1); return 0; } - // click-release-hold: go to highest level (for ramping down) + // click, hold: go to highest level (for ramping down) else if (event == EV_click2_hold) { set_state(steady_state, MAX_LEVEL); return 0; @@ -98,6 +103,7 @@ uint8_t off_state(EventPtr event, uint16_t arg) { return 1; } + uint8_t steady_state(EventPtr event, uint16_t arg) { // turn LED on when we first enter the mode if (event == EV_enter_state) { @@ -135,7 +141,7 @@ uint8_t steady_state(EventPtr event, uint16_t arg) { } // 3 clicks: go to strobe modes else if (event == EV_3clicks) { - set_state(party_strobe_state, 0xff); + set_state(strobe_state, 0); return 0; } // 4 clicks: toggle smooth vs discrete ramping @@ -170,7 +176,7 @@ uint8_t steady_state(EventPtr event, uint16_t arg) { set_level(memorized_level); return 0; } - // click-release-hold: change brightness (dimmer) + // click, hold: change brightness (dimmer) else if (event == EV_click2_hold) { // ramp slower in discrete mode if (arg % ramp_step_size != 0) { @@ -219,26 +225,9 @@ uint8_t steady_state(EventPtr event, uint16_t arg) { return 1; } -uint8_t party_strobe_state(EventPtr event, uint16_t arg) { - static volatile uint8_t frames = 0; - static volatile uint8_t between = 2; + +uint8_t strobe_state(EventPtr event, uint16_t arg) { if (event == EV_enter_state) { - if (arg < 64) between = arg; - frames = 0; - return 0; - } - // tick: strobe the emitter - else if (event == EV_tick) { - if (frames == 0) { - PWM1_LVL = 0; - PWM2_LVL = 255; - if (between < 3) delay_zero(); - else delay_ms(1); - PWM2_LVL = 0; - } - //frames = (frames + 1) % between; - frames++; - if (frames > between) frames = 0; return 0; } // 1 click: off @@ -246,25 +235,37 @@ uint8_t party_strobe_state(EventPtr event, uint16_t arg) { set_state(off_state, 0); return 0; } - // 2 clicks: go back to regular modes + // 2 clicks: toggle party strobe vs tactical strobe else if (event == EV_2clicks) { + strobe_type ^= 1; + return 0; + } + // 3 clicks: go back to regular modes + else if (event == EV_3clicks) { set_state(steady_state, memorized_level); return 0; } - // hold: change speed + // hold: change speed (go faster) else if (event == EV_click1_hold) { - if ((arg % HOLD_TIMEOUT) == 0) { - between = (between+1)%6; - frames = 0; + if ((arg & 1) == 0) { + if (strobe_delay > 8) strobe_delay --; + } + return 0; + } + // click, hold: change speed (go slower) + else if (event == EV_click2_hold) { + if ((arg & 1) == 0) { + if (strobe_delay < 255) strobe_delay ++; } return 0; } return 1; } + void low_voltage() { // "step down" from strobe to something low - if (current_state == party_strobe_state) { + if (current_state == strobe_state) { set_state(steady_state, RAMP_SIZE/6); } // in normal mode, step down by half or turn off @@ -278,6 +279,7 @@ void low_voltage() { } } + void setup() { set_level(RAMP_SIZE/8); delay_4ms(3); @@ -285,3 +287,18 @@ void setup() { push_state(off_state, 0); } + + +void loop() { + if (current_state == strobe_state) { + set_level(MAX_LEVEL); + if (strobe_type == 0) { // party strobe + if (strobe_delay < 30) delay_zero(); + else delay_ms(1); + } else { //tactical strobe + nice_delay_ms(strobe_delay >> 1); + } + set_level(0); + nice_delay_ms(strobe_delay); + } +} diff --git a/spaghetti-monster/spaghetti-monster.h b/spaghetti-monster/spaghetti-monster.h index 2ba3208..7d26390 100644 --- a/spaghetti-monster/spaghetti-monster.h +++ b/spaghetti-monster/spaghetti-monster.h @@ -54,9 +54,11 @@ void debug_blink(uint8_t num) { // TODO? new delay() functions which handle queue consumption? // TODO? new interruptible delay() functions? +// Define these in your SpaghettiMonster recipe // boot-time tasks -// Define this in your SpaghettiMonster recipe void setup(); +// single loop iteration, runs continuously +void loop(); // include executable functions too, for easier compiling #include "fsm-states.c" |
