aboutsummaryrefslogtreecommitdiff
path: root/spaghetti-monster
diff options
context:
space:
mode:
Diffstat (limited to 'spaghetti-monster')
-rw-r--r--spaghetti-monster/anduril/anduril.c271
-rw-r--r--spaghetti-monster/anduril/aux-leds.c174
-rw-r--r--spaghetti-monster/anduril/aux-leds.h83
3 files changed, 290 insertions, 238 deletions
diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c
index 6ef7954..b479552 100644
--- a/spaghetti-monster/anduril/anduril.c
+++ b/spaghetti-monster/anduril/anduril.c
@@ -2,7 +2,7 @@
* Anduril: Narsil-inspired UI for SpaghettiMonster.
* (Anduril is Aragorn's sword, the blade Narsil reforged)
*
- * Copyright (C) 2017-2019 Selene ToyKeeper
+ * Copyright (C) 2017-2020 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
@@ -18,34 +18,36 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-// Usually a program would be structured like this...
-// - Library headers
-// - App headers
-// - App code
-//
-// ... in each source file.
-// ... and each library and part of the program would be linked together.
-//
-// But this doesn't follow that pattern, because it's using the
-// -fwhole-program
-// flag to reduce the compiled size. It lets us fit more features
-// in a tiny MCU chip's ROM.
-//
-// So the structure is like this instead...
-// - App-level configuration headers
-// - Default config
-// - Per build target config
-// - Library-level configuration headers
-// - Library code (FSM itself)
-// - App headers
-// - App code (all of it, inline)
-//
-// Don't do this in regular programs. It's weird and kind of gross.
-// But in this case it gives us a bunch of much-needed space, so... woot.
-//
-// Also, there are a ton of compile-time flags because it needs to build
-// a bunch of different versions and each one needs to be trimmed as small
-// as possible. These are mostly "USE" flags.
+/*
+ * Usually a program would be structured like this...
+ * - Library headers
+ * - App headers
+ * - App code
+ *
+ * ... in each source file.
+ * ... and each library and part of the program would be linked together.
+ *
+ * But this doesn't follow that pattern, because it's using the
+ * -fwhole-program
+ * flag to reduce the compiled size. It lets us fit more features
+ * in a tiny MCU chip's ROM.
+ *
+ * So the structure is like this instead...
+ * - App-level configuration headers
+ * - Default config
+ * - Per build target config
+ * - Library-level configuration headers
+ * - Library code (FSM itself)
+ * - App headers
+ * - App code (all of it, inline)
+ *
+ * Don't do this in regular programs. It's weird and kind of gross.
+ * But in this case it gives us a bunch of much-needed space, so... woot.
+ *
+ * Also, there are a ton of compile-time flags because it needs to build
+ * a bunch of different versions and each one needs to be trimmed as small
+ * as possible. These are mostly "USE" flags.
+ */
/********* User-configurable options *********/
#include "config-default.h"
@@ -92,6 +94,7 @@
#include "ramp-mode.h"
#include "load-save-config.h"
#include "config-mode.h"
+#include "aux-leds.h"
#include "misc.h"
#ifdef USE_VERSION_CHECK
@@ -137,68 +140,6 @@
#include "sos-mode.h"
#endif
-// FSM states
-
-#if defined(USE_INDICATOR_LED) && defined(TICK_DURING_STANDBY)
-void indicator_blink(uint8_t arg);
-#endif
-#if defined(USE_AUX_RGB_LEDS) && defined(TICK_DURING_STANDBY)
-uint8_t setting_rgb_mode_now = 0;
-void rgb_led_update(uint8_t mode, uint8_t arg);
-void rgb_led_voltage_readout(uint8_t bright);
-/*
- * 0: R
- * 1: RG
- * 2: G
- * 3: GB
- * 4: B
- * 5: R B
- * 6: RGB
- * 7: rainbow
- * 8: voltage
- */
-const PROGMEM uint8_t rgb_led_colors[] = {
- 0b00000001, // 0: red
- 0b00000101, // 1: yellow
- 0b00000100, // 2: green
- 0b00010100, // 3: cyan
- 0b00010000, // 4: blue
- 0b00010001, // 5: purple
- 0b00010101, // 6: white
-};
-#define RGB_LED_NUM_COLORS 10
-#define RGB_LED_NUM_PATTERNS 4
-#ifndef RGB_LED_OFF_DEFAULT
-//#define RGB_LED_OFF_DEFAULT 0x18 // low, voltage
-#define RGB_LED_OFF_DEFAULT 0x17 // low, rainbow
-#endif
-#ifndef RGB_LED_LOCKOUT_DEFAULT
-#define RGB_LED_LOCKOUT_DEFAULT 0x37 // blinking, rainbow
-#endif
-#ifndef RGB_RAINBOW_SPEED
-#define RGB_RAINBOW_SPEED 0x0f // change color every 16 frames
-#endif
-uint8_t rgb_led_off_mode = RGB_LED_OFF_DEFAULT;
-uint8_t rgb_led_lockout_mode = RGB_LED_LOCKOUT_DEFAULT;
-#endif
-
-
-#ifdef USE_INDICATOR_LED
- // bits 2-3 control lockout mode
- // bits 0-1 control "off" mode
- // modes are: 0=off, 1=low, 2=high, 3=blinking (if TICK_DURING_STANDBY enabled)
- #ifdef INDICATOR_LED_DEFAULT_MODE
- uint8_t indicator_led_mode = INDICATOR_LED_DEFAULT_MODE;
- #else
- #ifdef USE_INDICATOR_LED_WHILE_RAMPING
- //uint8_t indicator_led_mode = (1<<2) + 2;
- uint8_t indicator_led_mode = (2<<2) + 1;
- #else
- uint8_t indicator_led_mode = (3<<2) + 1;
- #endif
- #endif
-#endif
-
/********* Include all the app logic source files *********/
// (is a bit weird to do things this way,
@@ -208,6 +149,7 @@ uint8_t rgb_led_lockout_mode = RGB_LED_LOCKOUT_DEFAULT;
#include "ramp-mode.c"
#include "load-save-config.c"
#include "config-mode.c"
+#include "aux-leds.c"
#include "misc.c"
#ifdef USE_VERSION_CHECK
@@ -255,153 +197,6 @@ uint8_t rgb_led_lockout_mode = RGB_LED_LOCKOUT_DEFAULT;
#endif
-#if defined(USE_INDICATOR_LED) && defined(TICK_DURING_STANDBY)
-// beacon-like mode for the indicator LED
-void indicator_blink(uint8_t arg) {
- // turn off aux LEDs when battery is empty
- if (voltage < VOLTAGE_LOW) { indicator_led(0); return; }
-
- #ifdef USE_FANCIER_BLINKING_INDICATOR
-
- // fancy blink, set off/low/high levels here:
- uint8_t seq[] = {0, 1, 2, 1, 0, 0, 0, 0,
- 0, 0, 1, 0, 0, 0, 0, 0};
- indicator_led(seq[arg & 15]);
-
- #else // basic blink, 1/8th duty cycle
-
- if (! (arg & 7)) {
- indicator_led(2);
- }
- else {
- indicator_led(0);
- }
-
- #endif
-}
-#endif
-
-#if defined(USE_AUX_RGB_LEDS) && defined(TICK_DURING_STANDBY)
-uint8_t voltage_to_rgb() {
- uint8_t levels[] = {
- // voltage, color
- 0, 0, // 0, R
- 33, 1, // 1, R+G
- 35, 2, // 2, G
- 37, 3, // 3, G+B
- 39, 4, // 4, B
- 41, 5, // 5, R + B
- 44, 6, // 6, R+G+B // skip; looks too similar to G+B
- 255, 6, // 7, R+G+B
- };
- uint8_t volts = voltage;
- if (volts < 29) return 0;
-
- uint8_t i;
- for (i = 0; volts >= levels[i]; i += 2) {}
- uint8_t color_num = levels[(i - 2) + 1];
- return pgm_read_byte(rgb_led_colors + color_num);
-}
-
-// do fancy stuff with the RGB aux LEDs
-// mode: 0bPPPPCCCC where PPPP is the pattern and CCCC is the color
-// arg: time slice number
-void rgb_led_update(uint8_t mode, uint8_t arg) {
- static uint8_t rainbow = 0; // track state of rainbow mode
- static uint8_t frame = 0; // track state of animation mode
-
- // turn off aux LEDs when battery is empty
- // (but if voltage==0, that means we just booted and don't know yet)
- uint8_t volts = voltage; // save a few bytes by caching volatile value
- if ((volts) && (volts < VOLTAGE_LOW)) {
- rgb_led_set(0);
- #ifdef USE_BUTTON_LED
- button_led_set(0);
- #endif
- return;
- }
-
- uint8_t pattern = (mode>>4); // off, low, high, blinking, ... more?
- uint8_t color = mode & 0x0f;
-
- // preview in blinking mode is awkward... use high instead
- if ((! go_to_standby) && (pattern > 2)) { pattern = 2; }
-
-
- const uint8_t *colors = rgb_led_colors;
- uint8_t actual_color = 0;
- if (color < 7) { // normal color
- actual_color = pgm_read_byte(colors + color);
- }
- else if (color == 7) { // rainbow
- uint8_t speed = 0x03; // awake speed
- if (go_to_standby) speed = RGB_RAINBOW_SPEED; // asleep speed
- if (0 == (arg & speed)) {
- rainbow = (rainbow + 1) % 6;
- }
- actual_color = pgm_read_byte(colors + rainbow);
- }
- else { // voltage
- // show actual voltage while asleep...
- if (go_to_standby) {
- actual_color = voltage_to_rgb();
- // choose a color based on battery voltage
- //if (volts >= 38) actual_color = pgm_read_byte(colors + 4);
- //else if (volts >= 33) actual_color = pgm_read_byte(colors + 2);
- //else actual_color = pgm_read_byte(colors + 0);
- }
- // ... but during preview, cycle colors quickly
- else {
- actual_color = pgm_read_byte(colors + (((arg>>1) % 3) << 1));
- }
- }
-
- // pick a brightness from the animation sequence
- if (pattern == 3) {
- // uses an odd length to avoid lining up with rainbow loop
- uint8_t animation[] = {2, 1, 0, 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 1};
- frame = (frame + 1) % sizeof(animation);
- pattern = animation[frame];
- }
- uint8_t result;
- #ifdef USE_BUTTON_LED
- uint8_t button_led_result;
- #endif
- switch (pattern) {
- case 0: // off
- result = 0;
- #ifdef USE_BUTTON_LED
- button_led_result = 0;
- #endif
- break;
- case 1: // low
- result = actual_color;
- #ifdef USE_BUTTON_LED
- button_led_result = 1;
- #endif
- break;
- default: // high
- result = (actual_color << 1);
- #ifdef USE_BUTTON_LED
- button_led_result = 2;
- #endif
- break;
- }
- rgb_led_set(result);
- #ifdef USE_BUTTON_LED
- button_led_set(button_led_result);
- #endif
-}
-
-void rgb_led_voltage_readout(uint8_t bright) {
- uint8_t color = voltage_to_rgb();
- if (bright) color = color << 1;
- rgb_led_set(color);
-}
-#endif
-
-
void low_voltage() {
StatePtr state = current_state;
diff --git a/spaghetti-monster/anduril/aux-leds.c b/spaghetti-monster/anduril/aux-leds.c
new file mode 100644
index 0000000..d783797
--- /dev/null
+++ b/spaghetti-monster/anduril/aux-leds.c
@@ -0,0 +1,174 @@
+/*
+ * aux-leds.c: Aux LED 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 AUX_LEDS_C
+#define AUX_LEDS_C
+
+#include "aux-leds.h"
+
+
+#if defined(USE_INDICATOR_LED) && defined(TICK_DURING_STANDBY)
+// beacon-like mode for the indicator LED
+void indicator_blink(uint8_t arg) {
+ // turn off aux LEDs when battery is empty
+ if (voltage < VOLTAGE_LOW) { indicator_led(0); return; }
+
+ #ifdef USE_FANCIER_BLINKING_INDICATOR
+
+ // fancy blink, set off/low/high levels here:
+ uint8_t seq[] = {0, 1, 2, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0};
+ indicator_led(seq[arg & 15]);
+
+ #else // basic blink, 1/8th duty cycle
+
+ if (! (arg & 7)) {
+ indicator_led(2);
+ }
+ else {
+ indicator_led(0);
+ }
+
+ #endif
+}
+#endif
+
+#if defined(USE_AUX_RGB_LEDS) && defined(TICK_DURING_STANDBY)
+uint8_t voltage_to_rgb() {
+ uint8_t levels[] = {
+ // voltage, color
+ 0, 0, // 0, R
+ 33, 1, // 1, R+G
+ 35, 2, // 2, G
+ 37, 3, // 3, G+B
+ 39, 4, // 4, B
+ 41, 5, // 5, R + B
+ 44, 6, // 6, R+G+B // skip; looks too similar to G+B
+ 255, 6, // 7, R+G+B
+ };
+ uint8_t volts = voltage;
+ if (volts < 29) return 0;
+
+ uint8_t i;
+ for (i = 0; volts >= levels[i]; i += 2) {}
+ uint8_t color_num = levels[(i - 2) + 1];
+ return pgm_read_byte(rgb_led_colors + color_num);
+}
+
+// do fancy stuff with the RGB aux LEDs
+// mode: 0bPPPPCCCC where PPPP is the pattern and CCCC is the color
+// arg: time slice number
+void rgb_led_update(uint8_t mode, uint8_t arg) {
+ static uint8_t rainbow = 0; // track state of rainbow mode
+ static uint8_t frame = 0; // track state of animation mode
+
+ // turn off aux LEDs when battery is empty
+ // (but if voltage==0, that means we just booted and don't know yet)
+ uint8_t volts = voltage; // save a few bytes by caching volatile value
+ if ((volts) && (volts < VOLTAGE_LOW)) {
+ rgb_led_set(0);
+ #ifdef USE_BUTTON_LED
+ button_led_set(0);
+ #endif
+ return;
+ }
+
+ uint8_t pattern = (mode>>4); // off, low, high, blinking, ... more?
+ uint8_t color = mode & 0x0f;
+
+ // preview in blinking mode is awkward... use high instead
+ if ((! go_to_standby) && (pattern > 2)) { pattern = 2; }
+
+
+ const uint8_t *colors = rgb_led_colors;
+ uint8_t actual_color = 0;
+ if (color < 7) { // normal color
+ actual_color = pgm_read_byte(colors + color);
+ }
+ else if (color == 7) { // rainbow
+ uint8_t speed = 0x03; // awake speed
+ if (go_to_standby) speed = RGB_RAINBOW_SPEED; // asleep speed
+ if (0 == (arg & speed)) {
+ rainbow = (rainbow + 1) % 6;
+ }
+ actual_color = pgm_read_byte(colors + rainbow);
+ }
+ else { // voltage
+ // show actual voltage while asleep...
+ if (go_to_standby) {
+ actual_color = voltage_to_rgb();
+ // choose a color based on battery voltage
+ //if (volts >= 38) actual_color = pgm_read_byte(colors + 4);
+ //else if (volts >= 33) actual_color = pgm_read_byte(colors + 2);
+ //else actual_color = pgm_read_byte(colors + 0);
+ }
+ // ... but during preview, cycle colors quickly
+ else {
+ actual_color = pgm_read_byte(colors + (((arg>>1) % 3) << 1));
+ }
+ }
+
+ // pick a brightness from the animation sequence
+ if (pattern == 3) {
+ // uses an odd length to avoid lining up with rainbow loop
+ uint8_t animation[] = {2, 1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+ frame = (frame + 1) % sizeof(animation);
+ pattern = animation[frame];
+ }
+ uint8_t result;
+ #ifdef USE_BUTTON_LED
+ uint8_t button_led_result;
+ #endif
+ switch (pattern) {
+ case 0: // off
+ result = 0;
+ #ifdef USE_BUTTON_LED
+ button_led_result = 0;
+ #endif
+ break;
+ case 1: // low
+ result = actual_color;
+ #ifdef USE_BUTTON_LED
+ button_led_result = 1;
+ #endif
+ break;
+ default: // high
+ result = (actual_color << 1);
+ #ifdef USE_BUTTON_LED
+ button_led_result = 2;
+ #endif
+ break;
+ }
+ rgb_led_set(result);
+ #ifdef USE_BUTTON_LED
+ button_led_set(button_led_result);
+ #endif
+}
+
+void rgb_led_voltage_readout(uint8_t bright) {
+ uint8_t color = voltage_to_rgb();
+ if (bright) color = color << 1;
+ rgb_led_set(color);
+}
+#endif
+
+
+#endif
+
diff --git a/spaghetti-monster/anduril/aux-leds.h b/spaghetti-monster/anduril/aux-leds.h
new file mode 100644
index 0000000..cb3975e
--- /dev/null
+++ b/spaghetti-monster/anduril/aux-leds.h
@@ -0,0 +1,83 @@
+/*
+ * aux-leds.h: Aux LED 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 AUX_LEDS_H
+#define AUX_LEDS_H
+
+#if defined(USE_INDICATOR_LED) && defined(TICK_DURING_STANDBY)
+void indicator_blink(uint8_t arg);
+#endif
+#if defined(USE_AUX_RGB_LEDS) && defined(TICK_DURING_STANDBY)
+uint8_t setting_rgb_mode_now = 0;
+void rgb_led_update(uint8_t mode, uint8_t arg);
+void rgb_led_voltage_readout(uint8_t bright);
+/*
+ * 0: R
+ * 1: RG
+ * 2: G
+ * 3: GB
+ * 4: B
+ * 5: R B
+ * 6: RGB
+ * 7: rainbow
+ * 8: voltage
+ */
+const PROGMEM uint8_t rgb_led_colors[] = {
+ 0b00000001, // 0: red
+ 0b00000101, // 1: yellow
+ 0b00000100, // 2: green
+ 0b00010100, // 3: cyan
+ 0b00010000, // 4: blue
+ 0b00010001, // 5: purple
+ 0b00010101, // 6: white
+};
+#define RGB_LED_NUM_COLORS 10
+#define RGB_LED_NUM_PATTERNS 4
+#ifndef RGB_LED_OFF_DEFAULT
+#define RGB_LED_OFF_DEFAULT 0x18 // low, voltage
+//#define RGB_LED_OFF_DEFAULT 0x17 // low, rainbow
+#endif
+#ifndef RGB_LED_LOCKOUT_DEFAULT
+#define RGB_LED_LOCKOUT_DEFAULT 0x37 // blinking, rainbow
+#endif
+#ifndef RGB_RAINBOW_SPEED
+#define RGB_RAINBOW_SPEED 0x0f // change color every 16 frames
+#endif
+uint8_t rgb_led_off_mode = RGB_LED_OFF_DEFAULT;
+uint8_t rgb_led_lockout_mode = RGB_LED_LOCKOUT_DEFAULT;
+#endif
+
+#ifdef USE_INDICATOR_LED
+ // bits 2-3 control lockout mode
+ // bits 0-1 control "off" mode
+ // modes are: 0=off, 1=low, 2=high, 3=blinking (if TICK_DURING_STANDBY enabled)
+ #ifdef INDICATOR_LED_DEFAULT_MODE
+ uint8_t indicator_led_mode = INDICATOR_LED_DEFAULT_MODE;
+ #else
+ #ifdef USE_INDICATOR_LED_WHILE_RAMPING
+ //uint8_t indicator_led_mode = (1<<2) + 2;
+ uint8_t indicator_led_mode = (2<<2) + 1;
+ #else
+ uint8_t indicator_led_mode = (3<<2) + 1;
+ #endif
+ #endif
+#endif
+
+
+#endif