From 9eb86affad419a9bad68d9c62e51d5d644f67af6 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 14 Apr 2019 16:47:45 -0600 Subject: applied upstream anduril changes to fireflies-ui --- spaghetti-monster/fireflies-ui/fireflies-ui.c | 56 +++++++++++++++++++-------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/spaghetti-monster/fireflies-ui/fireflies-ui.c b/spaghetti-monster/fireflies-ui/fireflies-ui.c index 0fc2a1d..772d197 100644 --- a/spaghetti-monster/fireflies-ui/fireflies-ui.c +++ b/spaghetti-monster/fireflies-ui/fireflies-ui.c @@ -33,7 +33,7 @@ // or too short) #define MOON_TIMING_HINT // short blips while ramping -#define BLINK_AT_CHANNEL_BOUNDARIES +#define BLINK_AT_RAMP_MIDDLE //#define BLINK_AT_RAMP_FLOOR #define BLINK_AT_RAMP_CEILING //#define BLINK_AT_STEPS // whenever a discrete ramp mode is passed in smooth mode @@ -319,8 +319,28 @@ void save_config_wl(); #define RAMP_DISCRETE_STEPS 7 #endif +// mile marker(s) partway up the ramp +// default: blink only at border between regulated and FET +#ifdef BLINK_AT_RAMP_MIDDLE + #if PWM_CHANNELS >= 3 + #ifndef BLINK_AT_RAMP_MIDDLE_1 + #define BLINK_AT_RAMP_MIDDLE_1 MAX_Nx7135 + #ifndef BLINK_AT_RAMP_MIDDLE_2 + #define BLINK_AT_RAMP_MIDDLE_2 MAX_1x7135 + #endif + #endif + #else + #ifndef BLINK_AT_RAMP_MIDDLE_1 + #define BLINK_AT_RAMP_MIDDLE_1 MAX_1x7135 + #endif + #endif +#endif + // brightness control -uint8_t memorized_level = MAX_1x7135; +#ifndef DEFAULT_LEVEL +#define DEFAULT_LEVEL MAX_1x7135 +#endif +uint8_t memorized_level = DEFAULT_LEVEL; // smooth vs discrete ramping volatile uint8_t ramp_style = 0; // 0 = smooth, 1 = discrete volatile uint8_t ramp_smooth_floor = RAMP_SMOOTH_FLOOR; @@ -450,7 +470,7 @@ uint8_t off_state(Event event, uint16_t arg) { // let the user know they can let go now to stay at moon uint8_t temp = actual_level; set_level(0); - delay_4ms(2); + delay_4ms(3); set_level(temp); } else #endif @@ -635,9 +655,13 @@ uint8_t steady_state(Event event, uint16_t arg) { return MISCHIEF_MANAGED; } #ifdef USE_REVERSING - // make it ramp down instead, if already at max - if ((arg <= 1) && (actual_level >= mode_max)) { - ramp_direction = -1; + // fix ramp direction on first frame if necessary + if (!arg) { + // make it ramp down instead, if already at max + if (actual_level >= mode_max) { ramp_direction = -1; } + // make it ramp up if already at min + // (off->hold->stepped_min->release causes this state) + else if (actual_level <= mode_min) { ramp_direction = 1; } } memorized_level = nearest_level((int16_t)actual_level \ + (ramp_step_size * ramp_direction)); @@ -647,15 +671,15 @@ uint8_t steady_state(Event event, uint16_t arg) { #ifdef USE_THERMAL_REGULATION target_level = memorized_level; #endif - #if defined(BLINK_AT_RAMP_CEILING) || defined(BLINK_AT_CHANNEL_BOUNDARIES) + #if defined(BLINK_AT_RAMP_CEILING) || defined(BLINK_AT_RAMP_MIDDLE) // only blink once for each threshold if ((memorized_level != actual_level) && ( 0 // for easier syntax below - #ifdef BLINK_AT_CHANNEL_BOUNDARIES - || (memorized_level == MAX_1x7135) - #if PWM_CHANNELS >= 3 - || (memorized_level == MAX_Nx7135) + #ifdef BLINK_AT_RAMP_MIDDLE_1 + || (memorized_level == BLINK_AT_RAMP_MIDDLE_1) #endif + #ifdef BLINK_AT_RAMP_MIDDLE_2 + || (memorized_level == BLINK_AT_RAMP_MIDDLE_2) #endif #ifdef BLINK_AT_RAMP_CEILING || (memorized_level == mode_max) @@ -712,15 +736,15 @@ uint8_t steady_state(Event event, uint16_t arg) { #ifdef USE_THERMAL_REGULATION target_level = memorized_level; #endif - #if defined(BLINK_AT_RAMP_FLOOR) || defined(BLINK_AT_CHANNEL_BOUNDARIES) + #if defined(BLINK_AT_RAMP_FLOOR) || defined(BLINK_AT_RAMP_MIDDLE) // only blink once for each threshold if ((memorized_level != actual_level) && ( 0 // for easier syntax below - #ifdef BLINK_AT_CHANNEL_BOUNDARIES - || (memorized_level == MAX_1x7135) - #if PWM_CHANNELS >= 3 - || (memorized_level == MAX_Nx7135) + #ifdef BLINK_AT_RAMP_MIDDLE_1 + || (memorized_level == BLINK_AT_RAMP_MIDDLE_1) #endif + #ifdef BLINK_AT_RAMP_MIDDLE_2 + || (memorized_level == BLINK_AT_RAMP_MIDDLE_2) #endif #ifdef BLINK_AT_RAMP_FLOOR || (memorized_level == mode_min) -- cgit v1.2.3 From 06b9803baf6c11f4fc9ac98cacac78bf8a322400 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 14 Apr 2019 17:21:53 -0600 Subject: added FF E07-2 configuration with requested values --- spaghetti-monster/anduril/cfg-ff-e07-2.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 spaghetti-monster/anduril/cfg-ff-e07-2.h diff --git a/spaghetti-monster/anduril/cfg-ff-e07-2.h b/spaghetti-monster/anduril/cfg-ff-e07-2.h new file mode 100644 index 0000000..48f9c15 --- /dev/null +++ b/spaghetti-monster/anduril/cfg-ff-e07-2.h @@ -0,0 +1,27 @@ +// Fireflies E07-2 config options for Anduril / FFUI +// mostly the same as PL47 +#include "cfg-ff-pl47.h" + +// ceiling is level 130/150 (50% power) +#undef RAMP_SMOOTH_CEIL +#define RAMP_SMOOTH_CEIL 130 + +// 20, 56, 93, 130 (83 is highest regulated) +// (requested config is 1%, 5%, 25%, 50%, double-click-turbo) +// (but this doesn't allow us to hit level 83) +#undef RAMP_DISCRETE_FLOOR +#define RAMP_DISCRETE_FLOOR 20 +#undef RAMP_DISCRETE_CEIL +#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL +#undef RAMP_DISCRETE_STEPS +#define RAMP_DISCRETE_STEPS 4 + +// regulate down faster when the FET is active, slower otherwise +#undef THERM_FASTER_LEVEL +#define THERM_FASTER_LEVEL 130 // throttle back faster when high + +// play it safe, don't try to regulate above the recommended safe level +#ifndef THERM_HARD_TURBO_DROP +#define THERM_HARD_TURBO_DROP +#endif + -- cgit v1.2.3 From 1c1a91c2a7b514baedc87faaea3f397ff0ba52b2 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 14 Apr 2019 17:22:20 -0600 Subject: moved FF UI's tempcheck to 8 clicks, and re-added 7-click aux LED configuration --- spaghetti-monster/fireflies-ui/fireflies-ui.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/spaghetti-monster/fireflies-ui/fireflies-ui.c b/spaghetti-monster/fireflies-ui/fireflies-ui.c index 772d197..234ae92 100644 --- a/spaghetti-monster/fireflies-ui/fireflies-ui.c +++ b/spaghetti-monster/fireflies-ui/fireflies-ui.c @@ -551,8 +551,26 @@ uint8_t off_state(Event event, uint16_t arg) { return MISCHIEF_MANAGED; } #endif - // 7 clicks: temperature check + #ifdef USE_INDICATOR_LED + // 7 clicks: change indicator LED mode else if (event == EV_7clicks) { + uint8_t mode = (indicator_led_mode & 3) + 1; + #ifdef TICK_DURING_STANDBY + mode = mode & 3; + #else + mode = mode % 3; + #endif + #ifdef INDICATOR_LED_SKIP_LOW + if (mode == 1) { mode ++; } + #endif + indicator_led_mode = (indicator_led_mode & 0b11111100) | mode; + indicator_led(mode); + save_config(); + return MISCHIEF_MANAGED; + } + #endif + // 8 clicks: temperature check + else if (event == EV_8clicks) { set_state(tempcheck_state, 0); return MISCHIEF_MANAGED; } -- cgit v1.2.3 From 4d286f70eabea8e9d5e037250805a0ba212d224a Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 14 Apr 2019 17:25:50 -0600 Subject: moved FF E07-2 config, since it's not for Anduril... it's mostly just for FF UI --- spaghetti-monster/anduril/cfg-ff-e07-2.h | 27 --------------------------- spaghetti-monster/fireflies-ui/cfg-ff-e07-2.h | 27 +++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 27 deletions(-) delete mode 100644 spaghetti-monster/anduril/cfg-ff-e07-2.h create mode 100644 spaghetti-monster/fireflies-ui/cfg-ff-e07-2.h diff --git a/spaghetti-monster/anduril/cfg-ff-e07-2.h b/spaghetti-monster/anduril/cfg-ff-e07-2.h deleted file mode 100644 index 48f9c15..0000000 --- a/spaghetti-monster/anduril/cfg-ff-e07-2.h +++ /dev/null @@ -1,27 +0,0 @@ -// Fireflies E07-2 config options for Anduril / FFUI -// mostly the same as PL47 -#include "cfg-ff-pl47.h" - -// ceiling is level 130/150 (50% power) -#undef RAMP_SMOOTH_CEIL -#define RAMP_SMOOTH_CEIL 130 - -// 20, 56, 93, 130 (83 is highest regulated) -// (requested config is 1%, 5%, 25%, 50%, double-click-turbo) -// (but this doesn't allow us to hit level 83) -#undef RAMP_DISCRETE_FLOOR -#define RAMP_DISCRETE_FLOOR 20 -#undef RAMP_DISCRETE_CEIL -#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL -#undef RAMP_DISCRETE_STEPS -#define RAMP_DISCRETE_STEPS 4 - -// regulate down faster when the FET is active, slower otherwise -#undef THERM_FASTER_LEVEL -#define THERM_FASTER_LEVEL 130 // throttle back faster when high - -// play it safe, don't try to regulate above the recommended safe level -#ifndef THERM_HARD_TURBO_DROP -#define THERM_HARD_TURBO_DROP -#endif - diff --git a/spaghetti-monster/fireflies-ui/cfg-ff-e07-2.h b/spaghetti-monster/fireflies-ui/cfg-ff-e07-2.h new file mode 100644 index 0000000..48f9c15 --- /dev/null +++ b/spaghetti-monster/fireflies-ui/cfg-ff-e07-2.h @@ -0,0 +1,27 @@ +// Fireflies E07-2 config options for Anduril / FFUI +// mostly the same as PL47 +#include "cfg-ff-pl47.h" + +// ceiling is level 130/150 (50% power) +#undef RAMP_SMOOTH_CEIL +#define RAMP_SMOOTH_CEIL 130 + +// 20, 56, 93, 130 (83 is highest regulated) +// (requested config is 1%, 5%, 25%, 50%, double-click-turbo) +// (but this doesn't allow us to hit level 83) +#undef RAMP_DISCRETE_FLOOR +#define RAMP_DISCRETE_FLOOR 20 +#undef RAMP_DISCRETE_CEIL +#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL +#undef RAMP_DISCRETE_STEPS +#define RAMP_DISCRETE_STEPS 4 + +// regulate down faster when the FET is active, slower otherwise +#undef THERM_FASTER_LEVEL +#define THERM_FASTER_LEVEL 130 // throttle back faster when high + +// play it safe, don't try to regulate above the recommended safe level +#ifndef THERM_HARD_TURBO_DROP +#define THERM_HARD_TURBO_DROP +#endif + -- cgit v1.2.3 From a721b8df50a9578b01a6256717a5ae1625d77677 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 14 Apr 2019 17:28:11 -0600 Subject: "make clean" shouldn't remove cfg files native to this directory --- spaghetti-monster/fireflies-ui/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetti-monster/fireflies-ui/Makefile b/spaghetti-monster/fireflies-ui/Makefile index 8db198e..0b59898 100644 --- a/spaghetti-monster/fireflies-ui/Makefile +++ b/spaghetti-monster/fireflies-ui/Makefile @@ -2,6 +2,6 @@ all: ./build-all.sh clean: - rm -f *.hex cfg-*.h *~ *.elf *.o + rm -f *.hex cfg-ff-[pr]*.h *~ *.elf *.o .phony: clean -- cgit v1.2.3 From 75afd1d8843ec8d6f0cf46acb0d4a33c733ae3cc Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 9 May 2019 23:59:35 -0600 Subject: Added Mateminco MF01S build target. --- hwdef-Mateminco_MF01S.h | 60 +++++++++++++++++++++++++ spaghetti-monster/anduril/cfg-mateminco-mf01s.h | 44 ++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 hwdef-Mateminco_MF01S.h create mode 100644 spaghetti-monster/anduril/cfg-mateminco-mf01s.h diff --git a/hwdef-Mateminco_MF01S.h b/hwdef-Mateminco_MF01S.h new file mode 100644 index 0000000..ab1c5bf --- /dev/null +++ b/hwdef-Mateminco_MF01S.h @@ -0,0 +1,60 @@ +#ifndef HWDEF_MF01S_H +#define HWDEF_MF01S_H + +/* MF01S driver layout + * ---- + * Reset -|1 8|- VCC (unused) + * eswitch -|2 7|- Voltage divider (2S) + * AUX LED -|3 6|- PWM (FET) + * GND -|4 5|- PWM (smaller FET) + * ---- + */ + +#define PWM_CHANNELS 2 + +#ifndef AUXLED_PIN +#define AUXLED_PIN PB4 // pin 3 +#endif + +#ifndef SWITCH_PIN +#define SWITCH_PIN PB3 // pin 2 +#define SWITCH_PCINT PCINT3 // pin 2 pin change interrupt +#endif + +#ifndef PWM1_PIN +#define PWM1_PIN PB0 // pin 5, 1x7135 PWM +#define PWM1_LVL OCR0A // OCR0A is the output compare register for PB0 +#endif +#ifndef PWM2_PIN +#define PWM2_PIN PB1 // pin 6, FET PWM +#define PWM2_LVL OCR0B // OCR0B is the output compare register for PB1 +#endif + +#define USE_VOLTAGE_DIVIDER // use a voltage divider on pin 7, not VCC +#ifndef VOLTAGE_PIN +#define VOLTAGE_PIN PB2 // pin 7, voltage ADC +#define VOLTAGE_CHANNEL 0x01 // MUX 01 corresponds with PB2 +#define VOLTAGE_ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2 +// 1.1V reference, left-adjust, ADC1/PB2 +//#define ADMUX_VOLTAGE_DIVIDER ((1 << V_REF) | (1 << ADLAR) | VOLTAGE_CHANNEL) +// 1.1V reference, no left-adjust, ADC1/PB2 +#define ADMUX_VOLTAGE_DIVIDER ((1 << V_REF) | VOLTAGE_CHANNEL) +#endif +#define ADC_PRSCL 0x06 // clk/64 + +// Raw ADC readings at 4.4V and 2.2V (in-between, we assume values form a straight line) +#ifndef ADC_44 +#define ADC_44 234 +#endif +#ifndef ADC_22 +#define ADC_22 117 +#endif + +#define TEMP_CHANNEL 0b00001111 + +#define FAST 0xA3 // fast PWM both channels +#define PHASE 0xA1 // phase-correct PWM both channels + +#define LAYOUT_DEFINED + +#endif diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h new file mode 100644 index 0000000..aed1188 --- /dev/null +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h @@ -0,0 +1,44 @@ +// Mateminco/Astrolux MF01S options for Anduril +#include "hwdef-Mateminco_MF01S.h" + +// the button lights up +#define USE_INDICATOR_LED +// the button is visible while main LEDs are on +//#define USE_INDICATOR_LED_WHILE_RAMPING +// enable blinking indicator LED while off +#define TICK_DURING_STANDBY +#define STANDBY_TICK_SPEED 3 // every 0.128 s +#define USE_FANCIER_BLINKING_INDICATOR +// off mode: low (1) +// lockout: blinking (3) +#define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 1) + + +// don't blink during ramp, it's irrelevant and annoying on this light +#define BLINK_AT_RAMP_CEILING +#undef BLINK_AT_RAMP_MIDDLE +#undef BLINK_AT_RAMP_FLOOR + +// measured brightness with 4x30Q cells at 4.11V: +// moon: 2.5 lm +// channel 1: 617 lm +// channel 2: 13500 lm +// ../../../bin/level_calc.py seventh 2 150 7135 1 12 717 FET 3 10 13000 +#define RAMP_LENGTH 150 +#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,5,6,7,7,8,9,10,11,12,13,14,15,16,18,19,20,22,24,25,27,29,31,33,35,38,40,43,46,48,51,55,58,61,65,69,73,77,81,86,90,95,101,106,112,118,124,130,137,144,151,159,167,175,184,193,202,212,222,232,243,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0 +#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,4,5,6,6,7,8,9,10,11,12,13,14,15,16,17,18,20,21,22,24,25,27,28,30,31,33,35,37,38,40,42,44,47,49,51,53,56,58,61,63,66,69,72,75,78,81,84,88,91,95,98,102,106,110,114,118,123,127,132,136,141,146,151,157,162,168,173,179,185,191,198,204,211,218,225,232,240,247,255 +#define MAX_1x7135 70 // ~626 lm +#define HALFSPEED_LEVEL 23 +#define QUARTERSPEED_LEVEL 6 + +#define RAMP_SMOOTH_FLOOR 1 // ~2.5 lm +#define RAMP_SMOOTH_CEIL 120 // ~5400 lm +// 20, 36, 53, [70], 86, 103, 120 +#define RAMP_DISCRETE_FLOOR 20 // 35 lm +#define RAMP_DISCRETE_CEIL 120 // ~5400 lm +#define RAMP_DISCRETE_STEPS 7 // 35, 108, 280, 626, 1500, 2930, 5400 lm + +#define USE_TENCLICK_THERMAL_CONFIG // by request +#define THERM_FASTER_LEVEL 125 // throttle back faster when high (>6000 lm) +#define THERM_HARD_TURBO_DROP // this light is massively overpowered + -- cgit v1.2.3 From c135d7f36bbb1cc1a122b7440f87c6f001a11d12 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 10 May 2019 01:13:57 -0600 Subject: renamed ff-edc-thrower to ff-e01, now that it has a name... also, added a separate config file for it for Anduril --- spaghetti-monster/anduril/cfg-ff-e01.h | 31 ++++++++++++++++++++++ spaghetti-monster/fireflies-ui/build-all.sh | 2 +- spaghetti-monster/fireflies-ui/cfg-ff-e01.h | 27 +++++++++++++++++++ .../fireflies-ui/cfg-ff-edc-thrower.h | 27 ------------------- 4 files changed, 59 insertions(+), 28 deletions(-) create mode 100644 spaghetti-monster/anduril/cfg-ff-e01.h create mode 100644 spaghetti-monster/fireflies-ui/cfg-ff-e01.h delete mode 100644 spaghetti-monster/fireflies-ui/cfg-ff-edc-thrower.h diff --git a/spaghetti-monster/anduril/cfg-ff-e01.h b/spaghetti-monster/anduril/cfg-ff-e01.h new file mode 100644 index 0000000..432f37b --- /dev/null +++ b/spaghetti-monster/anduril/cfg-ff-e01.h @@ -0,0 +1,31 @@ +// Fireflies E01 SST-40 thrower config options for Anduril +#include "cfg-ff-pl47.h" + +// disable indicator LED +#undef USE_INDICATOR_LED +#undef TICK_DURING_STANDBY + +// ceiling is level 130/150 (50% power) +#undef RAMP_SMOOTH_CEIL +#define RAMP_SMOOTH_CEIL 130 +#define BLINK_AT_RAMP_CEILING + +// 13, 36, 59, [83], 106, 130 (83 is highest regulated) +#undef RAMP_DISCRETE_FLOOR +#define RAMP_DISCRETE_FLOOR 13 +#undef RAMP_DISCRETE_CEIL +#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL +#undef RAMP_DISCRETE_STEPS +#define RAMP_DISCRETE_STEPS 6 + +// regulate down faster when the FET is active, slower otherwise +#undef THERM_FASTER_LEVEL +#define THERM_FASTER_LEVEL 130 // throttle back faster when high + +// play it safe, don't try to regulate above the recommended safe level +#ifndef THERM_HARD_TURBO_DROP +#define THERM_HARD_TURBO_DROP +#endif + +// shortcut for first-time setup +#define USE_TENCLICK_THERMAL_CONFIG diff --git a/spaghetti-monster/fireflies-ui/build-all.sh b/spaghetti-monster/fireflies-ui/build-all.sh index 41d92d0..81ebd97 100755 --- a/spaghetti-monster/fireflies-ui/build-all.sh +++ b/spaghetti-monster/fireflies-ui/build-all.sh @@ -1,6 +1,6 @@ #!/bin/sh -cp -av ../anduril/cfg-ff*.h . +cp -av --no-clobber ../anduril/cfg-ff*.h . UI=fireflies-ui diff --git a/spaghetti-monster/fireflies-ui/cfg-ff-e01.h b/spaghetti-monster/fireflies-ui/cfg-ff-e01.h new file mode 100644 index 0000000..31be0ef --- /dev/null +++ b/spaghetti-monster/fireflies-ui/cfg-ff-e01.h @@ -0,0 +1,27 @@ +// Fireflies EDC thrower config options for Fireflies UI +#include "cfg-ff-pl47.h" + +// disable indicator LED +#undef USE_INDICATOR_LED + +// ceiling is level 130/150 (50% power) +#undef RAMP_SMOOTH_CEIL +#define RAMP_SMOOTH_CEIL 130 + +// 36, 83, 130 (83 is highest regulated) +#undef RAMP_DISCRETE_FLOOR +#define RAMP_DISCRETE_FLOOR 36 +#undef RAMP_DISCRETE_CEIL +#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL +#undef RAMP_DISCRETE_STEPS +#define RAMP_DISCRETE_STEPS 3 + +// regulate down faster when the FET is active, slower otherwise +#undef THERM_FASTER_LEVEL +#define THERM_FASTER_LEVEL 130 // throttle back faster when high + +// play it safe, don't try to regulate above the recommended safe level +#ifndef THERM_HARD_TURBO_DROP +#define THERM_HARD_TURBO_DROP +#endif + diff --git a/spaghetti-monster/fireflies-ui/cfg-ff-edc-thrower.h b/spaghetti-monster/fireflies-ui/cfg-ff-edc-thrower.h deleted file mode 100644 index 31be0ef..0000000 --- a/spaghetti-monster/fireflies-ui/cfg-ff-edc-thrower.h +++ /dev/null @@ -1,27 +0,0 @@ -// Fireflies EDC thrower config options for Fireflies UI -#include "cfg-ff-pl47.h" - -// disable indicator LED -#undef USE_INDICATOR_LED - -// ceiling is level 130/150 (50% power) -#undef RAMP_SMOOTH_CEIL -#define RAMP_SMOOTH_CEIL 130 - -// 36, 83, 130 (83 is highest regulated) -#undef RAMP_DISCRETE_FLOOR -#define RAMP_DISCRETE_FLOOR 36 -#undef RAMP_DISCRETE_CEIL -#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL -#undef RAMP_DISCRETE_STEPS -#define RAMP_DISCRETE_STEPS 3 - -// regulate down faster when the FET is active, slower otherwise -#undef THERM_FASTER_LEVEL -#define THERM_FASTER_LEVEL 130 // throttle back faster when high - -// play it safe, don't try to regulate above the recommended safe level -#ifndef THERM_HARD_TURBO_DROP -#define THERM_HARD_TURBO_DROP -#endif - -- cgit v1.2.3 From 57efd792c50af6b9d8b28f2e2bf91dcc57a7d447 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 11 May 2019 00:41:14 -0600 Subject: attempt to reduce mid-ramp "pop" --- spaghetti-monster/anduril/cfg-mateminco-mf01s.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h index aed1188..b4a441a 100644 --- a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h @@ -26,7 +26,7 @@ // ../../../bin/level_calc.py seventh 2 150 7135 1 12 717 FET 3 10 13000 #define RAMP_LENGTH 150 #define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,5,6,7,7,8,9,10,11,12,13,14,15,16,18,19,20,22,24,25,27,29,31,33,35,38,40,43,46,48,51,55,58,61,65,69,73,77,81,86,90,95,101,106,112,118,124,130,137,144,151,159,167,175,184,193,202,212,222,232,243,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0 -#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,4,5,6,6,7,8,9,10,11,12,13,14,15,16,17,18,20,21,22,24,25,27,28,30,31,33,35,37,38,40,42,44,47,49,51,53,56,58,61,63,66,69,72,75,78,81,84,88,91,95,98,102,106,110,114,118,123,127,132,136,141,146,151,157,162,168,173,179,185,191,198,204,211,218,225,232,240,247,255 +#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,8,9,10,11,12,13,15,16,17,18,20,21,23,24,26,27,29,31,32,34,36,38,40,42,44,46,49,51,54,56,59,61,64,67,70,73,76,79,82,86,89,93,97,100,104,108,112,117,121,126,130,135,140,145,150,156,161,167,172,178,184,191,197,204,210,217,225,232,239,247,255 #define MAX_1x7135 70 // ~626 lm #define HALFSPEED_LEVEL 23 #define QUARTERSPEED_LEVEL 6 -- cgit v1.2.3 From 228b5a359900eb6865b968cc668075aba5f2b795 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 11 May 2019 03:22:32 -0600 Subject: smoothed out MF01S tint "pop" a little more by making a few steps which are sort of "in-between" FET PWM values --- spaghetti-monster/anduril/cfg-mateminco-mf01s.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h index b4a441a..0585b38 100644 --- a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h @@ -23,10 +23,11 @@ // moon: 2.5 lm // channel 1: 617 lm // channel 2: 13500 lm -// ../../../bin/level_calc.py seventh 2 150 7135 1 12 717 FET 3 10 13000 +// ../../../bin/level_calc.py seventh 2 150 7135 1 12 717 FET 1 10 13000 +// (with some manual tweaks afterward) #define RAMP_LENGTH 150 -#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,5,6,7,7,8,9,10,11,12,13,14,15,16,18,19,20,22,24,25,27,29,31,33,35,38,40,43,46,48,51,55,58,61,65,69,73,77,81,86,90,95,101,106,112,118,124,130,137,144,151,159,167,175,184,193,202,212,222,232,243,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0 -#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,8,9,10,11,12,13,15,16,17,18,20,21,23,24,26,27,29,31,32,34,36,38,40,42,44,46,49,51,54,56,59,61,64,67,70,73,76,79,82,86,89,93,97,100,104,108,112,117,121,126,130,135,140,145,150,156,161,167,172,178,184,191,197,204,210,217,225,232,239,247,255 +#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,5,6,7,7,8,9,10,11,12,13,14,15,17,18,19,21,22,24,26,28,30,32,34,36,38,41,44,46,49,52,55,59,62,66,70,74,78,83,87,92,97,102,108,114,120,126,133,139,147,154,162,170,178,187,196,206,215,226,236,248,255,235,255,240,255,245,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0 +#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,3,3,4,4,5,6,7,8,9,10,11,12,13,14,16,17,19,20,22,23,25,26,28,30,31,33,35,37,39,41,43,45,47,49,52,54,57,59,62,65,67,70,73,76,80,83,86,90,93,97,101,105,109,113,117,122,126,131,135,140,145,151,156,161,167,173,179,185,191,197,204,211,218,225,232,239,247,255 #define MAX_1x7135 70 // ~626 lm #define HALFSPEED_LEVEL 23 #define QUARTERSPEED_LEVEL 6 -- cgit v1.2.3 From dc085b52674c5abfc19bc46f2866976931de3de3 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 12 May 2019 04:14:34 -0600 Subject: completely recalibrated FF E01 to match production sample --- spaghetti-monster/anduril/cfg-ff-e01.h | 30 +++++------------- spaghetti-monster/fireflies-ui/cfg-ff-e01.h | 49 +++++++++++++++++++---------- 2 files changed, 40 insertions(+), 39 deletions(-) diff --git a/spaghetti-monster/anduril/cfg-ff-e01.h b/spaghetti-monster/anduril/cfg-ff-e01.h index 432f37b..3b47165 100644 --- a/spaghetti-monster/anduril/cfg-ff-e01.h +++ b/spaghetti-monster/anduril/cfg-ff-e01.h @@ -1,31 +1,15 @@ // Fireflies E01 SST-40 thrower config options for Anduril -#include "cfg-ff-pl47.h" +// most of the good stuff is in the FFUI config; just copy it +#include "../fireflies-ui/cfg-ff-e01.h" -// disable indicator LED -#undef USE_INDICATOR_LED -#undef TICK_DURING_STANDBY - -// ceiling is level 130/150 (50% power) -#undef RAMP_SMOOTH_CEIL -#define RAMP_SMOOTH_CEIL 130 +#ifndef BLINK_AT_RAMP_CEILING #define BLINK_AT_RAMP_CEILING +#endif -// 13, 36, 59, [83], 106, 130 (83 is highest regulated) -#undef RAMP_DISCRETE_FLOOR -#define RAMP_DISCRETE_FLOOR 13 -#undef RAMP_DISCRETE_CEIL -#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL +// 20, 38, 56, 75, [93], 111, 130 (93 is highest regulated) +// (9 / 45 / 116 / 248 / 467 / 742 / 1280 + 2140 lm) #undef RAMP_DISCRETE_STEPS -#define RAMP_DISCRETE_STEPS 6 - -// regulate down faster when the FET is active, slower otherwise -#undef THERM_FASTER_LEVEL -#define THERM_FASTER_LEVEL 130 // throttle back faster when high - -// play it safe, don't try to regulate above the recommended safe level -#ifndef THERM_HARD_TURBO_DROP -#define THERM_HARD_TURBO_DROP -#endif +#define RAMP_DISCRETE_STEPS 7 // shortcut for first-time setup #define USE_TENCLICK_THERMAL_CONFIG diff --git a/spaghetti-monster/fireflies-ui/cfg-ff-e01.h b/spaghetti-monster/fireflies-ui/cfg-ff-e01.h index 31be0ef..42c23b2 100644 --- a/spaghetti-monster/fireflies-ui/cfg-ff-e01.h +++ b/spaghetti-monster/fireflies-ui/cfg-ff-e01.h @@ -1,27 +1,44 @@ // Fireflies EDC thrower config options for Fireflies UI -#include "cfg-ff-pl47.h" +// (uses PL47 driver) +#include "hwdef-FF_PL47.h" -// disable indicator LED +// disable indicator LED; it's hardwired +#ifdef USE_INDICATOR_LED #undef USE_INDICATOR_LED +#endif + +// don't do this +#undef BLINK_AT_RAMP_MIDDLE +#undef BLINK_AT_RAMP_CEILING + +// ramp shape and size +#define RAMP_LENGTH 150 + +// driver is a FET + 3x7135, ~413 lm at highest regulated level +// ../../../bin/level_calc.py seventh 2 150 7135 1 12 414 FET 2 10 1930 +#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,5,6,6,7,8,8,9,10,10,11,12,13,14,15,15,16,17,18,20,21,22,23,24,26,27,28,30,31,33,34,36,38,39,41,43,45,47,49,51,53,56,58,60,63,65,68,71,74,77,80,83,86,89,93,96,100,103,107,111,115,119,124,128,132,137,142,147,152,157,163,168,174,180,186,192,198,204,211,218,225,232,240,247,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0 +#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5,7,9,12,14,16,19,22,24,27,30,33,36,39,42,45,48,52,55,58,62,66,69,73,77,81,85,90,94,98,103,107,112,117,122,127,132,137,143,148,154,160,166,172,178,184,191,197,204,211,218,225,232,240,247,255 +#define MAX_1x7135 93 +#define HALFSPEED_LEVEL 14 +#define QUARTERSPEED_LEVEL 7 + +#define MIN_THERM_STEPDOWN 65 // lowest value it'll step down to + // ceiling is level 130/150 (50% power) -#undef RAMP_SMOOTH_CEIL +#define RAMP_SMOOTH_FLOOR 1 #define RAMP_SMOOTH_CEIL 130 -// 36, 83, 130 (83 is highest regulated) -#undef RAMP_DISCRETE_FLOOR -#define RAMP_DISCRETE_FLOOR 36 -#undef RAMP_DISCRETE_CEIL +// 20, 56, [93], 130 (93 is highest regulated) +// (8 / 102 / 413 / 1163 + 1930 lm) +#define RAMP_DISCRETE_FLOOR 20 #define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL -#undef RAMP_DISCRETE_STEPS -#define RAMP_DISCRETE_STEPS 3 +#define RAMP_DISCRETE_STEPS 4 -// regulate down faster when the FET is active, slower otherwise -#undef THERM_FASTER_LEVEL -#define THERM_FASTER_LEVEL 130 // throttle back faster when high +// ~25 lm to ~400 lm +#define MUGGLE_FLOOR 30 +#define MUGGLE_CEILING MAX_1x7135 -// play it safe, don't try to regulate above the recommended safe level -#ifndef THERM_HARD_TURBO_DROP -#define THERM_HARD_TURBO_DROP -#endif +// throttle back faster when high +#define THERM_FASTER_LEVEL 130 -- cgit v1.2.3 From 059c9498899f7dc4eaab9095fb2b31d793274f05 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 22 May 2019 14:38:14 -0600 Subject: Fixed blip in PL47-219 ramp --- spaghetti-monster/anduril/cfg-ff-pl47-219.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spaghetti-monster/anduril/cfg-ff-pl47-219.h b/spaghetti-monster/anduril/cfg-ff-pl47-219.h index 3ded2aa..ad66adb 100644 --- a/spaghetti-monster/anduril/cfg-ff-pl47-219.h +++ b/spaghetti-monster/anduril/cfg-ff-pl47-219.h @@ -3,5 +3,7 @@ // to avoid destroying the LEDs #include "cfg-ff-pl47.h" +#undef PWM1_LEVELS #undef PWM2_LEVELS +#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,5,6,6,7,8,8,9,10,10,11,12,13,14,15,16,17,18,19,21,22,23,25,26,27,29,31,32,34,36,38,40,42,44,46,49,51,54,56,59,62,65,68,71,74,78,81,85,89,93,97,101,106,110,115,120,125,130,136,141,147,153,160,166,173,180,187,195,202,210,219,227,236,245,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 #define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,16,17,19,20,22,23,25,27,28,30,31,33,35,37,39,41,43,45,47,50,52,55,57,60,63,65,68,71,74,77,80,83,87,90,93,97,101,105,108,112,116,121,125,129,134,139,143,148,153,159,164,169 -- cgit v1.2.3 From 3aa46f6ec0068e5e1245a200856ab925e30b445a Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 22 May 2019 14:42:02 -0600 Subject: Rewrote thermal regulation. Seems to be much more stable now... doesn't bounce, doesn't overshoot, doesn't lag. (at least on the lights I've tested so far... PL47-219, FF E01, MF01S) --- spaghetti-monster/anduril/anduril.c | 20 +++--- spaghetti-monster/anduril/cfg-emisar-d4.h | 4 +- spaghetti-monster/anduril/cfg-ff-pl47.h | 6 +- spaghetti-monster/fsm-adc.c | 111 +++++++++++------------------- 4 files changed, 58 insertions(+), 83 deletions(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 5878d47..fadf51e 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -1697,12 +1697,13 @@ uint8_t muggle_state(Event event, uint16_t arg) { #ifdef USE_THERMAL_REGULATION // overheating is handled specially in muggle mode else if(event == EV_temperature_high) { - // don't even try... - // go immediately to the bottom, in case someone put the light on - // maximum while wrapped in dark-colored flammable insulation - // or something, because muggles are cool like that - // memorized_level = MUGGLE_FLOOR; // override memory? maybe not - set_level(MUGGLE_FLOOR); + #if 0 + blip(); + #endif + // step down proportional to the amount of overheating + uint8_t new = actual_level - arg; + if (new < MUGGLE_FLOOR) { new = MUGGLE_FLOOR; } + set_level(new); return MISCHIEF_MANAGED; } #endif @@ -1800,14 +1801,15 @@ void thermal_config_save() { // calibrate room temperature val = config_state_values[0]; if (val) { - int8_t rawtemp = (temperature >> 1) - therm_cal_offset; + int8_t rawtemp = temperature - therm_cal_offset; therm_cal_offset = val - rawtemp; + reset_thermal_history = 1; // invalidate all recent temperature data } val = config_state_values[1]; if (val) { // set maximum heat limit - therm_ceil = 30 + val; + therm_ceil = 30 + val - 1; } if (therm_ceil > MAX_THERM_CEIL) therm_ceil = MAX_THERM_CEIL; } @@ -2243,7 +2245,7 @@ void loop() { #ifdef USE_THERMAL_REGULATION // TODO: blink out therm_ceil during thermal_config_state? else if (state == tempcheck_state) { - blink_num(temperature>>1); + blink_num(temperature); nice_delay_ms(1000); } #endif diff --git a/spaghetti-monster/anduril/cfg-emisar-d4.h b/spaghetti-monster/anduril/cfg-emisar-d4.h index 2f4df49..3ce0fd7 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4.h @@ -13,7 +13,9 @@ // optional, makes initial turbo step-down faster so first peak isn't as hot // the D4 runs very very hot, so be extra careful -#define THERM_HARD_TURBO_DROP +#ifdef THERM_HARD_TURBO_DROP +#undef THERM_HARD_TURBO_DROP +#endif // stop panicking at ~30% power or ~1200 lm #define THERM_FASTER_LEVEL 105 diff --git a/spaghetti-monster/anduril/cfg-ff-pl47.h b/spaghetti-monster/anduril/cfg-ff-pl47.h index f9c8974..7a81c25 100644 --- a/spaghetti-monster/anduril/cfg-ff-pl47.h +++ b/spaghetti-monster/anduril/cfg-ff-pl47.h @@ -59,10 +59,12 @@ //#define MUGGLE_CEILING 90 // regulate down faster when the FET is active, slower otherwise -#define THERM_FASTER_LEVEL 130 // throttle back faster when high +#define THERM_FASTER_LEVEL 135 // throttle back faster when high // play it safe, don't try to regulate above the recommended safe level -#define THERM_HARD_TURBO_DROP +#ifdef THERM_HARD_TURBO_DROP +#undef THERM_HARD_TURBO_DROP +#endif // don't do this #undef BLINK_AT_RAMP_MIDDLE diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 8decd9d..bcf49ed 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -89,20 +89,16 @@ ISR(ADC_vect) { // thermal declarations #ifdef USE_THERMAL_REGULATION - #define NUM_THERMAL_VALUES 8 - #define NUM_THERMAL_VALUES_HISTORY 16 - #define NUM_THERMAL_PROJECTED_HISTORY 8 + #define NUM_THERMAL_VALUES_HISTORY 8 #define ADC_STEPS 4 - static int16_t temperature_values[NUM_THERMAL_VALUES]; // last few readings in C - static int16_t temperature_history[NUM_THERMAL_VALUES_HISTORY]; // 14.1 fixed-point - static int16_t projected_temperature_history[NUM_THERMAL_PROJECTED_HISTORY]; // 14.1 fixed-point - static uint8_t projected_temperature_history_counter = 0; + static uint8_t history_step = 0; // don't update history as often + static int16_t temperature_history[NUM_THERMAL_VALUES_HISTORY]; static uint8_t temperature_timer = 0; static uint8_t overheat_lowpass = 0; static uint8_t underheat_lowpass = 0; #define TEMPERATURE_TIMER_START (THERMAL_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) // N seconds between thermal regulation events - #define OVERHEAT_LOWPASS_STRENGTH ADC_CYCLES_PER_SECOND // lowpass for one second - #define UNDERHEAT_LOWPASS_STRENGTH ADC_CYCLES_PER_SECOND // lowpass for one second + #define OVERHEAT_LOWPASS_STRENGTH (ADC_CYCLES_PER_SECOND*2) // lowpass for 2 seconds + #define UNDERHEAT_LOWPASS_STRENGTH (ADC_CYCLES_PER_SECOND*2) // lowpass for 2 seconds #else #define ADC_STEPS 2 #endif @@ -190,33 +186,17 @@ ISR(ADC_vect) { // prime on first execution if (reset_thermal_history) { reset_thermal_history = 0; - for(uint8_t i=0; i temperature) { + temperature ++; + } else if (temp < temperature) { + temperature --; } - temperature_values[i] = temp; - total += temp; - - // Divide back to original range: - //temperature = total >> 2; - // More precise method: use noise as extra precision - // (values are now basically fixed-point, signed 13.2) - //temperature = total; - // 14.1 is less prone to overflows - temperature = total >> 2; } // guess what the temperature will be in a few seconds @@ -230,18 +210,20 @@ ISR(ADC_vect) { // how far ahead should we predict? #define THERM_PREDICTION_STRENGTH 4 // how proportional should the adjustments be? - #define THERM_DIFF_ATTENUATION 3 // acceptable temperature window size in C - #define THERM_WINDOW_SIZE 10 + #define THERM_WINDOW_SIZE 5 // highest temperature allowed - // (convert configured value to 14.1 fixed-point) - #define THERM_CEIL (((int16_t)therm_ceil)<<1) - // bottom of target temperature window (14.1 fixed-point) - #define THERM_FLOOR (THERM_CEIL - (THERM_WINDOW_SIZE<<1)) - - // rotate measurements and add a new one - for (i=0; i 0) diff --; + } // projected_temperature = current temp extended forward by amplified rate of change //projected_temperature = temperature_history[NUM_THERMAL_VALUES_HISTORY-1] + (diff< THERM_FLOOR) { underheat_lowpass = 0; // we're probably not too cold @@ -280,7 +253,7 @@ ISR(ADC_vect) { } else { // it has been long enough since the last warning // Too hot? - if (avg_projected_temperature > THERM_CEIL) { + if (pt > THERM_CEIL) { if (overheat_lowpass < OVERHEAT_LOWPASS_STRENGTH) { overheat_lowpass ++; } else { @@ -288,16 +261,14 @@ ISR(ADC_vect) { overheat_lowpass = 0; temperature_timer = TEMPERATURE_TIMER_START; // how far above the ceiling? - int16_t howmuch = (avg_projected_temperature - THERM_CEIL) >> THERM_DIFF_ATTENUATION; - if (howmuch > 0) { - // try to send out a warning - emit(EV_temperature_high, howmuch); - } + int16_t howmuch = pt - THERM_CEIL; + // try to send out a warning + emit(EV_temperature_high, howmuch); } } // Too cold? - else if (avg_projected_temperature < THERM_FLOOR) { + else if (pt < THERM_FLOOR) { if (underheat_lowpass < UNDERHEAT_LOWPASS_STRENGTH) { underheat_lowpass ++; } else { @@ -305,13 +276,11 @@ ISR(ADC_vect) { underheat_lowpass = 0; temperature_timer = TEMPERATURE_TIMER_START; // how far below the floor? - int16_t howmuch = (THERM_FLOOR - avg_projected_temperature) >> THERM_DIFF_ATTENUATION; - if (howmuch > 0) { - // try to send out a warning (unless voltage is low) - // (LVP and underheat warnings fight each other) - if (voltage > VOLTAGE_LOW) - emit(EV_temperature_low, howmuch); - } + int16_t howmuch = THERM_FLOOR - pt; + // try to send out a warning (unless voltage is low) + // (LVP and underheat warnings fight each other) + if (voltage > VOLTAGE_LOW) + emit(EV_temperature_low, howmuch); } } } -- cgit v1.2.3 From 7078f9c66d36deb1f1c8eeeb631bdc2f5465de01 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 22 May 2019 16:01:07 -0600 Subject: made momentary mode also do strobes --- spaghetti-monster/anduril/anduril-manual.txt | 20 ++++++++++++---- spaghetti-monster/anduril/anduril.c | 36 +++++++++++++++++++++++----- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/spaghetti-monster/anduril/anduril-manual.txt b/spaghetti-monster/anduril/anduril-manual.txt index 96640f6..3684b50 100644 --- a/spaghetti-monster/anduril/anduril-manual.txt +++ b/spaghetti-monster/anduril/anduril-manual.txt @@ -223,11 +223,23 @@ Momentary Mode Click 5 times from Off to enter Momentary mode. This locks the flashlight into a single-mode interface where the LEDs are only on when -the button is held down. It is intended for Morse code and other -signalling tasks. +the button is held down. It is intended for Morse code, light painting, +and other tasks where the light should be on only for a short time and +probably in a pattern. -Brightness is the last-ramped level, so adjust that before entering -momentary mode. +Momentary mode does either a steady brightness level or a strobe. To +select which one, go to the mode you want to use, adjust the brightness +and speed and other settings, then turn the light off. Then click 5 +times to enter momentary mode. + +Supported momentary modes are steady (normal ramping mode) and strobes +(everything in the "strobe" mode group). + +In steady mode, brightness is the last-ramped level, so adjust that +before entering momentary mode. + +In momentary strobe mode, the settings are copied from the last-used +strobe mode, such as party strobe, tactical strobe, or lightning. To exit this mode, physically disconnect power by unscrewing the tailcap or battery tube. diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index fadf51e..0fb9386 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -244,6 +244,8 @@ uint8_t beacon_config_state(Event event, uint16_t arg); uint8_t lockout_state(Event event, uint16_t arg); // momentary / signalling mode uint8_t momentary_state(Event event, uint16_t arg); +uint8_t momentary_mode = 0; // 0 = ramping, 1 = strobe +uint8_t momentary_active = 0; // boolean, true if active *right now* #ifdef USE_MUGGLE_MODE // muggle mode, super-simple, hard to exit uint8_t muggle_state(Event event, uint16_t arg); @@ -568,6 +570,7 @@ uint8_t steady_state(Event event, uint16_t arg) { // turn LED on when we first enter the mode if ((event == EV_enter_state) || (event == EV_reenter_state)) { + momentary_mode = 0; // 0 = ramping, 1 = strobes // if we just got back from config mode, go back to memorized level if (event == EV_reenter_state) { arg = memorized_level; @@ -935,6 +938,8 @@ uint8_t strobe_state(Event event, uint16_t arg) { // (maybe I should just make it nonvolatile?) strobe_mode_te st = strobe_type; + momentary_mode = 1; // 0 = ramping, 1 = strobes + #ifdef USE_CANDLE_MODE // pass all events to candle mode, when it's active // (the code is in its own pseudo-state to keep things cleaner) @@ -1542,14 +1547,24 @@ uint8_t lockout_state(Event event, uint16_t arg) { uint8_t momentary_state(Event event, uint16_t arg) { // TODO: momentary strobe here? (for light painting) + // init strobe mode, if relevant + if ((event == EV_enter_state) && (momentary_mode == 1)) { + strobe_state(event, arg); + } + // light up when the button is pressed; go dark otherwise // button is being held if ((event & (B_CLICK | B_PRESS)) == (B_CLICK | B_PRESS)) { - set_level(memorized_level); + momentary_active = 1; + // 0 = ramping, 1 = strobes + if (momentary_mode == 0) { + set_level(memorized_level); + } return MISCHIEF_MANAGED; } // button was released else if ((event & (B_CLICK | B_PRESS)) == (B_CLICK)) { + momentary_active = 0; set_level(0); //go_to_standby = 1; // sleep while light is off return MISCHIEF_MANAGED; @@ -1560,10 +1575,18 @@ uint8_t momentary_state(Event event, uint16_t arg) { // with exiting via tailcap loosen+tighten unless you leave power // disconnected for several seconds, so we want to be awake when that // happens to speed up the process) - else if ((event == EV_tick) && (actual_level == 0)) { - if (arg > TICKS_PER_SECOND*15) { // sleep after 15 seconds - go_to_standby = 1; // sleep while light is off - // TODO: lighted button should use lockout config? + else if (event == EV_tick) { + if (momentary_active) { + // 0 = ramping, 1 = strobes + if (momentary_mode == 1) { + return strobe_state(event, arg); + } + } + else { + if (arg > TICKS_PER_SECOND*15) { // sleep after 15 seconds + go_to_standby = 1; // sleep while light is off + // TODO: lighted button should use lockout config? + } } return MISCHIEF_MANAGED; } @@ -2181,7 +2204,8 @@ void loop() { if (0) {} #ifdef USE_STROBE_STATE - else if (state == strobe_state) { + else if ((state == strobe_state) + || ((state == momentary_state) && (momentary_mode == 1) && (momentary_active)) ) { // also handle momentary strobes uint8_t st = strobe_type; switch(st) { -- cgit v1.2.3 From 49c3d63ec197f39d94fb35ca8cce3cd28981c9f2 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 22 May 2019 16:22:58 -0600 Subject: enabled fancy (2-level) lockout momentary moon by default --- spaghetti-monster/anduril/anduril.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 0fb9386..6aa6198 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -240,7 +240,7 @@ uint8_t beacon_config_state(Event event, uint16_t arg); // soft lockout #define MOON_DURING_LOCKOUT_MODE // if enabled, 2nd lockout click goes to the other ramp's floor level -//#define LOCKOUT_MOON_FANCY +#define LOCKOUT_MOON_FANCY uint8_t lockout_state(Event event, uint16_t arg); // momentary / signalling mode uint8_t momentary_state(Event event, uint16_t arg); -- cgit v1.2.3 From 4df0180a21786e4e1128866602f33ce09d4a62bd Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 22 May 2019 18:22:09 -0600 Subject: made ramp-able strobe modes auto-reverse (mostly like the main ramp does) --- spaghetti-monster/anduril/anduril.c | 54 ++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 6aa6198..f9509e7 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -934,6 +934,8 @@ uint8_t tint_ramping_state(Event event, uint16_t arg) { #ifdef USE_STROBE_STATE uint8_t strobe_state(Event event, uint16_t arg) { + static int8_t ramp_direction = 1; + // 'st' reduces ROM size by avoiding access to a volatile var // (maybe I should just make it nonvolatile?) strobe_mode_te st = strobe_type; @@ -949,11 +951,11 @@ uint8_t strobe_state(Event event, uint16_t arg) { #endif if (0) {} // placeholder - /* not used any more + // init anything which needs to be initialized else if (event == EV_enter_state) { + ramp_direction = 1; return MISCHIEF_MANAGED; } - */ // 1 click: off else if (event == EV_1click) { set_state(off_state, 0); @@ -978,7 +980,11 @@ uint8_t strobe_state(Event event, uint16_t arg) { else if (st == party_strobe_e) { #endif if ((arg & 1) == 0) { - if (strobe_delays[st] > 8) strobe_delays[st] --; + uint8_t d = strobe_delays[st]; + d -= ramp_direction; + if (d < 8) d = 8; + else if (d > 254) d = 254; + strobe_delays[st] = d; } } #endif @@ -989,17 +995,27 @@ uint8_t strobe_state(Event event, uint16_t arg) { // biking mode brighter #ifdef USE_BIKE_FLASHER_MODE else if (st == bike_flasher_e) { - if (bike_flasher_brightness < MAX_BIKING_LEVEL) - bike_flasher_brightness ++; + 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); } #endif return MISCHIEF_MANAGED; } + // reverse ramp direction on hold release + // ... and save new strobe settings + else if (event == EV_click1_hold_release) { + ramp_direction = -ramp_direction; + save_config(); + return MISCHIEF_MANAGED; + } // click, hold: change speed (go slower) // or change brightness (dimmer) else if (event == EV_click2_hold) { + ramp_direction = 1; + if (0) {} // placeholder // party / tactical strobe slower @@ -1030,14 +1046,16 @@ uint8_t strobe_state(Event event, uint16_t arg) { return MISCHIEF_MANAGED; } // release hold: save new strobe settings - else if ((event == EV_click1_hold_release) - || (event == EV_click2_hold_release)) { + else if (event == EV_click2_hold_release) { save_config(); return MISCHIEF_MANAGED; } #if defined(USE_LIGHTNING_MODE) || defined(USE_CANDLE_MODE) // clock tick: bump the random seed else if (event == EV_tick) { + // un-reverse after 1 second + if (arg == TICKS_PER_SECOND) ramp_direction = 1; + pseudo_rand_seed += arg; return MISCHIEF_MANAGED; } @@ -1134,6 +1152,7 @@ inline void bike_flasher_iter() { #ifdef USE_CANDLE_MODE uint8_t candle_mode_state(Event event, uint16_t arg) { + static int8_t ramp_direction = 1; #define MAX_CANDLE_LEVEL (RAMP_LENGTH-CANDLE_AMPLITUDE-15) static uint8_t candle_wave1 = 0; static uint8_t candle_wave2 = 0; @@ -1153,6 +1172,7 @@ uint8_t candle_mode_state(Event event, uint16_t arg) { if (event == EV_enter_state) { candle_mode_timer = 0; // in case any time was left over from earlier + ramp_direction = 1; return MISCHIEF_MANAGED; } // 2 clicks: cancel timer @@ -1164,12 +1184,25 @@ uint8_t candle_mode_state(Event event, uint16_t arg) { } // hold: change brightness (brighter) else if (event == EV_click1_hold) { - if (candle_mode_brightness < MAX_CANDLE_LEVEL) - candle_mode_brightness ++; + // ramp away from extremes + if (! arg) { + if (candle_mode_brightness >= MAX_CANDLE_LEVEL) { ramp_direction = -1; } + else if (candle_mode_brightness <= 1) { ramp_direction = 1; } + } + // change brightness, but not too far + candle_mode_brightness += ramp_direction; + if (candle_mode_brightness < 1) candle_mode_brightness = 1; + else if (candle_mode_brightness > MAX_CANDLE_LEVEL) candle_mode_brightness = MAX_CANDLE_LEVEL; + return MISCHIEF_MANAGED; + } + // reverse ramp direction on hold release + else if (event == EV_click1_hold_release) { + ramp_direction = -ramp_direction; return MISCHIEF_MANAGED; } // click, hold: change brightness (dimmer) else if (event == EV_click2_hold) { + ramp_direction = 1; if (candle_mode_brightness > 1) candle_mode_brightness --; return MISCHIEF_MANAGED; @@ -1187,6 +1220,9 @@ uint8_t candle_mode_state(Event event, uint16_t arg) { } // clock tick: animate candle brightness else if (event == EV_tick) { + // un-reverse after 1 second + if (arg == TICKS_PER_SECOND) ramp_direction = 1; + // self-timer dims the light during the final minute uint8_t subtract = 0; if (candle_mode_timer == 1) { -- cgit v1.2.3 From 6d4d972ea3e543527d71766e4444fe7ce27b7158 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 22 May 2019 18:23:25 -0600 Subject: turned off hard turbo drop since it doesn't seem to be needed any more (but I haven't finished testing yet, so it's still possible it could be needed on D4) --- spaghetti-monster/anduril/cfg-emisar-d18.h | 2 +- spaghetti-monster/anduril/cfg-emisar-d4.h | 4 +--- spaghetti-monster/anduril/cfg-ff-rot66.h | 2 +- spaghetti-monster/anduril/cfg-fw3a.h | 4 ++-- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/spaghetti-monster/anduril/cfg-emisar-d18.h b/spaghetti-monster/anduril/cfg-emisar-d18.h index fcea43a..16fbacd 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d18.h +++ b/spaghetti-monster/anduril/cfg-emisar-d18.h @@ -43,4 +43,4 @@ // stop panicking at about ~40% power or ~5000 lm #define THERM_FASTER_LEVEL 125 // optional, makes initial turbo step-down faster so first peak isn't as hot -#define THERM_HARD_TURBO_DROP +//#define THERM_HARD_TURBO_DROP diff --git a/spaghetti-monster/anduril/cfg-emisar-d4.h b/spaghetti-monster/anduril/cfg-emisar-d4.h index 3ce0fd7..de8f796 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4.h @@ -13,9 +13,7 @@ // optional, makes initial turbo step-down faster so first peak isn't as hot // the D4 runs very very hot, so be extra careful -#ifdef THERM_HARD_TURBO_DROP -#undef THERM_HARD_TURBO_DROP -#endif +//#define THERM_HARD_TURBO_DROP // stop panicking at ~30% power or ~1200 lm #define THERM_FASTER_LEVEL 105 diff --git a/spaghetti-monster/anduril/cfg-ff-rot66.h b/spaghetti-monster/anduril/cfg-ff-rot66.h index 6073ce0..2a90343 100644 --- a/spaghetti-monster/anduril/cfg-ff-rot66.h +++ b/spaghetti-monster/anduril/cfg-ff-rot66.h @@ -39,7 +39,7 @@ #define THERM_FASTER_LEVEL 130 // throttle back faster when high // play it safe, don't try to regulate above the recommended safe level -#define THERM_HARD_TURBO_DROP +//#define THERM_HARD_TURBO_DROP // don't do this #undef BLINK_AT_RAMP_MIDDLE diff --git a/spaghetti-monster/anduril/cfg-fw3a.h b/spaghetti-monster/anduril/cfg-fw3a.h index dd77137..a28d12a 100644 --- a/spaghetti-monster/anduril/cfg-fw3a.h +++ b/spaghetti-monster/anduril/cfg-fw3a.h @@ -15,5 +15,5 @@ // stop panicking at about 3A or ~1100 lm, this light is a hotrod #define THERM_FASTER_LEVEL MAX_Nx7135 -// optional, makes initial turbo step-down faster so first peak isn't as hot -#define THERM_HARD_TURBO_DROP + +#define USE_TENCLICK_THERMAL_CONFIG -- cgit v1.2.3 From 16a51a45db7eda26403f88ddfc532f1cc4a98c87 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 22 May 2019 21:05:12 -0600 Subject: D4S actually steps down a bit too fast, so... minimize that --- spaghetti-monster/anduril/cfg-emisar-d4s.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetti-monster/anduril/cfg-emisar-d4s.h b/spaghetti-monster/anduril/cfg-emisar-d4s.h index e26634a..d19a514 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4s.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4s.h @@ -36,7 +36,7 @@ #undef MIN_THERM_STEPDOWN // this should be lower, because 3x7135 instead of 1x7135 #endif #define MIN_THERM_STEPDOWN 60 // lowest value it'll step down to -#define THERM_FASTER_LEVEL (RAMP_SIZE*9/10) // throttle back faster when high +#define THERM_FASTER_LEVEL (RAMP_SIZE-1) // don't throttle back faster when high // no need to be extra-careful on this light #ifdef THERM_HARD_TURBO_DROP -- cgit v1.2.3 From b46b04f11b26a1804926cea005369e4cc161d873 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 23 May 2019 15:48:09 -0600 Subject: merged recent anduril updates into fireflies-ui --- spaghetti-monster/fireflies-ui/fireflies-ui.c | 296 ++++++++++++++++++++------ 1 file changed, 225 insertions(+), 71 deletions(-) diff --git a/spaghetti-monster/fireflies-ui/fireflies-ui.c b/spaghetti-monster/fireflies-ui/fireflies-ui.c index 234ae92..2c3e60b 100644 --- a/spaghetti-monster/fireflies-ui/fireflies-ui.c +++ b/spaghetti-monster/fireflies-ui/fireflies-ui.c @@ -189,6 +189,9 @@ typedef enum { ramp_discrete_ceil_e, ramp_discrete_steps_e, #endif + #ifdef USE_TINT_RAMPING + tint_e, + #endif #ifdef USE_STROBE_STATE strobe_type_e, #endif @@ -226,6 +229,12 @@ typedef enum { #define USE_PSEUDO_RAND #endif +#if defined(USE_CANDLE_MODE) +#ifndef USE_TRIANGLE_WAVE +#define USE_TRIANGLE_WAVE +#endif +#endif + #include "spaghetti-monster.h" @@ -242,6 +251,10 @@ uint8_t steady_state(Event event, uint16_t arg); #ifdef USE_RAMP_CONFIG uint8_t ramp_config_state(Event event, uint16_t arg); #endif +#ifdef USE_TINT_RAMPING +// not actually a mode, more of a fallback under other modes +uint8_t tint_ramping_state(Event event, uint16_t arg); +#endif // party and tactical strobes #ifdef USE_STROBE_STATE uint8_t strobe_state(Event event, uint16_t arg); @@ -250,6 +263,7 @@ uint8_t strobe_state(Event event, uint16_t arg); uint8_t boring_strobe_state(Event event, uint16_t arg); volatile uint8_t boring_strobe_type = 0; void sos_blink(uint8_t num, uint8_t dah); +#define strobe_state boring_strobe_state // use the right strobes #define NUM_BORING_STROBES 2 #endif #ifdef USE_BATTCHECK @@ -271,10 +285,12 @@ uint8_t beacon_config_state(Event event, uint16_t arg); // soft lockout #define MOON_DURING_LOCKOUT_MODE // if enabled, 2nd lockout click goes to the other ramp's floor level -//#define LOCKOUT_MOON_FANCY +#define LOCKOUT_MOON_FANCY uint8_t lockout_state(Event event, uint16_t arg); // momentary / signalling mode uint8_t momentary_state(Event event, uint16_t arg); +uint8_t momentary_mode = 0; // 0 = ramping, 1 = strobe +uint8_t momentary_active = 0; // boolean, true if active *right now* #ifdef USE_MUGGLE_MODE // muggle mode, super-simple, hard to exit uint8_t muggle_state(Event event, uint16_t arg); @@ -287,6 +303,7 @@ uint8_t number_entry_state(Event event, uint16_t arg); volatile uint8_t number_entry_value; void blink_confirm(uint8_t num); +void blip(); #if defined(USE_INDICATOR_LED) && defined(TICK_DURING_STANDBY) void indicator_blink(uint8_t arg); #endif @@ -299,6 +316,9 @@ void save_config_wl(); #endif // default ramp options if not overridden earlier per-driver +#ifndef RAMP_STYLE +#define RAMP_STYLE 0 // smooth default +#endif #ifndef RAMP_SMOOTH_FLOOR #define RAMP_SMOOTH_FLOOR 1 #endif @@ -342,7 +362,7 @@ void save_config_wl(); #endif uint8_t memorized_level = DEFAULT_LEVEL; // smooth vs discrete ramping -volatile uint8_t ramp_style = 0; // 0 = smooth, 1 = discrete +volatile uint8_t ramp_style = RAMP_STYLE; // 0 = smooth, 1 = discrete volatile uint8_t ramp_smooth_floor = RAMP_SMOOTH_FLOOR; volatile uint8_t ramp_smooth_ceil = RAMP_SMOOTH_CEIL; volatile uint8_t ramp_discrete_floor = RAMP_DISCRETE_FLOOR; @@ -420,6 +440,9 @@ volatile uint8_t bike_flasher_brightness = MAX_1x7135; #ifdef USE_CANDLE_MODE uint8_t candle_mode_state(Event event, uint16_t arg); uint8_t triangle_wave(uint8_t phase); +#ifndef CANDLE_AMPLITUDE +#define CANDLE_AMPLITUDE 25 +#endif #endif #ifdef USE_BEACON_MODE @@ -468,10 +491,7 @@ uint8_t off_state(Event event, uint16_t arg) { #ifdef MOON_TIMING_HINT if (arg == 0) { // let the user know they can let go now to stay at moon - uint8_t temp = actual_level; - set_level(0); - delay_4ms(3); - set_level(temp); + blip(); } else #endif // don't start ramping immediately; @@ -600,6 +620,7 @@ uint8_t steady_state(Event event, uint16_t arg) { // turn LED on when we first enter the mode if ((event == EV_enter_state) || (event == EV_reenter_state)) { + momentary_mode = 0; // 0 = ramping, 1 = strobes // if we just got back from config mode, go back to memorized level if (event == EV_reenter_state) { arg = memorized_level; @@ -654,8 +675,7 @@ uint8_t steady_state(Event event, uint16_t arg) { #ifdef START_AT_MEMORIZED_LEVEL save_config_wl(); #endif - set_level(0); - delay_4ms(20/4); + blip(); set_level(memorized_level); return MISCHIEF_MANAGED; } @@ -706,8 +726,7 @@ uint8_t steady_state(Event event, uint16_t arg) { || (memorized_level == mode_min) #endif )) { - set_level(0); - delay_4ms(8/4); + blip(); } #endif #if defined(BLINK_AT_STEPS) @@ -721,8 +740,7 @@ uint8_t steady_state(Event event, uint16_t arg) { (memorized_level == nearest) ) { - set_level(0); - delay_4ms(8/4); + blip(); } #endif set_level(memorized_level); @@ -768,8 +786,7 @@ uint8_t steady_state(Event event, uint16_t arg) { || (memorized_level == mode_min) #endif )) { - set_level(0); - delay_4ms(8/4); + blip(); } #endif #if defined(BLINK_AT_STEPS) @@ -783,8 +800,7 @@ uint8_t steady_state(Event event, uint16_t arg) { (memorized_level == nearest) ) { - set_level(0); - delay_4ms(8/4); + blip(); } #endif set_level(memorized_level); @@ -855,10 +871,7 @@ uint8_t steady_state(Event event, uint16_t arg) { // overheating: drop by an amount proportional to how far we are above the ceiling else if (event == EV_temperature_high) { #if 0 - uint8_t foo = actual_level; - set_level(0); - delay_4ms(2); - set_level(foo); + blip(); #endif #ifdef THERM_HARD_TURBO_DROP if (actual_level > THERM_FASTER_LEVEL) { @@ -886,10 +899,7 @@ uint8_t steady_state(Event event, uint16_t arg) { // (proportional to how low we are) else if (event == EV_temperature_low) { #if 0 - uint8_t foo = actual_level; - set_level(0); - delay_4ms(2); - set_level(foo); + blip(); #endif if (actual_level < target_level) { //int16_t stepup = actual_level + (arg>>1); @@ -909,12 +919,79 @@ uint8_t steady_state(Event event, uint16_t arg) { } +#ifdef USE_TINT_RAMPING +uint8_t tint_ramping_state(Event event, uint16_t arg) { + static int8_t tint_ramp_direction = 1; + static uint8_t prev_tint = 0; + // don't activate auto-tint modes unless the user hits the edge + // and keeps pressing for a while + static uint8_t past_edge_counter = 0; + // bugfix: click-click-hold from off to strobes would invoke tint ramping + // 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; + + // click, click, hold: change the tint + if (event == EV_click3_hold) { + // reset at beginning of movement + if (! arg) { + active = 1; // first frame means this is for us + past_edge_counter = 0; // doesn't start until user hits the edge + } + // ignore event if we weren't the ones who handled the first frame + if (! active) return EVENT_HANDLED; + + // change normal tints + if ((tint_ramp_direction > 0) && (tint < 254)) { + tint += 1; + } + else if ((tint_ramp_direction < 0) && (tint > 1)) { + tint -= 1; + } + // if the user kept pressing long enough, go the final step + if (past_edge_counter == 64) { + past_edge_counter ++; + tint ^= 1; // 0 -> 1, 254 -> 255 + blip(); + } + // if tint change stalled, let user know we hit the edge + else if (prev_tint == tint) { + if (past_edge_counter == 0) blip(); + // count up but don't wrap back to zero + if (past_edge_counter < 255) past_edge_counter ++; + } + prev_tint = tint; + set_level(actual_level); + return EVENT_HANDLED; + } + + // click, click, hold, release: reverse direction for next ramp + else if (event == EV_click3_hold_release) { + active = 0; // ignore next hold if it wasn't meant for us + // reverse + tint_ramp_direction = -tint_ramp_direction; + if (tint == 0) tint_ramp_direction = 1; + else if (tint == 255) tint_ramp_direction = -1; + // remember tint after battery change + save_config(); + return EVENT_HANDLED; + } + + return EVENT_NOT_HANDLED; +} +#endif // ifdef USE_TINT_RAMPING + + #ifdef USE_STROBE_STATE uint8_t strobe_state(Event event, uint16_t arg) { + static int8_t ramp_direction = 1; + // 'st' reduces ROM size by avoiding access to a volatile var // (maybe I should just make it nonvolatile?) strobe_mode_te st = strobe_type; + momentary_mode = 1; // 0 = ramping, 1 = strobes + #ifdef USE_CANDLE_MODE // pass all events to candle mode, when it's active // (the code is in its own pseudo-state to keep things cleaner) @@ -924,11 +1001,11 @@ uint8_t strobe_state(Event event, uint16_t arg) { #endif if (0) {} // placeholder - /* not used any more + // init anything which needs to be initialized else if (event == EV_enter_state) { + ramp_direction = 1; return MISCHIEF_MANAGED; } - */ // 1 click: off else if (event == EV_1click) { set_state(off_state, 0); @@ -953,7 +1030,11 @@ uint8_t strobe_state(Event event, uint16_t arg) { else if (st == party_strobe_e) { #endif if ((arg & 1) == 0) { - if (strobe_delays[st] > 8) strobe_delays[st] --; + uint8_t d = strobe_delays[st]; + d -= ramp_direction; + if (d < 8) d = 8; + else if (d > 254) d = 254; + strobe_delays[st] = d; } } #endif @@ -964,17 +1045,27 @@ uint8_t strobe_state(Event event, uint16_t arg) { // biking mode brighter #ifdef USE_BIKE_FLASHER_MODE else if (st == bike_flasher_e) { - if (bike_flasher_brightness < MAX_BIKING_LEVEL) - bike_flasher_brightness ++; + 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); } #endif return MISCHIEF_MANAGED; } + // reverse ramp direction on hold release + // ... and save new strobe settings + else if (event == EV_click1_hold_release) { + ramp_direction = -ramp_direction; + save_config(); + return MISCHIEF_MANAGED; + } // click, hold: change speed (go slower) // or change brightness (dimmer) else if (event == EV_click2_hold) { + ramp_direction = 1; + if (0) {} // placeholder // party / tactical strobe slower @@ -1005,14 +1096,16 @@ uint8_t strobe_state(Event event, uint16_t arg) { return MISCHIEF_MANAGED; } // release hold: save new strobe settings - else if ((event == EV_click1_hold_release) - || (event == EV_click2_hold_release)) { + else if (event == EV_click2_hold_release) { save_config(); return MISCHIEF_MANAGED; } #if defined(USE_LIGHTNING_MODE) || defined(USE_CANDLE_MODE) // clock tick: bump the random seed else if (event == EV_tick) { + // un-reverse after 1 second + if (arg == TICKS_PER_SECOND) ramp_direction = 1; + pseudo_rand_seed += arg; return MISCHIEF_MANAGED; } @@ -1054,7 +1147,7 @@ inline void lightning_storm_iter() { //rand_time = 1 << (pseudo_rand() % 7); rand_time = pseudo_rand() & 63; brightness = 1 << (pseudo_rand() % 7); // 1, 2, 4, 8, 16, 32, 64 - brightness += 1 << (pseudo_rand() & 0x03); // 2 to 80 now + brightness += 1 << (pseudo_rand() % 5); // 2 to 80 now brightness += pseudo_rand() % brightness; // 2 to 159 now (w/ low bias) if (brightness > MAX_LEVEL) brightness = MAX_LEVEL; set_level(brightness); @@ -1109,17 +1202,19 @@ inline void bike_flasher_iter() { #ifdef USE_CANDLE_MODE uint8_t candle_mode_state(Event event, uint16_t arg) { - // FIXME: make candle variance magnitude a compile-time option, - // since 20 is sometimes too much or too little, - // depending on the driver type and ramp shape - //#define MAX_CANDLE_LEVEL (RAMP_SIZE-8-6-4) - #define MAX_CANDLE_LEVEL (RAMP_SIZE/2) + static int8_t ramp_direction = 1; + #define MAX_CANDLE_LEVEL (RAMP_LENGTH-CANDLE_AMPLITUDE-15) static uint8_t candle_wave1 = 0; static uint8_t candle_wave2 = 0; static uint8_t candle_wave3 = 0; static uint8_t candle_wave2_speed = 0; - static uint8_t candle_wave2_depth = 7; - static uint8_t candle_wave3_depth = 4; + // these should add up to 100 + #define CANDLE_WAVE1_MAXDEPTH 30 + #define CANDLE_WAVE2_MAXDEPTH 45 + #define CANDLE_WAVE3_MAXDEPTH 25 + static const uint8_t candle_wave1_depth = CANDLE_WAVE1_MAXDEPTH * CANDLE_AMPLITUDE / 100; + static uint8_t candle_wave2_depth = CANDLE_WAVE2_MAXDEPTH * CANDLE_AMPLITUDE / 100; + static uint8_t candle_wave3_depth = CANDLE_WAVE3_MAXDEPTH * CANDLE_AMPLITUDE / 100; static uint8_t candle_mode_brightness = 24; static uint8_t candle_mode_timer = 0; #define TICKS_PER_CANDLE_MINUTE 4096 // about 65 seconds @@ -1127,6 +1222,7 @@ uint8_t candle_mode_state(Event event, uint16_t arg) { if (event == EV_enter_state) { candle_mode_timer = 0; // in case any time was left over from earlier + ramp_direction = 1; return MISCHIEF_MANAGED; } // 2 clicks: cancel timer @@ -1138,12 +1234,25 @@ uint8_t candle_mode_state(Event event, uint16_t arg) { } // hold: change brightness (brighter) else if (event == EV_click1_hold) { - if (candle_mode_brightness < MAX_CANDLE_LEVEL) - candle_mode_brightness ++; + // ramp away from extremes + if (! arg) { + if (candle_mode_brightness >= MAX_CANDLE_LEVEL) { ramp_direction = -1; } + else if (candle_mode_brightness <= 1) { ramp_direction = 1; } + } + // change brightness, but not too far + candle_mode_brightness += ramp_direction; + if (candle_mode_brightness < 1) candle_mode_brightness = 1; + else if (candle_mode_brightness > MAX_CANDLE_LEVEL) candle_mode_brightness = MAX_CANDLE_LEVEL; + return MISCHIEF_MANAGED; + } + // reverse ramp direction on hold release + else if (event == EV_click1_hold_release) { + ramp_direction = -ramp_direction; return MISCHIEF_MANAGED; } // click, hold: change brightness (dimmer) else if (event == EV_click2_hold) { + ramp_direction = 1; if (candle_mode_brightness > 1) candle_mode_brightness --; return MISCHIEF_MANAGED; @@ -1161,10 +1270,13 @@ uint8_t candle_mode_state(Event event, uint16_t arg) { } // clock tick: animate candle brightness else if (event == EV_tick) { + // un-reverse after 1 second + if (arg == TICKS_PER_SECOND) ramp_direction = 1; + // self-timer dims the light during the final minute uint8_t subtract = 0; if (candle_mode_timer == 1) { - subtract = ((candle_mode_brightness+20) + subtract = ((candle_mode_brightness+CANDLE_AMPLITUDE) * ((arg & (TICKS_PER_CANDLE_MINUTE-1)) >> 4)) >> 8; } @@ -1181,7 +1293,7 @@ uint8_t candle_mode_state(Event event, uint16_t arg) { } // 3-oscillator synth for a relatively organic pattern uint8_t add; - add = ((triangle_wave(candle_wave1) * 8) >> 8) + add = ((triangle_wave(candle_wave1) * candle_wave1_depth) >> 8) + ((triangle_wave(candle_wave2) * candle_wave2_depth) >> 8) + ((triangle_wave(candle_wave3) * candle_wave3_depth) >> 8); int8_t brightness = candle_mode_brightness + add - subtract; @@ -1189,6 +1301,7 @@ uint8_t candle_mode_state(Event event, uint16_t arg) { set_level(brightness); // wave1: slow random LFO + // TODO: make wave slower and more erratic? if ((arg & 1) == 0) candle_wave1 += pseudo_rand() & 1; // wave2: medium-speed erratic LFO candle_wave2 += candle_wave2_speed; @@ -1201,8 +1314,10 @@ uint8_t candle_mode_state(Event event, uint16_t arg) { if ((candle_wave2_depth > 0) && ((pseudo_rand() & 0b00111111) == 0)) candle_wave2_depth --; // random sawtooth retrigger - if ((pseudo_rand()) == 0) { - candle_wave2_depth = 7; + if (pseudo_rand() == 0) { + // random amplitude + //candle_wave2_depth = 2 + (pseudo_rand() % ((CANDLE_WAVE2_MAXDEPTH * CANDLE_AMPLITUDE / 100) - 2)); + candle_wave2_depth = pseudo_rand() % (CANDLE_WAVE2_MAXDEPTH * CANDLE_AMPLITUDE / 100); //candle_wave3_depth = 5; candle_wave2 = 0; } @@ -1210,17 +1325,13 @@ uint8_t candle_mode_state(Event event, uint16_t arg) { if ((candle_wave3_depth > 2) && ((pseudo_rand() & 0b00011111) == 0)) candle_wave3_depth --; if ((pseudo_rand() & 0b01111111) == 0) - candle_wave3_depth = 5; + // random amplitude + //candle_wave3_depth = 2 + (pseudo_rand() % ((CANDLE_WAVE3_MAXDEPTH * CANDLE_AMPLITUDE / 100) - 2)); + candle_wave3_depth = pseudo_rand() % (CANDLE_WAVE3_MAXDEPTH * CANDLE_AMPLITUDE / 100); return MISCHIEF_MANAGED; } return EVENT_NOT_HANDLED; } - -uint8_t triangle_wave(uint8_t phase) { - uint8_t result = phase << 1; - if (phase > 127) result = 255 - result; - return result; -} #endif // #ifdef USE_CANDLE_MODE @@ -1231,6 +1342,8 @@ uint8_t boring_strobe_state(Event event, uint16_t arg) { // (maybe I should just make it nonvolatile?) uint8_t st = boring_strobe_type; + momentary_mode = 1; // 0 = ramping, 1 = strobes + if (event == EV_enter_state) { return MISCHIEF_MANAGED; } @@ -1534,14 +1647,24 @@ uint8_t lockout_state(Event event, uint16_t arg) { uint8_t momentary_state(Event event, uint16_t arg) { // TODO: momentary strobe here? (for light painting) + // init strobe mode, if relevant + if ((event == EV_enter_state) && (momentary_mode == 1)) { + strobe_state(event, arg); + } + // light up when the button is pressed; go dark otherwise // button is being held if ((event & (B_CLICK | B_PRESS)) == (B_CLICK | B_PRESS)) { - set_level(memorized_level); + momentary_active = 1; + // 0 = ramping, 1 = strobes + if (momentary_mode == 0) { + set_level(memorized_level); + } return MISCHIEF_MANAGED; } // button was released else if ((event & (B_CLICK | B_PRESS)) == (B_CLICK)) { + momentary_active = 0; set_level(0); //go_to_standby = 1; // sleep while light is off return MISCHIEF_MANAGED; @@ -1552,10 +1675,18 @@ uint8_t momentary_state(Event event, uint16_t arg) { // with exiting via tailcap loosen+tighten unless you leave power // disconnected for several seconds, so we want to be awake when that // happens to speed up the process) - else if ((event == EV_tick) && (actual_level == 0)) { - if (arg > TICKS_PER_SECOND*15) { // sleep after 15 seconds - go_to_standby = 1; // sleep while light is off - // TODO: lighted button should use lockout config? + else if (event == EV_tick) { + if (momentary_active) { + // 0 = ramping, 1 = strobes + if (momentary_mode == 1) { + return strobe_state(event, arg); + } + } + else { + if (arg > TICKS_PER_SECOND*15) { // sleep after 15 seconds + go_to_standby = 1; // sleep while light is off + // TODO: lighted button should use lockout config? + } } return MISCHIEF_MANAGED; } @@ -1689,12 +1820,13 @@ uint8_t muggle_state(Event event, uint16_t arg) { #ifdef USE_THERMAL_REGULATION // overheating is handled specially in muggle mode else if(event == EV_temperature_high) { - // don't even try... - // go immediately to the bottom, in case someone put the light on - // maximum while wrapped in dark-colored flammable insulation - // or something, because muggles are cool like that - // memorized_level = MUGGLE_FLOOR; // override memory? maybe not - set_level(MUGGLE_FLOOR); + #if 0 + blip(); + #endif + // step down proportional to the amount of overheating + uint8_t new = actual_level - arg; + if (new < MUGGLE_FLOOR) { new = MUGGLE_FLOOR; } + set_level(new); return MISCHIEF_MANAGED; } #endif @@ -1792,14 +1924,15 @@ void thermal_config_save() { // calibrate room temperature val = config_state_values[0]; if (val) { - int8_t rawtemp = (temperature >> 1) - therm_cal_offset; + int8_t rawtemp = temperature - therm_cal_offset; therm_cal_offset = val - rawtemp; + reset_thermal_history = 1; // invalidate all recent temperature data } val = config_state_values[1]; if (val) { // set maximum heat limit - therm_ceil = 30 + val; + therm_ceil = 30 + val - 1; } if (therm_ceil > MAX_THERM_CEIL) therm_ceil = MAX_THERM_CEIL; } @@ -1828,9 +1961,9 @@ uint8_t beacon_config_state(Event event, uint16_t arg) { inline void beacon_mode_iter() { // one iteration of main loop() set_level(memorized_level); - nice_delay_ms(500); + nice_delay_ms(100); set_level(0); - nice_delay_ms(((beacon_seconds) * 1000) - 500); + nice_delay_ms(((beacon_seconds) * 1000) - 100); } #endif // #ifdef USE_BEACON_MODE @@ -1962,6 +2095,14 @@ void blink_confirm(uint8_t num) { } } +// Just go dark for a moment to indicate to user that something happened +void blip() { + uint8_t temp = actual_level; + set_level(0); + delay_4ms(3); + set_level(temp); +} + #if defined(USE_INDICATOR_LED) && defined(TICK_DURING_STANDBY) // beacon-like mode for the indicator LED @@ -1997,6 +2138,9 @@ void load_config() { ramp_discrete_ceil = eeprom[ramp_discrete_ceil_e]; ramp_discrete_steps = eeprom[ramp_discrete_steps_e]; #endif + #ifdef USE_TINT_RAMPING + tint = eeprom[tint_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]; @@ -2035,6 +2179,9 @@ void save_config() { eeprom[ramp_discrete_ceil_e] = ramp_discrete_ceil; eeprom[ramp_discrete_steps_e] = ramp_discrete_steps; #endif + #ifdef USE_TINT_RAMPING + eeprom[tint_e] = tint; + #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]; @@ -2134,14 +2281,19 @@ void setup() { load_config(); + #ifdef USE_TINT_RAMPING + // add tint ramping underneath every other state + push_state(tint_ramping_state, 0); + #endif // ifdef USE_TINT_RAMPING + #ifdef USE_MUGGLE_MODE if (muggle_mode_active) push_state(muggle_state, (MUGGLE_FLOOR+MUGGLE_CEILING)/2); else #endif push_state(off_state, 0); - #endif + #endif // ifdef START_AT_MEMORIZED_LEVEL } @@ -2152,7 +2304,8 @@ void loop() { if (0) {} #ifdef USE_STROBE_STATE - else if (state == strobe_state) { + else if ((state == strobe_state) + || ((state == momentary_state) && (momentary_mode == 1) && (momentary_active)) ) { // also handle momentary strobes uint8_t st = strobe_type; switch(st) { @@ -2184,7 +2337,8 @@ void loop() { #endif // #ifdef USE_STROBE_STATE #ifdef USE_BORING_STROBE_STATE - else if (state == boring_strobe_state) { + else if ((state == boring_strobe_state) + || ((state == momentary_state) && (momentary_mode == 1) && (momentary_active)) ) { // also handle momentary strobes switch(boring_strobe_type) { #ifdef USE_POLICE_STROBE_MODE case 0: // police strobe @@ -2216,7 +2370,7 @@ void loop() { #ifdef USE_THERMAL_REGULATION // TODO: blink out therm_ceil during thermal_config_state? else if (state == tempcheck_state) { - blink_num(temperature>>1); + blink_num(temperature); nice_delay_ms(1000); } #endif -- cgit v1.2.3 From 8a10d804fe32e1215789dd3d55275979689fbee5 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 25 May 2019 16:02:00 -0600 Subject: Added a compile-time option for manual memory. (as opposed to the automatic memory it uses by default) 5 clicks while on: enable manual memory and save the current level 5 clicks and hold the last press: turn manual memory off, go back to automatic --- spaghetti-monster/anduril/anduril.c | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index f9509e7..8e801bc 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -77,6 +77,9 @@ // dual-switch support (second switch is a tail clicky) //#define START_AT_MEMORIZED_LEVEL +// add a "manual memory" function (as opposed to the default automatic memory) +//#define USE_MANUAL_MEMORY + /***** specific settings for known driver types *****/ #include "tk.h" #include incfile(CONFIGFILE) @@ -145,6 +148,9 @@ typedef enum { ramp_discrete_ceil_e, ramp_discrete_steps_e, #endif + #ifdef USE_MANUAL_MEMORY + manual_memory_e, + #endif #ifdef USE_TINT_RAMPING tint_e, #endif @@ -316,6 +322,9 @@ void save_config_wl(); #define DEFAULT_LEVEL MAX_1x7135 #endif uint8_t memorized_level = DEFAULT_LEVEL; +#ifdef USE_MANUAL_MEMORY +uint8_t manual_memory = 0; +#endif // smooth vs discrete ramping volatile uint8_t ramp_style = RAMP_STYLE; // 0 = smooth, 1 = discrete volatile uint8_t ramp_smooth_floor = RAMP_SMOOTH_FLOOR; @@ -464,11 +473,21 @@ uint8_t off_state(Event event, uint16_t arg) { } // 1 click (before timeout): go to memorized level, but allow abort for double click else if (event == EV_click1_release) { + #ifdef USE_MANUAL_MEMORY + if (manual_memory) + set_level(nearest_level(manual_memory)); + else + #endif set_level(nearest_level(memorized_level)); return MISCHIEF_MANAGED; } // 1 click: regular mode else if (event == EV_1click) { + #ifdef USE_MANUAL_MEMORY + if (manual_memory) + set_state(steady_state, manual_memory); + else + #endif set_state(steady_state, memorized_level); return MISCHIEF_MANAGED; } @@ -763,6 +782,20 @@ uint8_t steady_state(Event event, uint16_t arg) { return MISCHIEF_MANAGED; } #endif + #ifdef USE_MANUAL_MEMORY + else if (event == EV_5clicks) { + manual_memory = actual_level; + save_config(); + blip(); + } + else if (event == EV_click5_hold) { + if (0 == arg) { + manual_memory = 0; + save_config(); + blip(); + } + } + #endif #if defined(USE_SET_LEVEL_GRADUALLY) || defined(USE_REVERSING) else if (event == EV_tick) { #ifdef USE_REVERSING @@ -2074,6 +2107,9 @@ void load_config() { ramp_discrete_ceil = eeprom[ramp_discrete_ceil_e]; ramp_discrete_steps = eeprom[ramp_discrete_steps_e]; #endif + #ifdef USE_MANUAL_MEMORY + manual_memory = eeprom[manual_memory_e]; + #endif #ifdef USE_TINT_RAMPING tint = eeprom[tint_e]; #endif @@ -2115,6 +2151,9 @@ void save_config() { eeprom[ramp_discrete_ceil_e] = ramp_discrete_ceil; eeprom[ramp_discrete_steps_e] = ramp_discrete_steps; #endif + #ifdef USE_MANUAL_MEMORY + eeprom[manual_memory_e] = manual_memory; + #endif #ifdef USE_TINT_RAMPING eeprom[tint_e] = tint; #endif -- cgit v1.2.3 From 3131258326e509e0d3e6d32f647bc77454b4e4c5 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 2 Jun 2019 00:49:12 -0600 Subject: made button release timeout faster (384ms -> 288ms) to make light shut off sooner after 1 click --- spaghetti-monster/fsm-events.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetti-monster/fsm-events.h b/spaghetti-monster/fsm-events.h index 0ebcfd0..39ad3aa 100644 --- a/spaghetti-monster/fsm-events.h +++ b/spaghetti-monster/fsm-events.h @@ -43,7 +43,7 @@ static volatile uint16_t ticks_since_last_event = 0; #define HOLD_TIMEOUT 24 #endif #ifndef RELEASE_TIMEOUT -#define RELEASE_TIMEOUT 24 +#define RELEASE_TIMEOUT 18 #endif /* Event structure -- cgit v1.2.3 From 66fbafe914c88724f7f3edff8936928bd664f77d Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 2 Jun 2019 00:50:22 -0600 Subject: enabled manual memory option by default --- spaghetti-monster/anduril/anduril.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 8e801bc..0fa5340 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -42,6 +42,13 @@ // ("hold, release, hold" ramps down instead of up) #define USE_REVERSING +// add a runtime option to switch between automatic memory (default) +// and manual memory (only available if compiled in) +// (manual memory makes 1-click-from-off start at the same level each time) +// (the level can be set explicitly with 5 clicks from on, +// or the user can go back to automatic with click-click-click-click-hold) +#define USE_MANUAL_MEMORY + // battery readout style (pick one) #define BATTCHECK_VpT //#define BATTCHECK_8bars // FIXME: breaks build @@ -77,9 +84,6 @@ // dual-switch support (second switch is a tail clicky) //#define START_AT_MEMORIZED_LEVEL -// add a "manual memory" function (as opposed to the default automatic memory) -//#define USE_MANUAL_MEMORY - /***** specific settings for known driver types *****/ #include "tk.h" #include incfile(CONFIGFILE) -- cgit v1.2.3 From fd75cddc425f13a96071e723392b60d894100088 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 2 Jun 2019 00:51:53 -0600 Subject: added compile option to configure response timing on 1-click on/off (at press, at release, or at event timeout), changed default from press-on to release-on (but release-off is funky and annoying so it's still not default) --- spaghetti-monster/anduril/anduril.c | 89 +++++++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 18 deletions(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 0fa5340..dffa981 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -31,7 +31,7 @@ // short blip when crossing from "click" to "hold" from off // (helps the user hit moon mode exactly, instead of holding too long // or too short) -#define MOON_TIMING_HINT +#define MOON_TIMING_HINT // only applies if B_TIMING_ON == B_PRESS_T // short blips while ramping #define BLINK_AT_RAMP_MIDDLE //#define BLINK_AT_RAMP_FLOOR @@ -204,6 +204,24 @@ typedef enum { #include "spaghetti-monster.h" +// configure the timing of turning on/off in regular ramp mode +// press: react as soon as the button is pressed +#define B_PRESS_T 0 +// release: react as soon as the button is released +#define B_RELEASE_T 1 +// timeout: react as soon as we're sure the user isn't doing a double-click +#define B_TIMEOUT_T 2 +// defaults are release on, timeout off +#ifndef B_TIMING_ON +//#define B_TIMING_ON B_PRESS_T +#define B_TIMING_ON B_RELEASE_T +#endif +#ifndef B_TIMING_OFF +//#define B_TIMING_OFF B_RELEASE_T +#define B_TIMING_OFF B_TIMEOUT_T +#endif + + // FSM states uint8_t off_state(Event event, uint16_t arg); // simple numeric entry config menu @@ -449,19 +467,25 @@ uint8_t off_state(Event event, uint16_t arg) { return MISCHIEF_MANAGED; } #endif + #if (B_TIMING_ON == B_PRESS_T) // hold (initially): go to lowest level (floor), but allow abort for regular click else if (event == EV_click1_press) { set_level(nearest_level(1)); return MISCHIEF_MANAGED; } + #endif // B_TIMING_ON == B_PRESS_T // hold: go to lowest level else if (event == EV_click1_hold) { + #if (B_TIMING_ON == B_PRESS_T) #ifdef MOON_TIMING_HINT if (arg == 0) { // let the user know they can let go now to stay at moon blip(); } else #endif + #else // B_RELEASE_T or B_TIMEOUT_T + set_level(nearest_level(1)); + #endif // don't start ramping immediately; // give the user time to release at moon level //if (arg >= HOLD_TIMEOUT) { // smaller @@ -475,6 +499,7 @@ uint8_t off_state(Event event, uint16_t arg) { set_state(steady_state, 1); return MISCHIEF_MANAGED; } + #if (B_TIMING_ON != B_TIMEOUT_T) // 1 click (before timeout): go to memorized level, but allow abort for double click else if (event == EV_click1_release) { #ifdef USE_MANUAL_MEMORY @@ -485,6 +510,7 @@ uint8_t off_state(Event event, uint16_t arg) { set_level(nearest_level(memorized_level)); return MISCHIEF_MANAGED; } + #endif // if (B_TIMING_ON != B_TIMEOUT_T) // 1 click: regular mode else if (event == EV_1click) { #ifdef USE_MANUAL_MEMORY @@ -585,6 +611,11 @@ uint8_t steady_state(Event event, uint16_t arg) { #ifdef USE_REVERSING static int8_t ramp_direction = 1; #endif + #if (B_TIMING_OFF == B_RELEASE_T) + // if the user double clicks, we need to abort turning off, + // and this stores the level to return to + static uint8_t level_before_off = 0; + #endif if (ramp_style) { mode_min = ramp_discrete_floor; mode_max = ramp_discrete_ceil; @@ -612,6 +643,25 @@ uint8_t steady_state(Event event, uint16_t arg) { #endif return MISCHIEF_MANAGED; } + #if (B_TIMING_OFF == B_RELEASE_T) + // 1 click (early): off, if configured for early response + else if (event == EV_click1_release) { + level_before_off = actual_level; + #ifdef USE_THERMAL_REGULATION + target_level = 0; + #endif + set_level(0); + return MISCHIEF_MANAGED; + } + // 2 clicks (early): abort turning off, if configured for early response + else if (event == EV_click2_press) { + #ifdef USE_THERMAL_REGULATION + target_level = level_before_off; + #endif + set_level(level_before_off); + return MISCHIEF_MANAGED; + } + #endif // if (B_TIMING_OFF == B_RELEASE_T) // 1 click: off else if (event == EV_1click) { set_state(off_state, 0); @@ -831,26 +881,29 @@ uint8_t steady_state(Event event, uint16_t arg) { else { diff = actual_level - gradual_target; } - uint8_t magnitude = 0; - #ifndef THERM_HARD_TURBO_DROP - // if we're on a really high mode, drop faster - if (actual_level >= THERM_FASTER_LEVEL) { magnitude ++; } - #endif - while (diff) { - magnitude ++; - diff >>= 1; - } - uint8_t ticks_per_adjust = intervals[magnitude]; - if (ticks_since_adjust > ticks_per_adjust) - { - gradual_tick(); - ticks_since_adjust = 0; + // if there's any adjustment to be made, make it + if (diff) { + uint8_t magnitude = 0; + #ifndef THERM_HARD_TURBO_DROP + // if we're on a really high mode, drop faster + if (actual_level >= THERM_FASTER_LEVEL) { magnitude ++; } + #endif + while (diff) { + magnitude ++; + diff >>= 1; + } + uint8_t ticks_per_adjust = intervals[magnitude]; + if (ticks_since_adjust > ticks_per_adjust) + { + gradual_tick(); + ticks_since_adjust = 0; + } + //if (!(arg % ticks_per_adjust)) gradual_tick(); } - //if (!(arg % ticks_per_adjust)) gradual_tick(); #ifdef THERM_HARD_TURBO_DROP } #endif - #endif + #endif // ifdef USE_SET_LEVEL_GRADUALLY return MISCHIEF_MANAGED; } #endif @@ -901,7 +954,7 @@ uint8_t steady_state(Event event, uint16_t arg) { } return MISCHIEF_MANAGED; } - #endif + #endif // ifdef USE_THERMAL_REGULATION return EVENT_NOT_HANDLED; } -- cgit v1.2.3 From 2cbd4b971ec838523faa966335e222a5f484400a Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 4 Jun 2019 18:55:42 -0600 Subject: reduced size by 28 bytes and made code slightly cleaner by moving a common 2-line pattern into its own function (instead of "target_level = x; set_level(x);", it does "set_level_and_therm_target(x);") --- spaghetti-monster/anduril/anduril.c | 67 ++++++++++++------------------------- 1 file changed, 21 insertions(+), 46 deletions(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index dffa981..913a857 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -380,6 +380,9 @@ uint8_t nearest_level(int16_t target); #ifdef USE_THERMAL_REGULATION // brightness before thermal step-down uint8_t target_level = 0; +void set_level_and_therm_target(uint8_t level); +#else +#define set_level_and_therm_target(level) set_level(level) #endif // internal numbering for strobe modes @@ -634,10 +637,7 @@ uint8_t steady_state(Event event, uint16_t arg) { memorized_level = arg; // use the requested level even if not memorized arg = nearest_level(arg); - #ifdef USE_THERMAL_REGULATION - target_level = arg; - #endif - set_level(arg); + set_level_and_therm_target(arg); #ifdef USE_REVERSING ramp_direction = 1; #endif @@ -647,18 +647,12 @@ uint8_t steady_state(Event event, uint16_t arg) { // 1 click (early): off, if configured for early response else if (event == EV_click1_release) { level_before_off = actual_level; - #ifdef USE_THERMAL_REGULATION - target_level = 0; - #endif - set_level(0); + set_level_and_therm_target(0); return MISCHIEF_MANAGED; } // 2 clicks (early): abort turning off, if configured for early response else if (event == EV_click2_press) { - #ifdef USE_THERMAL_REGULATION - target_level = level_before_off; - #endif - set_level(level_before_off); + set_level_and_therm_target(level_before_off); return MISCHIEF_MANAGED; } #endif // if (B_TIMING_OFF == B_RELEASE_T) @@ -670,36 +664,24 @@ uint8_t steady_state(Event event, uint16_t arg) { // 2 clicks: go to/from highest level else if (event == EV_2clicks) { if (actual_level < MAX_LEVEL) { - #ifdef USE_THERMAL_REGULATION - target_level = MAX_LEVEL; - #endif // true turbo, not the mode-specific ceiling - set_level(MAX_LEVEL); + set_level_and_therm_target(MAX_LEVEL); } else { - #ifdef USE_THERMAL_REGULATION - target_level = memorized_level; - #endif - set_level(memorized_level); + set_level_and_therm_target(memorized_level); } return MISCHIEF_MANAGED; } // 3 clicks: toggle smooth vs discrete ramping else if (event == EV_3clicks) { ramp_style = !ramp_style; - memorized_level = nearest_level(actual_level); - #ifdef USE_THERMAL_REGULATION - target_level = memorized_level; - #ifdef USE_SET_LEVEL_GRADUALLY - //set_level_gradually(lvl); - #endif - #endif save_config(); #ifdef START_AT_MEMORIZED_LEVEL save_config_wl(); #endif blip(); - set_level(memorized_level); + memorized_level = nearest_level(actual_level); + set_level_and_therm_target(memorized_level); return MISCHIEF_MANAGED; } #ifdef USE_RAMP_CONFIG @@ -729,9 +711,6 @@ uint8_t steady_state(Event event, uint16_t arg) { #else memorized_level = nearest_level((int16_t)actual_level + ramp_step_size); #endif - #ifdef USE_THERMAL_REGULATION - target_level = memorized_level; - #endif #if defined(BLINK_AT_RAMP_CEILING) || defined(BLINK_AT_RAMP_MIDDLE) // only blink once for each threshold if ((memorized_level != actual_level) && ( @@ -766,7 +745,7 @@ uint8_t steady_state(Event event, uint16_t arg) { blip(); } #endif - set_level(memorized_level); + set_level_and_therm_target(memorized_level); return MISCHIEF_MANAGED; } #if defined(USE_REVERSING) || defined(START_AT_MEMORIZED_LEVEL) @@ -792,9 +771,6 @@ uint8_t steady_state(Event event, uint16_t arg) { } // TODO? make it ramp up instead, if already at min? memorized_level = nearest_level((int16_t)actual_level - ramp_step_size); - #ifdef USE_THERMAL_REGULATION - target_level = memorized_level; - #endif #if defined(BLINK_AT_RAMP_FLOOR) || defined(BLINK_AT_RAMP_MIDDLE) // only blink once for each threshold if ((memorized_level != actual_level) && ( @@ -826,7 +802,7 @@ uint8_t steady_state(Event event, uint16_t arg) { blip(); } #endif - set_level(memorized_level); + set_level_and_therm_target(memorized_level); return MISCHIEF_MANAGED; } #ifdef START_AT_MEMORIZED_LEVEL @@ -917,10 +893,10 @@ uint8_t steady_state(Event event, uint16_t arg) { if (actual_level > THERM_FASTER_LEVEL) { #ifdef USE_SET_LEVEL_GRADUALLY set_level_gradually(THERM_FASTER_LEVEL); + target_level = THERM_FASTER_LEVEL; #else - set_level(THERM_FASTER_LEVEL); + set_level_and_therm_target(THERM_FASTER_LEVEL); #endif - target_level = THERM_FASTER_LEVEL; } else #endif if (actual_level > MIN_THERM_STEPDOWN) { @@ -2111,6 +2087,12 @@ uint8_t nearest_level(int16_t target) { return this_level; } +#ifdef USE_THERMAL_REGULATION +void set_level_and_therm_target(uint8_t level) { + target_level = level; + set_level(level); +} +#endif void blink_confirm(uint8_t num) { for (; num>0; num--) { @@ -2266,14 +2248,7 @@ void low_voltage() { else if (state == steady_state) { if (actual_level > 1) { uint8_t lvl = (actual_level >> 1) + (actual_level >> 2); - set_level(lvl); - #ifdef USE_THERMAL_REGULATION - target_level = lvl; - #ifdef USE_SET_LEVEL_GRADUALLY - // not needed? - //set_level_gradually(lvl); - #endif - #endif + set_level_and_therm_target(lvl); } else { set_state(off_state, 0); -- cgit v1.2.3 From cf98788bafdbc6f7fdd246b4085248eeefb7c915 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 21 Jun 2019 05:19:55 -0600 Subject: anduril manual: added info about manual memory, 2-level lockout, and aux LED colors --- spaghetti-monster/anduril/anduril-manual.txt | 19 ++++++++++++++++++- spaghetti-monster/anduril/anduril.txt | 18 +++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/spaghetti-monster/anduril/anduril-manual.txt b/spaghetti-monster/anduril/anduril-manual.txt index 3684b50..3f17f41 100644 --- a/spaghetti-monster/anduril/anduril-manual.txt +++ b/spaghetti-monster/anduril/anduril-manual.txt @@ -56,6 +56,13 @@ While the light is on, a few basic actions are available: - Click, hold: Change brightness (down). - 3 clicks: Switch to the other ramp. - 4 clicks: Go to ramp config mode. + - 5 clicks: Activate manual memory and save the current brightness. + - 5 clicks, but hold the last click: Go back to automatic memory. + +The "automatic" vs "manual" memory modes change the level the light goes +to with 1 click from off. In automatic mode, it uses the last +brightness the user ramped to. In manual mode, it uses the brightness +the user explicitly saved with 5 clicks. Other Modes @@ -215,7 +222,10 @@ then return to the regular "off" mode. Lockout mode also doubles as a momentary moon mode, so the user can do quick tasks without having to unlock the light. The brightness in -lockout mode is determined by the floor setting of the current ramp. +lockout mode has two levels: + + - Hold: light up at the floor level of the current ramp. + - Click, Hold: light up at the floor level of the other ramp. Momentary Mode @@ -364,6 +374,13 @@ click the button a few times: This should change the aux LEDs to the next mode supported on this light. +If the aux LEDs can change color, there are additional actions to change +the color. It is the same as above, but hold the button on the last +click and then let go when the desired color is reached. + + - Off mode: 7 clicks, but hold the last click. + - Lockout mode: 3 clicks, but hold the last click. + For lights with a button LED, the button LED typically stays on while the main emitters are on. Its brightness level is set in a way which mirrors the main LED -- off, low, or high. diff --git a/spaghetti-monster/anduril/anduril.txt b/spaghetti-monster/anduril/anduril.txt index 3e0328c..db73cdb 100644 --- a/spaghetti-monster/anduril/anduril.txt +++ b/spaghetti-monster/anduril/anduril.txt @@ -20,6 +20,8 @@ From off: * On hardware with an indicator LED... * 7 clicks: Change aux LED mode used in "off" mode. (the modes are usually off/low/high/blinking) + * 7 clicks (but hold the last click): + Change aux LED color used in "off" mode. In steady / ramping mode: * 1 click: off @@ -28,6 +30,8 @@ In steady / ramping mode: * 2 clicks: to/from turbo (actual turbo, not just highest ramp level) * 3 clicks: toggle smooth vs discrete ramping * 4 clicks: configure current ramp + * 5 clicks: activate manual memory and save current brightness + * 5 clicks (but hold the last click): go back to automatic memory Smooth ramp config mode: * Setting 1: low end @@ -104,14 +108,18 @@ Discrete ramp config mode: At buzz, click N times to set thermal limit to roughly 30 C + N. Lockout mode: - * Hold: momentary moon + * Hold: momentary moon (current ramp floor) + * Click, Hold: momentary moon (other ramp floor) * 4 clicks: exit lockout (return to regular "off" mode) * On hardware with an indicator LED... * 3 clicks: Change aux LED brightness used in lockout mode. (the modes are usually off/low/high/blinking) + * 3 clicks (but hold the last click): + Change aux LED color used in lockout mode. Momentary mode: - * Press button: Light on (at memorized level). + * Press button: Light on (at memorized mode/level). + (uses either a steady mode or a strobe-group mode) * Release button: Light off. * To exit, disconnect power. (loosen/tighten the tailcap) @@ -148,6 +156,10 @@ Indicator LED / aux LED support: - High - Blinking + If the aux LEDs can change color, the user can configure the color + using exactly the same method... except hold the last click until the + desired color is reached. + TODO: * save settings in eeprom @@ -167,7 +179,7 @@ TODO: * move all config menus to four clicks * candle mode timer, with three clicks to add 30 minutes * diagram updates for 3-click special actions + * add a toggle for memory (manual vs automatic memory) - candle mode: smoother adjustments? - make sunset mode timer and brightness configurable? - make beacon mode actually sleep between pulses - - add a toggle for memory? -- cgit v1.2.3 From 41fef25bf05bb8fa377c9bcbbc7c0b5858cd20a1 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 27 Jun 2019 02:40:38 -0600 Subject: added factory reset function to Anduril, and reboot function for FSM --- spaghetti-monster/anduril/anduril.c | 80 ++++++++++++++++++++++++++++++++++-- spaghetti-monster/anduril/cfg-fw3a.h | 3 ++ spaghetti-monster/fsm-main.c | 5 +++ spaghetti-monster/fsm-misc.c | 17 ++++++++ spaghetti-monster/fsm-misc.h | 4 ++ 5 files changed, 106 insertions(+), 3 deletions(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 913a857..c2a4b77 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -28,6 +28,14 @@ #define USE_THERMAL_REGULATION #define DEFAULT_THERM_CEIL 45 // try not to get hotter than this +#define USE_FACTORY_RESET +//#define USE_SOFT_FACTORY_RESET // only needed on models which can't use hold-button-at-boot + +// dual-switch support (second switch is a tail clicky) +// (currently incompatible with factory reset) +//#define START_AT_MEMORIZED_LEVEL + + // short blip when crossing from "click" to "hold" from off // (helps the user hit moon mode exactly, instead of holding too long // or too short) @@ -81,9 +89,6 @@ //#define USE_POLICE_STROBE_MODE //#define USE_SOS_MODE -// dual-switch support (second switch is a tail clicky) -//#define START_AT_MEMORIZED_LEVEL - /***** specific settings for known driver types *****/ #include "tk.h" #include incfile(CONFIGFILE) @@ -201,6 +206,10 @@ typedef enum { #endif #endif +#ifdef USE_SOFT_FACTORY_RESET +#define USE_REBOOT +#endif + #include "spaghetti-monster.h" @@ -291,6 +300,10 @@ void blip(); void indicator_blink(uint8_t arg); #endif +#ifdef USE_FACTORY_RESET +void factory_reset(); +#endif + // remember stuff even after battery was changed void load_config(); void save_config(); @@ -603,6 +616,13 @@ uint8_t off_state(Event event, uint16_t arg) { return MISCHIEF_MANAGED; } #endif + #if defined(USE_FACTORY_RESET) && defined(USE_SOFT_FACTORY_RESET) + // 13 clicks and hold the last click: invoke factory reset (reboot) + else if (event == EV_click13_hold) { + reboot(); + return MISCHIEF_MANAGED; + } + #endif return EVENT_NOT_HANDLED; } @@ -2136,6 +2156,55 @@ void indicator_blink(uint8_t arg) { #endif +#ifdef USE_FACTORY_RESET +void factory_reset() { + // display a warning for a few seconds before doing the actual reset, + // so the user has time to abort if they want + #define SPLODEY_TIME 3000 + #define SPLODEY_STEPS 64 + #define SPLODEY_TIME_PER_STEP (SPLODEY_TIME/SPLODEY_STEPS) + uint8_t bright; + uint8_t reset = 1; + // wind up to an explosion + for (bright=0; bright>1); + delay_4ms(SPLODEY_TIME_PER_STEP/2/4); + if (! button_is_pressed()) { + reset = 0; + break; + } + } + // explode, if button pressed long enough + if (reset) { + #ifdef USE_THERMAL_REGULATION + // auto-calibrate temperature... assume current temperature is 21 C + config_state_values[0] = 21; + config_state_values[1] = 0; + thermal_config_save(); + #endif + // save all settings to eeprom + // (assuming they're all at default because we haven't loaded them yet) + save_config(); + + bright = MAX_LEVEL; + for (; bright > 0; bright--) { + set_level(bright); + delay_4ms(SPLODEY_TIME_PER_STEP/6/4); + } + } + // explosion cancelled, fade away + else { + for (; bright > 0; bright--) { + set_level(bright); + delay_4ms(SPLODEY_TIME_PER_STEP/3/4); + } + } +} +#endif + + void load_config() { if (load_eeprom()) { ramp_style = eeprom[ramp_style_e]; @@ -2286,6 +2355,11 @@ void setup() { delay_4ms(3); set_level(0); + #ifdef USE_FACTORY_RESET + if (button_is_pressed()) + factory_reset(); + #endif + load_config(); #ifdef USE_TINT_RAMPING diff --git a/spaghetti-monster/anduril/cfg-fw3a.h b/spaghetti-monster/anduril/cfg-fw3a.h index a28d12a..489766c 100644 --- a/spaghetti-monster/anduril/cfg-fw3a.h +++ b/spaghetti-monster/anduril/cfg-fw3a.h @@ -17,3 +17,6 @@ #define THERM_FASTER_LEVEL MAX_Nx7135 #define USE_TENCLICK_THERMAL_CONFIG + +// can't reset the normal way because power is connected before the button +#define USE_SOFT_FACTORY_RESET diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index 6f74e9b..1c28f5f 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -40,6 +40,11 @@ int main() { // Don't allow interrupts while booting cli(); + #ifdef USE_REBOOT // prevent reboot loops + MCUSR &= ~(1< 286759 bytes spaghetti-monster/anduril/anduril.svg | 982 ++++++++++++++++++++++--------- 2 files changed, 688 insertions(+), 294 deletions(-) diff --git a/spaghetti-monster/anduril/anduril-ui.png b/spaghetti-monster/anduril/anduril-ui.png index b778a30..3c032bc 100644 Binary files a/spaghetti-monster/anduril/anduril-ui.png and b/spaghetti-monster/anduril/anduril-ui.png differ diff --git a/spaghetti-monster/anduril/anduril.svg b/spaghetti-monster/anduril/anduril.svg index ab2926d..36840a4 100644 --- a/spaghetti-monster/anduril/anduril.svg +++ b/spaghetti-monster/anduril/anduril.svg @@ -12,14 +12,14 @@ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="18.056446cm" - height="26.675991cm" + height="30.084438cm" id="svg2" version="1.1" - inkscape:version="0.92.1 r15371" + inkscape:version="0.92.4 (5da689c313, 2019-01-14)" sodipodi:docname="anduril.svg" inkscape:export-filename="/tmp/anduril-ui.png" - inkscape:export-xdpi="342.78015" - inkscape:export-ydpi="342.78015"> + inkscape:export-xdpi="109.75774" + inkscape:export-ydpi="109.75774"> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + originy="95.554798" /> @@ -2747,6 +2869,12 @@ x="-885.51392" y="1093.7063" style="font-size:29.33333397px;line-height:1.25;stroke-width:1.06666672">Strobes + - + + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> BeaconCfg @@ -2981,113 +3108,11 @@ style="fill:none;stroke:#000000;stroke-width:2.39758635;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> - - - Faster - - Slower - - Faster - - Slower - - Brighter - - Dimmer - @@ -3237,8 +3256,8 @@ inkscape:connector-curvature="0" sodipodi:nodetypes="csc" /> @@ -3347,7 +3366,7 @@ sodipodi:role="line" x="1444.4535" y="854.61517" - id="tspan58146"> (click N times for 1+Turbo-N) (click N times for Nth highest) (click N times for 30 C + N) + id="tspan39625"> (click N times for N + 30 C) for N seconds per flash) + transform="translate(-742.72705,222.13423)"> Actions 1 Fast Click + style="font-size:17.06666756px;line-height:1.25;stroke-width:1.06666672">1 Click Hold 3 Fast Clicks + style="font-size:17.06666756px;line-height:1.25;stroke-width:1.06666672">3 Clicks Other Action @@ -3546,24 +3565,24 @@ 2 Fast Clicks + style="font-size:17.06666756px;line-height:1.25;fill:#009d00;fill-opacity:1;stroke-width:1.06666672">2 Clicks Click, Hold @@ -3579,7 +3598,7 @@ sodipodi:role="line" id="tspan6532-6">Andúril‎ UI Beacon Cfg - - - Lockout - - - - - Momentary - - Signalling - / Faster - @@ -3846,15 +3791,6 @@ x="1172.5502" y="720.89923" style="font-size:25.60000038px;line-height:1.25;stroke-width:1.06666672">Muggle - Momentary - - OFF + style="fill:none;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow1Mend-31-1-0-9-9-9)" /> + + + + + OFF + + While On: + 1C + 1H + 3C + 2C + 2H + Brightness: Off, Low, High, Blinking + + 3C. Smooth /4C. Ramp Cfg5C. Manual Memory5H. Automatic Memory + Stepped ramp + + + + + + + + + + Color: R, Y, G, C, B, V, W, Rainbow, Volts + + + + + Lockout + + 7C + 7H + + Aux /ButtonLEDs + 3C + 3H + 3C + 3 Clicks + 3C + + + + + Lockout + + Momentary Moon / Low + + + + On / Strobes + + Factory Reset: Loosen tailcap, Hold button, Tighten tailcap, Hold 3s (or 13H from Off) -- cgit v1.2.3 From ba961635820f16e4726bf19bfb012aa7d7876c47 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 30 Jul 2019 14:39:55 -0600 Subject: ensure muggle thermal step-down can't overflow or wrap around --- spaghetti-monster/anduril/anduril.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index c2a4b77..24211d7 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -1846,7 +1846,7 @@ uint8_t muggle_state(Event event, uint16_t arg) { blip(); #endif // step down proportional to the amount of overheating - uint8_t new = actual_level - arg; + int16_t new = actual_level - arg; if (new < MUGGLE_FLOOR) { new = MUGGLE_FLOOR; } set_level(new); return MISCHIEF_MANAGED; -- cgit v1.2.3 From 25f430e0b0b25d57cccc53debe4f8ee48b5f634e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 5 Aug 2019 01:40:20 -0600 Subject: merged a sanitized copy of the Emisar D4v2 branch; history summarized below: ------------------------------------------------------------ revno: 457 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Thu 2019-07-18 22:42:50 -0600 message: make sure no thermal events are handled while off (even though it shouldn't be possible, since it only happens after 15 minutes, and the light is only awake in muggle-off mode for 1 second) modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ------------------------------------------------------------ revno: 456 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Thu 2019-07-18 20:09:58 -0600 message: don't measure temperature while asleep (fixes bug on D4 V2, where it would start flashing after 15 minutes turned off in muggle mode) (also should speed up response to battery voltage changes while asleep) modified: ToyKeeper/spaghetti-monster/fsm-adc.c ------------------------------------------------------------ revno: 455 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Thu 2019-07-18 20:05:56 -0600 message: made strobe brightness configurable per build target modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ------------------------------------------------------------ revno: 454 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Wed 2019-07-10 10:22:44 -0600 message: made the "therm faster" code only affect ramping down, and fixed a couple minor logic issues in the thermal regulation code modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ToyKeeper/spaghetti-monster/fsm-adc.c ------------------------------------------------------------ revno: 452 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Sat 2019-07-06 08:18:25 -0600 message: fixed spelling error in D4 / D4V2 files modified: ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4.h ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4v2.h ------------------------------------------------------------ revno: 451 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Sat 2019-07-06 08:16:57 -0600 message: fixed placement of #ifdefs on reboot loop prevention modified: ToyKeeper/spaghetti-monster/fsm-main.c ------------------------------------------------------------ revno: 450 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Sat 2019-07-06 08:15:59 -0600 message: made level_calc.py also find and show the channel transition points, so I won't have to do this manually all the time modified: bin/level_calc.py ------------------------------------------------------------ revno: 449 [merge] committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Sat 2019-07-06 05:31:37 -0600 message: merged from fsm branch to get factory reset function modified: ToyKeeper/spaghetti-monster/anduril/anduril-manual.txt ToyKeeper/spaghetti-monster/anduril/anduril.c ToyKeeper/spaghetti-monster/anduril/anduril.txt ToyKeeper/spaghetti-monster/anduril/cfg-fw3a.h ToyKeeper/spaghetti-monster/fsm-main.c ToyKeeper/spaghetti-monster/fsm-misc.c ToyKeeper/spaghetti-monster/fsm-misc.h ------------------------------------------------------------ revno: 448 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Sat 2019-07-06 05:13:40 -0600 message: started adding some ideas for later (maybe), but not currently used... ... may remove again later modified: ToyKeeper/spaghetti-monster/fsm-adc.c ------------------------------------------------------------ revno: 447 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Sat 2019-07-06 05:13:11 -0600 message: adjusted D4 / D4v2 thermal response again; it really doesn't want to behave modified: ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4.h ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4v2.h ------------------------------------------------------------ revno: 446 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Mon 2019-06-17 03:18:06 -0600 message: made d4 ramp slightly smoother at clock speed change modified: ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4.h ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4v2.h ------------------------------------------------------------ revno: 445 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Mon 2019-06-17 03:17:40 -0600 message: improved D4S thermal response; less prone to overshooting and oscillation modified: ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4s.h ------------------------------------------------------------ revno: 444 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Thu 2019-06-06 23:12:26 -0600 message: adjusted Emisar D4 thermal response values... (this light really doesn't want to behave thermally, so the values here don't quite get an ideal response, but they're a lot better than they were) modified: ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4.h ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4v2.h ------------------------------------------------------------ revno: 443 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Thu 2019-06-06 23:11:08 -0600 message: made anduril raise brightness slower when doing thermal regulation, made hard turbo drop only activate when it's actually at turbo modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ------------------------------------------------------------ revno: 442 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Thu 2019-06-06 23:09:54 -0600 message: made more thermal parameters configurable... - the speed of thermal history rotation (every 1s, 2s, or 4s) - prediction strength also made minimum time between temperature warnings factor in the lowpass, so the default is 5s again instead of 7s modified: ToyKeeper/spaghetti-monster/fsm-adc.c ------------------------------------------------------------ revno: 441 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Wed 2019-06-05 03:39:34 -0600 message: adjusted d4v2 ramp to hit 1x7135 exactly at level 4/7, turned off hard turbo drop because it doesn't seem to be needed any more modified: ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4v2.h ------------------------------------------------------------ revno: 440 [merge] committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Wed 2019-06-05 03:33:21 -0600 message: merged updates from fsm branch added: ToyKeeper/spaghetti-monster/anduril/cfg-ff-e01.h ToyKeeper/spaghetti-monster/fireflies-ui/cfg-ff-e07-2.h renamed: ToyKeeper/spaghetti-monster/fireflies-ui/cfg-ff-edc-thrower.h => ToyKeeper/spaghetti-monster/fireflies-ui/cfg-ff-e01.h modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ToyKeeper/spaghetti-monster/fireflies-ui/Makefile ToyKeeper/spaghetti-monster/fireflies-ui/build-all.sh ToyKeeper/spaghetti-monster/fireflies-ui/fireflies-ui.c ToyKeeper/spaghetti-monster/fireflies-ui/meta ToyKeeper/spaghetti-monster/fsm-events.h ToyKeeper/spaghetti-monster/fireflies-ui/cfg-ff-e01.h ------------------------------------------------------------ revno: 439 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-31 02:10:02 -0600 message: added D4v2-219 build for reduced power (only 75% FET) added: ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4v2-219.h ------------------------------------------------------------ revno: 438 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-31 01:57:14 -0600 message: made MCU stay awake at boot long enough to get accurate voltage reading, sped up return-to-sleep delays, made RGB "voltage" preview mode last twice as long modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ------------------------------------------------------------ revno: 437 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-31 01:56:18 -0600 message: sped up button release timeout slightly to reduce lag when turning off light modified: ToyKeeper/spaghetti-monster/fsm-events.h ------------------------------------------------------------ revno: 436 [merge] committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Thu 2019-05-23 00:43:14 -0600 message: merged from fsm branch to get a bunch of recent updates modified: ... a lot of files ------------------------------------------------------------ revno: 435 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Tue 2019-05-21 14:25:28 -0600 message: no muggle mode on D4v2, by request modified: ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4v2.h ------------------------------------------------------------ revno: 434 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Mon 2019-05-20 00:16:26 -0600 message: improved RGB aux LED previews for voltage mode and blinking mode modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ------------------------------------------------------------ revno: 433 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-10 23:53:47 -0600 message: fixed D4v2 ramp shape and thermal limit modified: ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4v2.h ------------------------------------------------------------ revno: 432 [merge] committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-10 23:39:48 -0600 message: merged from lantern branch, to get newer candle mode added: ToyKeeper/spaghetti-monster/anduril/cfg-blf-lantern.h modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ToyKeeper/spaghetti-monster/fsm-ramping.c ToyKeeper/spaghetti-monster/fsm-ramping.h ------------------------------------------------------------ revno: 431 [merge] committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-10 23:29:28 -0600 message: merged from upstream fsm branch added: ToyKeeper/spaghetti-monster/anduril/cfg-fw3a-219.h modified: ToyKeeper/spaghetti-monster/anduril/anduril-manual.txt ------------------------------------------------------------ revno: 430 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-10 23:27:55 -0600 message: use only red, green, and blue for voltage display... don't do color mixes modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ------------------------------------------------------------ revno: 429 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-10 23:27:30 -0600 message: flash-tiny1634-fuses had a typo modified: bin/flash-tiny1634-fuses.sh ------------------------------------------------------------ revno: 428 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Sat 2019-05-04 18:03:28 -0600 message: fixed builds without sleep ticks enabled modified: ToyKeeper/spaghetti-monster/fsm-wdt.c ------------------------------------------------------------ revno: 427 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Sat 2019-05-04 18:01:17 -0600 message: made aux LEDs turn on at boot time, instead of waiting until sleep LVP measures the battery modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ------------------------------------------------------------ revno: 426 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Sat 2019-05-04 18:00:34 -0600 message: implemented LVP in standby mode (which allows LVP to turn off high-drain aux LEDs while asleep, and allows RGB readout to change with battery charge) modified: ToyKeeper/spaghetti-monster/fsm-adc.c ToyKeeper/spaghetti-monster/fsm-adc.h ToyKeeper/spaghetti-monster/fsm-wdt.c ------------------------------------------------------------ revno: 425 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Sat 2019-05-04 03:14:33 -0600 message: enable tenclick thermal config in D4v2 target modified: ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4v2.h ------------------------------------------------------------ revno: 424 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Sat 2019-05-04 03:14:16 -0600 message: added RGB support to lockout mode, improved RGB behavior, set defaults to low because the high mode is way too bright modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ------------------------------------------------------------ revno: 423 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Sat 2019-05-04 02:36:55 -0600 message: got RGB aux LED modes working -- (off, low, high, blinking) and (7 colors + rainbow + voltage) (off mode only, for now, no lockout) modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ------------------------------------------------------------ revno: 422 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-03 18:25:23 -0600 message: Turn off aux LEDs when voltage is low. They use too much power on high mode. modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ------------------------------------------------------------ revno: 421 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-03 18:24:15 -0600 message: Calibrated D4v2 voltage. modified: ToyKeeper/hwdef-Emisar_D4v2.h ------------------------------------------------------------ revno: 420 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-03 17:48:51 -0600 message: fixed RGB aux LED low mode modified: ToyKeeper/hwdef-Emisar_D4v2.h ToyKeeper/spaghetti-monster/fsm-misc.c ------------------------------------------------------------ revno: 419 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-03 17:35:47 -0600 message: started on RGB aux LED support in Anduril, but it's just an early test right now modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4v2.h ------------------------------------------------------------ revno: 418 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-03 17:35:05 -0600 message: adjust ramping auto-aux-LED code to include RGB version (shut off when main LEDs are on) modified: ToyKeeper/spaghetti-monster/fsm-ramping.c ------------------------------------------------------------ revno: 417 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-03 17:33:08 -0600 message: started on tiny1634 RGB aux LED support (seems to work except for the "low" output mode) modified: ToyKeeper/hwdef-Emisar_D4v2.h ToyKeeper/spaghetti-monster/fsm-misc.c ToyKeeper/spaghetti-monster/fsm-misc.h ------------------------------------------------------------ revno: 416 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-03 16:22:15 -0600 message: fixed D4v2 PWM speed and delay speed, fixed hardware setup reference comments modified: ToyKeeper/hwdef-Emisar_D4v2.h ------------------------------------------------------------ revno: 415 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-03 16:20:50 -0600 message: fixed attiny1634 clock speed adjustments modified: ToyKeeper/tk-attiny.h ------------------------------------------------------------ revno: 414 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-03 15:38:52 -0600 message: renamed SWITCH_PIN_D (pin data) to SWITCH_PORT, to match AVR manual terminology (even though the value should be PINA or PINB or PINC) modified: ToyKeeper/hwdef-Emisar_D4v2.h ToyKeeper/spaghetti-monster/fsm-pcint.c ToyKeeper/tk-attiny.h ------------------------------------------------------------ revno: 413 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-03 01:48:10 -0600 message: added tiny1634 flashing scripts added: bin/flash-tiny1634-fuses.sh bin/flash-tiny1634.sh ------------------------------------------------------------ revno: 411 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-03 01:42:35 -0600 message: started adding tiny1634 support to FSM ... so much kludge, such need clean modified: ToyKeeper/spaghetti-monster/fsm-adc.c ToyKeeper/spaghetti-monster/fsm-main.c ToyKeeper/spaghetti-monster/fsm-pcint.c ToyKeeper/spaghetti-monster/fsm-wdt.c ToyKeeper/tk-attiny.h ------------------------------------------------------------ revno: 410 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-03 01:40:15 -0600 message: added D4v2-1634 config and hwdef files modified: ToyKeeper/hwdef-Emisar_D4v2.h ToyKeeper/spaghetti-monster/anduril/cfg-emisar-d4v2.h ------------------------------------------------------------ revno: 409 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Fri 2019-05-03 01:39:24 -0600 message: made build-all.sh detect attiny type from cfg file, and use it modified: ToyKeeper/spaghetti-monster/anduril/build-all.sh ------------------------------------------------------------ revno: 403 [merge] committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Sun 2019-04-14 18:14:51 -0600 message: merged updates from upstream added/modified: ... lots of files ------------------------------------------------------------ revno: 402 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Sun 2019-04-14 18:08:08 -0600 message: merged in some aux LED code updates from anduril modified: ToyKeeper/spaghetti-monster/rampingios/rampingiosv3.c ------------------------------------------------------------ revno: 401 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Thu 2018-12-27 16:23:09 -0700 message: tk-attiny.h: started adding other MCU support also removed redundant eeprom size hints modified: ToyKeeper/tk-attiny.h ------------------------------------------------------------ revno: 400 committer: Selene ToyKeeper branch nick: emisar-d4v2 timestamp: Thu 2018-12-27 16:21:59 -0700 message: made dynamic clocking safer and more portable (uses library function instead of direct register access) (lib disables interrupts properly, which I wasn't doing) modified: ToyKeeper/spaghetti-monster/anduril/anduril.c ToyKeeper/spaghetti-monster/fsm-events.c ToyKeeper/spaghetti-monster/fsm-misc.c ToyKeeper/spaghetti-monster/spaghetti-monster.h --- hwdef-Emisar_D4v2.h | 100 +++++++++ spaghetti-monster/anduril/anduril.c | 282 +++++++++++++++++++----- spaghetti-monster/anduril/build-all.sh | 6 +- spaghetti-monster/anduril/cfg-emisar-d4.h | 14 +- spaghetti-monster/anduril/cfg-emisar-d4s.h | 6 +- spaghetti-monster/anduril/cfg-emisar-d4v2-219.h | 8 + spaghetti-monster/anduril/cfg-emisar-d4v2.h | 51 +++++ spaghetti-monster/fsm-adc.c | 137 +++++++++--- spaghetti-monster/fsm-adc.h | 3 +- spaghetti-monster/fsm-events.c | 24 +- spaghetti-monster/fsm-main.c | 56 +++-- spaghetti-monster/fsm-misc.c | 35 ++- spaghetti-monster/fsm-misc.h | 7 + spaghetti-monster/fsm-pcint.c | 42 +++- spaghetti-monster/fsm-ramping.c | 26 ++- spaghetti-monster/fsm-standby.c | 2 + spaghetti-monster/fsm-wdt.c | 82 +++++-- spaghetti-monster/fsm-wdt.h | 5 + spaghetti-monster/rampingios/rampingiosv3.c | 43 +--- spaghetti-monster/spaghetti-monster.h | 1 + tk-attiny.h | 55 ++++- 21 files changed, 797 insertions(+), 188 deletions(-) create mode 100644 hwdef-Emisar_D4v2.h create mode 100644 spaghetti-monster/anduril/cfg-emisar-d4v2-219.h create mode 100644 spaghetti-monster/anduril/cfg-emisar-d4v2.h diff --git a/hwdef-Emisar_D4v2.h b/hwdef-Emisar_D4v2.h new file mode 100644 index 0000000..0460fad --- /dev/null +++ b/hwdef-Emisar_D4v2.h @@ -0,0 +1,100 @@ +#ifndef HWDEF_EMISAR_D4V2_H +#define HWDEF_EMISAR_D4V2_H + +/* Emisar D4v2 driver layout (attiny1634) + * + * Pin / Name / Function + * 1 PA6 FET PWM (PWM1B) + * 2 PA5 red aux LED (PWM0B) + * 3 PA4 green aux LED + * 4 PA3 blue aux LED + * 5 PA2 e-switch + * 6 PA1 (none) + * 7 PA0 (none) + * 8 GND GND + * 9 VCC VCC + * 10 PC5 (none) + * 11 PC4 (none) + * 12 PC3 RESET + * 13 PC2 (none) + * 14 PC1 SCK + * 15 PC0 (none) PWM0A + * 16 PB3 7135 PWM (PWM1A) + * 17 PB2 MISO + * 18 PB1 MOSI + * 19 PB0 (none) + * 20 PA7 (none) + * ADC12 thermal sensor + */ + +#ifdef ATTINY +#undef ATTINY +#endif +#define ATTINY 1634 +#include + +#define PWM_CHANNELS 2 + +#define SWITCH_PIN PA2 // pin 5 +#define SWITCH_PCINT PCINT2 // pin 5 pin change interrupt +#define SWITCH_PCIE PCIE0 // PCIE0 is for PCINT[7:0] +#define SWITCH_PCMSK PCMSK0 // PCMSK0 is for PCINT[7:0] +#define SWITCH_PORT PINA // PINA or PINB or PINC + +#define PWM1_PIN PB3 // pin 16, 1x7135 PWM +#define PWM1_LVL OCR1A // OCR1A is the output compare register for PB3 + +#define PWM2_PIN PA6 // pin 1, FET PWM +#define PWM2_LVL OCR1B // OCR1B is the output compare register for PB1 + + +#define ADC_PRSCL 0x06 // clk/64 + +// average drop across diode on this hardware +#ifndef VOLTAGE_FUDGE_FACTOR +#define VOLTAGE_FUDGE_FACTOR 4 // add 0.20V (measured 0.22V) +#endif + +#define TEMP_CHANNEL 0b00001111 + +// this light has aux LEDs under the optic +#define AUXLED_R_PIN PA5 // pin 2 +#define AUXLED_G_PIN PA4 // pin 3 +#define AUXLED_B_PIN PA3 // pin 4 +#define AUXLED_RGB_PORT PORTA // PORTA or PORTB or PORTC +#define AUXLED_RGB_DDR DDRA // DDRA or DDRB or DDRC +#define AUXLED_RGB_PUE PUEA // PUEA or PUEB or PUEC + +// with so many pins, doing this all with #ifdefs gets awkward... +// ... so just hardcode it in each hwdef file instead +inline void hwdef_setup() { + // enable output ports + // 7135 + DDRB = (1 << PWM1_PIN); + // FET, aux R/G/B + DDRA = (1 << PWM2_PIN) + | (1 << AUXLED_R_PIN) + | (1 << AUXLED_G_PIN) + | (1 << AUXLED_B_PIN) + ; + + // configure PWM + // Setup PWM. F_pwm = F_clkio / 2 / N / TOP, where N = prescale factor, TOP = top of counter + // pre-scale for timer: N = 1 + TCCR1A = (0< TICKS_PER_SECOND*2) { + if (arg > HOLD_TIMEOUT) { go_to_standby = 1; #ifdef USE_INDICATOR_LED indicator_led(indicator_led_mode & 0x03); + #elif defined(USE_AUX_RGB_LEDS) + rgb_led_update(rgb_led_off_mode, arg); #endif } return MISCHIEF_MANAGED; } - #if defined(TICK_DURING_STANDBY) && defined(USE_INDICATOR_LED) + #if defined(TICK_DURING_STANDBY) && (defined(USE_INDICATOR_LED) || defined(USE_AUX_RGB_LEDS)) // blink the indicator LED, maybe else if (event == EV_sleep_tick) { + #ifdef USE_INDICATOR_LED if ((indicator_led_mode & 0b00000011) == 0b00000011) { indicator_blink(arg); } + #elif defined(USE_AUX_RGB_LEDS) + rgb_led_update(rgb_led_off_mode, arg); + #endif return MISCHIEF_MANAGED; } #endif @@ -608,7 +648,33 @@ uint8_t off_state(Event event, uint16_t arg) { save_config(); return MISCHIEF_MANAGED; } - #endif + #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; + 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); + save_config(); + blink_confirm(1); + return MISCHIEF_MANAGED; + } + // 7 clicks (hold last): change RGB aux LED color + else if (event == EV_click7_hold) { + if (0 == (arg & 0x3f)) { + uint8_t mode = (rgb_led_off_mode & 0x0f) + 1; + mode = mode % RGB_LED_NUM_COLORS; + rgb_led_off_mode = mode | (rgb_led_off_mode & 0xf0); + //save_config(); + } + rgb_led_update(rgb_led_off_mode, arg); + return MISCHIEF_MANAGED; + } + else if (event == EV_click7_hold_release) { + save_config(); + return MISCHIEF_MANAGED; + } + #endif // end 7 clicks #ifdef USE_TENCLICK_THERMAL_CONFIG // 10 clicks: thermal config mode else if (event == EV_10clicks) { @@ -854,7 +920,10 @@ uint8_t steady_state(Event event, uint16_t arg) { #endif #ifdef USE_SET_LEVEL_GRADUALLY // make thermal adjustment speed scale with magnitude - if ((arg & 1) && (actual_level < THERM_FASTER_LEVEL)) { + // also, adjust slower when going up + if ((arg & 1) && + ((actual_level < THERM_FASTER_LEVEL) || + (actual_level < gradual_target))) { return MISCHIEF_MANAGED; // adjust slower when not a high mode } #ifdef THERM_HARD_TURBO_DROP @@ -872,17 +941,21 @@ uint8_t steady_state(Event event, uint16_t arg) { uint8_t intervals[] = {248, 128, 66, 34, 17, 9, 4, 2}; uint8_t diff; static uint8_t ticks_since_adjust = 0; - ticks_since_adjust ++; - if (gradual_target > actual_level) diff = gradual_target - actual_level; - else { + if (gradual_target > actual_level) { + // rise at half speed (skip half the frames) + if (arg & 2) return MISCHIEF_MANAGED; + diff = gradual_target - actual_level; + } else { diff = actual_level - gradual_target; } + ticks_since_adjust ++; // if there's any adjustment to be made, make it if (diff) { uint8_t magnitude = 0; #ifndef THERM_HARD_TURBO_DROP // if we're on a really high mode, drop faster - if (actual_level >= THERM_FASTER_LEVEL) { magnitude ++; } + if ((actual_level >= THERM_FASTER_LEVEL) + && (actual_level > gradual_target)) { magnitude ++; } #endif while (diff) { magnitude ++; @@ -910,7 +983,8 @@ uint8_t steady_state(Event event, uint16_t arg) { blip(); #endif #ifdef THERM_HARD_TURBO_DROP - if (actual_level > THERM_FASTER_LEVEL) { + //if (actual_level > THERM_FASTER_LEVEL) { + if (actual_level == MAX_LEVEL) { #ifdef USE_SET_LEVEL_GRADUALLY set_level_gradually(THERM_FASTER_LEVEL); target_level = THERM_FASTER_LEVEL; @@ -1553,6 +1627,10 @@ uint8_t lockout_state(Event event, uint16_t arg) { #ifdef MOON_DURING_LOCKOUT_MODE // momentary(ish) moon mode during lockout // button is being held + #ifdef USE_AUX_RGB_LEDS + // don't turn on during RGB aux LED configuration + if (event == EV_click3_hold) { set_level(0); } else + #endif if ((event & (B_CLICK | B_PRESS)) == (B_CLICK | B_PRESS)) { #ifdef LOCKOUT_MOON_LOWEST // Use lowest moon configured @@ -1586,75 +1664,82 @@ uint8_t lockout_state(Event event, uint16_t arg) { if (event == EV_enter_state) { indicator_led(indicator_led_mode >> 2); } else + #elif defined(USE_AUX_RGB_LEDS) + if (event == EV_enter_state) { + rgb_led_update(rgb_led_lockout_mode, 0); + } else #endif if (event == EV_tick) { - if (arg > TICKS_PER_SECOND*2) { + if (arg > HOLD_TIMEOUT) { go_to_standby = 1; #ifdef USE_INDICATOR_LED indicator_led(indicator_led_mode >> 2); + #elif defined(USE_AUX_RGB_LEDS) + rgb_led_update(rgb_led_lockout_mode, arg); #endif } return MISCHIEF_MANAGED; } - #if defined(TICK_DURING_STANDBY) && defined(USE_INDICATOR_LED) + #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) if ((indicator_led_mode & 0b00001100) == 0b00001100) { indicator_blink(arg); } + #elif defined(USE_AUX_RGB_LEDS) + rgb_led_update(rgb_led_lockout_mode, arg); + #endif return MISCHIEF_MANAGED; } #endif - #ifdef USE_INDICATOR_LED + #if defined(USE_INDICATOR_LED) // 3 clicks: rotate through indicator LED modes (lockout mode) else if (event == EV_3clicks) { - uint8_t mode = indicator_led_mode >> 2; - #ifdef TICK_DURING_STANDBY - mode = (mode + 1) & 3; - #else - mode = (mode + 1) % 3; - #endif - #ifdef INDICATOR_LED_SKIP_LOW - if (mode == 1) { mode ++; } + #if defined(USE_INDICATOR_LED) + uint8_t mode = indicator_led_mode >> 2; + #ifdef TICK_DURING_STANDBY + mode = (mode + 1) & 3; + #else + mode = (mode + 1) % 3; + #endif + #ifdef INDICATOR_LED_SKIP_LOW + if (mode == 1) { mode ++; } + #endif + indicator_led_mode = (mode << 2) + (indicator_led_mode & 0x03); + indicator_led(mode); + #elif defined(USE_AUX_RGB_LEDS) #endif - indicator_led_mode = (mode << 2) + (indicator_led_mode & 0x03); - indicator_led(mode); save_config(); return MISCHIEF_MANAGED; } - #if 0 // old method, deprecated in favor of "7 clicks from off" - // click, click, hold: rotate through indicator LED modes (off mode) + #elif defined(USE_AUX_RGB_LEDS) + // 3 clicks: change RGB aux LED pattern + else if (event == EV_3clicks) { + uint8_t mode = (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); + save_config(); + blink_confirm(1); + return MISCHIEF_MANAGED; + } + // click, click, hold: change RGB aux LED color else if (event == EV_click3_hold) { - #ifndef USE_INDICATOR_LED_WHILE_RAMPING - // if main LED obscures aux LEDs, turn it off - set_level(0); - #endif - #ifdef TICK_DURING_STANDBY - uint8_t mode = (arg >> 5) & 3; - #else - uint8_t mode = (arg >> 5) % 3; - #endif - #ifdef INDICATOR_LED_SKIP_LOW - if (mode == 1) { mode ++; } - #endif - indicator_led_mode = (indicator_led_mode & 0b11111100) | mode; - #ifdef TICK_DURING_STANDBY - if (mode == 3) - indicator_led(mode & (arg&3)); - else - indicator_led(mode); - #else - indicator_led(mode); - #endif - //save_config(); + if (0 == (arg & 0x3f)) { + uint8_t mode = (rgb_led_lockout_mode & 0x0f) + 1; + mode = mode % RGB_LED_NUM_COLORS; + rgb_led_lockout_mode = mode | (rgb_led_lockout_mode & 0xf0); + //save_config(); + } + rgb_led_update(rgb_led_lockout_mode, arg); return MISCHIEF_MANAGED; } - // click, click, hold, release: save indicator LED mode (off mode) + // click, click, hold, release: save new color else if (event == EV_click3_hold_release) { save_config(); return MISCHIEF_MANAGED; } #endif - #endif // 4 clicks: exit else if (event == EV_4clicks) { blink_confirm(1); @@ -1845,10 +1930,13 @@ uint8_t muggle_state(Event event, uint16_t arg) { #if 0 blip(); #endif - // step down proportional to the amount of overheating - int16_t new = actual_level - arg; - if (new < MUGGLE_FLOOR) { new = MUGGLE_FLOOR; } - set_level(new); + // ignore warnings while off + if (! muggle_off_mode) { + // step down proportional to the amount of overheating + int16_t new = actual_level - arg; + if (new < MUGGLE_FLOOR) { new = MUGGLE_FLOOR; } + set_level(new); + } return MISCHIEF_MANAGED; } #endif @@ -2135,6 +2223,9 @@ void blip() { #if defined(USE_INDICATOR_LED) && defined(TICK_DURING_STANDBY) // beacon-like mode for the indicator LED void indicator_blink(uint8_t arg) { + // turn off aux LEDs when battery is empty + if (voltage < VOLTAGE_LOW) { indicator_led(0); return; } + #ifdef USE_FANCIER_BLINKING_INDICATOR // fancy blink, set off/low/high levels here: @@ -2155,6 +2246,81 @@ void indicator_blink(uint8_t arg) { } #endif +#if defined(USE_AUX_RGB_LEDS) && defined(TICK_DURING_STANDBY) +// do fancy stuff with the RGB aux LEDs +// mode: 0bPPPPCCCC where PPPP is the pattern and CCCC is the color +// arg: time slice number +void rgb_led_update(uint8_t mode, uint8_t arg) { + static uint8_t rainbow = 0; // track state of rainbow mode + static uint8_t frame = 0; // track state of animation mode + + // turn off aux LEDs when battery is empty + // (but if voltage==0, that means we just booted and don't know yet) + uint8_t volts = voltage; // save a few bytes by caching volatile value + if ((volts) && (volts < VOLTAGE_LOW)) { rgb_led_set(0); return; } + + uint8_t pattern = (mode>>4); // off, low, high, blinking, ... more? + uint8_t color = mode & 0x0f; + + // preview in blinking mode is awkward... use high instead + if ((! go_to_standby) && (pattern > 2)) { pattern = 2; } + + + uint8_t colors[] = { + 0b00000001, // 0: red + 0b00000101, // 1: yellow + 0b00000100, // 2: green + 0b00010100, // 3: cyan + 0b00010000, // 4: blue + 0b00010001, // 5: purple + 0b00010101, // 6: white + }; + uint8_t actual_color = 0; + if (color < 7) { // normal color + actual_color = colors[color]; + } + else if (color == 7) { // rainbow + if (0 == (arg & 0x03)) { + rainbow = (rainbow + 1) % 6; + } + actual_color = colors[rainbow]; + } + else { // voltage + // show actual voltage while asleep... + if (go_to_standby) { + // choose a color based on battery voltage + if (volts >= 38) actual_color = colors[4]; + else if (volts >= 33) actual_color = colors[2]; + else actual_color = colors[0]; + } + // ... but during preview, cycle colors quickly + else { + actual_color = colors[((arg>>1) % 3) << 1]; + } + } + + // pick a brightness from the animation sequence + if (pattern == 3) { + // uses an odd length to avoid lining up with rainbow loop + uint8_t animation[] = {2, 1, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + frame = (frame + 1) % sizeof(animation); + pattern = animation[frame]; + } + switch (pattern) { + case 0: // off + rgb_led_set(0); + break; + case 1: // low + rgb_led_set(actual_color); + break; + case 2: // high + rgb_led_set(actual_color << 1); + break; + } +} +#endif + #ifdef USE_FACTORY_RESET void factory_reset() { @@ -2242,6 +2408,10 @@ void load_config() { #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 START_AT_MEMORIZED_LEVEL if (load_eeprom_wl()) { @@ -2286,6 +2456,10 @@ void save_config() { #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 save_eeprom(); } @@ -2372,7 +2546,7 @@ void setup() { push_state(muggle_state, (MUGGLE_FLOOR+MUGGLE_CEILING)/2); else #endif - push_state(off_state, 0); + push_state(off_state, 1); #endif // ifdef START_AT_MEMORIZED_LEVEL } diff --git a/spaghetti-monster/anduril/build-all.sh b/spaghetti-monster/anduril/build-all.sh index c355f1e..56a88bf 100755 --- a/spaghetti-monster/anduril/build-all.sh +++ b/spaghetti-monster/anduril/build-all.sh @@ -5,7 +5,9 @@ UI=anduril for TARGET in cfg-*.h ; do NAME=$(echo "$TARGET" | perl -ne '/cfg-(.*).h/ && print "$1\n";') echo "===== $NAME =====" - echo ../../../bin/build.sh 85 "$UI" "-DCONFIGFILE=${TARGET}" - ../../../bin/build.sh 85 "$UI" "-DCONFIGFILE=${TARGET}" + ATTINY=$(grep 'ATTINY:' $TARGET | awk '{ print $3 }') + if [ -z "$ATTINY" ]; then ATTINY=85 ; fi + echo ../../../bin/build.sh $ATTINY "$UI" "-DCONFIGFILE=${TARGET}" + ../../../bin/build.sh $ATTINY "$UI" "-DCONFIGFILE=${TARGET}" mv -f "$UI".hex "$UI".$NAME.hex done diff --git a/spaghetti-monster/anduril/cfg-emisar-d4.h b/spaghetti-monster/anduril/cfg-emisar-d4.h index de8f796..c86a534 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4.h @@ -9,7 +9,14 @@ #define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,4,5,7,8,9,11,12,14,15,17,19,20,22,24,25,27,29,31,33,35,37,39,41,43,45,48,50,52,55,57,59,62,64,67,70,72,75,78,81,84,87,90,93,96,99,102,105,109,112,115,119,122,126,129,133,137,141,144,148,152,156,160,165,169,173,177,182,186,191,195,200,205,209,214,219,224,229,234,239,244,250,255 #define MAX_1x7135 65 #define HALFSPEED_LEVEL 14 -#define QUARTERSPEED_LEVEL 5 +#define QUARTERSPEED_LEVEL 6 + +#define RAMP_SMOOTH_FLOOR 1 +#define RAMP_SMOOTH_CEIL 120 +// 10, 28, 46, [65], 83, 101, 120 +#define RAMP_DISCRETE_FLOOR 10 +#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL +#define RAMP_DISCRETE_STEPS 7 // optional, makes initial turbo step-down faster so first peak isn't as hot // the D4 runs very very hot, so be extra careful @@ -17,3 +24,8 @@ // stop panicking at ~30% power or ~1200 lm #define THERM_FASTER_LEVEL 105 +// respond to thermal changes faster +#define THERMAL_WARNING_SECONDS 3 +#define THERMAL_UPDATE_SPEED 1 +#define THERM_PREDICTION_STRENGTH 4 + diff --git a/spaghetti-monster/anduril/cfg-emisar-d4s.h b/spaghetti-monster/anduril/cfg-emisar-d4s.h index d19a514..230ac7c 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4s.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4s.h @@ -36,9 +36,13 @@ #undef MIN_THERM_STEPDOWN // this should be lower, because 3x7135 instead of 1x7135 #endif #define MIN_THERM_STEPDOWN 60 // lowest value it'll step down to -#define THERM_FASTER_LEVEL (RAMP_SIZE-1) // don't throttle back faster when high +#define THERM_FASTER_LEVEL (RAMP_SIZE-20) // don't throttle back faster when high // no need to be extra-careful on this light #ifdef THERM_HARD_TURBO_DROP #undef THERM_HARD_TURBO_DROP #endif + +#define THERMAL_WARNING_SECONDS 3 +#define THERMAL_UPDATE_SPEED 2 +#define THERM_PREDICTION_STRENGTH 4 diff --git a/spaghetti-monster/anduril/cfg-emisar-d4v2-219.h b/spaghetti-monster/anduril/cfg-emisar-d4v2-219.h new file mode 100644 index 0000000..0770935 --- /dev/null +++ b/spaghetti-monster/anduril/cfg-emisar-d4v2-219.h @@ -0,0 +1,8 @@ +// Emisar D4v2-219 config options for Anduril +#include "cfg-emisar-d4v2.h" +// ATTINY: 1634 + +#undef PWM1_LEVELS +#undef PWM2_LEVELS +#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,7,8,9,10,12,13,14,15,17,19,20,22,24,26,29,31,34,36,39,42,45,48,51,55,59,62,66,70,75,79,84,89,93,99,104,110,115,121,127,134,140,147,154,161,168,176,184,192,200,209,217,226,236,245,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 +#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,3,5,6,6,8,9,10,11,12,14,15,16,18,18,20,21,23,24,26,27,29,30,32,33,36,37,39,41,43,44,46,48,50,52,54,56,58,61,63,65,67,70,72,74,77,79,82,84,86,89,92,95,97,100,103,106,108,111,114,117,120,124,127,130,133,137,140,144,147,151,154,157,161,165,169,172,176,180,184,188,192 diff --git a/spaghetti-monster/anduril/cfg-emisar-d4v2.h b/spaghetti-monster/anduril/cfg-emisar-d4v2.h new file mode 100644 index 0000000..b83c65c --- /dev/null +++ b/spaghetti-monster/anduril/cfg-emisar-d4v2.h @@ -0,0 +1,51 @@ +// Emisar D4 config options for Anduril +#include "hwdef-Emisar_D4v2.h" +// ATTINY: 1634 + +// this light has three aux LED channels: R, G, B +#define USE_AUX_RGB_LEDS +// the aux LEDs are front-facing, so turn them off while main LEDs are on +#ifdef USE_INDICATOR_LED_WHILE_RAMPING +#undef USE_INDICATOR_LED_WHILE_RAMPING +#endif +// enable blinking aux LEDs +#define TICK_DURING_STANDBY +#define STANDBY_TICK_SPEED 3 // every 0.128 s +//#define STANDBY_TICK_SPEED 4 // every 0.256 s +//#define STANDBY_TICK_SPEED 5 // every 0.512 s + + +// copied from original D4, since it's also a FET+1 and has the same host +// ../../bin/level_calc.py 1 65 7135 1 0.8 150 +// ... mixed with this: +// ../../bin/level_calc.py 2 150 7135 4 0.33 150 FET 1 10 1500 +#define RAMP_LENGTH 150 +#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,7,8,9,10,12,13,14,15,17,19,20,22,24,26,29,31,34,36,39,42,45,48,51,55,59,62,66,70,75,79,84,89,93,99,104,110,115,121,127,134,140,147,154,161,168,176,184,192,200,209,217,226,236,245,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0 +#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,4,5,7,8,9,11,12,14,15,17,19,20,22,24,25,27,29,31,33,35,37,39,41,43,45,48,50,52,55,57,59,62,64,67,70,72,75,78,81,84,87,90,93,96,99,102,105,109,112,115,119,122,126,129,133,137,141,144,148,152,156,160,165,169,173,177,182,186,191,195,200,205,209,214,219,224,229,234,239,244,250,255 +#define MAX_1x7135 65 +#define HALFSPEED_LEVEL 14 +#define QUARTERSPEED_LEVEL 6 + +#define RAMP_SMOOTH_FLOOR 1 +#define RAMP_SMOOTH_CEIL 120 +// 10, 28, 46, [65], 83, 101, 120 +#define RAMP_DISCRETE_FLOOR 10 +#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL +#define RAMP_DISCRETE_STEPS 7 + +// optional, makes initial turbo step-down faster so first peak isn't as hot +// the D4 runs very very hot, so be extra careful +//#define THERM_HARD_TURBO_DROP + +// stop panicking at ~30% power or ~1200 lm +#define THERM_FASTER_LEVEL 105 +// respond to thermal changes faster +#define THERMAL_WARNING_SECONDS 3 +#define THERMAL_UPDATE_SPEED 1 +#define THERM_PREDICTION_STRENGTH 4 +//#define THERM_RESPONSE_MAGNITUDE 128 + +// easier access to thermal config mode, for Emisar +#define USE_TENCLICK_THERMAL_CONFIG + +#define THERM_CAL_OFFSET 5 diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index bcf49ed..6832e32 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -20,27 +20,76 @@ #ifndef FSM_ADC_C #define FSM_ADC_C -#ifdef USE_VOLTAGE_DIVIDER -// 1.1V / pin7 -#define ADMUX_VOLTAGE ADMUX_VOLTAGE_DIVIDER -#else -// VCC / 1.1V reference -#define ADMUX_VOLTAGE ADMUX_VCC -#endif +inline void set_admux_therm() { + #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 1634) + ADMUX = ADMUX_THERM; + #elif (ATTINY == 841) + ADMUXA = ADMUXA_THERM; + ADMUXB = ADMUXB_THERM; + #else + #error Unrecognized MCU type + #endif +} + +inline void set_admux_voltage() { + #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 1634) + #ifdef USE_VOLTAGE_DIVIDER + // 1.1V / pin7 + ADMUX = ADMUX_VOLTAGE_DIVIDER; + #else + // VCC / 1.1V reference + ADMUX = ADMUX_VCC; + #endif + #elif (ATTINY == 841) + #ifdef USE_VOLTAGE_DIVIDER + ADMUXA = ADMUXA_VOLTAGE_DIVIDER; + ADMUXB = ADMUXB_VOLTAGE_DIVIDER; + #else + ADMUXA = ADMUXA_VCC; + ADMUXB = ADMUXB_VCC; + #endif + #else + #error Unrecognized MCU type + #endif +} + +inline void ADC_start_measurement() { + #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 841) || (ATTINY == 1634) + ADCSRA |= (1 << ADSC) | (1 << ADIE); + #else + #error unrecognized MCU type + #endif +} + +// set up ADC for reading battery voltage inline void ADC_on() { - // read voltage on VCC by default - ADMUX = ADMUX_VOLTAGE; - #ifdef USE_VOLTAGE_DIVIDER - // disable digital input on divider pin to reduce power consumption - DIDR0 |= (1 << VOLTAGE_ADC_DIDR); + #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 1634) + set_admux_voltage(); + #ifdef USE_VOLTAGE_DIVIDER + // disable digital input on divider pin to reduce power consumption + DIDR0 |= (1 << VOLTAGE_ADC_DIDR); + #else + // disable digital input on VCC pin to reduce power consumption + //DIDR0 |= (1 << ADC_DIDR); // FIXME: unsure how to handle for VCC pin + #endif + #if (ATTINY == 1634) + ACSRA |= (1 << ACD); // turn off analog comparator to save power + #endif + // enable, start, prescale + ADCSRA = (1 << ADEN) | (1 << ADSC) | ADC_PRSCL; + // end tiny25/45/85 + #elif (ATTINY == 841) + ADCSRB = 0; // Right adjusted, auto trigger bits cleared. + //ADCSRA = (1 << ADEN ) | 0b011; // ADC on, prescaler division factor 8. + set_admux_voltage(); + // enable, start, prescale + ADCSRA = (1 << ADEN) | (1 << ADSC) | ADC_PRSCL; + //ADCSRA |= (1 << ADSC); // start measuring #else - // disable digital input on VCC pin to reduce power consumption - //DIDR0 |= (1 << ADC_DIDR); // FIXME: unsure how to handle for VCC pin + #error Unrecognized MCU type #endif - // enable, start, prescale - ADCSRA = (1 << ADEN) | (1 << ADSC) | ADC_PRSCL; } inline void ADC_off() { @@ -89,6 +138,9 @@ ISR(ADC_vect) { // thermal declarations #ifdef USE_THERMAL_REGULATION + #ifndef THERMAL_UPDATE_SPEED + #define THERMAL_UPDATE_SPEED 2 + #endif #define NUM_THERMAL_VALUES_HISTORY 8 #define ADC_STEPS 4 static uint8_t history_step = 0; // don't update history as often @@ -96,7 +148,7 @@ ISR(ADC_vect) { static uint8_t temperature_timer = 0; static uint8_t overheat_lowpass = 0; static uint8_t underheat_lowpass = 0; - #define TEMPERATURE_TIMER_START (THERMAL_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) // N seconds between thermal regulation events + #define TEMPERATURE_TIMER_START ((THERMAL_WARNING_SECONDS-2)*ADC_CYCLES_PER_SECOND) // N seconds between thermal regulation events #define OVERHEAT_LOWPASS_STRENGTH (ADC_CYCLES_PER_SECOND*2) // lowpass for 2 seconds #define UNDERHEAT_LOWPASS_STRENGTH (ADC_CYCLES_PER_SECOND*2) // lowpass for 2 seconds #else @@ -110,6 +162,12 @@ ISR(ADC_vect) { pseudo_rand_seed += measurement; #endif + #if defined(TICK_DURING_STANDBY) && defined(USE_SLEEP_LVP) + // only measure battery voltage while asleep + if (go_to_standby) adc_step = 1; + else + #endif + adc_step = (adc_step + 1) & (ADC_STEPS-1); #ifdef USE_LVP @@ -120,7 +178,7 @@ ISR(ADC_vect) { if (voltage == 0) { for(uint8_t i=0; i THERM_FLOOR) { underheat_lowpass = 0; // we're probably not too cold - } else if (pt < THERM_CEIL) { + } + if (pt < THERM_CEIL) { overheat_lowpass = 0; // we're probably not too hot } @@ -261,6 +333,7 @@ ISR(ADC_vect) { overheat_lowpass = 0; temperature_timer = TEMPERATURE_TIMER_START; // how far above the ceiling? + //int16_t howmuch = (pt - THERM_CEIL) * THERM_RESPONSE_MAGNITUDE / 128; int16_t howmuch = pt - THERM_CEIL; // try to send out a warning emit(EV_temperature_high, howmuch); @@ -276,6 +349,7 @@ ISR(ADC_vect) { underheat_lowpass = 0; temperature_timer = TEMPERATURE_TIMER_START; // how far below the floor? + //int16_t howmuch = (THERM_FLOOR - pt) * THERM_RESPONSE_MAGNITUDE / 128; int16_t howmuch = THERM_FLOOR - pt; // try to send out a warning (unless voltage is low) // (LVP and underheat warnings fight each other) @@ -291,16 +365,21 @@ ISR(ADC_vect) { // set the correct type of measurement for next time #ifdef USE_THERMAL_REGULATION #ifdef USE_LVP - if (adc_step < 2) ADMUX = ADMUX_VOLTAGE; - else ADMUX = ADMUX_THERM; + if (adc_step < 2) set_admux_voltage(); + else set_admux_therm(); #else - ADMUX = ADMUX_THERM; + set_admux_therm(); #endif #else #ifdef USE_LVP - ADMUX = ADMUX_VOLTAGE; + set_admux_voltage(); #endif #endif + + #ifdef TICK_DURING_STANDBY + // if we were asleep, go back to sleep + if (go_to_standby) ADC_off(); + #endif } #ifdef USE_BATTCHECK diff --git a/spaghetti-monster/fsm-adc.h b/spaghetti-monster/fsm-adc.h index 6256e2c..274fb4d 100644 --- a/spaghetti-monster/fsm-adc.h +++ b/spaghetti-monster/fsm-adc.h @@ -38,7 +38,7 @@ #define VOLTAGE_FUDGE_FACTOR 5 #endif #endif -volatile uint8_t voltage; +volatile uint8_t voltage = 0; volatile uint8_t adcint_enable; // kludge, because adc auto-retrigger won't turn off void low_voltage(); #ifdef USE_BATTCHECK @@ -84,6 +84,7 @@ volatile uint8_t reset_thermal_history = 1; inline void ADC_on(); inline void ADC_off(); +inline void ADC_start_measurement(); #endif diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index 72216ae..362a5cc 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -20,6 +20,7 @@ #ifndef FSM_EVENTS_C #define FSM_EVENTS_C + void empty_event_sequence() { current_event = EV_none; // when the user completes an input sequence, interrupt any running timers @@ -116,26 +117,26 @@ uint8_t nice_delay_ms(uint16_t ms) { #ifdef USE_RAMPING uint8_t level = actual_level; // volatile, avoid repeat access if (level < QUARTERSPEED_LEVEL) { - CLKPR = 1< 0) { // underclock MCU to save power - CLKPR = 1< 0) { + // wait + _delay_loop_2(BOGOMIPS*398/100); } } #endif diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index 1c28f5f..e537a9e 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -36,21 +36,8 @@ ISR(TIMER1_COMPA_vect) { } #endif -int main() { - // Don't allow interrupts while booting - cli(); - - #ifdef USE_REBOOT // prevent reboot loops - MCUSR &= ~(1<= 1 DDRB |= (1 << PWM1_PIN); @@ -80,6 +67,45 @@ int main() { // configure e-switch PORTB = (1 << SWITCH_PIN); // e-switch is the only input PCMSK = (1 << SWITCH_PIN); // pin change interrupt uses this pin +} +#elif (ATTINY == 1634) +inline void hw_setup() { + // this gets tricky with so many pins... + // ... so punt it to the hwdef file + hwdef_setup(); +} +#else + #error Unrecognized MCU type +#endif + + +#ifdef USE_REBOOT +void prevent_reboot_loop() { + // prevent WDT from rebooting MCU again + MCUSR &= ~(1<> (i<<1)) & 0x03; + uint8_t pin = pins[i]; + switch (lvl) { + case 0: // LED off + AUXLED_RGB_DDR &= 0xff ^ (1 << pin); + AUXLED_RGB_PUE &= 0xff ^ (1 << pin); + AUXLED_RGB_PORT &= 0xff ^ (1 << pin); + break; + case 1: // LED low + AUXLED_RGB_DDR &= 0xff ^ (1 << pin); + AUXLED_RGB_PUE |= (1 << pin); + AUXLED_RGB_PORT |= (1 << pin); + break; + default: // LED high + AUXLED_RGB_DDR |= (1 << pin); + AUXLED_RGB_PUE |= (1 << pin); + AUXLED_RGB_PORT |= (1 << pin); + break; + } + } +} +#endif // ifdef USE_AUX_RGB_LEDS + #ifdef USE_TRIANGLE_WAVE uint8_t triangle_wave(uint8_t phase) { uint8_t result = phase << 1; diff --git a/spaghetti-monster/fsm-misc.h b/spaghetti-monster/fsm-misc.h index 1381ca2..a39d31a 100644 --- a/spaghetti-monster/fsm-misc.h +++ b/spaghetti-monster/fsm-misc.h @@ -43,9 +43,16 @@ uint8_t blink(uint8_t num, uint8_t speed); */ #ifdef USE_INDICATOR_LED +// lvl: 0=off, 1=low, 2=high void indicator_led(uint8_t lvl); #endif +#ifdef USE_AUX_RGB_LEDS +// value: 0b00BBGGRR +// each pair of bits: 0=off, 1=low, 2=high +void rgb_led_set(uint8_t value); +#endif + #ifdef USE_TRIANGLE_WAVE uint8_t triangle_wave(uint8_t phase); #endif diff --git a/spaghetti-monster/fsm-pcint.c b/spaghetti-monster/fsm-pcint.c index acb627d..4928980 100644 --- a/spaghetti-monster/fsm-pcint.c +++ b/spaghetti-monster/fsm-pcint.c @@ -30,7 +30,7 @@ uint8_t button_is_pressed() { // and wait for measurements to settle to all zeroes or all ones do { // shift past readings and add current value - readings = (readings << 1) | ((PINB & (1< 0) + (level > MAX_1x7135)); - //if (level > MAX_1x7135) indicator_led(2); - //else if (level > 0) indicator_led(1); - //else if (! go_to_standby) indicator_led(0); + #ifdef USE_INDICATOR_LED + if (! go_to_standby) + indicator_led((level > 0) + (level > MAX_1x7135)); + #endif + //if (level > MAX_1x7135) indicator_led(2); + //else if (level > 0) indicator_led(1); + //else if (! go_to_standby) indicator_led(0); #else - if (! go_to_standby) - indicator_led(0); - #endif + #if defined(USE_INDICATOR_LED) || defined(USE_AUX_RGB_LEDS) + if (! go_to_standby) { + #ifdef USE_INDICATOR_LED + indicator_led(0); + #endif + #ifdef USE_AUX_RGB_LEDS + rgb_led_set(0); + #endif + } + #endif #endif //TCCR0A = PHASE; diff --git a/spaghetti-monster/fsm-standby.c b/spaghetti-monster/fsm-standby.c index 7d60c1d..44b047a 100644 --- a/spaghetti-monster/fsm-standby.c +++ b/spaghetti-monster/fsm-standby.c @@ -56,7 +56,9 @@ void sleep_until_eswitch_pressed() set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); + #ifdef BODCR // only do this on MCUs which support it sleep_bod_disable(); + #endif sleep_cpu(); // wait here // something happened; wake up diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index d5bbdb9..6e61e87 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -25,38 +25,65 @@ void WDT_on() { - // interrupt every 16ms - //cli(); // Disable interrupts - wdt_reset(); // Reset the WDT - WDTCR |= (1< +#include // include project definitions to help with recognizing symbols #include "fsm-events.h" diff --git a/tk-attiny.h b/tk-attiny.h index 3c985f2..947a87c 100644 --- a/tk-attiny.h +++ b/tk-attiny.h @@ -28,24 +28,26 @@ /******************** hardware-specific values **************************/ #if (ATTINY == 13) #define F_CPU 4800000UL - #define EEPSIZE 64 + //#define EEPSIZE 64 #define V_REF REFS0 #define BOGOMIPS 950 #define ADMUX_VCC 0b00001100 #define DELAY_ZERO_TIME 252 + #define SWITCH_PORT PINB // PINA or PINB or PINC #elif (ATTINY == 25) // TODO: Use 6.4 MHz instead of 8 MHz? #define F_CPU 8000000UL - #define EEPSIZE 128 + //#define EEPSIZE 128 #define V_REF REFS1 #define BOGOMIPS (F_CPU/4000) #define ADMUX_VCC 0b00001100 #define ADMUX_THERM 0b10001111 #define DELAY_ZERO_TIME 1020 + #define SWITCH_PORT PINB // PINA or PINB or PINC #elif (ATTINY == 85) // TODO: Use 6.4 MHz instead of 8 MHz? #define F_CPU 8000000UL - #define EEPSIZE 512 + //#define EEPSIZE 512 #define V_REF REFS1 #define BOGOMIPS (F_CPU/4000) // (1 << V_REF) | (0 << ADLAR) | (VCC_CHANNEL) @@ -53,10 +55,30 @@ // (1 << V_REF) | (0 << ADLAR) | (THERM_CHANNEL) #define ADMUX_THERM 0b10001111 #define DELAY_ZERO_TIME 1020 + #define SWITCH_PORT PINB // PINA or PINB or PINC +#elif (ATTINY == 1634) + #define F_CPU 8000000UL + #define V_REF REFS1 + #define BOGOMIPS (F_CPU/4000) + // (1 << V_REF) | (0 << ADLAR) | (VCC_CHANNEL) + #define ADMUX_VCC 0b00001101 + // (1 << V_REF) | (0 << ADLAR) | (THERM_CHANNEL) + #define ADMUX_THERM 0b10001110 + #define DELAY_ZERO_TIME 1020 + //#define SWITCH_PORT PINA // set this in hwdef #else #error Hey, you need to define ATTINY. #endif +// auto-detect eeprom size from avr-libc headers +#ifndef EEPSIZE +#ifdef E2SIZE +#define EEPSIZE E2SIZE +#else +#define EEPSIZE (E2END+1) +#endif +#endif + #include @@ -86,4 +108,31 @@ #error Hey, you need to define an I/O pin layout. #endif +#if (ATTINY==25) || (ATTINY==45) || (ATTINY==85) + // use clock_prescale_set(n) instead; it's safer + //#define CLOCK_DIVIDER_SET(n) {CLKPR = 1<