From 268b2deacc7b65c7d9d2805d1e504cf94f5734ac Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 12 Oct 2018 16:16:02 -0600 Subject: Moved "off" mode's aux LED to config to "7 clicks from off". --- spaghetti-monster/anduril/anduril.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 6e33610..300e32b 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -139,13 +139,20 @@ #define RAMP_LENGTH 150 // default, if not overridden in a driver cfg file #define MAX_BIKING_LEVEL 120 // should be 127 or less #define USE_BATTCHECK -#ifdef USE_MUGGLE_MODE + +// determine the highest number of clicks to handle +#ifdef USE_INDICATOR_LED +#define MAX_CLICKS 7 +#elif defined(USE_MUGGLE_MODE) #define MAX_CLICKS 6 -#define MUGGLE_FLOOR 22 -#define MUGGLE_CEILING (MAX_1x7135+20) #else #define MAX_CLICKS 5 #endif + +#if defined(USE_MUGGLE_MODE) +#define MUGGLE_FLOOR 22 +#define MUGGLE_CEILING (MAX_1x7135+20) +#endif #define USE_IDLE_MODE // reduce power use while awake and no tasks are pending #define USE_DYNAMIC_UNDERCLOCKING // cut clock speed at very low modes for better efficiency @@ -488,6 +495,24 @@ uint8_t off_state(EventPtr event, uint16_t arg) { return MISCHIEF_MANAGED; } #endif + #ifdef USE_INDICATOR_LED + // 7 clicks: change indicator LED mode + else if (event == EV_7clicks) { + uint8_t mode = (indicator_led_mode & 3) + 1; + #ifdef TICK_DURING_STANDBY + mode = mode & 3; + #else + mode = mode % 3; + #endif + #ifdef INDICATOR_LED_SKIP_LOW + if (mode == 1) { mode ++; } + #endif + indicator_led_mode = (indicator_led_mode & 0b11111100) | mode; + indicator_led(mode); + save_config(); + return MISCHIEF_MANAGED; + } + #endif return EVENT_NOT_HANDLED; } @@ -1198,6 +1223,7 @@ uint8_t lockout_state(EventPtr event, uint16_t arg) { save_config(); return MISCHIEF_MANAGED; } + #if 0 // old method, deprecated in favor of "7 clicks from off" // click, click, hold: rotate through indicator LED modes (off mode) else if (event == EV_click3_hold) { #ifndef USE_INDICATOR_LED_WHILE_RAMPING @@ -1230,6 +1256,7 @@ uint8_t lockout_state(EventPtr event, uint16_t arg) { return MISCHIEF_MANAGED; } #endif + #endif // 4 clicks: exit else if (event == EV_4clicks) { blink_confirm(1); -- cgit v1.2.3 From 565fb109ec5e7cf195914834523b1723da374e40 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 15 Oct 2018 15:08:17 -0600 Subject: cleaned up fsm baton UI a little, added a short manual --- spaghetti-monster/baton/baton-simpler.c | 40 +++++------- spaghetti-monster/baton/baton.c | 112 ++++++++++++++++++-------------- spaghetti-monster/baton/baton.txt | 21 ++++++ 3 files changed, 103 insertions(+), 70 deletions(-) create mode 100644 spaghetti-monster/baton/baton.txt diff --git a/spaghetti-monster/baton/baton-simpler.c b/spaghetti-monster/baton/baton-simpler.c index 96b0ea7..d4725ef 100644 --- a/spaghetti-monster/baton/baton-simpler.c +++ b/spaghetti-monster/baton/baton-simpler.c @@ -20,7 +20,6 @@ #define FSM_EMISAR_D4_DRIVER #define USE_LVP #define USE_THERMAL_REGULATION -#define DEFAULT_THERM_CEIL 45 #define USE_DELAY_MS #include "spaghetti-monster.h" @@ -59,6 +58,11 @@ uint8_t off_state(EventPtr event, uint16_t arg) { set_level(0); return EVENT_HANDLED; } + // hold (longer): go to lowest level + else if (event == EV_click1_hold) { + set_state(steady_state, 0); + return EVENT_HANDLED; + } // 1 click (before timeout): go to memorized level, but allow abort for double click else if (event == EV_click1_release) { set_level(memorized_level); @@ -79,11 +83,6 @@ uint8_t off_state(EventPtr event, uint16_t arg) { set_state(lockout_state, 0); return EVENT_HANDLED; } - // hold: go to lowest level - else if (event == EV_click1_hold) { - set_state(steady_state, 0); - return EVENT_HANDLED; - } return EVENT_NOT_HANDLED; } @@ -91,8 +90,8 @@ uint8_t steady_state(EventPtr event, uint16_t arg) { // turn LED on when we first enter the mode if (event == EV_enter_state) { // remember this level, unless it's moon or turbo - if ((arg > 0) && (arg < MAX_LEVEL)) - memorized_level = arg; + if ((arg > 0) && (arg < MAX_LEVEL)) memorized_level = arg; + // use the requested level even if not memorized #ifdef USE_THERMAL_REGULATION target_level = arg; #endif @@ -135,16 +134,12 @@ uint8_t steady_state(EventPtr event, uint16_t arg) { #ifdef USE_THERMAL_REGULATION // overheating: drop by 1 level else if (event == EV_temperature_high) { - if (actual_level > 1) { - set_level(actual_level - 1); - } + if (actual_level > 1) { set_level(actual_level - 1); } return EVENT_HANDLED; } // underheating: increase by 1 level if we're lower than the target else if (event == EV_temperature_low) { - if (actual_level < target_level) { - set_level(actual_level + 1); - } + if (actual_level < target_level) { set_level(actual_level + 1); } return EVENT_HANDLED; } #endif @@ -152,18 +147,14 @@ uint8_t steady_state(EventPtr event, uint16_t arg) { } uint8_t lockout_state(EventPtr event, uint16_t arg) { - // stay asleep while locked, but allow waking long enough to click 4 times + // stay asleep while locked if (event == EV_tick) { - static uint8_t ticks_spent_awake = 0; - ticks_spent_awake ++; - PWM1_LVL = 0; PWM2_LVL = 0; - if (ticks_spent_awake > 3 * TICKS_PER_SECOND) { - ticks_spent_awake = 0; - go_to_standby = 1; - } + PWM1_LVL = 0; PWM2_LVL = 0; // make sure emitters are off + // sleep 1 second after user stops pressing buttons + if (arg > TICKS_PER_SECOND) { go_to_standby = 1; } return MISCHIEF_MANAGED; } - // 4 clicks: exit + // 4 clicks: exit, and turn on at "low" level else if (event == EV_4clicks) { set_state(steady_state, 1); return MISCHIEF_MANAGED; @@ -175,6 +166,9 @@ void low_voltage() { // step down by one level or turn off if (actual_level > 0) { set_level(actual_level - 1); + #ifdef USE_THERMAL_REGULATION + target_level = actual_level; // don't let low temperature override LVP + #endif } else { set_state(off_state, 0); diff --git a/spaghetti-monster/baton/baton.c b/spaghetti-monster/baton/baton.c index 1266ddd..59a7196 100644 --- a/spaghetti-monster/baton/baton.c +++ b/spaghetti-monster/baton/baton.c @@ -20,22 +20,17 @@ #define FSM_EMISAR_D4_DRIVER #define USE_LVP #define USE_THERMAL_REGULATION -#define DEFAULT_THERM_CEIL 45 #define USE_DEBUG_BLINK #define USE_DELAY_MS #define USE_DELAY_4MS #define USE_DELAY_ZERO #include "spaghetti-monster.h" -// moon + ../../bin/level_calc.py 2 6 7135 18 10 150 FET 1 10 1500 -uint8_t pwm1_modes[] = { 3, 18, 110, 255, 255, 255, 0, }; -uint8_t pwm2_modes[] = { 0, 0, 0, 9, 58, 138, 255, }; -#define MAX_LEVEL (sizeof(pwm1_modes)-1) - // 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 lockout_state(EventPtr event, uint16_t arg); // brightness control uint8_t memorized_level = 1; @@ -44,93 +39,100 @@ uint8_t actual_level = 0; uint8_t target_level = 0; #endif +// moon + ../../bin/level_calc.py 2 6 7135 18 10 150 FET 1 10 1500 +uint8_t pwm1_levels[] = { 3, 18, 110, 255, 255, 255, 0, }; +uint8_t pwm2_levels[] = { 0, 0, 0, 9, 58, 138, 255, }; +#define MAX_LEVEL (sizeof(pwm1_levels)-1) + +// set LED brightness void set_level(uint8_t lvl) { actual_level = lvl; - PWM1_LVL = pwm1_modes[lvl]; - PWM2_LVL = pwm2_modes[lvl]; + PWM1_LVL = pwm1_levels[lvl]; + PWM2_LVL = pwm2_levels[lvl]; } uint8_t off_state(EventPtr event, uint16_t arg) { // turn emitter off when entering state if (event == EV_enter_state) { - PWM1_LVL = 0; - PWM2_LVL = 0; - // sleep while off (lower power use) - go_to_standby = 1; - return 0; + go_to_standby = 1; // sleep while off (lower power use) + return EVENT_HANDLED; } // hold (initially): go to lowest level, but allow abort for regular click else if (event == EV_click1_press) { set_level(0); - return 0; + return EVENT_HANDLED; + } + // hold (longer): go to lowest level + else if (event == EV_click1_hold) { + set_state(steady_state, 0); + return EVENT_HANDLED; } // 1 click (before timeout): go to memorized level, but allow abort for double click else if (event == EV_click1_release) { set_level(memorized_level); - return 0; + return EVENT_HANDLED; } // 1 click: regular mode else if (event == EV_1click) { set_state(steady_state, memorized_level); - return 0; + return EVENT_HANDLED; } // 2 clicks: highest mode else if (event == EV_2clicks) { set_state(steady_state, MAX_LEVEL); - return 0; + return EVENT_HANDLED; } // 3 clicks: strobe mode else if (event == EV_3clicks) { set_state(party_strobe_state, 255); - return 0; + return EVENT_HANDLED; } - // hold: go to lowest level - else if (event == EV_click1_hold) { - set_state(steady_state, 0); - return 0; + // 4 clicks: soft lockout + else if (event == EV_4clicks) { + set_state(lockout_state, 0); + return EVENT_HANDLED; } - return 1; + return EVENT_NOT_HANDLED; } uint8_t steady_state(EventPtr event, uint16_t arg) { // turn LED on when we first enter the mode if (event == EV_enter_state) { // remember this level, unless it's moon or turbo - if ((arg > 0) && (arg < MAX_LEVEL)) - memorized_level = arg; + if ((arg > 0) && (arg < MAX_LEVEL)) memorized_level = arg; // use the requested level even if not memorized #ifdef USE_THERMAL_REGULATION target_level = arg; #endif set_level(arg); - return 0; + return EVENT_HANDLED; } // 1 click: off else if (event == EV_1click) { set_state(off_state, 0); - return 0; + return EVENT_HANDLED; } // 2 clicks: go to/from highest level else if (event == EV_2clicks) { - if (actual_level < MAX_LEVEL) { + if (actual_level < MAX_LEVEL) { // go to turbo memorized_level = actual_level; // in case we're on moon #ifdef USE_THERMAL_REGULATION target_level = MAX_LEVEL; #endif set_level(MAX_LEVEL); } - else { + else { // return from turbo #ifdef USE_THERMAL_REGULATION target_level = memorized_level; #endif set_level(memorized_level); } - return 0; + return EVENT_HANDLED; } // 3 clicks: go to strobe modes else if (event == EV_3clicks) { set_state(party_strobe_state, 0xff); - return 0; + return EVENT_HANDLED; } // hold: change brightness else if (event == EV_click1_hold) { @@ -141,25 +143,21 @@ uint8_t steady_state(EventPtr event, uint16_t arg) { #endif set_level(memorized_level); } - return 0; + return EVENT_HANDLED; } #ifdef USE_THERMAL_REGULATION // overheating: drop by 1 level else if (event == EV_temperature_high) { - if (actual_level > 1) { - set_level(actual_level - 1); - } - return 0; + if (actual_level > 1) { set_level(actual_level - 1); } + return EVENT_HANDLED; } // underheating: increase by 1 level if we're lower than the target else if (event == EV_temperature_low) { - if (actual_level < target_level) { - set_level(actual_level + 1); - } - return 0; + if (actual_level < target_level) { set_level(actual_level + 1); } + return EVENT_HANDLED; } #endif - return 1; + return EVENT_NOT_HANDLED; } uint8_t party_strobe_state(EventPtr event, uint16_t arg) { @@ -168,7 +166,7 @@ uint8_t party_strobe_state(EventPtr event, uint16_t arg) { if (event == EV_enter_state) { if (arg < 64) between = arg; frames = 0; - return 0; + return MISCHIEF_MANAGED; } // tick: strobe the emitter else if (event == EV_tick) { @@ -182,17 +180,17 @@ uint8_t party_strobe_state(EventPtr event, uint16_t arg) { //frames = (frames + 1) % between; frames++; if (frames > between) frames = 0; - return 0; + return MISCHIEF_MANAGED; } // 1 click: off else if (event == EV_1click) { set_state(off_state, 0); - return 0; + return MISCHIEF_MANAGED; } // 2 clicks: go back to regular modes else if (event == EV_2clicks) { set_state(steady_state, memorized_level); - return 0; + return MISCHIEF_MANAGED; } // hold: change speed else if (event == EV_click1_hold) { @@ -200,9 +198,25 @@ uint8_t party_strobe_state(EventPtr event, uint16_t arg) { between = (between+1)%6; frames = 0; } - return 0; + return MISCHIEF_MANAGED; + } + return EVENT_NOT_HANDLED; +} + +uint8_t lockout_state(EventPtr event, uint16_t arg) { + // stay asleep while locked + if (event == EV_tick) { + PWM1_LVL = 0; PWM2_LVL = 0; // make sure emitters are off + // sleep 1 second after user stops pressing + if (arg > TICKS_PER_SECOND) { go_to_standby = 1; } + return MISCHIEF_MANAGED; + } + // 4 clicks: exit, and turn on at "low" level + else if (event == EV_4clicks) { + set_state(steady_state, 1); + return MISCHIEF_MANAGED; } - return 1; + return EVENT_NOT_HANDLED; } void low_voltage() { @@ -214,6 +228,10 @@ void low_voltage() { else if (current_state == steady_state) { if (actual_level > 0) { set_level(actual_level - 1); + #ifdef USE_THERMAL_REGULATION + target_level = actual_level; // don't let low temperature override LVP + #endif + } else { set_state(off_state, 0); diff --git a/spaghetti-monster/baton/baton.txt b/spaghetti-monster/baton/baton.txt new file mode 100644 index 0000000..2f0c22f --- /dev/null +++ b/spaghetti-monster/baton/baton.txt @@ -0,0 +1,21 @@ +This is a very simple clone of the Olight Baton interface. It is not +exact, but it has the basics. Mostly, it exists for the purposes of +demonstrating how to create interfaces in FSM. + +While off: + + - 1 click: Turn on (at memorized level). + - Hold: Turn on (at moon level). + - 2 clicks: Turn on (at highest level). + - 4 clicks: Soft lockout mode. + +While on: + + - 1 click: Turn off. + - Hold: Change the brightness. Goes up in steps, then wraps around. + - 2 clicks: Go to/from highest level. + +While locked: + + - 4 clicks: Exit lockout mode. + -- cgit v1.2.3 From fa9baf747b32e77e4a753dec99b7b6dc4795af1b Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 15 Oct 2018 15:09:34 -0600 Subject: removed more-complex baton UI (which only different by having a party strobe mode), replaced it with the simpler version (since this UI exists mostly as an example) --- spaghetti-monster/baton/baton-simpler.c | 188 -------------------------------- spaghetti-monster/baton/baton.c | 86 +++------------ 2 files changed, 13 insertions(+), 261 deletions(-) delete mode 100644 spaghetti-monster/baton/baton-simpler.c diff --git a/spaghetti-monster/baton/baton-simpler.c b/spaghetti-monster/baton/baton-simpler.c deleted file mode 100644 index d4725ef..0000000 --- a/spaghetti-monster/baton/baton-simpler.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Baton: Olight Baton-like UI 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 . - */ - -#define FSM_EMISAR_D4_DRIVER -#define USE_LVP -#define USE_THERMAL_REGULATION -#define USE_DELAY_MS -#include "spaghetti-monster.h" - -// FSM states -uint8_t off_state(EventPtr event, uint16_t arg); -uint8_t steady_state(EventPtr event, uint16_t arg); -uint8_t lockout_state(EventPtr event, uint16_t arg); - -// brightness control -uint8_t memorized_level = 1; -uint8_t actual_level = 0; -#ifdef USE_THERMAL_REGULATION -uint8_t target_level = 0; -#endif - -// moon + ../../bin/level_calc.py 2 6 7135 18 10 150 FET 1 10 1500 -uint8_t pwm1_levels[] = { 3, 18, 110, 255, 255, 255, 0, }; -uint8_t pwm2_levels[] = { 0, 0, 0, 9, 58, 138, 255, }; -#define MAX_LEVEL (sizeof(pwm1_levels)-1) - -// set LED brightness -void set_level(uint8_t lvl) { - actual_level = lvl; - PWM1_LVL = pwm1_levels[lvl]; - PWM2_LVL = pwm2_levels[lvl]; -} - -uint8_t off_state(EventPtr event, uint16_t arg) { - // turn emitter off when entering state - if (event == EV_enter_state) { - go_to_standby = 1; // sleep while off (lower power use) - return EVENT_HANDLED; - } - // hold (initially): go to lowest level, but allow abort for regular click - else if (event == EV_click1_press) { - set_level(0); - return EVENT_HANDLED; - } - // hold (longer): go to lowest level - else if (event == EV_click1_hold) { - set_state(steady_state, 0); - return EVENT_HANDLED; - } - // 1 click (before timeout): go to memorized level, but allow abort for double click - else if (event == EV_click1_release) { - set_level(memorized_level); - return EVENT_HANDLED; - } - // 1 click: regular mode - else if (event == EV_1click) { - set_state(steady_state, memorized_level); - return EVENT_HANDLED; - } - // 2 clicks: highest mode - else if (event == EV_2clicks) { - set_state(steady_state, MAX_LEVEL); - return EVENT_HANDLED; - } - // 4 clicks: soft lockout - else if (event == EV_4clicks) { - set_state(lockout_state, 0); - return EVENT_HANDLED; - } - return EVENT_NOT_HANDLED; -} - -uint8_t steady_state(EventPtr event, uint16_t arg) { - // turn LED on when we first enter the mode - if (event == EV_enter_state) { - // remember this level, unless it's moon or turbo - if ((arg > 0) && (arg < MAX_LEVEL)) memorized_level = arg; - // use the requested level even if not memorized - #ifdef USE_THERMAL_REGULATION - target_level = arg; - #endif - set_level(arg); - return EVENT_HANDLED; - } - // 1 click: off - else if (event == EV_1click) { - set_state(off_state, 0); - return EVENT_HANDLED; - } - // 2 clicks: go to/from highest level - else if (event == EV_2clicks) { - if (actual_level < MAX_LEVEL) { // go to turbo - memorized_level = actual_level; // in case we're on moon - #ifdef USE_THERMAL_REGULATION - target_level = MAX_LEVEL; - #endif - set_level(MAX_LEVEL); - } - else { // return from turbo - #ifdef USE_THERMAL_REGULATION - target_level = memorized_level; - #endif - set_level(memorized_level); - } - return EVENT_HANDLED; - } - // hold: change brightness - else if (event == EV_click1_hold) { - if ((arg % HOLD_TIMEOUT) == 0) { - memorized_level = (actual_level+1) % (MAX_LEVEL+1); - #ifdef USE_THERMAL_REGULATION - target_level = memorized_level; - #endif - set_level(memorized_level); - } - return EVENT_HANDLED; - } - #ifdef USE_THERMAL_REGULATION - // overheating: drop by 1 level - else if (event == EV_temperature_high) { - if (actual_level > 1) { set_level(actual_level - 1); } - return EVENT_HANDLED; - } - // underheating: increase by 1 level if we're lower than the target - else if (event == EV_temperature_low) { - if (actual_level < target_level) { set_level(actual_level + 1); } - return EVENT_HANDLED; - } - #endif - return EVENT_NOT_HANDLED; -} - -uint8_t lockout_state(EventPtr event, uint16_t arg) { - // stay asleep while locked - if (event == EV_tick) { - PWM1_LVL = 0; PWM2_LVL = 0; // make sure emitters are off - // sleep 1 second after user stops pressing buttons - if (arg > TICKS_PER_SECOND) { go_to_standby = 1; } - return MISCHIEF_MANAGED; - } - // 4 clicks: exit, and turn on at "low" level - else if (event == EV_4clicks) { - set_state(steady_state, 1); - return MISCHIEF_MANAGED; - } - return EVENT_NOT_HANDLED; -} - -void low_voltage() { - // step down by one level or turn off - if (actual_level > 0) { - set_level(actual_level - 1); - #ifdef USE_THERMAL_REGULATION - target_level = actual_level; // don't let low temperature override LVP - #endif - } - else { - set_state(off_state, 0); - } -} - -void setup() { - // blink when power is connected - set_level(MAX_LEVEL/2); - delay_ms(10); - set_level(0); - - push_state(off_state, 0); -} - -void loop() { -} diff --git a/spaghetti-monster/baton/baton.c b/spaghetti-monster/baton/baton.c index 59a7196..d4725ef 100644 --- a/spaghetti-monster/baton/baton.c +++ b/spaghetti-monster/baton/baton.c @@ -20,16 +20,12 @@ #define FSM_EMISAR_D4_DRIVER #define USE_LVP #define USE_THERMAL_REGULATION -#define USE_DEBUG_BLINK #define USE_DELAY_MS -#define USE_DELAY_4MS -#define USE_DELAY_ZERO #include "spaghetti-monster.h" // 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 lockout_state(EventPtr event, uint16_t arg); // brightness control @@ -82,11 +78,6 @@ uint8_t off_state(EventPtr event, uint16_t arg) { set_state(steady_state, MAX_LEVEL); return EVENT_HANDLED; } - // 3 clicks: strobe mode - else if (event == EV_3clicks) { - set_state(party_strobe_state, 255); - return EVENT_HANDLED; - } // 4 clicks: soft lockout else if (event == EV_4clicks) { set_state(lockout_state, 0); @@ -129,11 +120,6 @@ uint8_t steady_state(EventPtr event, uint16_t arg) { } return EVENT_HANDLED; } - // 3 clicks: go to strobe modes - else if (event == EV_3clicks) { - set_state(party_strobe_state, 0xff); - return EVENT_HANDLED; - } // hold: change brightness else if (event == EV_click1_hold) { if ((arg % HOLD_TIMEOUT) == 0) { @@ -160,54 +146,11 @@ uint8_t steady_state(EventPtr event, uint16_t arg) { return EVENT_NOT_HANDLED; } -uint8_t party_strobe_state(EventPtr event, uint16_t arg) { - static volatile uint8_t frames = 0; - static volatile uint8_t between = 2; - if (event == EV_enter_state) { - if (arg < 64) between = arg; - frames = 0; - return MISCHIEF_MANAGED; - } - // 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 MISCHIEF_MANAGED; - } - // 1 click: off - else if (event == EV_1click) { - set_state(off_state, 0); - return MISCHIEF_MANAGED; - } - // 2 clicks: go back to regular modes - else if (event == EV_2clicks) { - set_state(steady_state, memorized_level); - return MISCHIEF_MANAGED; - } - // hold: change speed - else if (event == EV_click1_hold) { - if ((arg % HOLD_TIMEOUT) == 0) { - between = (between+1)%6; - frames = 0; - } - return MISCHIEF_MANAGED; - } - return EVENT_NOT_HANDLED; -} - uint8_t lockout_state(EventPtr event, uint16_t arg) { // stay asleep while locked if (event == EV_tick) { PWM1_LVL = 0; PWM2_LVL = 0; // make sure emitters are off - // sleep 1 second after user stops pressing + // sleep 1 second after user stops pressing buttons if (arg > TICKS_PER_SECOND) { go_to_standby = 1; } return MISCHIEF_MANAGED; } @@ -220,29 +163,26 @@ uint8_t lockout_state(EventPtr event, uint16_t arg) { } void low_voltage() { - // "step down" from strobe to level 2 - if (current_state == party_strobe_state) { - set_state(steady_state, 1); - } - // in normal mode, step down by one level or turn off - else if (current_state == steady_state) { - if (actual_level > 0) { - set_level(actual_level - 1); + // step down by one level or turn off + if (actual_level > 0) { + set_level(actual_level - 1); #ifdef USE_THERMAL_REGULATION target_level = actual_level; // don't let low temperature override LVP #endif - - } - else { - set_state(off_state, 0); - } + } + else { + set_state(off_state, 0); } } void setup() { - debug_blink(2); + // blink when power is connected + set_level(MAX_LEVEL/2); + delay_ms(10); + set_level(0); push_state(off_state, 0); } -void loop() { } +void loop() { +} -- cgit v1.2.3 From a58ba65298350e9e7a2f8ce33645cdf1db5916cd Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 17 Oct 2018 23:46:10 -0600 Subject: PL47 doesn't need "low" mode for aux LED / switch LED --- spaghetti-monster/anduril/cfg-ff-pl47.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spaghetti-monster/anduril/cfg-ff-pl47.h b/spaghetti-monster/anduril/cfg-ff-pl47.h index d916e06..ef12964 100644 --- a/spaghetti-monster/anduril/cfg-ff-pl47.h +++ b/spaghetti-monster/anduril/cfg-ff-pl47.h @@ -17,7 +17,8 @@ // the "low" mode doesn't work on this light's aux LEDs // (but it does work on the switch LEDs) -//#define INDICATOR_LED_SKIP_LOW +// Fireflies wants to skip aux LED mode 1 (low) +#define INDICATOR_LED_SKIP_LOW // ... or if TICK_DURING_STANDBY is turned off: // off mode: high (2) -- cgit v1.2.3 From a19560f92e0ead081e494d58dd6cf36c170c85c0 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 17 Oct 2018 23:47:12 -0600 Subject: Initial untested support for the Sofirn SP36 (like a Q8 but smaller). --- spaghetti-monster/anduril/anduril.c | 4 ++++ spaghetti-monster/anduril/build-all.sh | 1 + 2 files changed, 5 insertions(+) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 300e32b..085c674 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -32,6 +32,7 @@ //#define FSM_FF_ROT66_DRIVER //#define FSM_FF_ROT66_219_DRIVER //#define FSM_FW3A_DRIVER +//#define FSM_SOFIRN_SP36_DRIVER #define USE_LVP // FIXME: won't build when this option is turned off @@ -114,6 +115,9 @@ #elif defined(FSM_FW3A_DRIVER) #include "cfg-fw3a.h" +#elif defined(FSM_SOFIRN_SP36_DRIVER) +#include "cfg-sofirn-sp36.h" + #endif diff --git a/spaghetti-monster/anduril/build-all.sh b/spaghetti-monster/anduril/build-all.sh index 9e2a83c..1a1363c 100755 --- a/spaghetti-monster/anduril/build-all.sh +++ b/spaghetti-monster/anduril/build-all.sh @@ -16,6 +16,7 @@ for TARGET in \ FF_ROT66 \ FF_ROT66_219 \ FW3A \ + SOFIRN_SP36 \ ; do echo "===== $TARGET =====" ../../../bin/build-85.sh "$UI" "-DFSM_${TARGET}_DRIVER" -- cgit v1.2.3 From aab4ec0543a7563ff08fbc2013bd414c03e25648 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 30 Oct 2018 00:42:43 -0600 Subject: Adjusted FF PL47 config. Made muggle floor/ceiling configurable per config file. --- spaghetti-monster/anduril/anduril.c | 4 ++++ spaghetti-monster/anduril/cfg-ff-pl47.h | 18 +++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 085c674..fd3c534 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -154,9 +154,13 @@ #endif #if defined(USE_MUGGLE_MODE) +#ifndef MUGGLE_FLOOR #define MUGGLE_FLOOR 22 +#endif +#ifndef MUGGLE_CEILING #define MUGGLE_CEILING (MAX_1x7135+20) #endif +#endif #define USE_IDLE_MODE // reduce power use while awake and no tasks are pending #define USE_DYNAMIC_UNDERCLOCKING // cut clock speed at very low modes for better efficiency diff --git a/spaghetti-monster/anduril/cfg-ff-pl47.h b/spaghetti-monster/anduril/cfg-ff-pl47.h index ef12964..d9431a1 100644 --- a/spaghetti-monster/anduril/cfg-ff-pl47.h +++ b/spaghetti-monster/anduril/cfg-ff-pl47.h @@ -39,15 +39,27 @@ #define HALFSPEED_LEVEL 13 #define QUARTERSPEED_LEVEL 6 -// ceiling is level 120/150 -#define RAMP_SMOOTH_CEIL (MAX_LEVEL*4/5) - // thermal regulation parameters #ifdef MIN_THERM_STEPDOWN #undef MIN_THERM_STEPDOWN // this should be lower, because 3x7135 instead of 1x7135 #endif #define MIN_THERM_STEPDOWN 60 // lowest value it'll step down to +// ceiling is level 120/150 +#define RAMP_SMOOTH_CEIL 120 + +// 10, 28, 46, 65, 83, 101, 120 (83 is highest regulated) +#define RAMP_DISCRETE_FLOOR 10 +#define RAMP_DISCRETE_CEIL 120 +#define RAMP_DISCRETE_STEPS 7 + +// ~25 lm to ~300 lm +#define MUGGLE_FLOOR 30 +#define MUGGLE_CEILING MAX_1x7135 +// ~50 lm to ~500 lm +//#define MUGGLE_FLOOR 40 +//#define MUGGLE_CEILING 90 + // regulate down faster when the FET is active, slower otherwise #define THERM_FASTER_LEVEL 130 // throttle back faster when high -- cgit v1.2.3 From 0110aa7f7988d54119ae085b5366918783b32901 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 2 Nov 2018 15:41:00 -0600 Subject: Corrected anduril.txt with the new aux LED button mappings. --- spaghetti-monster/anduril/anduril.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/spaghetti-monster/anduril/anduril.txt b/spaghetti-monster/anduril/anduril.txt index 9cbef68..f0f0b4d 100644 --- a/spaghetti-monster/anduril/anduril.txt +++ b/spaghetti-monster/anduril/anduril.txt @@ -17,6 +17,9 @@ From off: * 4 clicks: lock-out * 5 clicks: momentary mode (disconnect power to exit) * 6 clicks: muggle mode + * On hardware with an indicator LED... + * 7 clicks: Change aux LED mode used in "off" mode. + (the modes are usually off/low/high/blinking) In steady mode: * 1 click: off @@ -111,8 +114,8 @@ Lockout mode: * Hold: momentary moon * 4 clicks: exit lockout (return to regular "off" mode) * On hardware with an indicator LED... - * 3 clicks: Change button brightness used in lockout mode. (low/high/off) - * Click, click, hold: Change button brightness used in "off" mode. + * 3 clicks: Change aux LED brightness used in lockout mode. + (the modes are usually off/low/high/blinking) Momentary mode: * Press button: Light on (at memorized level). -- cgit v1.2.3 From 9e3e7a8e6a7c0ed3abe21b9ae24c07d8c13e3e93 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 3 Nov 2018 17:22:58 -0600 Subject: added missing ifdef which broke per-hardware ramp lengths --- spaghetti-monster/anduril/anduril.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index fd3c534..df478ee 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -140,7 +140,9 @@ /********* Configure SpaghettiMonster *********/ #define USE_DELAY_ZERO #define USE_RAMPING +#ifndef RAMP_LENGTH #define RAMP_LENGTH 150 // default, if not overridden in a driver cfg file +#endif #define MAX_BIKING_LEVEL 120 // should be 127 or less #define USE_BATTCHECK -- cgit v1.2.3 From 5699260c774749d9a6b1b5ad855a816806ed1be7 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 3 Nov 2018 18:46:57 -0600 Subject: forgot to add the Sofirn SP36 config file earlier, oops --- spaghetti-monster/anduril/cfg-sofirn-sp36.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 spaghetti-monster/anduril/cfg-sofirn-sp36.h diff --git a/spaghetti-monster/anduril/cfg-sofirn-sp36.h b/spaghetti-monster/anduril/cfg-sofirn-sp36.h new file mode 100644 index 0000000..11e3735 --- /dev/null +++ b/spaghetti-monster/anduril/cfg-sofirn-sp36.h @@ -0,0 +1,16 @@ +// Sofirn SP36 (small Q8) config options for Anduril + +#define FSM_BLF_Q8_DRIVER +#include "cfg-blf-q8.h" + +// stop panicking at ~50% power or ~2000 lm +#ifdef THERM_FASTER_LEVEL +#undef THERM_FASTER_LEVEL +#endif +#define THERM_FASTER_LEVEL 125 + +// be extra-careful at high levels +#ifndef THERM_HARD_TURBO_DROP +#define THERM_HARD_TURBO_DROP +#endif + -- cgit v1.2.3 From 94ba77de5c2c4bf8df3f23ac9ab397a360a75e69 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 3 Nov 2018 18:55:31 -0600 Subject: Made it easier to override hwdef-*.h values in cfg-*.h files. --- hwdef-BLF_GT.h | 16 +++++++++++++++- hwdef-BLF_GT_Mini.h | 6 ++++++ hwdef-BLF_Q8.h | 13 +++++++------ hwdef-Emisar_D4.h | 16 ++++++++++++---- hwdef-FF_PL47.h | 29 ++++++++++++++--------------- hwdef-FF_ROT66.h | 15 ++++++++------- hwdef-FW3A.h | 22 +++++++++++++++++----- spaghetti-monster/anduril/cfg-blf-gt.h | 4 ---- spaghetti-monster/anduril/cfg-blf-q8.h | 4 ---- spaghetti-monster/anduril/cfg-emisar-d4.h | 3 --- spaghetti-monster/anduril/cfg-ff-pl47.h | 3 --- spaghetti-monster/anduril/cfg-ff-rot66.h | 4 ---- spaghetti-monster/anduril/cfg-fw3a.h | 4 ---- 13 files changed, 79 insertions(+), 60 deletions(-) diff --git a/hwdef-BLF_GT.h b/hwdef-BLF_GT.h index 1a05741..7dcc8a0 100644 --- a/hwdef-BLF_GT.h +++ b/hwdef-BLF_GT.h @@ -9,29 +9,43 @@ #define PWM_CHANNELS 2 +#ifndef AUXLED_PIN #define AUXLED_PIN PB4 // pin 3 +#endif +#ifndef SWITCH_PIN #define SWITCH_PIN PB3 // pin 2 #define SWITCH_PCINT PCINT3 // pin 2 pin change interrupt +#endif +#ifndef PWM1_PIN #define PWM1_PIN PB0 // pin 5, 1x7135 PWM #define PWM1_LVL OCR0A // OCR0A is the output compare register for PB0 +#endif +#ifndef PWM2_PIN #define PWM2_PIN PB1 // pin 6, FET PWM #define PWM2_LVL OCR0B // OCR0B is the output compare register for PB1 +#endif #define USE_VOLTAGE_DIVIDER // use a voltage divider on pin 7, not VCC +#ifndef VOLTAGE_PIN #define VOLTAGE_PIN PB2 // pin 7, voltage ADC #define VOLTAGE_CHANNEL 0x01 // MUX 01 corresponds with PB2 +#define VOLTAGE_ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2 // 1.1V reference, left-adjust, ADC1/PB2 //#define ADMUX_VOLTAGE_DIVIDER ((1 << V_REF) | (1 << ADLAR) | VOLTAGE_CHANNEL) // 1.1V reference, no left-adjust, ADC1/PB2 #define ADMUX_VOLTAGE_DIVIDER ((1 << V_REF) | VOLTAGE_CHANNEL) -#define VOLTAGE_ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2 +#endif #define ADC_PRSCL 0x06 // clk/64 // Raw ADC readings at 4.4V and 2.2V (in-between, we assume values form a straight line) +#ifndef ADC_44 #define ADC_44 184 +#endif +#ifndef ADC_22 #define ADC_22 92 +#endif #define TEMP_CHANNEL 0b00001111 diff --git a/hwdef-BLF_GT_Mini.h b/hwdef-BLF_GT_Mini.h index 504c561..aacbca4 100644 --- a/hwdef-BLF_GT_Mini.h +++ b/hwdef-BLF_GT_Mini.h @@ -2,3 +2,9 @@ */ // exactly the same as a D1S, but with a lighted button #include "hwdef-Emisar_D1S.h" + +// lighted button +#ifndef AUXLED_PIN +#define AUXLED_PIN PB4 // pin 3 +#endif + diff --git a/hwdef-BLF_Q8.h b/hwdef-BLF_Q8.h index f00c392..6e13faf 100644 --- a/hwdef-BLF_Q8.h +++ b/hwdef-BLF_Q8.h @@ -1,16 +1,17 @@ /* BLF Q8 driver layout + * Q8 driver is the same as a D4, basically */ -// Q8 driver is the same as a D4, basically -#include "hwdef-Emisar_D4.h" // ... except the Q8 has a lighted button #ifndef AUXLED_PIN #define AUXLED_PIN PB4 // pin 3 #endif -// average drop across diode on this hardware -#ifdef VOLTAGE_FUDGE_FACTOR -#undef VOLTAGE_FUDGE_FACTOR -#endif +// ... and slightly different calibration +#ifndef VOLTAGE_FUDGE_FACTOR #define VOLTAGE_FUDGE_FACTOR 7 // add 0.35V +#endif + +// Q8 driver is the same as a D4, basically +#include "hwdef-Emisar_D4.h" diff --git a/hwdef-Emisar_D4.h b/hwdef-Emisar_D4.h index 105d3b9..0dfcab9 100644 --- a/hwdef-Emisar_D4.h +++ b/hwdef-Emisar_D4.h @@ -9,24 +9,32 @@ #define PWM_CHANNELS 2 -#define AUXLED_PIN PB4 // pin 3 +//#define AUXLED_PIN PB4 // pin 3 +#ifndef SWITCH_PIN #define SWITCH_PIN PB3 // pin 2 #define SWITCH_PCINT PCINT3 // pin 2 pin change interrupt +#endif +#ifndef PWM1_PIN #define PWM1_PIN PB0 // pin 5, 1x7135 PWM #define PWM1_LVL OCR0A // OCR0A is the output compare register for PB0 +#endif +#ifndef PWM2_PIN #define PWM2_PIN PB1 // pin 6, FET PWM #define PWM2_LVL OCR0B // OCR0B is the output compare register for PB1 +#endif // (FIXME: remove? not used?) -#define VOLTAGE_PIN PB2 // pin 7, voltage ADC -#define ADC_CHANNEL 0x01 // MUX 01 corresponds with PB2 -#define ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2 +//#define VOLTAGE_PIN PB2 // pin 7, voltage ADC +//#define ADC_CHANNEL 0x01 // MUX 01 corresponds with PB2 +//#define ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2 #define ADC_PRSCL 0x06 // clk/64 // average drop across diode on this hardware +#ifndef VOLTAGE_FUDGE_FACTOR #define VOLTAGE_FUDGE_FACTOR 5 // add 0.25V +#endif //#define TEMP_DIDR ADC4D #define TEMP_CHANNEL 0b00001111 diff --git a/hwdef-FF_PL47.h b/hwdef-FF_PL47.h index 4189220..217ce45 100644 --- a/hwdef-FF_PL47.h +++ b/hwdef-FF_PL47.h @@ -1,24 +1,23 @@ /* Fireflies PL47 driver layout + * same as a D4S, basically, except ... */ -// same as a D4S, basically -#include "hwdef-Emisar_D4S.h" -#undef FSM_EMISAR_D4S_DRIVER -#undef FSM_EMISAR_D4_DRIVER -// ... except the PL47 has aux LEDs on pin 7 -#ifdef AUXLED_PIN -#undef AUXLED_PIN -#endif +// ... the PL47 has aux LEDs on pin 7 +#ifndef AUXLED_PIN #define AUXLED_PIN PB2 // pin 7 +#endif // ... and switch LEDs on pin 3 -#ifdef AUXLED2_PIN -#undef AUXLED2_PIN -#endif +#ifndef AUXLED2_PIN #define AUXLED2_PIN PB4 // pin 3 - -// average drop across diode on this hardware -#ifdef VOLTAGE_FUDGE_FACTOR -#undef VOLTAGE_FUDGE_FACTOR #endif + +// ... and slightly different calibration +#ifndef VOLTAGE_FUDGE_FACTOR #define VOLTAGE_FUDGE_FACTOR 7 // add 0.35V +#endif + +#include "hwdef-Emisar_D4S.h" +#undef FSM_EMISAR_D4S_DRIVER +#undef FSM_EMISAR_D4_DRIVER + diff --git a/hwdef-FF_ROT66.h b/hwdef-FF_ROT66.h index 49947ab..0913a76 100644 --- a/hwdef-FF_ROT66.h +++ b/hwdef-FF_ROT66.h @@ -1,20 +1,21 @@ /* Fireflies ROT66 driver layout + * same as a FW3A, basically, except ... */ -// same as a FW3A, basically -#include "hwdef-FW3A.h" // ... except the ROT66 has a lighted button #ifndef AUXLED_PIN #define AUXLED_PIN PB2 // pin 7 #endif +// ... and slightly different calibration +#ifndef VOLTAGE_FUDGE_FACTOR +#define VOLTAGE_FUDGE_FACTOR 7 // add 0.35V +#endif + +#include "hwdef-FW3A.h" + // ... and no optic nerve #ifdef VISION_PIN #undef VISION_PIN #endif -// average drop across diode on this hardware -#ifdef VOLTAGE_FUDGE_FACTOR -#undef VOLTAGE_FUDGE_FACTOR -#endif -#define VOLTAGE_FUDGE_FACTOR 7 // add 0.35V diff --git a/hwdef-FW3A.h b/hwdef-FW3A.h index 5e253c7..8abab9a 100644 --- a/hwdef-FW3A.h +++ b/hwdef-FW3A.h @@ -9,23 +9,35 @@ #define PWM_CHANNELS 3 +#ifndef SWITCH_PIN #define SWITCH_PIN PB3 // pin 2 #define SWITCH_PCINT PCINT3 // pin 2 pin change interrupt +#endif +#ifndef PWM1_PIN #define PWM1_PIN PB0 // pin 5, 1x7135 PWM #define PWM1_LVL OCR0A // OCR0A is the output compare register for PB0 -#define PWM2_PIN PB1 // pin 6, FET PWM +#endif +#ifndef PWM2_PIN +#define PWM2_PIN PB1 // pin 6, 7x7135 PWM #define PWM2_LVL OCR0B // OCR0B is the output compare register for PB1 -#define PWM3_PIN PB4 // pin 3 -#define PWM3_LVL OCR1B +#endif +#ifndef PWM3_PIN +#define PWM3_PIN PB4 // pin 3, FET PWM +#define PWM3_LVL OCR1B // OCR1B is the output compare register for PB4 +#endif +#ifndef VISION_PIN #define VISION_PIN PB2 // pin 7, optic nerve -#define ADC_CHANNEL 0x01 // MUX 01 corresponds with PB2 -#define ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2 +//#define ADC_CHANNEL 0x01 // MUX 01 corresponds with PB2 +//#define ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2 +#endif #define ADC_PRSCL 0x06 // clk/64 // average drop across diode on this hardware +#ifndef VOLTAGE_FUDGE_FACTOR #define VOLTAGE_FUDGE_FACTOR 5 // add 0.25V +#endif //#define TEMP_DIDR ADC4D #define TEMP_CHANNEL 0b00001111 diff --git a/spaghetti-monster/anduril/cfg-blf-gt.h b/spaghetti-monster/anduril/cfg-blf-gt.h index 369d028..a29d7e7 100644 --- a/spaghetti-monster/anduril/cfg-blf-gt.h +++ b/spaghetti-monster/anduril/cfg-blf-gt.h @@ -14,10 +14,6 @@ //#undef USE_SET_LEVEL_GRADUALLY -#ifdef RAMP_LENGTH -#undef RAMP_LENGTH -#endif - #define RAMP_LENGTH 150 // First 60 values: level_calc.py 1 60 7135 4 5.0 255 // Remainder: all 255 (buck driver at 100% duty cycle) diff --git a/spaghetti-monster/anduril/cfg-blf-q8.h b/spaghetti-monster/anduril/cfg-blf-q8.h index 269aae9..1b9b971 100644 --- a/spaghetti-monster/anduril/cfg-blf-q8.h +++ b/spaghetti-monster/anduril/cfg-blf-q8.h @@ -7,10 +7,6 @@ // enable blinking indicator LED while off #define TICK_DURING_STANDBY -#ifdef RAMP_LENGTH -#undef RAMP_LENGTH -#endif - // copied from Emisar D4 ramp // ../../bin/level_calc.py 1 65 7135 1 0.8 150 // ... mixed with this: diff --git a/spaghetti-monster/anduril/cfg-emisar-d4.h b/spaghetti-monster/anduril/cfg-emisar-d4.h index 251f81d..e83c62d 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4.h @@ -1,8 +1,5 @@ // Emisar D4 config options for Anduril -#ifdef RAMP_LENGTH -#undef RAMP_LENGTH -#endif // ../../bin/level_calc.py 1 65 7135 1 0.8 150 // ... mixed with this: // ../../bin/level_calc.py 2 150 7135 4 0.33 150 FET 1 10 1500 diff --git a/spaghetti-monster/anduril/cfg-ff-pl47.h b/spaghetti-monster/anduril/cfg-ff-pl47.h index d9431a1..2e5647d 100644 --- a/spaghetti-monster/anduril/cfg-ff-pl47.h +++ b/spaghetti-monster/anduril/cfg-ff-pl47.h @@ -26,9 +26,6 @@ //#define INDICATOR_LED_DEFAULT_MODE ((0<<2) + 2) -#ifdef RAMP_LENGTH -#undef RAMP_LENGTH -#endif #define RAMP_LENGTH 150 // driver is a FET + 3x7135, ~400 lm at highest regulated level diff --git a/spaghetti-monster/anduril/cfg-ff-rot66.h b/spaghetti-monster/anduril/cfg-ff-rot66.h index c8e0d52..165b2ba 100644 --- a/spaghetti-monster/anduril/cfg-ff-rot66.h +++ b/spaghetti-monster/anduril/cfg-ff-rot66.h @@ -18,10 +18,6 @@ #define INDICATOR_LED_DEFAULT_MODE ((0<<2) + 2) -#ifdef RAMP_LENGTH -#undef RAMP_LENGTH -#endif - // driver is a FET+N+1, // where N=6 for the 219b version, // or N=13 for the XP-L HI version (this version) diff --git a/spaghetti-monster/anduril/cfg-fw3a.h b/spaghetti-monster/anduril/cfg-fw3a.h index 65f1e48..efa70ae 100644 --- a/spaghetti-monster/anduril/cfg-fw3a.h +++ b/spaghetti-monster/anduril/cfg-fw3a.h @@ -1,9 +1,5 @@ // FW3A config options for Anduril -#ifdef RAMP_LENGTH -#undef RAMP_LENGTH -#endif - // ../../bin/level_calc.py 1 65 7135 1 0.8 150 // ... mixed with this: // ../../../bin/level_calc.py 3 150 7135 1 0.33 150 7135 1 1 850 FET 1 10 1500 -- cgit v1.2.3 From 387cb35e8f9e2ca74cfc019d06a0051bc7b11aea Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 10 Nov 2018 01:13:42 -0700 Subject: calibrated Sofirn SP36 config --- spaghetti-monster/anduril/cfg-sofirn-sp36.h | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/spaghetti-monster/anduril/cfg-sofirn-sp36.h b/spaghetti-monster/anduril/cfg-sofirn-sp36.h index 11e3735..f6f7447 100644 --- a/spaghetti-monster/anduril/cfg-sofirn-sp36.h +++ b/spaghetti-monster/anduril/cfg-sofirn-sp36.h @@ -1,16 +1,34 @@ // Sofirn SP36 (small Q8) config options for Anduril +// voltage readings were a little high with the Q8 value +#define VOLTAGE_FUDGE_FACTOR 5 // add 0.25V, not 0.35V + #define FSM_BLF_Q8_DRIVER #include "cfg-blf-q8.h" -// stop panicking at ~50% power or ~2000 lm +// the high button LED mode on this light uses too much power +// off mode: low (1) +// lockout: blinking (3) +#define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 1) + +// don't blink during the ramp; the button LED brightness is sufficient +// to indicate which power channel(s) are being used +#ifdef BLINK_AT_CHANNEL_BOUNDARIES +#undef BLINK_AT_CHANNEL_BOUNDARIES +#endif +#ifdef BLINK_AT_RAMP_CEILING +#undef BLINK_AT_RAMP_CEILING +#endif + +// stop panicking at ~60% power or ~3000 lm #ifdef THERM_FASTER_LEVEL #undef THERM_FASTER_LEVEL #endif -#define THERM_FASTER_LEVEL 125 +#define THERM_FASTER_LEVEL 130 // be extra-careful at high levels -#ifndef THERM_HARD_TURBO_DROP -#define THERM_HARD_TURBO_DROP -#endif +// (or not... this host seems to heat up pretty slowly) +//#ifndef THERM_HARD_TURBO_DROP +//#define THERM_HARD_TURBO_DROP +//#endif -- cgit v1.2.3 From e942fa7c47f446891e3bb0a07316d22cc32c00c2 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 11 Nov 2018 05:14:47 -0700 Subject: Rewrote the event system to use a single byte for each event instead of an array of actions. Not thoroughly tested yet, not done yet, have only updated Anduril to fit, and only partially. --- spaghetti-monster/anduril/anduril.c | 116 ++++--- spaghetti-monster/fsm-events.c | 96 ++---- spaghetti-monster/fsm-events.h | 607 ++++++++---------------------------- spaghetti-monster/fsm-pcint.c | 4 +- spaghetti-monster/fsm-states.c | 4 +- spaghetti-monster/fsm-states.h | 6 +- spaghetti-monster/fsm-wdt.c | 38 +-- 7 files changed, 253 insertions(+), 618 deletions(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index df478ee..de4f996 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -226,45 +226,45 @@ typedef enum { // FSM states -uint8_t off_state(EventPtr event, uint16_t arg); +uint8_t off_state(Event event, uint16_t arg); // simple numeric entry config menu -uint8_t config_state_base(EventPtr event, uint16_t arg, +uint8_t config_state_base(Event event, uint16_t arg, uint8_t num_config_steps, void (*savefunc)()); #define MAX_CONFIG_VALUES 3 uint8_t config_state_values[MAX_CONFIG_VALUES]; // ramping mode and its related config mode -uint8_t steady_state(EventPtr event, uint16_t arg); -uint8_t ramp_config_state(EventPtr event, uint16_t arg); +uint8_t steady_state(Event event, uint16_t arg); +uint8_t ramp_config_state(Event event, uint16_t arg); // party and tactical strobes #ifdef USE_STROBE_STATE -uint8_t strobe_state(EventPtr event, uint16_t arg); +uint8_t strobe_state(Event event, uint16_t arg); #endif #ifdef USE_BATTCHECK -uint8_t battcheck_state(EventPtr event, uint16_t arg); +uint8_t battcheck_state(Event event, uint16_t arg); #endif #ifdef USE_THERMAL_REGULATION -uint8_t tempcheck_state(EventPtr event, uint16_t arg); -uint8_t thermal_config_state(EventPtr event, uint16_t arg); +uint8_t tempcheck_state(Event event, uint16_t arg); +uint8_t thermal_config_state(Event event, uint16_t arg); #endif // 1-hour ramp down from low, then automatic off -uint8_t goodnight_state(EventPtr event, uint16_t arg); +uint8_t goodnight_state(Event event, uint16_t arg); // beacon mode and its related config mode -uint8_t beacon_state(EventPtr event, uint16_t arg); -uint8_t beacon_config_state(EventPtr event, uint16_t arg); +uint8_t beacon_state(Event event, uint16_t arg); +uint8_t beacon_config_state(Event event, uint16_t arg); // soft lockout #define MOON_DURING_LOCKOUT_MODE -uint8_t lockout_state(EventPtr event, uint16_t arg); +uint8_t lockout_state(Event event, uint16_t arg); // momentary / signalling mode -uint8_t momentary_state(EventPtr event, uint16_t arg); +uint8_t momentary_state(Event event, uint16_t arg); #ifdef USE_MUGGLE_MODE // muggle mode, super-simple, hard to exit -uint8_t muggle_state(EventPtr event, uint16_t arg); +uint8_t muggle_state(Event event, uint16_t arg); uint8_t muggle_mode_active = 0; #endif // general helper function for config modes -uint8_t number_entry_state(EventPtr event, uint16_t arg); +uint8_t number_entry_state(Event event, uint16_t arg); // return value from number_entry_state() volatile uint8_t number_entry_value; @@ -387,7 +387,7 @@ uint8_t triangle_wave(uint8_t phase); volatile uint8_t beacon_seconds = 2; -uint8_t off_state(EventPtr event, uint16_t arg) { +uint8_t off_state(Event event, uint16_t arg) { // turn emitter off when entering state if (event == EV_enter_state) { set_level(0); @@ -527,7 +527,7 @@ uint8_t off_state(EventPtr event, uint16_t arg) { } -uint8_t steady_state(EventPtr event, uint16_t arg) { +uint8_t steady_state(Event event, uint16_t arg) { uint8_t mode_min = ramp_smooth_floor; uint8_t mode_max = ramp_smooth_ceil; uint8_t ramp_step_size = 1; @@ -846,7 +846,7 @@ uint8_t steady_state(EventPtr event, uint16_t arg) { #ifdef USE_STROBE_STATE -uint8_t strobe_state(EventPtr event, uint16_t arg) { +uint8_t strobe_state(Event event, uint16_t arg) { // 'st' reduces ROM size by avoiding access to a volatile var // (maybe I should just make it nonvolatile?) strobe_mode_te st = strobe_type; @@ -1059,7 +1059,7 @@ uint8_t strobe_state(EventPtr event, uint16_t arg) { #ifdef USE_BATTCHECK -uint8_t battcheck_state(EventPtr event, uint16_t arg) { +uint8_t battcheck_state(Event event, uint16_t arg) { // 1 click: off if (event == EV_1click) { set_state(off_state, 0); @@ -1076,7 +1076,7 @@ uint8_t battcheck_state(EventPtr event, uint16_t arg) { #ifdef USE_THERMAL_REGULATION -uint8_t tempcheck_state(EventPtr event, uint16_t arg) { +uint8_t tempcheck_state(Event event, uint16_t arg) { // 1 click: off if (event == EV_1click) { set_state(off_state, 0); @@ -1097,7 +1097,7 @@ uint8_t tempcheck_state(EventPtr event, uint16_t arg) { #endif -uint8_t beacon_state(EventPtr event, uint16_t arg) { +uint8_t beacon_state(Event event, uint16_t arg) { // 1 click: off if (event == EV_1click) { set_state(off_state, 0); @@ -1124,7 +1124,7 @@ uint8_t beacon_state(EventPtr event, uint16_t arg) { #define GOODNIGHT_TICKS_PER_STEPDOWN (GOODNIGHT_TIME*TICKS_PER_SECOND*60L/GOODNIGHT_LEVEL) -uint8_t goodnight_state(EventPtr event, uint16_t arg) { +uint8_t goodnight_state(Event event, uint16_t arg) { static uint16_t ticks_since_stepdown = 0; // blink on start if (event == EV_enter_state) { @@ -1163,28 +1163,27 @@ uint8_t goodnight_state(EventPtr event, uint16_t arg) { } -uint8_t lockout_state(EventPtr event, uint16_t arg) { +uint8_t lockout_state(Event event, uint16_t arg) { #ifdef MOON_DURING_LOCKOUT_MODE // momentary(ish) moon mode during lockout // not all presses will be counted; // it depends on what is in the master event_sequences table - uint8_t last = 0; - for(uint8_t i=0; pgm_read_byte(event + i) && (i TICKS_PER_SECOND*15) { // sleep after 15 seconds go_to_standby = 1; // sleep while light is off + // TODO: lighted button should use lockout config? } return MISCHIEF_MANAGED; } @@ -1311,7 +1323,7 @@ uint8_t momentary_state(EventPtr event, uint16_t arg) { #ifdef USE_MUGGLE_MODE -uint8_t muggle_state(EventPtr event, uint16_t arg) { +uint8_t muggle_state(Event event, uint16_t arg) { static int8_t ramp_direction; static int8_t muggle_off_mode; @@ -1461,7 +1473,7 @@ uint8_t muggle_state(EventPtr event, uint16_t arg) { // ask the user for a sequence of numbers, then save them and return to caller -uint8_t config_state_base(EventPtr event, uint16_t arg, +uint8_t config_state_base(Event event, uint16_t arg, uint8_t num_config_steps, void (*savefunc)()) { static uint8_t config_step; @@ -1520,7 +1532,7 @@ void ramp_config_save() { } } -uint8_t ramp_config_state(EventPtr event, uint16_t arg) { +uint8_t ramp_config_state(Event event, uint16_t arg) { uint8_t num_config_steps; num_config_steps = 2 + ramp_style; return config_state_base(event, arg, @@ -1548,7 +1560,7 @@ void thermal_config_save() { if (therm_ceil > MAX_THERM_CEIL) therm_ceil = MAX_THERM_CEIL; } -uint8_t thermal_config_state(EventPtr event, uint16_t arg) { +uint8_t thermal_config_state(Event event, uint16_t arg) { return config_state_base(event, arg, 2, thermal_config_save); } @@ -1563,13 +1575,13 @@ void beacon_config_save() { } } -uint8_t beacon_config_state(EventPtr event, uint16_t arg) { +uint8_t beacon_config_state(Event event, uint16_t arg) { return config_state_base(event, arg, 1, beacon_config_save); } -uint8_t number_entry_state(EventPtr event, uint16_t arg) { +uint8_t number_entry_state(Event event, uint16_t arg) { static uint8_t value; static uint8_t blinks_left; static uint8_t entry_step; diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index ee7bc97..091d4cf 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -20,25 +20,8 @@ #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; -} -*/ + return 0; // unexpected event type -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; @@ -210,26 +188,10 @@ uint8_t emit_now(EventPtr event, uint16_t arg) { return 1; // event not handled } -void emit(EventPtr event, uint16_t arg) { +void emit(Event 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; -} - #endif diff --git a/spaghetti-monster/fsm-events.h b/spaghetti-monster/fsm-events.h index 0212c2c..d838800 100644 --- a/spaghetti-monster/fsm-events.h +++ b/spaghetti-monster/fsm-events.h @@ -23,10 +23,9 @@ #include // typedefs -typedef PROGMEM const uint8_t Event; -typedef Event * EventPtr; +typedef uint8_t Event; typedef struct Emission { - EventPtr event; + Event event; uint16_t arg; } Emission; @@ -36,11 +35,11 @@ typedef struct Emission { #define MISCHIEF_NOT_MANAGED EVENT_NOT_HANDLED #ifndef MAX_CLICKS -#define MAX_CLICKS 4 +#define MAX_CLICKS 15 #endif #define EV_MAX_LEN ((MAX_CLICKS*2)+3) -uint8_t current_event[EV_MAX_LEN]; +Event current_event; // at 0.016 ms per tick, 255 ticks = 4.08 s static volatile uint16_t ticks_since_last_event = 0; @@ -52,509 +51,175 @@ static volatile uint16_t ticks_since_last_event = 0; #define RELEASE_TIMEOUT 24 #endif -#define A_ENTER_STATE 1 -#define A_LEAVE_STATE 2 -#define A_REENTER_STATE 3 -#define A_TICK 4 -#define A_SLEEP_TICK 5 -#define A_PRESS 6 -#define A_HOLD 7 -#define A_RELEASE 8 -#define A_RELEASE_TIMEOUT 9 -#define A_OVERHEATING 10 -#define A_UNDERHEATING 11 -#define A_VOLTAGE_LOW 12 -//#define A_VOLTAGE_CRITICAL 13 -#define A_DEBUG 255 // test event for debugging +/* Event structure + * Bit 7: 1 for a button input event, 0 for all others. + * If bit 7 is 1: + * Bits 0,1,2,3: Click counter. Up to 15 clicks. + * Bit 4: 1 for a "press" event, 0 for a "release" event. + * Bit 5: 1 for a "hold" event, 0 otherwise. + * Bit 6: 1 for a "timeout" event, 0 otherwise. + * If bit 7 is 0: + * Not yet defined. + */ + +// event masks / bits +#define B_SYSTEM 0b10000000 +#define B_CLICK 0b00000000 +#define B_TIMEOUT 0b01000000 +#define B_HOLD 0b00100000 +#define B_PRESS 0b00010000 +#define B_RELEASE 0b00000000 +#define B_COUNT 0b00001111 +#define B_FLAGS 0b11110000 // Event types -// TODO: make these progmem-only? -Event EV_debug[] = { - A_DEBUG, - 0 } ; -Event EV_enter_state[] = { - A_ENTER_STATE, - 0 } ; -Event EV_leave_state[] = { - A_LEAVE_STATE, - 0 } ; -Event EV_reenter_state[] = { - A_REENTER_STATE, - 0 } ; -Event EV_tick[] = { - A_TICK, - 0 } ; +#define EV_debug (B_SYSTEM|0b01111111) +#define EV_enter_state (B_SYSTEM|0b00001000) +#define EV_leave_state (B_SYSTEM|0b00001001) +#define EV_reenter_state (B_SYSTEM|0b00001010) +#define EV_tick (B_SYSTEM|0b00000001) #ifdef TICK_DURING_STANDBY -Event EV_sleep_tick[] = { - A_SLEEP_TICK, - 0 } ; +#define EV_sleep_tick (B_SYSTEM|0b00000011) #endif #ifdef USE_LVP -Event EV_voltage_low[] = { - A_VOLTAGE_LOW, - 0 } ; +#define EV_voltage_low (B_SYSTEM|0b00000100) #endif #ifdef USE_THERMAL_REGULATION -Event EV_temperature_high[] = { - A_OVERHEATING, - 0 } ; -Event EV_temperature_low[] = { - A_UNDERHEATING, - 0 } ; +#define EV_temperature_high (B_SYSTEM|0b00000101) +#define EV_temperature_low (B_SYSTEM|0b00000110) #endif -Event EV_click1_press[] = { - A_PRESS, - 0 }; + +#define EV_none 0 + // shouldn't normally happen, but UI might reset event while button is down // so a release with no recorded prior hold could be possible -Event EV_release[] = { - A_RELEASE, - 0 }; -Event EV_click1_release[] = { - A_PRESS, - A_RELEASE, - 0 }; +#define EV_release (B_CLICK|B_RELEASE|0) + +#define EV_click1_press (B_CLICK|B_PRESS|1) +#define EV_click1_hold (B_CLICK|B_HOLD|B_PRESS|1) +#define EV_click1_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|1) +#define EV_click1_release (B_CLICK|B_RELEASE|1) +#define EV_click1_complete (B_CLICK|B_TIMEOUT|1) #define EV_1click EV_click1_complete -Event EV_click1_complete[] = { - A_PRESS, - A_RELEASE, - A_RELEASE_TIMEOUT, - 0 }; #define EV_hold EV_click1_hold -// FIXME: Should holds use "start+tick" or just "tick" with a tick number? -// Or "start+tick" with a tick number? -Event EV_click1_hold[] = { - A_PRESS, - A_HOLD, - 0 }; -Event EV_click1_hold_release[] = { - A_PRESS, - A_HOLD, - A_RELEASE, - 0 }; -#if MAX_CLICKS >= 2 -Event EV_click2_press[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - 0 }; -Event EV_click2_hold[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_HOLD, - 0 }; -Event EV_click2_hold_release[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_HOLD, - A_RELEASE, - 0 }; -Event EV_click2_release[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - 0 }; + +#define EV_click2_press (B_CLICK|B_PRESS|2) +#define EV_click2_hold (B_CLICK|B_HOLD|B_PRESS|2) +#define EV_click2_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|2) +#define EV_click2_release (B_CLICK|B_RELEASE|2) +#define EV_click2_complete (B_CLICK|B_TIMEOUT|2) #define EV_2clicks EV_click2_complete -Event EV_click2_complete[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_RELEASE_TIMEOUT, - 0 }; -#endif // MAX_CLICKS >= 2 -#if MAX_CLICKS >= 3 -Event EV_click3_press[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - 0 }; -Event EV_click3_hold[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_HOLD, - 0 }; -Event EV_click3_hold_release[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_HOLD, - A_RELEASE, - 0 }; -Event EV_click3_release[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - 0 }; + +#define EV_click3_press (B_CLICK|B_PRESS|3) +#define EV_click3_hold (B_CLICK|B_HOLD|B_PRESS|3) +#define EV_click3_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|3) +#define EV_click3_release (B_CLICK|B_RELEASE|3) +#define EV_click3_complete (B_CLICK|B_TIMEOUT|3) #define EV_3clicks EV_click3_complete -Event EV_click3_complete[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_RELEASE_TIMEOUT, - 0 }; -#endif // MAX_CLICKS >= 3 -#if MAX_CLICKS >= 4 + +#define EV_click4_press (B_CLICK|B_PRESS|4) +#define EV_click4_hold (B_CLICK|B_HOLD|B_PRESS|4) +#define EV_click4_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|4) +#define EV_click4_release (B_CLICK|B_RELEASE|4) +#define EV_click4_complete (B_CLICK|B_TIMEOUT|4) #define EV_4clicks EV_click4_complete -Event EV_click4_complete[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_RELEASE_TIMEOUT, - 0 }; -#endif -#if MAX_CLICKS >= 5 + +#define EV_click5_press (B_CLICK|B_PRESS|5) +#define EV_click5_hold (B_CLICK|B_HOLD|B_PRESS|5) +#define EV_click5_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|5) +#define EV_click5_release (B_CLICK|B_RELEASE|5) +#define EV_click5_complete (B_CLICK|B_TIMEOUT|5) #define EV_5clicks EV_click5_complete -Event EV_click5_complete[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_RELEASE_TIMEOUT, - 0 }; -#endif -#if MAX_CLICKS >= 6 + +#define EV_click6_press (B_CLICK|B_PRESS|6) +#define EV_click6_hold (B_CLICK|B_HOLD|B_PRESS|6) +#define EV_click6_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|6) +#define EV_click6_release (B_CLICK|B_RELEASE|6) +#define EV_click6_complete (B_CLICK|B_TIMEOUT|6) #define EV_6clicks EV_click6_complete -Event EV_click6_complete[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_RELEASE_TIMEOUT, - 0 }; -#endif -#if MAX_CLICKS >= 7 + +#define EV_click7_press (B_CLICK|B_PRESS|7) +#define EV_click7_hold (B_CLICK|B_HOLD|B_PRESS|7) +#define EV_click7_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|7) +#define EV_click7_release (B_CLICK|B_RELEASE|7) +#define EV_click7_complete (B_CLICK|B_TIMEOUT|7) #define EV_7clicks EV_click7_complete -Event EV_click7_complete[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_RELEASE_TIMEOUT, - 0 }; -#endif -#if MAX_CLICKS >= 8 + +#define EV_click8_press (B_CLICK|B_PRESS|8) +#define EV_click8_hold (B_CLICK|B_HOLD|B_PRESS|8) +#define EV_click8_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|8) +#define EV_click8_release (B_CLICK|B_RELEASE|8) +#define EV_click8_complete (B_CLICK|B_TIMEOUT|8) #define EV_8clicks EV_click8_complete -Event EV_click8_complete[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_RELEASE_TIMEOUT, - 0 }; -#endif -#if MAX_CLICKS >= 9 + +#define EV_click9_press (B_CLICK|B_PRESS|9) +#define EV_click9_hold (B_CLICK|B_HOLD|B_PRESS|9) +#define EV_click9_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|9) +#define EV_click9_release (B_CLICK|B_RELEASE|9) +#define EV_click9_complete (B_CLICK|B_TIMEOUT|9) #define EV_9clicks EV_click9_complete -Event EV_click9_complete[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_RELEASE_TIMEOUT, - 0 }; -#endif -#if MAX_CLICKS >= 10 + +#define EV_click10_press (B_CLICK|B_PRESS|10) +#define EV_click10_hold (B_CLICK|B_HOLD|B_PRESS|10) +#define EV_click10_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|10) +#define EV_click10_release (B_CLICK|B_RELEASE|10) +#define EV_click10_complete (B_CLICK|B_TIMEOUT|10) #define EV_10clicks EV_click10_complete -Event EV_click10_complete[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_RELEASE_TIMEOUT, - 0 }; -#endif -#if MAX_CLICKS >= 11 + +#define EV_click11_press (B_CLICK|B_PRESS|11) +#define EV_click11_hold (B_CLICK|B_HOLD|B_PRESS|11) +#define EV_click11_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|11) +#define EV_click11_release (B_CLICK|B_RELEASE|11) +#define EV_click11_complete (B_CLICK|B_TIMEOUT|11) #define EV_11clicks EV_click11_complete -Event EV_click11_complete[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_RELEASE_TIMEOUT, - 0 }; -#endif -#if MAX_CLICKS >= 12 + +#define EV_click12_press (B_CLICK|B_PRESS|12) +#define EV_click12_hold (B_CLICK|B_HOLD|B_PRESS|12) +#define EV_click12_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|12) +#define EV_click12_release (B_CLICK|B_RELEASE|12) +#define EV_click12_complete (B_CLICK|B_TIMEOUT|12) #define EV_12clicks EV_click12_complete -Event EV_click12_complete[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_RELEASE_TIMEOUT, - 0 }; -#endif -#if MAX_CLICKS >= 13 + +#define EV_click13_press (B_CLICK|B_PRESS|13) +#define EV_click13_hold (B_CLICK|B_HOLD|B_PRESS|13) +#define EV_click13_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|13) +#define EV_click13_release (B_CLICK|B_RELEASE|13) +#define EV_click13_complete (B_CLICK|B_TIMEOUT|13) #define EV_13clicks EV_click13_complete -Event EV_click13_complete[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_RELEASE_TIMEOUT, - 0 }; -#endif -#if MAX_CLICKS >= 14 + +#define EV_click14_press (B_CLICK|B_PRESS|14) +#define EV_click14_hold (B_CLICK|B_HOLD|B_PRESS|14) +#define EV_click14_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|14) +#define EV_click14_release (B_CLICK|B_RELEASE|14) +#define EV_click14_complete (B_CLICK|B_TIMEOUT|14) #define EV_14clicks EV_click14_complete -Event EV_click14_complete[] = { - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_PRESS, - A_RELEASE, - A_RELEASE_TIMEOUT, - 0 }; -#endif -// ... and so on - -// A list of button event types for easy iteration -// TODO: make this progmem-only? -EventPtr event_sequences[] = { - EV_click1_press, - EV_release, - EV_click1_release, - EV_click1_complete, - EV_click1_hold, - EV_click1_hold_release, - #if MAX_CLICKS >= 2 - EV_click2_press, - EV_click2_hold, - EV_click2_hold_release, - EV_click2_release, - EV_click2_complete, - #endif - #if MAX_CLICKS >= 3 - EV_click3_press, - EV_click3_hold, - EV_click3_hold_release, - EV_click3_release, - EV_click3_complete, - #endif - #if MAX_CLICKS >= 4 - EV_click4_complete, - #endif - #if MAX_CLICKS >= 5 - EV_click5_complete, - #endif - #if MAX_CLICKS >= 6 - EV_click6_complete, - #endif - #if MAX_CLICKS >= 7 - EV_click7_complete, - #endif - #if MAX_CLICKS >= 8 - EV_click8_complete, - #endif - #if MAX_CLICKS >= 9 - EV_click9_complete, - #endif - #if MAX_CLICKS >= 10 - EV_click10_complete, - #endif - #if MAX_CLICKS >= 11 - EV_click11_complete, - #endif - #if MAX_CLICKS >= 12 - EV_click12_complete, - #endif - #if MAX_CLICKS >= 13 - EV_click13_complete, - #endif - #if MAX_CLICKS >= 14 - EV_click14_complete, - #endif - // ... -}; - -#define events_match(a,b) compare_event_sequences(a,b) + +#define EV_click15_press (B_CLICK|B_PRESS|15) +#define EV_click15_hold (B_CLICK|B_HOLD|B_PRESS|15) +#define EV_click15_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|15) +#define EV_click15_release (B_CLICK|B_RELEASE|15) +#define EV_click15_complete (B_CLICK|B_TIMEOUT|15) +#define EV_15clicks EV_click15_complete + + +#define events_match(a,b) (a == b) // return 1 if (a == b), 0 otherwise -uint8_t compare_event_sequences(uint8_t *a, const uint8_t *b); +#define compare_event_sequences(a,b) (a == b) void empty_event_sequence(); uint8_t push_event(uint8_t ev_type); -// uint8_t last_event(uint8_t offset); -inline uint8_t last_event_num(); #define EMISSION_QUEUE_LEN 16 // no comment about "volatile emissions" volatile Emission emissions[EMISSION_QUEUE_LEN]; -void append_emission(EventPtr event, uint16_t arg); +void append_emission(Event 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 emit_now(Event event, uint16_t arg); +void emit(Event event, uint16_t arg); +#define emit_current_event(arg) emit(current_event, arg) uint8_t nice_delay_ms(uint16_t ms); //uint8_t nice_delay_4ms(uint8_t ms); diff --git a/spaghetti-monster/fsm-pcint.c b/spaghetti-monster/fsm-pcint.c index a79572d..acb627d 100644 --- a/spaghetti-monster/fsm-pcint.c +++ b/spaghetti-monster/fsm-pcint.c @@ -75,9 +75,9 @@ void PCINT_inner(uint8_t pressed) { uint8_t pushed; if (pressed) { - pushed = push_event(A_PRESS); + pushed = push_event(B_PRESS); } else { - pushed = push_event(A_RELEASE); + pushed = push_event(B_RELEASE); } // check if sequence matches any defined sequences diff --git a/spaghetti-monster/fsm-states.c b/spaghetti-monster/fsm-states.c index 09ae804..f91dc4b 100644 --- a/spaghetti-monster/fsm-states.c +++ b/spaghetti-monster/fsm-states.c @@ -32,7 +32,7 @@ // TODO: function to call stacked callbacks until one returns "handled" void _set_state(StatePtr new_state, uint16_t arg, - EventPtr exit_event, EventPtr enter_event) { + Event exit_event, Event enter_event) { // call old state-exit hook (don't use stack) if (current_state != NULL) current_state(exit_event, arg); // set new state @@ -82,7 +82,7 @@ uint8_t set_state(StatePtr new_state, uint16_t arg) { #ifndef DONT_USE_DEFAULT_STATE // bottom state on stack // handles default actions for LVP, thermal regulation, etc -uint8_t default_state(EventPtr event, uint16_t arg) { +uint8_t default_state(Event event, uint16_t arg) { if (0) {} // this should get compiled out #ifdef USE_LVP diff --git a/spaghetti-monster/fsm-states.h b/spaghetti-monster/fsm-states.h index 6e4a2a0..7d9361b 100644 --- a/spaghetti-monster/fsm-states.h +++ b/spaghetti-monster/fsm-states.h @@ -23,7 +23,7 @@ #include "fsm-adc.h" // typedefs -typedef uint8_t State(EventPtr event, uint16_t arg); +typedef uint8_t State(Event event, uint16_t arg); typedef State * StatePtr; // top of the stack @@ -36,12 +36,12 @@ StatePtr state_stack[STATE_STACK_SIZE]; uint8_t state_stack_len = 0; void _set_state(StatePtr new_state, uint16_t arg, - EventPtr exit_event, EventPtr enter_event); + Event exit_event, Event 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); #ifndef DONT_USE_DEFAULT_STATE -uint8_t default_state(EventPtr event, uint16_t arg); +uint8_t default_state(Event event, uint16_t arg); #endif #endif diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index e8419bc..cfff1fa 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -85,15 +85,8 @@ ISR(WDT_vect) { // append timeout to current event sequence, then // send event to current state callback - // preload recent events - uint8_t le_num = last_event_num(); - uint8_t last_event = 0; - uint8_t prev_event = 0; - if (le_num >= 1) last_event = current_event[le_num-1]; - if (le_num >= 2) prev_event = current_event[le_num-2]; - // callback on each timer tick - if (last_event == A_HOLD) { + if ((current_event & B_FLAGS) == (B_HOLD | B_PRESS)) { emit(EV_tick, 0); // override tick counter while holding button } else { @@ -101,29 +94,32 @@ ISR(WDT_vect) { } // user held button long enough to count as a long click? - if (last_event == A_PRESS) { - if (ticks_since_last_event >= HOLD_TIMEOUT) { - push_event(A_HOLD); - emit_current_event(0); + if (current_event & B_PRESS) { + // during a "hold", send a hold event each tick, with a timer + if (current_event & B_HOLD) { + emit_current_event(ticks_since_last_event); + } + // has button been down long enough to become a "hold"? + else { + if (ticks_since_last_event >= HOLD_TIMEOUT) { + current_event |= B_HOLD; + emit_current_event(0); + } } } - // user is still holding button, so tick - else if (last_event == A_HOLD) { - emit_current_event(ticks_since_last_event); - } - - // detect completed button presses with expired timeout - else if (last_event == A_RELEASE) { + // event in progress, but button not currently down + else if (current_event) { + // "hold" event just ended // no timeout required when releasing a long-press // TODO? move this logic to PCINT() and simplify things here? - if (prev_event == A_HOLD) { + if (current_event & B_HOLD) { //emit_current_event(0); // should have been emitted by PCINT empty_event_sequence(); } // end and clear event after release timeout else if (ticks_since_last_event >= RELEASE_TIMEOUT) { - push_event(A_RELEASE_TIMEOUT); + current_event |= B_TIMEOUT; emit_current_event(0); empty_event_sequence(); } -- cgit v1.2.3 From 6b41b5df92128c8810cbe14fd56258d90c3bb2b2 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 11 Nov 2018 06:09:07 -0700 Subject: Several fixes... - Made momentary+lockout modes smaller and work better. - Fixed buggy timing on hold events; made ticks_since_last_event reset when it should. - Reduced ROM size by caching volatile ticks_since_last_event sometimes. - Swapped what the top Event bit means, because it makes event handlers easier to write. - Made the maximum click event keep triggering if user keeps pressing, instead of dropping everything after the limit. --- spaghetti-monster/anduril/anduril.c | 54 +++++++++++++------------------------ spaghetti-monster/fsm-events.c | 13 ++++++--- spaghetti-monster/fsm-events.h | 6 ++--- spaghetti-monster/fsm-wdt.c | 23 ++++++++++------ 4 files changed, 46 insertions(+), 50 deletions(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index de4f996..4c3ccd7 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -1166,25 +1166,21 @@ uint8_t goodnight_state(Event event, uint16_t arg) { uint8_t lockout_state(Event event, uint16_t arg) { #ifdef MOON_DURING_LOCKOUT_MODE // momentary(ish) moon mode during lockout - // not all presses will be counted; - // it depends on what is in the master event_sequences table - if (arg == 0) { // Only turn on/off when button state changes - if (! (event & B_SYSTEM)) { // event is a button click type - if (event & B_PRESS) { // button is being held - #ifdef LOCKOUT_MOON_LOWEST - // Use lowest moon configured - uint8_t lvl = ramp_smooth_floor; - if (ramp_discrete_floor < lvl) lvl = ramp_discrete_floor; - set_level(lvl); - #else - // Use moon from current ramp - set_level(nearest_level(1)); - #endif - } - else { // button not being held - set_level(0); - } - } + // button is being held + if ((event & (B_CLICK | B_PRESS)) == (B_CLICK | B_PRESS)) { + #ifdef LOCKOUT_MOON_LOWEST + // Use lowest moon configured + uint8_t lvl = ramp_smooth_floor; + if (ramp_discrete_floor < lvl) lvl = ramp_discrete_floor; + set_level(lvl); + #else + // Use moon from current ramp + set_level(nearest_level(1)); + #endif + } + // button was released + else if ((event & (B_CLICK | B_PRESS)) == (B_CLICK)) { + set_level(0); } #endif @@ -1281,29 +1277,17 @@ uint8_t momentary_state(Event event, uint16_t arg) { // TODO: momentary strobe here? (for light painting) // light up when the button is pressed; go dark otherwise - #if 0 - if ((event ^ B_SYSTEM) & B_PRESS) { + // button is being held + if ((event & (B_CLICK | B_PRESS)) == (B_CLICK | B_PRESS)) { set_level(memorized_level); return MISCHIEF_MANAGED; } - else if (((event ^ B_SYSTEM) & B_PRESS) == 0) { + // button was released + else if ((event & (B_CLICK | B_PRESS)) == (B_CLICK)) { set_level(0); - empty_event_sequence(); //go_to_standby = 1; // sleep while light is off return MISCHIEF_MANAGED; } - #else - if (! (event & B_SYSTEM)) { // is a button-related event - if (event & B_PRESS) { // button is pressed - set_level(memorized_level); - } else { // button was released - set_level(0); - empty_event_sequence(); - //go_to_standby = 1; // sleep while light is off - } - return MISCHIEF_MANAGED; - } - #endif // Sleep, dammit! (but wait a few seconds first) // (because standby mode uses such little power that it can interfere diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index 091d4cf..b36c9f4 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -21,7 +21,7 @@ #define FSM_EVENTS_C void empty_event_sequence() { - current_event = 0; + current_event = EV_none; // when the user completes an input sequence, interrupt any running timers // to cancel any delays currently in progress // This eliminates a whole bunch of extra code: @@ -34,7 +34,7 @@ uint8_t push_event(uint8_t ev_type) { ticks_since_last_event = 0; // something happened // only click events are sent to this function - //current_event |= B_CLICK; + current_event |= B_CLICK; // handle button presses if (ev_type == B_PRESS) { @@ -43,9 +43,9 @@ uint8_t push_event(uint8_t ev_type) { // increase click counter if ((current_event & B_COUNT) < (B_COUNT-1)) { current_event ++; - return 1; // event pushed } - return 0; // maximum number of clicks reached + return 1; // event pushed, even if max clicks already reached + // (will just repeat the max over and over) } // handle button releases else if (ev_type == B_RELEASE) { @@ -194,4 +194,9 @@ void emit(Event event, uint16_t arg) { append_emission(event, arg); } +void emit_current_event(uint16_t arg) { + ticks_since_last_event = arg; + emit(current_event, arg); +} + #endif diff --git a/spaghetti-monster/fsm-events.h b/spaghetti-monster/fsm-events.h index d838800..45c95ee 100644 --- a/spaghetti-monster/fsm-events.h +++ b/spaghetti-monster/fsm-events.h @@ -63,8 +63,8 @@ static volatile uint16_t ticks_since_last_event = 0; */ // event masks / bits -#define B_SYSTEM 0b10000000 -#define B_CLICK 0b00000000 +#define B_SYSTEM 0b00000000 +#define B_CLICK 0b10000000 #define B_TIMEOUT 0b01000000 #define B_HOLD 0b00100000 #define B_PRESS 0b00010000 @@ -219,7 +219,7 @@ void process_emissions(); //#define emit_now emit uint8_t emit_now(Event event, uint16_t arg); void emit(Event event, uint16_t arg); -#define emit_current_event(arg) emit(current_event, arg) +void emit_current_event(uint16_t arg); uint8_t nice_delay_ms(uint16_t ms); //uint8_t nice_delay_4ms(uint8_t ms); diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index cfff1fa..3606c67 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -76,32 +76,38 @@ ISR(WDT_vect) { uint8_t pressed = button_is_pressed(); if (was_pressed != pressed) PCINT_inner(pressed); - //if (ticks_since_last_event < 0xff) ticks_since_last_event ++; + // cache this here to reduce ROM size, because it's volatile + uint16_t ticks_since_last = ticks_since_last_event; + // increment, but loop from max back to half - ticks_since_last_event = (ticks_since_last_event + 1) \ - | (ticks_since_last_event & 0x8000); + //if (ticks_since_last < 0xff) ticks_since_last ++; + ticks_since_last = (ticks_since_last + 1) \ + | (ticks_since_last & 0x8000); + // copy back to the original + ticks_since_last_event = ticks_since_last; // if time since last event exceeds timeout, // append timeout to current event sequence, then // send event to current state callback // callback on each timer tick - if ((current_event & B_FLAGS) == (B_HOLD | B_PRESS)) { + if ((current_event & B_FLAGS) == (B_CLICK | B_HOLD | B_PRESS)) { emit(EV_tick, 0); // override tick counter while holding button } else { - emit(EV_tick, ticks_since_last_event); + emit(EV_tick, ticks_since_last); } // user held button long enough to count as a long click? if (current_event & B_PRESS) { // during a "hold", send a hold event each tick, with a timer if (current_event & B_HOLD) { - emit_current_event(ticks_since_last_event); + emit_current_event(ticks_since_last); } // has button been down long enough to become a "hold"? else { - if (ticks_since_last_event >= HOLD_TIMEOUT) { + if (ticks_since_last >= HOLD_TIMEOUT) { + //ticks_since_last_event = 0; current_event |= B_HOLD; emit_current_event(0); } @@ -118,8 +124,9 @@ ISR(WDT_vect) { empty_event_sequence(); } // end and clear event after release timeout - else if (ticks_since_last_event >= RELEASE_TIMEOUT) { + else if (ticks_since_last >= RELEASE_TIMEOUT) { current_event |= B_TIMEOUT; + //ticks_since_last_event = 0; emit_current_event(0); empty_event_sequence(); } -- cgit v1.2.3 From a71c92e1f27a1ffe513bd0488011f3b6097455da Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 11 Nov 2018 16:00:12 -0700 Subject: Fixed the corner case of a button release when the previous state was already released. --- spaghetti-monster/fsm-events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index b36c9f4..72216ae 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -50,7 +50,7 @@ uint8_t push_event(uint8_t ev_type) { // handle button releases else if (ev_type == B_RELEASE) { // clear the press flag - current_event ^= B_PRESS; + current_event &= (~B_PRESS); // if a "hold" event just ended, set the timeout flag // to indicate that the event is done and can be cleared if (current_event & B_HOLD) { current_event |= B_TIMEOUT; } -- cgit v1.2.3 From 69d0d92c7902aa27510ab52a533bf91c37363910 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 11 Nov 2018 16:01:12 -0700 Subject: Fixed the sleep tick counter wrapping around to 0 instead of 32768. --- spaghetti-monster/fsm-events.h | 15 +++++---------- spaghetti-monster/fsm-wdt.c | 4 +++- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/spaghetti-monster/fsm-events.h b/spaghetti-monster/fsm-events.h index 45c95ee..2fd47b6 100644 --- a/spaghetti-monster/fsm-events.h +++ b/spaghetti-monster/fsm-events.h @@ -34,11 +34,6 @@ typedef struct Emission { #define MISCHIEF_MANAGED EVENT_HANDLED #define MISCHIEF_NOT_MANAGED EVENT_NOT_HANDLED -#ifndef MAX_CLICKS -#define MAX_CLICKS 15 -#endif - -#define EV_MAX_LEN ((MAX_CLICKS*2)+3) Event current_event; // at 0.016 ms per tick, 255 ticks = 4.08 s static volatile uint16_t ticks_since_last_event = 0; @@ -59,7 +54,7 @@ static volatile uint16_t ticks_since_last_event = 0; * Bit 5: 1 for a "hold" event, 0 otherwise. * Bit 6: 1 for a "timeout" event, 0 otherwise. * If bit 7 is 0: - * Not yet defined. + * Sort of ad-hoc, shown in #defines below. */ // event masks / bits @@ -73,6 +68,9 @@ static volatile uint16_t ticks_since_last_event = 0; #define B_FLAGS 0b11110000 // Event types +#define EV_none 0 + +// Events which aren't button presses #define EV_debug (B_SYSTEM|0b01111111) #define EV_enter_state (B_SYSTEM|0b00001000) #define EV_leave_state (B_SYSTEM|0b00001001) @@ -89,7 +87,7 @@ static volatile uint16_t ticks_since_last_event = 0; #define EV_temperature_low (B_SYSTEM|0b00000110) #endif -#define EV_none 0 +// Button press events // shouldn't normally happen, but UI might reset event while button is down // so a release with no recorded prior hold could be possible @@ -202,9 +200,6 @@ static volatile uint16_t ticks_since_last_event = 0; #define EV_15clicks EV_click15_complete -#define events_match(a,b) (a == b) -// return 1 if (a == b), 0 otherwise -#define compare_event_sequences(a,b) (a == b) void empty_event_sequence(); uint8_t push_event(uint8_t ev_type); diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index 3606c67..d5bbdb9 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -64,7 +64,9 @@ ISR(WDT_vect) { // handle standby mode specially if (go_to_standby) { // emit a halfsleep tick, and process it - emit(EV_sleep_tick, sleep_counter++); + emit(EV_sleep_tick, sleep_counter); + // wrap around from 65535 to 32768, not 0 + sleep_counter = (sleep_counter + 1) | (sleep_counter & 0x8000); process_emissions(); return; } -- cgit v1.2.3 From 699a304bdaf67b89b1f7657f15071aeefbebd46b Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 11 Nov 2018 16:01:40 -0700 Subject: Updated the documentation to reflect recent changes to the event system. --- spaghetti-monster/spaghetti-monster.txt | 103 ++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 39 deletions(-) diff --git a/spaghetti-monster/spaghetti-monster.txt b/spaghetti-monster/spaghetti-monster.txt index 0401224..9e051f1 100644 --- a/spaghetti-monster/spaghetti-monster.txt +++ b/spaghetti-monster/spaghetti-monster.txt @@ -112,6 +112,11 @@ Event types: entering the state. When 'arg' exceeds 65535, it wraps around to 32768. + - EV_sleep_tick: This happens every 0.5s during standby, if + enabled at compile time. The 'arg' is the number of ticks since + entering the state. When 'arg' exceeds 65535, it wraps around + to 32768. + LVP and thermal regulation: - EV_voltage_low: Sent whenever the input power drops below the @@ -130,57 +135,81 @@ Event types: Button presses: - - EV_1click: The user clicked the e-switch, released it, and - enough time passed that no more clicks were detected. + Button events can be referred to either by pre-defined symbols, or + by teasing out the flags manually. The structure of a button + event is as follows: + + - Bit 7: 1 for button events, 0 otherwise. + + - Bit 6: 1 for a "timeout" event (signals the end of a + sequence), or 0 otherwise. + + - Bit 5: 1 for a "hold" event, 0 otherwise. This flag is only + necessary because, without it, it would be impossible to + distinguish between "click, click, timeout" and "click, hold, + release". - - EV_2clicks: The user clicked and released the e-switch twice, then - enough time passed that no more clicks were detected. + - Bit 4: 1 if button is currently pressed, 0 otherwise. Button + release events look just like button press events, except this + is not set. - - EV_3clicks: The user clicked and released the e-switch three - times, then enough time passed that no more clicks were detected. + - Bits 0,1,2,3: Counter for how many clicks there have been. + The first click is 1, second is 2, and it goes up to 15 clicks + in a row. Clicks after 15 are coded as 15. - - EV_4clicks: The user clicked and released the e-switch four times, - then enough time passed that no more clicks were detected. + The pre-defined button event symbols are like the following: - - EV_click1_hold: The user pressed the button and is still holding - it. The 'arg' indicates how many clock ticks since the "hold" - state started. + - EV_click1_press: The user pressed the button, but no time has + passed since then. - - EV_click1_hold_release: The user pressed the button, held it for a - while, and then released it. No timeout is attempted after this. + - EV_click1_release: The user pressed and released the button, + but no time has passed since then. - - EV_click2_hold: The user clicked once, then pressed the button and - is still holding it. The 'arg' indicates how many clock ticks - since the "hold" state started. + - EV_click1_complete: The user clicked the e-switch, released + it, and enough time passed that no more clicks were detected. + (a.k.a. EV_1click) - - EV_click2_hold_release: The user clicked once, then pressed the - button, held it for a while, and released it. No timeout is - attempted after this. + - EV_click1_hold: The user pressed the button, and continued + holding it long enough to count as a "hold" event. This event + is sent once per timer tick as long as the button is held, and + the 'arg' value indicates how many timer ticks since the + button state went from 'press' to 'hold'. - - EV_click1_press: The user pressed the button and it's still down. - No time has yet passed. + - EV_click1_hold_release: The button was released at the end of + a "hold" event. This is the end of the input sequence, + because no timeout period is used after a hold. - - EV_click1_release: The user quickly pressed and released the - button. The click timeout has not yet expired, so they might - still click again. + It's worth noting that a "hold" event can only happen at the + end of an input sequence, and the sequence will reset to empty + after the hold is released. - - EV_click2_press: The user pressed the button, released it, pressed - again, and it's still down. No time has yet passed since then. + If the user pressed the button more than once, events follow the + same pattern. These are the same as above, except with a full + short-press and release first. - - EV_click2_release: The quickly pressed and released the button - twice. The click timeout has not yet expired, so they might still - click again. + - EV_click2_press + - EV_click2_release + - EV_click2_complete (a.k.a. EV_2clicks) + - EV_click2_hold + - EV_click2_hold_release + + Each of the above patterns continues up to 15 clicks. + + To match entire categories of events, use the bitmasks provided. + For example, to match button events where the button is down or + the button is up, the code would look like this: + + if ((event & (B_CLICK | B_PRESS)) == (B_CLICK | B_PRESS)) { + // button is down (can be a press event or a hold event) + } + else if ((event & (B_CLICK | B_PRESS)) == (B_CLICK)) { + // button was just released + } In theory, you could also define your own arbitrary event types, and emit() them as necessary, and handle them in State functions the same as any other event. - One thing to note if you create your own Event types: The copy which - gets sent to States must be in the 'event_sequences' array, meaning - the State gets a const PROGMEM version of the Event. It cannot simply - send the dynamic 'current_event' object, because it has probably - already changed by the time the callback happens. - Cooperative multitasking: @@ -287,10 +316,6 @@ Useful #defines: becomes a "click" event? Basically, the maximum time between clicks in a double-click or triple-click. - - MAX_CLICKS N: Convenience define to limit the size of the - recognized Event arrays. Click sequences longer than N won't be - recognized or sent to State functions. - - USE_BATTCHECK: Enable the battcheck function. Also define one of the following to select a display style: -- cgit v1.2.3 From 453199bfab1b9c431ce07b5b32aabdd115dcd6e6 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 11 Nov 2018 16:03:07 -0700 Subject: Updated most of the UIs to use the new event API. --- spaghetti-monster/baton/baton.c | 12 +++--- spaghetti-monster/darkhorse/darkhorse.c | 28 +++++++------- spaghetti-monster/meteor/meteor.c | 62 +++++++++++++++---------------- spaghetti-monster/momentary/momentary.c | 2 +- spaghetti-monster/ramping-ui/ramping-ui.c | 20 +++++----- spaghetti-monster/werner/werner.c | 33 ++++++++-------- 6 files changed, 78 insertions(+), 79 deletions(-) diff --git a/spaghetti-monster/baton/baton.c b/spaghetti-monster/baton/baton.c index d4725ef..d138297 100644 --- a/spaghetti-monster/baton/baton.c +++ b/spaghetti-monster/baton/baton.c @@ -24,9 +24,9 @@ #include "spaghetti-monster.h" // FSM states -uint8_t off_state(EventPtr event, uint16_t arg); -uint8_t steady_state(EventPtr event, uint16_t arg); -uint8_t lockout_state(EventPtr event, uint16_t arg); +uint8_t off_state(Event event, uint16_t arg); +uint8_t steady_state(Event event, uint16_t arg); +uint8_t lockout_state(Event event, uint16_t arg); // brightness control uint8_t memorized_level = 1; @@ -47,7 +47,7 @@ void set_level(uint8_t lvl) { PWM2_LVL = pwm2_levels[lvl]; } -uint8_t off_state(EventPtr event, uint16_t arg) { +uint8_t off_state(Event event, uint16_t arg) { // turn emitter off when entering state if (event == EV_enter_state) { go_to_standby = 1; // sleep while off (lower power use) @@ -86,7 +86,7 @@ uint8_t off_state(EventPtr event, uint16_t arg) { return EVENT_NOT_HANDLED; } -uint8_t steady_state(EventPtr event, uint16_t arg) { +uint8_t steady_state(Event event, uint16_t arg) { // turn LED on when we first enter the mode if (event == EV_enter_state) { // remember this level, unless it's moon or turbo @@ -146,7 +146,7 @@ uint8_t steady_state(EventPtr event, uint16_t arg) { return EVENT_NOT_HANDLED; } -uint8_t lockout_state(EventPtr event, uint16_t arg) { +uint8_t lockout_state(Event event, uint16_t arg) { // stay asleep while locked if (event == EV_tick) { PWM1_LVL = 0; PWM2_LVL = 0; // make sure emitters are off diff --git a/spaghetti-monster/darkhorse/darkhorse.c b/spaghetti-monster/darkhorse/darkhorse.c index 97053b5..d76afc2 100644 --- a/spaghetti-monster/darkhorse/darkhorse.c +++ b/spaghetti-monster/darkhorse/darkhorse.c @@ -32,16 +32,16 @@ #include "spaghetti-monster.h" // FSM states -uint8_t off_state(EventPtr event, uint16_t arg); -uint8_t low_mode_state(EventPtr event, uint16_t arg); -uint8_t med_mode_state(EventPtr event, uint16_t arg); -uint8_t hi_mode_state(EventPtr event, uint16_t arg); -uint8_t strobe_beacon_state(EventPtr event, uint16_t arg); +uint8_t off_state(Event event, uint16_t arg); +uint8_t low_mode_state(Event event, uint16_t arg); +uint8_t med_mode_state(Event event, uint16_t arg); +uint8_t hi_mode_state(Event event, uint16_t arg); +uint8_t strobe_beacon_state(Event event, uint16_t arg); #ifdef USE_BATTCHECK -uint8_t battcheck_state(EventPtr event, uint16_t arg); +uint8_t battcheck_state(Event event, uint16_t arg); #endif // Not a FSM state, just handles stuff common to all low/med/hi states -uint8_t any_mode_state(EventPtr event, uint16_t arg, uint8_t *primary, uint8_t *secondary, uint8_t *modes); +uint8_t any_mode_state(Event event, uint16_t arg, uint8_t *primary, uint8_t *secondary, uint8_t *modes); void load_config(); void save_config(); @@ -89,7 +89,7 @@ inline void set_med_mode() { set_any_mode(M1, M2, med_modes); } inline void set_hi_mode() { set_any_mode(H1, H2, hi_modes); } -uint8_t off_state(EventPtr event, uint16_t arg) { +uint8_t off_state(Event event, uint16_t arg) { // turn emitter off when entering state if (event == EV_enter_state) { set_level(0); @@ -163,7 +163,7 @@ uint8_t off_state(EventPtr event, uint16_t arg) { } -uint8_t any_mode_state(EventPtr event, uint16_t arg, uint8_t *primary, uint8_t *secondary, uint8_t *modes) { +uint8_t any_mode_state(Event event, uint16_t arg, uint8_t *primary, uint8_t *secondary, uint8_t *modes) { // turn on LED when entering the mode if (event == EV_enter_state) { set_any_mode(*primary, *secondary, modes); @@ -236,27 +236,27 @@ uint8_t any_mode_state(EventPtr event, uint16_t arg, uint8_t *primary, uint8_t * return EVENT_NOT_HANDLED; } -uint8_t low_mode_state(EventPtr event, uint16_t arg) { +uint8_t low_mode_state(Event event, uint16_t arg) { return any_mode_state(event, arg, &L1, &L2, low_modes); } -uint8_t med_mode_state(EventPtr event, uint16_t arg) { +uint8_t med_mode_state(Event event, uint16_t arg) { return any_mode_state(event, arg, &M1, &M2, med_modes); } -uint8_t hi_mode_state(EventPtr event, uint16_t arg) { +uint8_t hi_mode_state(Event event, uint16_t arg) { return any_mode_state(event, arg, &H1, &H2, hi_modes); } #ifdef USE_BATTCHECK -uint8_t battcheck_state(EventPtr event, uint16_t arg) { +uint8_t battcheck_state(Event event, uint16_t arg) { return EVENT_NOT_HANDLED; } #endif -uint8_t strobe_beacon_state(EventPtr event, uint16_t arg) { +uint8_t strobe_beacon_state(Event event, uint16_t arg) { // 1 click: off if (event == EV_1click) { set_state(off_state, 0); diff --git a/spaghetti-monster/meteor/meteor.c b/spaghetti-monster/meteor/meteor.c index b2467d7..a50b034 100644 --- a/spaghetti-monster/meteor/meteor.c +++ b/spaghetti-monster/meteor/meteor.c @@ -1,5 +1,6 @@ /* * Meteor: Meteor M43 clone UI for SpaghettiMonster. + * (in progress, not really in a usable state yet) * * Copyright (C) 2017 Selene ToyKeeper * @@ -29,26 +30,25 @@ #define DONT_DELAY_AFTER_BATTCHECK //#define USE_EEPROM //#define EEPROM_BYTES 5 -#define MAX_CLICKS 11 #include "spaghetti-monster.h" // FSM states -uint8_t base_off_state(EventPtr event, uint16_t arg); -uint8_t ui1_off_state(EventPtr event, uint16_t arg); -uint8_t ui2_off_state(EventPtr event, uint16_t arg); -uint8_t ui3_off_state(EventPtr event, uint16_t arg); -uint8_t base_on_state(EventPtr event, uint16_t arg, uint8_t *mode, uint8_t *group); -uint8_t ui1_on_state(EventPtr event, uint16_t arg); -uint8_t ui2_on_state(EventPtr event, uint16_t arg); -uint8_t ui3_on_state(EventPtr event, uint16_t arg); -uint8_t beacon_state(EventPtr event, uint16_t arg); -uint8_t battcheck_state(EventPtr event, uint16_t arg); -uint8_t strobe_state(EventPtr event, uint16_t arg); -uint8_t biking_state(EventPtr event, uint16_t arg); -uint8_t lockout_state(EventPtr event, uint16_t arg); -uint8_t momentary_state(EventPtr event, uint16_t arg); +uint8_t base_off_state(Event event, uint16_t arg); +uint8_t ui1_off_state(Event event, uint16_t arg); +uint8_t ui2_off_state(Event event, uint16_t arg); +uint8_t ui3_off_state(Event event, uint16_t arg); +uint8_t base_on_state(Event event, uint16_t arg, uint8_t *mode, uint8_t *group); +uint8_t ui1_on_state(Event event, uint16_t arg); +uint8_t ui2_on_state(Event event, uint16_t arg); +uint8_t ui3_on_state(Event event, uint16_t arg); +uint8_t beacon_state(Event event, uint16_t arg); +uint8_t battcheck_state(Event event, uint16_t arg); +uint8_t strobe_state(Event event, uint16_t arg); +uint8_t biking_state(Event event, uint16_t arg); +uint8_t lockout_state(Event event, uint16_t arg); +uint8_t momentary_state(Event event, uint16_t arg); // Not a FSM state, just handles stuff common to all low/med/hi states -uint8_t any_mode_state(EventPtr event, uint16_t arg, uint8_t *primary, uint8_t *secondary, uint8_t *modes); +uint8_t any_mode_state(Event event, uint16_t arg, uint8_t *primary, uint8_t *secondary, uint8_t *modes); #ifdef USE_EEPROM void load_config(); @@ -99,7 +99,7 @@ void blink_fast() { set_level(0); } -uint8_t base_off_state(EventPtr event, uint16_t arg) { +uint8_t base_off_state(Event event, uint16_t arg) { // turn emitter off when entering state if (event == EV_enter_state) { set_level(0); @@ -154,7 +154,7 @@ uint8_t base_off_state(EventPtr event, uint16_t arg) { return EVENT_NOT_HANDLED; } -uint8_t ui1_off_state(EventPtr event, uint16_t arg) { +uint8_t ui1_off_state(Event event, uint16_t arg) { UI = 1; if (event == EV_enter_state) { return EVENT_HANDLED; @@ -187,7 +187,7 @@ uint8_t ui1_off_state(EventPtr event, uint16_t arg) { return base_off_state(event, arg); } -uint8_t ui2_off_state(EventPtr event, uint16_t arg) { +uint8_t ui2_off_state(Event event, uint16_t arg) { UI = 2; if (event == EV_enter_state) { return EVENT_HANDLED; @@ -220,7 +220,7 @@ uint8_t ui2_off_state(EventPtr event, uint16_t arg) { return base_off_state(event, arg); } -uint8_t ui3_off_state(EventPtr event, uint16_t arg) { +uint8_t ui3_off_state(Event event, uint16_t arg) { UI = 3; if (event == EV_enter_state) { return EVENT_HANDLED; @@ -259,7 +259,7 @@ uint8_t ui3_off_state(EventPtr event, uint16_t arg) { return base_off_state(event, arg); } -uint8_t base_on_state(EventPtr event, uint16_t arg, uint8_t *mode, uint8_t *group) { +uint8_t base_on_state(Event event, uint16_t arg, uint8_t *mode, uint8_t *group) { // 1 click: off if (event == EV_1click) { set_state(base_off_state, 0); @@ -289,7 +289,7 @@ uint8_t base_on_state(EventPtr event, uint16_t arg, uint8_t *mode, uint8_t *grou return EVENT_NOT_HANDLED; } -uint8_t ui1_on_state(EventPtr event, uint16_t arg) { +uint8_t ui1_on_state(Event event, uint16_t arg) { // turn on LED when entering the mode static uint8_t *mode = &UI1_mode1; static uint8_t *group = UI1_group1; @@ -328,7 +328,7 @@ uint8_t ui1_on_state(EventPtr event, uint16_t arg) { return base_on_state(event, arg, mode, group); } -uint8_t ui2_on_state(EventPtr event, uint16_t arg) { +uint8_t ui2_on_state(Event event, uint16_t arg) { // turn on LED when entering the mode static uint8_t *mode = &UI2_mode1; static uint8_t *group = UI2_group1; @@ -377,7 +377,7 @@ uint8_t ui2_on_state(EventPtr event, uint16_t arg) { return base_on_state(event, arg, mode, group); } -uint8_t ui3_on_state(EventPtr event, uint16_t arg) { +uint8_t ui3_on_state(Event event, uint16_t arg) { // turn on LED when entering the mode static uint8_t *mode = &UI3_mode1; if (event == EV_enter_state) { @@ -424,7 +424,7 @@ uint8_t ui3_on_state(EventPtr event, uint16_t arg) { } -uint8_t blinky_base_state(EventPtr event, uint16_t arg) { +uint8_t blinky_base_state(Event event, uint16_t arg) { // 1 click: off if (event == EV_1click) { set_state(base_off_state, 0); @@ -433,27 +433,27 @@ uint8_t blinky_base_state(EventPtr event, uint16_t arg) { return EVENT_NOT_HANDLED; } -uint8_t beacon_state(EventPtr event, uint16_t arg) { +uint8_t beacon_state(Event event, uint16_t arg) { return blinky_base_state(event, arg); } -uint8_t battcheck_state(EventPtr event, uint16_t arg) { +uint8_t battcheck_state(Event event, uint16_t arg) { return EVENT_NOT_HANDLED; } -uint8_t strobe_state(EventPtr event, uint16_t arg) { +uint8_t strobe_state(Event event, uint16_t arg) { return blinky_base_state(event, arg); } -uint8_t biking_state(EventPtr event, uint16_t arg) { +uint8_t biking_state(Event event, uint16_t arg) { return blinky_base_state(event, arg); } -uint8_t lockout_state(EventPtr event, uint16_t arg) { +uint8_t lockout_state(Event event, uint16_t arg) { return blinky_base_state(event, arg); } -uint8_t momentary_state(EventPtr event, uint16_t arg) { +uint8_t momentary_state(Event event, uint16_t arg) { return blinky_base_state(event, arg); } diff --git a/spaghetti-monster/momentary/momentary.c b/spaghetti-monster/momentary/momentary.c index d4ac1db..0372b3d 100644 --- a/spaghetti-monster/momentary/momentary.c +++ b/spaghetti-monster/momentary/momentary.c @@ -40,7 +40,7 @@ void light_off() { PWM2_LVL = 0; } -uint8_t momentary_state(EventPtr event, uint16_t arg) { +uint8_t momentary_state(Event event, uint16_t arg) { if (event == EV_click1_press) { brightness = 255; diff --git a/spaghetti-monster/ramping-ui/ramping-ui.c b/spaghetti-monster/ramping-ui/ramping-ui.c index e6f571d..234cdf4 100644 --- a/spaghetti-monster/ramping-ui/ramping-ui.c +++ b/spaghetti-monster/ramping-ui/ramping-ui.c @@ -31,12 +31,12 @@ #include "spaghetti-monster.h" // FSM states -uint8_t off_state(EventPtr event, uint16_t arg); -uint8_t steady_state(EventPtr event, uint16_t arg); -uint8_t strobe_state(EventPtr event, uint16_t arg); +uint8_t off_state(Event event, uint16_t arg); +uint8_t steady_state(Event event, uint16_t arg); +uint8_t strobe_state(Event event, uint16_t arg); #ifdef USE_BATTCHECK -uint8_t battcheck_state(EventPtr event, uint16_t arg); -uint8_t tempcheck_state(EventPtr event, uint16_t arg); +uint8_t battcheck_state(Event event, uint16_t arg); +uint8_t tempcheck_state(Event event, uint16_t arg); #endif // brightness control @@ -54,7 +54,7 @@ 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) { +uint8_t off_state(Event event, uint16_t arg) { // turn emitter off when entering state if (event == EV_enter_state) { set_level(0); @@ -121,7 +121,7 @@ uint8_t off_state(EventPtr event, uint16_t arg) { } -uint8_t steady_state(EventPtr event, uint16_t arg) { +uint8_t steady_state(Event event, uint16_t arg) { // turn LED on when we first enter the mode if (event == EV_enter_state) { // remember this level, unless it's moon or turbo @@ -243,7 +243,7 @@ uint8_t steady_state(EventPtr event, uint16_t arg) { } -uint8_t strobe_state(EventPtr event, uint16_t arg) { +uint8_t strobe_state(Event event, uint16_t arg) { if (event == EV_enter_state) { return MISCHIEF_MANAGED; } @@ -281,7 +281,7 @@ uint8_t strobe_state(EventPtr event, uint16_t arg) { #ifdef USE_BATTCHECK -uint8_t battcheck_state(EventPtr event, uint16_t arg) { +uint8_t battcheck_state(Event event, uint16_t arg) { // 1 click: off if (event == EV_1click) { set_state(off_state, 0); @@ -295,7 +295,7 @@ uint8_t battcheck_state(EventPtr event, uint16_t arg) { return EVENT_NOT_HANDLED; } -uint8_t tempcheck_state(EventPtr event, uint16_t arg) { +uint8_t tempcheck_state(Event event, uint16_t arg) { // 1 click: off if (event == EV_1click) { set_state(off_state, 0); diff --git a/spaghetti-monster/werner/werner.c b/spaghetti-monster/werner/werner.c index 3c55d98..b6cdf12 100644 --- a/spaghetti-monster/werner/werner.c +++ b/spaghetti-monster/werner/werner.c @@ -73,7 +73,6 @@ #define USE_RAMPING #define RAMP_LENGTH 150 // default, if not overridden in a driver cfg file #define USE_BATTCHECK -#define MAX_CLICKS 4 #define USE_IDLE_MODE // reduce power use while awake and no tasks are pending #define USE_DYNAMIC_UNDERCLOCKING // cut clock speed at very low modes for better efficiency @@ -92,26 +91,26 @@ // FSM states -uint8_t off_state(EventPtr event, uint16_t arg); +uint8_t off_state(Event event, uint16_t arg); // simple numeric entry config menu -uint8_t config_state_base(EventPtr event, uint16_t arg, +uint8_t config_state_base(Event event, uint16_t arg, uint8_t num_config_steps, void (*savefunc)()); #define MAX_CONFIG_VALUES 3 uint8_t config_state_values[MAX_CONFIG_VALUES]; // ramping mode and its related config mode -uint8_t steady_state(EventPtr event, uint16_t arg); -uint8_t ramp_config_state(EventPtr event, uint16_t arg); +uint8_t steady_state(Event event, uint16_t arg); +uint8_t ramp_config_state(Event event, uint16_t arg); #ifdef USE_BATTCHECK -uint8_t battcheck_state(EventPtr event, uint16_t arg); +uint8_t battcheck_state(Event event, uint16_t arg); #endif #ifdef USE_THERMAL_REGULATION -uint8_t tempcheck_state(EventPtr event, uint16_t arg); -uint8_t thermal_config_state(EventPtr event, uint16_t arg); +uint8_t tempcheck_state(Event event, uint16_t arg); +uint8_t thermal_config_state(Event event, uint16_t arg); #endif // general helper function for config modes -uint8_t number_entry_state(EventPtr event, uint16_t arg); +uint8_t number_entry_state(Event event, uint16_t arg); // return value from number_entry_state() volatile uint8_t number_entry_value; @@ -152,7 +151,7 @@ uint8_t target_level = 0; #endif -uint8_t off_state(EventPtr event, uint16_t arg) { +uint8_t off_state(Event event, uint16_t arg) { // turn emitter off when entering state if ((event == EV_enter_state) || (event == EV_reenter_state)) { // let the user know the power is connected @@ -230,7 +229,7 @@ uint8_t off_state(EventPtr event, uint16_t arg) { } -uint8_t steady_state(EventPtr event, uint16_t arg) { +uint8_t steady_state(Event event, uint16_t arg) { uint8_t mode_min = ramp_discrete_floor; uint8_t mode_max = ramp_discrete_ceil; uint8_t ramp_step_size = ramp_discrete_step_size; @@ -375,7 +374,7 @@ uint8_t steady_state(EventPtr event, uint16_t arg) { #ifdef USE_BATTCHECK -uint8_t battcheck_state(EventPtr event, uint16_t arg) { +uint8_t battcheck_state(Event event, uint16_t arg) { // 1 click: off if (event == EV_1click) { set_state(off_state, 0); @@ -392,7 +391,7 @@ uint8_t battcheck_state(EventPtr event, uint16_t arg) { #endif #ifdef USE_THERMAL_REGULATION -uint8_t tempcheck_state(EventPtr event, uint16_t arg) { +uint8_t tempcheck_state(Event event, uint16_t arg) { // 1 click: off if (event == EV_1click) { set_state(off_state, 0); @@ -415,7 +414,7 @@ uint8_t tempcheck_state(EventPtr event, uint16_t arg) { // ask the user for a sequence of numbers, then save them and return to caller -uint8_t config_state_base(EventPtr event, uint16_t arg, +uint8_t config_state_base(Event event, uint16_t arg, uint8_t num_config_steps, void (*savefunc)()) { static uint8_t config_step; @@ -463,7 +462,7 @@ void ramp_config_save() { if (val) ramp_discrete_steps = val; } -uint8_t ramp_config_state(EventPtr event, uint16_t arg) { +uint8_t ramp_config_state(Event event, uint16_t arg) { uint8_t num_config_steps; num_config_steps = 3; return config_state_base(event, arg, @@ -491,14 +490,14 @@ void thermal_config_save() { if (therm_ceil > MAX_THERM_CEIL) therm_ceil = MAX_THERM_CEIL; } -uint8_t thermal_config_state(EventPtr event, uint16_t arg) { +uint8_t thermal_config_state(Event event, uint16_t arg) { return config_state_base(event, arg, 2, thermal_config_save); } #endif -uint8_t number_entry_state(EventPtr event, uint16_t arg) { +uint8_t number_entry_state(Event event, uint16_t arg) { static uint8_t value; static uint8_t blinks_left; static uint8_t entry_step; -- cgit v1.2.3 From 7f199d9e52a73393530b296e5ff1e0fcaf0140bf Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 11 Nov 2018 16:03:39 -0700 Subject: Added a README for the Werner UI. Fixed its build script. --- spaghetti-monster/werner/README | 56 +++++++++++++++++++++++++++++++++++ spaghetti-monster/werner/build-all.sh | 2 +- 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 spaghetti-monster/werner/README diff --git a/spaghetti-monster/werner/README b/spaghetti-monster/werner/README new file mode 100644 index 0000000..5fe392d --- /dev/null +++ b/spaghetti-monster/werner/README @@ -0,0 +1,56 @@ +This is a Werner-style interface for dual-switch lights +(e-switch + clicky switch). What that means is: + +While the clicky switch is off: + + - Click the clicky switch: Turn on, at the last-used level. The clicky + switch works as a momentary mode. + + - Click the clicky switch while holding the e-switch: Go into sort of a + utility mode. + +While on, in a normal steady mode: + + - Click the clicky switch: Turn off. + + - Click the e-switch: Brighter. One step per click. + + - Hold the e-switch: Dimmer. Keep holding to go down multiple steps. + +While in standby, in utility mode: + + - Click the e-switch: Turn on. + + - Hold the e-switch: Turn on at lowest level. + + - Double-click the e-switch: Turn on at highest level. + + - Triple-click the e-switch: Battery check mode. + + - Quad-click the e-switch: Ramp config mode. + +While in battery check mode: + + - Click either switch: Turn off. + + - Double-click the e-switch: Go to temperature check mode. + +While in temperature check mode: + + - Click either switch: Turn off. + + - Double-click the e-switch: Go to battery check mode. + + - Quad-click the e-switch: Go to thermal config mode. + +Ramp config mode and thermal config mode work the same as in Anduril or +RampingIOS V3. The options are: + + - Ramp config mode: + 1. Floor level. + 2. Ceiling level. + 3. Number of steps. + + - Thermal config mode: + 1. Calibrate sensor by entering current temperature in C. + 2. Set temperature limit to 30 C + N clicks. diff --git a/spaghetti-monster/werner/build-all.sh b/spaghetti-monster/werner/build-all.sh index 944b31d..43879bb 100755 --- a/spaghetti-monster/werner/build-all.sh +++ b/spaghetti-monster/werner/build-all.sh @@ -14,6 +14,6 @@ for TARGET in \ FW3A \ ; do echo "===== $TARGET =====" - ../../../bin/build-85.sh "$UI" "-DFSM_${TARGET}_DRIVER" + ../../../bin/build.sh 85 "$UI" "-DFSM_${TARGET}_DRIVER" mv -f "$UI".hex "$UI".$TARGET.hex done -- cgit v1.2.3 From 741b29e7b31ca460674a5cc11ac00628c8bf8e1b Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 11 Nov 2018 16:04:43 -0700 Subject: Updated RampingIOS V3 to new event API. Applied recent changes from Anduril too. --- spaghetti-monster/anduril/anduril.c | 9 --- spaghetti-monster/rampingios/rampingiosv3.c | 109 ++++++++++++++-------------- 2 files changed, 56 insertions(+), 62 deletions(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 4c3ccd7..ec16497 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -146,15 +146,6 @@ #define MAX_BIKING_LEVEL 120 // should be 127 or less #define USE_BATTCHECK -// determine the highest number of clicks to handle -#ifdef USE_INDICATOR_LED -#define MAX_CLICKS 7 -#elif defined(USE_MUGGLE_MODE) -#define MAX_CLICKS 6 -#else -#define MAX_CLICKS 5 -#endif - #if defined(USE_MUGGLE_MODE) #ifndef MUGGLE_FLOOR #define MUGGLE_FLOOR 22 diff --git a/spaghetti-monster/rampingios/rampingiosv3.c b/spaghetti-monster/rampingios/rampingiosv3.c index 2aeeddf..4142121 100644 --- a/spaghetti-monster/rampingios/rampingiosv3.c +++ b/spaghetti-monster/rampingios/rampingiosv3.c @@ -112,9 +112,10 @@ /********* Configure SpaghettiMonster *********/ #define USE_DELAY_ZERO #define USE_RAMPING +#ifndef RAMP_LENGTH #define RAMP_LENGTH 150 // default, if not overridden in a driver cfg file +#endif #define USE_BATTCHECK -#define MAX_CLICKS 10 #define USE_IDLE_MODE // reduce power use while awake and no tasks are pending #define USE_DYNAMIC_UNDERCLOCKING // cut clock speed at very low modes for better efficiency @@ -141,34 +142,34 @@ // FSM states -uint8_t off_state(EventPtr event, uint16_t arg); +uint8_t off_state(Event event, uint16_t arg); // simple numeric entry config menu -uint8_t config_state_base(EventPtr event, uint16_t arg, +uint8_t config_state_base(Event event, uint16_t arg, uint8_t num_config_steps, void (*savefunc)()); #define MAX_CONFIG_VALUES 3 uint8_t config_state_values[MAX_CONFIG_VALUES]; // ramping mode and its related config mode -uint8_t steady_state(EventPtr event, uint16_t arg); -uint8_t ramp_config_state(EventPtr event, uint16_t arg); +uint8_t steady_state(Event event, uint16_t arg); +uint8_t ramp_config_state(Event event, uint16_t arg); #ifdef USE_BATTCHECK -uint8_t battcheck_state(EventPtr event, uint16_t arg); +uint8_t battcheck_state(Event event, uint16_t arg); #endif #ifdef USE_THERMAL_REGULATION -uint8_t tempcheck_state(EventPtr event, uint16_t arg); -uint8_t thermal_config_state(EventPtr event, uint16_t arg); +uint8_t tempcheck_state(Event event, uint16_t arg); +uint8_t thermal_config_state(Event event, uint16_t arg); #endif // beacon mode and its related config mode -uint8_t beacon_state(EventPtr event, uint16_t arg); -uint8_t beacon_config_state(EventPtr event, uint16_t arg); +uint8_t beacon_state(Event event, uint16_t arg); +uint8_t beacon_config_state(Event event, uint16_t arg); // soft lockout #define MOON_DURING_LOCKOUT_MODE -uint8_t lockout_state(EventPtr event, uint16_t arg); +uint8_t lockout_state(Event event, uint16_t arg); // momentary / signalling mode -uint8_t momentary_state(EventPtr event, uint16_t arg); +uint8_t momentary_state(Event event, uint16_t arg); // general helper function for config modes -uint8_t number_entry_state(EventPtr event, uint16_t arg); +uint8_t number_entry_state(Event event, uint16_t arg); // return value from number_entry_state() volatile uint8_t number_entry_value; @@ -177,7 +178,7 @@ void blink_confirm(uint8_t num); void indicator_blink(uint8_t arg); #endif #ifdef USE_INDICATOR_LED -uint8_t auxled_next_state(EventPtr event, uint16_t arg); +uint8_t auxled_next_state(Event event, uint16_t arg); #endif // remember stuff even after battery was changed @@ -246,7 +247,7 @@ uint8_t target_level = 0; volatile uint8_t beacon_seconds = 2; -uint8_t off_state(EventPtr event, uint16_t arg) { +uint8_t off_state(Event event, uint16_t arg) { // turn emitter off when entering state if (event == EV_enter_state) { set_level(0); @@ -371,7 +372,7 @@ uint8_t off_state(EventPtr event, uint16_t arg) { } -uint8_t steady_state(EventPtr event, uint16_t arg) { +uint8_t steady_state(Event event, uint16_t arg) { uint8_t mode_min = ramp_smooth_floor; uint8_t mode_max = ramp_smooth_ceil; uint8_t ramp_step_size = 1; @@ -677,7 +678,7 @@ uint8_t steady_state(EventPtr event, uint16_t arg) { #ifdef USE_BATTCHECK -uint8_t battcheck_state(EventPtr event, uint16_t arg) { +uint8_t battcheck_state(Event event, uint16_t arg) { // 1 click: off if (event == EV_1click) { set_state(off_state, 0); @@ -694,7 +695,7 @@ uint8_t battcheck_state(EventPtr event, uint16_t arg) { #ifdef USE_THERMAL_REGULATION -uint8_t tempcheck_state(EventPtr event, uint16_t arg) { +uint8_t tempcheck_state(Event event, uint16_t arg) { // 1 click: off if (event == EV_1click) { set_state(off_state, 0); @@ -710,7 +711,7 @@ uint8_t tempcheck_state(EventPtr event, uint16_t arg) { #endif -uint8_t beacon_state(EventPtr event, uint16_t arg) { +uint8_t beacon_state(Event event, uint16_t arg) { // 1 click: off if (event == EV_1click) { set_state(off_state, 0); @@ -727,29 +728,24 @@ uint8_t beacon_state(EventPtr event, uint16_t arg) { } -uint8_t lockout_state(EventPtr event, uint16_t arg) { +uint8_t lockout_state(Event event, uint16_t arg) { #ifdef MOON_DURING_LOCKOUT_MODE // momentary(ish) moon mode during lockout - // not all presses will be counted; - // it depends on what is in the master event_sequences table - uint8_t last = 0; - for(uint8_t i=0; pgm_read_byte(event + i) && (i TICKS_PER_SECOND*15) { // sleep after 15 seconds go_to_standby = 1; // sleep while light is off + // TODO: lighted button should use lockout config? } return MISCHIEF_MANAGED; } @@ -863,7 +866,7 @@ uint8_t momentary_state(EventPtr event, uint16_t arg) { // ask the user for a sequence of numbers, then save them and return to caller -uint8_t config_state_base(EventPtr event, uint16_t arg, +uint8_t config_state_base(Event event, uint16_t arg, uint8_t num_config_steps, void (*savefunc)()) { static uint8_t config_step; @@ -922,7 +925,7 @@ void ramp_config_save() { } } -uint8_t ramp_config_state(EventPtr event, uint16_t arg) { +uint8_t ramp_config_state(Event event, uint16_t arg) { uint8_t num_config_steps; num_config_steps = 2 + ramp_style; return config_state_base(event, arg, @@ -950,7 +953,7 @@ void thermal_config_save() { if (therm_ceil > MAX_THERM_CEIL) therm_ceil = MAX_THERM_CEIL; } -uint8_t thermal_config_state(EventPtr event, uint16_t arg) { +uint8_t thermal_config_state(Event event, uint16_t arg) { return config_state_base(event, arg, 2, thermal_config_save); } @@ -965,13 +968,13 @@ void beacon_config_save() { } } -uint8_t beacon_config_state(EventPtr event, uint16_t arg) { +uint8_t beacon_config_state(Event event, uint16_t arg) { return config_state_base(event, arg, 1, beacon_config_save); } -uint8_t number_entry_state(EventPtr event, uint16_t arg) { +uint8_t number_entry_state(Event event, uint16_t arg) { static uint8_t value; static uint8_t blinks_left; static uint8_t entry_step; -- cgit v1.2.3 From ec34acd89d80c5a26c68e873a006f602a2d9e598 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 11 Nov 2018 18:02:40 -0700 Subject: Made event definitions a little cleaner. --- spaghetti-monster/fsm-events.h | 64 +++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/spaghetti-monster/fsm-events.h b/spaghetti-monster/fsm-events.h index 2fd47b6..0ebcfd0 100644 --- a/spaghetti-monster/fsm-events.h +++ b/spaghetti-monster/fsm-events.h @@ -89,115 +89,115 @@ static volatile uint16_t ticks_since_last_event = 0; // Button press events -// shouldn't normally happen, but UI might reset event while button is down -// so a release with no recorded prior hold could be possible +// shouldn't normally happen, but UI might empty_event_sequence() while button +// is down so a release with no recorded prior hold could be possible #define EV_release (B_CLICK|B_RELEASE|0) #define EV_click1_press (B_CLICK|B_PRESS|1) -#define EV_click1_hold (B_CLICK|B_HOLD|B_PRESS|1) -#define EV_click1_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|1) #define EV_click1_release (B_CLICK|B_RELEASE|1) #define EV_click1_complete (B_CLICK|B_TIMEOUT|1) #define EV_1click EV_click1_complete +#define EV_click1_hold (B_CLICK|B_HOLD|B_PRESS|1) +#define EV_click1_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|1) #define EV_hold EV_click1_hold #define EV_click2_press (B_CLICK|B_PRESS|2) -#define EV_click2_hold (B_CLICK|B_HOLD|B_PRESS|2) -#define EV_click2_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|2) #define EV_click2_release (B_CLICK|B_RELEASE|2) #define EV_click2_complete (B_CLICK|B_TIMEOUT|2) #define EV_2clicks EV_click2_complete +#define EV_click2_hold (B_CLICK|B_HOLD|B_PRESS|2) +#define EV_click2_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|2) #define EV_click3_press (B_CLICK|B_PRESS|3) -#define EV_click3_hold (B_CLICK|B_HOLD|B_PRESS|3) -#define EV_click3_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|3) #define EV_click3_release (B_CLICK|B_RELEASE|3) #define EV_click3_complete (B_CLICK|B_TIMEOUT|3) #define EV_3clicks EV_click3_complete +#define EV_click3_hold (B_CLICK|B_HOLD|B_PRESS|3) +#define EV_click3_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|3) #define EV_click4_press (B_CLICK|B_PRESS|4) -#define EV_click4_hold (B_CLICK|B_HOLD|B_PRESS|4) -#define EV_click4_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|4) #define EV_click4_release (B_CLICK|B_RELEASE|4) #define EV_click4_complete (B_CLICK|B_TIMEOUT|4) #define EV_4clicks EV_click4_complete +#define EV_click4_hold (B_CLICK|B_HOLD|B_PRESS|4) +#define EV_click4_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|4) #define EV_click5_press (B_CLICK|B_PRESS|5) -#define EV_click5_hold (B_CLICK|B_HOLD|B_PRESS|5) -#define EV_click5_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|5) #define EV_click5_release (B_CLICK|B_RELEASE|5) #define EV_click5_complete (B_CLICK|B_TIMEOUT|5) #define EV_5clicks EV_click5_complete +#define EV_click5_hold (B_CLICK|B_HOLD|B_PRESS|5) +#define EV_click5_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|5) #define EV_click6_press (B_CLICK|B_PRESS|6) -#define EV_click6_hold (B_CLICK|B_HOLD|B_PRESS|6) -#define EV_click6_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|6) #define EV_click6_release (B_CLICK|B_RELEASE|6) #define EV_click6_complete (B_CLICK|B_TIMEOUT|6) #define EV_6clicks EV_click6_complete +#define EV_click6_hold (B_CLICK|B_HOLD|B_PRESS|6) +#define EV_click6_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|6) #define EV_click7_press (B_CLICK|B_PRESS|7) -#define EV_click7_hold (B_CLICK|B_HOLD|B_PRESS|7) -#define EV_click7_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|7) #define EV_click7_release (B_CLICK|B_RELEASE|7) #define EV_click7_complete (B_CLICK|B_TIMEOUT|7) #define EV_7clicks EV_click7_complete +#define EV_click7_hold (B_CLICK|B_HOLD|B_PRESS|7) +#define EV_click7_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|7) #define EV_click8_press (B_CLICK|B_PRESS|8) -#define EV_click8_hold (B_CLICK|B_HOLD|B_PRESS|8) -#define EV_click8_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|8) #define EV_click8_release (B_CLICK|B_RELEASE|8) #define EV_click8_complete (B_CLICK|B_TIMEOUT|8) #define EV_8clicks EV_click8_complete +#define EV_click8_hold (B_CLICK|B_HOLD|B_PRESS|8) +#define EV_click8_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|8) #define EV_click9_press (B_CLICK|B_PRESS|9) -#define EV_click9_hold (B_CLICK|B_HOLD|B_PRESS|9) -#define EV_click9_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|9) #define EV_click9_release (B_CLICK|B_RELEASE|9) #define EV_click9_complete (B_CLICK|B_TIMEOUT|9) #define EV_9clicks EV_click9_complete +#define EV_click9_hold (B_CLICK|B_HOLD|B_PRESS|9) +#define EV_click9_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|9) #define EV_click10_press (B_CLICK|B_PRESS|10) -#define EV_click10_hold (B_CLICK|B_HOLD|B_PRESS|10) -#define EV_click10_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|10) #define EV_click10_release (B_CLICK|B_RELEASE|10) #define EV_click10_complete (B_CLICK|B_TIMEOUT|10) #define EV_10clicks EV_click10_complete +#define EV_click10_hold (B_CLICK|B_HOLD|B_PRESS|10) +#define EV_click10_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|10) #define EV_click11_press (B_CLICK|B_PRESS|11) -#define EV_click11_hold (B_CLICK|B_HOLD|B_PRESS|11) -#define EV_click11_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|11) #define EV_click11_release (B_CLICK|B_RELEASE|11) #define EV_click11_complete (B_CLICK|B_TIMEOUT|11) #define EV_11clicks EV_click11_complete +#define EV_click11_hold (B_CLICK|B_HOLD|B_PRESS|11) +#define EV_click11_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|11) #define EV_click12_press (B_CLICK|B_PRESS|12) -#define EV_click12_hold (B_CLICK|B_HOLD|B_PRESS|12) -#define EV_click12_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|12) #define EV_click12_release (B_CLICK|B_RELEASE|12) #define EV_click12_complete (B_CLICK|B_TIMEOUT|12) #define EV_12clicks EV_click12_complete +#define EV_click12_hold (B_CLICK|B_HOLD|B_PRESS|12) +#define EV_click12_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|12) #define EV_click13_press (B_CLICK|B_PRESS|13) -#define EV_click13_hold (B_CLICK|B_HOLD|B_PRESS|13) -#define EV_click13_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|13) #define EV_click13_release (B_CLICK|B_RELEASE|13) #define EV_click13_complete (B_CLICK|B_TIMEOUT|13) #define EV_13clicks EV_click13_complete +#define EV_click13_hold (B_CLICK|B_HOLD|B_PRESS|13) +#define EV_click13_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|13) #define EV_click14_press (B_CLICK|B_PRESS|14) -#define EV_click14_hold (B_CLICK|B_HOLD|B_PRESS|14) -#define EV_click14_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|14) #define EV_click14_release (B_CLICK|B_RELEASE|14) #define EV_click14_complete (B_CLICK|B_TIMEOUT|14) #define EV_14clicks EV_click14_complete +#define EV_click14_hold (B_CLICK|B_HOLD|B_PRESS|14) +#define EV_click14_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|14) #define EV_click15_press (B_CLICK|B_PRESS|15) -#define EV_click15_hold (B_CLICK|B_HOLD|B_PRESS|15) -#define EV_click15_hold_release (B_CLICK|B_TIMEOUT|B_HOLD|B_RELEASE|15) #define EV_click15_release (B_CLICK|B_RELEASE|15) #define EV_click15_complete (B_CLICK|B_TIMEOUT|15) #define EV_15clicks EV_click15_complete +#define EV_click15_hold (B_CLICK|B_HOLD|B_PRESS|15) +#define EV_click15_hold_release (B_CLICK|B_HOLD|B_RELEASE|B_TIMEOUT|15) void empty_event_sequence(); -- cgit v1.2.3