aboutsummaryrefslogtreecommitdiff
path: root/spaghetti-monster
diff options
context:
space:
mode:
authorSelene ToyKeeper2023-04-16 18:21:29 -0600
committerSelene ToyKeeper2023-04-16 18:21:29 -0600
commitfbcac59563c32f14de4861449c1b267c247b5b78 (patch)
tree3cddc0e447194d7a6432ebf3561a86208037d44e /spaghetti-monster
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 'spaghetti-monster')
-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
28 files changed, 572 insertions, 596 deletions
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
If you find this content useful please consider a small donation via bitcoin: bitcoin:1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2?amount=0.001&message=Donation Scraping git contents via cgit is very resource intensive. The continued hosting of these git repositories is entirely financed by your bitcoin contributions. For donations of a least 1 mBTC you include your IP address in the message of your bitcoin donation. This will remove this message in the future for requests from your IP, which will significantly reduce token usage. In any case, any contributions to bitcoin address 1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2 are very welcome. Thanks in advance for you contribution to a self-sustaining ecosystem.