From c7b6a22af23fb611c66d3f6c5d6e9a934589f0ca Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 28 Jun 2019 03:41:42 -0600 Subject: added support for Mateminco MF01-Mini --- .../anduril/cfg-mateminco-mf01-mini.h | 61 ++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h b/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h new file mode 100644 index 0000000..2d1e5c7 --- /dev/null +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h @@ -0,0 +1,61 @@ +// Mateminco/Astrolux MF01-Mini options for Anduril +#include "hwdef-Mateminco_MF01-Mini.h" + +// the button lights up +#define USE_INDICATOR_LED +#define INDICATOR_LED_SKIP_LOW // low mode doesn't work on this driver +// 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: high (2) +// lockout: blinking (3) +#define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 2) + + +// 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 Sofirn 5500mAh cell at 3.97V: +// moon: 0.3 lm +// channel 1: 113 lm +// channel 2: 718 lm +// channel 3: 3500 lm +// ../../../bin/level_calc.py ninth 3 150 7135 1 2.5 115.65 7135 11 5 708.65 FET 1 10 3500 +// (plus some manual tweaks for a smoother ramp) +#define RAMP_LENGTH 150 +#define PWM1_LEVELS 1,1,2,2,3,3,4,5,5,6,7,8,9,9,10,14,15,16,17,18,19,20,21,22,24,26,28,30,32,34,37,39,42,45,48,51,54,58,62,65,69,74,78,83,88,93,98,104,110,116,123,130,137,145,153,161,170,179,188,198,208,219,231,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,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,11,13,16,18,20,23,25,28,31,34,37,40,43,47,50,54,58,62,66,70,75,80,85,90,95,100,106,112,118,125,131,138,145,153,161,169,177,185,194,204,213,223,233,244,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,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 PWM3_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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,6,10,13,17,21,24,28,33,37,41,46,50,55,60,66,71,76,82,88,94,101,107,114,121,128,135,143,151,159,167,176,185,194,203,213,223,233,244,255 +#define MAX_1x7135 65 // ~113 lm +#define MAX_Nx7135 110 +#define HALFSPEED_LEVEL 16 +#define QUARTERSPEED_LEVEL 8 + +#define RAMP_SMOOTH_FLOOR 1 // ~0.3 lm +#define RAMP_SMOOTH_CEIL 130 // ~??? lm +// 14/135/6 = 14, 38, 62, 86, [110], 135 +// 20/110/7 = 20, 35, 50, [65], 80, 95, [110] +// 15/130/7 = 15, 34, 53, 72, 91, [110], 130 +#if 1 +#define RAMP_DISCRETE_FLOOR 15 // ~?? lm +#define RAMP_DISCRETE_CEIL 130 // ~??? lm +#define RAMP_DISCRETE_STEPS 7 // ??, ??, ... lm +#else // testing only; for calibrating the ramp in detail +#define RAMP_DISCRETE_FLOOR 1 // ~?? lm +#define RAMP_DISCRETE_CEIL 150 // ~??? lm +#define RAMP_DISCRETE_STEPS 150 // ??, ??, ... lm +#endif + + +#define USE_TENCLICK_THERMAL_CONFIG // by request +#define THERM_FASTER_LEVEL 130 // throttle back faster when high +//#define THERM_HARD_TURBO_DROP // this light is massively overpowered +#define THERMAL_WARNING_SECONDS 1 // FIXME: increase by 2 after merging newer code +//#define THERMAL_UPDATE_SPEED 1 +//#define THERM_PREDICTION_STRENGTH 4 + -- cgit v1.2.3 From 849fcfd3e1b828c6f35d62792a308917b2ef0053 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 26 Jul 2019 20:51:38 -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 --- 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 + 19 files changed, 645 insertions(+), 185 deletions(-) create mode 100644 spaghetti-monster/anduril/cfg-emisar-d4v2-219.h create mode 100644 spaghetti-monster/anduril/cfg-emisar-d4v2.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index c2a4b77..8ab66f5 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -132,11 +132,13 @@ // full FET strobe can be a bit much... use max regulated level instead, // if there's a bright enough regulated level +#ifndef STROBE_BRIGHTNESS #ifdef MAX_Nx7135 #define STROBE_BRIGHTNESS MAX_Nx7135 #else #define STROBE_BRIGHTNESS MAX_LEVEL #endif +#endif #if defined(USE_CANDLE_MODE) || defined(USE_BIKE_FLASHER_MODE) || defined(USE_PARTY_STROBE_MODE) || defined(USE_TACTICAL_STROBE_MODE) || defined(USE_LIGHTNING_MODE) #define USE_STROBE_STATE @@ -186,6 +188,10 @@ typedef enum { #ifdef USE_INDICATOR_LED indicator_led_mode_e, #endif + #ifdef USE_AUX_RGB_LEDS + rgb_led_off_mode_e, + rgb_led_lockout_mode_e, + #endif eeprom_indexes_e_END } eeprom_indexes_e; #define EEPROM_BYTES eeprom_indexes_e_END @@ -299,6 +305,31 @@ void blip(); #if defined(USE_INDICATOR_LED) && defined(TICK_DURING_STANDBY) void indicator_blink(uint8_t arg); #endif +#if defined(USE_AUX_RGB_LEDS) && defined(TICK_DURING_STANDBY) +void rgb_led_update(uint8_t mode, uint8_t arg); +/* + * 0: R + * 1: RG + * 2: G + * 3: GB + * 4: B + * 5: R B + * 6: RGB + * 7: rainbow + * 8: voltage + */ +#define RGB_LED_NUM_COLORS 10 +#define RGB_LED_NUM_PATTERNS 4 +#ifndef RGB_LED_OFF_DEFAULT +//#define RGB_LED_OFF_DEFAULT 0x18 // low, voltage +#define RGB_LED_OFF_DEFAULT 0x17 // low, rainbow +#endif +#ifndef RGB_LED_LOCKOUT_DEFAULT +#define RGB_LED_LOCKOUT_DEFAULT 0x37 // blinking, rainbow +#endif +uint8_t rgb_led_off_mode = RGB_LED_OFF_DEFAULT; +uint8_t rgb_led_lockout_mode = RGB_LED_LOCKOUT_DEFAULT; +#endif #ifdef USE_FACTORY_RESET void factory_reset(); @@ -459,27 +490,36 @@ uint8_t off_state(Event event, uint16_t arg) { set_level(0); #ifdef USE_INDICATOR_LED indicator_led(indicator_led_mode & 0x03); + #elif defined(USE_AUX_RGB_LEDS) + rgb_led_update(rgb_led_off_mode, 0); #endif // sleep while off (lower power use) - go_to_standby = 1; + // (unless delay requested; give the ADC some time to catch up) + if (! arg) { go_to_standby = 1; } return MISCHIEF_MANAGED; } // go back to sleep eventually if we got bumped but didn't leave "off" state else 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 & 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 - uint8_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" -- cgit v1.2.3 From b4faa446aca1271d918d8a809c770ebeb5efa8a4 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 30 Jul 2019 15:59:23 -0600 Subject: fsm-ramping: made it possible to change bit depth of PWM values (8-bit or 16-bit) --- spaghetti-monster/fsm-ramping.c | 26 +++++++++--------- spaghetti-monster/fsm-ramping.h | 58 +++++++++++++++++++++++++---------------- 2 files changed, 48 insertions(+), 36 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index efa07e4..69e20bc 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -71,7 +71,7 @@ void set_level(uint8_t level) { #ifdef USE_TINT_RAMPING // calculate actual PWM levels based on a single-channel ramp // and a global tint value - uint8_t brightness = pgm_read_byte(pwm1_levels + level); + uint8_t brightness = PWM_GET(pwm1_levels, level); uint8_t warm_PWM, cool_PWM; // auto-tint modes @@ -104,16 +104,16 @@ void set_level(uint8_t level) { #else #if PWM_CHANNELS >= 1 - PWM1_LVL = pgm_read_byte(pwm1_levels + level); + PWM1_LVL = PWM_GET(pwm1_levels, level); #endif #if PWM_CHANNELS >= 2 - PWM2_LVL = pgm_read_byte(pwm2_levels + level); + PWM2_LVL = PWM_GET(pwm2_levels, level); #endif #if PWM_CHANNELS >= 3 - PWM3_LVL = pgm_read_byte(pwm3_levels + level); + PWM3_LVL = PWM_GET(pwm3_levels, level); #endif #if PWM_CHANNELS >= 4 - PWM4_LVL = pgm_read_byte(pwm4_levels + level); + PWM4_LVL = PWM_GET(pwm4_levels, level); #endif #endif // ifdef USE_TINT_RAMPING @@ -140,7 +140,7 @@ void gradual_tick() { uint8_t target; #if PWM_CHANNELS >= 1 - target = pgm_read_byte(pwm1_levels + gt); + target = PWM_GET(pwm1_levels, gt); if ((gt < actual_level) // special case for FET-only turbo && (PWM1_LVL == 0) // (bypass adjustment period for first step) && (target == 255)) PWM1_LVL = 255; @@ -148,32 +148,32 @@ void gradual_tick() { else if (PWM1_LVL > target) PWM1_LVL --; #endif #if PWM_CHANNELS >= 2 - target = pgm_read_byte(pwm2_levels + gt); + target = PWM_GET(pwm2_levels, gt); if (PWM2_LVL < target) PWM2_LVL ++; else if (PWM2_LVL > target) PWM2_LVL --; #endif #if PWM_CHANNELS >= 3 - target = pgm_read_byte(pwm3_levels + gt); + target = PWM_GET(pwm3_levels, gt); if (PWM3_LVL < target) PWM3_LVL ++; else if (PWM3_LVL > target) PWM3_LVL --; #endif #if PWM_CHANNELS >= 4 - target = pgm_read_byte(pwm4_levels + gt); + target = PWM_GET(pwm4_levels, gt); if (PWM4_LVL < target) PWM4_LVL ++; else if (PWM4_LVL > target) PWM4_LVL --; #endif // did we go far enough to hit the next defined ramp level? // if so, update the main ramp level tracking var - if ((PWM1_LVL == pgm_read_byte(pwm1_levels + gt)) + if ((PWM1_LVL == PWM_GET(pwm1_levels, gt)) #if PWM_CHANNELS >= 2 - && (PWM2_LVL == pgm_read_byte(pwm2_levels + gt)) + && (PWM2_LVL == PWM_GET(pwm2_levels, gt)) #endif #if PWM_CHANNELS >= 3 - && (PWM3_LVL == pgm_read_byte(pwm3_levels + gt)) + && (PWM3_LVL == PWM_GET(pwm3_levels, gt)) #endif #if PWM_CHANNELS >= 4 - && (PWM4_LVL == pgm_read_byte(pwm4_levels + gt)) + && (PWM4_LVL == PWM_GET(pwm4_levels, gt)) #endif ) { diff --git a/spaghetti-monster/fsm-ramping.h b/spaghetti-monster/fsm-ramping.h index dcc3b74..7233474 100644 --- a/spaghetti-monster/fsm-ramping.h +++ b/spaghetti-monster/fsm-ramping.h @@ -38,18 +38,30 @@ inline void set_level_gradually(uint8_t lvl); void gradual_tick(); #endif +// auto-detect the data type for PWM tables +#ifndef PWM_BITS +#define PWM_BITS 8 +#endif +#if PWM_BITS <= 8 +#define PWM_DATATYPE uint8_t +#define PWM_GET(x,y) pgm_read_byte(x+y) +#else +#define PWM_DATATYPE uint16_t +#define PWM_GET(x,y) pgm_read_word(x+(2*y)) +#endif + // use UI-defined ramp tables if they exist #ifdef PWM1_LEVELS -PROGMEM const uint8_t pwm1_levels[] = { PWM1_LEVELS }; +PROGMEM const PWM_DATATYPE pwm1_levels[] = { PWM1_LEVELS }; #endif #ifdef PWM2_LEVELS -PROGMEM const uint8_t pwm2_levels[] = { PWM2_LEVELS }; +PROGMEM const PWM_DATATYPE pwm2_levels[] = { PWM2_LEVELS }; #endif #ifdef PWM3_LEVELS -PROGMEM const uint8_t pwm3_levels[] = { PWM3_LEVELS }; +PROGMEM const PWM_DATATYPE pwm3_levels[] = { PWM3_LEVELS }; #endif #ifdef PWM4_LEVELS -PROGMEM const uint8_t pwm4_levels[] = { PWM4_LEVELS }; +PROGMEM const PWM_DATATYPE pwm4_levels[] = { PWM4_LEVELS }; #endif // default / example ramps @@ -57,31 +69,31 @@ PROGMEM const uint8_t pwm4_levels[] = { PWM4_LEVELS }; #if PWM_CHANNELS == 1 #if RAMP_LENGTH == 50 // ../../bin/level_calc.py 1 50 7135 3 0.25 980 - PROGMEM const uint8_t pwm1_levels[] = { 3,3,3,3,4,4,4,5,5,6,7,8,9,11,12,14,16,18,20,23,25,28,32,35,39,43,47,52,57,62,68,74,80,87,94,102,110,118,127,136,146,156,167,178,189,201,214,227,241,255 }; + PROGMEM const PWM_DATATYPE pwm1_levels[] = { 3,3,3,3,4,4,4,5,5,6,7,8,9,11,12,14,16,18,20,23,25,28,32,35,39,43,47,52,57,62,68,74,80,87,94,102,110,118,127,136,146,156,167,178,189,201,214,227,241,255 }; #elif RAMP_LENGTH == 75 // ../../bin/level_calc.py 1 75 7135 3 0.25 980 - PROGMEM const uint8_t pwm1_levels[] = { 3,3,3,3,3,3,4,4,4,4,5,5,5,6,6,7,8,8,9,10,11,12,13,14,15,17,18,20,21,23,25,27,29,31,33,36,38,41,44,47,50,53,56,59,63,67,71,75,79,83,88,93,98,103,108,113,119,125,131,137,143,150,157,164,171,178,186,194,202,210,219,227,236,246,255 }; + PROGMEM const PWM_DATATYPE pwm1_levels[] = { 3,3,3,3,3,3,4,4,4,4,5,5,5,6,6,7,8,8,9,10,11,12,13,14,15,17,18,20,21,23,25,27,29,31,33,36,38,41,44,47,50,53,56,59,63,67,71,75,79,83,88,93,98,103,108,113,119,125,131,137,143,150,157,164,171,178,186,194,202,210,219,227,236,246,255 }; #elif RAMP_LENGTH == 150 // ../../bin/level_calc.py 1 150 7135 3 0.25 980 - PROGMEM const uint8_t pwm1_levels[] = { 3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,6,6,6,6,7,7,7,8,8,8,9,9,9,10,10,11,11,12,12,13,13,14,15,15,16,17,17,18,19,19,20,21,22,23,24,24,25,26,27,28,29,31,32,33,34,35,36,38,39,40,42,43,44,46,47,49,50,52,53,55,57,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,89,91,93,96,98,101,103,106,109,111,114,117,120,123,125,128,131,134,138,141,144,147,151,154,157,161,164,168,171,175,179,183,186,190,194,198,202,206,210,215,219,223,228,232,236,241,246,250,255 }; + PROGMEM const PWM_DATATYPE pwm1_levels[] = { 3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,6,6,6,6,7,7,7,8,8,8,9,9,9,10,10,11,11,12,12,13,13,14,15,15,16,17,17,18,19,19,20,21,22,23,24,24,25,26,27,28,29,31,32,33,34,35,36,38,39,40,42,43,44,46,47,49,50,52,53,55,57,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,89,91,93,96,98,101,103,106,109,111,114,117,120,123,125,128,131,134,138,141,144,147,151,154,157,161,164,168,171,175,179,183,186,190,194,198,202,206,210,215,219,223,228,232,236,241,246,250,255 }; #endif #elif PWM_CHANNELS == 2 #if RAMP_LENGTH == 50 // ../../bin/level_calc.py 2 50 7135 4 0.33 150 FET 1 10 1500 - PROGMEM const uint8_t pwm1_levels[] = { 4,5,6,8,10,13,17,22,28,35,44,54,65,78,93,109,128,149,171,197,224,255,255,255,255,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 }; - PROGMEM const uint8_t pwm2_levels[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,7,11,15,20,26,31,37,44,51,58,65,73,82,91,100,110,121,132,143,155,168,181,194,209,224,239,255 }; + PROGMEM const PWM_DATATYPE pwm1_levels[] = { 4,5,6,8,10,13,17,22,28,35,44,54,65,78,93,109,128,149,171,197,224,255,255,255,255,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 }; + PROGMEM const PWM_DATATYPE pwm2_levels[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,7,11,15,20,26,31,37,44,51,58,65,73,82,91,100,110,121,132,143,155,168,181,194,209,224,239,255 }; #define MAX_1x7135 22 #elif RAMP_LENGTH == 75 // ../../bin/level_calc.py 2 75 7135 4 0.33 150 FET 1 10 1500 - PROGMEM const uint8_t pwm1_levels[] = { 4,4,5,6,7,8,10,12,14,17,20,24,28,32,37,43,49,56,64,72,82,91,102,114,126,139,153,168,184,202,220,239,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,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 }; - PROGMEM const uint8_t 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,2,5,7,10,13,16,19,23,26,30,34,38,42,47,51,56,61,66,72,77,83,89,95,101,108,115,122,129,136,144,152,160,168,177,186,195,204,214,224,234,244,255 }; + PROGMEM const PWM_DATATYPE pwm1_levels[] = { 4,4,5,6,7,8,10,12,14,17,20,24,28,32,37,43,49,56,64,72,82,91,102,114,126,139,153,168,184,202,220,239,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,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 }; + PROGMEM const PWM_DATATYPE 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,2,5,7,10,13,16,19,23,26,30,34,38,42,47,51,56,61,66,72,77,83,89,95,101,108,115,122,129,136,144,152,160,168,177,186,195,204,214,224,234,244,255 }; #define MAX_1x7135 33 #elif RAMP_LENGTH == 150 // ../../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 - PROGMEM const uint8_t 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 }; - PROGMEM const uint8_t 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 }; + PROGMEM const PWM_DATATYPE 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 }; + PROGMEM const PWM_DATATYPE 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 @@ -89,25 +101,25 @@ PROGMEM const uint8_t pwm4_levels[] = { PWM4_LEVELS }; #elif PWM_CHANNELS == 3 #if RAMP_LENGTH == 50 // ../../bin/level_calc.py 3 50 7135 4 0.33 150 7135 4 1 840 FET 1 10 2000 - PROGMEM const uint8_t pwm1_levels[] = { 4,5,6,8,11,15,20,26,34,43,54,67,82,99,118,140,165,192,221,254,255,255,255,255,255,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 }; - PROGMEM const uint8_t pwm2_levels[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,17,25,33,42,52,62,73,85,97,111,125,140,157,174,192,210,230,251,255,255,255,255,255,255,255,255,255,255,0 }; - PROGMEM const uint8_t pwm3_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,14,34,54,76,98,122,146,172,198,226,255 }; + PROGMEM const PWM_DATATYPE pwm1_levels[] = { 4,5,6,8,11,15,20,26,34,43,54,67,82,99,118,140,165,192,221,254,255,255,255,255,255,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 }; + PROGMEM const PWM_DATATYPE pwm2_levels[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,17,25,33,42,52,62,73,85,97,111,125,140,157,174,192,210,230,251,255,255,255,255,255,255,255,255,255,255,0 }; + PROGMEM const PWM_DATATYPE pwm3_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,14,34,54,76,98,122,146,172,198,226,255 }; #define MAX_1x7135 20 #define MAX_Nx7135 39 #elif RAMP_LENGTH == 75 // ../../bin/level_calc.py 3 75 7135 4 0.33 150 7135 4 1 840 FET 1 10 2000 - PROGMEM const uint8_t pwm1_levels[] = { 4,4,5,6,7,9,11,14,16,20,24,28,34,40,46,54,62,71,81,92,104,117,130,146,162,179,198,218,239,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,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 }; - PROGMEM const uint8_t 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,5,9,14,18,23,29,34,40,47,53,60,67,75,83,91,99,108,117,127,137,148,158,170,181,193,206,219,232,246,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0 }; - PROGMEM const uint8_t pwm3_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,3,15,28,42,55,70,84,99,115,131,147,164,181,199,217,236,255 }; + PROGMEM const PWM_DATATYPE pwm1_levels[] = { 4,4,5,6,7,9,11,14,16,20,24,28,34,40,46,54,62,71,81,92,104,117,130,146,162,179,198,218,239,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,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 }; + PROGMEM const PWM_DATATYPE 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,5,9,14,18,23,29,34,40,47,53,60,67,75,83,91,99,108,117,127,137,148,158,170,181,193,206,219,232,246,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0 }; + PROGMEM const PWM_DATATYPE pwm3_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,3,15,28,42,55,70,84,99,115,131,147,164,181,199,217,236,255 }; #define MAX_1x7135 30 #define MAX_Nx7135 59 #elif RAMP_LENGTH == 150 // ../../bin/level_calc.py 1 65 7135 1 0.8 150 // ... mixed with this: // ../../../bin/level_calc.py 3 150 7135 1 0.33 150 7135 1 1 850 FET 1 10 1500 - PROGMEM const uint8_t 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 }; - PROGMEM const uint8_t 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,2,4,6,8,10,13,15,17,19,22,24,26,29,31,34,37,39,42,45,48,51,54,57,60,64,67,70,74,77,81,85,88,92,96,100,104,108,112,116,121,125,130,134,139,143,148,153,158,163,168,173,179,184,189,195,201,206,212,218,224,230,236,243,249,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0 }; - PROGMEM const uint8_t pwm3_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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,19,31,43,55,67,79,91,104,117,130,143,157,170,184,198,212,226,240,255 }; + PROGMEM const PWM_DATATYPE 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 }; + PROGMEM const PWM_DATATYPE 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,2,4,6,8,10,13,15,17,19,22,24,26,29,31,34,37,39,42,45,48,51,54,57,60,64,67,70,74,77,81,85,88,92,96,100,104,108,112,116,121,125,130,134,139,143,148,153,158,163,168,173,179,184,189,195,201,206,212,218,224,230,236,243,249,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0 }; + PROGMEM const PWM_DATATYPE pwm3_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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,19,31,43,55,67,79,91,104,117,130,143,157,170,184,198,212,226,240,255 }; #define MAX_1x7135 65 #define MAX_Nx7135 130 #define HALFSPEED_LEVEL 14 @@ -119,7 +131,7 @@ PROGMEM const uint8_t pwm4_levels[] = { PWM4_LEVELS }; #endif // RAMP_SIZE / MAX_LVL -#define RAMP_SIZE sizeof(pwm1_levels) +#define RAMP_SIZE (sizeof(pwm1_levels)/sizeof(PWM_DATATYPE)) #define MAX_LEVEL RAMP_SIZE void set_level(uint8_t level); -- cgit v1.2.3 From 26c61658ff87710d9528f6749202245464675a1c Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 30 Jul 2019 15:59:58 -0600 Subject: anduril: made it possible for config files to disable underclocking at low levels --- spaghetti-monster/anduril/anduril.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 8ab66f5..9853878 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -89,6 +89,10 @@ //#define USE_POLICE_STROBE_MODE //#define USE_SOS_MODE +// cut clock speed at very low modes for better efficiency +// (defined here so config files can override it) +#define USE_DYNAMIC_UNDERCLOCKING + /***** specific settings for known driver types *****/ #include "tk.h" #include incfile(CONFIGFILE) @@ -128,7 +132,6 @@ #endif #endif #define USE_IDLE_MODE // reduce power use while awake and no tasks are pending -#define USE_DYNAMIC_UNDERCLOCKING // cut clock speed at very low modes for better efficiency // full FET strobe can be a bit much... use max regulated level instead, // if there's a bright enough regulated level -- cgit v1.2.3 From 9fdb43496a1d2b54ab5c4f030d480d8f69d7529c Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 30 Jul 2019 16:00:57 -0600 Subject: added an early version of Emisar D1S v2 hwdef and cfg files (it compiles, but most likely doesn't actually work because it's far from finished) --- spaghetti-monster/anduril/cfg-emisar-d1sv2.h | 51 ++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 spaghetti-monster/anduril/cfg-emisar-d1sv2.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-emisar-d1sv2.h b/spaghetti-monster/anduril/cfg-emisar-d1sv2.h new file mode 100644 index 0000000..45424b3 --- /dev/null +++ b/spaghetti-monster/anduril/cfg-emisar-d1sv2.h @@ -0,0 +1,51 @@ +// Emisar D1S v2 config options for Anduril +#include "hwdef-Emisar_D1Sv2.h" +// ATTINY: 1634 + +// this light has three aux LED channels: R, G, B +#define USE_AUX_RGB_LEDS +#define USE_AUX_RGB_LEDS_WHILE_RAMPING + +// enable blinking aux LEDs +#define TICK_DURING_STANDBY +#define STANDBY_TICK_SPEED 3 // every 0.128 s + + +// ../../bin/level_calc.py cube 1 150 7135 1 4 1300 +// (with max_pwm set to 1023) +#define RAMP_LENGTH 150 +#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,6,7,8,9,10,11,12,13,14,15,16,17,18,20,21,23,24,26,27,29,31,32,34,36,38,40,43,45,47,49,52,54,57,60,62,65,68,71,74,77,81,84,87,91,95,98,102,106,110,114,118,122,127,131,136,141,145,150,155,160,166,171,176,182,188,193,199,205,211,218,224,231,237,244,251,258,265,272,280,287,295,303,310,319,327,335,344,352,361,370,379,388,397,407,416,426,436,446,457,467,477,488,499,510,521,533,544,556,568,580,592,604,617,629,642,655,668,682,695,709,723,737,751,766,781,795,810,826,841,857,872,888,904,921,937,954,971,988,1005,1023 +#define MAX_1x7135 65 + +// the entire ramp is regulated; don't blink halfway up +#ifdef BLINK_AT_RAMP_MIDDLE +#undef BLINK_AT_RAMP_MIDDLE +#endif + +// don't slow down at low levels; this isn't that sort of light +// (it needs to stay at full speed for the 10-bit PWM to work) +#ifdef USE_DYNAMIC_UNDERCLOCKING +#undef USE_DYNAMIC_UNDERCLOCKING +#endif + +#define RAMP_SMOOTH_FLOOR 1 +#define RAMP_SMOOTH_CEIL 130 +#define RAMP_DISCRETE_FLOOR 20 +#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 ~70% power or ~900 lm +#define THERM_FASTER_LEVEL 130 +// respond to thermal changes faster +#define THERMAL_WARNING_SECONDS 3 +#define THERMAL_UPDATE_SPEED 1 +#define THERM_PREDICTION_STRENGTH 4 + +// easier access to thermal config mode, for Emisar +#define USE_TENCLICK_THERMAL_CONFIG + +#define THERM_CAL_OFFSET 5 -- cgit v1.2.3 From 775a114098b9db17fe52ddff5ed080e0b24e5a38 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 30 Jul 2019 20:15:06 -0600 Subject: fsm-ramping: turn opamp chip on and off automatically based on ramp level --- spaghetti-monster/fsm-ramping.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 69e20bc..52a7246 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -65,9 +65,18 @@ void set_level(uint8_t level) { #if PWM_CHANNELS >= 4 PWM4_LVL = 0; #endif + // disable the power channel, if relevant + #ifdef LED_ENABLE_PIN + LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN); + #endif } else { level --; + // enable the power channel, if relevant + #ifdef LED_ENABLE_PIN + LED_ENABLE_PORT |= (1 << LED_ENABLE_PIN); + #endif + #ifdef USE_TINT_RAMPING // calculate actual PWM levels based on a single-channel ramp // and a global tint value -- cgit v1.2.3 From 319fbbcb6de77d26fd5d3e935dea47cd4c12ed07 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 30 Jul 2019 20:16:16 -0600 Subject: anduril: allow RGB LEDs to stay on (in voltage mode) while main LEDs are on (also, refactored RGB aux LED code a little; moved color table to ROM) --- spaghetti-monster/anduril/anduril.c | 61 ++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 15 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 9853878..a82ba4b 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -310,6 +310,7 @@ void indicator_blink(uint8_t arg); #endif #if defined(USE_AUX_RGB_LEDS) && defined(TICK_DURING_STANDBY) void rgb_led_update(uint8_t mode, uint8_t arg); +void rgb_led_voltage_readout(uint8_t bright); /* * 0: R * 1: RG @@ -321,6 +322,15 @@ void rgb_led_update(uint8_t mode, uint8_t arg); * 7: rainbow * 8: voltage */ +const PROGMEM uint8_t rgb_led_colors[] = { + 0b00000001, // 0: red + 0b00000101, // 1: yellow + 0b00000100, // 2: green + 0b00010100, // 3: cyan + 0b00010000, // 4: blue + 0b00010001, // 5: purple + 0b00010101, // 6: white +}; #define RGB_LED_NUM_COLORS 10 #define RGB_LED_NUM_PATTERNS 4 #ifndef RGB_LED_OFF_DEFAULT @@ -2269,36 +2279,28 @@ void rgb_led_update(uint8_t mode, uint8_t arg) { 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 - }; + const uint8_t *colors = rgb_led_colors; uint8_t actual_color = 0; if (color < 7) { // normal color - actual_color = colors[color]; + actual_color = pgm_read_byte(colors + color); } else if (color == 7) { // rainbow if (0 == (arg & 0x03)) { rainbow = (rainbow + 1) % 6; } - actual_color = colors[rainbow]; + actual_color = pgm_read_byte(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]; + if (volts >= 38) actual_color = pgm_read_byte(colors + 4); + else if (volts >= 33) actual_color = pgm_read_byte(colors + 2); + else actual_color = pgm_read_byte(colors + 0); } // ... but during preview, cycle colors quickly else { - actual_color = colors[((arg>>1) % 3) << 1]; + actual_color = pgm_read_byte(colors + (((arg>>1) % 3) << 1)); } } @@ -2322,6 +2324,31 @@ void rgb_led_update(uint8_t mode, uint8_t arg) { break; } } + +void rgb_led_voltage_readout(uint8_t bright) { + uint8_t volts = voltage; + if (volts < 29) { + rgb_led_set(0); + } + else { + uint8_t levels[] = { + 30, 0, + 33, 1, + 35, 2, + 37, 3, + 39, 4, + 40, 5, + 255, 6, + }; + uint8_t i; + for (i = 0; volts > levels[i]; i += 2) { + if (levels[i] >= volts) break; + } + uint8_t color = pgm_read_byte(rgb_led_colors + i); + if (bright) color = color << 1; + rgb_led_set(color); + } +} #endif @@ -2559,6 +2586,10 @@ void loop() { StatePtr state = current_state; + #ifdef USE_AUX_RGB_LEDS_WHILE_RAMPING + rgb_led_voltage_readout(1); + #endif + if (0) {} #ifdef USE_STROBE_STATE -- cgit v1.2.3 From 3f89c8d35619e37fd6d80b75a7574c7802b3556b Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 31 Jul 2019 14:47:19 -0600 Subject: mf01-mini: enable aux LED low mode --- spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h b/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h index 2d1e5c7..e5db4f4 100644 --- a/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h @@ -3,16 +3,16 @@ // the button lights up #define USE_INDICATOR_LED -#define INDICATOR_LED_SKIP_LOW // low mode doesn't work on this driver +//#define INDICATOR_LED_SKIP_LOW // low mode doesn't work on this driver // 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: high (2) +// off mode: low (1) // lockout: blinking (3) -#define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 2) +#define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 1) // don't blink during ramp, it's irrelevant and annoying on this light -- cgit v1.2.3 From a68560963d9dd7a16982bc67d5b5ef100a51c8a6 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 5 Aug 2019 21:34:37 -0600 Subject: fixed weird ramp behavior on D1S v2 (by trusting the compiler more) --- spaghetti-monster/fsm-ramping.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-ramping.h b/spaghetti-monster/fsm-ramping.h index 7233474..24c19c0 100644 --- a/spaghetti-monster/fsm-ramping.h +++ b/spaghetti-monster/fsm-ramping.h @@ -47,7 +47,10 @@ void gradual_tick(); #define PWM_GET(x,y) pgm_read_byte(x+y) #else #define PWM_DATATYPE uint16_t -#define PWM_GET(x,y) pgm_read_word(x+(2*y)) +// pointer plus 2*y bytes +//#define PWM_GET(x,y) pgm_read_word(x+(2*y)) +// nope, the compiler was already doing the math correctly +#define PWM_GET(x,y) pgm_read_word(x+y) #endif // use UI-defined ramp tables if they exist -- cgit v1.2.3 From d8841fd80ae1366b9d9f31ca0bd1971b405ef327 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 5 Aug 2019 21:37:48 -0600 Subject: fixed party strobe on D1S v2, set better default aux LED modes, enabled aux LEDs in blinky modes, fixed user feedback when changing aux LED mode, refactored voltage-to-auxled-color code --- spaghetti-monster/anduril/anduril.c | 70 +++++++++++++++++----------- spaghetti-monster/anduril/cfg-emisar-d1sv2.h | 8 +++- 2 files changed, 49 insertions(+), 29 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index a82ba4b..8625946 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -309,6 +309,7 @@ void blip(); void indicator_blink(uint8_t arg); #endif #if defined(USE_AUX_RGB_LEDS) && defined(TICK_DURING_STANDBY) +uint8_t setting_rgb_mode_now = 0; void rgb_led_update(uint8_t mode, uint8_t arg); void rgb_led_voltage_readout(uint8_t bright); /* @@ -674,6 +675,7 @@ uint8_t off_state(Event event, uint16_t arg) { } // 7 clicks (hold last): change RGB aux LED color else if (event == EV_click7_hold) { + setting_rgb_mode_now = 1; if (0 == (arg & 0x3f)) { uint8_t mode = (rgb_led_off_mode & 0x0f) + 1; mode = mode % RGB_LED_NUM_COLORS; @@ -684,6 +686,7 @@ uint8_t off_state(Event event, uint16_t arg) { return MISCHIEF_MANAGED; } else if (event == EV_click7_hold_release) { + setting_rgb_mode_now = 0; save_config(); return MISCHIEF_MANAGED; } @@ -1245,8 +1248,12 @@ inline void party_tactical_strobe_mode_iter(uint8_t st) { if (0) {} // placeholde0 #ifdef USE_PARTY_STROBE_MODE else if (st == party_strobe_e) { // party strobe + #ifdef PARTY_STROBE_ONTIME + nice_delay_ms(PARTY_STROBE_ONTIME); + #else if (del < 42) delay_zero(); else nice_delay_ms(1); + #endif } #endif #ifdef USE_TACTICAL_STROBE_MODE @@ -1738,6 +1745,7 @@ uint8_t lockout_state(Event event, uint16_t arg) { } // click, click, hold: change RGB aux LED color else if (event == EV_click3_hold) { + setting_rgb_mode_now = 1; if (0 == (arg & 0x3f)) { uint8_t mode = (rgb_led_lockout_mode & 0x0f) + 1; mode = mode % RGB_LED_NUM_COLORS; @@ -1749,6 +1757,7 @@ uint8_t lockout_state(Event event, uint16_t arg) { } // click, click, hold, release: save new color else if (event == EV_click3_hold_release) { + setting_rgb_mode_now = 0; save_config(); return MISCHIEF_MANAGED; } @@ -2260,6 +2269,27 @@ void indicator_blink(uint8_t arg) { #endif #if defined(USE_AUX_RGB_LEDS) && defined(TICK_DURING_STANDBY) +uint8_t voltage_to_rgb() { + uint8_t levels[] = { + // voltage, color + 0, 0, // 0, R + 33, 1, // 1, R+G + 35, 2, // 2, G + // 0, 3, // 3, G+B // skip; looks too similar to R+G+B + 38, 4, // 4, B + 40, 5, // 5, R + B + 42, 6, // 6, R+G+B + 255, 6, // 7, R+G+B + }; + uint8_t volts = voltage; + if (volts < 29) return 0; + + uint8_t i; + for (i = 0; volts >= levels[i]; i += 2) {} + uint8_t color_num = levels[(i - 2) + 1]; + return pgm_read_byte(rgb_led_colors + color_num); +} + // do fancy stuff with the RGB aux LEDs // mode: 0bPPPPCCCC where PPPP is the pattern and CCCC is the color // arg: time slice number @@ -2285,7 +2315,9 @@ void rgb_led_update(uint8_t mode, uint8_t arg) { actual_color = pgm_read_byte(colors + color); } else if (color == 7) { // rainbow - if (0 == (arg & 0x03)) { + uint8_t speed = 0x03; // awake speed + if (go_to_standby) speed = 0x0f; // asleep speed + if (0 == (arg & speed)) { rainbow = (rainbow + 1) % 6; } actual_color = pgm_read_byte(colors + rainbow); @@ -2293,10 +2325,11 @@ void rgb_led_update(uint8_t mode, uint8_t arg) { else { // voltage // show actual voltage while asleep... if (go_to_standby) { + actual_color = voltage_to_rgb(); // choose a color based on battery voltage - if (volts >= 38) actual_color = pgm_read_byte(colors + 4); - else if (volts >= 33) actual_color = pgm_read_byte(colors + 2); - else actual_color = pgm_read_byte(colors + 0); + //if (volts >= 38) actual_color = pgm_read_byte(colors + 4); + //else if (volts >= 33) actual_color = pgm_read_byte(colors + 2); + //else actual_color = pgm_read_byte(colors + 0); } // ... but during preview, cycle colors quickly else { @@ -2326,28 +2359,9 @@ void rgb_led_update(uint8_t mode, uint8_t arg) { } void rgb_led_voltage_readout(uint8_t bright) { - uint8_t volts = voltage; - if (volts < 29) { - rgb_led_set(0); - } - else { - uint8_t levels[] = { - 30, 0, - 33, 1, - 35, 2, - 37, 3, - 39, 4, - 40, 5, - 255, 6, - }; - uint8_t i; - for (i = 0; volts > levels[i]; i += 2) { - if (levels[i] >= volts) break; - } - uint8_t color = pgm_read_byte(rgb_led_colors + i); - if (bright) color = color << 1; - rgb_led_set(color); - } + uint8_t color = voltage_to_rgb(); + if (bright) color = color << 1; + rgb_led_set(color); } #endif @@ -2586,8 +2600,8 @@ void loop() { StatePtr state = current_state; - #ifdef USE_AUX_RGB_LEDS_WHILE_RAMPING - rgb_led_voltage_readout(1); + #ifdef USE_AUX_RGB_LEDS_WHILE_ON + if (! setting_rgb_mode_now) rgb_led_voltage_readout(1); #endif if (0) {} diff --git a/spaghetti-monster/anduril/cfg-emisar-d1sv2.h b/spaghetti-monster/anduril/cfg-emisar-d1sv2.h index 45424b3..d53d938 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d1sv2.h +++ b/spaghetti-monster/anduril/cfg-emisar-d1sv2.h @@ -4,7 +4,10 @@ // this light has three aux LED channels: R, G, B #define USE_AUX_RGB_LEDS -#define USE_AUX_RGB_LEDS_WHILE_RAMPING +#define USE_AUX_RGB_LEDS_WHILE_ON +#define USE_INDICATOR_LED_WHILE_RAMPING +#define RGB_LED_OFF_DEFAULT 0x18 // low, voltage +#define RGB_LED_LOCKOUT_DEFAULT 0x37 // blinking, rainbow // enable blinking aux LEDs #define TICK_DURING_STANDBY @@ -48,4 +51,7 @@ // easier access to thermal config mode, for Emisar #define USE_TENCLICK_THERMAL_CONFIG +// slow down party strobe; this driver can't pulse for 1ms or less +#define PARTY_STROBE_ONTIME 2 + #define THERM_CAL_OFFSET 5 -- cgit v1.2.3 From 2813cc0130eb3bcc9d0dc1fca5135ee6720764c5 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 6 Aug 2019 16:52:11 -0600 Subject: turn off button LED when muggle mode turns off the main LED (to reduce power use in standby) --- spaghetti-monster/anduril/anduril.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 8625946..f8492fc 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -1941,6 +1941,9 @@ uint8_t muggle_state(Event event, uint16_t arg) { // turn off, but don't go to the main "off" state if (muggle_off_mode) { if (arg > TICKS_PER_SECOND*1) { // sleep after 1 second + #ifdef USE_AUX_RGB_LEDS_WHILE_ON + rgb_led_set(0); + #endif go_to_standby = 1; // sleep while light is off } } -- cgit v1.2.3 From 8084f6083ed387b6eb4246758778e99deb781ac9 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 6 Aug 2019 16:52:58 -0600 Subject: measured and adjusted D1S v2 ramp parameters --- spaghetti-monster/anduril/cfg-emisar-d1sv2.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-emisar-d1sv2.h b/spaghetti-monster/anduril/cfg-emisar-d1sv2.h index d53d938..33b240d 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d1sv2.h +++ b/spaghetti-monster/anduril/cfg-emisar-d1sv2.h @@ -18,7 +18,7 @@ // (with max_pwm set to 1023) #define RAMP_LENGTH 150 #define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,6,7,8,9,10,11,12,13,14,15,16,17,18,20,21,23,24,26,27,29,31,32,34,36,38,40,43,45,47,49,52,54,57,60,62,65,68,71,74,77,81,84,87,91,95,98,102,106,110,114,118,122,127,131,136,141,145,150,155,160,166,171,176,182,188,193,199,205,211,218,224,231,237,244,251,258,265,272,280,287,295,303,310,319,327,335,344,352,361,370,379,388,397,407,416,426,436,446,457,467,477,488,499,510,521,533,544,556,568,580,592,604,617,629,642,655,668,682,695,709,723,737,751,766,781,795,810,826,841,857,872,888,904,921,937,954,971,988,1005,1023 -#define MAX_1x7135 65 +#define MAX_1x7135 50 // the entire ramp is regulated; don't blink halfway up #ifdef BLINK_AT_RAMP_MIDDLE @@ -33,10 +33,14 @@ #define RAMP_SMOOTH_FLOOR 1 #define RAMP_SMOOTH_CEIL 130 -#define RAMP_DISCRETE_FLOOR 20 +// 10, 30, [50], 70, 90, 110, 130 +#define RAMP_DISCRETE_FLOOR 10 #define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL #define RAMP_DISCRETE_STEPS 7 +#define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR +#define MUGGLE_CEILING 70 + // 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 -- cgit v1.2.3 From 7d09466da0552c17b9968fa92d8ede534abfbbb6 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 6 Aug 2019 20:17:09 -0600 Subject: un-hardcoded 255 as the highest PWM level, and used a "PWM_TOP" value instead (should make gradual adjustments work better on devices with more than 8 bits of PWM resolution) --- spaghetti-monster/fsm-ramping.c | 4 ++-- spaghetti-monster/fsm-ramping.h | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 52a7246..7bee07e 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -146,13 +146,13 @@ void gradual_tick() { gt --; // convert 1-based number to 0-based - uint8_t target; + PWM_DATATYPE target; #if PWM_CHANNELS >= 1 target = PWM_GET(pwm1_levels, gt); if ((gt < actual_level) // special case for FET-only turbo && (PWM1_LVL == 0) // (bypass adjustment period for first step) - && (target == 255)) PWM1_LVL = 255; + && (target == PWM_TOP)) PWM1_LVL = PWM_TOP; else if (PWM1_LVL < target) PWM1_LVL ++; else if (PWM1_LVL > target) PWM1_LVL --; #endif diff --git a/spaghetti-monster/fsm-ramping.h b/spaghetti-monster/fsm-ramping.h index 24c19c0..c650e21 100644 --- a/spaghetti-monster/fsm-ramping.h +++ b/spaghetti-monster/fsm-ramping.h @@ -41,12 +41,15 @@ void gradual_tick(); // auto-detect the data type for PWM tables #ifndef PWM_BITS #define PWM_BITS 8 +#define PWM_TOP 255 #endif #if PWM_BITS <= 8 #define PWM_DATATYPE uint8_t +#define PWM_TOP 255 #define PWM_GET(x,y) pgm_read_byte(x+y) #else #define PWM_DATATYPE uint16_t +#define PWM_TOP 1023 // 10 bits by default // pointer plus 2*y bytes //#define PWM_GET(x,y) pgm_read_word(x+(2*y)) // nope, the compiler was already doing the math correctly -- cgit v1.2.3 From 64da1475d73d5d021f125209360c024518fc1751 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 26 Aug 2019 16:31:12 -0600 Subject: just cleaning up some comments --- spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h b/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h index e5db4f4..bbf751b 100644 --- a/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h @@ -40,16 +40,10 @@ #define RAMP_SMOOTH_CEIL 130 // ~??? lm // 14/135/6 = 14, 38, 62, 86, [110], 135 // 20/110/7 = 20, 35, 50, [65], 80, 95, [110] -// 15/130/7 = 15, 34, 53, 72, 91, [110], 130 -#if 1 +// 15/130/7 = 15, 34, 53, 72, 91, [110], 130 <-- #define RAMP_DISCRETE_FLOOR 15 // ~?? lm #define RAMP_DISCRETE_CEIL 130 // ~??? lm #define RAMP_DISCRETE_STEPS 7 // ??, ??, ... lm -#else // testing only; for calibrating the ramp in detail -#define RAMP_DISCRETE_FLOOR 1 // ~?? lm -#define RAMP_DISCRETE_CEIL 150 // ~??? lm -#define RAMP_DISCRETE_STEPS 150 // ??, ??, ... lm -#endif #define USE_TENCLICK_THERMAL_CONFIG // by request -- cgit v1.2.3 From 62223a6e1c304d3e5952a0a7138b75dc3c232dfc Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 29 Aug 2019 04:57:54 -0600 Subject: added Emisar D4S V2 support --- spaghetti-monster/anduril/cfg-emisar-d4sv2-219.h | 10 ++++ spaghetti-monster/anduril/cfg-emisar-d4sv2.h | 63 ++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 spaghetti-monster/anduril/cfg-emisar-d4sv2-219.h create mode 100644 spaghetti-monster/anduril/cfg-emisar-d4sv2.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-emisar-d4sv2-219.h b/spaghetti-monster/anduril/cfg-emisar-d4sv2-219.h new file mode 100644 index 0000000..9898246 --- /dev/null +++ b/spaghetti-monster/anduril/cfg-emisar-d4sv2-219.h @@ -0,0 +1,10 @@ +// Emisar D4Sv2-219 config options for Anduril +#include "cfg-emisar-d4sv2.h" +// ATTINY: 1634 + +#undef PWM1_LEVELS +#undef PWM2_LEVELS +#undef PWM3_LEVELS +#define PWM1_LEVELS 1,1,2,2,3,3,4,5,5,6,7,8,9,10,11,12,13,17,18,19,20,21,22,24,26,28,30,33,35,38,41,44,47,50,54,57,61,65,69,74,79,84,89,94,100,106,113,119,126,134,142,150,158,167,176,186,196,207,218,230,242,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,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,12,16,21,25,30,35,41,46,52,58,64,71,77,84,92,99,107,115,124,133,142,151,161,172,182,193,205,217,229,242,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,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 PWM3_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,3,4,6,7,9,10,12,13,15,17,18,20,22,24,26,28,30,33,35,37,40,43,45,48,50,53,56,59,62,65,69,72,76,80,83,87,91,95,99,104,108,113,117,123,127,132,138,143,148,154,160,166,172,178,185,192 diff --git a/spaghetti-monster/anduril/cfg-emisar-d4sv2.h b/spaghetti-monster/anduril/cfg-emisar-d4sv2.h new file mode 100644 index 0000000..acc9101 --- /dev/null +++ b/spaghetti-monster/anduril/cfg-emisar-d4sv2.h @@ -0,0 +1,63 @@ +// Emisar D4S V2 config options for Anduril +#include "hwdef-Emisar_D4Sv2.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 + + +// 1x7135 + 3x7135 + FET +// ../../../bin/level_calc.py seventh 3 150 7135 1 2.3 130 7135 11 5 400.1 FET 2 10 4000 +// (and some manual edits to make the clock speed changes smoother) +#define PWM1_LEVELS 1,1,2,2,3,3,4,5,5,6,7,8,9,10,11,12,13,17,18,19,20,21,22,24,26,28,30,33,35,38,41,44,47,50,54,57,61,65,69,74,79,84,89,94,100,106,113,119,126,134,142,150,158,167,176,186,196,207,218,230,242,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,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,12,16,21,25,30,35,41,46,52,58,64,71,77,84,92,99,107,115,124,133,142,151,161,172,182,193,205,217,229,242,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,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 PWM3_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,3,5,6,8,10,12,14,16,18,20,23,25,27,30,32,35,38,41,44,47,50,53,57,60,64,67,71,75,79,83,87,92,96,101,106,111,116,121,127,132,138,144,150,156,163,169,176,183,190,197,205,213,221,229,237,246,255 +#define MAX_1x7135 62 +#define MAX_Nx7135 93 +#define HALFSPEED_LEVEL 18 +#define QUARTERSPEED_LEVEL 8 + +#define RAMP_SMOOTH_FLOOR 1 +#define RAMP_SMOOTH_CEIL 130 +// 20, 38, 56, 75, [93], 111, 130 +#define RAMP_DISCRETE_FLOOR 20 +#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL +#define RAMP_DISCRETE_STEPS 7 + +#define DEFAULT_LEVEL MAX_Nx7135 +#define STROBE_BRIGHTNESS MAX_LEVEL + +#define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR +#define MUGGLE_CEILING MAX_Nx7135 + +// stop panicking at ~50% power or ~2000 lm +#define THERM_FASTER_LEVEL 130 + +// no need to be extra-careful on this light +#ifdef THERM_HARD_TURBO_DROP +#undef THERM_HARD_TURBO_DROP +#endif + +// respond to thermal changes faster +#define THERMAL_WARNING_SECONDS 3 +#define THERMAL_UPDATE_SPEED 2 +#define THERM_PREDICTION_STRENGTH 4 + +// easier access to thermal config mode, for Emisar +#define USE_TENCLICK_THERMAL_CONFIG + +#ifdef BLINK_AT_RAMP_MIDDLE +#undef BLINK_AT_RAMP_MIDDLE +#endif + +// seems relevant on attiny1634 +#define THERM_CAL_OFFSET 5 -- cgit v1.2.3 From 7851656847738192e0e12cfe77861ba58d98cf6f Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 6 Sep 2019 04:38:00 -0600 Subject: added button LED support to D4v2 (in a way which doesn't break backward compatibility... ... but it really needs some refactoring to reduce code duplication) --- spaghetti-monster/anduril/anduril.c | 33 ++++++++++++++++++++++++----- spaghetti-monster/anduril/cfg-emisar-d4v2.h | 4 ++++ spaghetti-monster/fsm-misc.c | 23 ++++++++++++++++++++ spaghetti-monster/fsm-misc.h | 6 ++++++ spaghetti-monster/fsm-ramping.c | 3 +++ 5 files changed, 64 insertions(+), 5 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 8ab66f5..5032dcd 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -2257,7 +2257,13 @@ void rgb_led_update(uint8_t mode, uint8_t arg) { // 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; } + if ((volts) && (volts < VOLTAGE_LOW)) { + rgb_led_set(0); + #ifdef USE_BUTTON_LED + button_led_set(0); + #endif + return; + } uint8_t pattern = (mode>>4); // off, low, high, blinking, ... more? uint8_t color = mode & 0x0f; @@ -2307,17 +2313,34 @@ void rgb_led_update(uint8_t mode, uint8_t arg) { frame = (frame + 1) % sizeof(animation); pattern = animation[frame]; } + uint8_t result; + #ifdef USE_BUTTON_LED + uint8_t button_led_result; + #endif switch (pattern) { case 0: // off - rgb_led_set(0); + result = 0; + #ifdef USE_BUTTON_LED + button_led_result = 0; + #endif break; case 1: // low - rgb_led_set(actual_color); + result = actual_color; + #ifdef USE_BUTTON_LED + button_led_result = 1; + #endif break; - case 2: // high - rgb_led_set(actual_color << 1); + default: // high + result = (actual_color << 1); + #ifdef USE_BUTTON_LED + button_led_result = 2; + #endif break; } + rgb_led_set(result); + #ifdef USE_BUTTON_LED + button_led_set(button_led_result); + #endif } #endif diff --git a/spaghetti-monster/anduril/cfg-emisar-d4v2.h b/spaghetti-monster/anduril/cfg-emisar-d4v2.h index b83c65c..d0d2cf6 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4v2.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4v2.h @@ -4,7 +4,11 @@ // this light has three aux LED channels: R, G, B #define USE_AUX_RGB_LEDS +// it also has an independent LED in the button +#define USE_BUTTON_LED // the aux LEDs are front-facing, so turn them off while main LEDs are on +// TODO: the whole "indicator LED" thing needs to be refactored into +// "aux LED(s)" and "button LED(s)" since they work a bit differently #ifdef USE_INDICATOR_LED_WHILE_RAMPING #undef USE_INDICATOR_LED_WHILE_RAMPING #endif diff --git a/spaghetti-monster/fsm-misc.c b/spaghetti-monster/fsm-misc.c index 8e88cbd..18dc7c5 100644 --- a/spaghetti-monster/fsm-misc.c +++ b/spaghetti-monster/fsm-misc.c @@ -147,6 +147,29 @@ void indicator_led_auto() { */ #endif // USE_INDICATOR_LED +#ifdef USE_BUTTON_LED +// TODO: Refactor this and RGB LED function to merge code and save space +void button_led_set(uint8_t lvl) { + switch (lvl) { + case 0: // LED off + BUTTON_LED_DDR &= 0xff ^ (1 << BUTTON_LED_PIN); + BUTTON_LED_PUE &= 0xff ^ (1 << BUTTON_LED_PIN); + BUTTON_LED_PORT &= 0xff ^ (1 << BUTTON_LED_PIN); + break; + case 1: // LED low + BUTTON_LED_DDR &= 0xff ^ (1 << BUTTON_LED_PIN); + BUTTON_LED_PUE |= (1 << BUTTON_LED_PIN); + BUTTON_LED_PORT |= (1 << BUTTON_LED_PIN); + break; + default: // LED high + BUTTON_LED_DDR |= (1 << BUTTON_LED_PIN); + BUTTON_LED_PUE |= (1 << BUTTON_LED_PIN); + BUTTON_LED_PORT |= (1 << BUTTON_LED_PIN); + break; + } +} +#endif + #ifdef USE_AUX_RGB_LEDS void rgb_led_set(uint8_t value) { // value: 0b00BBGGRR diff --git a/spaghetti-monster/fsm-misc.h b/spaghetti-monster/fsm-misc.h index a39d31a..66d31ba 100644 --- a/spaghetti-monster/fsm-misc.h +++ b/spaghetti-monster/fsm-misc.h @@ -43,10 +43,16 @@ uint8_t blink(uint8_t num, uint8_t speed); */ #ifdef USE_INDICATOR_LED +// FIXME: Remove this, replace with button_led() // lvl: 0=off, 1=low, 2=high void indicator_led(uint8_t lvl); #endif +#ifdef USE_BUTTON_LED +// lvl: 0=off, 1=low, 2=high +void button_led_set(uint8_t lvl); +#endif + #ifdef USE_AUX_RGB_LEDS // value: 0b00BBGGRR // each pair of bits: 0=off, 1=low, 2=high diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index efa07e4..37c8073 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -46,6 +46,9 @@ void set_level(uint8_t level) { #endif #ifdef USE_AUX_RGB_LEDS rgb_led_set(0); + #ifdef USE_BUTTON_LED + button_led_set((level > 0) + (level > MAX_1x7135)); + #endif #endif } #endif -- cgit v1.2.3 From f1ff71108531137d4a94b913175084781987199d Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 7 Sep 2019 00:30:39 -0600 Subject: slowed down rainbow RGB mode, added a ramp-down on stuck-button for safety purposes --- spaghetti-monster/anduril/anduril.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 5032dcd..e8524a8 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -792,6 +792,10 @@ uint8_t steady_state(Event event, uint16_t arg) { // (off->hold->stepped_min->release causes this state) else if (actual_level <= mode_min) { ramp_direction = 1; } } + // if the button is stuck, err on the side of safety and ramp down + else if ((arg > TICKS_PER_SECOND * 5) && (actual_level >= mode_max)) { + ramp_direction = -1; + } memorized_level = nearest_level((int16_t)actual_level \ + (ramp_step_size * ramp_direction)); #else @@ -2286,7 +2290,9 @@ void rgb_led_update(uint8_t mode, uint8_t arg) { actual_color = colors[color]; } else if (color == 7) { // rainbow - if (0 == (arg & 0x03)) { + uint8_t speed = 0x03; // awake speed + if (go_to_standby) speed = 0x0f; // asleep speed + if (0 == (arg & speed)) { rainbow = (rainbow + 1) % 6; } actual_color = colors[rainbow]; -- cgit v1.2.3 From 2fcf49ed1f04d560ae2f422aa85e626147089171 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 15 Sep 2019 15:37:12 -0600 Subject: added some ideas for stuff to do, updated the UI diagram to show the stepped ramp mode differently --- spaghetti-monster/anduril/anduril-ui.png | Bin 286759 -> 281904 bytes spaghetti-monster/anduril/anduril.svg | 238 ++++++++++++++++++++++++------- spaghetti-monster/anduril/anduril.txt | 6 + 3 files changed, 195 insertions(+), 49 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril-ui.png b/spaghetti-monster/anduril/anduril-ui.png index 3c032bc..70f6be0 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 36840a4..d58e478 100644 --- a/spaghetti-monster/anduril/anduril.svg +++ b/spaghetti-monster/anduril/anduril.svg @@ -22,6 +22,49 @@ inkscape:export-ydpi="109.75774"> + + + + + + + + + @@ -57,7 +100,7 @@ @@ -1896,16 +1939,6 @@ style="fill-rule:evenodd;stroke:#000000;stroke-width:0.42666668pt" inkscape:connector-curvature="0" /> - + + + + + + + + inkscape:snap-bbox-midpoints="true" + inkscape:snap-midpoints="true" + inkscape:snap-object-midpoints="true" + inkscape:object-paths="true" + inkscape:snap-intersection-paths="true"> + + + - Ceil Floor @@ -3245,22 +3354,16 @@ - 6 Clicks + transform="translate(-191.75097,7.3367765)"> + transform="translate(-281.95292,43.516866)"> @@ -4289,7 +4392,7 @@ sodipodi:nodetypes="cc" /> @@ -4639,11 +4742,11 @@ 3C 3C @@ -4799,5 +4902,42 @@ x="1091.5458" y="1212.6874" id="tspan43995-1">Factory Reset: Loosen tailcap, Hold button, Tighten tailcap, Hold 3s (or 13H from Off) + 3C + + + + + + diff --git a/spaghetti-monster/anduril/anduril.txt b/spaghetti-monster/anduril/anduril.txt index db73cdb..0a3dc4c 100644 --- a/spaghetti-monster/anduril/anduril.txt +++ b/spaghetti-monster/anduril/anduril.txt @@ -162,6 +162,12 @@ Indicator LED / aux LED support: TODO: + - change 6C to 6H for exiting muggle mode? + - move muggle mode from 6C to ... 8C or something? + - add 4H from lockout to turn light on and start ramping up? + - move config modes to 5C instead of 4C, and move manual memory to 4C? + - remove beacon config mode, and use a hold to set timing instead? + - rewrite muggle mode to split it into on and off states * save settings in eeprom * decide on "hold until hot" or "click N times" for thermal config mode * test thermal regulation on an actual light -- cgit v1.2.3 From dc8ec8b1817591e929555dcf6ae7302bbec758e8 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 24 Sep 2019 00:00:39 -0600 Subject: made the maximum number of clicks 15 instead of 14 --- spaghetti-monster/fsm-events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index 362a5cc..f35607d 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -42,7 +42,7 @@ uint8_t push_event(uint8_t ev_type) { // set press flag current_event |= B_PRESS; // increase click counter - if ((current_event & B_COUNT) < (B_COUNT-1)) { + if ((current_event & B_COUNT) < (B_COUNT)) { current_event ++; } return 1; // event pushed, even if max clicks already reached -- cgit v1.2.3 From 4948fc7cfb09d5d9bf7f899917f5aa7d274f1a1a Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 24 Sep 2019 00:01:31 -0600 Subject: sped up blink_digit() a little bit, because it was annoyingly slow --- spaghetti-monster/fsm-misc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-misc.c b/spaghetti-monster/fsm-misc.c index 8e88cbd..0a3cdca 100644 --- a/spaghetti-monster/fsm-misc.c +++ b/spaghetti-monster/fsm-misc.c @@ -41,20 +41,21 @@ void auto_clock_speed() { #endif #if defined(USE_BLINK_NUM) || defined(USE_BLINK_DIGIT) +#define BLINK_SPEED 1000 uint8_t blink_digit(uint8_t num) { //StatePtr old_state = current_state; // "zero" digit gets a single short blink - uint8_t ontime = 200; + uint8_t ontime = BLINK_SPEED * 2 / 10; if (!num) { ontime = 8; num ++; } for (; num>0; num--) { set_level(BLINK_BRIGHTNESS); nice_delay_ms(ontime); set_level(0); - nice_delay_ms(400); + nice_delay_ms(BLINK_SPEED * 3 / 10); } - return nice_delay_ms(600); + return nice_delay_ms(BLINK_SPEED * 5 / 10); } #endif -- cgit v1.2.3 From e2b727acfce7bc19843cdcc7f327efc9c61230d8 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 24 Sep 2019 00:32:53 -0600 Subject: added a version check function on 15+ clicks from off, added a safety ramp-down if button is held too long at ceiling (also removed muggle mode from a couple build targets because it doesn't fit, not enough ROM) --- spaghetti-monster/anduril/anduril.c | 38 ++++++++++++++++++++++ spaghetti-monster/anduril/build-all.sh | 2 ++ spaghetti-monster/anduril/cfg-emisar-d18.h | 6 ++++ .../anduril/cfg-mateminco-mf01-mini.h | 6 ++++ 4 files changed, 52 insertions(+) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 8ab66f5..1505f59 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -35,6 +35,8 @@ // (currently incompatible with factory reset) //#define START_AT_MEMORIZED_LEVEL +// include a function to blink out the firmware version +#define USE_VERSION_CHECK // short blip when crossing from "click" to "hold" from off // (helps the user hit moon mode exactly, instead of holding too long @@ -483,6 +485,11 @@ uint8_t triangle_wave(uint8_t phase); volatile uint8_t beacon_seconds = 2; #endif +#ifdef USE_VERSION_CHECK +#include "version.h" +const PROGMEM uint8_t version_number[] = VERSION_NUMBER; +uint8_t version_check_state(Event event, uint16_t arg); +#endif uint8_t off_state(Event event, uint16_t arg) { // turn emitter off when entering state @@ -682,6 +689,13 @@ uint8_t off_state(Event event, uint16_t arg) { return MISCHIEF_MANAGED; } #endif + #ifdef USE_VERSION_CHECK + // 15+ clicks: show the version number + else if (event == EV_15clicks) { + set_state(version_check_state, 0); + 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) { @@ -792,6 +806,10 @@ uint8_t steady_state(Event event, uint16_t arg) { // (off->hold->stepped_min->release causes this state) else if (actual_level <= mode_min) { ramp_direction = 1; } } + // if the button is stuck, err on the side of safety and ramp down + else if ((arg > TICKS_PER_SECOND * 5) && (actual_level >= mode_max)) { + ramp_direction = -1; + } memorized_level = nearest_level((int16_t)actual_level \ + (ramp_step_size * ramp_direction)); #else @@ -1956,6 +1974,13 @@ uint8_t muggle_state(Event event, uint16_t arg) { #endif +#ifdef USE_VERSION_CHECK +uint8_t version_check_state(Event event, uint16_t arg) { + return EVENT_NOT_HANDLED; +} +#endif + + // ask the user for a sequence of numbers, then save them and return to caller uint8_t config_state_base(Event event, uint16_t arg, uint8_t num_config_steps, @@ -2558,6 +2583,19 @@ void loop() { if (0) {} + #ifdef USE_VERSION_CHECK + else if (state == version_check_state) { + for (uint8_t i=0; i version.h + for TARGET in cfg-*.h ; do NAME=$(echo "$TARGET" | perl -ne '/cfg-(.*).h/ && print "$1\n";') echo "===== $NAME =====" diff --git a/spaghetti-monster/anduril/cfg-emisar-d18.h b/spaghetti-monster/anduril/cfg-emisar-d18.h index 16fbacd..02e8f01 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d18.h +++ b/spaghetti-monster/anduril/cfg-emisar-d18.h @@ -16,6 +16,12 @@ #define USE_TENCLICK_THERMAL_CONFIG +// save space, and remove a mode which doesn't make much sense on this light +#ifdef USE_MUGGLE_MODE +#undef USE_MUGGLE_MODE +#endif + + // level_calc.py seventh 3 150 7135 1 1.4 117.99 7135 6 1 1706.86 FET 3 10 13000 // (designed to make 1x hit at level 50, and Nx hit at level 100) #define RAMP_LENGTH 150 diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h b/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h index bbf751b..a1d366d 100644 --- a/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h @@ -15,6 +15,12 @@ #define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 1) +// doesn't quite fit +#ifdef USE_MUGGLE_MODE +#undef USE_MUGGLE_MODE +#endif + + // don't blink during ramp, it's irrelevant and annoying on this light #define BLINK_AT_RAMP_CEILING #undef BLINK_AT_RAMP_MIDDLE -- cgit v1.2.3 From 0df827391ced9bb0b7114248c78b696de4676b25 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 28 Sep 2019 23:14:16 -0600 Subject: remapped D1S V2 pins to match new driver (and changed a bit about how ADC / DIDR definitions work, since this now uses DIDR1 instead of DIDR0) --- spaghetti-monster/fsm-adc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 6832e32..a5507a9 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -69,10 +69,10 @@ inline void ADC_on() set_admux_voltage(); #ifdef USE_VOLTAGE_DIVIDER // disable digital input on divider pin to reduce power consumption - DIDR0 |= (1 << VOLTAGE_ADC_DIDR); + VOLTAGE_ADC_DIDR |= (1 << VOLTAGE_ADC); #else // disable digital input on VCC pin to reduce power consumption - //DIDR0 |= (1 << ADC_DIDR); // FIXME: unsure how to handle for VCC pin + //VOLTAGE_ADC_DIDR |= (1 << VOLTAGE_ADC); // FIXME: unsure how to handle for VCC pin #endif #if (ATTINY == 1634) ACSRA |= (1 << ACD); // turn off analog comparator to save power -- cgit v1.2.3 From a86db913783008a14996415e09183a1097ab5389 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 28 Sep 2019 23:25:54 -0600 Subject: after safety ramp-down, if the button remains stuck, lock the light --- spaghetti-monster/anduril/anduril.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 1505f59..48f4ac1 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -810,6 +810,11 @@ uint8_t steady_state(Event event, uint16_t arg) { else if ((arg > TICKS_PER_SECOND * 5) && (actual_level >= mode_max)) { ramp_direction = -1; } + // if the button is still stuck, lock the light + else if ((arg > TICKS_PER_SECOND * 10) && (actual_level <= mode_min)) { + blip(); + set_state(lockout_state, 0); + } memorized_level = nearest_level((int16_t)actual_level \ + (ramp_step_size * ramp_direction)); #else @@ -2589,10 +2594,13 @@ void loop() { blink_digit(pgm_read_byte(version_number + i) - '0'); nice_delay_ms(300); } - set_state(off_state, 0); // FIXME: when user interrupts with button, "off" takes an extra click // before it'll turn back on, because the click to cancel gets sent // to the "off" state instead of version_check_state + //while (button_is_pressed()) {} + //empty_event_sequence(); + + set_state(off_state, 0); } #endif // #ifdef USE_VERSION_CHECK -- cgit v1.2.3 From 06d75ac58143cf3dccd981975f20d589895de5b3 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 2 Oct 2019 00:02:27 -0600 Subject: added a default version.h for people who don't use the build script --- spaghetti-monster/anduril/version.h | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 spaghetti-monster/anduril/version.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/version.h b/spaghetti-monster/anduril/version.h new file mode 100644 index 0000000..8cf3c90 --- /dev/null +++ b/spaghetti-monster/anduril/version.h @@ -0,0 +1,4 @@ +// this file is replaced automatically by the build script +// set your own date here if you're not using the build script +// otherwise, default to first human contact with the moon +#define VERSION_NUMBER "19690720" -- cgit v1.2.3 From fcc0cf099618c57e5a0635d35111bf75e1a2164e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 2 Oct 2019 18:22:52 -0600 Subject: made lantern's muggle mode brighter (matches default stepped ramp level 4 of 5) and made the floor slightly lower (almost as low as level 1 of 5) because this light doesn't run hot enough for the previous limit to make sense (was roughly step 2.9 of 5) --- spaghetti-monster/anduril/cfg-blf-lantern.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-blf-lantern.h b/spaghetti-monster/anduril/cfg-blf-lantern.h index 9467397..bf183eb 100644 --- a/spaghetti-monster/anduril/cfg-blf-lantern.h +++ b/spaghetti-monster/anduril/cfg-blf-lantern.h @@ -51,6 +51,9 @@ #define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL #define RAMP_DISCRETE_STEPS 5 +#define MUGGLE_FLOOR 15 // about 20 lm +#define MUGGLE_CEILING 115 // about 350 lm + // the sensor (attiny85) is nowhere near the emitters // so thermal regulation can't work #ifdef USE_THERMAL_REGULATION -- cgit v1.2.3 From 3fbd6973fcaa805e4ac1cae4d56a8c84985caf89 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 13 Nov 2019 18:33:23 -0700 Subject: fixed some compile issues related to delay_4ms() --- spaghetti-monster/darkhorse/darkhorse.c | 1 - spaghetti-monster/fsm-events.c | 2 ++ spaghetti-monster/meteor/meteor.c | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/darkhorse/darkhorse.c b/spaghetti-monster/darkhorse/darkhorse.c index e613f55..4058c2f 100644 --- a/spaghetti-monster/darkhorse/darkhorse.c +++ b/spaghetti-monster/darkhorse/darkhorse.c @@ -21,7 +21,6 @@ #define USE_LVP #define USE_THERMAL_REGULATION #define DEFAULT_THERM_CEIL 45 -#define USE_DELAY_4MS #define USE_RAMPING #define RAMP_LENGTH 150 #define USE_BATTCHECK diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index f35607d..3e9a12d 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -20,6 +20,8 @@ #ifndef FSM_EVENTS_C #define FSM_EVENTS_C +#include + void empty_event_sequence() { current_event = EV_none; diff --git a/spaghetti-monster/meteor/meteor.c b/spaghetti-monster/meteor/meteor.c index 5e925e2..7d854a1 100644 --- a/spaghetti-monster/meteor/meteor.c +++ b/spaghetti-monster/meteor/meteor.c @@ -22,7 +22,6 @@ #define USE_LVP #define USE_THERMAL_REGULATION #define DEFAULT_THERM_CEIL 45 -#define USE_DELAY_4MS #define USE_RAMPING #define RAMP_LENGTH 150 #define USE_BATTCHECK -- cgit v1.2.3 From 8b59e880614455bd7bc7d8595de847dd6fe9b5b2 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 14 Nov 2019 01:52:50 -0700 Subject: refactored how interrupts work... set a flag and return immediately, then handle the actual logic later during a less-critical code path Enables smarter responses to standby wakeups. Seems to fix missed button presses during standby, and most of the too-fast sleep ticks. Also eliminated waits from button state measurement, so it can happen easier during standby. (also eliminates the chance of an infinite loop on extra-noisy hardware) Also might improve timing-sensitive interrupts like attiny85 PWM channel 4, or a PWM-DSM hybrid technique I'd like to try. BUT this change also appears to break the thermal sensor, so that needs to be fixed. --- spaghetti-monster/fsm-adc.c | 45 ++++++++++++++++++++++++++++++++--------- spaghetti-monster/fsm-adc.h | 8 +++++++- spaghetti-monster/fsm-events.c | 3 +++ spaghetti-monster/fsm-main.c | 21 +++++++++++++++++++ spaghetti-monster/fsm-main.h | 2 ++ spaghetti-monster/fsm-pcint.c | 21 +++++++------------ spaghetti-monster/fsm-pcint.h | 1 + spaghetti-monster/fsm-standby.c | 19 +++++++++++++---- spaghetti-monster/fsm-wdt.c | 22 +++++++++++++------- spaghetti-monster/fsm-wdt.h | 4 ++-- 10 files changed, 108 insertions(+), 38 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 6832e32..1fc5472 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -113,15 +113,44 @@ static inline uint8_t calc_voltage_divider(uint16_t value) { #else #define ADC_CYCLES_PER_SECOND 8 #endif -// TODO: is this better done in main() or WDT()? + +// save the measurement result, set a flag to show something happened, +// and count how many times we've triggered since last counter reset ISR(ADC_vect) { - // For some reason, the ADC interrupt is getting called a *lot* - // more often than it should be, like it's auto-triggering after each - // measurement, but I don't know why, or how to turn that off... - // So, skip every call except when explicitly requested. + #if 0 // the fancy method is probably not even needed + // count up but wrap around from 255 to 128; not 255 to 0 + // TODO: find a way to do this faster if possible + uint8_t val = irq_adc; // cache volatile value + irq_adc = (val + 1) | (val & 0b10000000); + #else + irq_adc ++; + #endif + adc_value = ADC; // save this for later use +} + +void ADC_inner() { + // ignore the first measurement; the docs say it's junk + if (irq_adc < 2) { + ADC_start_measurement(); // start a second measurement + return; + } + + // the ADC triggers repeatedly when it's on, but we only want one value + // (so ignore everything after the first value, until it's manually reset) if (! adcint_enable) return; + + // if we're actually runnning, reset the status flags / counters + irq_adc = 0; adcint_enable = 0; + #ifdef TICK_DURING_STANDBY + // in sleep mode, turn off after just one measurement + // (having the ADC on raises standby power by about 250 uA) + // (and the usual standby level is only ~20 uA) + if (go_to_standby) ADC_off(); + #endif + + // what is being measured? 0/1 = battery voltage, 2/3 = temperature static uint8_t adc_step = 0; // LVP declarations @@ -155,7 +184,7 @@ ISR(ADC_vect) { #define ADC_STEPS 2 #endif - uint16_t measurement = ADC; // latest 10-bit ADC reading + uint16_t measurement = adc_value; // latest 10-bit ADC reading #ifdef USE_PSEUDO_RAND // real-world entropy makes this a true random, not pseudo @@ -376,10 +405,6 @@ ISR(ADC_vect) { #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 274fb4d..acb3da6 100644 --- a/spaghetti-monster/fsm-adc.h +++ b/spaghetti-monster/fsm-adc.h @@ -38,9 +38,15 @@ #define VOLTAGE_FUDGE_FACTOR 5 #endif #endif + +volatile uint8_t irq_adc = 0; // ADC interrupt happened? +uint16_t adc_value; // last ADC measurement +uint8_t adcint_enable = 0; // is the current ADC result needed? +void ADC_inner(); // do the actual ADC-related calculations + 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 void battcheck(); #ifdef BATTCHECK_VpT diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index 3e9a12d..e125e84 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -145,6 +145,9 @@ uint8_t nice_delay_ms(uint16_t ms) { _delay_loop_2(BOGOMIPS*98/100); #endif // ifdef USE_DYNAMIC_UNDERCLOCKING + // run pending system processes while we wait + handle_deferred_interrupts(); + if ((nice_delay_interrupt) || (old_state != current_state)) { return 0; // state changed; abort } diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index e537a9e..a898f41 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -160,6 +160,9 @@ int main() { standby_mode(); } + // catch up on interrupts + handle_deferred_interrupts(); + // give the recipe some time slices loop(); @@ -168,4 +171,22 @@ int main() { } } + +void handle_deferred_interrupts() { + /* + if (irq_pcint) { // button pressed or released + // nothing to do here + // (PCINT only matters during standby) + } + */ + if (irq_adc) { // ADC done measuring + ADC_inner(); + // irq_adc = 0; // takes care of itself + } + if (irq_wdt) { // the clock ticked + WDT_inner(); + // irq_wdt = 0; // takes care of itself + } +} + #endif diff --git a/spaghetti-monster/fsm-main.h b/spaghetti-monster/fsm-main.h index cc469d7..55ae2ff 100644 --- a/spaghetti-monster/fsm-main.h +++ b/spaghetti-monster/fsm-main.h @@ -21,5 +21,7 @@ #define FSM_MAIN_H int main(); +// needs to run frequently to execute the logic for WDT and ADC and stuff +void handle_deferred_interrupts(); #endif diff --git a/spaghetti-monster/fsm-pcint.c b/spaghetti-monster/fsm-pcint.c index 4928980..a4a496a 100644 --- a/spaghetti-monster/fsm-pcint.c +++ b/spaghetti-monster/fsm-pcint.c @@ -24,19 +24,9 @@ #include uint8_t button_is_pressed() { - // remember the past 32 measurements - static uint32_t readings = 0; - // take at least one new measurement, - // and wait for measurements to settle to all zeroes or all ones - do { - // shift past readings and add current value - readings = (readings << 1) | ((SWITCH_PORT & (1<> 2; + + #ifdef USE_VOLTAGE_DIVIDER + voltage = calc_voltage_divider(total); + #else + voltage = (uint16_t)(1.1*1024*10)/total + VOLTAGE_FUDGE_FACTOR; + #endif + } + #else // no USE_LVP_AVG + #ifdef USE_VOLTAGE_DIVIDER + voltage = calc_voltage_divider(measurement); + #else + // calculate actual voltage: volts * 10 + // ADC = 1.1 * 1024 / volts + // volts = 1.1 * 1024 / ADC + //voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; + voltage = ((uint16_t)(2*1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR) >> 1; + #endif #endif + // if low, callback EV_voltage_low / EV_voltage_critical + // (but only if it has been more than N ticks since last call) + if (lvp_timer) { + lvp_timer --; + } else { // it has been long enough since the last warning + if (voltage < VOLTAGE_LOW) { + if (lvp_lowpass < LVP_LOWPASS_STRENGTH) { + lvp_lowpass ++; + } else { + // try to send out a warning + //uint8_t err = emit(EV_voltage_low, 0); + //uint8_t err = emit_now(EV_voltage_low, 0); + emit(EV_voltage_low, 0); + //if (!err) { + // on successful warning, reset counters + lvp_timer = LVP_TIMER_START; + lvp_lowpass = 0; + //} + } + } else { + // voltage not low? reset count + lvp_lowpass = 0; + } + } +} +#endif + +#ifdef USE_THERMAL_REGULATION +static inline void ADC_temperature_handler() { // 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 static int16_t temperature_history[NUM_THERMAL_VALUES_HISTORY]; static uint8_t temperature_timer = 0; @@ -180,232 +292,132 @@ void ADC_inner() { #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 - #define ADC_STEPS 2 - #endif uint16_t measurement = adc_value; // latest 10-bit ADC reading - #ifdef USE_PSEUDO_RAND - // real-world entropy makes this a true random, not pseudo - 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 - // voltage - if (adc_step == 1) { - #ifdef USE_LVP_AVG - // prime on first execution - if (voltage == 0) { - for(uint8_t i=0; i> 2; - - #ifdef USE_VOLTAGE_DIVIDER - voltage = calc_voltage_divider(total); - #else - voltage = (uint16_t)(1.1*1024*10)/total + VOLTAGE_FUDGE_FACTOR; - #endif - } - #else // no USE_LVP_AVG - #ifdef USE_VOLTAGE_DIVIDER - voltage = calc_voltage_divider(measurement); - #else - // calculate actual voltage: volts * 10 - // ADC = 1.1 * 1024 / volts - // volts = 1.1 * 1024 / ADC - //voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; - voltage = ((uint16_t)(2*1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR) >> 1; - #endif - #endif - // if low, callback EV_voltage_low / EV_voltage_critical - // (but only if it has been more than N ticks since last call) - if (lvp_timer) { - lvp_timer --; - } else { // it has been long enough since the last warning - if (voltage < VOLTAGE_LOW) { - if (lvp_lowpass < LVP_LOWPASS_STRENGTH) { - lvp_lowpass ++; - } else { - // try to send out a warning - //uint8_t err = emit(EV_voltage_low, 0); - //uint8_t err = emit_now(EV_voltage_low, 0); - emit(EV_voltage_low, 0); - //if (!err) { - // on successful warning, reset counters - lvp_timer = LVP_TIMER_START; - lvp_lowpass = 0; - //} - } - } else { - // voltage not low? reset count - lvp_lowpass = 0; - } + // Convert ADC units to Celsius (ish) + int16_t temp = measurement - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; + + // prime on first execution + if (reset_thermal_history) { + reset_thermal_history = 0; + temperature = temp; + for(uint8_t i=0; i temperature) { + temperature ++; + } else if (temp < temperature) { + temperature --; } } - #endif // ifdef USE_LVP + // guess what the temperature will be in a few seconds + int16_t pt; + { + int16_t diff; + int16_t t = temperature; - #ifdef USE_THERMAL_REGULATION - // temperature - else if (adc_step == 3) { - // Convert ADC units to Celsius (ish) - int16_t temp = measurement - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; - - // prime on first execution - if (reset_thermal_history) { - reset_thermal_history = 0; - temperature = temp; - for(uint8_t i=0; i temperature) { - temperature ++; - } else if (temp < temperature) { - temperature --; + // algorithm tweaking; not really intended to be modified + // how far ahead should we predict? + #ifndef THERM_PREDICTION_STRENGTH + #define THERM_PREDICTION_STRENGTH 4 + #endif + // how proportional should the adjustments be? (not used yet) + #ifndef THERM_RESPONSE_MAGNITUDE + #define THERM_RESPONSE_MAGNITUDE 128 + #endif + // acceptable temperature window size in C + #define THERM_WINDOW_SIZE 5 + // highest temperature allowed + #define THERM_CEIL ((int16_t)therm_ceil) + // bottom of target temperature window + #define THERM_FLOOR (THERM_CEIL - THERM_WINDOW_SIZE) + + // if it's time to rotate the thermal history, do it + history_step ++; + #if (THERMAL_UPDATE_SPEED == 4) // new value every 4s + #define THERM_HISTORY_STEP_MAX 15 + #elif (THERMAL_UPDATE_SPEED == 2) // new value every 2s + #define THERM_HISTORY_STEP_MAX 7 + #elif (THERMAL_UPDATE_SPEED == 1) // new value every 1s + #define THERM_HISTORY_STEP_MAX 3 + #elif (THERMAL_UPDATE_SPEED == 0) // new value every 0.5s + #define THERM_HISTORY_STEP_MAX 1 + #endif + if (0 == (history_step & THERM_HISTORY_STEP_MAX)) { + // rotate measurements and add a new one + for (uint8_t 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< 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 - } - if (pt < THERM_CEIL) { - overheat_lowpass = 0; // we're probably not too hot - } + // cancel counters if appropriate + if (pt > THERM_FLOOR) { + underheat_lowpass = 0; // we're probably not too cold + } + if (pt < THERM_CEIL) { + overheat_lowpass = 0; // we're probably not too hot + } - if (temperature_timer) { - temperature_timer --; - } else { // it has been long enough since the last warning - - // Too hot? - if (pt > THERM_CEIL) { - if (overheat_lowpass < OVERHEAT_LOWPASS_STRENGTH) { - overheat_lowpass ++; - } else { - // reset counters - 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); - } + if (temperature_timer) { + temperature_timer --; + } else { // it has been long enough since the last warning + + // Too hot? + if (pt > THERM_CEIL) { + if (overheat_lowpass < OVERHEAT_LOWPASS_STRENGTH) { + overheat_lowpass ++; + } else { + // reset counters + 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); } + } - // Too cold? - else if (pt < THERM_FLOOR) { - if (underheat_lowpass < UNDERHEAT_LOWPASS_STRENGTH) { - underheat_lowpass ++; - } else { - // reset counters - 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) - if (voltage > VOLTAGE_LOW) - emit(EV_temperature_low, howmuch); - } + // Too cold? + else if (pt < THERM_FLOOR) { + if (underheat_lowpass < UNDERHEAT_LOWPASS_STRENGTH) { + underheat_lowpass ++; + } else { + // reset counters + 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) + if (voltage > VOLTAGE_LOW) + emit(EV_temperature_low, howmuch); } } } - #endif // ifdef USE_THERMAL_REGULATION - - - // set the correct type of measurement for next time - #ifdef USE_THERMAL_REGULATION - #ifdef USE_LVP - if (adc_step < 2) set_admux_voltage(); - else set_admux_therm(); - #else - set_admux_therm(); - #endif - #else - #ifdef USE_LVP - set_admux_voltage(); - #endif - #endif - } +#endif + #ifdef USE_BATTCHECK #ifdef BATTCHECK_4bars diff --git a/spaghetti-monster/fsm-adc.h b/spaghetti-monster/fsm-adc.h index acb3da6..5f4d0c8 100644 --- a/spaghetti-monster/fsm-adc.h +++ b/spaghetti-monster/fsm-adc.h @@ -44,6 +44,7 @@ uint16_t adc_value; // last ADC measurement uint8_t adcint_enable = 0; // is the current ADC result needed? void ADC_inner(); // do the actual ADC-related calculations +static inline void ADC_voltage_handler(); volatile uint8_t voltage = 0; void low_voltage(); @@ -56,7 +57,7 @@ void battcheck(); #define USE_BLINK_DIGIT #endif #endif -#endif +#endif // ifdef USE_LVP #ifdef USE_THERMAL_REGULATION @@ -85,7 +86,8 @@ int8_t therm_cal_offset = 0; //void low_temperature(); //void high_temperature(); volatile uint8_t reset_thermal_history = 1; -#endif +static inline void ADC_temperature_handler(); +#endif // ifdef USE_THERMAL_REGULATION inline void ADC_on(); -- cgit v1.2.3 From ae082e6331d75c2cbe339290fbce4e79c2aa2ede Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 14 Nov 2019 18:00:54 -0700 Subject: fixed ADC code; measures and behaves correctly now, and is easier to read... ... but factory reset's auto-calibrate still doesn't get the right values for some reason (manual calibration works, but not auto) --- spaghetti-monster/fsm-adc.c | 76 ++++++++++++++++++++++----------------------- spaghetti-monster/fsm-adc.h | 4 ++- spaghetti-monster/fsm-wdt.c | 2 +- 3 files changed, 41 insertions(+), 41 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index ddf4c65..d447189 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -30,6 +30,7 @@ inline void set_admux_therm() { #else #error Unrecognized MCU type #endif + adc_channel = 1; } inline void set_admux_voltage() { @@ -52,6 +53,7 @@ inline void set_admux_voltage() { #else #error Unrecognized MCU type #endif + adc_channel = 0; } inline void ADC_start_measurement() { @@ -115,38 +117,37 @@ static inline uint8_t calc_voltage_divider(uint16_t value) { #endif #ifdef USE_THERMAL_REGULATION -#define ADC_STEPS 4 -#else #define ADC_STEPS 2 +#else +#define ADC_STEPS 1 #endif -// save the measurement result, set a flag to show something happened, -// and count how many times we've triggered since last counter reset +// happens every time the ADC sampler finishes a measurement ISR(ADC_vect) { - #if 0 // the fancy method is probably not even needed - // count up but wrap around from 255 to 128; not 255 to 0 - // TODO: find a way to do this faster if possible - uint8_t val = irq_adc; // cache volatile value - irq_adc = (val + 1) | (val & 0b10000000); - #else - irq_adc ++; + #ifdef USE_PSEUDO_RAND + // real-world entropy makes this a true random, not pseudo + pseudo_rand_seed += ADCL; #endif - adc_value = ADC; // save this for later use + + if (irq_adc_stable) { // skip first result; it's junk + adc_values[adc_channel] = ADC; // save this for later use + irq_adc = 1; // a value was saved, so trigger deferred logic + } + irq_adc_stable = 1; + + // start another measurement + // (is explicit because it otherwise doesn't seem to happen during standby mode) + ADC_start_measurement(); } void ADC_inner() { - // ignore the first measurement; the docs say it's junk - if (irq_adc < 2) { - ADC_start_measurement(); // start a second measurement - return; - } + irq_adc = 0; // event handled // the ADC triggers repeatedly when it's on, but we only want one value // (so ignore everything after the first value, until it's manually reset) if (! adcint_enable) return; - // if we're actually runnning, reset the status flags / counters - irq_adc = 0; + // disable after one iteration adcint_enable = 0; #ifdef TICK_DURING_STANDBY @@ -156,41 +157,37 @@ void ADC_inner() { if (go_to_standby) ADC_off(); #endif - // what is being measured? 0/1 = battery voltage, 2/3 = temperature + // what is being measured? 0 = battery voltage, 1 = temperature static uint8_t adc_step = 0; - #ifdef USE_PSEUDO_RAND - // real-world entropy makes this a true random, not pseudo - pseudo_rand_seed += adc_value; - #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 - if (adc_step == 1) { // voltage + if (0 == adc_step) { // voltage ADC_voltage_handler(); } #endif #ifdef USE_THERMAL_REGULATION - else if (adc_step == 3) { // temperature + else if (1 == adc_step) { // temperature ADC_temperature_handler(); } #endif + #if defined(TICK_DURING_STANDBY) && defined(USE_SLEEP_LVP) + // only measure battery voltage while asleep + if (go_to_standby) adc_step = 0; + else + #endif + + adc_step = (adc_step + 1) & (ADC_STEPS-1); + // set the correct type of measurement for next time #ifdef USE_THERMAL_REGULATION #ifdef USE_LVP - if (adc_step < 2) set_admux_voltage(); + if (0 == adc_step) set_admux_voltage(); else set_admux_therm(); #else - set_admux_therm(); + //set_admux_therm(); + #error "USE_THERMAL_REGULATION set without USE_LVP" #endif #else #ifdef USE_LVP @@ -198,6 +195,7 @@ void ADC_inner() { #endif #endif + irq_adc_stable = 0; // first result is unstable } @@ -213,7 +211,7 @@ static inline void ADC_voltage_handler() { #define LVP_TIMER_START (VOLTAGE_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) // N seconds between LVP warnings #define LVP_LOWPASS_STRENGTH ADC_CYCLES_PER_SECOND // lowpass for one second - uint16_t measurement = adc_value; // latest 10-bit ADC reading + uint16_t measurement = adc_values[0]; // latest 10-bit ADC reading #ifdef USE_LVP_AVG // prime on first execution @@ -293,7 +291,7 @@ static inline void ADC_temperature_handler() { #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 - uint16_t measurement = adc_value; // latest 10-bit ADC reading + uint16_t measurement = adc_values[1]; // latest 10-bit ADC reading // Convert ADC units to Celsius (ish) int16_t temp = measurement - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; diff --git a/spaghetti-monster/fsm-adc.h b/spaghetti-monster/fsm-adc.h index 5f4d0c8..6e39750 100644 --- a/spaghetti-monster/fsm-adc.h +++ b/spaghetti-monster/fsm-adc.h @@ -40,7 +40,9 @@ #endif volatile uint8_t irq_adc = 0; // ADC interrupt happened? -uint16_t adc_value; // last ADC measurement +volatile uint8_t irq_adc_stable = 0; // have we passed the 1st junk value yet? +uint8_t adc_channel = 0; // 0=voltage, 1=temperature +uint16_t adc_values[2]; // last ADC measurements (0=voltage, 1=temperature) uint8_t adcint_enable = 0; // is the current ADC result needed? void ADC_inner(); // do the actual ADC-related calculations diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index 3cb7d86..beab1a2 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -185,7 +185,7 @@ void WDT_inner() { if (go_to_standby) ADC_on(); #endif ADC_start_measurement(); - irq_adc = 0; + irq_adc_stable = 0; adcint_enable = 1; } #endif -- cgit v1.2.3 From 81ed77d88c999f9c2368718047d0969fef44e534 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 14 Nov 2019 18:28:52 -0700 Subject: fixed factory reset (wasn't running interrupt logic since it's deferred now) (also fixed issue where nice_delay_ms() was aborted during setup()) (and adjusted the timing to make factory reset similar to the speed it was before this change) --- spaghetti-monster/anduril/anduril.c | 10 +++++----- spaghetti-monster/fsm-events.c | 12 ++++++------ spaghetti-monster/fsm-main.c | 1 - 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 48f4ac1..19d61b7 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -2356,7 +2356,7 @@ void rgb_led_update(uint8_t mode, uint8_t arg) { 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_TIME 2500 #define SPLODEY_STEPS 64 #define SPLODEY_TIME_PER_STEP (SPLODEY_TIME/SPLODEY_STEPS) uint8_t bright; @@ -2364,9 +2364,9 @@ void factory_reset() { // wind up to an explosion for (bright=0; bright>1); - delay_4ms(SPLODEY_TIME_PER_STEP/2/4); + nice_delay_ms(SPLODEY_TIME_PER_STEP/2); if (! button_is_pressed()) { reset = 0; break; @@ -2387,14 +2387,14 @@ void factory_reset() { bright = MAX_LEVEL; for (; bright > 0; bright--) { set_level(bright); - delay_4ms(SPLODEY_TIME_PER_STEP/6/4); + nice_delay_ms(SPLODEY_TIME_PER_STEP/8); } } // explosion cancelled, fade away else { for (; bright > 0; bright--) { set_level(bright); - delay_4ms(SPLODEY_TIME_PER_STEP/3/4); + nice_delay_ms(SPLODEY_TIME_PER_STEP/3); } } } diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index e125e84..a1b013a 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -110,7 +110,7 @@ uint8_t nice_delay_ms(uint16_t ms) { /* // delay_zero() implementation if (ms == 0) { CLKPR = 1<> 2; + #ifdef USE_VOLTAGE_LOWPASS + static uint16_t prev_measurement = 0; - #ifdef USE_VOLTAGE_DIVIDER - voltage = calc_voltage_divider(total); - #else - voltage = (uint16_t)(1.1*1024*10)/total + VOLTAGE_FUDGE_FACTOR; - #endif - } - #else // no USE_LVP_AVG - #ifdef USE_VOLTAGE_DIVIDER - voltage = calc_voltage_divider(measurement); - #else - // calculate actual voltage: volts * 10 - // ADC = 1.1 * 1024 / volts - // volts = 1.1 * 1024 / ADC - //voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; - voltage = ((uint16_t)(2*1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR) >> 1; - #endif + // prime on first execution, or while asleep + if (go_to_standby || (! prev_measurement)) prev_measurement = measurement; + + // only allow raw value to go up or down by 1 per iteration + if (measurement > prev_measurement) measurement = prev_measurement + 1; + else if (measurement < prev_measurement) measurement = prev_measurement - 1; + + // remember for later + prev_measurement = measurement; + #endif // no USE_VOLTAGE_LOWPASS + + #ifdef USE_VOLTAGE_DIVIDER + voltage = calc_voltage_divider(measurement); + #else + // calculate actual voltage: volts * 10 + // ADC = 1.1 * 1024 / volts + // volts = 1.1 * 1024 / ADC + //voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; + voltage = ((uint16_t)(2*1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR) >> 1; #endif + // if low, callback EV_voltage_low / EV_voltage_critical // (but only if it has been more than N ticks since last call) if (lvp_timer) { -- cgit v1.2.3 From 69788279c4bac4508d363634e680abf999e6d631 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 14 Nov 2019 19:28:32 -0700 Subject: oops, put voltage lowpass on the wrong D4S --- spaghetti-monster/anduril/cfg-emisar-d4s.h | 3 --- spaghetti-monster/anduril/cfg-emisar-d4sv2.h | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-emisar-d4s.h b/spaghetti-monster/anduril/cfg-emisar-d4s.h index a9ac5f0..6fe95a6 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4s.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4s.h @@ -47,6 +47,3 @@ #define THERMAL_UPDATE_SPEED 2 #define THERM_PREDICTION_STRENGTH 4 -// attiny1634 has enough space to smooth out voltage readings -#define USE_VOLTAGE_LOWPASS - diff --git a/spaghetti-monster/anduril/cfg-emisar-d4sv2.h b/spaghetti-monster/anduril/cfg-emisar-d4sv2.h index acc9101..c47e774 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4sv2.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4sv2.h @@ -61,3 +61,7 @@ // seems relevant on attiny1634 #define THERM_CAL_OFFSET 5 + +// attiny1634 has enough space to smooth out voltage readings +#define USE_VOLTAGE_LOWPASS + -- cgit v1.2.3 From c8a74e625ea00efc3fd9923e9204e3f32eda4091 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 14 Nov 2019 19:35:33 -0700 Subject: turned off muggle mode on Q8 and MF01S, to make builds small enough again --- spaghetti-monster/anduril/cfg-blf-q8.h | 5 +++++ spaghetti-monster/anduril/cfg-mateminco-mf01s.h | 6 ++++++ 2 files changed, 11 insertions(+) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-blf-q8.h b/spaghetti-monster/anduril/cfg-blf-q8.h index 970fedb..166b10e 100644 --- a/spaghetti-monster/anduril/cfg-blf-q8.h +++ b/spaghetti-monster/anduril/cfg-blf-q8.h @@ -13,6 +13,11 @@ // lockout: blinking (3) #define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 2) +// doesn't quite fit +#ifdef USE_MUGGLE_MODE +#undef USE_MUGGLE_MODE +#endif + // copied from Emisar D4 ramp // ../../bin/level_calc.py 1 65 7135 1 0.8 150 // ... mixed with this: diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h index 0585b38..2af1305 100644 --- a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h @@ -14,6 +14,12 @@ #define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 1) +// doesn't quite fit +#ifdef USE_MUGGLE_MODE +#undef USE_MUGGLE_MODE +#endif + + // don't blink during ramp, it's irrelevant and annoying on this light #define BLINK_AT_RAMP_CEILING #undef BLINK_AT_RAMP_MIDDLE -- cgit v1.2.3 From 35d5a5a245e4fba7bcaa0dd59d6c02c1c321b1fd Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 18 Nov 2019 00:41:11 -0700 Subject: added SOS mode to the BLF LT1 Lantern build, because people wanted it --- spaghetti-monster/anduril/anduril.c | 48 ++++++++++++++++++++++++----- spaghetti-monster/anduril/cfg-blf-lantern.h | 3 ++ 2 files changed, 44 insertions(+), 7 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 48f4ac1..3ab97cb 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -90,6 +90,8 @@ // so don't enable them at the same time as any of the above strobes) //#define USE_POLICE_STROBE_MODE //#define USE_SOS_MODE +//#define USE_SOS_MODE_IN_FF_GROUP // put SOS in the "boring strobes" mode +//#define USE_SOS_MODE_IN_BLINKY_GROUP // put SOS in the blinkies mode group /***** specific settings for known driver types *****/ #include "tk.h" @@ -146,7 +148,7 @@ #define USE_STROBE_STATE #endif -#if defined(USE_POLICE_STROBE_MODE) || defined(USE_SOS_MODE) +#if defined(USE_POLICE_STROBE_MODE) || defined(USE_SOS_MODE_IN_FF_GROUP) #define USE_BORING_STROBE_STATE #endif @@ -282,6 +284,10 @@ uint8_t goodnight_state(Event event, uint16_t arg); uint8_t beacon_state(Event event, uint16_t arg); uint8_t beacon_config_state(Event event, uint16_t arg); #endif +#ifdef USE_SOS_MODE_IN_BLINKY_GROUP +// automatic SOS emergency signal +uint8_t sos_state(Event event, uint16_t arg); +#endif // soft lockout #define MOON_DURING_LOCKOUT_MODE // if enabled, 2nd lockout click goes to the other ramp's floor level @@ -1507,8 +1513,29 @@ inline void police_strobe_iter() { } } #endif +#endif // #ifdef USE_BORING_STROBE_STATE #ifdef USE_SOS_MODE +#ifdef USE_SOS_MODE_IN_BLINKY_GROUP +uint8_t sos_state(Event event, uint16_t arg) { + // 1 click: off + if (event == EV_1click) { + set_state(off_state, 0); + return MISCHIEF_MANAGED; + } + // 2 clicks: next mode + else if (event == EV_2clicks) { + #ifdef USE_THERMAL_REGULATION + set_state(tempcheck_state, 0); + #else + set_state(battcheck_state, 0); + #endif + return MISCHIEF_MANAGED; + } + return EVENT_NOT_HANDLED; +} +#endif + void sos_blink(uint8_t num, uint8_t dah) { #define DIT_LENGTH 200 for (; num > 0; num--) { @@ -1527,14 +1554,13 @@ void sos_blink(uint8_t num, uint8_t dah) { inline void sos_mode_iter() { // one iteration of main loop() - nice_delay_ms(1000); + //nice_delay_ms(1000); sos_blink(3, 0); // S sos_blink(3, 1); // O sos_blink(3, 0); // S - nice_delay_ms(1000); + nice_delay_ms(2000); } #endif // #ifdef USE_SOS_MODE -#endif // #ifdef USE_BORING_STROBE_STATE #ifdef USE_BATTCHECK @@ -1585,9 +1611,11 @@ uint8_t beacon_state(Event event, uint16_t arg) { } // TODO: use sleep ticks to measure time between pulses, // to save power - // 2 clicks: tempcheck mode + // 2 clicks: next mode else if (event == EV_2clicks) { - #ifdef USE_THERMAL_REGULATION + #ifdef USE_SOS_MODE_IN_BLINKY_GROUP + set_state(sos_state, 0); + #elif defined(USE_THERMAL_REGULATION) set_state(tempcheck_state, 0); #else set_state(battcheck_state, 0); @@ -2646,7 +2674,7 @@ void loop() { break; #endif - #ifdef USE_SOS_MODE + #ifdef USE_SOS_MODE_IN_FF_GROUP default: // SOS sos_mode_iter(); break; @@ -2667,6 +2695,12 @@ void loop() { } #endif + #ifdef USE_SOS_MODE_IN_BLINKY_GROUP + else if (state == sos_state) { + sos_mode_iter(); + } + #endif + #ifdef USE_THERMAL_REGULATION // TODO: blink out therm_ceil during thermal_config_state? else if (state == tempcheck_state) { diff --git a/spaghetti-monster/anduril/cfg-blf-lantern.h b/spaghetti-monster/anduril/cfg-blf-lantern.h index bf183eb..bdcd893 100644 --- a/spaghetti-monster/anduril/cfg-blf-lantern.h +++ b/spaghetti-monster/anduril/cfg-blf-lantern.h @@ -54,6 +54,9 @@ #define MUGGLE_FLOOR 15 // about 20 lm #define MUGGLE_CEILING 115 // about 350 lm +#define USE_SOS_MODE +#define USE_SOS_MODE_IN_BLINKY_GROUP + // the sensor (attiny85) is nowhere near the emitters // so thermal regulation can't work #ifdef USE_THERMAL_REGULATION -- cgit v1.2.3 From 36b0f74974140093e1b4b9cd6c358ba89f286f48 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 18 Nov 2019 23:59:49 -0700 Subject: fixed issue where button-press-during-sleep could occasionally cause a reboot (by turning off PCINT when the light is awake) --- spaghetti-monster/fsm-standby.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-standby.c b/spaghetti-monster/fsm-standby.c index 4124d92..e4ef92c 100644 --- a/spaghetti-monster/fsm-standby.c +++ b/spaghetti-monster/fsm-standby.c @@ -43,8 +43,6 @@ void sleep_until_eswitch_pressed() while (button_is_pressed()) {} empty_event_sequence(); // cancel pending input on suspend - PCINT_on(); // wake on e-switch event - #ifdef TICK_DURING_STANDBY // detect which type of event caused a wake-up irq_adc = 0; @@ -54,6 +52,9 @@ void sleep_until_eswitch_pressed() #else go_to_standby = 0; #endif + + PCINT_on(); // wake on e-switch event + // configure sleep mode set_sleep_mode(SLEEP_MODE_PWR_DOWN); @@ -89,7 +90,10 @@ void sleep_until_eswitch_pressed() #endif // go back to normal running mode - //PCINT_on(); // should be on already + // PCINT not needed any more, and can cause problems if on + // (occasional reboots on wakeup-by-button-press) + PCINT_off(); + // restore normal awake-mode interrupts ADC_on(); WDT_on(); } -- cgit v1.2.3 From ed6a02bc0ba93b9ef3139a545225b611fc4c99dc Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 19 Nov 2019 00:06:41 -0700 Subject: cleaned up WDT code a bit, reduced total size, fixed bug where ticks_since_last could have the wrong value sometimes, reduced power use in sleep mode very slightly by skipping button-handling code while asleep --- spaghetti-monster/fsm-pcint.c | 3 +-- spaghetti-monster/fsm-wdt.c | 51 ++++++++++++++++++++----------------------- 2 files changed, 25 insertions(+), 29 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-pcint.c b/spaghetti-monster/fsm-pcint.c index a4a496a..1ba1c15 100644 --- a/spaghetti-monster/fsm-pcint.c +++ b/spaghetti-monster/fsm-pcint.c @@ -97,8 +97,7 @@ void PCINT_inner(uint8_t pressed) { pushed = push_event(B_RELEASE); } - // check if sequence matches any defined sequences - // if so, send event to current state callback + // send event to the current state callback if (pushed) { button_last_state = pressed; emit_current_event(0); diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index beab1a2..0c49a75 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -90,6 +90,14 @@ void WDT_inner() { static uint8_t adc_trigger = 0; + // cache this here to reduce ROM size, because it's volatile + uint16_t ticks_since_last = ticks_since_last_event; + // increment, but loop from max back to half + ticks_since_last = (ticks_since_last + 1) \ + | (ticks_since_last & 0x8000); + // copy back to the original + ticks_since_last_event = ticks_since_last; + // detect and emit button change events (even during standby) uint8_t was_pressed = button_last_state; uint8_t pressed = button_is_pressed(); @@ -97,38 +105,29 @@ void WDT_inner() { go_to_standby = 0; PCINT_inner(pressed); } + // cache again, in case the value changed + ticks_since_last = ticks_since_last_event; #ifdef TICK_DURING_STANDBY - static uint16_t sleep_counter = 0; // handle standby mode specially if (go_to_standby) { // emit a halfsleep tick, and process it - emit(EV_sleep_tick, sleep_counter); - // wrap around from 65535 to 32768, not 0 - sleep_counter = (sleep_counter + 1) | (sleep_counter & 0x8000); + emit(EV_sleep_tick, ticks_since_last); process_emissions(); - #if defined(USE_SLEEP_LVP) + #ifndef USE_SLEEP_LVP + return; // no sleep LVP needed if nothing drains power while off + #else // stop here, usually... but proceed often enough for sleep LVP to work - if (0 != (sleep_counter & 0x7f)) return; + if (0 != (ticks_since_last & 0x7f)) return; + adc_trigger = 255; // make sure a measurement will happen - #else - return; // no sleep LVP needed if nothing drains power while off + ADC_on(); // enable ADC voltage measurement functions temporarily #endif } - else { sleep_counter = 0; } + else { // button handling should only happen while awake #endif - // cache this here to reduce ROM size, because it's volatile - uint16_t ticks_since_last = ticks_since_last_event; - - // increment, but loop from max back to half - //if (ticks_since_last < 0xff) ticks_since_last ++; - ticks_since_last = (ticks_since_last + 1) \ - | (ticks_since_last & 0x8000); - // copy back to the original - ticks_since_last_event = ticks_since_last; - // if time since last event exceeds timeout, // append timeout to current event sequence, then // send event to current state callback @@ -148,9 +147,9 @@ void WDT_inner() { emit_current_event(ticks_since_last); } // has button been down long enough to become a "hold"? + // (first frame of a "hold" event) else { if (ticks_since_last >= HOLD_TIMEOUT) { - //ticks_since_last_event = 0; current_event |= B_HOLD; emit_current_event(0); } @@ -163,27 +162,25 @@ void WDT_inner() { // no timeout required when releasing a long-press // TODO? move this logic to PCINT() and simplify things here? if (current_event & B_HOLD) { - //emit_current_event(0); // should have been emitted by PCINT + //emit_current_event(0); // should have been emitted by PCINT_inner() empty_event_sequence(); } // end and clear event after release timeout else if (ticks_since_last >= RELEASE_TIMEOUT) { current_event |= B_TIMEOUT; - //ticks_since_last_event = 0; emit_current_event(0); empty_event_sequence(); } } + #ifdef TICK_DURING_STANDBY + } + #endif + #if defined(USE_LVP) || defined(USE_THERMAL_REGULATION) // start a new ADC measurement every 4 ticks adc_trigger ++; if (0 == (adc_trigger & 3)) { - #if defined(TICK_DURING_STANDBY) && defined(USE_SLEEP_LVP) - // we shouldn't be here unless it woke up for a LVP check... - // so enable ADC voltage measurement functions temporarily - if (go_to_standby) ADC_on(); - #endif ADC_start_measurement(); irq_adc_stable = 0; adcint_enable = 1; -- cgit v1.2.3 From 492fdf3281aa7bbcb5aa37b10420766b433e8d34 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 19 Nov 2019 00:21:15 -0700 Subject: fixed ADC cycles running 2X as fast as intended --- spaghetti-monster/fsm-adc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index c859539..ccf1ca2 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -108,12 +108,12 @@ static inline uint8_t calc_voltage_divider(uint16_t value) { } #endif -// Each full cycle runs 7.8X per second with just voltage enabled, -// or 3.9X per second with voltage and temperature. +// Each full cycle runs 15.6X per second with just voltage enabled, +// or 7.8X per second with voltage and temperature. #if defined(USE_LVP) && defined(USE_THERMAL_REGULATION) -#define ADC_CYCLES_PER_SECOND 4 -#else #define ADC_CYCLES_PER_SECOND 8 +#else +#define ADC_CYCLES_PER_SECOND 16 #endif #ifdef USE_THERMAL_REGULATION @@ -322,13 +322,13 @@ static inline void ADC_temperature_handler() { // if it's time to rotate the thermal history, do it history_step ++; #if (THERMAL_UPDATE_SPEED == 4) // new value every 4s - #define THERM_HISTORY_STEP_MAX 15 + #define THERM_HISTORY_STEP_MAX ((2*ADC_CYCLES_PER_SECOND)-1) #elif (THERMAL_UPDATE_SPEED == 2) // new value every 2s - #define THERM_HISTORY_STEP_MAX 7 + #define THERM_HISTORY_STEP_MAX (ADC_CYCLES_PER_SECOND-1) #elif (THERMAL_UPDATE_SPEED == 1) // new value every 1s - #define THERM_HISTORY_STEP_MAX 3 + #define THERM_HISTORY_STEP_MAX ((ADC_CYCLES_PER_SECOND/2)-1) #elif (THERMAL_UPDATE_SPEED == 0) // new value every 0.5s - #define THERM_HISTORY_STEP_MAX 1 + #define THERM_HISTORY_STEP_MAX ((ADC_CYCLES_PER_SECOND/4)-1) #endif if (0 == (history_step & THERM_HISTORY_STEP_MAX)) { // rotate measurements and add a new one -- cgit v1.2.3 From bac2e2572bf2d12aed8f0eecdd2b47bf4c29c001 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 19 Nov 2019 00:25:54 -0700 Subject: enabled prevent_reboot_loop() on all builds, to reduce the impact of any potential crashes (even though I just fixed the only known bug which could trigger an unintentional reboot) --- spaghetti-monster/fsm-main.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index c9ab69b..d352a36 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -79,22 +79,24 @@ inline void hw_setup() { #endif -#ifdef USE_REBOOT -void prevent_reboot_loop() { +//#ifdef USE_REBOOT +static inline void prevent_reboot_loop() { // prevent WDT from rebooting MCU again MCUSR &= ~(1<= 1 DDRB |= (1 << PWM1_PIN); @@ -69,7 +69,7 @@ inline void hw_setup() { PCMSK = (1 << SWITCH_PIN); // pin change interrupt uses this pin } #elif (ATTINY == 1634) -inline void hw_setup() { +static inline void hw_setup() { // this gets tricky with so many pins... // ... so punt it to the hwdef file hwdef_setup(); -- cgit v1.2.3 From 1354b727e203a2c93b12a349b58c04b1cc31228e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 19 Nov 2019 00:37:16 -0700 Subject: Mateminco MF01S can fit muggle mode again, barely --- spaghetti-monster/anduril/cfg-mateminco-mf01s.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h index 2af1305..22b497b 100644 --- a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h @@ -15,9 +15,9 @@ // doesn't quite fit -#ifdef USE_MUGGLE_MODE -#undef USE_MUGGLE_MODE -#endif +//#ifdef USE_MUGGLE_MODE +//#undef USE_MUGGLE_MODE +//#endif // don't blink during ramp, it's irrelevant and annoying on this light -- cgit v1.2.3 From edede40c7ae37c5e13bce7c31d3ffba9e9fefdf8 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 20 Nov 2019 15:29:51 -0700 Subject: fixed unintentional wakeup right after going to sleep (by enabling the PCINT slightly sooner, before setting its "handled" flag) --- spaghetti-monster/fsm-standby.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-standby.c b/spaghetti-monster/fsm-standby.c index e4ef92c..9398f52 100644 --- a/spaghetti-monster/fsm-standby.c +++ b/spaghetti-monster/fsm-standby.c @@ -43,6 +43,8 @@ void sleep_until_eswitch_pressed() while (button_is_pressed()) {} empty_event_sequence(); // cancel pending input on suspend + PCINT_on(); // wake on e-switch event + #ifdef TICK_DURING_STANDBY // detect which type of event caused a wake-up irq_adc = 0; @@ -53,8 +55,6 @@ void sleep_until_eswitch_pressed() go_to_standby = 0; #endif - PCINT_on(); // wake on e-switch event - // configure sleep mode set_sleep_mode(SLEEP_MODE_PWR_DOWN); -- cgit v1.2.3 From 02ba399f83371d3c8dba866fefb2519767d809b7 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 20 Nov 2019 15:34:48 -0700 Subject: made the button LED turn off in momentary mode, instead of staying on forever --- spaghetti-monster/anduril/anduril.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index a86af16..5c5a6ee 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -1863,9 +1863,14 @@ uint8_t momentary_state(Event event, uint16_t arg) { } } else { - if (arg > TICKS_PER_SECOND*15) { // sleep after 15 seconds + if (arg > TICKS_PER_SECOND*5) { // sleep after 5 seconds go_to_standby = 1; // sleep while light is off - // TODO: lighted button should use lockout config? + // turn off lighted button + #ifdef USE_INDICATOR_LED + indicator_led(0); + #elif defined(USE_AUX_RGB_LEDS) + rgb_led_update(0, 0); + #endif } } return MISCHIEF_MANAGED; -- cgit v1.2.3 From 00b94bcce6cd96a1d007578915c9d4347efb36eb Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 24 Nov 2019 21:35:40 -0700 Subject: enabled muggle mode again in all build targets, since it fits now --- spaghetti-monster/anduril/cfg-blf-q8.h | 5 ----- spaghetti-monster/anduril/cfg-emisar-d18.h | 6 ------ spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h | 6 ------ spaghetti-monster/anduril/cfg-mateminco-mf01s.h | 6 ------ 4 files changed, 23 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-blf-q8.h b/spaghetti-monster/anduril/cfg-blf-q8.h index 31c22ff..970fedb 100644 --- a/spaghetti-monster/anduril/cfg-blf-q8.h +++ b/spaghetti-monster/anduril/cfg-blf-q8.h @@ -13,11 +13,6 @@ // lockout: blinking (3) #define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 2) -// doesn't quite fit -//#ifdef USE_MUGGLE_MODE -//#undef USE_MUGGLE_MODE -//#endif - // copied from Emisar D4 ramp // ../../bin/level_calc.py 1 65 7135 1 0.8 150 // ... mixed with this: diff --git a/spaghetti-monster/anduril/cfg-emisar-d18.h b/spaghetti-monster/anduril/cfg-emisar-d18.h index 02e8f01..16fbacd 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d18.h +++ b/spaghetti-monster/anduril/cfg-emisar-d18.h @@ -16,12 +16,6 @@ #define USE_TENCLICK_THERMAL_CONFIG -// save space, and remove a mode which doesn't make much sense on this light -#ifdef USE_MUGGLE_MODE -#undef USE_MUGGLE_MODE -#endif - - // level_calc.py seventh 3 150 7135 1 1.4 117.99 7135 6 1 1706.86 FET 3 10 13000 // (designed to make 1x hit at level 50, and Nx hit at level 100) #define RAMP_LENGTH 150 diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h b/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h index a1d366d..bbf751b 100644 --- a/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h @@ -15,12 +15,6 @@ #define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 1) -// doesn't quite fit -#ifdef USE_MUGGLE_MODE -#undef USE_MUGGLE_MODE -#endif - - // don't blink during ramp, it's irrelevant and annoying on this light #define BLINK_AT_RAMP_CEILING #undef BLINK_AT_RAMP_MIDDLE diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h index 22b497b..0585b38 100644 --- a/spaghetti-monster/anduril/cfg-mateminco-mf01s.h +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01s.h @@ -14,12 +14,6 @@ #define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 1) -// doesn't quite fit -//#ifdef USE_MUGGLE_MODE -//#undef USE_MUGGLE_MODE -//#endif - - // don't blink during ramp, it's irrelevant and annoying on this light #define BLINK_AT_RAMP_CEILING #undef BLINK_AT_RAMP_MIDDLE -- cgit v1.2.3 From 1ab6cd428c3b43a80ffac01f29ca0c27a438e3b1 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 25 Nov 2019 18:41:24 -0700 Subject: calibrated Noctigon K1, changed voltage divider calibration values to 10-bit (was 8-bit before) --- spaghetti-monster/fsm-adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 9e52ab6..b8b00de 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -101,7 +101,7 @@ inline void ADC_off() { #ifdef USE_VOLTAGE_DIVIDER static inline uint8_t calc_voltage_divider(uint16_t value) { // use 9.7 fixed-point to get sufficient precision - uint16_t adc_per_volt = ((ADC_44<<7) - (ADC_22<<7)) / (44-22); + uint16_t adc_per_volt = ((ADC_44<<5) - (ADC_22<<5)) / (44-22); // incoming value is 8.2 fixed-point, so shift it 2 bits less uint8_t result = ((value<<5) / adc_per_volt) + VOLTAGE_FUDGE_FACTOR; return result; -- cgit v1.2.3 From 87022ebce2be6da2bffe467d4489c528fc607ea4 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 25 Nov 2019 18:42:37 -0700 Subject: increased Noctigon K1's default temperature limit to 55 C --- spaghetti-monster/anduril/cfg-emisar-d1sv2.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-emisar-d1sv2.h b/spaghetti-monster/anduril/cfg-emisar-d1sv2.h index 19610dc..2bf6ccb 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d1sv2.h +++ b/spaghetti-monster/anduril/cfg-emisar-d1sv2.h @@ -2,6 +2,10 @@ #include "hwdef-Emisar_D1Sv2.h" // ATTINY: 1634 +// this light can safely run a bit hotter than most +#undef DEFAULT_THERM_CEIL +#define DEFAULT_THERM_CEIL 55 + // this light has three aux LED channels: R, G, B #define USE_AUX_RGB_LEDS #define USE_AUX_RGB_LEDS_WHILE_ON -- cgit v1.2.3 From 87ab9d1162174c1844b1d60c6444391ebf9afddf Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 25 Nov 2019 18:56:37 -0700 Subject: renamed Emisar D1S V2 -> Noctigon K1 --- spaghetti-monster/anduril/cfg-emisar-d1sv2.h | 70 --------------------------- spaghetti-monster/anduril/cfg-noctigon-k1.h | 71 ++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 70 deletions(-) delete mode 100644 spaghetti-monster/anduril/cfg-emisar-d1sv2.h create mode 100644 spaghetti-monster/anduril/cfg-noctigon-k1.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-emisar-d1sv2.h b/spaghetti-monster/anduril/cfg-emisar-d1sv2.h deleted file mode 100644 index 2bf6ccb..0000000 --- a/spaghetti-monster/anduril/cfg-emisar-d1sv2.h +++ /dev/null @@ -1,70 +0,0 @@ -// Emisar D1S v2 config options for Anduril -#include "hwdef-Emisar_D1Sv2.h" -// ATTINY: 1634 - -// this light can safely run a bit hotter than most -#undef DEFAULT_THERM_CEIL -#define DEFAULT_THERM_CEIL 55 - -// this light has three aux LED channels: R, G, B -#define USE_AUX_RGB_LEDS -#define USE_AUX_RGB_LEDS_WHILE_ON -#define USE_INDICATOR_LED_WHILE_RAMPING -#define RGB_LED_OFF_DEFAULT 0x18 // low, voltage -#define RGB_LED_LOCKOUT_DEFAULT 0x37 // blinking, rainbow - -// enable blinking aux LEDs -#define TICK_DURING_STANDBY -#define STANDBY_TICK_SPEED 3 // every 0.128 s - - -// ../../bin/level_calc.py cube 1 150 7135 1 4 1300 -// (with max_pwm set to 1023) -#define RAMP_LENGTH 150 -#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,6,7,8,9,10,11,12,13,14,15,16,17,18,20,21,23,24,26,27,29,31,32,34,36,38,40,43,45,47,49,52,54,57,60,62,65,68,71,74,77,81,84,87,91,95,98,102,106,110,114,118,122,127,131,136,141,145,150,155,160,166,171,176,182,188,193,199,205,211,218,224,231,237,244,251,258,265,272,280,287,295,303,310,319,327,335,344,352,361,370,379,388,397,407,416,426,436,446,457,467,477,488,499,510,521,533,544,556,568,580,592,604,617,629,642,655,668,682,695,709,723,737,751,766,781,795,810,826,841,857,872,888,904,921,937,954,971,988,1005,1023 -#define MAX_1x7135 50 - -// the entire ramp is regulated; don't blink halfway up -#ifdef BLINK_AT_RAMP_MIDDLE -#undef BLINK_AT_RAMP_MIDDLE -#endif - -// don't slow down at low levels; this isn't that sort of light -// (it needs to stay at full speed for the 10-bit PWM to work) -#ifdef USE_DYNAMIC_UNDERCLOCKING -#undef USE_DYNAMIC_UNDERCLOCKING -#endif - -#define RAMP_SMOOTH_FLOOR 1 -#define RAMP_SMOOTH_CEIL 130 -// 10, 30, [50], 70, 90, 110, 130 -#define RAMP_DISCRETE_FLOOR 10 -#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL -#define RAMP_DISCRETE_STEPS 7 - -#define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR -#define MUGGLE_CEILING 70 - -// 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 ~70% power or ~900 lm -#define THERM_FASTER_LEVEL 130 -// respond to thermal changes faster -#define THERMAL_WARNING_SECONDS 3 -#define THERMAL_UPDATE_SPEED 1 -#define THERM_PREDICTION_STRENGTH 4 - -// easier access to thermal config mode, for Emisar -#define USE_TENCLICK_THERMAL_CONFIG - -// slow down party strobe; this driver can't pulse for 1ms or less -#define PARTY_STROBE_ONTIME 2 - -#define THERM_CAL_OFFSET 5 - -// attiny1634 has enough space to smooth out voltage readings -// (prevent the button from blinking during use) -#define USE_VOLTAGE_LOWPASS - diff --git a/spaghetti-monster/anduril/cfg-noctigon-k1.h b/spaghetti-monster/anduril/cfg-noctigon-k1.h new file mode 100644 index 0000000..bf418c7 --- /dev/null +++ b/spaghetti-monster/anduril/cfg-noctigon-k1.h @@ -0,0 +1,71 @@ +// Noctigon K1 config options for Anduril +// (originally known as Emisar D1S v2) +#include "hwdef-Noctigon_K1.h" +// ATTINY: 1634 + +// this light can safely run a bit hotter than most +#undef DEFAULT_THERM_CEIL +#define DEFAULT_THERM_CEIL 55 + +// this light has three aux LED channels: R, G, B +#define USE_AUX_RGB_LEDS +#define USE_AUX_RGB_LEDS_WHILE_ON +#define USE_INDICATOR_LED_WHILE_RAMPING +#define RGB_LED_OFF_DEFAULT 0x18 // low, voltage +#define RGB_LED_LOCKOUT_DEFAULT 0x37 // blinking, rainbow + +// enable blinking aux LEDs +#define TICK_DURING_STANDBY +#define STANDBY_TICK_SPEED 3 // every 0.128 s + + +// ../../bin/level_calc.py cube 1 150 7135 1 4 1300 +// (with max_pwm set to 1023) +#define RAMP_LENGTH 150 +#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,6,7,8,9,10,11,12,13,14,15,16,17,18,20,21,23,24,26,27,29,31,32,34,36,38,40,43,45,47,49,52,54,57,60,62,65,68,71,74,77,81,84,87,91,95,98,102,106,110,114,118,122,127,131,136,141,145,150,155,160,166,171,176,182,188,193,199,205,211,218,224,231,237,244,251,258,265,272,280,287,295,303,310,319,327,335,344,352,361,370,379,388,397,407,416,426,436,446,457,467,477,488,499,510,521,533,544,556,568,580,592,604,617,629,642,655,668,682,695,709,723,737,751,766,781,795,810,826,841,857,872,888,904,921,937,954,971,988,1005,1023 +#define MAX_1x7135 50 + +// the entire ramp is regulated; don't blink halfway up +#ifdef BLINK_AT_RAMP_MIDDLE +#undef BLINK_AT_RAMP_MIDDLE +#endif + +// don't slow down at low levels; this isn't that sort of light +// (it needs to stay at full speed for the 10-bit PWM to work) +#ifdef USE_DYNAMIC_UNDERCLOCKING +#undef USE_DYNAMIC_UNDERCLOCKING +#endif + +#define RAMP_SMOOTH_FLOOR 1 +#define RAMP_SMOOTH_CEIL 130 +// 10, 30, [50], 70, 90, 110, 130 +#define RAMP_DISCRETE_FLOOR 10 +#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL +#define RAMP_DISCRETE_STEPS 7 + +#define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR +#define MUGGLE_CEILING 70 + +// 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 ~70% power or ~900 lm +#define THERM_FASTER_LEVEL 130 +// respond to thermal changes faster +#define THERMAL_WARNING_SECONDS 3 +#define THERMAL_UPDATE_SPEED 1 +#define THERM_PREDICTION_STRENGTH 4 + +// easier access to thermal config mode, for Noctigon +#define USE_TENCLICK_THERMAL_CONFIG + +// slow down party strobe; this driver can't pulse for 1ms or less +#define PARTY_STROBE_ONTIME 2 + +#define THERM_CAL_OFFSET 5 + +// attiny1634 has enough space to smooth out voltage readings +// (prevent the button from blinking during use) +#define USE_VOLTAGE_LOWPASS + -- cgit v1.2.3 From 9cd6b0c4386e983075606b67dce25ec31f382e30 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 28 Nov 2019 00:12:22 -0700 Subject: changed voltage colors to better match Noctigon K1 --- spaghetti-monster/anduril/anduril.c | 8 ++++---- spaghetti-monster/anduril/cfg-noctigon-k1.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 580609b..c3a1d8a 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -2341,10 +2341,10 @@ uint8_t voltage_to_rgb() { 0, 0, // 0, R 33, 1, // 1, R+G 35, 2, // 2, G - // 0, 3, // 3, G+B // skip; looks too similar to R+G+B - 38, 4, // 4, B - 40, 5, // 5, R + B - 42, 6, // 6, R+G+B + 37, 3, // 3, G+B + 39, 4, // 4, B + 41, 5, // 5, R + B + 44, 6, // 6, R+G+B // skip; looks too similar to G+B 255, 6, // 7, R+G+B }; uint8_t volts = voltage; diff --git a/spaghetti-monster/anduril/cfg-noctigon-k1.h b/spaghetti-monster/anduril/cfg-noctigon-k1.h index bf418c7..6a8e8ee 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-k1.h +++ b/spaghetti-monster/anduril/cfg-noctigon-k1.h @@ -50,7 +50,7 @@ // the D4 runs very very hot, so be extra careful //#define THERM_HARD_TURBO_DROP -// stop panicking at ~70% power or ~900 lm +// stop panicking at ~70% power or ~600 lm #define THERM_FASTER_LEVEL 130 // respond to thermal changes faster #define THERMAL_WARNING_SECONDS 3 -- cgit v1.2.3 From 255133f7a652796e4386f469c90f6d71b5755088 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 29 Nov 2019 15:01:34 -0700 Subject: adjusted BLF Lantern (Sofirn LT1) tint ramping power correction factor to match production units (also made the factor configurable per build target) --- spaghetti-monster/anduril/cfg-blf-lantern.h | 4 ++++ spaghetti-monster/fsm-ramping.c | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-blf-lantern.h b/spaghetti-monster/anduril/cfg-blf-lantern.h index bdcd893..35f25f1 100644 --- a/spaghetti-monster/anduril/cfg-blf-lantern.h +++ b/spaghetti-monster/anduril/cfg-blf-lantern.h @@ -27,6 +27,10 @@ // (one channel for warm emitters, one channel for cold) // so enable a special ramping mode which changes tint instead of brightness #define USE_TINT_RAMPING +// how much to increase total brightness at middle tint +// (0 = 100% brightness, 64 = 200% brightness) +//#define TINT_RAMPING_CORRECTION 26 // prototype, 140% +#define TINT_RAMPING_CORRECTION 6 // production model, 109% #ifdef RAMP_LENGTH #undef RAMP_LENGTH diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 37c8073..8515885 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -72,6 +72,9 @@ void set_level(uint8_t level) { level --; #ifdef USE_TINT_RAMPING + #ifndef TINT_RAMPING_CORRECTION + #define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint + #endif // calculate actual PWM levels based on a single-channel ramp // and a global tint value uint8_t brightness = pgm_read_byte(pwm1_levels + level); @@ -96,7 +99,7 @@ void set_level(uint8_t level) { // correction is only necessary when PWM is fast if (level > HALFSPEED_LEVEL) { base_PWM = brightness - + ((((uint16_t)brightness) * 26 / 64) * triangle_wave(mytint) / 255); + + ((((uint16_t)brightness) * TINT_RAMPING_CORRECTION / 64) * triangle_wave(mytint) / 255); } cool_PWM = (((uint16_t)mytint * (uint16_t)base_PWM) + 127) / 255; -- cgit v1.2.3 From fa36403947842c23383b71e8d85b12126a20d6d6 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 3 Dec 2019 16:55:23 -0700 Subject: adjusted lantern tint ramping power correction again, based on measurements of the previous attempt --- spaghetti-monster/anduril/cfg-blf-lantern.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-blf-lantern.h b/spaghetti-monster/anduril/cfg-blf-lantern.h index 35f25f1..e12a453 100644 --- a/spaghetti-monster/anduril/cfg-blf-lantern.h +++ b/spaghetti-monster/anduril/cfg-blf-lantern.h @@ -30,7 +30,7 @@ // how much to increase total brightness at middle tint // (0 = 100% brightness, 64 = 200% brightness) //#define TINT_RAMPING_CORRECTION 26 // prototype, 140% -#define TINT_RAMPING_CORRECTION 6 // production model, 109% +#define TINT_RAMPING_CORRECTION 10 // production model, 115% #ifdef RAMP_LENGTH #undef RAMP_LENGTH -- cgit v1.2.3 From 5cab13e327da93c7682454ab4d3fb147e9ece04a Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 3 Dec 2019 16:55:52 -0700 Subject: added a FW3A build with the FET turned off completely --- spaghetti-monster/anduril/cfg-fw3a-nofet.h | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 spaghetti-monster/anduril/cfg-fw3a-nofet.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-fw3a-nofet.h b/spaghetti-monster/anduril/cfg-fw3a-nofet.h new file mode 100644 index 0000000..a6be10d --- /dev/null +++ b/spaghetti-monster/anduril/cfg-fw3a-nofet.h @@ -0,0 +1,36 @@ +// FW3A with the FET disabled +#include "cfg-fw3a.h" + +// don't use channel 3 (FET) +#undef PWM_CHANNELS +#undef PWM3_PIN +#undef PWM3_LVL +#define PWM_CHANNELS 2 + +// reconfigure the ramp +#undef PWM1_LEVELS +#undef PWM2_LEVELS +#undef PWM3_LEVELS +// copied from Emisar D4, mostly +#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,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 +#undef MAX_1x7135 +#define MAX_1x7135 65 +#undef HALFSPEED_LEVEL +#define HALFSPEED_LEVEL 14 +#undef QUARTERSPEED_LEVEL +#define QUARTERSPEED_LEVEL 6 + +#undef RAMP_SMOOTH_FLOOR +#undef RAMP_SMOOTH_CEIL +#undef RAMP_DISCRETE_FLOOR +#undef RAMP_DISCRETE_CEIL +#undef RAMP_DISCRETE_STEPS + +#define RAMP_SMOOTH_FLOOR 1 +#define RAMP_SMOOTH_CEIL 150 +// 10, 33, 56, 80, 103, 126, 150 +#define RAMP_DISCRETE_FLOOR 10 +#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL +#define RAMP_DISCRETE_STEPS 7 + -- cgit v1.2.3 From 480898878f845067b5e17bd49c25ad3e67b2e7b0 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 4 Dec 2019 01:53:08 -0700 Subject: fixed compile errors to handle a couple USE_ flags better: - beacon mode off (suggested by Agro) - tenclick shortcut on with thermal regulation off --- spaghetti-monster/anduril/anduril.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 4a61da3..c89e5fe 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -688,7 +688,7 @@ uint8_t off_state(Event event, uint16_t arg) { return MISCHIEF_MANAGED; } #endif // end 7 clicks - #ifdef USE_TENCLICK_THERMAL_CONFIG + #if defined(USE_TENCLICK_THERMAL_CONFIG) && defined(USE_THERMAL_REGULATION) // 10 clicks: thermal config mode else if (event == EV_10clicks) { push_state(thermal_config_state, 0); @@ -1648,9 +1648,15 @@ uint8_t goodnight_state(Event event, uint16_t arg) { set_state(off_state, 0); return MISCHIEF_MANAGED; } - // 2 clicks: beacon mode + // 2 clicks: next mode else if (event == EV_2clicks) { + #ifdef USE_BEACON_MODE set_state(beacon_state, 0); + #elif defined(USE_SOS_MODE_IN_BLINKY_GROUP) + set_state(sos_state, 0); + #elif defined(USE_THERMAL_REGULATION) + set_state(tempcheck_state, 0); + #endif return MISCHIEF_MANAGED; } // tick: step down (maybe) or off (maybe) -- cgit v1.2.3 From befe77a863e39b4bae70985bf2bf24449f8521d2 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 4 Dec 2019 02:00:16 -0700 Subject: added a compile-time flag to enable/disable momentary mode (suggested by Agro) --- spaghetti-monster/anduril/anduril.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index c89e5fe..380e2f9 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -79,6 +79,9 @@ // enable beacon mode #define USE_BEACON_MODE +// enable momentary mode +#define USE_MOMENTARY_MODE + //Muggle mode for easy UI #define USE_MUGGLE_MODE @@ -293,10 +296,12 @@ uint8_t sos_state(Event event, uint16_t arg); // if enabled, 2nd lockout click goes to the other ramp's floor level #define LOCKOUT_MOON_FANCY uint8_t lockout_state(Event event, uint16_t arg); +#ifdef USE_MOMENTARY_MODE // 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* +#endif #ifdef USE_MUGGLE_MODE // muggle mode, super-simple, hard to exit uint8_t muggle_state(Event event, uint16_t arg); @@ -630,12 +635,14 @@ uint8_t off_state(Event event, uint16_t arg) { set_state(lockout_state, 0); return MISCHIEF_MANAGED; } + #ifdef USE_MOMENTARY_MODE // 5 clicks: momentary mode else if (event == EV_5clicks) { blink_confirm(1); set_state(momentary_state, 0); return MISCHIEF_MANAGED; } + #endif #ifdef USE_MUGGLE_MODE // 6 clicks: muggle mode else if (event == EV_6clicks) { @@ -733,7 +740,9 @@ 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)) { + #if defined(USE_MOMENTARY_MODE) && defined(USE_STROBE_STATE) momentary_mode = 0; // 0 = ramping, 1 = strobes + #endif // if we just got back from config mode, go back to memorized level if (event == EV_reenter_state) { arg = memorized_level; @@ -1129,7 +1138,9 @@ uint8_t strobe_state(Event event, uint16_t arg) { // (maybe I should just make it nonvolatile?) strobe_mode_te st = strobe_type; + #ifdef USE_MOMENTARY_MODE momentary_mode = 1; // 0 = ramping, 1 = strobes + #endif #ifdef USE_CANDLE_MODE // pass all events to candle mode, when it's active @@ -1808,6 +1819,7 @@ uint8_t lockout_state(Event event, uint16_t arg) { } +#ifdef USE_MOMENTARY_MODE uint8_t momentary_state(Event event, uint16_t arg) { // TODO: momentary strobe here? (for light painting) @@ -1857,6 +1869,7 @@ uint8_t momentary_state(Event event, uint16_t arg) { return EVENT_NOT_HANDLED; } +#endif #ifdef USE_MUGGLE_MODE @@ -2665,7 +2678,11 @@ void loop() { #ifdef USE_STROBE_STATE else if ((state == strobe_state) - || ((state == momentary_state) && (momentary_mode == 1) && (momentary_active)) ) { // also handle momentary strobes + #ifdef USE_MOMENTARY_MODE + // also handle momentary strobes + || ((state == momentary_state) && (momentary_mode == 1) && (momentary_active)) + #endif + ) { uint8_t st = strobe_type; switch(st) { -- cgit v1.2.3 From 1a7a2b70d83882f71ddb59080f2cac82085a3b26 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 11 Dec 2019 00:59:20 -0700 Subject: added support for Fireflies ROT66 G2 and PL47 G2 --- spaghetti-monster/anduril/cfg-ff-pl47g2.h | 60 ++++++++++++++++++++++++++++++ spaghetti-monster/anduril/cfg-ff-rot66g2.h | 49 ++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 spaghetti-monster/anduril/cfg-ff-pl47g2.h create mode 100644 spaghetti-monster/anduril/cfg-ff-rot66g2.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-ff-pl47g2.h b/spaghetti-monster/anduril/cfg-ff-pl47g2.h new file mode 100644 index 0000000..d5dd79d --- /dev/null +++ b/spaghetti-monster/anduril/cfg-ff-pl47g2.h @@ -0,0 +1,60 @@ +// Fireflies PL47 G2 config options for Anduril +#include "hwdef-FF_PL47.h" + +// the button lights up +#define USE_INDICATOR_LED +// the aux LEDs are in the same place as the main LEDs +#ifdef USE_INDICATOR_LED_WHILE_RAMPING +#undef USE_INDICATOR_LED_WHILE_RAMPING +#endif +// enable blinking indicator LED while off? +#define TICK_DURING_STANDBY +#define STANDBY_TICK_SPEED 3 // every 0.128 s +#define USE_FANCIER_BLINKING_INDICATOR + +// If TICK_DURING_STANDBY is enabled... +// off mode: low (1) +// lockout: blinking (3) +#define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 1) + + +#define RAMP_LENGTH 150 + +// driver is a FET + 3x7135, ~400 lm at highest regulated level +// ramp copied from Emisar D4S ramp +#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,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,1,3,4,5,7,8,10,11,13,14,16,18,19,21,23,25,27,29,31,34,36,38,41,43,46,48,51,54,57,60,63,66,69,72,76,79,83,87,91,95,99,103,107,112,116,121,126,131,136,141,146,152,158,163,169,175,182,188,195,202,209,216,223,231,239,247,255 +#define MAX_1x7135 83 +#define HALFSPEED_LEVEL 13 +#define QUARTERSPEED_LEVEL 6 + +// thermal regulation parameters +#ifdef MIN_THERM_STEPDOWN +#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 + +// ceiling is level 120/150 +#define RAMP_SMOOTH_CEIL 120 + +// 10, 28, 46, 65, [83], 101, 120 +#define RAMP_DISCRETE_FLOOR 10 +#define RAMP_DISCRETE_CEIL 120 +#define RAMP_DISCRETE_STEPS 7 + +// ~25 lm to ~300 lm +#define MUGGLE_FLOOR 30 +#define MUGGLE_CEILING MAX_1x7135 + +// regulate down faster when the FET is active, slower otherwise +#define THERM_FASTER_LEVEL 135 // throttle back faster when high + +// hard drop doesn't seem to be needed on this light +#ifdef THERM_HARD_TURBO_DROP +#undef THERM_HARD_TURBO_DROP +#endif + +// don't do this +#undef BLINK_AT_RAMP_MIDDLE +#undef BLINK_AT_RAMP_CEILING + diff --git a/spaghetti-monster/anduril/cfg-ff-rot66g2.h b/spaghetti-monster/anduril/cfg-ff-rot66g2.h new file mode 100644 index 0000000..4e353a8 --- /dev/null +++ b/spaghetti-monster/anduril/cfg-ff-rot66g2.h @@ -0,0 +1,49 @@ +// Fireflies ROT66 G2 config options for Anduril +#include "cfg-ff-rot66.h" + +// if the "low" mode was disabled, turn it back on +#ifdef INDICATOR_LED_SKIP_LOW +#undef INDICATOR_LED_SKIP_LOW +#endif +// enable blinking indicator LED while off +#define TICK_DURING_STANDBY +#define STANDBY_TICK_SPEED 3 // every 0.128 s +#define USE_FANCIER_BLINKING_INDICATOR + +// lockout: blinking (3), off: low (1) +#ifdef INDICATOR_LED_DEFAULT_MODE +#undef INDICATOR_LED_DEFAULT_MODE +#endif +#define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 1) + +// ramp shape is different than original ROT66 +// 1x7135: 150 lm +// Nx7135: 1200 lm +// FET: 4500 lm +// ../../../bin/level_calc.py 7.0 3 150 7135 1 4 180.16 7135 8 1 1374.48 FET 1 10 4000 +// (plus some manual tweaks) +#undef PWM1_LEVELS +#undef PWM2_LEVELS +#undef PWM3_LEVELS +#define PWM1_LEVELS 1,1,2,3,3,4,4,5,6,7,7,8,9,10,11,12,16,17,18,19,20,21,22,24,26,28,30,32,35,37,40,42,45,48,51,55,58,62,65,69,74,78,83,87,92,98,103,109,115,121,128,134,142,149,157,165,173,182,191,201,211,221,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,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,9,11,13,14,16,18,20,22,24,26,28,30,33,35,38,41,43,46,49,52,55,59,62,66,69,73,77,81,85,89,94,98,103,108,113,118,124,129,135,141,147,153,160,166,173,180,188,195,203,211,219,228,237,246,255,255,255,255,255,255,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 PWM3_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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,11,17,23,29,36,42,49,56,63,71,78,86,94,102,111,119,128,137,147,156,166,176,187,197,208,219,231,243,255 + +#undef MAX_1x7135 +#undef MAX_Nx7135 +#define MAX_1x7135 65 // ~150 lm +#define MAX_Nx7135 120 // ~1200 m +#undef HALFSPEED_LEVEL +#undef QUARTERSPEED_LEVEL +#define HALFSPEED_LEVEL 17 +#define QUARTERSPEED_LEVEL 6 + +// higher floor than default, and stop at highest regulated level +#define RAMP_SMOOTH_FLOOR 1 // ~0.3 lm +#define RAMP_SMOOTH_CEIL MAX_Nx7135 // ~1200 lm +// 10, 28, 46, [65], 83, 101, [120] +#define RAMP_DISCRETE_FLOOR 10 +#define RAMP_DISCRETE_CEIL MAX_Nx7135 +#define RAMP_DISCRETE_STEPS 7 + + -- cgit v1.2.3 From e7f75ac1177d49d9081755c1d9b54885c996ec80 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 17 Dec 2019 18:17:58 -0700 Subject: fixed too-slow thermal response (was introduced in the irq-refactor branch) --- spaghetti-monster/fsm-adc.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 4ee2018..3763a3e 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -276,6 +276,8 @@ static inline void ADC_temperature_handler() { #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 + // TODO: left-shift this so the lowpass can get higher resolution + // TODO: increase the sampling rate, to keep the lowpass from lagging uint16_t measurement = adc_values[1]; // latest 10-bit ADC reading // Convert ADC units to Celsius (ish) @@ -322,15 +324,16 @@ static inline void ADC_temperature_handler() { // if it's time to rotate the thermal history, do it history_step ++; #if (THERMAL_UPDATE_SPEED == 4) // new value every 4s - #define THERM_HISTORY_STEP_MAX ((2*ADC_CYCLES_PER_SECOND)-1) + #define THERM_HISTORY_STEP_MAX (4*ADC_CYCLES_PER_SECOND) #elif (THERMAL_UPDATE_SPEED == 2) // new value every 2s - #define THERM_HISTORY_STEP_MAX (ADC_CYCLES_PER_SECOND-1) + #define THERM_HISTORY_STEP_MAX (2*ADC_CYCLES_PER_SECOND) #elif (THERMAL_UPDATE_SPEED == 1) // new value every 1s - #define THERM_HISTORY_STEP_MAX ((ADC_CYCLES_PER_SECOND/2)-1) + #define THERM_HISTORY_STEP_MAX (ADC_CYCLES_PER_SECOND) #elif (THERMAL_UPDATE_SPEED == 0) // new value every 0.5s - #define THERM_HISTORY_STEP_MAX ((ADC_CYCLES_PER_SECOND/4)-1) + #define THERM_HISTORY_STEP_MAX (ADC_CYCLES_PER_SECOND/2) #endif - if (0 == (history_step & THERM_HISTORY_STEP_MAX)) { + if (THERM_HISTORY_STEP_MAX == history_step) { + history_step = 0; // rotate measurements and add a new one for (uint8_t i=0; i>1) / adc_per_volt) + VOLTAGE_FUDGE_FACTOR; return result; } #endif @@ -124,78 +135,115 @@ static inline uint8_t calc_voltage_divider(uint16_t value) { // happens every time the ADC sampler finishes a measurement ISR(ADC_vect) { - #ifdef USE_PSEUDO_RAND - // real-world entropy makes this a true random, not pseudo - pseudo_rand_seed += ADCL; - #endif - if (irq_adc_stable) { // skip first result; it's junk + // skip the first measurement; it's junk + //if (adc_sample_count) { + // slow down even more than ADC_PRSCL + // (result is about 600 Hz or a maximum of ~9 ADC units per second) + // (8 MHz / 128 prescale / 13.5 ticks per measurement / 8 = ~578 Hz) + // (~578 Hz / 64X resolution = ~9 original-resolution units per second) + if (1 == (adc_sample_count & 7)) { + + uint16_t m; // latest measurement + uint16_t s; // smoothed measurement + uint8_t channel = adc_channel; + + // update the latest value + m = ADC; + adc_raw[channel] = m; + + // lowpass the value + //s = adc_smooth[channel]; // easier to read + uint16_t *v = adc_smooth + channel; // compiles smaller + s = *v; + if (m > s) { s++; } + if (m < s) { s--; } + //adc_smooth[channel] = s; + *v = s; + + // track what woke us up, and enable deferred logic + irq_adc = 1; + + } + + // the next measurement isn't the first + //adc_sample_count = 1; + adc_sample_count ++; + + /* + if (adc_sample_count) { // skip first result; it's junk adc_values[adc_channel] = ADC; // save this for later use irq_adc = 1; // a value was saved, so trigger deferred logic } - irq_adc_stable = 1; + adc_sample_count = 1; // start another measurement // (is explicit because it otherwise doesn't seem to happen during standby mode) ADC_start_measurement(); + */ } -void ADC_inner() { +void adc_deferred() { irq_adc = 0; // event handled - // the ADC triggers repeatedly when it's on, but we only want one value - // (so ignore everything after the first value, until it's manually reset) - if (! adcint_enable) return; + #ifdef USE_PSEUDO_RAND + // real-world entropy makes this a true random, not pseudo + // Why here instead of the ISR? Because it makes the time-critical ISR + // code a few cycles faster and we don't need crypto-grade randomness. + pseudo_rand_seed += (ADCL >> 6) + (ADCH << 2); + #endif + + // the ADC triggers repeatedly when it's on, but we only need to run the + // voltage and temperature regulation stuff once in a while...so disable + // this after each activation, until it's manually enabled again + if (! adc_deferred_enable) return; // disable after one iteration - adcint_enable = 0; + adc_deferred_enable = 0; + + // what is being measured? 0 = battery voltage, 1 = temperature + uint8_t adc_step; - #ifdef TICK_DURING_STANDBY + #if defined(USE_LVP) && defined(USE_THERMAL_REGULATION) + // do whichever one is currently active + adc_step = adc_channel; + #else + // unless there's no temperature sensor... then just do voltage + adc_step = 0; + #endif + + #if defined(TICK_DURING_STANDBY) && defined(USE_SLEEP_LVP) // in sleep mode, turn off after just one measurement // (having the ADC on raises standby power by about 250 uA) // (and the usual standby level is only ~20 uA) - if (go_to_standby) ADC_off(); + if (go_to_standby) { + ADC_off(); + // also, only check the battery while asleep, not the temperature + adc_channel = 0; + } #endif - // what is being measured? 0 = battery voltage, 1 = temperature - static uint8_t adc_step = 0; + if (0) {} // placeholder for easier syntax #ifdef USE_LVP - if (0 == adc_step) { // voltage + else if (0 == adc_step) { // voltage ADC_voltage_handler(); + #ifdef USE_THERMAL_REGULATION + // set the correct type of measurement for next time + if (! go_to_standby) set_admux_therm(); + #endif } #endif #ifdef USE_THERMAL_REGULATION else if (1 == adc_step) { // temperature ADC_temperature_handler(); - } - #endif - - #if defined(TICK_DURING_STANDBY) && defined(USE_SLEEP_LVP) - // only measure battery voltage while asleep - if (go_to_standby) adc_step = 0; - else - #endif - - adc_step = (adc_step + 1) & (ADC_STEPS-1); - - // set the correct type of measurement for next time - #ifdef USE_THERMAL_REGULATION - #ifdef USE_LVP - if (0 == adc_step) set_admux_voltage(); - else set_admux_therm(); - #else - //set_admux_therm(); - #error "USE_THERMAL_REGULATION set without USE_LVP" - #endif - #else #ifdef USE_LVP + // set the correct type of measurement for next time set_admux_voltage(); #endif + } #endif - - irq_adc_stable = 0; // first result is unstable } @@ -206,21 +254,14 @@ static inline void ADC_voltage_handler() { #define LVP_TIMER_START (VOLTAGE_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) // N seconds between LVP warnings #define LVP_LOWPASS_STRENGTH ADC_CYCLES_PER_SECOND // lowpass for one second - uint16_t measurement = adc_values[0]; // latest 10-bit ADC reading - - #ifdef USE_VOLTAGE_LOWPASS - static uint16_t prev_measurement = 0; - - // prime on first execution, or while asleep - if (go_to_standby || (! prev_measurement)) prev_measurement = measurement; + uint16_t measurement = adc_smooth[0]; // latest 16-bit ADC value - // only allow raw value to go up or down by 1 per iteration - if (measurement > prev_measurement) measurement = prev_measurement + 1; - else if (measurement < prev_measurement) measurement = prev_measurement - 1; - - // remember for later - prev_measurement = measurement; - #endif // no USE_VOLTAGE_LOWPASS + // jump-start the lowpass seed at boot + // (otherwise it takes a while to rise from zero) + if (measurement < 255) { + measurement = adc_raw[0]; + adc_smooth[0] = measurement; + } #ifdef USE_VOLTAGE_DIVIDER voltage = calc_voltage_divider(measurement); @@ -229,7 +270,7 @@ static inline void ADC_voltage_handler() { // ADC = 1.1 * 1024 / volts // volts = 1.1 * 1024 / ADC //voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; - voltage = ((uint16_t)(2*1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR) >> 1; + voltage = ((uint16_t)(2*1.1*1024*10)/(measurement>>6) + VOLTAGE_FUDGE_FACTOR) >> 1; #endif // if low, callback EV_voltage_low / EV_voltage_critical @@ -268,7 +309,7 @@ static inline void ADC_temperature_handler() { #endif #define NUM_THERMAL_VALUES_HISTORY 8 static uint8_t history_step = 0; // don't update history as often - static int16_t temperature_history[NUM_THERMAL_VALUES_HISTORY]; + static uint16_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; @@ -276,34 +317,61 @@ static inline void ADC_temperature_handler() { #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 - // TODO: left-shift this so the lowpass can get higher resolution - // TODO: increase the sampling rate, to keep the lowpass from lagging - uint16_t measurement = adc_values[1]; // latest 10-bit ADC reading + // latest 16-bit ADC reading (left-adjusted, lowpassed) + uint16_t measurement; - // Convert ADC units to Celsius (ish) - int16_t temp = measurement - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; - - // prime on first execution if (reset_thermal_history) { + // don't keep resetting reset_thermal_history = 0; - temperature = temp; + + // ignore lowpass, use latest sample + measurement = adc_raw[1]; + + // reset lowpass to latest sample + adc_smooth[1] = measurement; + + // forget any past measurements for(uint8_t i=0; i temperature) { - temperature ++; - } else if (temp < temperature) { - temperature --; + temperature_history[i] = measurement; + } + else { + measurement = adc_smooth[1]; // average of recent samples + } + + { // rotate the temperature history + // if it's time to rotate the thermal history, do it + // FIXME? allow more than 255 frames per step + // (that's only about 8 seconds maximum) + history_step ++; + #if (THERMAL_UPDATE_SPEED == 4) // new value every 4s + #define THERM_HISTORY_STEP_MAX (4*ADC_CYCLES_PER_SECOND) + #elif (THERMAL_UPDATE_SPEED == 2) // new value every 2s + #define THERM_HISTORY_STEP_MAX (2*ADC_CYCLES_PER_SECOND) + #elif (THERMAL_UPDATE_SPEED == 1) // new value every 1s + #define THERM_HISTORY_STEP_MAX (ADC_CYCLES_PER_SECOND) + #elif (THERMAL_UPDATE_SPEED == 0) // new value every 0.5s + #define THERM_HISTORY_STEP_MAX (ADC_CYCLES_PER_SECOND/2) + #endif + // FIXME: rotate the index instead of moving the values + if (THERM_HISTORY_STEP_MAX == history_step) { + history_step = 0; + // rotate measurements and add a new one + for (uint8_t i=0; i>6) - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; + // guess what the temperature will be in a few seconds int16_t pt; { int16_t diff; - int16_t t = temperature; + uint16_t t = measurement; // algorithm tweaking; not really intended to be modified // how far ahead should we predict? @@ -315,44 +383,28 @@ static inline void ADC_temperature_handler() { #define THERM_RESPONSE_MAGNITUDE 128 #endif // acceptable temperature window size in C - #define THERM_WINDOW_SIZE 5 + #define THERM_WINDOW_SIZE (3<<6) // highest temperature allowed - #define THERM_CEIL ((int16_t)therm_ceil) + #define THERM_CEIL (((int16_t)therm_ceil)<<6) // bottom of target temperature window #define THERM_FLOOR (THERM_CEIL - THERM_WINDOW_SIZE) - // if it's time to rotate the thermal history, do it - history_step ++; - #if (THERMAL_UPDATE_SPEED == 4) // new value every 4s - #define THERM_HISTORY_STEP_MAX (4*ADC_CYCLES_PER_SECOND) - #elif (THERMAL_UPDATE_SPEED == 2) // new value every 2s - #define THERM_HISTORY_STEP_MAX (2*ADC_CYCLES_PER_SECOND) - #elif (THERMAL_UPDATE_SPEED == 1) // new value every 1s - #define THERM_HISTORY_STEP_MAX (ADC_CYCLES_PER_SECOND) - #elif (THERMAL_UPDATE_SPEED == 0) // new value every 0.5s - #define THERM_HISTORY_STEP_MAX (ADC_CYCLES_PER_SECOND/2) - #endif - if (THERM_HISTORY_STEP_MAX == history_step) { - history_step = 0; - // rotate measurements and add a new one - for (uint8_t 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<>1) / adc_per_volt) + VOLTAGE_FUDGE_FACTOR; return result; } @@ -134,40 +134,41 @@ static inline uint8_t calc_voltage_divider(uint16_t value) { #endif // happens every time the ADC sampler finishes a measurement +// collects an average of 64 samples, which increases effective number of +// bits from 10 to about 16 (ish, probably more like 14 really) +// (64 was chosen because it's the largest sample size which allows the +// sum to still fit into a 16-bit integer, and for speed and size reasons, +// we want to avoid doing 32-bit math) ISR(ADC_vect) { - // slow down even more than ADC_PRSCL - // (result is about 600 Hz or a maximum of ~9 ADC units per second) - // (8 MHz / 128 prescale / 13.5 ticks per measurement / 8 = ~578 Hz) - // (~578 Hz / 64X resolution = ~9 original-resolution units per second) - if (1 == (adc_sample_count & 7)) { + static uint16_t adc_sum; - uint16_t m; // latest measurement - uint16_t s; // smoothed measurement - uint8_t channel = adc_channel; + // keep this moving along + adc_sample_count ++; + // reset on first sample + // also, ignore first value since it's probably junk + if (1 == adc_sample_count) { + adc_sum = 0; + return; + } + // 64 samples collected, save the result + else if (66 == adc_sample_count) { + adc_smooth[adc_channel] = adc_sum; + } + // add the latest measurement to the pile + else { + uint16_t m = ADC; + // add to the running total + adc_sum += m; // update the latest value - m = ADC; - adc_raw[channel] = m; - - // lowpass the value - //s = adc_smooth[channel]; // easier to read - uint16_t *v = adc_smooth + channel; // compiles smaller - s = *v; - if (m > s) { s++; } - if (m < s) { s--; } - //adc_smooth[channel] = s; - *v = s; - - // track what woke us up, and enable deferred logic - irq_adc = 1; - + adc_raw[adc_channel] = m; } + // don't worry about the running total overflowing after sample 64... + // it doesn't matter - // the next measurement isn't the first - //adc_sample_count = 1; - adc_sample_count ++; - + // track what woke us up, and enable deferred logic + irq_adc = 1; } void adc_deferred() { @@ -177,7 +178,7 @@ void adc_deferred() { // real-world entropy makes this a true random, not pseudo // Why here instead of the ISR? Because it makes the time-critical ISR // code a few cycles faster and we don't need crypto-grade randomness. - pseudo_rand_seed += (ADCL >> 6) + (ADCH << 2); + pseudo_rand_seed += ADCL; #endif // the ADC triggers repeatedly when it's on, but we only need to run the @@ -241,22 +242,11 @@ static inline void ADC_voltage_handler() { #define LVP_TIMER_START (VOLTAGE_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) // N seconds between LVP warnings #define LVP_LOWPASS_STRENGTH ADC_CYCLES_PER_SECOND // lowpass for one second - uint16_t measurement = adc_smooth[0]; // latest 16-bit ADC value - - // jump-start the lowpass seed at boot - // (otherwise it takes a while to rise from zero) - if (measurement < 255) { - measurement = adc_raw[0]; - adc_smooth[0] = measurement; - } + uint16_t measurement; - // values stair-step between intervals of 64, with random variations - // of 1 or 2 in either direction, so if we chop off the last 6 bits - // it'll flap between N and N-1... but if we add half an interval, - // the values should be really stable after right-alignment - // (instead of 99.98, 100.00, and 100.02, it'll hit values like - // 100.48, 100.50, and 100.52... which are stable when truncated) - measurement += 32; + // latest ADC value + if (go_to_standby) measurement = adc_raw[0] << 6; + else measurement = adc_smooth[0]; #ifdef USE_VOLTAGE_DIVIDER voltage = calc_voltage_divider(measurement); @@ -264,7 +254,6 @@ static inline void ADC_voltage_handler() { // calculate actual voltage: volts * 10 // ADC = 1.1 * 1024 / volts // volts = 1.1 * 1024 / ADC - //voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR; voltage = ((uint16_t)(2*1.1*1024*10)/(measurement>>6) + VOLTAGE_FUDGE_FACTOR) >> 1; #endif @@ -308,34 +297,24 @@ static inline void ADC_temperature_handler() { #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 - // latest 16-bit ADC reading (left-adjusted, lowpassed) + // latest 16-bit ADC reading uint16_t measurement; if (! reset_thermal_history) { - measurement = adc_smooth[1]; // average of recent samples + // average of recent samples + measurement = adc_smooth[1]; } else { // wipe out old data // don't keep resetting reset_thermal_history = 0; - // ignore lowpass, use latest sample - measurement = adc_raw[1]; - - // reset lowpass to latest sample - adc_smooth[1] = measurement; + // ignore average, use latest sample + measurement = adc_raw[1] << 6; // forget any past measurements for(uint8_t i=0; i>= 1; + adc_sample_count = 33; } // add the latest measurement to the pile else { @@ -164,8 +171,6 @@ ISR(ADC_vect) { // update the latest value adc_raw[adc_channel] = m; } - // don't worry about the running total overflowing after sample 64... - // it doesn't matter // track what woke us up, and enable deferred logic irq_adc = 1; -- cgit v1.2.3 From d275f50525ed9a0950c743faa317c7aa4fe9420b Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 30 Jan 2020 23:10:25 -0700 Subject: saving state of ADC / WDT refactoring before doing more changes... what changed so far: - removed LVP lowpass and thermal regulation lowpass logic; it's probably redundant now - slowed ADC deferred logic timing to 4X per second instead of 16X, because there doesn't seem to be much reason to do it any faster - reduced thermal event rate-limit to just 1 second, for more responsive regulation - added "EV_temperature_okay" signal, to help stop adjustments at an appropriate time instead of going to far - sped up sleep LVP to one measurement every 8 seconds instead of 16, to help the aux LEDs respond to voltage changes faster (effect on standby time is negligible) - make sure the WDT doesn't set the ADC channel or counter... except in standby mode --- spaghetti-monster/anduril/anduril.c | 10 ++++ spaghetti-monster/fsm-adc.c | 107 +++++++++++++----------------------- spaghetti-monster/fsm-adc.h | 4 +- spaghetti-monster/fsm-events.h | 1 + spaghetti-monster/fsm-wdt.c | 13 +++-- 5 files changed, 59 insertions(+), 76 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 380e2f9..2b11486 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -1062,6 +1062,16 @@ uint8_t steady_state(Event event, uint16_t arg) { } return MISCHIEF_MANAGED; } + #ifdef USE_SET_LEVEL_GRADUALLY + // temperature is within target window + // (so stop trying to adjust output) + else if (event == EV_temperature_okay) { + // if we're still adjusting output... stop + gradual_target = actual_level; + //set_level_gradually(actual_level); + return MISCHIEF_MANAGED; + } + #endif // ifdef USE_SET_LEVEL_GRADUALLY #endif // ifdef USE_THERMAL_REGULATION return EVENT_NOT_HANDLED; } diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index f10114f..6fae262 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -119,18 +119,12 @@ static inline uint8_t calc_voltage_divider(uint16_t value) { } #endif -// Each full cycle runs 15.6X per second with just voltage enabled, -// or 7.8X per second with voltage and temperature. +// Each full cycle runs ~4X per second with just voltage enabled, +// or ~2X per second with voltage and temperature. #if defined(USE_LVP) && defined(USE_THERMAL_REGULATION) -#define ADC_CYCLES_PER_SECOND 8 +#define ADC_CYCLES_PER_SECOND 2 #else -#define ADC_CYCLES_PER_SECOND 16 -#endif - -#ifdef USE_THERMAL_REGULATION -#define ADC_STEPS 2 -#else -#define ADC_STEPS 1 +#define ADC_CYCLES_PER_SECOND 4 #endif // happens every time the ADC sampler finishes a measurement @@ -242,10 +236,9 @@ void adc_deferred() { #ifdef USE_LVP static inline void ADC_voltage_handler() { + // rate-limit low-voltage warnings to a max of 1 per N seconds static uint8_t lvp_timer = 0; - static uint8_t lvp_lowpass = 0; #define LVP_TIMER_START (VOLTAGE_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) // N seconds between LVP warnings - #define LVP_LOWPASS_STRENGTH ADC_CYCLES_PER_SECOND // lowpass for one second uint16_t measurement; @@ -263,23 +256,15 @@ static inline void ADC_voltage_handler() { #endif // if low, callback EV_voltage_low / EV_voltage_critical - // (but only if it has been more than N ticks since last call) + // (but only if it has been more than N seconds since last call) if (lvp_timer) { lvp_timer --; } else { // it has been long enough since the last warning if (voltage < VOLTAGE_LOW) { - if (lvp_lowpass < LVP_LOWPASS_STRENGTH) { - lvp_lowpass ++; - } else { - // try to send out a warning - emit(EV_voltage_low, 0); - // reset counters - lvp_timer = LVP_TIMER_START; - lvp_lowpass = 0; - } - } else { - // voltage not low? reset count - lvp_lowpass = 0; + // send out a warning + emit(EV_voltage_low, 0); + // reset rate-limit counter + lvp_timer = LVP_TIMER_START; } } } @@ -296,11 +281,7 @@ static inline void ADC_temperature_handler() { static uint8_t history_step = 0; // don't update history as often static uint16_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-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 + #define TEMPERATURE_TIMER_START (THERMAL_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) // N seconds between thermal regulation events // latest 16-bit ADC reading uint16_t measurement; @@ -373,28 +354,17 @@ static inline void ADC_temperature_handler() { // guess what the temp will be several seconds in the future // diff = rate of temperature change - //diff = temperature_history[NUM_THERMAL_VALUES_HISTORY-1] - temperature_history[0]; diff = t - temperature_history[0]; // slight bias toward zero; ignore very small changes (noise) - // FIXME: this is way too small for left-adjusted values /* + // FIXME: this is way too small for 16-bit values for (uint8_t z=0; z<3; z++) { if (diff < 0) diff ++; if (diff > 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 - } - if (pt < THERM_CEIL) { - overheat_lowpass = 0; // we're probably not too hot } if (temperature_timer) { @@ -403,39 +373,38 @@ static inline void ADC_temperature_handler() { // Too hot? if (pt > THERM_CEIL) { - if (overheat_lowpass < OVERHEAT_LOWPASS_STRENGTH) { - overheat_lowpass ++; - } else { - // reset counters - 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); - } + // reset counters + 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) >> 6; + // send a warning + emit(EV_temperature_high, howmuch); } // Too cold? else if (pt < THERM_FLOOR) { - if (underheat_lowpass < UNDERHEAT_LOWPASS_STRENGTH) { - underheat_lowpass ++; - } else { - // reset counters - 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) - if (voltage > VOLTAGE_LOW) - emit(EV_temperature_low, howmuch); - } + // reset counters + 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) >> 6; + // send a notification (unless voltage is low) + // (LVP and underheat warnings fight each other) + if (voltage > VOLTAGE_LOW) + emit(EV_temperature_low, howmuch); + } + + // Goldilocks? (temperature is within target window) + else { + // reset counters + temperature_timer = TEMPERATURE_TIMER_START; + // send a notification (unless voltage is low) + // (LVP and temp-okay events fight each other) + if (voltage > VOLTAGE_LOW) + emit(EV_temperature_okay, 0); } - // TODO: add EV_temperature_okay signal } } #endif diff --git a/spaghetti-monster/fsm-adc.h b/spaghetti-monster/fsm-adc.h index f4c1332..6283b2c 100644 --- a/spaghetti-monster/fsm-adc.h +++ b/spaghetti-monster/fsm-adc.h @@ -67,9 +67,9 @@ void battcheck(); #ifdef USE_THERMAL_REGULATION -// default 5 seconds between thermal regulation events +// default 1 seconds between thermal regulation events #ifndef THERMAL_WARNING_SECONDS -#define THERMAL_WARNING_SECONDS 5 +#define THERMAL_WARNING_SECONDS 1 #endif // try to keep temperature below 45 C #ifndef DEFAULT_THERM_CEIL diff --git a/spaghetti-monster/fsm-events.h b/spaghetti-monster/fsm-events.h index 39ad3aa..6760fdd 100644 --- a/spaghetti-monster/fsm-events.h +++ b/spaghetti-monster/fsm-events.h @@ -85,6 +85,7 @@ static volatile uint16_t ticks_since_last_event = 0; #ifdef USE_THERMAL_REGULATION #define EV_temperature_high (B_SYSTEM|0b00000101) #define EV_temperature_low (B_SYSTEM|0b00000110) +#define EV_temperature_okay (B_SYSTEM|0b00000111) #endif // Button press events diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index e9dca3a..459010f 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -119,7 +119,7 @@ void WDT_inner() { return; // no sleep LVP needed if nothing drains power while off #else // stop here, usually... but proceed often enough for sleep LVP to work - if (0 != (ticks_since_last & 0x7f)) return; + if (0 != (ticks_since_last & 0x3f)) return; adc_trigger = 255; // make sure a measurement will happen ADC_on(); // enable ADC voltage measurement functions temporarily @@ -178,12 +178,15 @@ void WDT_inner() { #endif #if defined(USE_LVP) || defined(USE_THERMAL_REGULATION) - // start a new ADC measurement every 4 ticks + // start a new ADC measurement every 16 ticks adc_trigger ++; - if (0 == (adc_trigger & 3)) { - // in case we're in standby mode and auto-retrigger is turned off + if (0 == (adc_trigger & 15)) { + // in case we're in standby mode and the ADC is turned off + if (go_to_standby) { + //set_admux_voltage(); + ADC_on(); + } ADC_start_measurement(); - adc_sample_count = 0; // allow regulation logic to run adc_deferred_enable = 1; } -- cgit v1.2.3 From f6f553bc5dbef8ef4a00b5e19838d775eff9ab41 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 3 Feb 2020 02:52:53 -0700 Subject: mention the maximum allowed temperature in the manual --- spaghetti-monster/anduril/anduril-manual.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril-manual.txt b/spaghetti-monster/anduril/anduril-manual.txt index 3f17f41..97e6589 100644 --- a/spaghetti-monster/anduril/anduril-manual.txt +++ b/spaghetti-monster/anduril/anduril-manual.txt @@ -147,7 +147,7 @@ In more detail, this is what each blinky / utility mode does: can reach before it will start doing thermal regulation to keep itself from overheating. Click once per degree C above 30. For example, to set the limit to 50 C, click 20 times. The default - is 45 C. + is 45 C, and the highest value it will allow is 70 C. Strobe / Mood Modes -- cgit v1.2.3 From 32cc8a10f500456a0288eff38d41e8b820ee2a7d Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 5 Feb 2020 02:35:10 -0700 Subject: replaced Anduril's gradual adjustment speed code with a smaller simpler version --- spaghetti-monster/anduril/anduril.c | 60 +++++++++++-------------------------- 1 file changed, 17 insertions(+), 43 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 2b11486..69dd118 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -957,59 +957,33 @@ uint8_t steady_state(Event event, uint16_t arg) { if (arg == TICKS_PER_SECOND) ramp_direction = 1; #endif #ifdef USE_SET_LEVEL_GRADUALLY - // make thermal adjustment speed scale with magnitude - // 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 - else if ((! (actual_level < THERM_FASTER_LEVEL)) - && (actual_level > gradual_target)) { - gradual_tick(); - } - else { - #endif - // [int(62*4 / (x**0.8)) for x in (1,2,4,8,16,32,64,128)] - //uint8_t intervals[] = {248, 142, 81, 46, 26, 15, 8, 5}; - // [int(62*4 / (x**0.9)) for x in (1,2,4,8,16,32,64,128)] - //uint8_t intervals[] = {248, 132, 71, 38, 20, 10, 5, 3}; - // [int(62*4 / (x**0.95)) for x in (1,2,4,8,16,32,64,128)] - uint8_t intervals[] = {248, 128, 66, 34, 17, 9, 4, 2}; - uint8_t diff; - static uint8_t ticks_since_adjust = 0; - 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 + int16_t diff = gradual_target - actual_level; + static uint16_t ticks_since_adjust = 0; + ticks_since_adjust++; 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) - && (actual_level > gradual_target)) { magnitude ++; } - #endif + uint16_t ticks_per_adjust = 256; + if (diff < 0) { + diff = -diff; + if (actual_level > THERM_FASTER_LEVEL) { + #ifdef THERM_HARD_TURBO_DROP + ticks_per_adjust >>= 2; + #endif + ticks_per_adjust >>= 2; + } + } else { + // rise at half speed + ticks_per_adjust <<= 1; + } while (diff) { - magnitude ++; + ticks_per_adjust >>= 1; 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(); } - #ifdef THERM_HARD_TURBO_DROP - } - #endif #endif // ifdef USE_SET_LEVEL_GRADUALLY return MISCHIEF_MANAGED; } -- cgit v1.2.3 From 7e994a1a76d7a61e3cdd921b3275169d9a725b6a Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 5 Feb 2020 02:36:24 -0700 Subject: first pass at a smaller simpler thermal regulation algorithm... ... doesn't work well, but I'm saving it so I can experiment with other methods and maybe revert back later. --- spaghetti-monster/fsm-adc.c | 127 ++++++++++++++++++-------------------------- 1 file changed, 52 insertions(+), 75 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 6fae262..d1efff3 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -273,15 +273,24 @@ static inline void ADC_voltage_handler() { #ifdef USE_THERMAL_REGULATION static inline void ADC_temperature_handler() { - // thermal declarations - #ifndef THERMAL_UPDATE_SPEED - #define THERMAL_UPDATE_SPEED 2 + // coarse adjustment + #ifndef THERM_LOOKAHEAD + #define THERM_LOOKAHEAD 5 // can be tweaked per build target #endif - #define NUM_THERMAL_VALUES_HISTORY 8 - static uint8_t history_step = 0; // don't update history as often - static uint16_t temperature_history[NUM_THERMAL_VALUES_HISTORY]; + // fine-grained adjustment + // how proportional should the adjustments be? (not used yet) + #ifndef THERM_RESPONSE_MAGNITUDE + #define THERM_RESPONSE_MAGNITUDE 128 + #endif + // acceptable temperature window size in C + #define THERM_WINDOW_SIZE 3 + + #define NUM_TEMP_HISTORY_STEPS 8 // don't change; it'll break stuff + static uint8_t history_step = 0; + static uint16_t temperature_history[NUM_TEMP_HISTORY_STEPS]; static uint8_t temperature_timer = 0; - #define TEMPERATURE_TIMER_START (THERMAL_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) // N seconds between thermal regulation events + // N seconds between thermal regulation events + #define TEMPERATURE_TIMER_START (THERMAL_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) // latest 16-bit ADC reading uint16_t measurement; @@ -297,105 +306,73 @@ static inline void ADC_temperature_handler() { measurement = adc_raw[1] << 6; // forget any past measurements - for(uint8_t i=0; i>6) - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; - // guess what the temperature will be in a few seconds - int16_t pt; - { - int16_t diff; - uint16_t t = measurement; + // how much has the temperature changed between now and a few seconds ago? + int16_t diff; + diff = measurement - temperature_history[history_step]; + + // update / rotate the temperature history + temperature_history[history_step] = measurement; + history_step = (history_step + 1) & (NUM_TEMP_HISTORY_STEPS-1); + + // PI[D]: guess what the temperature will be in a few seconds + int16_t pt; // predicted temperature + pt = measurement + (diff * THERM_LOOKAHEAD); + + // P[I]D: average of recent measurements + uint16_t avg = 0; + for(uint8_t i=0; i>3); + + uint16_t ceil = therm_ceil << 6; + //uint16_t floor = ceil - (THERM_WINDOW_SIZE << 6); + int16_t offset_pt, offset_avg; + offset_pt = pt - ceil; + offset_avg = avg - ceil; + int16_t offset = offset_pt + offset_avg; + //int16_t offset = (pt - ceil) + (avg - ceil); - // algorithm tweaking; not really intended to be modified - // how far ahead should we predict? - #ifndef THERM_PREDICTION_STRENGTH - #define THERM_PREDICTION_STRENGTH 4 - #endif - // how proportional should the adjustments be? (not used yet) - #ifndef THERM_RESPONSE_MAGNITUDE - #define THERM_RESPONSE_MAGNITUDE 128 - #endif - // acceptable temperature window size in C - #define THERM_WINDOW_SIZE (3<<6) - // highest temperature allowed - #define THERM_CEIL (((int16_t)therm_ceil)<<6) - // bottom of target temperature window - #define THERM_FLOOR (THERM_CEIL - THERM_WINDOW_SIZE) - - // guess what the temp will be several seconds in the future - // diff = rate of temperature change - diff = t - temperature_history[0]; - // slight bias toward zero; ignore very small changes (noise) - /* - // FIXME: this is way too small for 16-bit values - for (uint8_t z=0; z<3; z++) { - if (diff < 0) diff ++; - if (diff > 0) diff --; - } - */ - // projected_temperature = current temp extended forward by amplified rate of change - pt = projected_temperature = t + (diff< THERM_CEIL) { + // (if it's too hot and not getting colder...) + if ((offset > 0) && (diff > (-1 << 5))) { // reset counters 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) >> 6; + //int16_t howmuch = (offset >> 6) * THERM_RESPONSE_MAGNITUDE / 128; + int16_t howmuch = (offset >> 6); // send a warning emit(EV_temperature_high, howmuch); } // Too cold? - else if (pt < THERM_FLOOR) { + // (if it's too cold and not getting warmer...) + else if ((offset < -(THERM_WINDOW_SIZE << 6)) + && (diff < (1 << 5))) { // reset counters 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) >> 6; + //int16_t howmuch = (((-offset) - (THERM_WINDOW_SIZE<<6)) >> 7) * THERM_WINDOW_SIZE / 128; + int16_t howmuch = ((-offset) - (THERM_WINDOW_SIZE<<6)) >> 7; // send a notification (unless voltage is low) // (LVP and underheat warnings fight each other) if (voltage > VOLTAGE_LOW) emit(EV_temperature_low, howmuch); } - // Goldilocks? (temperature is within target window) + // Goldilocks? + // (temperature is within target window, or at least heading toward it) else { // reset counters temperature_timer = TEMPERATURE_TIMER_START; -- cgit v1.2.3 From 46af6026a2dc2bae92d41609a8ecd6144082825e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 5 Feb 2020 22:12:45 -0700 Subject: still doesn't work, but at least it's a bit less broken than before... (ceiling value was all wrong, and the response magnitude was way too big) (also, temperatures here are unsigned, since freezing is about 270 in ADC units) --- spaghetti-monster/fsm-adc.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index d1efff3..2df884e 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -275,7 +275,7 @@ static inline void ADC_voltage_handler() { static inline void ADC_temperature_handler() { // coarse adjustment #ifndef THERM_LOOKAHEAD - #define THERM_LOOKAHEAD 5 // can be tweaked per build target + #define THERM_LOOKAHEAD 3 // can be tweaked per build target #endif // fine-grained adjustment // how proportional should the adjustments be? (not used yet) @@ -323,7 +323,7 @@ static inline void ADC_temperature_handler() { history_step = (history_step + 1) & (NUM_TEMP_HISTORY_STEPS-1); // PI[D]: guess what the temperature will be in a few seconds - int16_t pt; // predicted temperature + uint16_t pt; // predicted temperature pt = measurement + (diff * THERM_LOOKAHEAD); // P[I]D: average of recent measurements @@ -331,11 +331,15 @@ static inline void ADC_temperature_handler() { for(uint8_t i=0; i>3); - uint16_t ceil = therm_ceil << 6; + // convert temperature limit from C to raw 16-bit ADC units + // C = (ADC>>6) - 275 + THERM_CAL_OFFSET + therm_cal_offset; + // ... so ... + // (C + 275 - THERM_CAL_OFFSET - therm_cal_offset) << 6 = ADC; + uint16_t ceil = (therm_ceil + 275 - therm_cal_offset - THERM_CAL_OFFSET) << 6; //uint16_t floor = ceil - (THERM_WINDOW_SIZE << 6); int16_t offset_pt, offset_avg; - offset_pt = pt - ceil; - offset_avg = avg - ceil; + offset_pt = (pt - ceil) >> 1; + offset_avg = (avg - ceil) >> 1; int16_t offset = offset_pt + offset_avg; //int16_t offset = (pt - ceil) + (avg - ceil); @@ -351,7 +355,7 @@ static inline void ADC_temperature_handler() { temperature_timer = TEMPERATURE_TIMER_START; // how far above the ceiling? //int16_t howmuch = (offset >> 6) * THERM_RESPONSE_MAGNITUDE / 128; - int16_t howmuch = (offset >> 6); + int16_t howmuch = (offset >> 8); // send a warning emit(EV_temperature_high, howmuch); } @@ -359,12 +363,12 @@ static inline void ADC_temperature_handler() { // Too cold? // (if it's too cold and not getting warmer...) else if ((offset < -(THERM_WINDOW_SIZE << 6)) - && (diff < (1 << 5))) { + && (diff < (1 << 4))) { // reset counters temperature_timer = TEMPERATURE_TIMER_START; // how far below the floor? //int16_t howmuch = (((-offset) - (THERM_WINDOW_SIZE<<6)) >> 7) * THERM_WINDOW_SIZE / 128; - int16_t howmuch = ((-offset) - (THERM_WINDOW_SIZE<<6)) >> 7; + int16_t howmuch = ((-offset) - (THERM_WINDOW_SIZE<<6)) >> 9; // send a notification (unless voltage is low) // (LVP and underheat warnings fight each other) if (voltage > VOLTAGE_LOW) -- cgit v1.2.3 From 14ad6787546b3a2c55c129c8bd95eb6b98f14531 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 5 Feb 2020 23:34:44 -0700 Subject: brute force method for reducing ADC noise -- average a ridiculous number of samples (because, for some reason, even though 64 samples is plenty in a test program, it ends up being extremely erratic when used inside Anduril... and I'm not sure why) also, use 15-bit ADC values instead of 16 bits, in the temperature logic (to help protect against integer overflows) ... but this code still doesn't work well. It regulates down *very* fast, and then gradually rises until the next extra-fast drop-down. :( ... also, tempcheck mode sometimes changes by 4-5 C between readouts, which is worrisome. ... and factory reset is still broken. --- spaghetti-monster/fsm-adc.c | 32 +++++++++++++------------------- spaghetti-monster/fsm-adc.h | 2 +- 2 files changed, 14 insertions(+), 20 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 2df884e..65669b3 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -135,7 +135,7 @@ static inline uint8_t calc_voltage_divider(uint16_t value) { // doing 32-bit math) ISR(ADC_vect) { - static uint16_t adc_sum; + static uint32_t adc_sum; // keep this moving along adc_sample_count ++; @@ -146,16 +146,10 @@ ISR(ADC_vect) { adc_sum = 0; return; } - // 64 samples collected, save the result - // (actually triggers at 64 and every 32 afterward) - else if (66 == adc_sample_count) { + // 2048 samples collected, save the result + else if (2050 == adc_sample_count) { // save the latest result - adc_smooth[adc_channel] = adc_sum; - // cut sum in half and set up another half-window of samples - // (for sort of a continuous average) - // (this seems to significantly reduce noise) - adc_sum >>= 1; - adc_sample_count = 33; + adc_smooth[adc_channel] = adc_sum >> 5; } // add the latest measurement to the pile else { @@ -275,7 +269,7 @@ static inline void ADC_voltage_handler() { static inline void ADC_temperature_handler() { // coarse adjustment #ifndef THERM_LOOKAHEAD - #define THERM_LOOKAHEAD 3 // can be tweaked per build target + #define THERM_LOOKAHEAD 4 // can be tweaked per build target #endif // fine-grained adjustment // how proportional should the adjustments be? (not used yet) @@ -297,13 +291,13 @@ static inline void ADC_temperature_handler() { if (! reset_thermal_history) { // average of recent samples - measurement = adc_smooth[1]; + measurement = adc_smooth[1] >> 1; } else { // wipe out old data // don't keep resetting reset_thermal_history = 0; // ignore average, use latest sample - measurement = adc_raw[1] << 6; + measurement = adc_raw[1] << 5; // forget any past measurements for(uint8_t i=0; i>6) - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; + temperature = (measurement>>5) - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; // how much has the temperature changed between now and a few seconds ago? int16_t diff; @@ -335,7 +329,7 @@ static inline void ADC_temperature_handler() { // C = (ADC>>6) - 275 + THERM_CAL_OFFSET + therm_cal_offset; // ... so ... // (C + 275 - THERM_CAL_OFFSET - therm_cal_offset) << 6 = ADC; - uint16_t ceil = (therm_ceil + 275 - therm_cal_offset - THERM_CAL_OFFSET) << 6; + uint16_t ceil = (therm_ceil + 275 - therm_cal_offset - THERM_CAL_OFFSET) << 5; //uint16_t floor = ceil - (THERM_WINDOW_SIZE << 6); int16_t offset_pt, offset_avg; offset_pt = (pt - ceil) >> 1; @@ -350,7 +344,7 @@ static inline void ADC_temperature_handler() { // Too hot? // (if it's too hot and not getting colder...) - if ((offset > 0) && (diff > (-1 << 5))) { + if ((offset > 0) && (diff > (-1 << 4))) { // reset counters temperature_timer = TEMPERATURE_TIMER_START; // how far above the ceiling? @@ -362,13 +356,13 @@ static inline void ADC_temperature_handler() { // Too cold? // (if it's too cold and not getting warmer...) - else if ((offset < -(THERM_WINDOW_SIZE << 6)) - && (diff < (1 << 4))) { + else if ((offset < -(THERM_WINDOW_SIZE << 5)) + && (diff < (1 << 3))) { // reset counters temperature_timer = TEMPERATURE_TIMER_START; // how far below the floor? //int16_t howmuch = (((-offset) - (THERM_WINDOW_SIZE<<6)) >> 7) * THERM_WINDOW_SIZE / 128; - int16_t howmuch = ((-offset) - (THERM_WINDOW_SIZE<<6)) >> 9; + int16_t howmuch = ((-offset) - (THERM_WINDOW_SIZE<<5)) >> 8; // send a notification (unless voltage is low) // (LVP and underheat warnings fight each other) if (voltage > VOLTAGE_LOW) diff --git a/spaghetti-monster/fsm-adc.h b/spaghetti-monster/fsm-adc.h index 6283b2c..7acb505 100644 --- a/spaghetti-monster/fsm-adc.h +++ b/spaghetti-monster/fsm-adc.h @@ -40,7 +40,7 @@ #endif volatile uint8_t irq_adc = 0; // ADC interrupt happened? -uint8_t adc_sample_count = 0; // skip the first sample; it's junk +uint16_t adc_sample_count = 0; // skip the first sample; it's junk uint8_t adc_channel = 0; // 0=voltage, 1=temperature uint16_t adc_raw[2]; // last ADC measurements (0=voltage, 1=temperature) uint16_t adc_smooth[2]; // lowpassed ADC measurements (0=voltage, 1=temperature) -- cgit v1.2.3 From c3e0370b57fc8ee4c237233b80532a07eb8b543d Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 25 Feb 2020 23:32:00 -0700 Subject: Added template files for Noctigon K1 12V model. --- spaghetti-monster/anduril/cfg-noctigon-k1-12v.h | 70 +++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 spaghetti-monster/anduril/cfg-noctigon-k1-12v.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h b/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h new file mode 100644 index 0000000..38a672f --- /dev/null +++ b/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h @@ -0,0 +1,70 @@ +// Noctigon K1 12V config options for Anduril +#include "hwdef-Noctigon_K1-12V.h" +// ATTINY: 1634 + +// this light can safely run a bit hotter than most +#undef DEFAULT_THERM_CEIL +#define DEFAULT_THERM_CEIL 55 + +// this light has three aux LED channels: R, G, B +#define USE_AUX_RGB_LEDS +#define USE_AUX_RGB_LEDS_WHILE_ON +#define USE_INDICATOR_LED_WHILE_RAMPING +#define RGB_LED_OFF_DEFAULT 0x18 // low, voltage +#define RGB_LED_LOCKOUT_DEFAULT 0x37 // blinking, rainbow + +// enable blinking aux LEDs +#define TICK_DURING_STANDBY +#define STANDBY_TICK_SPEED 3 // every 0.128 s + + +// ../../bin/level_calc.py cube 1 150 7135 1 4 1300 +// (with max_pwm set to 1023) +#define RAMP_LENGTH 150 +#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,6,7,8,9,10,11,12,13,14,15,16,17,18,20,21,23,24,26,27,29,31,32,34,36,38,40,43,45,47,49,52,54,57,60,62,65,68,71,74,77,81,84,87,91,95,98,102,106,110,114,118,122,127,131,136,141,145,150,155,160,166,171,176,182,188,193,199,205,211,218,224,231,237,244,251,258,265,272,280,287,295,303,310,319,327,335,344,352,361,370,379,388,397,407,416,426,436,446,457,467,477,488,499,510,521,533,544,556,568,580,592,604,617,629,642,655,668,682,695,709,723,737,751,766,781,795,810,826,841,857,872,888,904,921,937,954,971,988,1005,1023 +#define MAX_1x7135 50 + +// the entire ramp is regulated; don't blink halfway up +#ifdef BLINK_AT_RAMP_MIDDLE +#undef BLINK_AT_RAMP_MIDDLE +#endif + +// don't slow down at low levels; this isn't that sort of light +// (it needs to stay at full speed for the 10-bit PWM to work) +#ifdef USE_DYNAMIC_UNDERCLOCKING +#undef USE_DYNAMIC_UNDERCLOCKING +#endif + +#define RAMP_SMOOTH_FLOOR 1 +#define RAMP_SMOOTH_CEIL 130 +// 10, 30, [50], 70, 90, 110, 130 +#define RAMP_DISCRETE_FLOOR 10 +#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL +#define RAMP_DISCRETE_STEPS 7 + +#define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR +#define MUGGLE_CEILING 70 + +// 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 ~70% power or ~600 lm +#define THERM_FASTER_LEVEL 130 +// respond to thermal changes faster +#define THERMAL_WARNING_SECONDS 3 +#define THERMAL_UPDATE_SPEED 1 +#define THERM_PREDICTION_STRENGTH 4 + +// easier access to thermal config mode, for Noctigon +#define USE_TENCLICK_THERMAL_CONFIG + +// slow down party strobe; this driver can't pulse for 1ms or less +#define PARTY_STROBE_ONTIME 2 + +#define THERM_CAL_OFFSET 5 + +// attiny1634 has enough space to smooth out voltage readings +// (prevent the button from blinking during use) +#define USE_VOLTAGE_LOWPASS + -- cgit v1.2.3 From 7d07887e11cf7804ce8eb15fac666551b9a2497e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 25 Feb 2020 23:43:33 -0700 Subject: added support for boost PMIC enable pin (K1 12V has 2 pins which need to turn on/off for main LED output) --- spaghetti-monster/fsm-ramping.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c index 20500cc..bae601e 100644 --- a/spaghetti-monster/fsm-ramping.c +++ b/spaghetti-monster/fsm-ramping.c @@ -72,6 +72,9 @@ void set_level(uint8_t level) { #ifdef LED_ENABLE_PIN LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN); #endif + #ifdef LED_ENABLE2_PIN + LED_ENABLE2_PORT &= ~(1 << LED_ENABLE2_PIN); + #endif } else { level --; @@ -79,6 +82,9 @@ void set_level(uint8_t level) { #ifdef LED_ENABLE_PIN LED_ENABLE_PORT |= (1 << LED_ENABLE_PIN); #endif + #ifdef LED_ENABLE2_PIN + LED_ENABLE2_PORT |= (1 << LED_ENABLE2_PIN); + #endif #ifdef USE_TINT_RAMPING #ifndef TINT_RAMPING_CORRECTION -- cgit v1.2.3 From 93cdcd9d46772d559fccb2ba0d4d26127fa193ce Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 26 Feb 2020 00:02:37 -0700 Subject: K1 12V needs party strobe slowed down even more --- spaghetti-monster/anduril/cfg-noctigon-k1-12v.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h b/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h index 38a672f..12f69de 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h +++ b/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h @@ -60,7 +60,7 @@ #define USE_TENCLICK_THERMAL_CONFIG // slow down party strobe; this driver can't pulse for 1ms or less -#define PARTY_STROBE_ONTIME 2 +#define PARTY_STROBE_ONTIME 4 #define THERM_CAL_OFFSET 5 -- cgit v1.2.3 From c0ffafddc1c2aea1cde4ab6d7ad805fc4bcc32de Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 27 Feb 2020 23:13:15 -0700 Subject: fixed eeprom corruption after turning boost chip on/off (boost chip apparently makes power unstable for a few ms, so we have to wait before accessing eeprom) --- spaghetti-monster/fsm-eeprom.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-eeprom.c b/spaghetti-monster/fsm-eeprom.c index 277e2b2..77352cf 100644 --- a/spaghetti-monster/fsm-eeprom.c +++ b/spaghetti-monster/fsm-eeprom.c @@ -30,6 +30,10 @@ uint8_t eeprom[EEPROM_BYTES]; #endif uint8_t load_eeprom() { + #ifdef LED_ENABLE_PIN + delay_4ms(2); // wait for power to stabilize + #endif + cli(); // check if eeprom has been initialized; abort if it hasn't uint8_t marker = eeprom_read_byte((uint8_t *)EEP_START); @@ -44,6 +48,10 @@ uint8_t load_eeprom() { } void save_eeprom() { + #ifdef LED_ENABLE_PIN + delay_4ms(2); // wait for power to stabilize + #endif + cli(); // save the actual data @@ -62,6 +70,10 @@ uint8_t eeprom_wl[EEPROM_WL_BYTES]; EEP_OFFSET_T eep_wl_prev_offset; uint8_t load_eeprom_wl() { + #ifdef LED_ENABLE_PIN + delay_4ms(2); // wait for power to stabilize + #endif + cli(); // check if eeprom has been initialized; abort if it hasn't uint8_t found = 0; @@ -87,6 +99,10 @@ uint8_t load_eeprom_wl() { } void save_eeprom_wl() { + #ifdef LED_ENABLE_PIN + delay_4ms(2); // wait for power to stabilize + #endif + cli(); // erase old state EEP_OFFSET_T offset = eep_wl_prev_offset; -- cgit v1.2.3 From 930752b496ad8a1d9f3db96184839022c16a5c7f Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 28 Feb 2020 02:06:53 -0700 Subject: went back to continuous lowpass because it had the best noise reduction (also, now treating smoothed ADC values as 11-bit, with the lowest 5 bits chopped off to eliminate noise) --- spaghetti-monster/fsm-adc.c | 124 ++++++++++++++++++++++++++------------------ spaghetti-monster/fsm-wdt.c | 2 +- 2 files changed, 74 insertions(+), 52 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 65669b3..59d4e5c 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -25,7 +25,7 @@ static inline void set_admux_therm() { #if (ATTINY == 1634) ADMUX = ADMUX_THERM; #elif (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) - ADMUX = ADMUX_THERM; + ADMUX = ADMUX_THERM | (1 << ADLAR); #elif (ATTINY == 841) // FIXME: not tested ADMUXA = ADMUXA_THERM; ADMUXB = ADMUXB_THERM; @@ -46,9 +46,9 @@ inline void set_admux_voltage() { #endif #elif (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) #ifdef USE_VOLTAGE_DIVIDER // 1.1V / pin7 - ADMUX = ADMUX_VOLTAGE_DIVIDER; + ADMUX = ADMUX_VOLTAGE_DIVIDER | (1 << ADLAR); #else // VCC / 1.1V reference - ADMUX = ADMUX_VCC; + ADMUX = ADMUX_VCC | (1 << ADLAR); #endif #elif (ATTINY == 841) // FIXME: not tested #ifdef USE_VOLTAGE_DIVIDER // 1.1V / pin7 @@ -88,7 +88,7 @@ inline void ADC_on() #endif #if (ATTINY == 1634) //ACSRA |= (1 << ACD); // turn off analog comparator to save power - //ADCSRB |= (1 << ADLAR); // left-adjust flag is here instead of ADMUX + ADCSRB |= (1 << ADLAR); // left-adjust flag is here instead of ADMUX #endif // enable, start, auto-retrigger, prescale ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | ADC_PRSCL; @@ -122,46 +122,42 @@ static inline uint8_t calc_voltage_divider(uint16_t value) { // Each full cycle runs ~4X per second with just voltage enabled, // or ~2X per second with voltage and temperature. #if defined(USE_LVP) && defined(USE_THERMAL_REGULATION) -#define ADC_CYCLES_PER_SECOND 2 +#define ADC_CYCLES_PER_SECOND 1 #else -#define ADC_CYCLES_PER_SECOND 4 +#define ADC_CYCLES_PER_SECOND 2 #endif // happens every time the ADC sampler finishes a measurement -// collects a rolling average of 64+ samples, which increases effective number -// of bits from 10 to about 16 (ish, probably more like 14 really) (64 was -// chosen because it's the largest sample size which allows the sum to still -// fit into a 16-bit integer, and for speed and size reasons, we want to avoid -// doing 32-bit math) ISR(ADC_vect) { - static uint32_t adc_sum; + if (adc_sample_count) { - // keep this moving along - adc_sample_count ++; + uint16_t m; // latest measurement + uint16_t s; // smoothed measurement + uint8_t channel = adc_channel; - // reset on first sample - // also, ignore first value since it's probably junk - if (1 == adc_sample_count) { - adc_sum = 0; - return; - } - // 2048 samples collected, save the result - else if (2050 == adc_sample_count) { - // save the latest result - adc_smooth[adc_channel] = adc_sum >> 5; - } - // add the latest measurement to the pile - else { - uint16_t m = ADC; - // add to the running total - adc_sum += m; // update the latest value - adc_raw[adc_channel] = m; + m = ADC; + adc_raw[channel] = m; + + // lowpass the value + //s = adc_smooth[channel]; // easier to read + uint16_t *v = adc_smooth + channel; // compiles smaller + s = *v; + if (m > s) { s++; } + if (m < s) { s--; } + //adc_smooth[channel] = s; + *v = s; + + // track what woke us up, and enable deferred logic + irq_adc = 1; + } - // track what woke us up, and enable deferred logic - irq_adc = 1; + // the next measurement isn't the first + //adc_sample_count = 1; + adc_sample_count ++; + } void adc_deferred() { @@ -171,7 +167,7 @@ void adc_deferred() { // real-world entropy makes this a true random, not pseudo // Why here instead of the ISR? Because it makes the time-critical ISR // code a few cycles faster and we don't need crypto-grade randomness. - pseudo_rand_seed += ADCL; + pseudo_rand_seed += (ADCL >> 6) + (ADCH << 2); #endif // the ADC triggers repeatedly when it's on, but we only need to run the @@ -237,9 +233,22 @@ static inline void ADC_voltage_handler() { uint16_t measurement; // latest ADC value - if (go_to_standby) measurement = adc_raw[0] << 6; + if (go_to_standby || (adc_smooth[0] < 255)) { + measurement = adc_raw[0]; + adc_smooth[0] = measurement; // no lowpass while asleep + } else measurement = adc_smooth[0]; + // values stair-step between intervals of 64, with random variations + // of 1 or 2 in either direction, so if we chop off the last 6 bits + // it'll flap between N and N-1... but if we add half an interval, + // the values should be really stable after right-alignment + // (instead of 99.98, 100.00, and 100.02, it'll hit values like + // 100.48, 100.50, and 100.52... which are stable when truncated) + //measurement += 32; + //measurement = (measurement + 16) >> 5; + measurement = (measurement + 16) & 0xffe0; // 1111 1111 1110 0000 + #ifdef USE_VOLTAGE_DIVIDER voltage = calc_voltage_divider(measurement); #else @@ -286,27 +295,35 @@ static inline void ADC_temperature_handler() { // N seconds between thermal regulation events #define TEMPERATURE_TIMER_START (THERMAL_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) - // latest 16-bit ADC reading - uint16_t measurement; - - if (! reset_thermal_history) { - // average of recent samples - measurement = adc_smooth[1] >> 1; - } else { // wipe out old data + if (reset_thermal_history) { // wipe out old data // don't keep resetting reset_thermal_history = 0; // ignore average, use latest sample - measurement = adc_raw[1] << 5; + uint16_t foo = adc_raw[1]; + adc_smooth[1] = foo; // forget any past measurements for(uint8_t i=0; i> 5; } + // latest 16-bit ADC reading + uint16_t measurement = adc_smooth[1]; + + // values stair-step between intervals of 64, with random variations + // of 1 or 2 in either direction, so if we chop off the last 6 bits + // it'll flap between N and N-1... but if we add half an interval, + // the values should be really stable after right-alignment + // (instead of 99.98, 100.00, and 100.02, it'll hit values like + // 100.48, 100.50, and 100.52... which are stable when truncated) + //measurement += 32; + measurement = (measurement + 16) >> 5; + //measurement = (measurement + 16) & 0xffe0; // 1111 1111 1110 0000 + // let the UI see the current temperature in C // Convert ADC units to Celsius (ish) - temperature = (measurement>>5) - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; + temperature = (measurement>>1) + THERM_CAL_OFFSET + (int16_t)therm_cal_offset - 275; // how much has the temperature changed between now and a few seconds ago? int16_t diff; @@ -320,22 +337,27 @@ static inline void ADC_temperature_handler() { uint16_t pt; // predicted temperature pt = measurement + (diff * THERM_LOOKAHEAD); + /* seems unnecessary; simply sending repeated warnings has a similar effect // P[I]D: average of recent measurements uint16_t avg = 0; for(uint8_t i=0; i>3); + */ // convert temperature limit from C to raw 16-bit ADC units // C = (ADC>>6) - 275 + THERM_CAL_OFFSET + therm_cal_offset; // ... so ... // (C + 275 - THERM_CAL_OFFSET - therm_cal_offset) << 6 = ADC; - uint16_t ceil = (therm_ceil + 275 - therm_cal_offset - THERM_CAL_OFFSET) << 5; + uint16_t ceil = (therm_ceil + 275 - therm_cal_offset - THERM_CAL_OFFSET) << 1; //uint16_t floor = ceil - (THERM_WINDOW_SIZE << 6); + /* average of I and D terms int16_t offset_pt, offset_avg; offset_pt = (pt - ceil) >> 1; offset_avg = (avg - ceil) >> 1; int16_t offset = offset_pt + offset_avg; //int16_t offset = (pt - ceil) + (avg - ceil); + */ + int16_t offset = pt - ceil; if (temperature_timer) { @@ -344,25 +366,25 @@ static inline void ADC_temperature_handler() { // Too hot? // (if it's too hot and not getting colder...) - if ((offset > 0) && (diff > (-1 << 4))) { + if ((offset > 0) && (diff > (-1))) { // reset counters temperature_timer = TEMPERATURE_TIMER_START; // how far above the ceiling? //int16_t howmuch = (offset >> 6) * THERM_RESPONSE_MAGNITUDE / 128; - int16_t howmuch = (offset >> 8); + int16_t howmuch = (offset >> 1); // send a warning emit(EV_temperature_high, howmuch); } // Too cold? // (if it's too cold and not getting warmer...) - else if ((offset < -(THERM_WINDOW_SIZE << 5)) - && (diff < (1 << 3))) { + else if ((offset < -(THERM_WINDOW_SIZE << 1)) + && (diff < (1))) { // reset counters temperature_timer = TEMPERATURE_TIMER_START; // how far below the floor? //int16_t howmuch = (((-offset) - (THERM_WINDOW_SIZE<<6)) >> 7) * THERM_WINDOW_SIZE / 128; - int16_t howmuch = ((-offset) - (THERM_WINDOW_SIZE<<5)) >> 8; + int16_t howmuch = ((-offset) - (THERM_WINDOW_SIZE<<1)) >> 1; // send a notification (unless voltage is low) // (LVP and underheat warnings fight each other) if (voltage > VOLTAGE_LOW) diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index 459010f..12aab7b 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -180,7 +180,7 @@ void WDT_inner() { #if defined(USE_LVP) || defined(USE_THERMAL_REGULATION) // start a new ADC measurement every 16 ticks adc_trigger ++; - if (0 == (adc_trigger & 15)) { + if (0 == (adc_trigger & 31)) { // in case we're in standby mode and the ADC is turned off if (go_to_standby) { //set_admux_voltage(); -- cgit v1.2.3 From 4d1c7a34fd00a4dd19e591ea0602f0f47f10d9f0 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 5 Mar 2020 17:51:27 -0700 Subject: initial support for Noctigon KR4 (not complete, but far enough that it installs and runs) New hardware support features: - allow using PCINT other than 0 (PCINT1, PCINT2, etc) - option to ignore voltage ADC while the button is pressed (because my prototype shorts the voltage divider to 0 while the button is down) --- spaghetti-monster/anduril/cfg-noctigon-kr4.h | 66 ++++++++++++++++++++++++++++ spaghetti-monster/fsm-adc.c | 6 +++ spaghetti-monster/fsm-pcint.c | 4 ++ 3 files changed, 76 insertions(+) create mode 100644 spaghetti-monster/anduril/cfg-noctigon-kr4.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4.h b/spaghetti-monster/anduril/cfg-noctigon-kr4.h new file mode 100644 index 0000000..87be78e --- /dev/null +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4.h @@ -0,0 +1,66 @@ +// Noctigon KR4 config options for Anduril +#include "hwdef-Noctigon_KR4.h" +// ATTINY: 1634 + +// this light has three aux LED channels: R, G, B +#define USE_AUX_RGB_LEDS +//#define USE_AUX_RGB_LEDS_WHILE_ON +//#define USE_INDICATOR_LED_WHILE_RAMPING +#define RGB_LED_OFF_DEFAULT 0x18 // low, voltage +#define RGB_LED_LOCKOUT_DEFAULT 0x37 // blinking, rainbow + +// enable blinking aux LEDs +#define TICK_DURING_STANDBY +#define STANDBY_TICK_SPEED 3 // every 0.128 s + + +// ../../bin/level_calc.py cube 1 150 7135 1 4 1300 +// (with max_pwm set to 1023) +#define RAMP_LENGTH 150 +#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,6,7,8,9,10,11,12,13,14,15,16,17,18,20,21,23,24,26,27,29,31,32,34,36,38,40,43,45,47,49,52,54,57,60,62,65,68,71,74,77,81,84,87,91,95,98,102,106,110,114,118,122,127,131,136,141,145,150,155,160,166,171,176,182,188,193,199,205,211,218,224,231,237,244,251,258,265,272,280,287,295,303,310,319,327,335,344,352,361,370,379,388,397,407,416,426,436,446,457,467,477,488,499,510,521,533,544,556,568,580,592,604,617,629,642,655,668,682,695,709,723,737,751,766,781,795,810,826,841,857,872,888,904,921,937,954,971,988,1005,1023 +#define MAX_1x7135 50 + +// the entire ramp is regulated; don't blink halfway up +#ifdef BLINK_AT_RAMP_MIDDLE +#undef BLINK_AT_RAMP_MIDDLE +#endif + +// don't slow down at low levels; this isn't that sort of light +// (it needs to stay at full speed for the 10-bit PWM to work) +#ifdef USE_DYNAMIC_UNDERCLOCKING +#undef USE_DYNAMIC_UNDERCLOCKING +#endif + +#define RAMP_SMOOTH_FLOOR 1 +#define RAMP_SMOOTH_CEIL 130 +// 10, 30, [50], 70, 90, 110, 130 +#define RAMP_DISCRETE_FLOOR 10 +#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL +#define RAMP_DISCRETE_STEPS 7 + +#define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR +#define MUGGLE_CEILING 70 + +// optional, makes initial turbo step-down faster so first peak isn't as hot +// the KR4 runs very very hot on turbo, so be extra careful +//#define THERM_HARD_TURBO_DROP + +// stop panicking at ~70% power or ~600 lm +#define THERM_FASTER_LEVEL 130 +// respond to thermal changes faster +#define THERMAL_WARNING_SECONDS 3 +#define THERMAL_UPDATE_SPEED 1 +#define THERM_PREDICTION_STRENGTH 4 + +// easier access to thermal config mode, for Noctigon +#define USE_TENCLICK_THERMAL_CONFIG + +// slow down party strobe; this driver can't pulse for 1ms or less +#define PARTY_STROBE_ONTIME 2 + +#define THERM_CAL_OFFSET 5 + +// attiny1634 has enough space to smooth out voltage readings +// (prevent the button from blinking during use) +//#define USE_VOLTAGE_LOWPASS + diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 2a3c5c6..2d8d01f 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -206,6 +206,12 @@ static inline void ADC_voltage_handler() { #define LVP_TIMER_START (VOLTAGE_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) // N seconds between LVP warnings #define LVP_LOWPASS_STRENGTH ADC_CYCLES_PER_SECOND // lowpass for one second + #ifdef NO_LVP_WHILE_BUTTON_PRESSED + // don't run if button is currently being held + // (because the button causes a reading of zero volts) + if (button_last_state) return; + #endif + uint16_t measurement = adc_values[0]; // latest 10-bit ADC reading #ifdef USE_VOLTAGE_LOWPASS diff --git a/spaghetti-monster/fsm-pcint.c b/spaghetti-monster/fsm-pcint.c index 1ba1c15..d362633 100644 --- a/spaghetti-monster/fsm-pcint.c +++ b/spaghetti-monster/fsm-pcint.c @@ -66,7 +66,11 @@ inline void PCINT_off() { //void button_change_interrupt() { #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 1634) //EMPTY_INTERRUPT(PCINT0_vect); +#ifdef PCINT_vect +ISR(PCINT_vect) { +#else ISR(PCINT0_vect) { +#endif irq_pcint = 1; } #else -- cgit v1.2.3 From 490630291c3fb10fc63801645116a73b4c7a5e73 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 6 Mar 2020 03:20:26 -0700 Subject: KR4: added FET channel, measured output, calibrated ramp --- spaghetti-monster/anduril/cfg-noctigon-kr4.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4.h b/spaghetti-monster/anduril/cfg-noctigon-kr4.h index 87be78e..8971fca 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4.h @@ -14,11 +14,19 @@ #define STANDBY_TICK_SPEED 3 // every 0.128 s -// ../../bin/level_calc.py cube 1 150 7135 1 4 1300 +// brightness w/ SST-20 4000K LEDs: +// 0/1023: 0.35 lm +// 1/1023: 2.56 lm +// max regulated: 1740 lm +// FET: ~3700 lm +// level_calc.py 3.0 2 150 7135 0 2.5 1740 FET 1 10 2565 // (with max_pwm set to 1023) +// (designed to hit max regulated at 130/150) #define RAMP_LENGTH 150 -#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,6,7,8,9,10,11,12,13,14,15,16,17,18,20,21,23,24,26,27,29,31,32,34,36,38,40,43,45,47,49,52,54,57,60,62,65,68,71,74,77,81,84,87,91,95,98,102,106,110,114,118,122,127,131,136,141,145,150,155,160,166,171,176,182,188,193,199,205,211,218,224,231,237,244,251,258,265,272,280,287,295,303,310,319,327,335,344,352,361,370,379,388,397,407,416,426,436,446,457,467,477,488,499,510,521,533,544,556,568,580,592,604,617,629,642,655,668,682,695,709,723,737,751,766,781,795,810,826,841,857,872,888,904,921,937,954,971,988,1005,1023 +#define PWM1_LEVELS 0,0,1,1,2,2,3,3,4,4,5,5,6,7,8,9,10,11,12,13,15,16,17,19,21,22,24,26,28,30,32,34,36,39,41,44,47,49,52,55,58,62,65,68,72,76,80,84,88,92,96,101,105,110,115,120,125,131,136,142,147,153,159,166,172,179,185,192,199,206,214,221,229,237,245,253,262,270,279,288,298,307,317,326,336,346,357,367,378,389,401,412,424,436,448,460,472,485,498,511,525,539,552,567,581,596,611,626,641,657,673,689,705,722,739,756,773,791,809,827,846,864,883,903,922,942,962,983,1003,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,83,130,177,225,273,323,372,423,474,526,578,632,686,740,795,851,908,965,1023 #define MAX_1x7135 50 +#define MAX_Nx7135 130 // the entire ramp is regulated; don't blink halfway up #ifdef BLINK_AT_RAMP_MIDDLE -- cgit v1.2.3 From 99d1551da9cfba76840ad69cf337728dd08b3f3d Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 6 Mar 2020 03:32:30 -0700 Subject: FET ramp was too steep; slowed it down by 50% (20 steps -> 30 steps) --- spaghetti-monster/anduril/cfg-noctigon-kr4.h | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4.h b/spaghetti-monster/anduril/cfg-noctigon-kr4.h index 8971fca..7771cd4 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4.h @@ -19,14 +19,13 @@ // 1/1023: 2.56 lm // max regulated: 1740 lm // FET: ~3700 lm -// level_calc.py 3.0 2 150 7135 0 2.5 1740 FET 1 10 2565 -// (with max_pwm set to 1023) -// (designed to hit max regulated at 130/150) +// maxreg at 130: level_calc.py cube 2 150 7135 0 2.5 1740 FET 1 10 2565 +// maxreg at 120: level_calc.py cube 2 150 7135 0 2.5 1740 FET 1 10 3190 #define RAMP_LENGTH 150 -#define PWM1_LEVELS 0,0,1,1,2,2,3,3,4,4,5,5,6,7,8,9,10,11,12,13,15,16,17,19,21,22,24,26,28,30,32,34,36,39,41,44,47,49,52,55,58,62,65,68,72,76,80,84,88,92,96,101,105,110,115,120,125,131,136,142,147,153,159,166,172,179,185,192,199,206,214,221,229,237,245,253,262,270,279,288,298,307,317,326,336,346,357,367,378,389,401,412,424,436,448,460,472,485,498,511,525,539,552,567,581,596,611,626,641,657,673,689,705,722,739,756,773,791,809,827,846,864,883,903,922,942,962,983,1003,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,37,83,130,177,225,273,323,372,423,474,526,578,632,686,740,795,851,908,965,1023 -#define MAX_1x7135 50 -#define MAX_Nx7135 130 +#define PWM1_LEVELS 0,0,1,1,2,2,3,3,4,4,5,6,7,8,9,10,11,13,14,15,17,19,20,22,24,26,28,30,33,35,38,40,43,46,49,52,55,59,62,66,70,74,78,82,86,91,96,100,105,111,116,121,127,133,139,145,151,158,165,172,179,186,193,201,209,217,225,234,243,251,261,270,280,289,299,310,320,331,342,353,364,376,388,400,412,425,438,451,464,478,492,506,521,536,551,566,582,597,614,630,647,664,681,699,717,735,754,772,792,811,831,851,871,892,913,935,956,978,1001,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,51,79,109,138,168,198,229,260,292,324,357,390,423,457,492,527,562,598,634,671,708,746,784,822,861,901,941,982,1023 +#define MAX_1x7135 46 +#define MAX_Nx7135 120 // the entire ramp is regulated; don't blink halfway up #ifdef BLINK_AT_RAMP_MIDDLE @@ -40,21 +39,21 @@ #endif #define RAMP_SMOOTH_FLOOR 1 -#define RAMP_SMOOTH_CEIL 130 -// 10, 30, [50], 70, 90, 110, 130 +#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 #define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR -#define MUGGLE_CEILING 70 +#define MUGGLE_CEILING 65 // optional, makes initial turbo step-down faster so first peak isn't as hot // the KR4 runs very very hot on turbo, so be extra careful //#define THERM_HARD_TURBO_DROP // stop panicking at ~70% power or ~600 lm -#define THERM_FASTER_LEVEL 130 +#define THERM_FASTER_LEVEL 120 // respond to thermal changes faster #define THERMAL_WARNING_SECONDS 3 #define THERMAL_UPDATE_SPEED 1 -- cgit v1.2.3 From 7110fdbae15c6303eb405705bf0b319fc1381a4f Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 13 Mar 2020 18:06:27 -0600 Subject: tried to make thermal code a bit less twitchy... it regulates really fast on D4, but once it's stable, the adjustments are too large --- spaghetti-monster/anduril/anduril.c | 13 ++++++++----- spaghetti-monster/fsm-adc.c | 17 ++++++++++------- spaghetti-monster/fsm-wdt.c | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 69dd118..469d0d8 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -963,7 +963,7 @@ uint8_t steady_state(Event event, uint16_t arg) { if (diff) { uint16_t ticks_per_adjust = 256; if (diff < 0) { - diff = -diff; + //diff = -diff; if (actual_level > THERM_FASTER_LEVEL) { #ifdef THERM_HARD_TURBO_DROP ticks_per_adjust >>= 2; @@ -976,7 +976,8 @@ uint8_t steady_state(Event event, uint16_t arg) { } while (diff) { ticks_per_adjust >>= 1; - diff >>= 1; + //diff >>= 1; + diff /= 2; // because shifting produces weird behavior } if (ticks_since_adjust > ticks_per_adjust) { @@ -1040,9 +1041,11 @@ uint8_t steady_state(Event event, uint16_t arg) { // temperature is within target window // (so stop trying to adjust output) else if (event == EV_temperature_okay) { - // if we're still adjusting output... stop - gradual_target = actual_level; - //set_level_gradually(actual_level); + // if we're still adjusting output... stop after the current step + if (gradual_target > actual_level) + gradual_target = actual_level + 1; + else if (gradual_target < actual_level) + gradual_target = actual_level - 1; return MISCHIEF_MANAGED; } #endif // ifdef USE_SET_LEVEL_GRADUALLY diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 59d4e5c..358ff26 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -288,6 +288,9 @@ static inline void ADC_temperature_handler() { // acceptable temperature window size in C #define THERM_WINDOW_SIZE 3 + // TODO: make this configurable per build target? + // (shorter time for hosts with a lower power-to-mass ratio) + // (because then it'll have smaller responses) #define NUM_TEMP_HISTORY_STEPS 8 // don't change; it'll break stuff static uint8_t history_step = 0; static uint16_t temperature_history[NUM_TEMP_HISTORY_STEPS]; @@ -365,21 +368,21 @@ static inline void ADC_temperature_handler() { } else { // it has been long enough since the last warning // Too hot? - // (if it's too hot and not getting colder...) - if ((offset > 0) && (diff > (-1))) { + // (if it's too hot and still getting warmer...) + if ((offset > 0) && (diff > 0)) { // reset counters temperature_timer = TEMPERATURE_TIMER_START; // how far above the ceiling? //int16_t howmuch = (offset >> 6) * THERM_RESPONSE_MAGNITUDE / 128; - int16_t howmuch = (offset >> 1); + //int16_t howmuch = (offset >> 1); + int16_t howmuch = offset; // send a warning emit(EV_temperature_high, howmuch); } // Too cold? - // (if it's too cold and not getting warmer...) - else if ((offset < -(THERM_WINDOW_SIZE << 1)) - && (diff < (1))) { + // (if it's too cold and still getting colder...) + else if ((offset < -(THERM_WINDOW_SIZE << 1)) && (diff < 0)) { // reset counters temperature_timer = TEMPERATURE_TIMER_START; // how far below the floor? @@ -387,7 +390,7 @@ static inline void ADC_temperature_handler() { int16_t howmuch = ((-offset) - (THERM_WINDOW_SIZE<<1)) >> 1; // send a notification (unless voltage is low) // (LVP and underheat warnings fight each other) - if (voltage > VOLTAGE_LOW) + if (voltage > (VOLTAGE_LOW + 1)) emit(EV_temperature_low, howmuch); } diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index 12aab7b..1d630a4 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -178,7 +178,7 @@ void WDT_inner() { #endif #if defined(USE_LVP) || defined(USE_THERMAL_REGULATION) - // start a new ADC measurement every 16 ticks + // enable the deferred ADC handler every 32 ticks adc_trigger ++; if (0 == (adc_trigger & 31)) { // in case we're in standby mode and the ADC is turned off -- cgit v1.2.3 From ccc82a57904097ffd1c1225ef5a8f0082f7046d8 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 15 Mar 2020 19:21:37 -0600 Subject: replaced temperature_timer (which wasn't even being used) with a variable delay between warnings, so large warnings can remain frequent while small warnings are separated by more time, based on a cumulative error counter which must pass a threshold before the next warning is sent (this is producing good test results so far on D4v2 and D4Sv2) --- spaghetti-monster/fsm-adc.c | 70 ++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 27 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 358ff26..93c58f1 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -280,6 +280,10 @@ static inline void ADC_temperature_handler() { #ifndef THERM_LOOKAHEAD #define THERM_LOOKAHEAD 4 // can be tweaked per build target #endif + // reduce frequency of minor warnings + #ifndef THERM_NEXT_WARNING_THRESHOLD + #define THERM_NEXT_WARNING_THRESHOLD 24 + #endif // fine-grained adjustment // how proportional should the adjustments be? (not used yet) #ifndef THERM_RESPONSE_MAGNITUDE @@ -294,7 +298,7 @@ static inline void ADC_temperature_handler() { #define NUM_TEMP_HISTORY_STEPS 8 // don't change; it'll break stuff static uint8_t history_step = 0; static uint16_t temperature_history[NUM_TEMP_HISTORY_STEPS]; - static uint8_t temperature_timer = 0; + static int8_t warning_threshold = 0; // N seconds between thermal regulation events #define TEMPERATURE_TIMER_START (THERMAL_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) @@ -363,15 +367,17 @@ static inline void ADC_temperature_handler() { int16_t offset = pt - ceil; - if (temperature_timer) { - temperature_timer --; - } else { // it has been long enough since the last warning + //int16_t below = offset + (THERM_WINDOW_SIZE<<1); + + // Too hot? + // (if it's too hot and still getting warmer...) + if ((offset > 0) && (diff > 0)) { + // accumulated error isn't big enough yet to send a warning + if (warning_threshold > 0) { + warning_threshold -= offset; + } else { // error is big enough; send a warning + warning_threshold = THERM_NEXT_WARNING_THRESHOLD - offset; - // Too hot? - // (if it's too hot and still getting warmer...) - if ((offset > 0) && (diff > 0)) { - // reset counters - temperature_timer = TEMPERATURE_TIMER_START; // how far above the ceiling? //int16_t howmuch = (offset >> 6) * THERM_RESPONSE_MAGNITUDE / 128; //int16_t howmuch = (offset >> 1); @@ -379,32 +385,42 @@ static inline void ADC_temperature_handler() { // send a warning emit(EV_temperature_high, howmuch); } + } + + // Too cold? + // (if it's too cold and still getting colder...) + // the temperature is this far below the floor: + #define BELOW (offset + (THERM_WINDOW_SIZE<<1)) + //else if ((offset < -(THERM_WINDOW_SIZE << 1)) && (diff < 0)) { + else if ((BELOW < 0) && (diff < 0)) { + // accumulated error isn't big enough yet to send a warning + if (warning_threshold < 0) { + //warning_threshold += ((THERM_WINDOW_SIZE<<1) - offset); + //warning_threshold -= (offset + (THERM_WINDOW_SIZE<<1)); + warning_threshold -= BELOW; + } else { // error is big enough; send a warning + //warning_threshold = (-THERM_NEXT_WARNING_THRESHOLD) - (offset + (THERM_WINDOW_SIZE<<1)); + warning_threshold = (-THERM_NEXT_WARNING_THRESHOLD) - BELOW; - // Too cold? - // (if it's too cold and still getting colder...) - else if ((offset < -(THERM_WINDOW_SIZE << 1)) && (diff < 0)) { - // reset counters - temperature_timer = TEMPERATURE_TIMER_START; // how far below the floor? //int16_t howmuch = (((-offset) - (THERM_WINDOW_SIZE<<6)) >> 7) * THERM_WINDOW_SIZE / 128; - int16_t howmuch = ((-offset) - (THERM_WINDOW_SIZE<<1)) >> 1; + //int16_t howmuch = ((-offset) - (THERM_WINDOW_SIZE<<1)) >> 1; + int16_t howmuch = (-BELOW) >> 1; // send a notification (unless voltage is low) // (LVP and underheat warnings fight each other) if (voltage > (VOLTAGE_LOW + 1)) emit(EV_temperature_low, howmuch); } - - // Goldilocks? - // (temperature is within target window, or at least heading toward it) - else { - // reset counters - temperature_timer = TEMPERATURE_TIMER_START; - // send a notification (unless voltage is low) - // (LVP and temp-okay events fight each other) - if (voltage > VOLTAGE_LOW) - emit(EV_temperature_okay, 0); - } - + } + #undef BELOW + + // Goldilocks? + // (temperature is within target window, or at least heading toward it) + else { + // send a notification (unless voltage is low) + // (LVP and temp-okay events fight each other) + if (voltage > VOLTAGE_LOW) + emit(EV_temperature_okay, 0); } } #endif -- cgit v1.2.3 From 4c1d17f4604bf38140381649a45a3c7c109ee97a Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 15 Mar 2020 19:56:50 -0600 Subject: removed dead comments and dead code --- spaghetti-monster/fsm-adc.c | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 93c58f1..725902f 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -299,8 +299,6 @@ static inline void ADC_temperature_handler() { static uint8_t history_step = 0; static uint16_t temperature_history[NUM_TEMP_HISTORY_STEPS]; static int8_t warning_threshold = 0; - // N seconds between thermal regulation events - #define TEMPERATURE_TIMER_START (THERMAL_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) if (reset_thermal_history) { // wipe out old data // don't keep resetting @@ -344,31 +342,13 @@ static inline void ADC_temperature_handler() { uint16_t pt; // predicted temperature pt = measurement + (diff * THERM_LOOKAHEAD); - /* seems unnecessary; simply sending repeated warnings has a similar effect - // P[I]D: average of recent measurements - uint16_t avg = 0; - for(uint8_t i=0; i>3); - */ - // convert temperature limit from C to raw 16-bit ADC units // C = (ADC>>6) - 275 + THERM_CAL_OFFSET + therm_cal_offset; // ... so ... // (C + 275 - THERM_CAL_OFFSET - therm_cal_offset) << 6 = ADC; uint16_t ceil = (therm_ceil + 275 - therm_cal_offset - THERM_CAL_OFFSET) << 1; - //uint16_t floor = ceil - (THERM_WINDOW_SIZE << 6); - /* average of I and D terms - int16_t offset_pt, offset_avg; - offset_pt = (pt - ceil) >> 1; - offset_avg = (avg - ceil) >> 1; - int16_t offset = offset_pt + offset_avg; - //int16_t offset = (pt - ceil) + (avg - ceil); - */ int16_t offset = pt - ceil; - - //int16_t below = offset + (THERM_WINDOW_SIZE<<1); - // Too hot? // (if it's too hot and still getting warmer...) if ((offset > 0) && (diff > 0)) { @@ -379,8 +359,7 @@ static inline void ADC_temperature_handler() { warning_threshold = THERM_NEXT_WARNING_THRESHOLD - offset; // how far above the ceiling? - //int16_t howmuch = (offset >> 6) * THERM_RESPONSE_MAGNITUDE / 128; - //int16_t howmuch = (offset >> 1); + //int16_t howmuch = offset * THERM_RESPONSE_MAGNITUDE / 128; int16_t howmuch = offset; // send a warning emit(EV_temperature_high, howmuch); @@ -391,20 +370,15 @@ static inline void ADC_temperature_handler() { // (if it's too cold and still getting colder...) // the temperature is this far below the floor: #define BELOW (offset + (THERM_WINDOW_SIZE<<1)) - //else if ((offset < -(THERM_WINDOW_SIZE << 1)) && (diff < 0)) { else if ((BELOW < 0) && (diff < 0)) { // accumulated error isn't big enough yet to send a warning if (warning_threshold < 0) { - //warning_threshold += ((THERM_WINDOW_SIZE<<1) - offset); - //warning_threshold -= (offset + (THERM_WINDOW_SIZE<<1)); warning_threshold -= BELOW; } else { // error is big enough; send a warning - //warning_threshold = (-THERM_NEXT_WARNING_THRESHOLD) - (offset + (THERM_WINDOW_SIZE<<1)); warning_threshold = (-THERM_NEXT_WARNING_THRESHOLD) - BELOW; // how far below the floor? - //int16_t howmuch = (((-offset) - (THERM_WINDOW_SIZE<<6)) >> 7) * THERM_WINDOW_SIZE / 128; - //int16_t howmuch = ((-offset) - (THERM_WINDOW_SIZE<<1)) >> 1; + // int16_t howmuch = ((-BELOW) >> 1) * THERM_RESPONSE_MAGNITUDE / 128; int16_t howmuch = (-BELOW) >> 1; // send a notification (unless voltage is low) // (LVP and underheat warnings fight each other) -- cgit v1.2.3 From eccf9c3d4df44c5a8fd88571ee2aaeca70975926 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 15 Mar 2020 19:58:35 -0600 Subject: the ADC sample count doesn't need to be 16-bit any more, and isn't really a count any more... ... just a boolean flag for whether this is the first sample or a later sample (so I changed it and reduced the ROM size by ~28 bytes) --- spaghetti-monster/fsm-adc.c | 5 +++-- spaghetti-monster/fsm-adc.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 725902f..c382a8a 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -155,8 +155,9 @@ ISR(ADC_vect) { } // the next measurement isn't the first - //adc_sample_count = 1; - adc_sample_count ++; + adc_sample_count = 1; + // rollover doesn't really matter + //adc_sample_count ++; } diff --git a/spaghetti-monster/fsm-adc.h b/spaghetti-monster/fsm-adc.h index 7acb505..6283b2c 100644 --- a/spaghetti-monster/fsm-adc.h +++ b/spaghetti-monster/fsm-adc.h @@ -40,7 +40,7 @@ #endif volatile uint8_t irq_adc = 0; // ADC interrupt happened? -uint16_t adc_sample_count = 0; // skip the first sample; it's junk +uint8_t adc_sample_count = 0; // skip the first sample; it's junk uint8_t adc_channel = 0; // 0=voltage, 1=temperature uint16_t adc_raw[2]; // last ADC measurements (0=voltage, 1=temperature) uint16_t adc_smooth[2]; // lowpassed ADC measurements (0=voltage, 1=temperature) -- cgit v1.2.3 From 79c9e662b98bf4219de9419eb2ccb171f80ef12b Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 16 Mar 2020 00:11:02 -0600 Subject: reduced regulation jitter by biasing errors toward zero by a constant amount, which mostly impacts small errors (and reduces jitter during the flat phase of regulation) while leaving large errors pretty much unaffected... also, made acceptable thermal window smaller to make up for this new extra tolerance --- spaghetti-monster/fsm-adc.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index c382a8a..dd43cb9 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -291,7 +291,7 @@ static inline void ADC_temperature_handler() { #define THERM_RESPONSE_MAGNITUDE 128 #endif // acceptable temperature window size in C - #define THERM_WINDOW_SIZE 3 + #define THERM_WINDOW_SIZE 2 // TODO: make this configurable per build target? // (shorter time for hosts with a lower power-to-mass ratio) @@ -350,6 +350,19 @@ static inline void ADC_temperature_handler() { uint16_t ceil = (therm_ceil + 275 - therm_cal_offset - THERM_CAL_OFFSET) << 1; int16_t offset = pt - ceil; + // bias small errors toward zero, while leaving large errors mostly unaffected + // (a diff of 1 C is 2 ADC units, * 4 for therm lookahead, so it becomes 8) + // (but a diff of 1 C should only send a warning of magnitude 1) + // (this also makes it only respond to small errors at the time the error + // happened, not after the temperature has stabilized) + for(uint8_t foo=0; foo<5; foo++) { + if (offset > 0) { + offset --; + } else if (offset < 0) { + offset ++; + } + } + // Too hot? // (if it's too hot and still getting warmer...) if ((offset > 0) && (diff > 0)) { -- cgit v1.2.3 From 6e7884cf5b4756ffba9f6dc9dd1fb94184779bf1 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 16 Mar 2020 00:13:44 -0600 Subject: cleaned up WDT ADC timer code slightly, and removed a bit of redundant code --- spaghetti-monster/fsm-wdt.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index 1d630a4..9858e09 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -111,7 +111,7 @@ void WDT_inner() { #ifdef TICK_DURING_STANDBY // handle standby mode specially if (go_to_standby) { - // emit a halfsleep tick, and process it + // emit a sleep tick, and process it emit(EV_sleep_tick, ticks_since_last); process_emissions(); @@ -121,7 +121,7 @@ void WDT_inner() { // stop here, usually... but proceed often enough for sleep LVP to work if (0 != (ticks_since_last & 0x3f)) return; - adc_trigger = 255; // make sure a measurement will happen + adc_trigger = 0; // make sure a measurement will happen ADC_on(); // enable ADC voltage measurement functions temporarily #endif } @@ -178,18 +178,20 @@ void WDT_inner() { #endif #if defined(USE_LVP) || defined(USE_THERMAL_REGULATION) - // enable the deferred ADC handler every 32 ticks - adc_trigger ++; - if (0 == (adc_trigger & 31)) { + // enable the deferred ADC handler once in a while + if (! adc_trigger) { + /* redundant; it was already turned on earlier in this function // in case we're in standby mode and the ADC is turned off if (go_to_standby) { //set_admux_voltage(); ADC_on(); } + */ ADC_start_measurement(); - // allow regulation logic to run adc_deferred_enable = 1; } + // timing for the ADC handler is every 32 ticks (~2Hz) + adc_trigger = (adc_trigger + 1) & 31; #endif } -- cgit v1.2.3 From 46e0f50a224c300b7e66ef00719edc0cef1f4c8d Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 16 Mar 2020 00:15:19 -0600 Subject: deleted commented-out WDT code from previous revision (had only saved it so there would be a note in history about why it's gone) --- spaghetti-monster/fsm-wdt.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c index 9858e09..94266c1 100644 --- a/spaghetti-monster/fsm-wdt.c +++ b/spaghetti-monster/fsm-wdt.c @@ -180,13 +180,6 @@ void WDT_inner() { #if defined(USE_LVP) || defined(USE_THERMAL_REGULATION) // enable the deferred ADC handler once in a while if (! adc_trigger) { - /* redundant; it was already turned on earlier in this function - // in case we're in standby mode and the ADC is turned off - if (go_to_standby) { - //set_admux_voltage(); - ADC_on(); - } - */ ADC_start_measurement(); adc_deferred_enable = 1; } -- cgit v1.2.3 From a9dfc872aab50767a2e7749b70e9ed6c61e579cb Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 16 Mar 2020 02:45:25 -0600 Subject: added FETless KR4 build target, calibrated other KR4 therm faster level better --- spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h | 45 ++++++++++++++++++++++ spaghetti-monster/anduril/cfg-noctigon-kr4.h | 4 +- 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h b/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h new file mode 100644 index 0000000..66177bf --- /dev/null +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h @@ -0,0 +1,45 @@ +// Noctigon KR4 (fetless) config options for Anduril +#include "cfg-noctigon-kr4.h" +// ATTINY: 1634 + +// brightness w/ SST-20 4000K LEDs: +// 0/1023: 0.35 lm +// 1/1023: 2.56 lm +// max regulated: 1740 lm +// level_calc.py 3.0 1 150 7135 0 5 1740 +#undef PWM_CHANNELS +#define PWM_CHANNELS 1 +#define RAMP_LENGTH 150 +#undef PWM1_LEVELS +#define PWM1_LEVELS 0,0,1,1,2,2,3,3,4,4,5,5,6,7,8,9,10,11,12,13,15,16,17,18,20,21,23,24,26,27,29,31,33,35,37,39,41,43,45,48,50,53,55,58,61,63,66,69,72,75,79,82,85,89,92,96,100,104,108,112,116,120,125,129,134,138,143,148,153,158,163,169,174,180,185,191,197,203,209,215,222,228,235,242,248,255,263,270,277,285,292,300,308,316,324,333,341,350,359,368,377,386,395,405,414,424,434,444,454,465,475,486,497,508,519,531,542,554,566,578,590,603,615,628,641,654,667,680,694,708,722,736,750,765,779,794,809,825,840,856,872,888,904,920,937,954,971,988,1005,1023 +#undef PWM2_LEVELS +#undef MAX_1x7135 +#define MAX_1x7135 50 +#undef MAX_Nx7135 + +#undef RAMP_SMOOTH_FLOOR +#undef RAMP_SMOOTH_CEIL +#undef RAMP_DISCRETE_FLOOR +#undef RAMP_DISCRETE_CEIL +#undef RAMP_DISCRETE_STEPS + +#define RAMP_SMOOTH_FLOOR 1 +#define RAMP_SMOOTH_CEIL 130 +// 10, 30, [50], 70, 90, 110, 130 (plus [150] on turbo) +#define RAMP_DISCRETE_FLOOR 10 +#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL +#define RAMP_DISCRETE_STEPS 7 + +#undef MUGGLE_FLOOR +#undef MUGGLE_CEILING +#define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR +#define MUGGLE_CEILING 70 + +// stop panicking at ~70% power or ~1200 lm +#undef THERM_FASTER_LEVEL +#define THERM_FASTER_LEVEL 130 +// 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-noctigon-kr4.h b/spaghetti-monster/anduril/cfg-noctigon-kr4.h index 7771cd4..9b810ab 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4.h @@ -52,8 +52,8 @@ // the KR4 runs very very hot on turbo, so be extra careful //#define THERM_HARD_TURBO_DROP -// stop panicking at ~70% power or ~600 lm -#define THERM_FASTER_LEVEL 120 +// stop panicking at ~25% power or ~1000 lm +#define THERM_FASTER_LEVEL 100 // respond to thermal changes faster #define THERMAL_WARNING_SECONDS 3 #define THERMAL_UPDATE_SPEED 1 -- cgit v1.2.3 From 84f9a0c9daf991b23d665a5dffdb3b76e6753491 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 16 Mar 2020 03:17:14 -0600 Subject: increased blink speed slightly, and added a library function to blink out 16-bit numbers --- spaghetti-monster/fsm-misc.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-misc.c b/spaghetti-monster/fsm-misc.c index 8da7b5b..152f047 100644 --- a/spaghetti-monster/fsm-misc.c +++ b/spaghetti-monster/fsm-misc.c @@ -46,19 +46,41 @@ uint8_t blink_digit(uint8_t num) { //StatePtr old_state = current_state; // "zero" digit gets a single short blink - uint8_t ontime = BLINK_SPEED * 2 / 10; + uint8_t ontime = BLINK_SPEED * 2 / 12; if (!num) { ontime = 8; num ++; } for (; num>0; num--) { set_level(BLINK_BRIGHTNESS); nice_delay_ms(ontime); set_level(0); - nice_delay_ms(BLINK_SPEED * 3 / 10); + nice_delay_ms(BLINK_SPEED * 3 / 12); } - return nice_delay_ms(BLINK_SPEED * 5 / 10); + return nice_delay_ms(BLINK_SPEED * 8 / 12); } #endif +#ifdef USE_BLINK_BIG_NUM +uint8_t blink_big_num(uint16_t num) { + uint16_t digits[] = { 10000, 1000, 100, 10, 1 }; + uint8_t started = 0; + for (uint8_t digit=0; digit= scale) { + started = 1; + } + if (started) { + uint8_t digit = 0; + while (num >= scale) { + num -= scale; + digit ++; + } + if (! blink_digit(digit)) return 0; + } + } + + return nice_delay_ms(1000); +} +#endif #ifdef USE_BLINK_NUM uint8_t blink_num(uint8_t num) { //StatePtr old_state = current_state; -- cgit v1.2.3 From 49f1b5ccd2033109814b99ea4650375e8f33a6be Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 16 Mar 2020 03:19:42 -0600 Subject: merged some misc fixes from pakutrai, cleaned up comments, removed unused symbols --- spaghetti-monster/anduril/anduril.c | 10 ++++++++-- spaghetti-monster/anduril/cfg-emisar-d18.h | 2 -- spaghetti-monster/anduril/cfg-emisar-d4.h | 4 ---- spaghetti-monster/anduril/cfg-emisar-d4s.h | 5 ----- spaghetti-monster/anduril/cfg-emisar-d4sv2.h | 14 -------------- spaghetti-monster/anduril/cfg-emisar-d4v2.h | 12 ------------ spaghetti-monster/anduril/cfg-ff-pl47.h | 5 ----- spaghetti-monster/anduril/cfg-ff-pl47g2.h | 5 ----- spaghetti-monster/anduril/cfg-ff-rot66.h | 3 --- spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h | 5 ----- spaghetti-monster/anduril/cfg-sofirn-sp36.h | 7 ------- spaghetti-monster/fsm-adc.c | 5 +++-- spaghetti-monster/fsm-adc.h | 12 +++--------- spaghetti-monster/fsm-standby.c | 4 ---- spaghetti-monster/spaghetti-monster.txt | 12 ++++-------- 15 files changed, 18 insertions(+), 87 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 469d0d8..bc2f9c6 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -22,7 +22,7 @@ // Anduril config file name (set it here or define it at the gcc command line) //#define CONFIGFILE cfg-blf-q8.h -#define USE_LVP // FIXME: won't build when this option is turned off +#define USE_LVP // parameters for this defined below or per-driver #define USE_THERMAL_REGULATION @@ -275,6 +275,7 @@ void sos_blink(uint8_t num, uint8_t dah); uint8_t battcheck_state(Event event, uint16_t arg); #endif #ifdef USE_THERMAL_REGULATION +#define USE_BLINK_NUM uint8_t tempcheck_state(Event event, uint16_t arg); uint8_t thermal_config_state(Event event, uint16_t arg); #endif @@ -497,6 +498,7 @@ volatile uint8_t beacon_seconds = 2; #endif #ifdef USE_VERSION_CHECK +#define USE_BLINK_DIGIT #include "version.h" const PROGMEM uint8_t version_number[] = VERSION_NUMBER; uint8_t version_check_state(Event event, uint16_t arg); @@ -1585,11 +1587,13 @@ uint8_t tempcheck_state(Event event, uint16_t arg) { set_state(off_state, 0); return MISCHIEF_MANAGED; } + #ifdef USE_BATTCHECK // 2 clicks: battcheck mode else if (event == EV_2clicks) { set_state(battcheck_state, 0); return MISCHIEF_MANAGED; } + #endif // 4 clicks: thermal config mode else if (event == EV_4clicks) { push_state(thermal_config_state, 0); @@ -1615,7 +1619,7 @@ uint8_t beacon_state(Event event, uint16_t arg) { set_state(sos_state, 0); #elif defined(USE_THERMAL_REGULATION) set_state(tempcheck_state, 0); - #else + #elif defined(USE_BATTCHECK) set_state(battcheck_state, 0); #endif return MISCHIEF_MANAGED; @@ -1997,6 +2001,7 @@ uint8_t muggle_state(Event event, uint16_t arg) { return MISCHIEF_MANAGED; } #endif + #ifdef USE_LVP // low voltage is handled specially in muggle mode else if(event == EV_voltage_low) { uint8_t lvl = (actual_level >> 1) + (actual_level >> 2); @@ -2007,6 +2012,7 @@ uint8_t muggle_state(Event event, uint16_t arg) { } return MISCHIEF_MANAGED; } + #endif return EVENT_NOT_HANDLED; } diff --git a/spaghetti-monster/anduril/cfg-emisar-d18.h b/spaghetti-monster/anduril/cfg-emisar-d18.h index 16fbacd..155a747 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d18.h +++ b/spaghetti-monster/anduril/cfg-emisar-d18.h @@ -42,5 +42,3 @@ // 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 diff --git a/spaghetti-monster/anduril/cfg-emisar-d4.h b/spaghetti-monster/anduril/cfg-emisar-d4.h index c86a534..501b9c7 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4.h @@ -24,8 +24,4 @@ // 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 6fe95a6..88465da 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4s.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4s.h @@ -42,8 +42,3 @@ #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-d4sv2.h b/spaghetti-monster/anduril/cfg-emisar-d4sv2.h index c47e774..c578c4a 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4sv2.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4sv2.h @@ -42,16 +42,6 @@ // stop panicking at ~50% power or ~2000 lm #define THERM_FASTER_LEVEL 130 -// no need to be extra-careful on this light -#ifdef THERM_HARD_TURBO_DROP -#undef THERM_HARD_TURBO_DROP -#endif - -// respond to thermal changes faster -#define THERMAL_WARNING_SECONDS 3 -#define THERMAL_UPDATE_SPEED 2 -#define THERM_PREDICTION_STRENGTH 4 - // easier access to thermal config mode, for Emisar #define USE_TENCLICK_THERMAL_CONFIG @@ -61,7 +51,3 @@ // seems relevant on attiny1634 #define THERM_CAL_OFFSET 5 - -// attiny1634 has enough space to smooth out voltage readings -#define USE_VOLTAGE_LOWPASS - diff --git a/spaghetti-monster/anduril/cfg-emisar-d4v2.h b/spaghetti-monster/anduril/cfg-emisar-d4v2.h index 3da877e..241ca7e 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4v2.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4v2.h @@ -37,22 +37,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 - -// attiny1634 has enough space to smooth out voltage readings -#define USE_VOLTAGE_LOWPASS diff --git a/spaghetti-monster/anduril/cfg-ff-pl47.h b/spaghetti-monster/anduril/cfg-ff-pl47.h index 7a81c25..e6907c1 100644 --- a/spaghetti-monster/anduril/cfg-ff-pl47.h +++ b/spaghetti-monster/anduril/cfg-ff-pl47.h @@ -61,11 +61,6 @@ // regulate down faster when the FET is active, slower otherwise #define THERM_FASTER_LEVEL 135 // throttle back faster when high -// play it safe, don't try to regulate above the recommended safe level -#ifdef THERM_HARD_TURBO_DROP -#undef THERM_HARD_TURBO_DROP -#endif - // don't do this #undef BLINK_AT_RAMP_MIDDLE #undef BLINK_AT_RAMP_CEILING diff --git a/spaghetti-monster/anduril/cfg-ff-pl47g2.h b/spaghetti-monster/anduril/cfg-ff-pl47g2.h index d5dd79d..cab008c 100644 --- a/spaghetti-monster/anduril/cfg-ff-pl47g2.h +++ b/spaghetti-monster/anduril/cfg-ff-pl47g2.h @@ -49,11 +49,6 @@ // regulate down faster when the FET is active, slower otherwise #define THERM_FASTER_LEVEL 135 // throttle back faster when high -// hard drop doesn't seem to be needed on this light -#ifdef THERM_HARD_TURBO_DROP -#undef THERM_HARD_TURBO_DROP -#endif - // don't do this #undef BLINK_AT_RAMP_MIDDLE #undef BLINK_AT_RAMP_CEILING diff --git a/spaghetti-monster/anduril/cfg-ff-rot66.h b/spaghetti-monster/anduril/cfg-ff-rot66.h index 2a90343..a87b66d 100644 --- a/spaghetti-monster/anduril/cfg-ff-rot66.h +++ b/spaghetti-monster/anduril/cfg-ff-rot66.h @@ -38,9 +38,6 @@ // regulate down faster when the FET is active, slower otherwise #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 - // don't do this #undef BLINK_AT_RAMP_MIDDLE #undef BLINK_AT_RAMP_CEILING diff --git a/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h b/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h index bbf751b..28c77c2 100644 --- a/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h +++ b/spaghetti-monster/anduril/cfg-mateminco-mf01-mini.h @@ -48,8 +48,3 @@ #define USE_TENCLICK_THERMAL_CONFIG // by request #define THERM_FASTER_LEVEL 130 // throttle back faster when high -//#define THERM_HARD_TURBO_DROP // this light is massively overpowered -#define THERMAL_WARNING_SECONDS 1 // FIXME: increase by 2 after merging newer code -//#define THERMAL_UPDATE_SPEED 1 -//#define THERM_PREDICTION_STRENGTH 4 - diff --git a/spaghetti-monster/anduril/cfg-sofirn-sp36.h b/spaghetti-monster/anduril/cfg-sofirn-sp36.h index 494a263..d808e2a 100644 --- a/spaghetti-monster/anduril/cfg-sofirn-sp36.h +++ b/spaghetti-monster/anduril/cfg-sofirn-sp36.h @@ -28,10 +28,3 @@ #undef THERM_FASTER_LEVEL #endif #define THERM_FASTER_LEVEL 130 - -// be extra-careful at high levels -// (or not... this host seems to heat up pretty slowly) -//#ifndef THERM_HARD_TURBO_DROP -//#define THERM_HARD_TURBO_DROP -//#endif - diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index dd43cb9..59d624b 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -119,8 +119,8 @@ static inline uint8_t calc_voltage_divider(uint16_t value) { } #endif -// Each full cycle runs ~4X per second with just voltage enabled, -// or ~2X per second with voltage and temperature. +// Each full cycle runs ~2X per second with just voltage enabled, +// or ~1X per second with voltage and temperature. #if defined(USE_LVP) && defined(USE_THERMAL_REGULATION) #define ADC_CYCLES_PER_SECOND 1 #else @@ -276,6 +276,7 @@ static inline void ADC_voltage_handler() { #ifdef USE_THERMAL_REGULATION +// generally happens once per second while awake static inline void ADC_temperature_handler() { // coarse adjustment #ifndef THERM_LOOKAHEAD diff --git a/spaghetti-monster/fsm-adc.h b/spaghetti-monster/fsm-adc.h index 6283b2c..241dee4 100644 --- a/spaghetti-monster/fsm-adc.h +++ b/spaghetti-monster/fsm-adc.h @@ -52,7 +52,9 @@ void adc_deferred(); // do the actual ADC-related calculations static inline void ADC_voltage_handler(); volatile uint8_t voltage = 0; +#ifdef USE_LVP void low_voltage(); +#endif #ifdef USE_BATTCHECK void battcheck(); @@ -67,10 +69,6 @@ void battcheck(); #ifdef USE_THERMAL_REGULATION -// default 1 seconds between thermal regulation events -#ifndef THERMAL_WARNING_SECONDS -#define THERMAL_WARNING_SECONDS 1 -#endif // try to keep temperature below 45 C #ifndef DEFAULT_THERM_CEIL #define DEFAULT_THERM_CEIL 45 @@ -83,14 +81,10 @@ void battcheck(); #ifndef THERM_CAL_OFFSET #define THERM_CAL_OFFSET 0 #endif -// temperature now, in C (ish) * 2 (14.1 fixed-point) +// temperature now, in C (ish) volatile int16_t temperature; -// temperature in a few seconds, in C (ish) * 2 (14.1 fixed-point) -volatile int16_t projected_temperature; // Fight the future! uint8_t therm_ceil = DEFAULT_THERM_CEIL; int8_t therm_cal_offset = 0; -//void low_temperature(); -//void high_temperature(); volatile uint8_t reset_thermal_history = 1; static inline void ADC_temperature_handler(); #endif // ifdef USE_THERMAL_REGULATION diff --git a/spaghetti-monster/fsm-standby.c b/spaghetti-monster/fsm-standby.c index 14b6df1..b002b91 100644 --- a/spaghetti-monster/fsm-standby.c +++ b/spaghetti-monster/fsm-standby.c @@ -87,10 +87,6 @@ void sleep_until_eswitch_pressed() #ifdef USE_THERMAL_REGULATION // forget what the temperature was last time we were on reset_thermal_history = 1; - // FIXME: not sure if this should be here - // (the intent is to make sure temperature gets measured before - // thermal logic gets executed) - //set_admux_therm(); #endif // go back to normal running mode diff --git a/spaghetti-monster/spaghetti-monster.txt b/spaghetti-monster/spaghetti-monster.txt index 9e051f1..434e1bc 100644 --- a/spaghetti-monster/spaghetti-monster.txt +++ b/spaghetti-monster/spaghetti-monster.txt @@ -124,14 +124,13 @@ Event types: between events. - EV_temperature_high: Sent whenever the MCU's projected temperature - is higher than therm_ceil. Minimum of THERMAL_WARNING_SECONDS - between events. The 'arg' indicates how far the temperature - exceeds the limit. + is higher than therm_ceil. Minimum of one second between events. + The 'arg' indicates how far the temperature exceeds the limit. - EV_temperature_low: Sent whenever the MCU's projected temperature is lower than (therm_ceil - THERMAL_WINDOW_SIZE). Minimum of - THERMAL_WARNING_SECONDS between events. The 'arg' indicates how - far the temperature exceeds the limit. + one second between events. The 'arg' indicates how far the + temperature exceeds the limit. Button presses: @@ -297,9 +296,6 @@ Useful #defines: - DEFAULT_THERM_CEIL: Set the temperature limit to use by default when the user hasn't configured anything. - - THERMAL_WARNING_SECONDS: How long to wait between temperature - events. - - USE_RAMPING: Enable smooth ramping helpers. - RAMP_LENGTH: Pick a pre-defined ramp by length. Defined sizes -- cgit v1.2.3 From b7f6dd21c396d1431e8864158d1868620ae334d6 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 16 Mar 2020 03:33:51 -0600 Subject: fixed a few things in ramping-ui, rampingiosv3, and werner's UI (just copied a few updates from anduril, particularly regarding FSM's "temperature" variable) --- spaghetti-monster/ramping-ui/ramping-ui.c | 3 +-- spaghetti-monster/rampingios/rampingiosv3.c | 12 +++++++----- spaghetti-monster/werner/werner.c | 12 +++++------- 3 files changed, 13 insertions(+), 14 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/ramping-ui/ramping-ui.c b/spaghetti-monster/ramping-ui/ramping-ui.c index 18f488d..5eb7d8f 100644 --- a/spaghetti-monster/ramping-ui/ramping-ui.c +++ b/spaghetti-monster/ramping-ui/ramping-ui.c @@ -22,7 +22,6 @@ #define USE_THERMAL_REGULATION #define DEFAULT_THERM_CEIL 32 #define USE_DELAY_MS -#define USE_DELAY_4MS #define USE_DELAY_ZERO #define USE_RAMPING #define USE_BATTCHECK @@ -353,7 +352,7 @@ void loop() { battcheck(); } else if (current_state == tempcheck_state) { - blink_num(projected_temperature>>2); + blink_num(temperature); nice_delay_ms(1000); } #endif diff --git a/spaghetti-monster/rampingios/rampingiosv3.c b/spaghetti-monster/rampingios/rampingiosv3.c index d72e971..7f03e77 100644 --- a/spaghetti-monster/rampingios/rampingiosv3.c +++ b/spaghetti-monster/rampingios/rampingiosv3.c @@ -123,6 +123,7 @@ uint8_t ramp_config_state(Event event, uint16_t arg); uint8_t battcheck_state(Event event, uint16_t arg); #endif #ifdef USE_THERMAL_REGULATION +#define USE_BLINK_NUM uint8_t tempcheck_state(Event event, uint16_t arg); uint8_t thermal_config_state(Event event, uint16_t arg); #endif @@ -930,14 +931,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; } @@ -966,9 +968,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 @@ -1235,7 +1237,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/werner/werner.c b/spaghetti-monster/werner/werner.c index 7c47cd7..4159fc6 100644 --- a/spaghetti-monster/werner/werner.c +++ b/spaghetti-monster/werner/werner.c @@ -467,14 +467,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; } @@ -589,7 +590,7 @@ uint8_t nearest_level(int16_t target) { for(uint8_t i=0; i>1)) return this_level; @@ -684,9 +685,6 @@ void loop() { StatePtr state = current_state; - #ifdef USE_DYNAMIC_UNDERCLOCKING - auto_clock_speed(); - #endif if (0) {} #ifdef USE_BATTCHECK @@ -697,7 +695,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 227b54b1095e47ae9d0ab4b4c2a49862fd708559 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 16 Mar 2020 04:13:55 -0600 Subject: fixed calc_voltage_divider() (use 10-bit calibration values, not 8-bit) --- spaghetti-monster/fsm-adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 7880238..e7b7feb 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -112,7 +112,7 @@ inline void ADC_off() { #ifdef USE_VOLTAGE_DIVIDER static inline uint8_t calc_voltage_divider(uint16_t value) { // use 9.7 fixed-point to get sufficient precision - uint16_t adc_per_volt = ((ADC_44<<7) - (ADC_22<<7)) / (44-22); + uint16_t adc_per_volt = ((ADC_44<<5) - (ADC_22<<5)) / (44-22); // shift incoming value into a matching position uint8_t result = ((value>>1) / adc_per_volt) + VOLTAGE_FUDGE_FACTOR; return result; -- cgit v1.2.3 From a749a489c0895388336b1f2ac532b345243fa5f7 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 16 Mar 2020 04:16:12 -0600 Subject: removed old thermal junk and voltage_lowpass junk from cfg files --- spaghetti-monster/anduril/cfg-noctigon-k1.h | 12 ------------ spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h | 5 ----- spaghetti-monster/anduril/cfg-noctigon-kr4.h | 12 ------------ 3 files changed, 29 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-k1.h b/spaghetti-monster/anduril/cfg-noctigon-k1.h index 6a8e8ee..4db8787 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-k1.h +++ b/spaghetti-monster/anduril/cfg-noctigon-k1.h @@ -46,16 +46,8 @@ #define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR #define MUGGLE_CEILING 70 -// 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 ~70% power or ~600 lm #define THERM_FASTER_LEVEL 130 -// respond to thermal changes faster -#define THERMAL_WARNING_SECONDS 3 -#define THERMAL_UPDATE_SPEED 1 -#define THERM_PREDICTION_STRENGTH 4 // easier access to thermal config mode, for Noctigon #define USE_TENCLICK_THERMAL_CONFIG @@ -65,7 +57,3 @@ #define THERM_CAL_OFFSET 5 -// attiny1634 has enough space to smooth out voltage readings -// (prevent the button from blinking during use) -#define USE_VOLTAGE_LOWPASS - diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h b/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h index 66177bf..0434258 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h @@ -38,8 +38,3 @@ // stop panicking at ~70% power or ~1200 lm #undef THERM_FASTER_LEVEL #define THERM_FASTER_LEVEL 130 -// 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-noctigon-kr4.h b/spaghetti-monster/anduril/cfg-noctigon-kr4.h index 9b810ab..d3e6d7b 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4.h @@ -48,16 +48,8 @@ #define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR #define MUGGLE_CEILING 65 -// optional, makes initial turbo step-down faster so first peak isn't as hot -// the KR4 runs very very hot on turbo, so be extra careful -//#define THERM_HARD_TURBO_DROP - // stop panicking at ~25% power or ~1000 lm #define THERM_FASTER_LEVEL 100 -// respond to thermal changes faster -#define THERMAL_WARNING_SECONDS 3 -#define THERMAL_UPDATE_SPEED 1 -#define THERM_PREDICTION_STRENGTH 4 // easier access to thermal config mode, for Noctigon #define USE_TENCLICK_THERMAL_CONFIG @@ -67,7 +59,3 @@ #define THERM_CAL_OFFSET 5 -// attiny1634 has enough space to smooth out voltage readings -// (prevent the button from blinking during use) -//#define USE_VOLTAGE_LOWPASS - -- cgit v1.2.3 From 1afe3758f58c1adc76c847d134e21f69faacc64e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 16 Mar 2020 04:23:43 -0600 Subject: removed more references to THERM_HARD_TURBO_DROP --- spaghetti-monster/anduril/cfg-emisar-d1.h | 5 ----- spaghetti-monster/anduril/cfg-emisar-d1s.h | 5 ----- spaghetti-monster/anduril/cfg-emisar-d4.h | 4 ---- spaghetti-monster/anduril/cfg-emisar-d4s.h | 5 ----- 4 files changed, 19 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-emisar-d1.h b/spaghetti-monster/anduril/cfg-emisar-d1.h index 35e91db..9276ba3 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d1.h +++ b/spaghetti-monster/anduril/cfg-emisar-d1.h @@ -8,8 +8,3 @@ #undef THERM_FASTER_LEVEL #endif #define THERM_FASTER_LEVEL (RAMP_SIZE*9/10) // 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 diff --git a/spaghetti-monster/anduril/cfg-emisar-d1s.h b/spaghetti-monster/anduril/cfg-emisar-d1s.h index 56200a2..c01c37d 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d1s.h +++ b/spaghetti-monster/anduril/cfg-emisar-d1s.h @@ -8,8 +8,3 @@ #undef THERM_FASTER_LEVEL #endif #define THERM_FASTER_LEVEL 144 // 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 diff --git a/spaghetti-monster/anduril/cfg-emisar-d4.h b/spaghetti-monster/anduril/cfg-emisar-d4.h index 501b9c7..7700d88 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4.h @@ -18,10 +18,6 @@ #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 diff --git a/spaghetti-monster/anduril/cfg-emisar-d4s.h b/spaghetti-monster/anduril/cfg-emisar-d4s.h index 88465da..f5addb2 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d4s.h +++ b/spaghetti-monster/anduril/cfg-emisar-d4s.h @@ -37,8 +37,3 @@ #endif #define MIN_THERM_STEPDOWN 60 // lowest value it'll step down to #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 -- cgit v1.2.3 From 7134924ce13956770ff07ae5da978b6f2061b00e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 20 Mar 2020 00:07:34 -0600 Subject: added reboot() support for tiny1634 --- spaghetti-monster/fsm-misc.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-misc.c b/spaghetti-monster/fsm-misc.c index 152f047..82be745 100644 --- a/spaghetti-monster/fsm-misc.c +++ b/spaghetti-monster/fsm-misc.c @@ -231,18 +231,20 @@ uint8_t triangle_wave(uint8_t phase) { #ifdef USE_REBOOT void reboot() { - #if 1 // WDT method, safer but larger + // put the WDT in hard reset mode, then trigger it cli(); - WDTCR = 0xD8 | WDTO_15MS; + #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) + WDTCR = 0xD8 | WDTO_15MS; + #elif (ATTINY == 1634) + // allow protected configuration changes for next 4 clock cycles + CCP = 0xD8; // magic number + // reset (WDIF + WDE), no WDIE, fastest (16ms) timing (0000) + // (DS section 8.5.2 and table 8-4) + WDTCSR = 0b10001000; + #endif sei(); wdt_reset(); while (1) {} - #else // raw assembly method, doesn't reset registers or anything - __asm__ __volatile__ ( - "cli" "\n\t" - "rjmp 0x00" "\n\t" - ); - #endif } #endif -- cgit v1.2.3 From 8d5584c789fe95a97a8385adfce8c52c572c1536 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 20 Mar 2020 00:09:04 -0600 Subject: enabled soft factory reset on KR4, raised default floor to the lowest reliable level (moon level 1 flickers or doesn't work at all on some hardware) --- spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h | 2 +- spaghetti-monster/anduril/cfg-noctigon-kr4.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h b/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h index 0434258..0e53e5f 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h @@ -23,7 +23,7 @@ #undef RAMP_DISCRETE_CEIL #undef RAMP_DISCRETE_STEPS -#define RAMP_SMOOTH_FLOOR 1 +#define RAMP_SMOOTH_FLOOR 3 // level 1 is unreliable #define RAMP_SMOOTH_CEIL 130 // 10, 30, [50], 70, 90, 110, 130 (plus [150] on turbo) #define RAMP_DISCRETE_FLOOR 10 diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4.h b/spaghetti-monster/anduril/cfg-noctigon-kr4.h index d3e6d7b..6f52eb3 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4.h @@ -38,7 +38,7 @@ #undef USE_DYNAMIC_UNDERCLOCKING #endif -#define RAMP_SMOOTH_FLOOR 1 +#define RAMP_SMOOTH_FLOOR 3 // level 1 is unreliable #define RAMP_SMOOTH_CEIL 120 // 10, 28, [46], 65, 83, 101, [120] #define RAMP_DISCRETE_FLOOR 10 @@ -59,3 +59,5 @@ #define THERM_CAL_OFFSET 5 +// can't reset the normal way because power is connected before the button +#define USE_SOFT_FACTORY_RESET -- cgit v1.2.3 From 52c58c46f7c9c7aced3a5eb174c88d444a6d8a57 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 21 Mar 2020 21:03:42 -0600 Subject: fixed potential eeprom corruption after turning boost/opamp chip on/off (some boost chips can make power unstable for a few ms, so we have to wait before accessing eeprom) --- spaghetti-monster/fsm-eeprom.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-eeprom.c b/spaghetti-monster/fsm-eeprom.c index 277e2b2..77352cf 100644 --- a/spaghetti-monster/fsm-eeprom.c +++ b/spaghetti-monster/fsm-eeprom.c @@ -30,6 +30,10 @@ uint8_t eeprom[EEPROM_BYTES]; #endif uint8_t load_eeprom() { + #ifdef LED_ENABLE_PIN + delay_4ms(2); // wait for power to stabilize + #endif + cli(); // check if eeprom has been initialized; abort if it hasn't uint8_t marker = eeprom_read_byte((uint8_t *)EEP_START); @@ -44,6 +48,10 @@ uint8_t load_eeprom() { } void save_eeprom() { + #ifdef LED_ENABLE_PIN + delay_4ms(2); // wait for power to stabilize + #endif + cli(); // save the actual data @@ -62,6 +70,10 @@ uint8_t eeprom_wl[EEPROM_WL_BYTES]; EEP_OFFSET_T eep_wl_prev_offset; uint8_t load_eeprom_wl() { + #ifdef LED_ENABLE_PIN + delay_4ms(2); // wait for power to stabilize + #endif + cli(); // check if eeprom has been initialized; abort if it hasn't uint8_t found = 0; @@ -87,6 +99,10 @@ uint8_t load_eeprom_wl() { } void save_eeprom_wl() { + #ifdef LED_ENABLE_PIN + delay_4ms(2); // wait for power to stabilize + #endif + cli(); // erase old state EEP_OFFSET_T offset = eep_wl_prev_offset; -- cgit v1.2.3 From 9caa6cd6daf4875856e0d91247d8e9f46fa5f2ad Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 21 Mar 2020 21:23:21 -0600 Subject: added dynamic underclocking to KR4 to increase moon runtime, fixed ramp milestone levels --- spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h | 8 ++++++-- spaghetti-monster/anduril/cfg-noctigon-kr4.h | 18 +++++------------- 2 files changed, 11 insertions(+), 15 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h b/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h index 0e53e5f..00751fd 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h @@ -13,9 +13,10 @@ #undef PWM1_LEVELS #define PWM1_LEVELS 0,0,1,1,2,2,3,3,4,4,5,5,6,7,8,9,10,11,12,13,15,16,17,18,20,21,23,24,26,27,29,31,33,35,37,39,41,43,45,48,50,53,55,58,61,63,66,69,72,75,79,82,85,89,92,96,100,104,108,112,116,120,125,129,134,138,143,148,153,158,163,169,174,180,185,191,197,203,209,215,222,228,235,242,248,255,263,270,277,285,292,300,308,316,324,333,341,350,359,368,377,386,395,405,414,424,434,444,454,465,475,486,497,508,519,531,542,554,566,578,590,603,615,628,641,654,667,680,694,708,722,736,750,765,779,794,809,825,840,856,872,888,904,920,937,954,971,988,1005,1023 #undef PWM2_LEVELS +#undef DEFAULT_LEVEL +#define DEFAULT_LEVEL 50 #undef MAX_1x7135 -#define MAX_1x7135 50 -#undef MAX_Nx7135 +#define MAX_1x7135 150 #undef RAMP_SMOOTH_FLOOR #undef RAMP_SMOOTH_CEIL @@ -38,3 +39,6 @@ // stop panicking at ~70% power or ~1200 lm #undef THERM_FASTER_LEVEL #define THERM_FASTER_LEVEL 130 +#undef MIN_THERM_STEPDOWN +#define MIN_THERM_STEPDOWN DEFAULT_LEVEL + diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4.h b/spaghetti-monster/anduril/cfg-noctigon-kr4.h index 6f52eb3..98dc209 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4.h @@ -24,19 +24,10 @@ #define RAMP_LENGTH 150 #define PWM1_LEVELS 0,0,1,1,2,2,3,3,4,4,5,6,7,8,9,10,11,13,14,15,17,19,20,22,24,26,28,30,33,35,38,40,43,46,49,52,55,59,62,66,70,74,78,82,86,91,96,100,105,111,116,121,127,133,139,145,151,158,165,172,179,186,193,201,209,217,225,234,243,251,261,270,280,289,299,310,320,331,342,353,364,376,388,400,412,425,438,451,464,478,492,506,521,536,551,566,582,597,614,630,647,664,681,699,717,735,754,772,792,811,831,851,871,892,913,935,956,978,1001,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,51,79,109,138,168,198,229,260,292,324,357,390,423,457,492,527,562,598,634,671,708,746,784,822,861,901,941,982,1023 -#define MAX_1x7135 46 -#define MAX_Nx7135 120 - -// the entire ramp is regulated; don't blink halfway up -#ifdef BLINK_AT_RAMP_MIDDLE -#undef BLINK_AT_RAMP_MIDDLE -#endif - -// don't slow down at low levels; this isn't that sort of light -// (it needs to stay at full speed for the 10-bit PWM to work) -#ifdef USE_DYNAMIC_UNDERCLOCKING -#undef USE_DYNAMIC_UNDERCLOCKING -#endif +#define DEFAULT_LEVEL 46 +#define MAX_1x7135 120 +#define HALFSPEED_LEVEL 10 +#define QUARTERSPEED_LEVEL 2 #define RAMP_SMOOTH_FLOOR 3 // level 1 is unreliable #define RAMP_SMOOTH_CEIL 120 @@ -50,6 +41,7 @@ // stop panicking at ~25% power or ~1000 lm #define THERM_FASTER_LEVEL 100 +#define MIN_THERM_STEPDOWN DEFAULT_LEVEL // easier access to thermal config mode, for Noctigon #define USE_TENCLICK_THERMAL_CONFIG -- cgit v1.2.3 From ff9eedb56927387201f96f90bf3d39b99f86e283 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 22 Mar 2020 01:25:55 -0600 Subject: apparently the D1 can also be purchased with a D4v2 driver... so it's basically a D1v2 --- spaghetti-monster/anduril/cfg-emisar-d1v2.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 spaghetti-monster/anduril/cfg-emisar-d1v2.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-emisar-d1v2.h b/spaghetti-monster/anduril/cfg-emisar-d1v2.h new file mode 100644 index 0000000..63cb0e9 --- /dev/null +++ b/spaghetti-monster/anduril/cfg-emisar-d1v2.h @@ -0,0 +1,17 @@ +// Emisar D1v2 config options for Anduril (D1 w/ D4v2 driver) +// ATTINY: 1634 +// same as Emisar D4v2, mostly +#include "cfg-emisar-d4v2.h" + +// there are no aux LED on a D1 +#undef USE_AUX_RGB_LEDS +// ... and no button LED +#undef USE_BUTTON_LED +// no aux LEDs means no need for sleep ticks +#undef TICK_DURING_STANDBY + +// stop panicking at ~75% power or ~1000 lm (D1 has a decent power-to-thermal-mass ratio) +#ifdef THERM_FASTER_LEVEL +#undef THERM_FASTER_LEVEL +#endif +#define THERM_FASTER_LEVEL (RAMP_SIZE*9/10) // throttle back faster when high -- cgit v1.2.3 From ef1d96b85485000e70ef5423c9494eb91286d3d7 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 26 Mar 2020 03:46:47 -0600 Subject: made thermal regulation use a smaller target window, and prioritize cooling more --- spaghetti-monster/fsm-adc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index e7b7feb..edf1809 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -362,7 +362,7 @@ static inline void ADC_temperature_handler() { // (but a diff of 1 C should only send a warning of magnitude 1) // (this also makes it only respond to small errors at the time the error // happened, not after the temperature has stabilized) - for(uint8_t foo=0; foo<5; foo++) { + for(uint8_t foo=0; foo<3; foo++) { if (offset > 0) { offset --; } else if (offset < 0) { @@ -371,8 +371,8 @@ static inline void ADC_temperature_handler() { } // Too hot? - // (if it's too hot and still getting warmer...) - if ((offset > 0) && (diff > 0)) { + // (if it's too hot and not getting cooler...) + if ((offset > 0) && (diff > -1)) { // accumulated error isn't big enough yet to send a warning if (warning_threshold > 0) { warning_threshold -= offset; -- cgit v1.2.3 From b6059fdcaad276f65d55e73ce8b3003e884684ad Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 26 Mar 2020 03:47:46 -0600 Subject: Noctigon KR4 needed tighter/faster thermal response, and Hank wants RGB rainbow to be default instead of voltage mode. --- spaghetti-monster/anduril/cfg-noctigon-kr4.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4.h b/spaghetti-monster/anduril/cfg-noctigon-kr4.h index 98dc209..01310b5 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4.h @@ -6,7 +6,7 @@ #define USE_AUX_RGB_LEDS //#define USE_AUX_RGB_LEDS_WHILE_ON //#define USE_INDICATOR_LED_WHILE_RAMPING -#define RGB_LED_OFF_DEFAULT 0x18 // low, voltage +#define RGB_LED_OFF_DEFAULT 0x17 // low, rainbow #define RGB_LED_LOCKOUT_DEFAULT 0x37 // blinking, rainbow // enable blinking aux LEDs @@ -42,6 +42,8 @@ // stop panicking at ~25% power or ~1000 lm #define THERM_FASTER_LEVEL 100 #define MIN_THERM_STEPDOWN DEFAULT_LEVEL +#define THERM_LOOKAHEAD 6 +#define THERM_NEXT_WARNING_THRESHOLD 12 // easier access to thermal config mode, for Noctigon #define USE_TENCLICK_THERMAL_CONFIG -- cgit v1.2.3 From 691abdd22f83a9e8a35e2887e6345fb4234fba7c Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 28 Mar 2020 19:44:26 -0600 Subject: added a Noctigon KR4 219 (75% FET) build target --- spaghetti-monster/anduril/cfg-noctigon-kr4-219.h | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 spaghetti-monster/anduril/cfg-noctigon-kr4-219.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4-219.h b/spaghetti-monster/anduril/cfg-noctigon-kr4-219.h new file mode 100644 index 0000000..0cfccf2 --- /dev/null +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4-219.h @@ -0,0 +1,11 @@ +// Noctigon KR4 (75% FET) config options for Anduril +#include "cfg-noctigon-kr4.h" +// ATTINY: 1634 + +// don't turn off first channel at turbo level +#undef PWM1_LEVELS +#define PWM1_LEVELS 0,0,1,1,2,2,3,3,4,4,5,6,7,8,9,10,11,13,14,15,17,19,20,22,24,26,28,30,33,35,38,40,43,46,49,52,55,59,62,66,70,74,78,82,86,91,96,100,105,111,116,121,127,133,139,145,151,158,165,172,179,186,193,201,209,217,225,234,243,251,261,270,280,289,299,310,320,331,342,353,364,376,388,400,412,425,438,451,464,478,492,506,521,536,551,566,582,597,614,630,647,664,681,699,717,735,754,772,792,811,831,851,871,892,913,935,956,978,1001,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023 +// 75% FET power +#undef PWM2_LEVELS +#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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,39,60,82,104,126,149,172,195,219,243,268,293,318,343,369,396,422,449,476,504,531,560,588,617,646,676,706,737,768 + -- cgit v1.2.3 From c6db8faca50762aea53fb38c48c1bd5fae092f19 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 13 Apr 2020 19:50:05 -0600 Subject: recalibrated timing of nice_delay_ms() based on strobe speed measurements... gets very close to 24.2 Hz and 10.0 Hz for default strobe settings now --- spaghetti-monster/anduril/anduril.c | 2 +- spaghetti-monster/fsm-events.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index cb48b45..0758327 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -490,7 +490,7 @@ volatile strobe_mode_te strobe_type = 0; #if defined(USE_PARTY_STROBE_MODE) || defined(USE_TACTICAL_STROBE_MODE) // party / tactical strobe timing -volatile uint8_t strobe_delays[] = { 40, 67 }; // party strobe, tactical strobe +volatile uint8_t strobe_delays[] = { 41, 67 }; // party strobe 24 Hz, tactical strobe 10 Hz #endif // bike mode config options diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c index a1b013a..ad869a6 100644 --- a/spaghetti-monster/fsm-events.c +++ b/spaghetti-monster/fsm-events.c @@ -120,7 +120,7 @@ uint8_t nice_delay_ms(uint16_t ms) { uint8_t level = actual_level; // volatile, avoid repeat access if (level < QUARTERSPEED_LEVEL) { clock_prescale_set(clock_div_4); - _delay_loop_2(BOGOMIPS*95/100/4); + _delay_loop_2(BOGOMIPS*90/100/4); } //else if (level < HALFSPEED_LEVEL) { // clock_prescale_set(clock_div_2); @@ -128,7 +128,7 @@ uint8_t nice_delay_ms(uint16_t ms) { //} else { clock_prescale_set(clock_div_1); - _delay_loop_2(BOGOMIPS*95/100); + _delay_loop_2(BOGOMIPS*90/100); } // restore regular clock speed clock_prescale_set(clock_div_1); @@ -136,13 +136,13 @@ uint8_t nice_delay_ms(uint16_t ms) { // underclock MCU to save power clock_prescale_set(clock_div_4); // wait - _delay_loop_2(BOGOMIPS*95/100/4); + _delay_loop_2(BOGOMIPS*90/100/4); // restore regular clock speed clock_prescale_set(clock_div_1); #endif // ifdef USE_RAMPING #else // wait - _delay_loop_2(BOGOMIPS*95/100); + _delay_loop_2(BOGOMIPS*90/100); #endif // ifdef USE_DYNAMIC_UNDERCLOCKING // run pending system processes while we wait -- cgit v1.2.3 From 1c741d98cc30a62511120ec80f73f30e9ba30eb8 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 13 Apr 2020 19:50:41 -0600 Subject: added a noFET build for D4v2, by request --- spaghetti-monster/anduril/cfg-emisar-d1v2.h | 2 +- spaghetti-monster/anduril/cfg-emisar-d4v2-nofet.h | 34 +++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 spaghetti-monster/anduril/cfg-emisar-d4v2-nofet.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-emisar-d1v2.h b/spaghetti-monster/anduril/cfg-emisar-d1v2.h index 63cb0e9..91be3f3 100644 --- a/spaghetti-monster/anduril/cfg-emisar-d1v2.h +++ b/spaghetti-monster/anduril/cfg-emisar-d1v2.h @@ -3,7 +3,7 @@ // same as Emisar D4v2, mostly #include "cfg-emisar-d4v2.h" -// there are no aux LED on a D1 +// there are no aux LEDs on a D1 #undef USE_AUX_RGB_LEDS // ... and no button LED #undef USE_BUTTON_LED diff --git a/spaghetti-monster/anduril/cfg-emisar-d4v2-nofet.h b/spaghetti-monster/anduril/cfg-emisar-d4v2-nofet.h new file mode 100644 index 0000000..cbb5891 --- /dev/null +++ b/spaghetti-monster/anduril/cfg-emisar-d4v2-nofet.h @@ -0,0 +1,34 @@ +// Emisar D4v2-noFET config options for Anduril +#include "cfg-emisar-d4v2.h" +// ATTINY: 1634 + +#undef PWM_CHANNELS +#define PWM_CHANNELS 1 +#undef PWM1_LEVELS +#undef PWM2_LEVELS +#define PWM1_LEVELS 1,1,1,2,2,2,2,3,3,3,3,4,4,5,5,6,6,6,7,8,8,9,9,10,10,11,12,13,13,14,15,16,16,17,18,19,20,21,22,23,23,24,26,27,28,29,30,31,32,33,34,36,37,38,39,41,42,43,45,46,47,49,50,52,53,55,56,58,59,61,62,64,66,67,69,71,72,74,76,78,80,81,83,85,87,89,91,93,95,97,99,101,103,105,107,109,111,113,116,118,120,122,125,127,129,132,134,136,139,141,144,146,148,151,154,156,159,161,164,166,169,172,174,177,180,183,185,188,191,194,197,200,203,205,208,211,214,217,220,223,226,230,233,236,239,242,245,249,252,255 +#undef MAX_1x7135 +#define MAX_1x7135 150 +#undef QUARTERSPEED_LEVEL +#undef HALFSPEED_LEVEL +#define QUARTERSPEED_LEVEL 8 +#define HALFSPEED_LEVEL 16 + +#define DEFAULT_LEVEL 80 + +#undef RAMP_SMOOTH_CEIL +#define RAMP_SMOOTH_CEIL 150 +// 10, 45, 80, 115, 150 +#undef RAMP_DISCRETE_FLOOR +#undef RAMP_DISCRETE_CEIL +#undef RAMP_DISCRETE_STEPS +#define RAMP_DISCRETE_FLOOR 10 +#define RAMP_DISCRETE_CEIL 150 +#define RAMP_DISCRETE_STEPS 5 + +#define CANDLE_AMPLITUDE 60 + +#undef THERM_FASTER_LEVEL +#define THERM_FASTER_LEVEL 150 + +#undef USE_THERMAL_REGULATION -- cgit v1.2.3 From 83f1f66ca9760bcb968b2104d5f270804663961c Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 19 Apr 2020 03:10:56 -0600 Subject: anduril: made aux RGB rainbow mode speed configurable per build target --- spaghetti-monster/anduril/anduril.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index cb48b45..e87a30c 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -355,6 +355,9 @@ const PROGMEM uint8_t rgb_led_colors[] = { #ifndef RGB_LED_LOCKOUT_DEFAULT #define RGB_LED_LOCKOUT_DEFAULT 0x37 // blinking, rainbow #endif +#ifndef RGB_RAINBOW_SPEED +#define RGB_RAINBOW_SPEED 0x0f // change color every 16 frames +#endif uint8_t rgb_led_off_mode = RGB_LED_OFF_DEFAULT; uint8_t rgb_led_lockout_mode = RGB_LED_LOCKOUT_DEFAULT; #endif @@ -2400,7 +2403,7 @@ void rgb_led_update(uint8_t mode, uint8_t arg) { } else if (color == 7) { // rainbow uint8_t speed = 0x03; // awake speed - if (go_to_standby) speed = 0x0f; // asleep speed + if (go_to_standby) speed = RGB_RAINBOW_SPEED; // asleep speed if (0 == (arg & speed)) { rainbow = (rainbow + 1) % 6; } -- cgit v1.2.3 From d9105a32fee77822745c25e3c4b778cc079155da Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 19 Apr 2020 03:12:25 -0600 Subject: KR4-noFET: made candle mode vary more since the ramp is stretched out, raised therm faster level --- spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h b/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h index 00751fd..19cbc23 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4-nofet.h @@ -36,9 +36,12 @@ #define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR #define MUGGLE_CEILING 70 -// stop panicking at ~70% power or ~1200 lm +// make candle mode wobble more +#define CANDLE_AMPLITUDE 32 + +// stop panicking at ~90% power or ~1600 lm #undef THERM_FASTER_LEVEL -#define THERM_FASTER_LEVEL 130 +#define THERM_FASTER_LEVEL 143 #undef MIN_THERM_STEPDOWN #define MIN_THERM_STEPDOWN DEFAULT_LEVEL -- cgit v1.2.3 From 43eec5d7b84f1ac617519723373850733d3adcb1 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 19 Apr 2020 03:17:24 -0600 Subject: made thermal response larger when error is large, smaller when error is small (helps on KR4, but will probably need to add the response magnitude thing to adjust speed per build target) --- spaghetti-monster/fsm-adc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index edf1809..760acc4 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -377,11 +377,17 @@ static inline void ADC_temperature_handler() { if (warning_threshold > 0) { warning_threshold -= offset; } else { // error is big enough; send a warning - warning_threshold = THERM_NEXT_WARNING_THRESHOLD - offset; + //warning_threshold = THERM_NEXT_WARNING_THRESHOLD - offset; // how far above the ceiling? //int16_t howmuch = offset * THERM_RESPONSE_MAGNITUDE / 128; - int16_t howmuch = offset; + //int16_t howmuch = offset; + // increase the amount, except for small values + // 1:1, 2:1, 3:3, 4:5, 6:9, 8:13, 10:17, 40:77 + int16_t howmuch = offset + offset - 3; + if (howmuch < 1) howmuch = 1; + warning_threshold = THERM_NEXT_WARNING_THRESHOLD - (uint8_t)howmuch; + // send a warning emit(EV_temperature_high, howmuch); } -- cgit v1.2.3 From 536e9c0d3e89fea0e37a840c0c72136c25f71889 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 19 Apr 2020 03:29:43 -0600 Subject: added tweakable thermal_response_magnitude option, adjusted KR4 thermal vars, made KR4 rainbow mode faster --- spaghetti-monster/anduril/cfg-noctigon-kr4.h | 4 ++-- spaghetti-monster/fsm-adc.c | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4.h b/spaghetti-monster/anduril/cfg-noctigon-kr4.h index 01310b5..66c5a28 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4.h @@ -8,6 +8,7 @@ //#define USE_INDICATOR_LED_WHILE_RAMPING #define RGB_LED_OFF_DEFAULT 0x17 // low, rainbow #define RGB_LED_LOCKOUT_DEFAULT 0x37 // blinking, rainbow +#define RGB_RAINBOW_SPEED 0x03 // half a second per color // enable blinking aux LEDs #define TICK_DURING_STANDBY @@ -42,8 +43,7 @@ // stop panicking at ~25% power or ~1000 lm #define THERM_FASTER_LEVEL 100 #define MIN_THERM_STEPDOWN DEFAULT_LEVEL -#define THERM_LOOKAHEAD 6 -#define THERM_NEXT_WARNING_THRESHOLD 12 +#define THERM_NEXT_WARNING_THRESHOLD 16 // easier access to thermal config mode, for Noctigon #define USE_TENCLICK_THERMAL_CONFIG diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 760acc4..68361ae 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -286,21 +286,21 @@ static inline void ADC_voltage_handler() { static inline void ADC_temperature_handler() { // coarse adjustment #ifndef THERM_LOOKAHEAD - #define THERM_LOOKAHEAD 4 // can be tweaked per build target + #define THERM_LOOKAHEAD 4 #endif // reduce frequency of minor warnings #ifndef THERM_NEXT_WARNING_THRESHOLD #define THERM_NEXT_WARNING_THRESHOLD 24 #endif // fine-grained adjustment - // how proportional should the adjustments be? (not used yet) + // how proportional should the adjustments be? #ifndef THERM_RESPONSE_MAGNITUDE #define THERM_RESPONSE_MAGNITUDE 128 #endif // acceptable temperature window size in C #define THERM_WINDOW_SIZE 2 - // TODO: make this configurable per build target? + // TODO? make this configurable per build target? // (shorter time for hosts with a lower power-to-mass ratio) // (because then it'll have smaller responses) #define NUM_TEMP_HISTORY_STEPS 8 // don't change; it'll break stuff @@ -377,14 +377,14 @@ static inline void ADC_temperature_handler() { if (warning_threshold > 0) { warning_threshold -= offset; } else { // error is big enough; send a warning - //warning_threshold = THERM_NEXT_WARNING_THRESHOLD - offset; - // how far above the ceiling? - //int16_t howmuch = offset * THERM_RESPONSE_MAGNITUDE / 128; - //int16_t howmuch = offset; - // increase the amount, except for small values - // 1:1, 2:1, 3:3, 4:5, 6:9, 8:13, 10:17, 40:77 - int16_t howmuch = offset + offset - 3; + // original method works, but is too slow on some small hosts: + // (and typically has a minimum response magnitude of 2 instead of 1) + // int16_t howmuch = offset; + // ... so increase the amount, except for small values + // (for example, 1:1, 2:1, 3:3, 4:5, 6:9, 8:13, 10:17, 40:77) + // ... and let us tune the response per build target if desired + int16_t howmuch = (offset + offset - 3) * THERM_RESPONSE_MAGNITUDE / 128; if (howmuch < 1) howmuch = 1; warning_threshold = THERM_NEXT_WARNING_THRESHOLD - (uint8_t)howmuch; -- cgit v1.2.3 From 08781957244b9a30c9abc7425ff023d36f7e9160 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 26 Apr 2020 22:12:31 -0600 Subject: applied ADC rewrite updates to most recent build targets --- spaghetti-monster/anduril/cfg-noctigon-k1-12v.h | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h b/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h index 12f69de..10cdfa1 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h +++ b/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h @@ -45,16 +45,8 @@ #define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR #define MUGGLE_CEILING 70 -// 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 ~70% power or ~600 lm #define THERM_FASTER_LEVEL 130 -// respond to thermal changes faster -#define THERMAL_WARNING_SECONDS 3 -#define THERMAL_UPDATE_SPEED 1 -#define THERM_PREDICTION_STRENGTH 4 // easier access to thermal config mode, for Noctigon #define USE_TENCLICK_THERMAL_CONFIG @@ -64,7 +56,3 @@ #define THERM_CAL_OFFSET 5 -// attiny1634 has enough space to smooth out voltage readings -// (prevent the button from blinking during use) -#define USE_VOLTAGE_LOWPASS - -- cgit v1.2.3 From 0f0085f244d9ec7f49780d3f7286eb824825dfe6 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 27 Apr 2020 17:52:46 -0600 Subject: set default thermal response magnitude back to how it was before the KR4 updates, because it worked well on many hosts before... --- spaghetti-monster/anduril/cfg-noctigon-kr4.h | 3 ++- spaghetti-monster/fsm-adc.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-kr4.h b/spaghetti-monster/anduril/cfg-noctigon-kr4.h index 66c5a28..dc71655 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-kr4.h +++ b/spaghetti-monster/anduril/cfg-noctigon-kr4.h @@ -43,7 +43,8 @@ // stop panicking at ~25% power or ~1000 lm #define THERM_FASTER_LEVEL 100 #define MIN_THERM_STEPDOWN DEFAULT_LEVEL -#define THERM_NEXT_WARNING_THRESHOLD 16 +#define THERM_NEXT_WARNING_THRESHOLD 16 // accumulate less error before adjusting +#define THERM_RESPONSE_MAGNITUDE 128 // bigger adjustments // easier access to thermal config mode, for Noctigon #define USE_TENCLICK_THERMAL_CONFIG diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 68361ae..45a4297 100644 --- a/spaghetti-monster/fsm-adc.c +++ b/spaghetti-monster/fsm-adc.c @@ -295,7 +295,7 @@ static inline void ADC_temperature_handler() { // fine-grained adjustment // how proportional should the adjustments be? #ifndef THERM_RESPONSE_MAGNITUDE - #define THERM_RESPONSE_MAGNITUDE 128 + #define THERM_RESPONSE_MAGNITUDE 64 #endif // acceptable temperature window size in C #define THERM_WINDOW_SIZE 2 -- cgit v1.2.3 From 02da00884b824ee5fefcd4c64096821ce32888b4 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 27 Apr 2020 17:54:00 -0600 Subject: calibrated K1 and K1-12V thermal response (smaller, slower) and candle mode (wobblier), and gave K1-12V a lower moon mode --- spaghetti-monster/anduril/cfg-noctigon-k1-12v.h | 11 +++++++++-- spaghetti-monster/anduril/cfg-noctigon-k1.h | 7 +++++++ 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h b/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h index 10cdfa1..617801f 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h +++ b/spaghetti-monster/anduril/cfg-noctigon-k1-12v.h @@ -18,10 +18,11 @@ #define STANDBY_TICK_SPEED 3 // every 0.128 s -// ../../bin/level_calc.py cube 1 150 7135 1 4 1300 +// level_calc.py cube 1 150 7135 0 4 1300 // (with max_pwm set to 1023) +// (level 0 is usable on this light) #define RAMP_LENGTH 150 -#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,6,7,8,9,10,11,12,13,14,15,16,17,18,20,21,23,24,26,27,29,31,32,34,36,38,40,43,45,47,49,52,54,57,60,62,65,68,71,74,77,81,84,87,91,95,98,102,106,110,114,118,122,127,131,136,141,145,150,155,160,166,171,176,182,188,193,199,205,211,218,224,231,237,244,251,258,265,272,280,287,295,303,310,319,327,335,344,352,361,370,379,388,397,407,416,426,436,446,457,467,477,488,499,510,521,533,544,556,568,580,592,604,617,629,642,655,668,682,695,709,723,737,751,766,781,795,810,826,841,857,872,888,904,921,937,954,971,988,1005,1023 +#define PWM1_LEVELS 0,0,1,1,2,2,3,3,4,5,5,6,7,8,9,10,11,12,13,14,15,16,17,19,20,22,23,25,26,28,30,31,33,35,37,39,42,44,46,48,51,53,56,59,61,64,67,70,73,76,80,83,86,90,94,97,101,105,109,113,117,122,126,130,135,140,144,149,154,159,165,170,175,181,187,193,198,204,211,217,223,230,236,243,250,257,264,271,279,286,294,302,310,318,326,334,343,351,360,369,378,387,397,406,416,426,436,446,456,466,477,488,499,510,521,532,544,555,567,579,591,604,616,629,642,655,668,682,695,709,723,737,751,766,780,795,810,825,841,856,872,888,904,921,937,954,971,988,1005,1023 #define MAX_1x7135 50 // the entire ramp is regulated; don't blink halfway up @@ -45,9 +46,15 @@ #define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR #define MUGGLE_CEILING 70 +// make candle mode wobble more +#define CANDLE_AMPLITUDE 32 + // stop panicking at ~70% power or ~600 lm #define THERM_FASTER_LEVEL 130 +#define THERM_RESPONSE_MAGNITUDE 32 // smaller adjustments, this host changes temperature slowly +#define THERM_NEXT_WARNING_THRESHOLD 32 // more error tolerance before adjusting + // easier access to thermal config mode, for Noctigon #define USE_TENCLICK_THERMAL_CONFIG diff --git a/spaghetti-monster/anduril/cfg-noctigon-k1.h b/spaghetti-monster/anduril/cfg-noctigon-k1.h index 4db8787..4f2c2cc 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-k1.h +++ b/spaghetti-monster/anduril/cfg-noctigon-k1.h @@ -21,6 +21,7 @@ // ../../bin/level_calc.py cube 1 150 7135 1 4 1300 // (with max_pwm set to 1023) +// (level 0 flickers and isn't relevant on a thrower, so it's omitted) #define RAMP_LENGTH 150 #define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,6,7,8,9,10,11,12,13,14,15,16,17,18,20,21,23,24,26,27,29,31,32,34,36,38,40,43,45,47,49,52,54,57,60,62,65,68,71,74,77,81,84,87,91,95,98,102,106,110,114,118,122,127,131,136,141,145,150,155,160,166,171,176,182,188,193,199,205,211,218,224,231,237,244,251,258,265,272,280,287,295,303,310,319,327,335,344,352,361,370,379,388,397,407,416,426,436,446,457,467,477,488,499,510,521,533,544,556,568,580,592,604,617,629,642,655,668,682,695,709,723,737,751,766,781,795,810,826,841,857,872,888,904,921,937,954,971,988,1005,1023 #define MAX_1x7135 50 @@ -46,9 +47,15 @@ #define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR #define MUGGLE_CEILING 70 +// make candle mode wobble more +#define CANDLE_AMPLITUDE 32 + // stop panicking at ~70% power or ~600 lm #define THERM_FASTER_LEVEL 130 +#define THERM_RESPONSE_MAGNITUDE 32 // smaller adjustments, this host changes temperature slowly +#define THERM_NEXT_WARNING_THRESHOLD 32 // more error tolerance before adjusting + // easier access to thermal config mode, for Noctigon #define USE_TENCLICK_THERMAL_CONFIG -- cgit v1.2.3 From b86ed1f0ed7d713fbffe0f7e58069733ad065eba Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 28 Apr 2020 00:45:26 -0600 Subject: added config which matches the spec for K1-SBT90.2, but it's not tested (there's no hardware to test on) --- spaghetti-monster/anduril/cfg-noctigon-k1-sbt90.h | 57 +++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 spaghetti-monster/anduril/cfg-noctigon-k1-sbt90.h (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-k1-sbt90.h b/spaghetti-monster/anduril/cfg-noctigon-k1-sbt90.h new file mode 100644 index 0000000..fde5f3e --- /dev/null +++ b/spaghetti-monster/anduril/cfg-noctigon-k1-sbt90.h @@ -0,0 +1,57 @@ +// Noctigon K1-SBT90.2 config options for Anduril +// (is a K1 host with a KR4-like driver and a really high-powered LED) +#include "hwdef-Noctigon_K1-SBT90.h" +// ATTINY: 1634 + +// this light has three aux LED channels: R, G, B +#define USE_AUX_RGB_LEDS +#define USE_AUX_RGB_LEDS_WHILE_ON +#define USE_INDICATOR_LED_WHILE_RAMPING +#define RGB_LED_OFF_DEFAULT 0x18 // low, voltage +#define RGB_LED_LOCKOUT_DEFAULT 0x37 // blinking, rainbow +#define RGB_RAINBOW_SPEED 0x03 // half a second per color + +// enable blinking aux LEDs +#define TICK_DURING_STANDBY +#define STANDBY_TICK_SPEED 3 // every 0.128 s + + +// brightness: +// 0/1023: 0.35 lm +// 1/1023: 2.56 lm +// max regulated: 1740 lm +// FET: ~3700 lm +// maxreg at 130: level_calc.py cube 2 150 7135 0 2.5 1740 FET 1 10 2565 +// maxreg at 120: level_calc.py cube 2 150 7135 0 2.5 1740 FET 1 10 3190 +#define RAMP_LENGTH 150 +#define PWM1_LEVELS 0,0,1,1,2,2,3,3,4,4,5,6,7,8,9,10,11,13,14,15,17,19,20,22,24,26,28,30,33,35,38,40,43,46,49,52,55,59,62,66,70,74,78,82,86,91,96,100,105,111,116,121,127,133,139,145,151,158,165,172,179,186,193,201,209,217,225,234,243,251,261,270,280,289,299,310,320,331,342,353,364,376,388,400,412,425,438,451,464,478,492,506,521,536,551,566,582,597,614,630,647,664,681,699,717,735,754,772,792,811,831,851,871,892,913,935,956,978,1001,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,51,79,109,138,168,198,229,260,292,324,357,390,423,457,492,527,562,598,634,671,708,746,784,822,861,901,941,982,1023 +#define DEFAULT_LEVEL 46 +#define MAX_1x7135 120 +#define HALFSPEED_LEVEL 10 +#define QUARTERSPEED_LEVEL 2 + +#define RAMP_SMOOTH_FLOOR 3 // level 1 is unreliable +#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 + +#define MUGGLE_FLOOR RAMP_DISCRETE_FLOOR +#define MUGGLE_CEILING 65 + +// stop panicking at ~25% power or ~1000 lm +#define THERM_FASTER_LEVEL 120 +#define MIN_THERM_STEPDOWN DEFAULT_LEVEL +//#define THERM_NEXT_WARNING_THRESHOLD 16 // accumulate less error before adjusting +//#define THERM_RESPONSE_MAGNITUDE 128 // bigger adjustments + +// easier access to thermal config mode, for Noctigon +#define USE_TENCLICK_THERMAL_CONFIG + +// slow down party strobe; this driver can't pulse for 1ms or less +#define PARTY_STROBE_ONTIME 2 + +#define THERM_CAL_OFFSET 5 + -- cgit v1.2.3 From 11e2778dabb5ff6fa12475c752044c7ff35cf94c Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 14 May 2020 16:20:33 -0600 Subject: fixed build when USE_GOODNIGHT_MODE not enabled --- spaghetti-monster/anduril/anduril.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 8a9584e..a23b2e1 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -1593,11 +1593,25 @@ uint8_t battcheck_state(Event event, uint16_t arg) { set_state(off_state, 0); return MISCHIEF_MANAGED; } + #ifdef USE_GOODNIGHT_MODE // 2 clicks: goodnight mode else if (event == EV_2clicks) { set_state(goodnight_state, 0); return MISCHIEF_MANAGED; } + #elif defined(USE_BEACON_MODE) + // 2 clicks: beacon mode + else if (event == EV_2clicks) { + set_state(beacon_state, 0); + return MISCHIEF_MANAGED; + } + #elif defined(USE_THERMAL_REGULATION) + // 2 clicks: tempcheck mode + else if (event == EV_2clicks) { + set_state(tempcheck_state, 0); + return MISCHIEF_MANAGED; + } + #endif return EVENT_NOT_HANDLED; } #endif -- cgit v1.2.3 From 72542bdb90a0ab9e7a7dc8faad86a646507ef6f7 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 14 May 2020 16:29:29 -0600 Subject: fixed build of "momentary" example UI --- spaghetti-monster/fsm-events.h | 2 +- spaghetti-monster/momentary/momentary.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-events.h b/spaghetti-monster/fsm-events.h index 6760fdd..a132d5a 100644 --- a/spaghetti-monster/fsm-events.h +++ b/spaghetti-monster/fsm-events.h @@ -218,8 +218,8 @@ void emit(Event event, uint16_t arg); void emit_current_event(uint16_t arg); uint8_t nice_delay_ms(uint16_t ms); -//uint8_t nice_delay_4ms(uint8_t ms); //uint8_t nice_delay_s(); inline void interrupt_nice_delays(); +void delay_4ms(uint8_t ms); #endif diff --git a/spaghetti-monster/momentary/momentary.c b/spaghetti-monster/momentary/momentary.c index 26acd44..c7a8cf1 100644 --- a/spaghetti-monster/momentary/momentary.c +++ b/spaghetti-monster/momentary/momentary.c @@ -22,7 +22,6 @@ #include "hwdef-Emisar_D4.h" #define USE_LVP #define USE_DEBUG_BLINK -#define USE_DELAY_4MS #include "spaghetti-monster.h" volatile uint8_t brightness; -- cgit v1.2.3 From 4958a769029f7d1f444c5662fc0bee54a377229e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 14 May 2020 16:49:14 -0600 Subject: fixed eeprom_wl functions on attiny1634 (didn't build before, due to a data type mismatch) --- spaghetti-monster/fsm-eeprom.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/fsm-eeprom.c b/spaghetti-monster/fsm-eeprom.c index 77352cf..0de7e05 100644 --- a/spaghetti-monster/fsm-eeprom.c +++ b/spaghetti-monster/fsm-eeprom.c @@ -67,7 +67,7 @@ void save_eeprom() { #ifdef USE_EEPROM_WL uint8_t eeprom_wl[EEPROM_WL_BYTES]; -EEP_OFFSET_T eep_wl_prev_offset; +uint8_t * eep_wl_prev_offset; uint8_t load_eeprom_wl() { #ifdef LED_ENABLE_PIN @@ -77,11 +77,11 @@ uint8_t load_eeprom_wl() { cli(); // check if eeprom has been initialized; abort if it hasn't uint8_t found = 0; - EEP_OFFSET_T offset; + uint8_t * offset; for(offset = 0; - offset < EEP_WL_SIZE - EEPROM_WL_BYTES - 1; + offset < (uint8_t *)(EEP_WL_SIZE - EEPROM_WL_BYTES - 1); offset += (EEPROM_WL_BYTES + 1)) { - if (eeprom_read_byte((uint8_t *)offset) == EEP_MARKER) { + if (eeprom_read_byte(offset) == EEP_MARKER) { found = 1; eep_wl_prev_offset = offset; break; @@ -91,7 +91,7 @@ uint8_t load_eeprom_wl() { if (found) { // load the actual data for(uint8_t i=0; i EEP_WL_SIZE-EEPROM_WL_BYTES-1) offset = 0; + if (offset > (uint8_t *)(EEP_WL_SIZE-EEPROM_WL_BYTES-1)) offset = 0; eep_wl_prev_offset = offset; // marker byte // FIXME: write the marker last, to signal completed transaction - eeprom_update_byte((uint8_t *)offset, EEP_MARKER); + eeprom_update_byte(offset, EEP_MARKER); offset ++; // user data for(uint8_t i=0; i TICKS_PER_SECOND*5) { // sleep after 5 seconds go_to_standby = 1; // sleep while light is off // turn off lighted button @@ -1898,7 +1902,9 @@ uint8_t momentary_state(Event event, uint16_t arg) { rgb_led_update(0, 0); #endif } + #ifdef USE_STROBE_STATE } + #endif return MISCHIEF_MANAGED; } -- cgit v1.2.3 From 55e9741b187221a97ddb7cda5547be04dfd0b005 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 1 Jun 2020 20:56:58 -0600 Subject: K1-SBT90.2 doesn't need party strobe slowed down --- spaghetti-monster/anduril/cfg-noctigon-k1-sbt90.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/cfg-noctigon-k1-sbt90.h b/spaghetti-monster/anduril/cfg-noctigon-k1-sbt90.h index fde5f3e..fd98979 100644 --- a/spaghetti-monster/anduril/cfg-noctigon-k1-sbt90.h +++ b/spaghetti-monster/anduril/cfg-noctigon-k1-sbt90.h @@ -3,6 +3,10 @@ #include "hwdef-Noctigon_K1-SBT90.h" // ATTINY: 1634 +// this light can safely run a bit hotter than most +#undef DEFAULT_THERM_CEIL +#define DEFAULT_THERM_CEIL 55 + // this light has three aux LED channels: R, G, B #define USE_AUX_RGB_LEDS #define USE_AUX_RGB_LEDS_WHILE_ON @@ -51,7 +55,7 @@ #define USE_TENCLICK_THERMAL_CONFIG // slow down party strobe; this driver can't pulse for 1ms or less -#define PARTY_STROBE_ONTIME 2 +//#define PARTY_STROBE_ONTIME 2 #define THERM_CAL_OFFSET 5 -- cgit v1.2.3 From 45c6e163739d3ac095f283d07b31e65d6218e0b6 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 1 Jun 2020 20:58:45 -0600 Subject: "SOS" is treated as one "letter" in Morse code... it's not three letters (so, don't put the normal inter-letter gap between) --- spaghetti-monster/anduril/anduril.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'spaghetti-monster') diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c index 167c14d..01904dc 100644 --- a/spaghetti-monster/anduril/anduril.c +++ b/spaghetti-monster/anduril/anduril.c @@ -1572,7 +1572,8 @@ void sos_blink(uint8_t num, uint8_t dah) { nice_delay_ms(DIT_LENGTH); } // three "off" dits (or one "dah") between letters - nice_delay_ms(DIT_LENGTH*2); + // (except for SOS, which is collectively treated as a single "letter") + //nice_delay_ms(DIT_LENGTH*2); } inline void sos_mode_iter() { -- cgit v1.2.3