aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSelene ToyKeeper2023-04-16 18:21:29 -0600
committerSelene ToyKeeper2023-04-16 18:21:29 -0600
commitfbcac59563c32f14de4861449c1b267c247b5b78 (patch)
tree3cddc0e447194d7a6432ebf3561a86208037d44e
parentadded ability to use 2 colors in config mode (diff)
downloadanduril-fbcac59563c32f14de4861449c1b267c247b5b78.tar.gz
anduril-fbcac59563c32f14de4861449c1b267c247b5b78.tar.bz2
anduril-fbcac59563c32f14de4861449c1b267c247b5b78.zip
reduced ROM by ~600 bytes by moving all eeprom config values to a "cfg" struct
(this also made some parts of the code cleaner)
Diffstat (limited to '')
-rw-r--r--hwdef-Sofirn_LT1S-Pro.c74
-rw-r--r--hwdef-Sofirn_LT1S-Pro.h2
-rw-r--r--spaghetti-monster/anduril/anduril.c8
-rw-r--r--spaghetti-monster/anduril/aux-leds.h11
-rw-r--r--spaghetti-monster/anduril/battcheck-mode.c4
-rw-r--r--spaghetti-monster/anduril/beacon-mode.c4
-rw-r--r--spaghetti-monster/anduril/beacon-mode.h3
-rw-r--r--spaghetti-monster/anduril/channel-modes.c20
-rw-r--r--spaghetti-monster/anduril/channel-modes.h5
-rw-r--r--spaghetti-monster/anduril/config-mode.c2
-rw-r--r--spaghetti-monster/anduril/factory-reset.c3
-rw-r--r--spaghetti-monster/anduril/load-save-config-fsm.h173
-rw-r--r--spaghetti-monster/anduril/load-save-config.c201
-rw-r--r--spaghetti-monster/anduril/load-save-config.h162
-rw-r--r--spaghetti-monster/anduril/lockout-mode.c48
-rw-r--r--spaghetti-monster/anduril/lockout-mode.h1
-rw-r--r--spaghetti-monster/anduril/off-mode.c60
-rw-r--r--spaghetti-monster/anduril/ramp-mode.c77
-rw-r--r--spaghetti-monster/anduril/ramp-mode.h64
-rw-r--r--spaghetti-monster/anduril/strobe-modes.c36
-rw-r--r--spaghetti-monster/anduril/strobe-modes.h7
-rw-r--r--spaghetti-monster/anduril/sunset-timer.c2
-rw-r--r--spaghetti-monster/anduril/tactical-mode.c10
-rw-r--r--spaghetti-monster/anduril/tactical-mode.h7
-rw-r--r--spaghetti-monster/anduril/tempcheck-mode.c8
-rw-r--r--spaghetti-monster/fsm-adc.c14
-rw-r--r--spaghetti-monster/fsm-adc.h22
-rw-r--r--spaghetti-monster/fsm-eeprom.h7
-rw-r--r--spaghetti-monster/fsm-ramping.c126
-rw-r--r--spaghetti-monster/fsm-ramping.h83
30 files changed, 580 insertions, 664 deletions
diff --git a/hwdef-Sofirn_LT1S-Pro.c b/hwdef-Sofirn_LT1S-Pro.c
index a6d2b8f..f617933 100644
--- a/hwdef-Sofirn_LT1S-Pro.c
+++ b/hwdef-Sofirn_LT1S-Pro.c
@@ -5,66 +5,6 @@
#pragma once
-// calculate a "tint ramp" blend between 2 channels
-// results are placed in *warm and *cool vars
-// brightness : total amount of light units to distribute
-// top : maximum allowed brightness per channel
-// blend : ratio between warm and cool (0 = warm, 128 = 50%, 255 = cool)
-void calc_2ch_blend(
- PWM_DATATYPE *warm,
- PWM_DATATYPE *cool,
- PWM_DATATYPE brightness,
- PWM_DATATYPE top,
- uint8_t blend) {
-
- #ifndef TINT_RAMPING_CORRECTION
- #define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint
- #endif
-
- // calculate actual PWM levels based on a single-channel ramp
- // and a blend value
- PWM_DATATYPE warm_PWM, cool_PWM;
- PWM_DATATYPE2 base_PWM = brightness;
-
- #if defined(TINT_RAMPING_CORRECTION) && (TINT_RAMPING_CORRECTION > 0)
- uint8_t level = actual_level - 1;
-
- // middle tints sag, so correct for that effect
- // by adding extra power which peaks at the middle tint
- // (correction is only necessary when PWM is fast)
- if (level > HALFSPEED_LEVEL) {
- base_PWM = brightness
- + ((((PWM_DATATYPE2)brightness) * TINT_RAMPING_CORRECTION / 64)
- * triangle_wave(blend) / 255);
- }
- // fade the triangle wave out when above 100% power,
- // so it won't go over 200%
- if (brightness > top) {
- base_PWM -= 2 * (
- ((brightness - top) * TINT_RAMPING_CORRECTION / 64)
- * triangle_wave(blend) / 255
- );
- }
- // guarantee no more than 200% power
- if (base_PWM > (top << 1)) { base_PWM = top << 1; }
- #endif
-
- cool_PWM = (((PWM_DATATYPE2)blend * (PWM_DATATYPE2)base_PWM) + 127) / 255;
- warm_PWM = base_PWM - cool_PWM;
- // when running at > 100% power, spill extra over to other channel
- if (cool_PWM > top) {
- warm_PWM += (cool_PWM - top);
- cool_PWM = top;
- } else if (warm_PWM > top) {
- cool_PWM += (warm_PWM - top);
- warm_PWM = top;
- }
-
- *warm = warm_PWM;
- *cool = cool_PWM;
-}
-
-
// calculate a 3-channel "auto tint" blend
// (like red -> warm white -> cool white)
// results are placed in *a, *b, and *c vars
@@ -126,7 +66,7 @@ void set_level_white_blend(uint8_t level) {
PWM_DATATYPE warm_PWM, cool_PWM;
PWM_DATATYPE brightness = PWM_GET(pwm1_levels, level);
PWM_DATATYPE top = PWM_GET(pwm_tops, level);
- uint8_t blend = channel_mode_args[channel_mode];
+ uint8_t blend = cfg.channel_mode_args[cfg.channel_mode];
calc_2ch_blend(&warm_PWM, &cool_PWM, brightness, top, blend);
@@ -166,9 +106,9 @@ void set_level_auto_3ch_blend(uint8_t level) {
// "white + red" channel mode
void set_level_red_white_blend(uint8_t level) {
// set the warm+cool white LEDs first
- channel_mode = CM_WHITE;
+ cfg.channel_mode = CM_WHITE;
set_level_white_blend(level);
- channel_mode = CM_WHITE_RED;
+ cfg.channel_mode = CM_WHITE_RED;
if (level == 0) {
RED_PWM_LVL = 0;
@@ -182,7 +122,7 @@ void set_level_red_white_blend(uint8_t level) {
// set the red LED as a ratio of the white output level
// 0 = no red
// 255 = red at 100% of white channel PWM
- uint8_t ratio = channel_mode_args[channel_mode];
+ uint8_t ratio = cfg.channel_mode_args[cfg.channel_mode];
RED_PWM_LVL = (((PWM_DATATYPE2)ratio * (PWM_DATATYPE2)vpwm) + 127) / 255;
if (! actual_level) PWM_CNT = 0; // reset phase
@@ -213,7 +153,7 @@ void gradual_tick_white_blend() {
PWM_DATATYPE warm_PWM, cool_PWM;
PWM_DATATYPE brightness = PWM_GET(pwm1_levels, gt);
PWM_DATATYPE top = PWM_GET(pwm_tops, gt);
- uint8_t blend = channel_mode_args[channel_mode];
+ uint8_t blend = cfg.channel_mode_args[cfg.channel_mode];
calc_2ch_blend(&warm_PWM, &cool_PWM, brightness, top, blend);
@@ -259,9 +199,9 @@ void gradual_tick_auto_3ch_blend() {
void gradual_tick_red_white_blend() {
// do the white blend thing...
- channel_mode = CM_WHITE;
+ cfg.channel_mode = CM_WHITE;
gradual_tick_white_blend();
- channel_mode = CM_WHITE_RED;
+ cfg.channel_mode = CM_WHITE_RED;
// ... and then update red to the closest ramp level
// (coarse red adjustments aren't visible here anyway)
set_level_red(actual_level);
diff --git a/hwdef-Sofirn_LT1S-Pro.h b/hwdef-Sofirn_LT1S-Pro.h
index 84623fd..b50ccc7 100644
--- a/hwdef-Sofirn_LT1S-Pro.h
+++ b/hwdef-Sofirn_LT1S-Pro.h
@@ -48,7 +48,7 @@ Driver pinout:
gradual_tick_red, \
gradual_tick_red_white_blend
// can use some of the common handlers
-//#define USE_CALC_2CH_BLEND
+#define USE_CALC_2CH_BLEND
//#define USE_CALC_AUTO_3CH_BLEND
// TODO: remove this as soon as it's not needed
diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c
index 07560bc..e180cc4 100644
--- a/spaghetti-monster/anduril/anduril.c
+++ b/spaghetti-monster/anduril/anduril.c
@@ -104,7 +104,6 @@
#include "off-mode.h"
#include "ramp-mode.h"
-#include "load-save-config.h"
#include "config-mode.h"
#include "aux-leds.h"
#include "misc.h"
@@ -158,6 +157,9 @@
#include "sos-mode.h"
#endif
+// this should be last, so other headers have a chance to declare values
+#include "load-save-config.h"
+
/********* Include all the app logic source files *********/
// (is a bit weird to do things this way,
@@ -239,7 +241,7 @@ void setup() {
#if defined(USE_MANUAL_MEMORY) && defined(USE_MANUAL_MEMORY_TIMER)
// without this, initial boot-up brightness is wrong
// when manual mem is enabled with a non-zero timer
- if (manual_memory) manual_memory_restore();
+ if (cfg.manual_memory) manual_memory_restore();
#endif
#if defined(USE_CHANNEL_MODES)
@@ -321,7 +323,7 @@ void loop() {
// in simple mode, turn off after one readout
// FIXME: can eat the next button press
// (state changes in loop() act weird)
- if (simple_ui_active) set_state_deferred(off_state, 0);
+ if (cfg.simple_ui_active) set_state_deferred(off_state, 0);
else nice_delay_ms(1000);
#endif
}
diff --git a/spaghetti-monster/anduril/aux-leds.h b/spaghetti-monster/anduril/aux-leds.h
index 71a14e3..f496ddc 100644
--- a/spaghetti-monster/anduril/aux-leds.h
+++ b/spaghetti-monster/anduril/aux-leds.h
@@ -61,8 +61,6 @@ const PROGMEM uint8_t rgb_led_colors[] = {
#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
//#define USE_OLD_BLINKING_INDICATOR
@@ -71,14 +69,11 @@ uint8_t rgb_led_lockout_mode = RGB_LED_LOCKOUT_DEFAULT;
// 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
+ #ifndef INDICATOR_LED_DEFAULT_MODE
#ifdef USE_INDICATOR_LED_WHILE_RAMPING
- //uint8_t indicator_led_mode = (1<<2) + 2;
- uint8_t indicator_led_mode = (2<<2) + 1;
+ #define INDICATOR_LED_DEFAULT_MODE ((2<<2) + 1)
#else
- uint8_t indicator_led_mode = (3<<2) + 1;
+ #define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 1)
#endif
#endif
#endif
diff --git a/spaghetti-monster/anduril/battcheck-mode.c b/spaghetti-monster/anduril/battcheck-mode.c
index d34559b..5edc6f4 100644
--- a/spaghetti-monster/anduril/battcheck-mode.c
+++ b/spaghetti-monster/anduril/battcheck-mode.c
@@ -25,7 +25,7 @@
uint8_t battcheck_state(Event event, uint16_t arg) {
////////// Every action below here is blocked in the simple UI //////////
#ifdef USE_SIMPLE_UI
- if (simple_ui_active) {
+ if (cfg.simple_ui_active) {
return EVENT_NOT_HANDLED;
}
#endif
@@ -69,7 +69,7 @@ uint8_t battcheck_state(Event event, uint16_t arg) {
// ...
// 13 = add 0.30V
void voltage_config_save(uint8_t step, uint8_t value) {
- if (value) voltage_correction = value;
+ if (value) cfg.voltage_correction = value;
}
uint8_t voltage_config_state(Event event, uint16_t arg) {
diff --git a/spaghetti-monster/anduril/beacon-mode.c b/spaghetti-monster/anduril/beacon-mode.c
index e8e5004..76ada0f 100644
--- a/spaghetti-monster/anduril/beacon-mode.c
+++ b/spaghetti-monster/anduril/beacon-mode.c
@@ -28,7 +28,7 @@ inline void beacon_mode_iter() {
set_level(memorized_level);
nice_delay_ms(100);
set_level(0);
- nice_delay_ms(((beacon_seconds) * 1000) - 100);
+ nice_delay_ms(((cfg.beacon_seconds) * 1000) - 100);
}
}
@@ -61,7 +61,7 @@ uint8_t beacon_state(Event event, uint16_t arg) {
}
// release hold: save new timing
else if (event == EV_click1_hold_release) {
- beacon_seconds = 1 + (arg / TICKS_PER_SECOND);
+ cfg.beacon_seconds = 1 + (arg / TICKS_PER_SECOND);
save_config();
return MISCHIEF_MANAGED;
}
diff --git a/spaghetti-monster/anduril/beacon-mode.h b/spaghetti-monster/anduril/beacon-mode.h
index 752918e..c0f0b18 100644
--- a/spaghetti-monster/anduril/beacon-mode.h
+++ b/spaghetti-monster/anduril/beacon-mode.h
@@ -20,9 +20,6 @@
#ifndef BEACON_MODE_H
#define BEACON_MODE_H
-// beacon timing
-uint8_t beacon_seconds = 2;
-
// beacon mode
uint8_t beacon_state(Event event, uint16_t arg);
inline void beacon_mode_iter();
diff --git a/spaghetti-monster/anduril/channel-modes.c b/spaghetti-monster/anduril/channel-modes.c
index 958b375..f3a21cf 100644
--- a/spaghetti-monster/anduril/channel-modes.c
+++ b/spaghetti-monster/anduril/channel-modes.c
@@ -20,7 +20,7 @@ uint8_t channel_mode_state(Event event, uint16_t arg) {
// in addition to changing state... so ignore any tint-ramp events which
// don't look like they were meant to be here
static uint8_t active = 0;
- uint8_t tint = channel_mode_args[channel_mode];
+ uint8_t tint = cfg.channel_mode_args[cfg.channel_mode];
#endif
// it's possible that a light may need 3H but not 3C,
@@ -28,7 +28,7 @@ uint8_t channel_mode_state(Event event, uint16_t arg) {
#if NUM_CHANNEL_MODES > 1
// 3 clicks: next channel mode
if (event == EV_3clicks) {
- uint8_t next = channel_mode;
+ uint8_t next = cfg.channel_mode;
// go to next channel mode until we find one which is enabled
// (and don't do any infinite loops if the user disabled them all)
uint8_t count = 0;
@@ -39,10 +39,10 @@ uint8_t channel_mode_state(Event event, uint16_t arg) {
//} while ((! channel_modes_enabled[next]) && count < NUM_CHANNEL_MODES);
// undo change if infinite loop detected (redundant?)
- //if (NUM_CHANNEL_MODES == count) next = channel_mode;
+ //if (NUM_CHANNEL_MODES == count) next = cfg.channel_mode;
// if mode hasn't changed, abort
- if (channel_mode == next)
+ if (cfg.channel_mode == next)
return EVENT_NOT_HANDLED;
set_channel_mode(next);
@@ -55,9 +55,9 @@ uint8_t channel_mode_state(Event event, uint16_t arg) {
#ifdef USE_CUSTOM_CHANNEL_3H_MODES
// defer to mode-specific function if defined
- if (tint_ramp_modes[channel_mode]) {
- StatePtr tint_func = channel_3H_modes[channel_mode];
- return tint_func(channel_mode);
+ if (tint_ramp_modes[cfg.channel_mode]) {
+ StatePtr tint_func = channel_3H_modes[cfg.channel_mode];
+ return tint_func(cfg.channel_mode);
} else
#endif
#ifdef USE_CHANNEL_MODE_ARGS
@@ -86,7 +86,7 @@ uint8_t channel_mode_state(Event event, uint16_t arg) {
past_edge_counter = 1;
}
prev_tint = tint;
- channel_mode_args[channel_mode] = tint;
+ cfg.channel_mode_args[cfg.channel_mode] = tint;
set_level(actual_level);
return EVENT_HANDLED;
}
@@ -99,7 +99,7 @@ uint8_t channel_mode_state(Event event, uint16_t arg) {
if (0 == tint) tint_ramp_direction = 1;
else if (255 == tint) tint_ramp_direction = -1;
// remember tint after battery change
- channel_mode_args[channel_mode] = tint;
+ cfg.channel_mode_args[cfg.channel_mode] = tint;
save_config();
// bug?: for some reason, brightness can seemingly change
// from 1/150 to 2/150 without this next line... not sure why
@@ -111,7 +111,7 @@ uint8_t channel_mode_state(Event event, uint16_t arg) {
#if defined(USE_SIMPLE_UI)
// remaining mappings aren't "simple", so stop here
- if (simple_ui_active) {
+ if (cfg.simple_ui_active) {
return EVENT_NOT_HANDLED;
}
#endif
diff --git a/spaghetti-monster/anduril/channel-modes.h b/spaghetti-monster/anduril/channel-modes.h
index 167c293..c10af5b 100644
--- a/spaghetti-monster/anduril/channel-modes.h
+++ b/spaghetti-monster/anduril/channel-modes.h
@@ -6,11 +6,6 @@
#pragma once
-#if defined(USE_MANUAL_MEMORY) && defined(USE_CHANNEL_MODE_ARGS)
-// remember and reset 1 extra parameter per channel mode (like tint)
-uint8_t manual_memory_channel_args[NUM_CHANNEL_MODES] = { CHANNEL_MODE_ARGS };
-#endif
-
// not actually a mode, more of a fallback under other modes
uint8_t channel_mode_state(Event event, uint16_t arg);
diff --git a/spaghetti-monster/anduril/config-mode.c b/spaghetti-monster/anduril/config-mode.c
index a74bdbe..394998a 100644
--- a/spaghetti-monster/anduril/config-mode.c
+++ b/spaghetti-monster/anduril/config-mode.c
@@ -34,7 +34,7 @@ uint8_t config_state_base(
#endif
if (event == EV_enter_state) {
#ifdef USE_CONFIG_COLORS
- orig_channel = channel_mode;
+ orig_channel = cfg.channel_mode;
#endif
config_step = 0;
set_level(0);
diff --git a/spaghetti-monster/anduril/factory-reset.c b/spaghetti-monster/anduril/factory-reset.c
index a14b5b9..1e9714a 100644
--- a/spaghetti-monster/anduril/factory-reset.c
+++ b/spaghetti-monster/anduril/factory-reset.c
@@ -8,7 +8,6 @@
// allows setting channel mode per animation stage,
// so it can ramp up in red then explode in white (as one example)
-// TODO: maybe also do the same in menus?
void factory_reset() {
// display a warning for a few seconds before doing the actual reset,
@@ -38,7 +37,7 @@ void factory_reset() {
// AVR 1-Series has factory calibrated thermal sensor, always remove the offset on reset
#if defined(USE_THERMAL_REGULATION) && defined(AVRXMEGA3)
// this will cancel out the offset
- thermal_config_save(1, temperature - therm_cal_offset);
+ thermal_config_save(1, temperature - cfg.therm_cal_offset);
#elif defined(USE_THERMAL_REGULATION) && defined(USE_THERM_AUTOCALIBRATE)
// assume current temperature is 21 C
thermal_config_save(1, 21);
diff --git a/spaghetti-monster/anduril/load-save-config-fsm.h b/spaghetti-monster/anduril/load-save-config-fsm.h
index 9004f1f..ef079db 100644
--- a/spaghetti-monster/anduril/load-save-config-fsm.h
+++ b/spaghetti-monster/anduril/load-save-config-fsm.h
@@ -1,127 +1,122 @@
-/*
- * load-save-config-fsm.h: FSM config for eeprom configuration in 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 LOAD_SAVE_CONFIG_FSM_H
-#define LOAD_SAVE_CONFIG_FSM_H
+// load-save-config-fsm.h: FSM config for eeprom configuration in Anduril.
+// Copyright (C) 2017-2023 Selene ToyKeeper
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
-// auto-detect how many eeprom bytes
#define USE_EEPROM
-typedef enum {
- ramp_style_e,
- #ifdef USE_RAMP_CONFIG
- ramp_smooth_floor_e,
- ramp_smooth_ceil_e,
- #ifdef USE_RAMP_SPEED_CONFIG
- ramp_speed_e,
+// load into a custom RAM location instead of FSM's default byte array
+#define EEPROM_OVERRIDE
+
+#ifdef USE_SIMPLE_UI
+#define NUM_RAMPS 3
+#else
+#define NUM_RAMPS 2
+#endif
+
+// let FSM know this config struct exists
+#define USE_CFG
+
+typedef struct Config {
+
+ ///// ramp vars
+ uint8_t ramp_style;
+ #ifdef USE_2C_STYLE_CONFIG
+ uint8_t ramp_2c_style;
#endif
- ramp_discrete_floor_e,
- ramp_discrete_ceil_e,
- ramp_discrete_steps_e,
+ #ifdef USE_RAMP_CONFIG
+ uint8_t ramp_floors[NUM_RAMPS];
+ uint8_t ramp_ceils [NUM_RAMPS];
+ uint8_t ramp_stepss[NUM_RAMPS];
#endif
#ifdef USE_SIMPLE_UI
- simple_ui_floor_e,
- simple_ui_ceil_e,
- simple_ui_steps_e,
- simple_ui_active_e,
- #ifdef USE_2C_STYLE_CONFIG
- ramp_2c_style_simple_e,
- #endif
+ uint8_t simple_ui_active;
+ #ifdef USE_2C_STYLE_CONFIG
+ uint8_t ramp_2c_style_simple;
+ #endif
#endif
#ifdef USE_RAMP_AFTER_MOON_CONFIG
- dont_ramp_after_moon_e,
- #endif
- #ifdef USE_2C_STYLE_CONFIG
- ramp_2c_style_e,
+ uint8_t dont_ramp_after_moon;
#endif
#ifdef USE_MANUAL_MEMORY
- manual_memory_e,
+ uint8_t manual_memory;
#ifdef USE_MANUAL_MEMORY_TIMER
- manual_memory_timer_e,
+ uint8_t manual_memory_timer;
#endif
#endif
- #ifdef USE_JUMP_START
- jump_start_level_e,
+
+ ///// channel modes / color modes
+ #if NUM_CHANNEL_MODES > 1
+ uint8_t channel_mode;
+ uint8_t channel_modes_enabled;
+ #ifdef USE_MANUAL_MEMORY
+ uint8_t manual_memory_channel_mode;
+ #endif
+ #endif
+ #ifdef USE_CHANNEL_MODE_ARGS
+ // this is an array, needs a few bytes
+ uint8_t channel_mode_args[NUM_CHANNEL_MODES];
+ #ifdef USE_MANUAL_MEMORY
+ uint8_t manual_memory_channel_args[NUM_CHANNEL_MODES];
+ #endif
#endif
+
+ ///// strobe / blinky mode settings
#ifdef USE_STROBE_STATE
- strobe_type_e,
+ uint8_t strobe_type;
#endif
#if defined(USE_PARTY_STROBE_MODE) || defined(USE_TACTICAL_STROBE_MODE)
- strobe_delays_0_e,
- strobe_delays_1_e,
+ uint8_t strobe_delays[2];
#endif
#ifdef USE_BIKE_FLASHER_MODE
- bike_flasher_brightness_e,
+ uint8_t bike_flasher_brightness;
#endif
#ifdef USE_BEACON_MODE
- beacon_seconds_e,
- #endif
- #ifdef USE_THERMAL_REGULATION
- therm_ceil_e,
- therm_cal_offset_e,
+ uint8_t beacon_seconds;
#endif
+
+ ///// voltage and temperature
#ifdef USE_VOLTAGE_CORRECTION
- voltage_correction_e,
+ uint8_t voltage_correction;
+ #endif
+ #ifdef USE_THERMAL_REGULATION
+ uint8_t therm_ceil;
+ uint8_t therm_cal_offset;
#endif
+
+ ///// aux LEDs
#ifdef USE_INDICATOR_LED
- indicator_led_mode_e,
+ uint8_t indicator_led_mode;
#endif
#ifdef USE_AUX_RGB_LEDS
- rgb_led_off_mode_e,
- rgb_led_lockout_mode_e,
+ uint8_t rgb_led_off_mode;
+ uint8_t rgb_led_lockout_mode;
#endif
+
+ ///// misc other mode settings
#ifdef USE_AUTOLOCK
- autolock_time_e,
+ uint8_t autolock_time;
#endif
#ifdef USE_TACTICAL_MODE
- tactical_lvl_1_e,
- tactical_lvl_2_e,
- tactical_lvl_3_e,
- #endif
- #if NUM_CHANNEL_MODES > 1
- channel_mode_e,
- channel_modes_enabled_e,
- #if defined(USE_MANUAL_MEMORY)
- manual_memory_channel_mode_e,
- #endif
+ uint8_t tactical_levels[3];
#endif
- #ifdef USE_CHANNEL_MODE_ARGS
- // this is an array, needs a few bytes
- channel_mode_args_e,
- #if defined(USE_MANUAL_MEMORY)
- // this is an array, needs a few bytes
- manual_memory_channel_args_e = channel_mode_args_e + NUM_CHANNEL_MODES,
- // and this is an ugly ugly kludge
- // FIXME: use a struct for eeprom, not an array
- eeprom_indexes_e_END = manual_memory_channel_args_e + NUM_CHANNEL_MODES
- #else
- eeprom_indexes_e_END = channel_mode_args_e + NUM_CHANNEL_MODES
- #endif
- #else
- eeprom_indexes_e_END
+
+ ///// hardware config / globals menu
+ #ifdef USE_JUMP_START
+ uint8_t jump_start_level;
#endif
-} eeprom_indexes_e;
-#define EEPROM_BYTES eeprom_indexes_e_END
+
+} Config;
+
+// auto-detect how many eeprom bytes
+#define EEPROM_BYTES sizeof(Config)
+
+// declare this so FSM can see it,
+// but define its values in a file which loads later
+Config cfg;
#ifdef START_AT_MEMORIZED_LEVEL
#define USE_EEPROM_WL
#define EEPROM_WL_BYTES 1
#endif
-
-#endif
diff --git a/spaghetti-monster/anduril/load-save-config.c b/spaghetti-monster/anduril/load-save-config.c
index ad84450..aa772e1 100644
--- a/spaghetti-monster/anduril/load-save-config.c
+++ b/spaghetti-monster/anduril/load-save-config.c
@@ -1,114 +1,17 @@
-/*
- * load-save-config.c: Load/save/eeprom 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/>.
- */
+// load-save-config.c: Load/save/eeprom functions for Anduril.
+// Copyright (C) 2017-2023 Selene ToyKeeper
+// SPDX-License-Identifier: GPL-3.0-or-later
-#ifndef LOAD_SAVE_CONFIG_C
-#define LOAD_SAVE_CONFIG_C
+#pragma once
#include "load-save-config-fsm.h"
#include "load-save-config.h"
void load_config() {
- if (load_eeprom()) {
- ramp_style = eeprom[ramp_style_e];
- #ifdef USE_RAMP_CONFIG
- ramp_floors[0] = eeprom[ramp_smooth_floor_e];
- ramp_ceils[0] = eeprom[ramp_smooth_ceil_e];
- #ifdef USE_RAMP_SPEED_CONFIG
- ramp_speed = eeprom[ramp_speed_e];
- #endif
- ramp_floors[1] = eeprom[ramp_discrete_floor_e];
- ramp_ceils[1] = eeprom[ramp_discrete_ceil_e];
- ramp_stepss[1] = eeprom[ramp_discrete_steps_e];
- #endif
- #ifdef USE_SIMPLE_UI
- ramp_floors[2] = eeprom[simple_ui_floor_e];
- ramp_ceils[2] = eeprom[simple_ui_ceil_e];
- ramp_stepss[2] = eeprom[simple_ui_steps_e];
- simple_ui_active = eeprom[simple_ui_active_e];
- #ifdef USE_2C_STYLE_CONFIG
- ramp_2c_style_simple = eeprom[ramp_2c_style_simple_e];
- #endif
- #endif
- #ifdef USE_RAMP_AFTER_MOON_CONFIG
- dont_ramp_after_moon = eeprom[dont_ramp_after_moon_e];
- #endif
- #ifdef USE_2C_STYLE_CONFIG
- ramp_2c_style = eeprom[ramp_2c_style_e];
- #endif
- #ifdef USE_MANUAL_MEMORY
- manual_memory = eeprom[manual_memory_e];
- #ifdef USE_MANUAL_MEMORY_TIMER
- manual_memory_timer = eeprom[manual_memory_timer_e];
- #endif
- #endif
- #ifdef USE_JUMP_START
- jump_start_level = eeprom[jump_start_level_e],
- #endif
- #if defined(USE_PARTY_STROBE_MODE) || defined(USE_TACTICAL_STROBE_MODE)
- strobe_type = eeprom[strobe_type_e]; // TODO: move this to eeprom_wl?
- strobe_delays[0] = eeprom[strobe_delays_0_e];
- strobe_delays[1] = eeprom[strobe_delays_1_e];
- #endif
- #ifdef USE_BIKE_FLASHER_MODE
- bike_flasher_brightness = eeprom[bike_flasher_brightness_e];
- #endif
- #ifdef USE_BEACON_MODE
- beacon_seconds = eeprom[beacon_seconds_e];
- #endif
- #ifdef USE_THERMAL_REGULATION
- therm_ceil = eeprom[therm_ceil_e];
- therm_cal_offset = eeprom[therm_cal_offset_e];
- #endif
- #ifdef USE_VOLTAGE_CORRECTION
- voltage_correction = eeprom[voltage_correction_e];
- #endif
- #ifdef USE_INDICATOR_LED
- indicator_led_mode = eeprom[indicator_led_mode_e];
- #endif
- #ifdef USE_AUX_RGB_LEDS
- rgb_led_off_mode = eeprom[rgb_led_off_mode_e];
- rgb_led_lockout_mode = eeprom[rgb_led_lockout_mode_e];
- #endif
- #ifdef USE_AUTOLOCK
- autolock_time = eeprom[autolock_time_e];
- #endif
- #ifdef USE_TACTICAL_MODE
- tactical_levels[0] = eeprom[tactical_lvl_1_e];
- tactical_levels[1] = eeprom[tactical_lvl_2_e];
- tactical_levels[2] = eeprom[tactical_lvl_3_e];
- #endif
- #if NUM_CHANNEL_MODES > 1
- channel_mode = eeprom[channel_mode_e];
- channel_modes_enabled = eeprom[channel_modes_enabled_e];
- #if defined(USE_MANUAL_MEMORY)
- manual_memory_channel_mode = eeprom[manual_memory_channel_mode_e];
- #endif
- #endif
- #ifdef USE_CHANNEL_MODE_ARGS
- for (uint8_t i=0; i<NUM_CHANNEL_MODES; i++)
- channel_mode_args[i] = eeprom[i + channel_mode_args_e];
- #if defined(USE_MANUAL_MEMORY)
- for (uint8_t i=0; i<NUM_CHANNEL_MODES; i++)
- manual_memory_channel_args[i] = eeprom[i + manual_memory_channel_args_e];
- #endif
- #endif
- }
+ eeprom = (uint8_t *)&cfg;
+
+ if (! load_eeprom()) return;
+
#ifdef START_AT_MEMORIZED_LEVEL
if (load_eeprom_wl()) {
memorized_level = eeprom_wl[0];
@@ -117,90 +20,7 @@ void load_config() {
}
void save_config() {
- eeprom[ramp_style_e] = ramp_style;
- #ifdef USE_RAMP_CONFIG
- eeprom[ramp_smooth_floor_e] = ramp_floors[0];
- eeprom[ramp_smooth_ceil_e] = ramp_ceils[0];
- #ifdef USE_RAMP_SPEED_CONFIG
- eeprom[ramp_speed_e] = ramp_speed;
- #endif
- eeprom[ramp_discrete_floor_e] = ramp_floors[1];
- eeprom[ramp_discrete_ceil_e] = ramp_ceils[1];
- eeprom[ramp_discrete_steps_e] = ramp_stepss[1];
- #endif
- #ifdef USE_SIMPLE_UI
- eeprom[simple_ui_floor_e] = ramp_floors[2];
- eeprom[simple_ui_ceil_e] = ramp_ceils[2];
- eeprom[simple_ui_steps_e] = ramp_stepss[2];
- eeprom[simple_ui_active_e] = simple_ui_active;
- #ifdef USE_2C_STYLE_CONFIG
- eeprom[ramp_2c_style_simple_e] = ramp_2c_style_simple;
- #endif
- #endif
- #ifdef USE_RAMP_AFTER_MOON_CONFIG
- eeprom[dont_ramp_after_moon_e] = dont_ramp_after_moon;
- #endif
- #ifdef USE_2C_STYLE_CONFIG
- eeprom[ramp_2c_style_e] = ramp_2c_style;
- #endif
- #ifdef USE_MANUAL_MEMORY
- eeprom[manual_memory_e] = manual_memory;
- #ifdef USE_MANUAL_MEMORY_TIMER
- eeprom[manual_memory_timer_e] = manual_memory_timer;
- #endif
- #endif
- #ifdef USE_JUMP_START
- eeprom[jump_start_level_e] = jump_start_level,
- #endif
- #if defined(USE_PARTY_STROBE_MODE) || defined(USE_TACTICAL_STROBE_MODE)
- eeprom[strobe_type_e] = strobe_type; // TODO: move this to eeprom_wl?
- eeprom[strobe_delays_0_e] = strobe_delays[0];
- eeprom[strobe_delays_1_e] = strobe_delays[1];
- #endif
- #ifdef USE_BIKE_FLASHER_MODE
- eeprom[bike_flasher_brightness_e] = bike_flasher_brightness;
- #endif
- #ifdef USE_BEACON_MODE
- eeprom[beacon_seconds_e] = beacon_seconds;
- #endif
- #ifdef USE_THERMAL_REGULATION
- eeprom[therm_ceil_e] = therm_ceil;
- eeprom[therm_cal_offset_e] = therm_cal_offset;
- #endif
- #ifdef USE_VOLTAGE_CORRECTION
- eeprom[voltage_correction_e] = voltage_correction;
- #endif
- #ifdef USE_INDICATOR_LED
- eeprom[indicator_led_mode_e] = indicator_led_mode;
- #endif
- #ifdef USE_AUX_RGB_LEDS
- eeprom[rgb_led_off_mode_e] = rgb_led_off_mode;
- eeprom[rgb_led_lockout_mode_e] = rgb_led_lockout_mode;
- #endif
- #ifdef USE_AUTOLOCK
- eeprom[autolock_time_e] = autolock_time;
- #endif
- #ifdef USE_TACTICAL_MODE
- eeprom[tactical_lvl_1_e] = tactical_levels[0];
- eeprom[tactical_lvl_2_e] = tactical_levels[1];
- eeprom[tactical_lvl_3_e] = tactical_levels[2];
- #endif
- #if NUM_CHANNEL_MODES > 1
- eeprom[channel_mode_e] = channel_mode;
- eeprom[channel_modes_enabled_e] = channel_modes_enabled;
- #if defined(USE_MANUAL_MEMORY)
- eeprom[manual_memory_channel_mode_e] = manual_memory_channel_mode;
- #endif
- #endif
- #ifdef USE_CHANNEL_MODE_ARGS
- for (uint8_t i=0; i<NUM_CHANNEL_MODES; i++)
- eeprom[i + channel_mode_args_e] = channel_mode_args[i];
- #if defined(USE_MANUAL_MEMORY)
- for (uint8_t i=0; i<NUM_CHANNEL_MODES; i++)
- eeprom[i + manual_memory_channel_args_e] = manual_memory_channel_args[i];
- #endif
- #endif
-
+ eeprom = (uint8_t *)&cfg;
save_eeprom();
}
@@ -211,6 +31,3 @@ void save_config_wl() {
}
#endif
-
-#endif
-
diff --git a/spaghetti-monster/anduril/load-save-config.h b/spaghetti-monster/anduril/load-save-config.h
index 29c1a69..9fe24c7 100644
--- a/spaghetti-monster/anduril/load-save-config.h
+++ b/spaghetti-monster/anduril/load-save-config.h
@@ -1,24 +1,8 @@
-/*
- * load-save-config.h: Load/save/eeprom 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 LOAD_SAVE_CONFIG_H
-#define LOAD_SAVE_CONFIG_H
+// load-save-config.h: Load/save/eeprom functions for Anduril.
+// Copyright (C) 2017-2023 Selene ToyKeeper
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
// remember stuff even after battery was changed
void load_config();
@@ -27,5 +11,139 @@ void save_config();
void save_config_wl();
#endif
+// a struct to hold config values
+Config cfg = {
+
+ ///// ramp vars
+
+ // smooth vs discrete ramping
+ .ramp_style = RAMP_STYLE, // 0 = smooth, 1 = discrete
+ #ifdef USE_2C_STYLE_CONFIG
+ // 1 = A1 style, 2 = A2 style
+ .ramp_2c_style = DEFAULT_2C_STYLE,
+ #endif
+
+ // settings for each ramp (smooth, stepped, simple UI)
+ #ifdef USE_RAMP_CONFIG
+ .ramp_floors = {
+ RAMP_SMOOTH_FLOOR,
+ RAMP_DISCRETE_FLOOR,
+ #ifdef USE_SIMPLE_UI
+ SIMPLE_UI_FLOOR,
+ #endif
+ },
+ .ramp_ceils = {
+ RAMP_SMOOTH_CEIL,
+ RAMP_DISCRETE_CEIL,
+ #ifdef USE_SIMPLE_UI
+ SIMPLE_UI_CEIL,
+ #endif
+ },
+ .ramp_stepss = {
+ DEFAULT_RAMP_SPEED,
+ RAMP_DISCRETE_STEPS,
+ #ifdef USE_SIMPLE_UI
+ SIMPLE_UI_STEPS,
+ #endif
+ },
+ #endif
+
+ #ifdef USE_SIMPLE_UI
+ // whether to enable the simplified interface or not
+ .simple_ui_active = SIMPLE_UI_ACTIVE,
+ #ifdef USE_2C_STYLE_CONFIG
+ // 0 = no turbo, 1 = A1 style, 2 = A2 style
+ .ramp_2c_style_simple = DEFAULT_2C_STYLE_SIMPLE,
+ #endif
+ #endif
+
+ .dont_ramp_after_moon = DEFAULT_DONT_RAMP_AFTER_MOON,
+
+ #ifdef USE_MANUAL_MEMORY
+ .manual_memory = DEFAULT_MANUAL_MEMORY,
+ #ifdef USE_MANUAL_MEMORY_TIMER
+ .manual_memory_timer = DEFAULT_MANUAL_MEMORY_TIMER,
+ #endif
+ #endif
+
+ ///// channel modes / color modes
+
+ #if NUM_CHANNEL_MODES > 1
+ // current multi-channel mode
+ .channel_mode = DEFAULT_CHANNEL_MODE,
+ // user can take unwanted modes out of the rotation (bitmask)
+ .channel_modes_enabled = CHANNEL_MODES_ENABLED,
+ #ifdef USE_MANUAL_MEMORY
+ // reset w/ manual memory
+ .manual_memory_channel_mode = DEFAULT_CHANNEL_MODE,
+ #endif
+ #endif
+ #ifdef USE_CHANNEL_MODE_ARGS
+ // one byte of extra data per channel mode, like for tint value
+ .channel_mode_args = { CHANNEL_MODE_ARGS },
+ #ifdef USE_MANUAL_MEMORY
+ // remember and reset 1 extra parameter per channel mode (like tint)
+ .manual_memory_channel_args = { CHANNEL_MODE_ARGS },
+ #endif
+ #endif
+
+ ///// strobe / blinky mode settings
+
+ #ifdef USE_STROBE_STATE
+ .strobe_type = DEFAULT_STROBE,
+ #endif
+ #if defined(USE_PARTY_STROBE_MODE) || defined(USE_TACTICAL_STROBE_MODE)
+ // party / tactical strobe timing
+ // party strobe 24 Hz, tactical strobe 10 Hz
+ .strobe_delays = { 41, 67 },
+ #endif
+ #ifdef USE_BIKE_FLASHER_MODE
+ .bike_flasher_brightness = MAX_1x7135,
+ #endif
+ #ifdef USE_BEACON_MODE
+ // beacon timing
+ .beacon_seconds = 2,
+ #endif
+
+ ///// voltage and temperature
+
+ #ifdef USE_VOLTAGE_CORRECTION
+ // same 0.05V units as fudge factor,
+ // but 7 is neutral, and the expected range is from 1 to 13
+ .voltage_correction = 7,
+ #endif
+ #ifdef USE_THERMAL_REGULATION
+ .therm_ceil = DEFAULT_THERM_CEIL,
+ .therm_cal_offset = 0,
+ #endif
+
+ ///// aux LEDs
+
+ #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)
+ .indicator_led_mode = INDICATOR_LED_DEFAULT_MODE,
+ #endif
+ #ifdef USE_AUX_RGB_LEDS
+ .rgb_led_off_mode = RGB_LED_OFF_DEFAULT,
+ .rgb_led_lockout_mode = RGB_LED_LOCKOUT_DEFAULT,
+ #endif
+
+ ///// misc other mode settings
+
+ #ifdef USE_AUTOLOCK
+ .autolock_time = DEFAULT_AUTOLOCK_TIME,
+ #endif
+ #ifdef USE_TACTICAL_MODE
+ .tactical_levels = { TACTICAL_LEVELS },
+ #endif
+
+ ///// hardware config / globals menu
+
+ #ifdef USE_JUMP_START
+ .jump_start_level = DEFAULT_JUMP_START_LEVEL,
+ #endif
+
+};
-#endif
diff --git a/spaghetti-monster/anduril/lockout-mode.c b/spaghetti-monster/anduril/lockout-mode.c
index 4997f29..3bf7ce0 100644
--- a/spaghetti-monster/anduril/lockout-mode.c
+++ b/spaghetti-monster/anduril/lockout-mode.c
@@ -33,14 +33,14 @@ uint8_t lockout_state(Event event, uint16_t arg) {
if ((event & (B_CLICK | B_PRESS)) == (B_CLICK | B_PRESS)) {
// hold: lowest floor
// click, hold: highest floor (or manual mem level)
- uint8_t lvl = ramp_floors[0];
+ uint8_t lvl = cfg.ramp_floors[0];
if ((event & 0x0f) == 2) { // second click
- if (ramp_floors[1] > lvl) lvl = ramp_floors[1];
+ if (cfg.ramp_floors[1] > lvl) lvl = cfg.ramp_floors[1];
#ifdef USE_MANUAL_MEMORY
- if (manual_memory) lvl = manual_memory;
+ if (cfg.manual_memory) lvl = cfg.manual_memory;
#endif
} else { // anything except second click
- if (ramp_floors[1] < lvl) lvl = ramp_floors[1];
+ if (cfg.ramp_floors[1] < lvl) lvl = cfg.ramp_floors[1];
}
set_level(lvl);
}
@@ -58,11 +58,11 @@ uint8_t lockout_state(Event event, uint16_t arg) {
#ifdef USE_INDICATOR_LED
// redundant, sleep tick does the same thing
//if (event == EV_enter_state) {
- // indicator_led_update(indicator_led_mode >> 2, 0);
+ // indicator_led_update(cfg.indicator_led_mode >> 2, 0);
//} else
#elif defined(USE_AUX_RGB_LEDS)
if (event == EV_enter_state) {
- rgb_led_update(rgb_led_lockout_mode, 0);
+ rgb_led_update(cfg.rgb_led_lockout_mode, 0);
} else
#endif
@@ -71,9 +71,9 @@ uint8_t lockout_state(Event event, uint16_t arg) {
go_to_standby = 1;
#ifdef USE_INDICATOR_LED
// redundant, sleep tick does the same thing
- //indicator_led_update(indicator_led_mode >> 2, arg);
+ //indicator_led_update(cfg.indicator_led_mode >> 2, arg);
#elif defined(USE_AUX_RGB_LEDS)
- rgb_led_update(rgb_led_lockout_mode, arg);
+ rgb_led_update(cfg.rgb_led_lockout_mode, arg);
#endif
}
return MISCHIEF_MANAGED;
@@ -82,9 +82,9 @@ uint8_t lockout_state(Event event, uint16_t arg) {
#if defined(TICK_DURING_STANDBY) && (defined(USE_INDICATOR_LED) || defined(USE_AUX_RGB_LEDS))
else if (event == EV_sleep_tick) {
#if defined(USE_INDICATOR_LED)
- indicator_led_update(indicator_led_mode >> 2, arg);
+ indicator_led_update(cfg.indicator_led_mode >> 2, arg);
#elif defined(USE_AUX_RGB_LEDS)
- rgb_led_update(rgb_led_lockout_mode, arg);
+ rgb_led_update(cfg.rgb_led_lockout_mode, arg);
#endif
return MISCHIEF_MANAGED;
}
@@ -101,8 +101,8 @@ uint8_t lockout_state(Event event, uint16_t arg) {
else if (event == EV_4clicks) {
#ifdef USE_MANUAL_MEMORY
// FIXME: memory timer is totally ignored
- if (manual_memory)
- set_state(steady_state, manual_memory);
+ if (cfg.manual_memory)
+ set_state(steady_state, cfg.manual_memory);
else
#endif
set_state(steady_state, memorized_level);
@@ -129,7 +129,7 @@ uint8_t lockout_state(Event event, uint16_t arg) {
////////// Every action below here is blocked in the (non-Extended) Simple UI //////////
#if defined(USE_SIMPLE_UI) && !defined(USE_EXTENDED_SIMPLE_UI)
- if (simple_ui_active) {
+ if (cfg.simple_ui_active) {
return EVENT_NOT_HANDLED;
}
#endif // if simple UI but not extended simple UI
@@ -138,7 +138,7 @@ uint8_t lockout_state(Event event, uint16_t arg) {
// 7 clicks: rotate through indicator LED modes (lockout mode)
else if (event == EV_7clicks) {
#if defined(USE_INDICATOR_LED)
- uint8_t mode = indicator_led_mode >> 2;
+ uint8_t mode = cfg.indicator_led_mode >> 2;
#ifdef TICK_DURING_STANDBY
mode = (mode + 1) & 3;
#else
@@ -147,9 +147,9 @@ uint8_t lockout_state(Event event, uint16_t arg) {
#ifdef INDICATOR_LED_SKIP_LOW
if (mode == 1) { mode ++; }
#endif
- indicator_led_mode = (mode << 2) + (indicator_led_mode & 0x03);
+ cfg.indicator_led_mode = (mode << 2) + (cfg.indicator_led_mode & 0x03);
// redundant, sleep tick does the same thing
- //indicator_led_update(indicator_led_mode >> 2, arg);
+ //indicator_led_update(cfg.indicator_led_mode >> 2, arg);
#elif defined(USE_AUX_RGB_LEDS)
#endif
save_config();
@@ -158,10 +158,10 @@ uint8_t lockout_state(Event event, uint16_t arg) {
#elif defined(USE_AUX_RGB_LEDS)
// 7 clicks: change RGB aux LED pattern
else if (event == EV_7clicks) {
- uint8_t mode = (rgb_led_lockout_mode >> 4) + 1;
+ uint8_t mode = (cfg.rgb_led_lockout_mode >> 4) + 1;
mode = mode % RGB_LED_NUM_PATTERNS;
- rgb_led_lockout_mode = (mode << 4) | (rgb_led_lockout_mode & 0x0f);
- rgb_led_update(rgb_led_lockout_mode, 0);
+ cfg.rgb_led_lockout_mode = (mode << 4) | (cfg.rgb_led_lockout_mode & 0x0f);
+ rgb_led_update(cfg.rgb_led_lockout_mode, 0);
save_config();
blink_once();
return MISCHIEF_MANAGED;
@@ -170,12 +170,12 @@ uint8_t lockout_state(Event event, uint16_t arg) {
else if (event == EV_click7_hold) {
setting_rgb_mode_now = 1;
if (0 == (arg & 0x3f)) {
- uint8_t mode = (rgb_led_lockout_mode & 0x0f) + 1;
+ uint8_t mode = (cfg.rgb_led_lockout_mode & 0x0f) + 1;
mode = mode % RGB_LED_NUM_COLORS;
- rgb_led_lockout_mode = mode | (rgb_led_lockout_mode & 0xf0);
+ cfg.rgb_led_lockout_mode = mode | (cfg.rgb_led_lockout_mode & 0xf0);
//save_config();
}
- rgb_led_update(rgb_led_lockout_mode, arg);
+ rgb_led_update(cfg.rgb_led_lockout_mode, arg);
return MISCHIEF_MANAGED;
}
// 7H, release: save new color
@@ -188,7 +188,7 @@ uint8_t lockout_state(Event event, uint16_t arg) {
#if defined(USE_EXTENDED_SIMPLE_UI) && defined(USE_SIMPLE_UI)
////////// Every action below here is blocked in the Extended Simple UI //////////
- if (simple_ui_active) {
+ if (cfg.simple_ui_active) {
return EVENT_NOT_HANDLED;
}
#endif // if extended simple UI
@@ -207,7 +207,7 @@ uint8_t lockout_state(Event event, uint16_t arg) {
#ifdef USE_AUTOLOCK
// set the auto-lock timer to N minutes, where N is the number of clicks
void autolock_config_save(uint8_t step, uint8_t value) {
- autolock_time = value;
+ cfg.autolock_time = value;
}
uint8_t autolock_config_state(Event event, uint16_t arg) {
diff --git a/spaghetti-monster/anduril/lockout-mode.h b/spaghetti-monster/anduril/lockout-mode.h
index 1c9c081..37b02ab 100644
--- a/spaghetti-monster/anduril/lockout-mode.h
+++ b/spaghetti-monster/anduril/lockout-mode.h
@@ -27,7 +27,6 @@ uint8_t lockout_state(Event event, uint16_t arg);
#ifndef DEFAULT_AUTOLOCK_TIME
#define DEFAULT_AUTOLOCK_TIME 0 // autolock time in minutes, 0 = disabled
#endif
-uint8_t autolock_time = DEFAULT_AUTOLOCK_TIME;
uint8_t autolock_config_state(Event event, uint16_t arg);
#endif
diff --git a/spaghetti-monster/anduril/off-mode.c b/spaghetti-monster/anduril/off-mode.c
index c459979..d9ab5cb 100644
--- a/spaghetti-monster/anduril/off-mode.c
+++ b/spaghetti-monster/anduril/off-mode.c
@@ -33,9 +33,9 @@ uint8_t off_state(Event event, uint16_t arg) {
set_level(0);
#ifdef USE_INDICATOR_LED
// redundant, sleep tick does the same thing
- //indicator_led_update(indicator_led_mode & 0x03, 0);
+ //indicator_led_update(cfg.indicator_led_mode & 0x03, 0);
#elif defined(USE_AUX_RGB_LEDS)
- rgb_led_update(rgb_led_off_mode, 0);
+ rgb_led_update(cfg.rgb_led_off_mode, 0);
#endif
#ifdef USE_SUNSET_TIMER
sunset_timer = 0; // needs a reset in case previous timer was aborted
@@ -52,9 +52,9 @@ uint8_t off_state(Event event, uint16_t arg) {
go_to_standby = 1;
#ifdef USE_INDICATOR_LED
// redundant, sleep tick does the same thing
- //indicator_led_update(indicator_led_mode & 0x03, arg);
+ //indicator_led_update(cfg.indicator_led_mode & 0x03, arg);
#elif defined(USE_AUX_RGB_LEDS)
- rgb_led_update(rgb_led_off_mode, arg);
+ rgb_led_update(cfg.rgb_led_off_mode, arg);
#endif
}
return MISCHIEF_MANAGED;
@@ -65,21 +65,21 @@ uint8_t off_state(Event event, uint16_t arg) {
else if (event == EV_sleep_tick) {
#ifdef USE_MANUAL_MEMORY_TIMER
// reset to manual memory level when timer expires
- if (manual_memory &&
- (arg >= (manual_memory_timer * SLEEP_TICKS_PER_MINUTE))) {
+ if (cfg.manual_memory &&
+ (arg >= (cfg.manual_memory_timer * SLEEP_TICKS_PER_MINUTE))) {
manual_memory_restore();
}
#endif
#ifdef USE_INDICATOR_LED
- indicator_led_update(indicator_led_mode & 0x03, arg);
+ indicator_led_update(cfg.indicator_led_mode & 0x03, arg);
#elif defined(USE_AUX_RGB_LEDS)
- rgb_led_update(rgb_led_off_mode, arg);
+ rgb_led_update(cfg.rgb_led_off_mode, arg);
#endif
#ifdef USE_AUTOLOCK
// lock the light after being off for N minutes
- uint16_t ticks = autolock_time * SLEEP_TICKS_PER_MINUTE;
- if ((autolock_time > 0) && (arg > ticks)) {
+ uint16_t ticks = cfg.autolock_time * SLEEP_TICKS_PER_MINUTE;
+ if ((cfg.autolock_time > 0) && (arg > ticks)) {
set_state(lockout_state, 0);
}
#endif // ifdef USE_AUTOLOCK
@@ -108,14 +108,14 @@ uint8_t off_state(Event event, uint16_t arg) {
set_level(nearest_level(1));
#endif
#ifdef USE_RAMP_AFTER_MOON_CONFIG
- if (dont_ramp_after_moon) {
+ if (cfg.dont_ramp_after_moon) {
return MISCHIEF_MANAGED;
}
#endif
// don't start ramping immediately;
// give the user time to release at moon level
//if (arg >= HOLD_TIMEOUT) { // smaller
- if (arg >= (!ramp_style) * HOLD_TIMEOUT) { // more consistent
+ if (arg >= (!cfg.ramp_style) * HOLD_TIMEOUT) { // more consistent
set_state(steady_state, 1);
}
return MISCHIEF_MANAGED;
@@ -133,7 +133,7 @@ uint8_t off_state(Event event, uint16_t arg) {
#if defined(USE_MANUAL_MEMORY) && !defined(USE_MANUAL_MEMORY_TIMER)
// this clause probably isn't used by any configs any more
// but is included just in case someone configures it this way
- if (manual_memory) {
+ if (cfg.manual_memory) {
manual_memory_restore();
}
#endif
@@ -160,10 +160,10 @@ uint8_t off_state(Event event, uint16_t arg) {
uint8_t turbo_level; // how bright is "turbo"?
#if defined(USE_2C_STYLE_CONFIG) // user can choose 2C behavior
- uint8_t style_2c = ramp_2c_style;
+ uint8_t style_2c = cfg.ramp_2c_style;
#ifdef USE_SIMPLE_UI
// simple UI has its own turbo config
- if (simple_ui_active) style_2c = ramp_2c_style_simple;
+ if (cfg.simple_ui_active) style_2c = cfg.ramp_2c_style_simple;
#endif
// 0 = ceiling
// 1+ = full power
@@ -173,7 +173,7 @@ uint8_t off_state(Event event, uint16_t arg) {
// simple UI: ceiling
// full UI: full power
#ifdef USE_SIMPLE_UI
- if (simple_ui_active) turbo_level = nearest_level(MAX_LEVEL);
+ if (cfg.simple_ui_active) turbo_level = nearest_level(MAX_LEVEL);
else
#endif
turbo_level = MAX_LEVEL;
@@ -235,9 +235,9 @@ uint8_t off_state(Event event, uint16_t arg) {
#ifdef USE_SIMPLE_UI
// 10 clicks, but hold last click: turn simple UI off (or configure it)
else if ((event == EV_click10_hold) && (!arg)) {
- if (simple_ui_active) { // turn off simple UI
+ if (cfg.simple_ui_active) { // turn off simple UI
blink_once();
- simple_ui_active = 0;
+ cfg.simple_ui_active = 0;
save_config();
}
else { // configure simple UI ramp
@@ -249,7 +249,7 @@ uint8_t off_state(Event event, uint16_t arg) {
////////// Every action below here is blocked in the (non-Extended) Simple UI //////////
#ifndef USE_EXTENDED_SIMPLE_UI
- if (simple_ui_active) {
+ if (cfg.simple_ui_active) {
return EVENT_NOT_HANDLED;
}
#endif // ifndef USE_EXTENDED_SIMPLE_UI
@@ -271,7 +271,7 @@ uint8_t off_state(Event event, uint16_t arg) {
#ifdef USE_INDICATOR_LED
// 7 clicks: change indicator LED mode
else if (event == EV_7clicks) {
- uint8_t mode = (indicator_led_mode & 3) + 1;
+ uint8_t mode = (cfg.indicator_led_mode & 3) + 1;
#ifdef TICK_DURING_STANDBY
mode = mode & 3;
#else
@@ -280,19 +280,19 @@ uint8_t off_state(Event event, uint16_t arg) {
#ifdef INDICATOR_LED_SKIP_LOW
if (mode == 1) { mode ++; }
#endif
- indicator_led_mode = (indicator_led_mode & 0b11111100) | mode;
+ cfg.indicator_led_mode = (cfg.indicator_led_mode & 0b11111100) | mode;
// redundant, sleep tick does the same thing
- //indicator_led_update(indicator_led_mode & 0x03, arg);
+ //indicator_led_update(cfg.indicator_led_mode & 0x03, arg);
save_config();
return MISCHIEF_MANAGED;
}
#elif defined(USE_AUX_RGB_LEDS)
// 7 clicks: change RGB aux LED pattern
else if (event == EV_7clicks) {
- uint8_t mode = (rgb_led_off_mode >> 4) + 1;
+ uint8_t mode = (cfg.rgb_led_off_mode >> 4) + 1;
mode = mode % RGB_LED_NUM_PATTERNS;
- rgb_led_off_mode = (mode << 4) | (rgb_led_off_mode & 0x0f);
- rgb_led_update(rgb_led_off_mode, 0);
+ cfg.rgb_led_off_mode = (mode << 4) | (cfg.rgb_led_off_mode & 0x0f);
+ rgb_led_update(cfg.rgb_led_off_mode, 0);
save_config();
blink_once();
return MISCHIEF_MANAGED;
@@ -301,12 +301,12 @@ uint8_t off_state(Event event, uint16_t arg) {
else if (event == EV_click7_hold) {
setting_rgb_mode_now = 1;
if (0 == (arg & 0x3f)) {
- uint8_t mode = (rgb_led_off_mode & 0x0f) + 1;
+ uint8_t mode = (cfg.rgb_led_off_mode & 0x0f) + 1;
mode = mode % RGB_LED_NUM_COLORS;
- rgb_led_off_mode = mode | (rgb_led_off_mode & 0xf0);
+ cfg.rgb_led_off_mode = mode | (cfg.rgb_led_off_mode & 0xf0);
//save_config();
}
- rgb_led_update(rgb_led_off_mode, arg);
+ rgb_led_update(cfg.rgb_led_off_mode, arg);
return MISCHIEF_MANAGED;
}
else if (event == EV_click7_hold_release) {
@@ -320,7 +320,7 @@ uint8_t off_state(Event event, uint16_t arg) {
#ifdef USE_SIMPLE_UI
#ifdef USE_EXTENDED_SIMPLE_UI
- if (simple_ui_active) {
+ if (cfg.simple_ui_active) {
return EVENT_NOT_HANDLED;
}
#endif // ifdef USE_EXTENDED_SIMPLE_UI
@@ -328,7 +328,7 @@ uint8_t off_state(Event event, uint16_t arg) {
// 10 clicks: enable simple UI
else if (event == EV_10clicks) {
blink_once();
- simple_ui_active = 1;
+ cfg.simple_ui_active = 1;
save_config();
return MISCHIEF_MANAGED;
}
diff --git a/spaghetti-monster/anduril/ramp-mode.c b/spaghetti-monster/anduril/ramp-mode.c
index a87e9b0..88b141e 100644
--- a/spaghetti-monster/anduril/ramp-mode.c
+++ b/spaghetti-monster/anduril/ramp-mode.c
@@ -27,16 +27,16 @@ uint8_t steady_state(Event event, uint16_t arg) {
uint8_t mode_min = ramp_floor;
uint8_t mode_max = ramp_ceil;
uint8_t step_size;
- if (ramp_style) { step_size = ramp_discrete_step_size; }
+ if (cfg.ramp_style) { step_size = ramp_discrete_step_size; }
else { step_size = 1; }
// how bright is "turbo"?
uint8_t turbo_level;
#if defined(USE_2C_STYLE_CONFIG) // user can choose 2C behavior
- uint8_t style_2c = ramp_2c_style;
+ uint8_t style_2c = cfg.ramp_2c_style;
#ifdef USE_SIMPLE_UI
// simple UI has its own turbo config
- if (simple_ui_active) style_2c = ramp_2c_style_simple;
+ if (cfg.simple_ui_active) style_2c = cfg.ramp_2c_style_simple;
#endif
// 0 = no turbo
// 1 = Anduril 1 direct to turbo
@@ -51,7 +51,7 @@ uint8_t steady_state(Event event, uint16_t arg) {
// simple UI: to/from ceiling
// full UI: to/from turbo (Anduril1 behavior)
#ifdef USE_SIMPLE_UI
- if (simple_ui_active) turbo_level = mode_max;
+ if (cfg.simple_ui_active) turbo_level = mode_max;
else
#endif
turbo_level = MAX_LEVEL;
@@ -61,7 +61,7 @@ uint8_t steady_state(Event event, uint16_t arg) {
// or to/from turbo if mem >= ceiling
if ((memorized_level < mode_max)
#ifdef USE_SIMPLE_UI
- || simple_ui_active
+ || cfg.simple_ui_active
#endif
) { turbo_level = mode_max; }
else { turbo_level = MAX_LEVEL; }
@@ -146,12 +146,12 @@ uint8_t steady_state(Event event, uint16_t arg) {
// click, hold: change brightness (dimmer)
else if ((event == EV_click1_hold) || (event == EV_click2_hold)) {
// ramp slower in discrete mode
- if (ramp_style && (arg % HOLD_TIMEOUT != 0)) {
+ if (cfg.ramp_style && (arg % HOLD_TIMEOUT != 0)) {
return MISCHIEF_MANAGED;
}
#ifdef USE_RAMP_SPEED_CONFIG
// ramp slower if user configured things that way
- if ((! ramp_style) && (arg % ramp_speed)) {
+ if ((! cfg.ramp_style) && (arg % ramp_speed)) {
return MISCHIEF_MANAGED;
}
#endif
@@ -211,13 +211,13 @@ uint8_t steady_state(Event event, uint16_t arg) {
}
#endif
#if defined(BLINK_AT_STEPS)
- uint8_t foo = ramp_style;
- ramp_style = 1;
+ uint8_t foo = cfg.ramp_style;
+ cfg.ramp_style = 1;
uint8_t nearest = nearest_level((int16_t)actual_level);
- ramp_style = foo;
+ cfg.ramp_style = foo;
// only blink once for each threshold
if ((memorized_level != actual_level) &&
- (ramp_style == 0) &&
+ (cfg.ramp_style == 0) &&
(memorized_level == nearest)
)
{
@@ -360,7 +360,7 @@ uint8_t steady_state(Event event, uint16_t arg) {
////////// Every action below here is blocked in the simple UI //////////
// That is, unless we specifically want to enable 3C for smooth/stepped selection in Simple UI
#if defined(USE_SIMPLE_UI) && !defined(USE_SIMPLE_UI_RAMPING_TOGGLE)
- if (simple_ui_active) {
+ if (cfg.simple_ui_active) {
return EVENT_NOT_HANDLED;
}
#endif
@@ -386,7 +386,7 @@ uint8_t steady_state(Event event, uint16_t arg) {
) {
#endif
- ramp_style = !ramp_style;
+ cfg.ramp_style = !cfg.ramp_style;
save_config();
#ifdef START_AT_MEMORIZED_LEVEL
save_config_wl();
@@ -402,13 +402,14 @@ uint8_t steady_state(Event event, uint16_t arg) {
// If we allowed 3C in Simple UI, now block further actions
#if defined(USE_SIMPLE_UI) && defined(USE_SIMPLE_UI_RAMPING_TOGGLE)
- if (simple_ui_active) {
+ if (cfg.simple_ui_active) {
return EVENT_NOT_HANDLED;
}
#endif
// 3H: momentary turbo (on lights with no tint ramping)
// (or 4H on lights with tint ramping)
+ // FIXME: handle 3H if channel mode has no args
else if (event == EV_MOMENTARY_TURBO) {
if (! arg) { // first frame only, to allow thermal regulation to work
#ifdef USE_2C_STYLE_CONFIG
@@ -457,7 +458,7 @@ uint8_t steady_state(Event event, uint16_t arg) {
#else // manual mem, but no timer
// turn off manual memory; go back to automatic
if (0 == arg) {
- manual_memory = 0;
+ cfg.manual_memory = 0;
save_config();
blink_once();
}
@@ -474,7 +475,7 @@ uint8_t steady_state(Event event, uint16_t arg) {
void ramp_config_save(uint8_t step, uint8_t value) {
// 0 = smooth ramp, 1 = stepped ramp, 2 = simple UI's ramp
- uint8_t style = ramp_style;
+ uint8_t style = cfg.ramp_style;
#ifdef USE_SIMPLE_UI
if (current_state == simple_ui_config_state) style = 2;
#endif
@@ -483,7 +484,7 @@ void ramp_config_save(uint8_t step, uint8_t value) {
// simple UI config is weird...
// has some ramp extras after floor/ceil/steps
if (4 == step) {
- ramp_2c_style_simple = value;
+ cfg.ramp_2c_style_simple = value;
}
else
#endif
@@ -496,7 +497,7 @@ void ramp_config_save(uint8_t step, uint8_t value) {
// which option are we configuring?
// TODO? maybe rearrange definitions to avoid the need for this table
// (move all ramp values into a single array?)
- uint8_t *steps[] = { ramp_floors, ramp_ceils, ramp_stepss };
+ uint8_t *steps[] = { cfg.ramp_floors, cfg.ramp_ceils, cfg.ramp_stepss };
uint8_t *option;
option = steps[step-1];
option[style] = value;
@@ -507,7 +508,7 @@ uint8_t ramp_config_state(Event event, uint16_t arg) {
#ifdef USE_RAMP_SPEED_CONFIG
const uint8_t num_config_steps = 3;
#else
- uint8_t num_config_steps = ramp_style + 2;
+ uint8_t num_config_steps = cfg.ramp_style + 2;
#endif
return config_state_base(event, arg,
num_config_steps, ramp_config_save);
@@ -530,14 +531,14 @@ uint8_t simple_ui_config_state(Event event, uint16_t arg) {
#ifdef USE_RAMP_EXTRAS_CONFIG
void ramp_extras_config_save(uint8_t step, uint8_t value) {
// item 1: disable manual memory, go back to automatic
- if (1 == step) { manual_memory = 0; }
+ if (1 == step) { cfg.manual_memory = 0; }
#ifdef USE_MANUAL_MEMORY_TIMER
// item 2: set manual memory timer duration
// FIXME: should be limited to (65535 / SLEEP_TICKS_PER_MINUTE)
// to avoid overflows or impossibly long timeouts
// (by default, the effective limit is 145, but it allows up to 255)
- else if (2 == step) { manual_memory_timer = value; }
+ else if (2 == step) { cfg.manual_memory_timer = value; }
#endif
#ifdef USE_RAMP_AFTER_MOON_CONFIG
@@ -545,7 +546,7 @@ void ramp_extras_config_save(uint8_t step, uint8_t value) {
// 0 = yes, ramp after moon
// 1+ = no, stay at moon
else if (3 == step) {
- dont_ramp_after_moon = value;
+ cfg.dont_ramp_after_moon = value;
}
#endif
@@ -554,7 +555,7 @@ void ramp_extras_config_save(uint8_t step, uint8_t value) {
// 1 = Anduril 1, 2C turbo
// 2+ = Anduril 2, 2C ceiling
else if (4 == step) {
- ramp_2c_style = value;
+ cfg.ramp_2c_style = value;
}
#endif
}
@@ -575,7 +576,7 @@ void globals_config_save(uint8_t step, uint8_t value) {
}
#endif
#ifdef USE_JUMP_START
- else if (step == 1+jump_start_config_step) { jump_start_level = value; }
+ else if (step == 1+jump_start_config_step) { cfg.jump_start_level = value; }
#endif
}
@@ -597,20 +598,20 @@ uint8_t nearest_level(int16_t target) {
// bounds check
uint8_t mode_min = ramp_floor;
uint8_t mode_max = ramp_ceil;
- uint8_t num_steps = ramp_stepss[1
+ uint8_t num_steps = cfg.ramp_stepss[1
#ifdef USE_SIMPLE_UI
- + simple_ui_active
+ + cfg.simple_ui_active
#endif
];
// special case for 1-step ramp... use halfway point between floor and ceiling
- if (ramp_style && (1 == num_steps)) {
+ if (cfg.ramp_style && (1 == num_steps)) {
uint8_t mid = (mode_max + mode_min) >> 1;
return mid;
}
if (target < mode_min) return mode_min;
if (target > mode_max) return mode_max;
// the rest isn't relevant for smooth ramping
- if (! ramp_style) return target;
+ if (! cfg.ramp_style) return target;
uint8_t ramp_range = mode_max - mode_min;
ramp_discrete_step_size = ramp_range / (num_steps-1);
@@ -628,13 +629,13 @@ uint8_t nearest_level(int16_t target) {
// ensure ramp globals are correct
void ramp_update_config() {
- uint8_t which = ramp_style;
+ uint8_t which = cfg.ramp_style;
#ifdef USE_SIMPLE_UI
- if (simple_ui_active) { which = 2; }
+ if (cfg.simple_ui_active) { which = 2; }
#endif
- ramp_floor = ramp_floors[which];
- ramp_ceil = ramp_ceils[which];
+ ramp_floor = cfg.ramp_floors[which];
+ ramp_ceil = cfg.ramp_ceils[which];
}
#ifdef USE_THERMAL_REGULATION
@@ -647,24 +648,24 @@ void set_level_and_therm_target(uint8_t level) {
#endif
void manual_memory_restore() {
- memorized_level = manual_memory;
+ memorized_level = cfg.manual_memory;
#if NUM_CHANNEL_MODES > 1
- channel_mode = manual_memory_channel_mode;
+ cfg.channel_mode = cfg.manual_memory_channel_mode;
#endif
#ifdef USE_CHANNEL_MODE_ARGS
for (uint8_t i=0; i<NUM_CHANNEL_MODES; i++)
- channel_mode_args[i] = manual_memory_channel_args[i];
+ cfg.channel_mode_args[i] = cfg.manual_memory_channel_args[i];
#endif
}
void manual_memory_save() {
- manual_memory = actual_level;
+ cfg.manual_memory = actual_level;
#if NUM_CHANNEL_MODES > 1
- manual_memory_channel_mode = channel_mode;
+ cfg.manual_memory_channel_mode = cfg.channel_mode;
#endif
#ifdef USE_CHANNEL_MODE_ARGS
for (uint8_t i=0; i<NUM_CHANNEL_MODES; i++)
- manual_memory_channel_args[i] = channel_mode_args[i];
+ cfg.manual_memory_channel_args[i] = cfg.channel_mode_args[i];
#endif
}
diff --git a/spaghetti-monster/anduril/ramp-mode.h b/spaghetti-monster/anduril/ramp-mode.h
index 6bc3846..c50e36a 100644
--- a/spaghetti-monster/anduril/ramp-mode.h
+++ b/spaghetti-monster/anduril/ramp-mode.h
@@ -151,76 +151,44 @@ void set_level_and_therm_target(uint8_t level);
// brightness control
uint8_t memorized_level = DEFAULT_LEVEL;
#ifdef USE_MANUAL_MEMORY
-#ifndef DEFAULT_MANUAL_MEMORY
-#define DEFAULT_MANUAL_MEMORY 0
-#endif
-uint8_t manual_memory = DEFAULT_MANUAL_MEMORY;
-#ifdef USE_MANUAL_MEMORY_TIMER
-#ifndef DEFAULT_MANUAL_MEMORY_TIMER
-#define DEFAULT_MANUAL_MEMORY_TIMER 0
-#endif
-uint8_t manual_memory_timer = DEFAULT_MANUAL_MEMORY_TIMER;
-#endif
-#endif
-void manual_memory_restore();
-void manual_memory_save();
-
-#ifdef USE_SIMPLE_UI
- // whether to enable the simplified interface or not
- uint8_t simple_ui_active = SIMPLE_UI_ACTIVE;
- #ifdef USE_2C_STYLE_CONFIG
- #ifndef DEFAULT_2C_STYLE_SIMPLE
- #define DEFAULT_2C_STYLE_SIMPLE 0
+ void manual_memory_restore();
+ void manual_memory_save();
+ #ifndef DEFAULT_MANUAL_MEMORY
+ #define DEFAULT_MANUAL_MEMORY 0
+ #endif
+ #ifdef USE_MANUAL_MEMORY_TIMER
+ #ifndef DEFAULT_MANUAL_MEMORY_TIMER
+ #define DEFAULT_MANUAL_MEMORY_TIMER 0
#endif
- uint8_t ramp_2c_style_simple = DEFAULT_2C_STYLE_SIMPLE; // 0 = no turbo, 1 = A1 style, 2 = A2 style
#endif
#endif
-// smooth vs discrete ramping
-uint8_t ramp_style = RAMP_STYLE; // 0 = smooth, 1 = discrete
+
+#ifndef DEFAULT_2C_STYLE_SIMPLE
+ #define DEFAULT_2C_STYLE_SIMPLE 0
+#endif
+
#ifdef USE_2C_STYLE_CONFIG
#ifndef DEFAULT_2C_STYLE
#define DEFAULT_2C_STYLE 2
#endif
-uint8_t ramp_2c_style = DEFAULT_2C_STYLE; // 1 = A1 style, 2 = A2 style
+
#ifdef USE_2C_MAX_TURBO
#error Cannot use USE_2C_MAX_TURBO and USE_2C_STYLE_CONFIG at the same time.
#endif
#endif
#ifdef USE_RAMP_SPEED_CONFIG
-#define ramp_speed (ramp_stepss[0])
+#define ramp_speed (cfg.ramp_stepss[0])
#endif
#ifdef USE_RAMP_AFTER_MOON_CONFIG
#ifndef DEFAULT_DONT_RAMP_AFTER_MOON
#define DEFAULT_DONT_RAMP_AFTER_MOON 0
#endif
-uint8_t dont_ramp_after_moon = DEFAULT_DONT_RAMP_AFTER_MOON;
#endif
// current values, regardless of style
uint8_t ramp_floor = RAMP_SMOOTH_FLOOR;
uint8_t ramp_ceil = RAMP_SMOOTH_CEIL;
-// per style
-uint8_t ramp_floors[] = {
- RAMP_SMOOTH_FLOOR,
- RAMP_DISCRETE_FLOOR,
- #ifdef USE_SIMPLE_UI
- SIMPLE_UI_FLOOR,
- #endif
- };
-uint8_t ramp_ceils[] = {
- RAMP_SMOOTH_CEIL,
- RAMP_DISCRETE_CEIL,
- #ifdef USE_SIMPLE_UI
- SIMPLE_UI_CEIL,
- #endif
- };
-uint8_t ramp_stepss[] = {
- DEFAULT_RAMP_SPEED,
- RAMP_DISCRETE_STEPS,
- #ifdef USE_SIMPLE_UI
- SIMPLE_UI_STEPS,
- #endif
- };
+
uint8_t ramp_discrete_step_size; // don't set this
#ifdef USE_SUNSET_TIMER
diff --git a/spaghetti-monster/anduril/strobe-modes.c b/spaghetti-monster/anduril/strobe-modes.c
index 5ee2386..0664418 100644
--- a/spaghetti-monster/anduril/strobe-modes.c
+++ b/spaghetti-monster/anduril/strobe-modes.c
@@ -27,7 +27,7 @@ uint8_t strobe_state(Event event, uint16_t arg) {
static int8_t ramp_direction = 1;
// 'st' reduces ROM size slightly
- strobe_mode_te st = strobe_type;
+ strobe_mode_te st = cfg.strobe_type;
#ifdef USE_MOMENTARY_MODE
momentary_mode = 1; // 0 = ramping, 1 = strobes
@@ -54,13 +54,13 @@ uint8_t strobe_state(Event event, uint16_t arg) {
}
// 2 clicks: rotate through strobe/flasher modes
else if (event == EV_2clicks) {
- strobe_type = (st + 1) % NUM_STROBES;
+ cfg.strobe_type = (st + 1) % NUM_STROBES;
save_config();
return MISCHIEF_MANAGED;
}
// 4 clicks: rotate backward through strobe/flasher modes
else if (event == EV_4clicks) {
- strobe_type = (st - 1 + NUM_STROBES) % NUM_STROBES;
+ cfg.strobe_type = (st - 1 + NUM_STROBES) % NUM_STROBES;
save_config();
return MISCHIEF_MANAGED;
}
@@ -77,11 +77,11 @@ uint8_t strobe_state(Event event, uint16_t arg) {
else if (st == party_strobe_e) {
#endif
if ((arg & 1) == 0) {
- uint8_t d = strobe_delays[st];
+ uint8_t d = cfg.strobe_delays[st];
d -= ramp_direction;
if (d < 8) d = 8;
else if (d > 254) d = 254;
- strobe_delays[st] = d;
+ cfg.strobe_delays[st] = d;
}
}
#endif
@@ -92,10 +92,10 @@ uint8_t strobe_state(Event event, uint16_t arg) {
// biking mode brighter
#ifdef USE_BIKE_FLASHER_MODE
else if (st == bike_flasher_e) {
- bike_flasher_brightness += ramp_direction;
- if (bike_flasher_brightness < 2) bike_flasher_brightness = 2;
- else if (bike_flasher_brightness > MAX_BIKING_LEVEL) bike_flasher_brightness = MAX_BIKING_LEVEL;
- set_level(bike_flasher_brightness);
+ cfg.bike_flasher_brightness += ramp_direction;
+ if (cfg.bike_flasher_brightness < 2) cfg.bike_flasher_brightness = 2;
+ else if (cfg.bike_flasher_brightness > MAX_BIKING_LEVEL) cfg.bike_flasher_brightness = MAX_BIKING_LEVEL;
+ set_level(cfg.bike_flasher_brightness);
}
#endif
@@ -123,7 +123,7 @@ uint8_t strobe_state(Event event, uint16_t arg) {
else if (st == party_strobe_e) {
#endif
if ((arg & 1) == 0) {
- if (strobe_delays[st] < 255) strobe_delays[st] ++;
+ if (cfg.strobe_delays[st] < 255) cfg.strobe_delays[st] ++;
}
}
#endif
@@ -134,9 +134,9 @@ uint8_t strobe_state(Event event, uint16_t arg) {
// biking mode dimmer
#ifdef USE_BIKE_FLASHER_MODE
else if (st == bike_flasher_e) {
- if (bike_flasher_brightness > 2)
- bike_flasher_brightness --;
- set_level(bike_flasher_brightness);
+ if (cfg.bike_flasher_brightness > 2)
+ cfg.bike_flasher_brightness --;
+ set_level(cfg.bike_flasher_brightness);
}
#endif
@@ -170,7 +170,7 @@ uint8_t strobe_state(Event event, uint16_t arg) {
// runs repeatedly in FSM loop() whenever UI is in strobe_state or momentary strobe
inline void strobe_state_iter() {
- uint8_t st = strobe_type; // can't use switch() on an enum
+ uint8_t st = cfg.strobe_type; // can't use switch() on an enum
switch(st) {
#if defined(USE_PARTY_STROBE_MODE) || defined(USE_TACTICAL_STROBE_MODE)
@@ -208,7 +208,7 @@ inline void strobe_state_iter() {
#if defined(USE_PARTY_STROBE_MODE) || defined(USE_TACTICAL_STROBE_MODE)
inline void party_tactical_strobe_mode_iter(uint8_t st) {
// one iteration of main loop()
- uint8_t del = strobe_delays[st];
+ uint8_t del = cfg.strobe_delays[st];
// TODO: make tac strobe brightness configurable?
set_level(STROBE_BRIGHTNESS);
if (0) {} // placeholder
@@ -238,7 +238,7 @@ inline void police_color_strobe_iter() {
uint8_t del = 66;
// TODO: make police strobe brightness configurable
uint8_t bright = memorized_level;
- uint8_t channel = channel_mode;
+ uint8_t channel = cfg.channel_mode;
for (uint8_t i=0; i<10; i++) {
if (0 == i) set_channel_mode(POLICE_COLOR_STROBE_CH1);
@@ -304,12 +304,12 @@ inline void lightning_storm_iter() {
#ifdef USE_BIKE_FLASHER_MODE
inline void bike_flasher_iter() {
// one iteration of main loop()
- uint8_t burst = bike_flasher_brightness << 1;
+ uint8_t burst = cfg.bike_flasher_brightness << 1;
if (burst > MAX_LEVEL) burst = MAX_LEVEL;
for(uint8_t i=0; i<4; i++) {
set_level(burst);
nice_delay_ms(5);
- set_level(bike_flasher_brightness);
+ set_level(cfg.bike_flasher_brightness);
nice_delay_ms(65);
}
nice_delay_ms(720); // no return check necessary on final delay
diff --git a/spaghetti-monster/anduril/strobe-modes.h b/spaghetti-monster/anduril/strobe-modes.h
index 685c249..0e7c873 100644
--- a/spaghetti-monster/anduril/strobe-modes.h
+++ b/spaghetti-monster/anduril/strobe-modes.h
@@ -48,9 +48,9 @@ const int NUM_STROBES = strobe_mode_END;
// which strobe mode is active?
#ifdef USE_CANDLE_MODE
-strobe_mode_te strobe_type = candle_mode_e;
+ #define DEFAULT_STROBE candle_mode_e
#else
-strobe_mode_te strobe_type = 0;
+ #define DEFAULT_STROBE 0
#endif
#endif
@@ -79,8 +79,6 @@ inline void strobe_state_iter();
#endif
#if defined(USE_PARTY_STROBE_MODE) || defined(USE_TACTICAL_STROBE_MODE)
-// party / tactical strobe timing
-uint8_t strobe_delays[] = { 41, 67 }; // party strobe 24 Hz, tactical strobe 10 Hz
inline void party_tactical_strobe_mode_iter(uint8_t st);
#endif
@@ -95,7 +93,6 @@ inline void lightning_storm_iter();
// bike mode config options
#ifdef USE_BIKE_FLASHER_MODE
#define MAX_BIKING_LEVEL 120 // should be 127 or less
-uint8_t bike_flasher_brightness = MAX_1x7135;
inline void bike_flasher_iter();
#endif
diff --git a/spaghetti-monster/anduril/sunset-timer.c b/spaghetti-monster/anduril/sunset-timer.c
index bad317c..bb59ec9 100644
--- a/spaghetti-monster/anduril/sunset-timer.c
+++ b/spaghetti-monster/anduril/sunset-timer.c
@@ -10,7 +10,7 @@ uint8_t sunset_timer_state(Event event, uint16_t arg) {
#if defined(USE_SIMPLE_UI) && !defined(USE_EXTENDED_SIMPLE_UI)
// No timer functions in Simple UI
- if (simple_ui_active) return EVENT_NOT_HANDLED;
+ if (cfg.simple_ui_active) return EVENT_NOT_HANDLED;
#endif
// reset on start
diff --git a/spaghetti-monster/anduril/tactical-mode.c b/spaghetti-monster/anduril/tactical-mode.c
index 7e9d66b..2447a11 100644
--- a/spaghetti-monster/anduril/tactical-mode.c
+++ b/spaghetti-monster/anduril/tactical-mode.c
@@ -22,8 +22,6 @@
#include "tactical-mode.h"
-// TODO: save these in eeprom
-uint8_t tactical_levels[] = { TACTICAL_LEVELS }; // high, low, strobe
uint8_t tactical_state(Event event, uint16_t arg) {
// momentary(ish) tactical mode
@@ -42,14 +40,14 @@ uint8_t tactical_state(Event event, uint16_t arg) {
if (click <= 3) {
momentary_active = 1;
uint8_t lvl;
- lvl = tactical_levels[click-1];
+ lvl = cfg.tactical_levels[click-1];
if ((1 <= lvl) && (lvl <= RAMP_SIZE)) { // steady output
memorized_level = lvl;
momentary_mode = 0;
} else { // momentary strobe mode
momentary_mode = 1;
if (lvl > RAMP_SIZE) {
- strobe_type = (lvl - RAMP_SIZE - 1) % strobe_mode_END;
+ cfg.strobe_type = (lvl - RAMP_SIZE - 1) % strobe_mode_END;
}
}
}
@@ -92,7 +90,7 @@ uint8_t tactical_state(Event event, uint16_t arg) {
// (unnecessary since this entire mode is blocked in simple UI)
/*
#ifdef USE_SIMPLE_UI
- if (simple_ui_active) {
+ if (cfg.simple_ui_active) {
return EVENT_NOT_HANDLED;
}
#endif
@@ -113,7 +111,7 @@ void tactical_config_save(uint8_t step, uint8_t value) {
// each value is 1 to 150, or other:
// - 1..150 is a ramp level
// - other means "strobe mode"
- tactical_levels[step - 1] = value;
+ cfg.tactical_levels[step - 1] = value;
}
uint8_t tactical_config_state(Event event, uint16_t arg) {
diff --git a/spaghetti-monster/anduril/tactical-mode.h b/spaghetti-monster/anduril/tactical-mode.h
index 4403314..14bf7ff 100644
--- a/spaghetti-monster/anduril/tactical-mode.h
+++ b/spaghetti-monster/anduril/tactical-mode.h
@@ -20,14 +20,13 @@
#ifndef TACTICAL_MODE_H
#define TACTICAL_MODE_H
-// tactical(ish) mode
-uint8_t tactical_state(Event event, uint16_t arg);
-
#ifndef TACTICAL_LEVELS
// high, low, tactical strobe
#define TACTICAL_LEVELS 120,30,(RAMP_SIZE+2)
#endif
-uint8_t tactical_levels[];
+
+// tactical(ish) mode
+uint8_t tactical_state(Event event, uint16_t arg);
uint8_t tactical_config_state(Event event, uint16_t arg);
diff --git a/spaghetti-monster/anduril/tempcheck-mode.c b/spaghetti-monster/anduril/tempcheck-mode.c
index f6e1ebe..2e3b56f 100644
--- a/spaghetti-monster/anduril/tempcheck-mode.c
+++ b/spaghetti-monster/anduril/tempcheck-mode.c
@@ -51,18 +51,18 @@ void thermal_config_save(uint8_t step, uint8_t value) {
if (value) {
// item 1: calibrate room temperature
if (step == 1) {
- int8_t rawtemp = temperature - therm_cal_offset;
- therm_cal_offset = value - rawtemp;
+ int8_t rawtemp = temperature - cfg.therm_cal_offset;
+ cfg.therm_cal_offset = value - rawtemp;
adc_reset = 2; // invalidate all recent temperature data
}
// item 2: set maximum heat limit
else {
- therm_ceil = 30 + value - 1;
+ cfg.therm_ceil = 30 + value - 1;
}
}
- if (therm_ceil > MAX_THERM_CEIL) therm_ceil = MAX_THERM_CEIL;
+ if (cfg.therm_ceil > MAX_THERM_CEIL) cfg.therm_ceil = MAX_THERM_CEIL;
}
uint8_t thermal_config_state(Event event, uint16_t arg) {
diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c
index 60eb843..9dc8866 100644
--- a/spaghetti-monster/fsm-adc.c
+++ b/spaghetti-monster/fsm-adc.c
@@ -149,7 +149,7 @@ static inline uint8_t calc_voltage_divider(uint16_t value) {
uint8_t result = ((value / adc_per_volt)
+ VOLTAGE_FUDGE_FACTOR
#ifdef USE_VOLTAGE_CORRECTION
- + voltage_correction - 7
+ + VOLT_CORR - 7
#endif
) >> 1;
return result;
@@ -349,7 +349,7 @@ static inline void ADC_voltage_handler() {
voltage = ((uint16_t)(2*1.1*1024*10)/(measurement>>6)
+ VOLTAGE_FUDGE_FACTOR
#ifdef USE_VOLTAGE_CORRECTION
- + voltage_correction - 7
+ + VOLT_CORR - 7
#endif
) >> 1;
#endif
@@ -428,10 +428,10 @@ static inline void ADC_temperature_handler() {
// Convert ADC units to Celsius (ish)
#ifndef USE_EXTERNAL_TEMP_SENSOR
// onboard sensor for attiny25/45/85/1634
- temperature = (measurement>>1) + THERM_CAL_OFFSET + (int16_t)therm_cal_offset - 275;
+ temperature = (measurement>>1) + THERM_CAL_OFFSET + (int16_t)TH_CAL - 275;
#else
// external sensor
- temperature = EXTERN_TEMP_FORMULA(measurement>>1) + THERM_CAL_OFFSET + (int16_t)therm_cal_offset;
+ temperature = EXTERN_TEMP_FORMULA(measurement>>1) + THERM_CAL_OFFSET + (int16_t)TH_CAL;
#endif
// how much has the temperature changed between now and a few seconds ago?
@@ -447,10 +447,10 @@ static inline void ADC_temperature_handler() {
pt = measurement + (diff * THERM_LOOKAHEAD);
// convert temperature limit from C to raw 16-bit ADC units
- // C = (ADC>>6) - 275 + THERM_CAL_OFFSET + therm_cal_offset;
+ // C = (ADC>>6) - 275 + THERM_CAL_OFFSET + TH_CAL;
// ... so ...
- // (C + 275 - THERM_CAL_OFFSET - therm_cal_offset) << 6 = ADC;
- uint16_t ceil = (therm_ceil + 275 - therm_cal_offset - THERM_CAL_OFFSET) << 1;
+ // (C + 275 - THERM_CAL_OFFSET - TH_CAL) << 6 = ADC;
+ uint16_t ceil = (TH_CEIL + 275 - TH_CAL - THERM_CAL_OFFSET) << 1;
int16_t offset = pt - ceil;
// bias small errors toward zero, while leaving large errors mostly unaffected
diff --git a/spaghetti-monster/fsm-adc.h b/spaghetti-monster/fsm-adc.h
index db2bb7b..77f625a 100644
--- a/spaghetti-monster/fsm-adc.h
+++ b/spaghetti-monster/fsm-adc.h
@@ -63,9 +63,14 @@ void adc_deferred(); // do the actual ADC-related calculations
static inline void ADC_voltage_handler();
uint8_t voltage = 0;
#ifdef USE_VOLTAGE_CORRECTION
-// same 0.05V units as fudge factor,
-// but 7 is neutral, and the expected range is from 1 to 13
-uint8_t voltage_correction = 7;
+ #ifdef USE_CFG
+ #define VOLT_CORR cfg.voltage_correction
+ #else
+ // same 0.05V units as fudge factor,
+ // but 7 is neutral, and the expected range is from 1 to 13
+ uint8_t voltage_correction = 7;
+ #define VOLT_CORR voltage_correction
+ #endif
#endif
#ifdef USE_LVP
void low_voltage();
@@ -98,8 +103,15 @@ void battcheck();
#endif
// temperature now, in C (ish)
int16_t temperature;
-uint8_t therm_ceil = DEFAULT_THERM_CEIL;
-int8_t therm_cal_offset = 0;
+#ifdef USE_CFG
+ #define TH_CEIL cfg.therm_ceil
+ #define TH_CAL cfg.therm_cal_offset
+#else
+ #define TH_CEIL therm_ceil
+ #define TH_CAL therm_cal_offset
+ uint8_t therm_ceil = DEFAULT_THERM_CEIL;
+ int8_t therm_cal_offset = 0;
+#endif
static inline void ADC_temperature_handler();
#endif // ifdef USE_THERMAL_REGULATION
diff --git a/spaghetti-monster/fsm-eeprom.h b/spaghetti-monster/fsm-eeprom.h
index 3621106..cda290b 100644
--- a/spaghetti-monster/fsm-eeprom.h
+++ b/spaghetti-monster/fsm-eeprom.h
@@ -33,9 +33,10 @@
#endif
#ifdef USE_EEPROM
-#if EEPROM_BYTES >= (EEPSIZE/2)
-#error Requested EEPROM_BYTES too big.
-#endif
+// this fails when EEPROM_BYTES is a sizeof()
+//#if EEPROM_BYTES >= (EEPSIZE/2)
+//#error Requested EEPROM_BYTES too big.
+//#endif
#ifdef EEPROM_OVERRIDE
uint8_t *eeprom;
#else
diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c
index a55c74b..14b0db8 100644
--- a/spaghetti-monster/fsm-ramping.c
+++ b/spaghetti-monster/fsm-ramping.c
@@ -16,7 +16,7 @@ void set_channel_mode(uint8_t mode) {
set_level(0);
// change the channel
- channel_mode = mode;
+ CH_MODE = mode;
// update the LEDs
set_level(cur_level);
@@ -61,8 +61,8 @@ void set_level(uint8_t level) {
// TODO: allow different jump start behavior per channel mode
if ((! actual_level)
&& level
- && (level < jump_start_level)) {
- set_level(jump_start_level);
+ && (level < JUMP_START_LEVEL)) {
+ set_level(JUMP_START_LEVEL);
delay_4ms(JUMP_START_TIME/4);
}
#endif
@@ -72,7 +72,7 @@ void set_level(uint8_t level) {
#endif
// call the relevant hardware-specific set_level_*()
- SetLevelFuncPtr set_level_func = channel_modes[channel_mode];
+ SetLevelFuncPtr set_level_func = channel_modes[CH_MODE];
set_level_func(level);
actual_level = level;
@@ -138,54 +138,52 @@ void set_level_3ch_stacked(uint8_t level) {
// TODO: 2ch stacked w/ dynamic PWM
// TODO: 2ch stacked w/ dynamic PWM and opamp enable pins?
-#ifdef USE_SET_LEVEL_2CH_BLEND
-// warm + cool blend w/ middle sag correction
-void set_level_2ch_blend(uint8_t level) {
+#ifdef USE_CALC_2CH_BLEND
+// calculate a "tint ramp" blend between 2 channels
+// results are placed in *warm and *cool vars
+// brightness : total amount of light units to distribute
+// top : maximum allowed brightness per channel
+// blend : ratio between warm and cool (0 = warm, 128 = 50%, 255 = cool)
+void calc_2ch_blend(
+ PWM_DATATYPE *warm,
+ PWM_DATATYPE *cool,
+ PWM_DATATYPE brightness,
+ PWM_DATATYPE top,
+ uint8_t blend) {
+
#ifndef TINT_RAMPING_CORRECTION
#define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint
#endif
- BLEND_PWM_DATATYPE vpwm;
-
- if (level == 0) {
- vpwm = 0;
- } else {
- level --; // PWM array index = level - 1
- vpwm = PWM_GET(blend_pwm_levels, level);
- }
-
// calculate actual PWM levels based on a single-channel ramp
- // and a global tint value
- uint16_t brightness = vpwm;
- uint16_t warm_PWM, cool_PWM;
- const uint16_t top = PWM_TOP;
-
- // auto-tint modes
- uint8_t mytint = channel_mode_args[channel_mode];
-
+ // and a blend value
+ PWM_DATATYPE warm_PWM, cool_PWM;
PWM_DATATYPE2 base_PWM = brightness;
+
#if defined(TINT_RAMPING_CORRECTION) && (TINT_RAMPING_CORRECTION > 0)
+ uint8_t level = actual_level - 1;
+
// middle tints sag, so correct for that effect
// by adding extra power which peaks at the middle tint
// (correction is only necessary when PWM is fast)
if (level > HALFSPEED_LEVEL) {
base_PWM = brightness
+ ((((PWM_DATATYPE2)brightness) * TINT_RAMPING_CORRECTION / 64)
- * triangle_wave(mytint) / 255);
+ * triangle_wave(blend) / 255);
}
// fade the triangle wave out when above 100% power,
// so it won't go over 200%
if (brightness > top) {
base_PWM -= 2 * (
((brightness - top) * TINT_RAMPING_CORRECTION / 64)
- * triangle_wave(mytint) / 255
+ * triangle_wave(blend) / 255
);
}
// guarantee no more than 200% power
if (base_PWM > (top << 1)) { base_PWM = top << 1; }
#endif
- cool_PWM = (((PWM_DATATYPE2)mytint * (PWM_DATATYPE2)base_PWM) + 127) / 255;
+ cool_PWM = (((PWM_DATATYPE2)blend * (PWM_DATATYPE2)base_PWM) + 127) / 255;
warm_PWM = base_PWM - cool_PWM;
// when running at > 100% power, spill extra over to other channel
if (cool_PWM > top) {
@@ -196,10 +194,76 @@ void set_level_2ch_blend(uint8_t level) {
warm_PWM = top;
}
- WARM_PWM_LVL = warm_PWM;
- COOL_PWM_LVL = cool_PWM;
+ *warm = warm_PWM;
+ *cool = cool_PWM;
}
-#endif // ifdef USE_TINT_RAMPING
+#endif // ifdef USE_CALC_2CH_BLEND
+
+#ifdef USE_HSV2RGB
+RGB_t hsv2rgb(uint8_t h, uint8_t s, uint8_t v) {
+ RGB_t color;
+
+ uint16_t region, fpart, high, low, rising, falling;
+
+ if (s == 0) { // grey
+ color.r = color.g = color.b = v;
+ return color;
+ }
+
+ // make hue 0-5
+ region = ((uint16_t)h * 6) >> 8;
+ // find remainder part, make it from 0-255
+ fpart = ((uint16_t)h * 6) - (region << 8);
+
+ // calculate graph segments, doing integer multiplication
+ high = v;
+ low = (v * (255 - s)) >> 8;
+ falling = (v * (255 - ((s * fpart) >> 8))) >> 8;
+ rising = (v * (255 - ((s * (255 - fpart)) >> 8))) >> 8;
+
+ // default floor
+ color.r = low;
+ color.g = low;
+ color.b = low;
+
+ // assign graph shapes based on color cone region
+ switch (region) {
+ case 0:
+ color.r = high;
+ color.g = rising;
+ //color.b = low;
+ break;
+ case 1:
+ color.r = falling;
+ color.g = high;
+ //color.b = low;
+ break;
+ case 2:
+ //color.r = low;
+ color.g = high;
+ color.b = rising;
+ break;
+ case 3:
+ //color.r = low;
+ color.g = falling;
+ color.b = high;
+ break;
+ case 4:
+ color.r = rising;
+ //color.g = low;
+ color.b = high;
+ break;
+ default:
+ color.r = high;
+ //color.g = low;
+ color.b = falling;
+ break;
+ }
+
+ return color;
+}
+#endif // ifdef USE_HSV2RGB
+
#ifdef USE_LEGACY_SET_LEVEL
// (this is mostly just here for reference, temporarily)
@@ -339,7 +403,7 @@ inline void set_level_gradually(uint8_t lvl) {
// call this every frame or every few frames to change brightness very smoothly
void gradual_tick() {
// call the relevant hardware-specific function
- GradualTickFuncPtr gradual_tick_func = gradual_tick_modes[channel_mode];
+ GradualTickFuncPtr gradual_tick_func = gradual_tick_modes[CH_MODE];
gradual_tick_func();
}
diff --git a/spaghetti-monster/fsm-ramping.h b/spaghetti-monster/fsm-ramping.h
index 8a12cc8..5ffd8d9 100644
--- a/spaghetti-monster/fsm-ramping.h
+++ b/spaghetti-monster/fsm-ramping.h
@@ -28,11 +28,12 @@ uint8_t actual_level = 0;
// TODO: size-optimize the case with only 1 channel mode
// (the arrays and stuff shouldn't be needed)
-// current multi-channel mode
-uint8_t channel_mode = DEFAULT_CHANNEL_MODE;
-#ifdef USE_MANUAL_MEMORY
-// reset w/ manual memory
-uint8_t manual_memory_channel_mode = DEFAULT_CHANNEL_MODE;
+#ifdef USE_CFG
+ #define CH_MODE cfg.channel_mode
+#else
+ // current multi-channel mode
+ uint8_t channel_mode = DEFAULT_CHANNEL_MODE;
+ #define CH_MODE channel_mode
#endif
#if NUM_CHANNEL_MODES > 1
@@ -62,36 +63,49 @@ StatePtr channel_3H_modes[NUM_CHANNEL_MODES];
//#ifdef USE_CHANNEL_MODE_TOGGLES
#if NUM_CHANNEL_MODES > 1
// user can take unwanted modes out of the rotation
-// TODO: save to eeprom
-// array
-//uint8_t channel_modes_enabled[NUM_CHANNEL_MODES] = { CHANNEL_MODES_ENABLED };
// bitmask
-uint8_t channel_modes_enabled = CHANNEL_MODES_ENABLED;
-#define channel_mode_enabled(n) ((channel_modes_enabled >> n) & 1)
-#define channel_mode_enable(n) channel_modes_enabled |= (1 << n)
-#define channel_mode_disable(n) channel_modes_enabled &= ((1 << n) ^ 0xff)
+#ifdef USE_CFG
+ #define channel_mode_enabled(n) ((cfg.channel_modes_enabled >> n) & 1)
+ #define channel_mode_enable(n) cfg.channel_modes_enabled |= (1 << n)
+ #define channel_mode_disable(n) cfg.channel_modes_enabled &= ((1 << n) ^ 0xff)
+#else
+ uint8_t channel_modes_enabled = CHANNEL_MODES_ENABLED;
+ #define channel_mode_enabled(n) ((channel_modes_enabled >> n) & 1)
+ #define channel_mode_enable(n) channel_modes_enabled |= (1 << n)
+ #define channel_mode_disable(n) channel_modes_enabled &= ((1 << n) ^ 0xff)
+ #endif
#endif
-#ifdef USE_CHANNEL_MODE_ARGS
-// one byte of extra data per channel mode, like for tint value
-uint8_t channel_mode_args[NUM_CHANNEL_MODES] = { CHANNEL_MODE_ARGS };
+#ifndef USE_CFG
+ #ifdef USE_CHANNEL_MODE_ARGS
+ // one byte of extra data per channel mode, like for tint value
+ uint8_t channel_mode_args[NUM_CHANNEL_MODES] = { CHANNEL_MODE_ARGS };
+ #endif
#endif
-// TODO: remove this after implementing channel modes
-//#ifdef USE_TINT_RAMPING
-//#ifdef TINT_RAMP_TOGGLE_ONLY
-//uint8_t tint = 0;
-//#else
-//uint8_t tint = 128;
-//#endif
-//#define USE_TRIANGLE_WAVE
-//#endif
-
void set_channel_mode(uint8_t mode);
void set_level(uint8_t level);
//void set_level_smooth(uint8_t level);
+#ifdef USE_CALC_2CH_BLEND
+void calc_2ch_blend(
+ PWM_DATATYPE *warm,
+ PWM_DATATYPE *cool,
+ PWM_DATATYPE brightness,
+ PWM_DATATYPE top,
+ uint8_t blend);
+#endif
+
+#ifdef USE_HSV2RGB
+typedef struct RGB_t {
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+} RGB_t;
+RGB_t hsv2rgb(uint8_t h, uint8_t s, uint8_t v);
+#endif // ifdef USE_HSV2RGB
+
#ifdef USE_SET_LEVEL_GRADUALLY
// adjust brightness very smoothly
uint8_t gradual_target;
@@ -213,13 +227,18 @@ PROGMEM const PWM_DATATYPE pwm_tops[] = { PWM_TOPS };
// FIXME: jump start should be per channel / channel mode
#ifdef USE_JUMP_START
-#ifndef JUMP_START_TIME
-#define JUMP_START_TIME 8 // in ms, should be 4, 8, or 12
-#endif
-#ifndef DEFAULT_JUMP_START_LEVEL
-#define DEFAULT_JUMP_START_LEVEL 10
-#endif
-uint8_t jump_start_level = DEFAULT_JUMP_START_LEVEL;
+ #ifndef JUMP_START_TIME
+ #define JUMP_START_TIME 8 // in ms, should be 4, 8, or 12
+ #endif
+ #ifndef DEFAULT_JUMP_START_LEVEL
+ #define DEFAULT_JUMP_START_LEVEL 10
+ #endif
+ #ifdef USE_CFG
+ #define JUMP_START_LEVEL cfg.jump_start_level
+ #else
+ #define JUMP_START_LEVEL jump_start_level
+ uint8_t jump_start_level = DEFAULT_JUMP_START_LEVEL;
+ #endif
#endif
// RAMP_SIZE / MAX_LVL