aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hwdef-BLF_GT.h16
-rw-r--r--hwdef-BLF_GT_Mini.h6
-rw-r--r--hwdef-BLF_Q8.h13
-rw-r--r--hwdef-Emisar_D4.h16
-rw-r--r--hwdef-FF_PL47.h29
-rw-r--r--hwdef-FF_ROT66.h15
-rw-r--r--hwdef-FW3A.h22
-rw-r--r--spaghetti-monster/anduril/anduril.c144
-rw-r--r--spaghetti-monster/anduril/anduril.txt7
-rwxr-xr-xspaghetti-monster/anduril/build-all.sh1
-rw-r--r--spaghetti-monster/anduril/cfg-blf-gt.h4
-rw-r--r--spaghetti-monster/anduril/cfg-blf-q8.h4
-rw-r--r--spaghetti-monster/anduril/cfg-emisar-d4.h3
-rw-r--r--spaghetti-monster/anduril/cfg-ff-pl47.h24
-rw-r--r--spaghetti-monster/anduril/cfg-ff-rot66.h4
-rw-r--r--spaghetti-monster/anduril/cfg-fw3a.h4
-rw-r--r--spaghetti-monster/anduril/cfg-sofirn-sp36.h34
-rw-r--r--spaghetti-monster/baton/baton-simpler.c194
-rw-r--r--spaghetti-monster/baton/baton.c178
-rw-r--r--spaghetti-monster/baton/baton.txt21
-rw-r--r--spaghetti-monster/darkhorse/darkhorse.c28
-rw-r--r--spaghetti-monster/fsm-events.c95
-rw-r--r--spaghetti-monster/fsm-events.h614
-rw-r--r--spaghetti-monster/fsm-pcint.c4
-rw-r--r--spaghetti-monster/fsm-states.c4
-rw-r--r--spaghetti-monster/fsm-states.h6
-rw-r--r--spaghetti-monster/fsm-wdt.c59
-rw-r--r--spaghetti-monster/meteor/meteor.c62
-rw-r--r--spaghetti-monster/momentary/momentary.c2
-rw-r--r--spaghetti-monster/ramping-ui/ramping-ui.c20
-rw-r--r--spaghetti-monster/rampingios/rampingiosv3.c109
-rw-r--r--spaghetti-monster/spaghetti-monster.txt103
-rw-r--r--spaghetti-monster/werner/README56
-rwxr-xr-xspaghetti-monster/werner/build-all.sh2
-rw-r--r--spaghetti-monster/werner/werner.c33
35 files changed, 765 insertions, 1171 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/anduril.c b/spaghetti-monster/anduril/anduril.c
index 6e33610..ec16497 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
@@ -136,15 +140,19 @@
/********* 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
-#ifdef USE_MUGGLE_MODE
-#define MAX_CLICKS 6
+
+#if defined(USE_MUGGLE_MODE)
+#ifndef MUGGLE_FLOOR
#define MUGGLE_FLOOR 22
+#endif
+#ifndef MUGGLE_CEILING
#define MUGGLE_CEILING (MAX_1x7135+20)
-#else
-#define MAX_CLICKS 5
+#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
@@ -209,45 +217,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;
@@ -370,7 +378,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);
@@ -488,11 +496,29 @@ 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;
}
-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;
@@ -811,7 +837,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;
@@ -1024,7 +1050,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);
@@ -1041,7 +1067,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);
@@ -1062,7 +1088,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);
@@ -1089,7 +1115,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) {
@@ -1128,29 +1154,24 @@ 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<EV_MAX_LEN); i++)
- last = pgm_read_byte(event + i);
- if (arg == 0) { // Only turn on/off when button state changes
- if ((last == A_PRESS) || (last == A_HOLD)) {
- #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 if ((last == A_RELEASE) || (last == A_RELEASE_TIMEOUT)) {
- 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
@@ -1198,6 +1219,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 +1252,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);
@@ -1241,19 +1264,19 @@ uint8_t lockout_state(EventPtr event, uint16_t arg) {
}
-uint8_t momentary_state(EventPtr event, uint16_t arg) {
+uint8_t momentary_state(Event event, uint16_t arg) {
// TODO: momentary strobe here? (for light painting)
- if (event == EV_click1_press) {
+
+ // light up when the button is pressed; go dark otherwise
+ // button is being held
+ if ((event & (B_CLICK | B_PRESS)) == (B_CLICK | B_PRESS)) {
set_level(memorized_level);
- empty_event_sequence(); // don't attempt to parse multiple clicks
return MISCHIEF_MANAGED;
}
-
- else if (event == EV_release) {
+ // button was released
+ else if ((event & (B_CLICK | B_PRESS)) == (B_CLICK)) {
set_level(0);
- empty_event_sequence(); // don't attempt to parse multiple clicks
//go_to_standby = 1; // sleep while light is off
- // TODO: lighted button should use lockout config?
return MISCHIEF_MANAGED;
}
@@ -1265,6 +1288,7 @@ uint8_t momentary_state(EventPtr event, uint16_t arg) {
else if ((event == EV_tick) && (actual_level == 0)) {
if (arg > 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;
}
@@ -1274,7 +1298,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;
@@ -1424,7 +1448,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;
@@ -1483,7 +1507,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,
@@ -1511,7 +1535,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);
}
@@ -1526,13 +1550,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/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).
diff --git a/spaghetti-monster/anduril/build-all.sh b/spaghetti-monster/anduril/build-all.sh
index 68d32fb..34df732 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.sh 85 "$UI" "-DFSM_${TARGET}_DRIVER"
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 d916e06..2e5647d 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)
@@ -25,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
@@ -38,15 +36,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
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
diff --git a/spaghetti-monster/anduril/cfg-sofirn-sp36.h b/spaghetti-monster/anduril/cfg-sofirn-sp36.h
new file mode 100644
index 0000000..f6f7447
--- /dev/null
+++ b/spaghetti-monster/anduril/cfg-sofirn-sp36.h
@@ -0,0 +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"
+
+// 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 130
+
+// be extra-careful at high levels
+// (or not... this host seems to heat up pretty slowly)
+//#ifndef THERM_HARD_TURBO_DROP
+//#define THERM_HARD_TURBO_DROP
+//#endif
+
diff --git a/spaghetti-monster/baton/baton-simpler.c b/spaghetti-monster/baton/baton-simpler.c
deleted file mode 100644
index 96b0ea7..0000000
--- a/spaghetti-monster/baton/baton-simpler.c
+++ /dev/null
@@ -1,194 +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 <http://www.gnu.org/licenses/>.
- */
-
-#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"
-
-// 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;
- }
- // 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;
- }
- // hold: go to lowest level
- else if (event == EV_click1_hold) {
- set_state(steady_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;
- #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, but allow waking long enough to click 4 times
- 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;
- }
- return MISCHIEF_MANAGED;
- }
- // 4 clicks: exit
- 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);
- }
- 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 1266ddd..d138297 100644
--- a/spaghetti-monster/baton/baton.c
+++ b/spaghetti-monster/baton/baton.c
@@ -20,22 +20,13 @@
#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 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;
@@ -44,93 +35,90 @@ 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) {
+uint8_t off_state(Event 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;
+ // 4 clicks: soft lockout
+ else if (event == EV_4clicks) {
+ 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 0;
- }
- return 1;
+ 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
- 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;
- }
- // 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,90 +129,60 @@ 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) {
- 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 0;
- }
- // tick: strobe the emitter
- else if (event == EV_tick) {
- if (frames == 0) {
- PWM1_LVL = 0;
- PWM2_LVL = 255;
- if (between < 3) delay_zero();
- else delay_ms(1);
- PWM2_LVL = 0;
- }
- //frames = (frames + 1) % between;
- frames++;
- if (frames > between) frames = 0;
- return 0;
- }
- // 1 click: off
- else if (event == EV_1click) {
- set_state(off_state, 0);
- return 0;
- }
- // 2 clicks: go back to regular modes
- else if (event == EV_2clicks) {
- set_state(steady_state, memorized_level);
- return 0;
- }
- // hold: change speed
- else if (event == EV_click1_hold) {
- if ((arg % HOLD_TIMEOUT) == 0) {
- between = (between+1)%6;
- frames = 0;
- }
- return 0;
+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
+ // 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 1;
+ return EVENT_NOT_HANDLED;
}
void low_voltage() {
- // "step down" from strobe to level 2
- if (current_state == party_strobe_state) {
- set_state(steady_state, 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
}
- // 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);
- }
- 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() {
+}
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.
+
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/fsm-events.c b/spaghetti-monster/fsm-events.c
index ee7bc97..72216ae 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<EV_MAX_LEN) && (a[i] == pgm_read_byte(b+i)); i++) {
- // end of zero-terminated sequence
- if (a[i] == 0) return 1;
- }
- // if we ever fall out, that means something was different
- // (or the sequence is too long)
- return 0;
-}
-
void empty_event_sequence() {
- for(uint8_t i=0; i<EV_MAX_LEN; i++) current_event[i] = 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:
@@ -49,46 +32,41 @@ void empty_event_sequence() {
uint8_t push_event(uint8_t ev_type) {
ticks_since_last_event = 0; // something happened
- uint8_t i;
- //uint8_t prev_event = 0; // never push the same event twice in a row
- for(i=0; current_event[i] && (i<EV_MAX_LEN); i++) {
- // this doesn't actually seem to be necessary any more...
- //prev_event = current_event[i];
+
+ // only click events are sent to this function
+ current_event |= B_CLICK;
+
+ // handle button presses
+ if (ev_type == B_PRESS) {
+ // set press flag
+ current_event |= B_PRESS;
+ // increase click counter
+ if ((current_event & B_COUNT) < (B_COUNT-1)) {
+ current_event ++;
+ }
+ return 1; // event pushed, even if max clicks already reached
+ // (will just repeat the max over and over)
}
- //if ((i < EV_MAX_LEN) && (prev_event != ev_type)) {
- //if (prev_event != ev_type) {
- if (i < EV_MAX_LEN) {
- current_event[i] = ev_type;
+ // handle button releases
+ else if (ev_type == B_RELEASE) {
+ // clear the press flag
+ 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; }
return 1; // event pushed
- } else {
- // TODO: ... something?
}
- return 0; // no event pushed
-}
-// find and return last action in the current event sequence
-/*
-uint8_t last_event(uint8_t offset) {
- uint8_t i;
- for(i=0; current_event[i] && (i<EV_MAX_LEN); i++);
- if (i == EV_MAX_LEN) return current_event[EV_MAX_LEN-offset];
- else if (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<EV_MAX_LEN); i++);
- return i;
}
-void append_emission(EventPtr event, uint16_t arg) {
+void append_emission(Event event, uint16_t arg) {
uint8_t i;
// find last entry
for(i=0;
- (i<EMISSION_QUEUE_LEN) && (emissions[i].event != NULL);
+ (i<EMISSION_QUEUE_LEN) && (emissions[i].event != EV_none);
i++) { }
// add new entry
if (i < EMISSION_QUEUE_LEN) {
@@ -105,12 +83,12 @@ void delete_first_emission() {
emissions[i].event = emissions[i+1].event;
emissions[i].arg = emissions[i+1].arg;
}
- emissions[i].event = NULL;
+ emissions[i].event = EV_none;
emissions[i].arg = 0;
}
void process_emissions() {
- while (emissions[0].event != NULL) {
+ while (emissions[0].event != EV_none) {
emit_now(emissions[0].event, emissions[0].arg);
delete_first_emission();
}
@@ -202,7 +180,7 @@ uint8_t nice_delay_s() {
*/
// Call stacked callbacks for the given event until one handles it.
-uint8_t emit_now(EventPtr event, uint16_t arg) {
+uint8_t emit_now(Event event, uint16_t arg) {
for(int8_t i=state_stack_len-1; i>=0; i--) {
uint8_t err = state_stack[i](event, arg);
if (! err) return 0;
@@ -210,26 +188,15 @@ 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;
+ 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 0212c2c..0ebcfd0 100644
--- a/spaghetti-monster/fsm-events.h
+++ b/spaghetti-monster/fsm-events.h
@@ -23,10 +23,9 @@
#include <avr/pgmspace.h>
// 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;
@@ -35,12 +34,7 @@ typedef struct Emission {
#define MISCHIEF_MANAGED EVENT_HANDLED
#define MISCHIEF_NOT_MANAGED EVENT_NOT_HANDLED
-#ifndef MAX_CLICKS
-#define MAX_CLICKS 4
-#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,508 +46,174 @@ 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:
+ * Sort of ad-hoc, shown in #defines below.
+ */
+
+// event masks / bits
+#define B_SYSTEM 0b00000000
+#define B_CLICK 0b10000000
+#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_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)
+#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 };
-// 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 };
+
+// Button press events
+
+// 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_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_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
-// 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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)
-// return 1 if (a == b), 0 otherwise
-uint8_t compare_event_sequences(uint8_t *a, const uint8_t *b);
+#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_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();
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);
+uint8_t emit_now(Event event, uint16_t arg);
+void emit(Event event, uint16_t arg);
void emit_current_event(uint16_t arg);
uint8_t nice_delay_ms(uint16_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..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;
}
@@ -76,54 +78,57 @@ 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
- // 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_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 (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);
+ }
+ // has button been down long enough to become a "hold"?
+ else {
+ if (ticks_since_last >= HOLD_TIMEOUT) {
+ //ticks_since_last_event = 0;
+ 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);
+ else if (ticks_since_last >= RELEASE_TIMEOUT) {
+ current_event |= B_TIMEOUT;
+ //ticks_since_last_event = 0;
emit_current_event(0);
empty_event_sequence();
}
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/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<EV_MAX_LEN); i++)
- last = pgm_read_byte(event + i);
- if (arg == 0) { // Only turn on/off when button state changes
- if ((last == A_PRESS) || (last == A_HOLD)) {
- #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 if ((last == A_RELEASE) || (last == A_RELEASE_TIMEOUT)) {
- 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
@@ -789,6 +785,9 @@ uint8_t lockout_state(EventPtr event, uint16_t arg) {
#else
mode = (mode + 1) % 3;
#endif
+ #ifdef INDICATOR_LED_SKIP_LOW
+ if (mode == 1) { mode ++; }
+ #endif
indicator_led_mode = (mode << 2) + (indicator_led_mode & 0x03);
indicator_led(mode);
save_config();
@@ -807,7 +806,7 @@ uint8_t lockout_state(EventPtr event, uint16_t arg) {
#ifdef USE_INDICATOR_LED
-uint8_t auxled_next_state(EventPtr event, uint16_t arg) {
+uint8_t auxled_next_state(Event event, uint16_t arg) {
if (event == EV_enter_state) {
uint8_t mode = indicator_led_mode & 3;
#ifdef TICK_DURING_STANDBY
@@ -815,6 +814,9 @@ uint8_t auxled_next_state(EventPtr event, uint16_t arg) {
#else
mode = (mode + 1) % 3;
#endif
+ #ifdef INDICATOR_LED_SKIP_LOW
+ if (mode == 1) { mode ++; }
+ #endif
indicator_led_mode = mode + (indicator_led_mode & 0b00001100);
indicator_led(mode);
save_config();
@@ -830,19 +832,19 @@ uint8_t auxled_next_state(EventPtr event, uint16_t arg) {
#endif
-uint8_t momentary_state(EventPtr event, uint16_t arg) {
+uint8_t momentary_state(Event event, uint16_t arg) {
// TODO: momentary strobe here? (for light painting)
- if (event == EV_click1_press) {
+
+ // light up when the button is pressed; go dark otherwise
+ // button is being held
+ if ((event & (B_CLICK | B_PRESS)) == (B_CLICK | B_PRESS)) {
set_level(memorized_level);
- empty_event_sequence(); // don't attempt to parse multiple clicks
return MISCHIEF_MANAGED;
}
-
- else if (event == EV_release) {
+ // button was released
+ else if ((event & (B_CLICK | B_PRESS)) == (B_CLICK)) {
set_level(0);
- empty_event_sequence(); // don't attempt to parse multiple clicks
//go_to_standby = 1; // sleep while light is off
- // TODO: lighted button should use lockout config?
return MISCHIEF_MANAGED;
}
@@ -854,6 +856,7 @@ uint8_t momentary_state(EventPtr event, uint16_t arg) {
else if ((event == EV_tick) && (actual_level == 0)) {
if (arg > 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;
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:
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
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;
If you find this content useful please consider a small donation via bitcoin: bitcoin:1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2?amount=0.001&message=Donation Scraping git contents via cgit is very resource intensive. The continued hosting of these git repositories is entirely financed by your bitcoin contributions. For donations of a least 1 mBTC you include your IP address in the message of your bitcoin donation. This will remove this message in the future for requests from your IP, which will significantly reduce token usage. In any case, any contributions to bitcoin address 1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2 are very welcome. Thanks in advance for you contribution to a self-sustaining ecosystem.