From 73a5a6974a98aa73ab392272b4d69d285c85dee5 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 19 Aug 2017 17:20:46 -0600 Subject: Completely reorganized SpaghettiMonster code into smaller logical pieces: fsm-*.c and fsm-*.h. --- spaghetti-monster/fsm-events.c | 137 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 spaghetti-monster/fsm-events.c (limited to 'spaghetti-monster/fsm-events.c') diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c new file mode 100644 index 0000000..6dda236 --- /dev/null +++ b/spaghetti-monster/fsm-events.c @@ -0,0 +1,137 @@ +/* + * fsm-events.c: Event-handling functions for SpaghettiMonster. + * + * Copyright (C) 2017 Selene ToyKeeper + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FSM_EVENTS_C +#define FSM_EVENTS_C + +// TODO: maybe compare events by number instead of pointer? +// (number = index in event types array) +// (comparison would use full event content, but send off index to callbacks) +// (saves space by using uint8_t instead of a pointer) +// (also eliminates the need to duplicate single-entry events like for voltage or timer tick) + +// return 1 if (a == b), 0 otherwise +uint8_t compare_event_sequences(uint8_t *a, const uint8_t *b) { + for(uint8_t i=0; (i= offset) return current_event[i-offset]; + return 0; +} +*/ + +inline uint8_t last_event_num() { + uint8_t i; + for(i=0; current_event[i] && (i=0; i--) { + uint8_t err = state_stack[i](event, arg); + if (! err) return 0; + } + return 1; // event not handled +} + +void emit(EventPtr event, uint16_t arg) { + // add this event to the queue for later, + // so we won't use too much time during an interrupt + append_emission(event, arg); +} + +// Search the pre-defined event list for one matching what the user just did, +// and emit it if one was found. +void emit_current_event(uint16_t arg) { + //uint8_t err = 1; + for (uint8_t i=0; i<(sizeof(event_sequences)/sizeof(EventPtr)); i++) { + if (events_match(current_event, event_sequences[i])) { + //DEBUG_FLASH; + //err = emit(event_sequences[i], arg); + //return err; + emit(event_sequences[i], arg); + return; + } + } + //return err; +} + +// TODO? add events to a queue when inside an interrupt +// instead of calling the event functions directly? +// (then empty the queue in main loop?) + +#endif -- cgit v1.2.3 From 32eaeddee34c76dda5456ed960be6278ed68e48d Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 24 Aug 2017 16:21:45 -0600 Subject: Added loop() to API, executes constantly. Added nice_delay_ms() to process events while waiting, and abort on state change. Converted ramping-ui strobe to smoothly variable with party and tactical modes. --- spaghetti-monster/fsm-events.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'spaghetti-monster/fsm-events.c') 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--) { -- cgit v1.2.3 From 39b30b41f92978a3e05a8de0a416279fb35b35b1 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 25 Aug 2017 02:14:31 -0600 Subject: Added battcheck mode to ramping-ui. It's bigger than I had hoped. :( Added fsm-misc.*, which currently only has interruptible blink functions in it. (for blinking out numbers and such) --- spaghetti-monster/fsm-events.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'spaghetti-monster/fsm-events.c') diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index 4831df6..29ef415 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -122,6 +122,18 @@ uint8_t nice_delay_ms(uint16_t ms) { return 1; } +/* +uint8_t nice_delay_4ms(uint8_t ms) { + return nice_delay_ms((uint16_t)ms << 2); +} +*/ + +/* +uint8_t nice_delay_s() { + return nice_delay_4ms(250); +} +*/ + // 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--) { -- cgit v1.2.3 From 674259407ace91bef354059c842b4114e95eb23c Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 26 Aug 2017 03:06:12 -0600 Subject: Added beacons/strobes to DarkHorse. Added a way to explicitly cancel the current "nice" delay without changing state. --- spaghetti-monster/fsm-events.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'spaghetti-monster/fsm-events.c') diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index 29ef415..90d0ffa 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -106,6 +106,10 @@ void process_emissions() { } } +// explicitly interrupt these "nice" delays +volatile uint8_t nice_delay_interrupt = 0; +inline void interrupt_nice_delays() { nice_delay_interrupt = 1; } + // like delay_ms, except it aborts on state change // return value: // 0: state changed @@ -115,7 +119,8 @@ uint8_t nice_delay_ms(uint16_t ms) { while(ms-- > 0) { _delay_loop_2(BOGOMIPS*98/100); process_emissions(); - if (old_state != current_state) { + if ((nice_delay_interrupt) || (old_state != current_state)) { + nice_delay_interrupt = 0; return 0; // state changed; abort } } -- cgit v1.2.3 From 4a96d3e40ee667fa819c8c95b5e360245a12865a Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 28 Aug 2017 02:13:35 -0600 Subject: Fixed a crash when user presses the button more times than the UI supports. (need to leave room for a trailing 0 in the array, oops) --- spaghetti-monster/fsm-events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spaghetti-monster/fsm-events.c') diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index 90d0ffa..99a6a72 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -47,7 +47,7 @@ uint8_t push_event(uint8_t ev_type) { uint8_t prev_event = 0; // never push the same event twice in a row for(i=0; current_event[i] && (i 0) { + #ifdef USE_DYNAMIC_UNDERCLOCKING + // underclock MCU to save power + CLKPR = 1< 0) { + // underclock MCU to save power + CLKPR = 1< 0) { #ifdef USE_DYNAMIC_UNDERCLOCKING + #ifdef USE_RAMPING + uint8_t level = actual_level; // volatile, avoid repeat access + if (level < QUARTERSPEED_LEVEL) { + CLKPR = 1<