aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spaghetti-monster/baton/baton-simpler.c40
-rw-r--r--spaghetti-monster/baton/baton.c112
-rw-r--r--spaghetti-monster/baton/baton.txt21
3 files changed, 103 insertions, 70 deletions
diff --git a/spaghetti-monster/baton/baton-simpler.c b/spaghetti-monster/baton/baton-simpler.c
index 96b0ea7..d4725ef 100644
--- a/spaghetti-monster/baton/baton-simpler.c
+++ b/spaghetti-monster/baton/baton-simpler.c
@@ -20,7 +20,6 @@
#define FSM_EMISAR_D4_DRIVER
#define USE_LVP
#define USE_THERMAL_REGULATION
-#define DEFAULT_THERM_CEIL 45
#define USE_DELAY_MS
#include "spaghetti-monster.h"
@@ -59,6 +58,11 @@ uint8_t off_state(EventPtr event, uint16_t arg) {
set_level(0);
return EVENT_HANDLED;
}
+ // hold (longer): go to lowest level
+ else if (event == EV_click1_hold) {
+ set_state(steady_state, 0);
+ return EVENT_HANDLED;
+ }
// 1 click (before timeout): go to memorized level, but allow abort for double click
else if (event == EV_click1_release) {
set_level(memorized_level);
@@ -79,11 +83,6 @@ uint8_t off_state(EventPtr event, uint16_t arg) {
set_state(lockout_state, 0);
return EVENT_HANDLED;
}
- // hold: go to lowest level
- else if (event == EV_click1_hold) {
- set_state(steady_state, 0);
- return EVENT_HANDLED;
- }
return EVENT_NOT_HANDLED;
}
@@ -91,8 +90,8 @@ uint8_t steady_state(EventPtr event, uint16_t arg) {
// turn LED on when we first enter the mode
if (event == EV_enter_state) {
// remember this level, unless it's moon or turbo
- if ((arg > 0) && (arg < MAX_LEVEL))
- memorized_level = arg;
+ if ((arg > 0) && (arg < MAX_LEVEL)) memorized_level = arg;
+ // use the requested level even if not memorized
#ifdef USE_THERMAL_REGULATION
target_level = arg;
#endif
@@ -135,16 +134,12 @@ uint8_t steady_state(EventPtr event, uint16_t arg) {
#ifdef USE_THERMAL_REGULATION
// overheating: drop by 1 level
else if (event == EV_temperature_high) {
- if (actual_level > 1) {
- set_level(actual_level - 1);
- }
+ if (actual_level > 1) { set_level(actual_level - 1); }
return EVENT_HANDLED;
}
// underheating: increase by 1 level if we're lower than the target
else if (event == EV_temperature_low) {
- if (actual_level < target_level) {
- set_level(actual_level + 1);
- }
+ if (actual_level < target_level) { set_level(actual_level + 1); }
return EVENT_HANDLED;
}
#endif
@@ -152,18 +147,14 @@ uint8_t steady_state(EventPtr event, uint16_t arg) {
}
uint8_t lockout_state(EventPtr event, uint16_t arg) {
- // stay asleep while locked, but allow waking long enough to click 4 times
+ // stay asleep while locked
if (event == EV_tick) {
- static uint8_t ticks_spent_awake = 0;
- ticks_spent_awake ++;
- PWM1_LVL = 0; PWM2_LVL = 0;
- if (ticks_spent_awake > 3 * TICKS_PER_SECOND) {
- ticks_spent_awake = 0;
- go_to_standby = 1;
- }
+ PWM1_LVL = 0; PWM2_LVL = 0; // make sure emitters are off
+ // sleep 1 second after user stops pressing buttons
+ if (arg > TICKS_PER_SECOND) { go_to_standby = 1; }
return MISCHIEF_MANAGED;
}
- // 4 clicks: exit
+ // 4 clicks: exit, and turn on at "low" level
else if (event == EV_4clicks) {
set_state(steady_state, 1);
return MISCHIEF_MANAGED;
@@ -175,6 +166,9 @@ void low_voltage() {
// step down by one level or turn off
if (actual_level > 0) {
set_level(actual_level - 1);
+ #ifdef USE_THERMAL_REGULATION
+ target_level = actual_level; // don't let low temperature override LVP
+ #endif
}
else {
set_state(off_state, 0);
diff --git a/spaghetti-monster/baton/baton.c b/spaghetti-monster/baton/baton.c
index 1266ddd..59a7196 100644
--- a/spaghetti-monster/baton/baton.c
+++ b/spaghetti-monster/baton/baton.c
@@ -20,22 +20,17 @@
#define FSM_EMISAR_D4_DRIVER
#define USE_LVP
#define USE_THERMAL_REGULATION
-#define DEFAULT_THERM_CEIL 45
#define USE_DEBUG_BLINK
#define USE_DELAY_MS
#define USE_DELAY_4MS
#define USE_DELAY_ZERO
#include "spaghetti-monster.h"
-// moon + ../../bin/level_calc.py 2 6 7135 18 10 150 FET 1 10 1500
-uint8_t pwm1_modes[] = { 3, 18, 110, 255, 255, 255, 0, };
-uint8_t pwm2_modes[] = { 0, 0, 0, 9, 58, 138, 255, };
-#define MAX_LEVEL (sizeof(pwm1_modes)-1)
-
// FSM states
uint8_t off_state(EventPtr event, uint16_t arg);
uint8_t steady_state(EventPtr event, uint16_t arg);
uint8_t party_strobe_state(EventPtr event, uint16_t arg);
+uint8_t lockout_state(EventPtr event, uint16_t arg);
// brightness control
uint8_t memorized_level = 1;
@@ -44,93 +39,100 @@ uint8_t actual_level = 0;
uint8_t target_level = 0;
#endif
+// moon + ../../bin/level_calc.py 2 6 7135 18 10 150 FET 1 10 1500
+uint8_t pwm1_levels[] = { 3, 18, 110, 255, 255, 255, 0, };
+uint8_t pwm2_levels[] = { 0, 0, 0, 9, 58, 138, 255, };
+#define MAX_LEVEL (sizeof(pwm1_levels)-1)
+
+// set LED brightness
void set_level(uint8_t lvl) {
actual_level = lvl;
- PWM1_LVL = pwm1_modes[lvl];
- PWM2_LVL = pwm2_modes[lvl];
+ PWM1_LVL = pwm1_levels[lvl];
+ PWM2_LVL = pwm2_levels[lvl];
}
uint8_t off_state(EventPtr event, uint16_t arg) {
// turn emitter off when entering state
if (event == EV_enter_state) {
- PWM1_LVL = 0;
- PWM2_LVL = 0;
- // sleep while off (lower power use)
- go_to_standby = 1;
- return 0;
+ go_to_standby = 1; // sleep while off (lower power use)
+ return EVENT_HANDLED;
}
// hold (initially): go to lowest level, but allow abort for regular click
else if (event == EV_click1_press) {
set_level(0);
- return 0;
+ return EVENT_HANDLED;
+ }
+ // hold (longer): go to lowest level
+ else if (event == EV_click1_hold) {
+ set_state(steady_state, 0);
+ return EVENT_HANDLED;
}
// 1 click (before timeout): go to memorized level, but allow abort for double click
else if (event == EV_click1_release) {
set_level(memorized_level);
- return 0;
+ return EVENT_HANDLED;
}
// 1 click: regular mode
else if (event == EV_1click) {
set_state(steady_state, memorized_level);
- return 0;
+ return EVENT_HANDLED;
}
// 2 clicks: highest mode
else if (event == EV_2clicks) {
set_state(steady_state, MAX_LEVEL);
- return 0;
+ return EVENT_HANDLED;
}
// 3 clicks: strobe mode
else if (event == EV_3clicks) {
set_state(party_strobe_state, 255);
- return 0;
+ return EVENT_HANDLED;
}
- // hold: go to lowest level
- else if (event == EV_click1_hold) {
- set_state(steady_state, 0);
- return 0;
+ // 4 clicks: soft lockout
+ else if (event == EV_4clicks) {
+ set_state(lockout_state, 0);
+ return EVENT_HANDLED;
}
- return 1;
+ return EVENT_NOT_HANDLED;
}
uint8_t steady_state(EventPtr event, uint16_t arg) {
// turn LED on when we first enter the mode
if (event == EV_enter_state) {
// remember this level, unless it's moon or turbo
- if ((arg > 0) && (arg < MAX_LEVEL))
- memorized_level = arg;
+ if ((arg > 0) && (arg < MAX_LEVEL)) memorized_level = arg;
// use the requested level even if not memorized
#ifdef USE_THERMAL_REGULATION
target_level = arg;
#endif
set_level(arg);
- return 0;
+ return EVENT_HANDLED;
}
// 1 click: off
else if (event == EV_1click) {
set_state(off_state, 0);
- return 0;
+ return EVENT_HANDLED;
}
// 2 clicks: go to/from highest level
else if (event == EV_2clicks) {
- if (actual_level < MAX_LEVEL) {
+ if (actual_level < MAX_LEVEL) { // go to turbo
memorized_level = actual_level; // in case we're on moon
#ifdef USE_THERMAL_REGULATION
target_level = MAX_LEVEL;
#endif
set_level(MAX_LEVEL);
}
- else {
+ else { // return from turbo
#ifdef USE_THERMAL_REGULATION
target_level = memorized_level;
#endif
set_level(memorized_level);
}
- return 0;
+ return EVENT_HANDLED;
}
// 3 clicks: go to strobe modes
else if (event == EV_3clicks) {
set_state(party_strobe_state, 0xff);
- return 0;
+ return EVENT_HANDLED;
}
// hold: change brightness
else if (event == EV_click1_hold) {
@@ -141,25 +143,21 @@ uint8_t steady_state(EventPtr event, uint16_t arg) {
#endif
set_level(memorized_level);
}
- return 0;
+ return EVENT_HANDLED;
}
#ifdef USE_THERMAL_REGULATION
// overheating: drop by 1 level
else if (event == EV_temperature_high) {
- if (actual_level > 1) {
- set_level(actual_level - 1);
- }
- return 0;
+ if (actual_level > 1) { set_level(actual_level - 1); }
+ return EVENT_HANDLED;
}
// underheating: increase by 1 level if we're lower than the target
else if (event == EV_temperature_low) {
- if (actual_level < target_level) {
- set_level(actual_level + 1);
- }
- return 0;
+ if (actual_level < target_level) { set_level(actual_level + 1); }
+ return EVENT_HANDLED;
}
#endif
- return 1;
+ return EVENT_NOT_HANDLED;
}
uint8_t party_strobe_state(EventPtr event, uint16_t arg) {
@@ -168,7 +166,7 @@ uint8_t party_strobe_state(EventPtr event, uint16_t arg) {
if (event == EV_enter_state) {
if (arg < 64) between = arg;
frames = 0;
- return 0;
+ return MISCHIEF_MANAGED;
}
// tick: strobe the emitter
else if (event == EV_tick) {
@@ -182,17 +180,17 @@ uint8_t party_strobe_state(EventPtr event, uint16_t arg) {
//frames = (frames + 1) % between;
frames++;
if (frames > between) frames = 0;
- return 0;
+ return MISCHIEF_MANAGED;
}
// 1 click: off
else if (event == EV_1click) {
set_state(off_state, 0);
- return 0;
+ return MISCHIEF_MANAGED;
}
// 2 clicks: go back to regular modes
else if (event == EV_2clicks) {
set_state(steady_state, memorized_level);
- return 0;
+ return MISCHIEF_MANAGED;
}
// hold: change speed
else if (event == EV_click1_hold) {
@@ -200,9 +198,25 @@ uint8_t party_strobe_state(EventPtr event, uint16_t arg) {
between = (between+1)%6;
frames = 0;
}
- return 0;
+ return MISCHIEF_MANAGED;
+ }
+ return EVENT_NOT_HANDLED;
+}
+
+uint8_t lockout_state(EventPtr event, uint16_t arg) {
+ // stay asleep while locked
+ if (event == EV_tick) {
+ PWM1_LVL = 0; PWM2_LVL = 0; // make sure emitters are off
+ // sleep 1 second after user stops pressing
+ if (arg > TICKS_PER_SECOND) { go_to_standby = 1; }
+ return MISCHIEF_MANAGED;
+ }
+ // 4 clicks: exit, and turn on at "low" level
+ else if (event == EV_4clicks) {
+ set_state(steady_state, 1);
+ return MISCHIEF_MANAGED;
}
- return 1;
+ return EVENT_NOT_HANDLED;
}
void low_voltage() {
@@ -214,6 +228,10 @@ void low_voltage() {
else if (current_state == steady_state) {
if (actual_level > 0) {
set_level(actual_level - 1);
+ #ifdef USE_THERMAL_REGULATION
+ target_level = actual_level; // don't let low temperature override LVP
+ #endif
+
}
else {
set_state(off_state, 0);
diff --git a/spaghetti-monster/baton/baton.txt b/spaghetti-monster/baton/baton.txt
new file mode 100644
index 0000000..2f0c22f
--- /dev/null
+++ b/spaghetti-monster/baton/baton.txt
@@ -0,0 +1,21 @@
+This is a very simple clone of the Olight Baton interface. It is not
+exact, but it has the basics. Mostly, it exists for the purposes of
+demonstrating how to create interfaces in FSM.
+
+While off:
+
+ - 1 click: Turn on (at memorized level).
+ - Hold: Turn on (at moon level).
+ - 2 clicks: Turn on (at highest level).
+ - 4 clicks: Soft lockout mode.
+
+While on:
+
+ - 1 click: Turn off.
+ - Hold: Change the brightness. Goes up in steps, then wraps around.
+ - 2 clicks: Go to/from highest level.
+
+While locked:
+
+ - 4 clicks: Exit lockout mode.
+