aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spaghetti-monster/anduril/anduril.c16
-rw-r--r--spaghetti-monster/anduril/battcheck-mode.c8
-rw-r--r--spaghetti-monster/anduril/candle-mode.c58
-rw-r--r--spaghetti-monster/anduril/config-default.h8
-rw-r--r--spaghetti-monster/anduril/goodnight-mode.c72
-rw-r--r--spaghetti-monster/anduril/ramp-mode.c37
-rw-r--r--spaghetti-monster/anduril/sunset-timer.c68
-rw-r--r--spaghetti-monster/anduril/sunset-timer.h (renamed from spaghetti-monster/anduril/goodnight-mode.h)18
8 files changed, 155 insertions, 130 deletions
diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c
index 1faf1be..9fe8aee 100644
--- a/spaghetti-monster/anduril/anduril.c
+++ b/spaghetti-monster/anduril/anduril.c
@@ -97,6 +97,10 @@
#include "aux-leds.h"
#include "misc.h"
+#ifdef USE_SUNSET_TIMER
+#include "sunset-timer.h"
+#endif
+
#ifdef USE_VERSION_CHECK
#include "version-check-mode.h"
#endif
@@ -105,10 +109,6 @@
#include "battcheck-mode.h"
#endif
-#ifdef USE_GOODNIGHT_MODE
-#include "goodnight-mode.h"
-#endif
-
#ifdef USE_BEACON_MODE
#include "beacon-mode.h"
#endif
@@ -152,6 +152,10 @@
#include "aux-leds.c"
#include "misc.c"
+#ifdef USE_SUNSET_TIMER
+#include "sunset-timer.c"
+#endif
+
#ifdef USE_VERSION_CHECK
#include "version-check-mode.c"
#endif
@@ -160,10 +164,6 @@
#include "battcheck-mode.c"
#endif
-#ifdef USE_GOODNIGHT_MODE
-#include "goodnight-mode.c"
-#endif
-
#ifdef USE_BEACON_MODE
#include "beacon-mode.c"
#endif
diff --git a/spaghetti-monster/anduril/battcheck-mode.c b/spaghetti-monster/anduril/battcheck-mode.c
index 3755249..c468332 100644
--- a/spaghetti-monster/anduril/battcheck-mode.c
+++ b/spaghetti-monster/anduril/battcheck-mode.c
@@ -35,13 +35,7 @@ uint8_t battcheck_state(Event event, uint16_t arg) {
set_state(off_state, 0);
return MISCHIEF_MANAGED;
}
- #ifdef USE_GOODNIGHT_MODE
- // 2 clicks: goodnight mode
- else if (event == EV_2clicks) {
- set_state(goodnight_state, 0);
- return MISCHIEF_MANAGED;
- }
- #elif defined(USE_BEACON_MODE)
+ #if defined(USE_BEACON_MODE)
// 2 clicks: beacon mode
else if (event == EV_2clicks) {
set_state(beacon_state, 0);
diff --git a/spaghetti-monster/anduril/candle-mode.c b/spaghetti-monster/anduril/candle-mode.c
index d0a4eb2..70f5e0e 100644
--- a/spaghetti-monster/anduril/candle-mode.c
+++ b/spaghetti-monster/anduril/candle-mode.c
@@ -21,6 +21,9 @@
#define CANDLE_MODE_C
#include "candle-mode.h"
+#ifdef USE_SUNSET_TIMER
+#include "sunset-timer.h"
+#endif
uint8_t candle_mode_state(Event event, uint16_t arg) {
static int8_t ramp_direction = 1;
@@ -37,22 +40,35 @@ uint8_t candle_mode_state(Event event, uint16_t arg) {
static uint8_t candle_wave2_depth = CANDLE_WAVE2_MAXDEPTH * CANDLE_AMPLITUDE / 100;
static uint8_t candle_wave3_depth = CANDLE_WAVE3_MAXDEPTH * CANDLE_AMPLITUDE / 100;
static uint8_t candle_mode_brightness = 24;
- static uint8_t candle_mode_timer = 0;
- #define TICKS_PER_CANDLE_MINUTE 4096 // about 65 seconds
- #define MINUTES_PER_CANDLE_HALFHOUR 27 // ish
+
+ #ifdef USE_SUNSET_TIMER
+ // let the candle "burn out" and shut itself off
+ // if the user told it to
+ // cache this in case it changes when the timer is called
+ uint8_t sunset_active = sunset_timer;
+ // clock tick
+ sunset_timer_state(event, arg);
+ // if the timer just expired, shut off
+ if (sunset_active && (! sunset_timer)) {
+ set_state(off_state, 0);
+ return MISCHIEF_MANAGED;
+ }
+ #endif // ifdef USE_SUNSET_TIMER
+
if (event == EV_enter_state) {
- candle_mode_timer = 0; // in case any time was left over from earlier
ramp_direction = 1;
return MISCHIEF_MANAGED;
}
+ #ifdef USE_SUNSET_TIMER
// 2 clicks: cancel timer
else if (event == EV_2clicks) {
// parent state just rotated through strobe/flasher modes,
// so cancel timer... in case any time was left over from earlier
- candle_mode_timer = 0;
+ sunset_timer = 0;
return MISCHIEF_MANAGED;
}
+ #endif // ifdef USE_SUNSET_TIMER
// hold: change brightness (brighter)
else if (event == EV_click1_hold) {
// ramp away from extremes
@@ -78,17 +94,6 @@ uint8_t candle_mode_state(Event event, uint16_t arg) {
candle_mode_brightness --;
return MISCHIEF_MANAGED;
}
- // 3 clicks: add 30m to candle timer
- else if (event == EV_3clicks) {
- if (candle_mode_timer < (255 - MINUTES_PER_CANDLE_HALFHOUR)) {
- // add 30m to the timer
- candle_mode_timer += MINUTES_PER_CANDLE_HALFHOUR;
- // blink to confirm
- set_level(actual_level + 32);
- delay_4ms(2);
- }
- return MISCHIEF_MANAGED;
- }
// clock tick: animate candle brightness
else if (event == EV_tick) {
// un-reverse after 1 second
@@ -96,22 +101,13 @@ uint8_t candle_mode_state(Event event, uint16_t arg) {
// self-timer dims the light during the final minute
uint8_t subtract = 0;
- if (candle_mode_timer == 1) {
- subtract = ((candle_mode_brightness+CANDLE_AMPLITUDE)
- * ((arg & (TICKS_PER_CANDLE_MINUTE-1)) >> 4))
- >> 8;
- }
- // we passed a minute mark, decrease timer if it's running
- if ((arg & (TICKS_PER_CANDLE_MINUTE-1)) == (TICKS_PER_CANDLE_MINUTE - 1)) {
- if (candle_mode_timer > 0) {
- candle_mode_timer --;
- //set_level(0); delay_4ms(2);
- // if the timer ran out, shut off
- if (! candle_mode_timer) {
- set_state(off_state, 0);
- }
- }
+ #ifdef USE_SUNSET_TIMER
+ if (sunset_timer == 1) {
+ subtract = (candle_mode_brightness+CANDLE_AMPLITUDE)
+ * sunset_ticks / TICKS_PER_MINUTE;
}
+ #endif // ifdef USE_SUNSET_TIMER
+
// 3-oscillator synth for a relatively organic pattern
uint8_t add;
add = ((triangle_wave(candle_wave1) * candle_wave1_depth) >> 8)
diff --git a/spaghetti-monster/anduril/config-default.h b/spaghetti-monster/anduril/config-default.h
index f055425..f037648 100644
--- a/spaghetti-monster/anduril/config-default.h
+++ b/spaghetti-monster/anduril/config-default.h
@@ -90,11 +90,9 @@
// enable beacon mode
#define USE_BEACON_MODE
-// enable sunset (goodnight) mode
-// TODO: replace goodnight mode with a sunset timer in the regular ramp
-#define USE_GOODNIGHT_MODE
-#define GOODNIGHT_TIME 60 // minutes (approximately)
-#define GOODNIGHT_LEVEL 24 // ~11 lm
+// enable sunset timer (ramp-down and automatic shutoff)
+// timer is available in regular ramp mode and candle mode
+#define USE_SUNSET_TIMER
// enable/disable various strobe modes
#define USE_BIKE_FLASHER_MODE
diff --git a/spaghetti-monster/anduril/goodnight-mode.c b/spaghetti-monster/anduril/goodnight-mode.c
deleted file mode 100644
index 2fe90e9..0000000
--- a/spaghetti-monster/anduril/goodnight-mode.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * goodnight-mode.c: Goodnight / sunset mode for Anduril.
- *
- * 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/>.
- */
-
-#ifndef GOODNIGHT_MODE_C
-#define GOODNIGHT_MODE_C
-
-#include "goodnight-mode.h"
-
-#define GOODNIGHT_TICKS_PER_STEPDOWN (GOODNIGHT_TIME*TICKS_PER_SECOND*60L/GOODNIGHT_LEVEL)
-uint8_t goodnight_state(Event event, uint16_t arg) {
- static uint16_t ticks_since_stepdown = 0;
- // blink on start
- if (event == EV_enter_state) {
- ticks_since_stepdown = 0;
- blink_confirm(2);
- set_level(GOODNIGHT_LEVEL);
- return MISCHIEF_MANAGED;
- }
- // 1 click: off
- else if (event == EV_1click) {
- set_state(off_state, 0);
- return MISCHIEF_MANAGED;
- }
- // 2 clicks: next mode
- else if (event == EV_2clicks) {
- #ifdef USE_BEACON_MODE
- set_state(beacon_state, 0);
- #elif defined(USE_SOS_MODE_IN_BLINKY_GROUP)
- set_state(sos_state, 0);
- #elif defined(USE_THERMAL_REGULATION)
- set_state(tempcheck_state, 0);
- #endif
- return MISCHIEF_MANAGED;
- }
- // tick: step down (maybe) or off (maybe)
- else if (event == EV_tick) {
- if (++ticks_since_stepdown > GOODNIGHT_TICKS_PER_STEPDOWN) {
- ticks_since_stepdown = 0;
- set_level(actual_level-1);
- if (! actual_level) {
- #if 0 // test blink, to help measure timing
- set_level(MAX_LEVEL>>2);
- delay_4ms(8/2);
- set_level(0);
- #endif
- set_state(off_state, 0);
- }
- }
- return MISCHIEF_MANAGED;
- }
- return EVENT_NOT_HANDLED;
-}
-
-
-#endif
-
diff --git a/spaghetti-monster/anduril/ramp-mode.c b/spaghetti-monster/anduril/ramp-mode.c
index b870550..a0a123d 100644
--- a/spaghetti-monster/anduril/ramp-mode.c
+++ b/spaghetti-monster/anduril/ramp-mode.c
@@ -21,6 +21,9 @@
#define RAMP_MODE_C
#include "ramp-mode.h"
+#ifdef USE_SUNSET_TIMER
+#include "sunset-timer.h"
+#endif
uint8_t steady_state(Event event, uint16_t arg) {
#ifdef USE_REVERSING
@@ -43,6 +46,23 @@ uint8_t steady_state(Event event, uint16_t arg) {
if (ramp_style) { step_size = ramp_discrete_step_size; }
else { step_size = 1; }
+ #ifdef USE_SUNSET_TIMER
+ // handle the shutoff timer first
+ static uint8_t timer_orig_level = 0;
+ uint8_t sunset_active = sunset_timer; // save for comparison
+ // clock tick
+ sunset_timer_state(event, arg);
+ // if the timer was just turned on
+ if (sunset_timer && (! sunset_active)) {
+ timer_orig_level = actual_level;
+ }
+ // if the timer just expired, shut off
+ else if (sunset_active && (! sunset_timer)) {
+ set_state(off_state, 0);
+ return MISCHIEF_MANAGED;
+ }
+ #endif // ifdef USE_SUNSET_TIMER
+
// turn LED on when we first enter the mode
if ((event == EV_enter_state) || (event == EV_reenter_state)) {
#if defined(USE_MOMENTARY_MODE) && defined(USE_STROBE_STATE)
@@ -232,8 +252,20 @@ uint8_t steady_state(Event event, uint16_t arg) {
}
#endif
- #if defined(USE_SET_LEVEL_GRADUALLY) || defined(USE_REVERSING)
else if (event == EV_tick) {
+ #ifdef USE_SUNSET_TIMER
+ // reduce output if shutoff timer is active
+ if (sunset_timer) {
+ uint8_t dimmed_level = timer_orig_level * (sunset_timer-1) / sunset_timer_peak;
+ if (dimmed_level < 1) dimmed_level = 1;
+ #ifdef USE_SET_LEVEL_GRADUALLY
+ set_level_gradually(dimmed_level);
+ target_level = dimmed_level;
+ #else
+ set_level_and_therm_target(dimmed_level);
+ #endif
+ }
+ #endif
#ifdef USE_REVERSING
// un-reverse after 1 second
if (arg == TICKS_PER_SECOND) ramp_direction = 1;
@@ -270,7 +302,6 @@ uint8_t steady_state(Event event, uint16_t arg) {
#endif // ifdef USE_SET_LEVEL_GRADUALLY
return MISCHIEF_MANAGED;
}
- #endif
#ifdef USE_THERMAL_REGULATION
// overheating: drop by an amount proportional to how far we are above the ceiling
else if (event == EV_temperature_high) {
@@ -453,6 +484,8 @@ void set_level_and_therm_target(uint8_t level) {
target_level = level;
set_level(level);
}
+#else
+#define set_level_and_therm_target(level) set_level(level)
#endif
diff --git a/spaghetti-monster/anduril/sunset-timer.c b/spaghetti-monster/anduril/sunset-timer.c
new file mode 100644
index 0000000..0687993
--- /dev/null
+++ b/spaghetti-monster/anduril/sunset-timer.c
@@ -0,0 +1,68 @@
+/*
+ * sunset-timer.c: Sunset / candle auto-shutoff functions for Anduril.
+ *
+ * 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/>.
+ */
+
+#ifndef SUNSET_TIMER_C
+#define SUNSET_TIMER_C
+
+#include "sunset-timer.h"
+
+uint8_t sunset_timer_state(Event event, uint16_t arg) {
+
+ // blink on start
+ if (event == EV_enter_state) {
+ sunset_timer = 0;
+ sunset_ticks = 0;
+ return MISCHIEF_MANAGED;
+ }
+ // 3 clicks: add 30m to timer
+ else if (event == EV_3clicks) {
+ if (sunset_timer < (255 - SUNSET_TIMER_UNIT)) {
+ // add 30m to the timer
+ sunset_timer += SUNSET_TIMER_UNIT;
+ sunset_timer_peak = sunset_timer; // reset ceiling
+ sunset_ticks = 0; // reset phase
+ // blink to confirm
+ uint8_t brightness = actual_level;
+ uint8_t bump = actual_level + 32;
+ if (bump > MAX_LEVEL) bump = 0;
+ set_level(bump);
+ delay_4ms(2);
+ set_level(brightness);
+ }
+ return MISCHIEF_MANAGED;
+ }
+ // tick: step down (maybe) or off (maybe)
+ else if (event == EV_tick) {
+ // time passed
+ sunset_ticks ++;
+ // did we reach a minute mark?
+ if (sunset_ticks >= TICKS_PER_MINUTE) {
+ sunset_ticks = 0;
+ if (sunset_timer > 0) {
+ sunset_timer --;
+ }
+ }
+ return MISCHIEF_MANAGED;
+ }
+ return EVENT_NOT_HANDLED;
+}
+
+
+#endif
+
diff --git a/spaghetti-monster/anduril/goodnight-mode.h b/spaghetti-monster/anduril/sunset-timer.h
index 3bb5272..2e39e5d 100644
--- a/spaghetti-monster/anduril/goodnight-mode.h
+++ b/spaghetti-monster/anduril/sunset-timer.h
@@ -1,5 +1,5 @@
/*
- * goodnight-mode.h: Goodnight / sunset for Anduril.
+ * sunset-timer.h: Sunset / candle auto-shutoff functions for Anduril.
*
* Copyright (C) 2017 Selene ToyKeeper
*
@@ -17,11 +17,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GOODNIGHT_MODE_H
-#define GOODNIGHT_MODE_H
+#ifndef SUNSET_TIMER_H
+#define SUNSET_TIMER_H
-// 1-hour ramp down from low, then automatic off
-uint8_t goodnight_state(Event event, uint16_t arg);
+// how many minutes to add each time the user "bumps" the timer?
+#define SUNSET_TIMER_UNIT 10
+
+#define TICKS_PER_MINUTE (TICKS_PER_SECOND*60)
+
+// automatic shutoff timer
+uint8_t sunset_timer = 0;
+uint8_t sunset_timer_peak = 0;
+uint16_t sunset_ticks = 0;
+uint8_t sunset_timer_state(Event event, uint16_t arg);
#endif