aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSelene ToyKeeper2019-08-05 01:40:20 -0600
committerSelene ToyKeeper2019-08-05 01:40:20 -0600
commit25f430e0b0b25d57cccc53debe4f8ee48b5f634e (patch)
tree0f57ee7b64882559db8957354ea1ddabf25aad0c
parentensure muggle thermal step-down can't overflow or wrap around (diff)
downloadanduril-25f430e0b0b25d57cccc53debe4f8ee48b5f634e.tar.gz
anduril-25f430e0b0b25d57cccc53debe4f8ee48b5f634e.tar.bz2
anduril-25f430e0b0b25d57cccc53debe4f8ee48b5f634e.zip
merged a sanitized copy of the Emisar D4v2 branch; history summarized below:
------------------------------------------------------------ revno: 457 committer: Selene ToyKeeper <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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 <git@toykeeper.net> 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
-rw-r--r--hwdef-Emisar_D4v2.h100
-rw-r--r--spaghetti-monster/anduril/anduril.c282
-rwxr-xr-xspaghetti-monster/anduril/build-all.sh6
-rw-r--r--spaghetti-monster/anduril/cfg-emisar-d4.h14
-rw-r--r--spaghetti-monster/anduril/cfg-emisar-d4s.h6
-rw-r--r--spaghetti-monster/anduril/cfg-emisar-d4v2-219.h8
-rw-r--r--spaghetti-monster/anduril/cfg-emisar-d4v2.h51
-rw-r--r--spaghetti-monster/fsm-adc.c137
-rw-r--r--spaghetti-monster/fsm-adc.h3
-rw-r--r--spaghetti-monster/fsm-events.c24
-rw-r--r--spaghetti-monster/fsm-main.c56
-rw-r--r--spaghetti-monster/fsm-misc.c35
-rw-r--r--spaghetti-monster/fsm-misc.h7
-rw-r--r--spaghetti-monster/fsm-pcint.c42
-rw-r--r--spaghetti-monster/fsm-ramping.c26
-rw-r--r--spaghetti-monster/fsm-standby.c2
-rw-r--r--spaghetti-monster/fsm-wdt.c82
-rw-r--r--spaghetti-monster/fsm-wdt.h5
-rw-r--r--spaghetti-monster/rampingios/rampingiosv3.c43
-rw-r--r--spaghetti-monster/spaghetti-monster.h1
-rw-r--r--tk-attiny.h55
21 files changed, 797 insertions, 188 deletions
diff --git a/hwdef-Emisar_D4v2.h b/hwdef-Emisar_D4v2.h
new file mode 100644
index 0000000..0460fad
--- /dev/null
+++ b/hwdef-Emisar_D4v2.h
@@ -0,0 +1,100 @@
+#ifndef HWDEF_EMISAR_D4V2_H
+#define HWDEF_EMISAR_D4V2_H
+
+/* Emisar D4v2 driver layout (attiny1634)
+ *
+ * Pin / Name / Function
+ * 1 PA6 FET PWM (PWM1B)
+ * 2 PA5 red aux LED (PWM0B)
+ * 3 PA4 green aux LED
+ * 4 PA3 blue aux LED
+ * 5 PA2 e-switch
+ * 6 PA1 (none)
+ * 7 PA0 (none)
+ * 8 GND GND
+ * 9 VCC VCC
+ * 10 PC5 (none)
+ * 11 PC4 (none)
+ * 12 PC3 RESET
+ * 13 PC2 (none)
+ * 14 PC1 SCK
+ * 15 PC0 (none) PWM0A
+ * 16 PB3 7135 PWM (PWM1A)
+ * 17 PB2 MISO
+ * 18 PB1 MOSI
+ * 19 PB0 (none)
+ * 20 PA7 (none)
+ * ADC12 thermal sensor
+ */
+
+#ifdef ATTINY
+#undef ATTINY
+#endif
+#define ATTINY 1634
+#include <avr/io.h>
+
+#define PWM_CHANNELS 2
+
+#define SWITCH_PIN PA2 // pin 5
+#define SWITCH_PCINT PCINT2 // pin 5 pin change interrupt
+#define SWITCH_PCIE PCIE0 // PCIE0 is for PCINT[7:0]
+#define SWITCH_PCMSK PCMSK0 // PCMSK0 is for PCINT[7:0]
+#define SWITCH_PORT PINA // PINA or PINB or PINC
+
+#define PWM1_PIN PB3 // pin 16, 1x7135 PWM
+#define PWM1_LVL OCR1A // OCR1A is the output compare register for PB3
+
+#define PWM2_PIN PA6 // pin 1, FET PWM
+#define PWM2_LVL OCR1B // OCR1B is the output compare register for PB1
+
+
+#define ADC_PRSCL 0x06 // clk/64
+
+// average drop across diode on this hardware
+#ifndef VOLTAGE_FUDGE_FACTOR
+#define VOLTAGE_FUDGE_FACTOR 4 // add 0.20V (measured 0.22V)
+#endif
+
+#define TEMP_CHANNEL 0b00001111
+
+// this light has aux LEDs under the optic
+#define AUXLED_R_PIN PA5 // pin 2
+#define AUXLED_G_PIN PA4 // pin 3
+#define AUXLED_B_PIN PA3 // pin 4
+#define AUXLED_RGB_PORT PORTA // PORTA or PORTB or PORTC
+#define AUXLED_RGB_DDR DDRA // DDRA or DDRB or DDRC
+#define AUXLED_RGB_PUE PUEA // PUEA or PUEB or PUEC
+
+// with so many pins, doing this all with #ifdefs gets awkward...
+// ... so just hardcode it in each hwdef file instead
+inline void hwdef_setup() {
+ // enable output ports
+ // 7135
+ DDRB = (1 << PWM1_PIN);
+ // FET, aux R/G/B
+ DDRA = (1 << PWM2_PIN)
+ | (1 << AUXLED_R_PIN)
+ | (1 << AUXLED_G_PIN)
+ | (1 << AUXLED_B_PIN)
+ ;
+
+ // configure PWM
+ // Setup PWM. F_pwm = F_clkio / 2 / N / TOP, where N = prescale factor, TOP = top of counter
+ // pre-scale for timer: N = 1
+ TCCR1A = (0<<WGM11) | (1<<WGM10) // 8-bit (TOP=0xFF) (DS table 12-5)
+ | (1<<COM1A1) | (0<<COM1A0) // PWM 1A in normal direction (DS table 12-4)
+ | (1<<COM1B1) | (0<<COM1B0) // PWM 1B in normal direction (DS table 12-4)
+ ;
+ TCCR1B = (0<<CS12) | (0<<CS11) | (1<<CS10) // clk/1 (no prescaling) (DS table 12-6)
+ | (0<<WGM13) | (0<<WGM12) // phase-correct PWM (DS table 12-5)
+ ;
+
+ // set up e-switch
+ //PORTA = (1 << SWITCH_PIN); // TODO: configure PORTA / PORTB / PORTC?
+ PUEA = (1 << SWITCH_PIN); // pull-up for e-switch
+ SWITCH_PCMSK = (1 << SWITCH_PCINT); // enable pin change interrupt
+}
+
+#define LAYOUT_DEFINED
+
+#endif
diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c
index 24211d7..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
- int16_t new = actual_level - arg;
- if (new < MUGGLE_FLOOR) { new = MUGGLE_FLOOR; }
- set_level(new);
+ // ignore warnings while off
+ if (! muggle_off_mode) {
+ // step down proportional to the amount of overheating
+ int16_t new = actual_level - arg;
+ if (new < MUGGLE_FLOOR) { new = MUGGLE_FLOOR; }
+ set_level(new);
+ }
return MISCHIEF_MANAGED;
}
#endif
@@ -2135,6 +2223,9 @@ void blip() {
#if defined(USE_INDICATOR_LED) && defined(TICK_DURING_STANDBY)
// beacon-like mode for the indicator LED
void indicator_blink(uint8_t arg) {
+ // turn off aux LEDs when battery is empty
+ if (voltage < VOLTAGE_LOW) { indicator_led(0); return; }
+
#ifdef USE_FANCIER_BLINKING_INDICATOR
// fancy blink, set off/low/high levels here:
@@ -2155,6 +2246,81 @@ void indicator_blink(uint8_t arg) {
}
#endif
+#if defined(USE_AUX_RGB_LEDS) && defined(TICK_DURING_STANDBY)
+// do fancy stuff with the RGB aux LEDs
+// mode: 0bPPPPCCCC where PPPP is the pattern and CCCC is the color
+// arg: time slice number
+void rgb_led_update(uint8_t mode, uint8_t arg) {
+ static uint8_t rainbow = 0; // track state of rainbow mode
+ static uint8_t frame = 0; // track state of animation mode
+
+ // turn off aux LEDs when battery is empty
+ // (but if voltage==0, that means we just booted and don't know yet)
+ uint8_t volts = voltage; // save a few bytes by caching volatile value
+ if ((volts) && (volts < VOLTAGE_LOW)) { rgb_led_set(0); return; }
+
+ uint8_t pattern = (mode>>4); // off, low, high, blinking, ... more?
+ uint8_t color = mode & 0x0f;
+
+ // preview in blinking mode is awkward... use high instead
+ if ((! go_to_standby) && (pattern > 2)) { pattern = 2; }
+
+
+ uint8_t colors[] = {
+ 0b00000001, // 0: red
+ 0b00000101, // 1: yellow
+ 0b00000100, // 2: green
+ 0b00010100, // 3: cyan
+ 0b00010000, // 4: blue
+ 0b00010001, // 5: purple
+ 0b00010101, // 6: white
+ };
+ uint8_t actual_color = 0;
+ if (color < 7) { // normal color
+ actual_color = colors[color];
+ }
+ else if (color == 7) { // rainbow
+ if (0 == (arg & 0x03)) {
+ rainbow = (rainbow + 1) % 6;
+ }
+ actual_color = colors[rainbow];
+ }
+ else { // voltage
+ // show actual voltage while asleep...
+ if (go_to_standby) {
+ // choose a color based on battery voltage
+ if (volts >= 38) actual_color = colors[4];
+ else if (volts >= 33) actual_color = colors[2];
+ else actual_color = colors[0];
+ }
+ // ... but during preview, cycle colors quickly
+ else {
+ actual_color = colors[((arg>>1) % 3) << 1];
+ }
+ }
+
+ // pick a brightness from the animation sequence
+ if (pattern == 3) {
+ // uses an odd length to avoid lining up with rainbow loop
+ uint8_t animation[] = {2, 1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+ frame = (frame + 1) % sizeof(animation);
+ pattern = animation[frame];
+ }
+ switch (pattern) {
+ case 0: // off
+ rgb_led_set(0);
+ break;
+ case 1: // low
+ rgb_led_set(actual_color);
+ break;
+ case 2: // high
+ rgb_led_set(actual_color << 1);
+ break;
+ }
+}
+#endif
+
#ifdef USE_FACTORY_RESET
void factory_reset() {
@@ -2242,6 +2408,10 @@ void load_config() {
#ifdef USE_INDICATOR_LED
indicator_led_mode = eeprom[indicator_led_mode_e];
#endif
+ #ifdef USE_AUX_RGB_LEDS
+ rgb_led_off_mode = eeprom[rgb_led_off_mode_e];
+ rgb_led_lockout_mode = eeprom[rgb_led_lockout_mode_e];
+ #endif
}
#ifdef START_AT_MEMORIZED_LEVEL
if (load_eeprom_wl()) {
@@ -2286,6 +2456,10 @@ void save_config() {
#ifdef USE_INDICATOR_LED
eeprom[indicator_led_mode_e] = indicator_led_mode;
#endif
+ #ifdef USE_AUX_RGB_LEDS
+ eeprom[rgb_led_off_mode_e] = rgb_led_off_mode;
+ eeprom[rgb_led_lockout_mode_e] = rgb_led_lockout_mode;
+ #endif
save_eeprom();
}
@@ -2372,7 +2546,7 @@ void setup() {
push_state(muggle_state, (MUGGLE_FLOOR+MUGGLE_CEILING)/2);
else
#endif
- push_state(off_state, 0);
+ push_state(off_state, 1);
#endif // ifdef START_AT_MEMORIZED_LEVEL
}
diff --git a/spaghetti-monster/anduril/build-all.sh b/spaghetti-monster/anduril/build-all.sh
index c355f1e..56a88bf 100755
--- a/spaghetti-monster/anduril/build-all.sh
+++ b/spaghetti-monster/anduril/build-all.sh
@@ -5,7 +5,9 @@ UI=anduril
for TARGET in cfg-*.h ; do
NAME=$(echo "$TARGET" | perl -ne '/cfg-(.*).h/ && print "$1\n";')
echo "===== $NAME ====="
- echo ../../../bin/build.sh 85 "$UI" "-DCONFIGFILE=${TARGET}"
- ../../../bin/build.sh 85 "$UI" "-DCONFIGFILE=${TARGET}"
+ ATTINY=$(grep 'ATTINY:' $TARGET | awk '{ print $3 }')
+ if [ -z "$ATTINY" ]; then ATTINY=85 ; fi
+ echo ../../../bin/build.sh $ATTINY "$UI" "-DCONFIGFILE=${TARGET}"
+ ../../../bin/build.sh $ATTINY "$UI" "-DCONFIGFILE=${TARGET}"
mv -f "$UI".hex "$UI".$NAME.hex
done
diff --git a/spaghetti-monster/anduril/cfg-emisar-d4.h b/spaghetti-monster/anduril/cfg-emisar-d4.h
index de8f796..c86a534 100644
--- a/spaghetti-monster/anduril/cfg-emisar-d4.h
+++ b/spaghetti-monster/anduril/cfg-emisar-d4.h
@@ -9,7 +9,14 @@
#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,4,5,7,8,9,11,12,14,15,17,19,20,22,24,25,27,29,31,33,35,37,39,41,43,45,48,50,52,55,57,59,62,64,67,70,72,75,78,81,84,87,90,93,96,99,102,105,109,112,115,119,122,126,129,133,137,141,144,148,152,156,160,165,169,173,177,182,186,191,195,200,205,209,214,219,224,229,234,239,244,250,255
#define MAX_1x7135 65
#define HALFSPEED_LEVEL 14
-#define QUARTERSPEED_LEVEL 5
+#define QUARTERSPEED_LEVEL 6
+
+#define RAMP_SMOOTH_FLOOR 1
+#define RAMP_SMOOTH_CEIL 120
+// 10, 28, 46, [65], 83, 101, 120
+#define RAMP_DISCRETE_FLOOR 10
+#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL
+#define RAMP_DISCRETE_STEPS 7
// optional, makes initial turbo step-down faster so first peak isn't as hot
// the D4 runs very very hot, so be extra careful
@@ -17,3 +24,8 @@
// stop panicking at ~30% power or ~1200 lm
#define THERM_FASTER_LEVEL 105
+// respond to thermal changes faster
+#define THERMAL_WARNING_SECONDS 3
+#define THERMAL_UPDATE_SPEED 1
+#define THERM_PREDICTION_STRENGTH 4
+
diff --git a/spaghetti-monster/anduril/cfg-emisar-d4s.h b/spaghetti-monster/anduril/cfg-emisar-d4s.h
index d19a514..230ac7c 100644
--- a/spaghetti-monster/anduril/cfg-emisar-d4s.h
+++ b/spaghetti-monster/anduril/cfg-emisar-d4s.h
@@ -36,9 +36,13 @@
#undef MIN_THERM_STEPDOWN // this should be lower, because 3x7135 instead of 1x7135
#endif
#define MIN_THERM_STEPDOWN 60 // lowest value it'll step down to
-#define THERM_FASTER_LEVEL (RAMP_SIZE-1) // don't throttle back faster when high
+#define THERM_FASTER_LEVEL (RAMP_SIZE-20) // don't throttle back faster when high
// no need to be extra-careful on this light
#ifdef THERM_HARD_TURBO_DROP
#undef THERM_HARD_TURBO_DROP
#endif
+
+#define THERMAL_WARNING_SECONDS 3
+#define THERMAL_UPDATE_SPEED 2
+#define THERM_PREDICTION_STRENGTH 4
diff --git a/spaghetti-monster/anduril/cfg-emisar-d4v2-219.h b/spaghetti-monster/anduril/cfg-emisar-d4v2-219.h
new file mode 100644
index 0000000..0770935
--- /dev/null
+++ b/spaghetti-monster/anduril/cfg-emisar-d4v2-219.h
@@ -0,0 +1,8 @@
+// Emisar D4v2-219 config options for Anduril
+#include "cfg-emisar-d4v2.h"
+// ATTINY: 1634
+
+#undef PWM1_LEVELS
+#undef PWM2_LEVELS
+#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,7,8,9,10,12,13,14,15,17,19,20,22,24,26,29,31,34,36,39,42,45,48,51,55,59,62,66,70,75,79,84,89,93,99,104,110,115,121,127,134,140,147,154,161,168,176,184,192,200,209,217,226,236,245,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
+#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,3,5,6,6,8,9,10,11,12,14,15,16,18,18,20,21,23,24,26,27,29,30,32,33,36,37,39,41,43,44,46,48,50,52,54,56,58,61,63,65,67,70,72,74,77,79,82,84,86,89,92,95,97,100,103,106,108,111,114,117,120,124,127,130,133,137,140,144,147,151,154,157,161,165,169,172,176,180,184,188,192
diff --git a/spaghetti-monster/anduril/cfg-emisar-d4v2.h b/spaghetti-monster/anduril/cfg-emisar-d4v2.h
new file mode 100644
index 0000000..b83c65c
--- /dev/null
+++ b/spaghetti-monster/anduril/cfg-emisar-d4v2.h
@@ -0,0 +1,51 @@
+// Emisar D4 config options for Anduril
+#include "hwdef-Emisar_D4v2.h"
+// ATTINY: 1634
+
+// this light has three aux LED channels: R, G, B
+#define USE_AUX_RGB_LEDS
+// the aux LEDs are front-facing, so turn them off while main LEDs are on
+#ifdef USE_INDICATOR_LED_WHILE_RAMPING
+#undef USE_INDICATOR_LED_WHILE_RAMPING
+#endif
+// enable blinking aux LEDs
+#define TICK_DURING_STANDBY
+#define STANDBY_TICK_SPEED 3 // every 0.128 s
+//#define STANDBY_TICK_SPEED 4 // every 0.256 s
+//#define STANDBY_TICK_SPEED 5 // every 0.512 s
+
+
+// copied from original D4, since it's also a FET+1 and has the same host
+// ../../bin/level_calc.py 1 65 7135 1 0.8 150
+// ... mixed with this:
+// ../../bin/level_calc.py 2 150 7135 4 0.33 150 FET 1 10 1500
+#define RAMP_LENGTH 150
+#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,7,8,9,10,12,13,14,15,17,19,20,22,24,26,29,31,34,36,39,42,45,48,51,55,59,62,66,70,75,79,84,89,93,99,104,110,115,121,127,134,140,147,154,161,168,176,184,192,200,209,217,226,236,245,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0
+#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,4,5,7,8,9,11,12,14,15,17,19,20,22,24,25,27,29,31,33,35,37,39,41,43,45,48,50,52,55,57,59,62,64,67,70,72,75,78,81,84,87,90,93,96,99,102,105,109,112,115,119,122,126,129,133,137,141,144,148,152,156,160,165,169,173,177,182,186,191,195,200,205,209,214,219,224,229,234,239,244,250,255
+#define MAX_1x7135 65
+#define HALFSPEED_LEVEL 14
+#define QUARTERSPEED_LEVEL 6
+
+#define RAMP_SMOOTH_FLOOR 1
+#define RAMP_SMOOTH_CEIL 120
+// 10, 28, 46, [65], 83, 101, 120
+#define RAMP_DISCRETE_FLOOR 10
+#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL
+#define RAMP_DISCRETE_STEPS 7
+
+// optional, makes initial turbo step-down faster so first peak isn't as hot
+// the D4 runs very very hot, so be extra careful
+//#define THERM_HARD_TURBO_DROP
+
+// stop panicking at ~30% power or ~1200 lm
+#define THERM_FASTER_LEVEL 105
+// respond to thermal changes faster
+#define THERMAL_WARNING_SECONDS 3
+#define THERMAL_UPDATE_SPEED 1
+#define THERM_PREDICTION_STRENGTH 4
+//#define THERM_RESPONSE_MAGNITUDE 128
+
+// easier access to thermal config mode, for Emisar
+#define USE_TENCLICK_THERMAL_CONFIG
+
+#define THERM_CAL_OFFSET 5
diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c
index bcf49ed..6832e32 100644
--- a/spaghetti-monster/fsm-adc.c
+++ b/spaghetti-monster/fsm-adc.c
@@ -20,27 +20,76 @@
#ifndef FSM_ADC_C
#define FSM_ADC_C
-#ifdef USE_VOLTAGE_DIVIDER
-// 1.1V / pin7
-#define ADMUX_VOLTAGE ADMUX_VOLTAGE_DIVIDER
-#else
-// VCC / 1.1V reference
-#define ADMUX_VOLTAGE ADMUX_VCC
-#endif
+inline void set_admux_therm() {
+ #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 1634)
+ ADMUX = ADMUX_THERM;
+ #elif (ATTINY == 841)
+ ADMUXA = ADMUXA_THERM;
+ ADMUXB = ADMUXB_THERM;
+ #else
+ #error Unrecognized MCU type
+ #endif
+}
+
+inline void set_admux_voltage() {
+ #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 1634)
+ #ifdef USE_VOLTAGE_DIVIDER
+ // 1.1V / pin7
+ ADMUX = ADMUX_VOLTAGE_DIVIDER;
+ #else
+ // VCC / 1.1V reference
+ ADMUX = ADMUX_VCC;
+ #endif
+ #elif (ATTINY == 841)
+ #ifdef USE_VOLTAGE_DIVIDER
+ ADMUXA = ADMUXA_VOLTAGE_DIVIDER;
+ ADMUXB = ADMUXB_VOLTAGE_DIVIDER;
+ #else
+ ADMUXA = ADMUXA_VCC;
+ ADMUXB = ADMUXB_VCC;
+ #endif
+ #else
+ #error Unrecognized MCU type
+ #endif
+}
+
+inline void ADC_start_measurement() {
+ #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 841) || (ATTINY == 1634)
+ ADCSRA |= (1 << ADSC) | (1 << ADIE);
+ #else
+ #error unrecognized MCU type
+ #endif
+}
+
+// set up ADC for reading battery voltage
inline void ADC_on()
{
- // read voltage on VCC by default
- ADMUX = ADMUX_VOLTAGE;
- #ifdef USE_VOLTAGE_DIVIDER
- // disable digital input on divider pin to reduce power consumption
- DIDR0 |= (1 << VOLTAGE_ADC_DIDR);
+ #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 1634)
+ set_admux_voltage();
+ #ifdef USE_VOLTAGE_DIVIDER
+ // disable digital input on divider pin to reduce power consumption
+ DIDR0 |= (1 << VOLTAGE_ADC_DIDR);
+ #else
+ // disable digital input on VCC pin to reduce power consumption
+ //DIDR0 |= (1 << ADC_DIDR); // FIXME: unsure how to handle for VCC pin
+ #endif
+ #if (ATTINY == 1634)
+ ACSRA |= (1 << ACD); // turn off analog comparator to save power
+ #endif
+ // enable, start, prescale
+ ADCSRA = (1 << ADEN) | (1 << ADSC) | ADC_PRSCL;
+ // end tiny25/45/85
+ #elif (ATTINY == 841)
+ ADCSRB = 0; // Right adjusted, auto trigger bits cleared.
+ //ADCSRA = (1 << ADEN ) | 0b011; // ADC on, prescaler division factor 8.
+ set_admux_voltage();
+ // enable, start, prescale
+ ADCSRA = (1 << ADEN) | (1 << ADSC) | ADC_PRSCL;
+ //ADCSRA |= (1 << ADSC); // start measuring
#else
- // disable digital input on VCC pin to reduce power consumption
- //DIDR0 |= (1 << ADC_DIDR); // FIXME: unsure how to handle for VCC pin
+ #error Unrecognized MCU type
#endif
- // enable, start, prescale
- ADCSRA = (1 << ADEN) | (1 << ADSC) | ADC_PRSCL;
}
inline void ADC_off() {
@@ -89,6 +138,9 @@ ISR(ADC_vect) {
// thermal declarations
#ifdef USE_THERMAL_REGULATION
+ #ifndef THERMAL_UPDATE_SPEED
+ #define THERMAL_UPDATE_SPEED 2
+ #endif
#define NUM_THERMAL_VALUES_HISTORY 8
#define ADC_STEPS 4
static uint8_t history_step = 0; // don't update history as often
@@ -96,7 +148,7 @@ ISR(ADC_vect) {
static uint8_t temperature_timer = 0;
static uint8_t overheat_lowpass = 0;
static uint8_t underheat_lowpass = 0;
- #define TEMPERATURE_TIMER_START (THERMAL_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) // N seconds between thermal regulation events
+ #define TEMPERATURE_TIMER_START ((THERMAL_WARNING_SECONDS-2)*ADC_CYCLES_PER_SECOND) // N seconds between thermal regulation events
#define OVERHEAT_LOWPASS_STRENGTH (ADC_CYCLES_PER_SECOND*2) // lowpass for 2 seconds
#define UNDERHEAT_LOWPASS_STRENGTH (ADC_CYCLES_PER_SECOND*2) // lowpass for 2 seconds
#else
@@ -110,6 +162,12 @@ ISR(ADC_vect) {
pseudo_rand_seed += measurement;
#endif
+ #if defined(TICK_DURING_STANDBY) && defined(USE_SLEEP_LVP)
+ // only measure battery voltage while asleep
+ if (go_to_standby) adc_step = 1;
+ else
+ #endif
+
adc_step = (adc_step + 1) & (ADC_STEPS-1);
#ifdef USE_LVP
@@ -120,7 +178,7 @@ ISR(ADC_vect) {
if (voltage == 0) {
for(uint8_t i=0; i<NUM_VOLTAGE_VALUES; i++)
voltage_values[i] = measurement;
- voltage = 42; // Life, the Universe, and Everything (*)
+ voltage = 42; // the answer to life, the universe, and the voltage of a full li-ion cell
} else {
uint16_t total = 0;
uint8_t i;
@@ -181,7 +239,7 @@ ISR(ADC_vect) {
// temperature
else if (adc_step == 3) {
// Convert ADC units to Celsius (ish)
- int16_t temp = measurement - 275 + THERM_CAL_OFFSET + therm_cal_offset;
+ int16_t temp = measurement - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset;
// prime on first execution
if (reset_thermal_history) {
@@ -202,14 +260,18 @@ ISR(ADC_vect) {
// guess what the temperature will be in a few seconds
int16_t pt;
{
- uint8_t i;
int16_t diff;
int16_t t = temperature;
// algorithm tweaking; not really intended to be modified
// how far ahead should we predict?
+ #ifndef THERM_PREDICTION_STRENGTH
#define THERM_PREDICTION_STRENGTH 4
- // how proportional should the adjustments be?
+ #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
@@ -219,13 +281,22 @@ ISR(ADC_vect) {
// if it's time to rotate the thermal history, do it
history_step ++;
- if (0 == (history_step & 7)) {
+ #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 (i=0; i<NUM_THERMAL_VALUES_HISTORY-1; i++) {
+ for (uint8_t i=0; i<NUM_THERMAL_VALUES_HISTORY-1; i++) {
temperature_history[i] = temperature_history[i+1];
}
+ temperature_history[NUM_THERMAL_VALUES_HISTORY-1] = t;
}
- temperature_history[NUM_THERMAL_VALUES_HISTORY-1] = t;
// guess what the temp will be several seconds in the future
// diff = rate of temperature change
@@ -244,7 +315,8 @@ ISR(ADC_vect) {
// cancel counters if appropriate
if (pt > 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<<CLKPCE; CLKPR = 2;
+ clock_prescale_set(clock_div_4);
_delay_loop_2(BOGOMIPS*98/100/4);
}
//else if (level < HALFSPEED_LEVEL) {
- // CLKPR = 1<<CLKPCE; CLKPR = 1;
+ // clock_prescale_set(clock_div_2);
// _delay_loop_2(BOGOMIPS*98/100/2);
//}
else {
- CLKPR = 1<<CLKPCE; CLKPR = 0;
+ clock_prescale_set(clock_div_1);
_delay_loop_2(BOGOMIPS*98/100);
}
// restore regular clock speed
- CLKPR = 1<<CLKPCE; CLKPR = 0;
+ clock_prescale_set(clock_div_1);
#else
// underclock MCU to save power
- CLKPR = 1<<CLKPCE; CLKPR = 2;
+ clock_prescale_set(clock_div_4);
// wait
_delay_loop_2(BOGOMIPS*98/100/4);
// restore regular clock speed
- CLKPR = 1<<CLKPCE; CLKPR = 0;
+ clock_prescale_set(clock_div_1);
#endif // ifdef USE_RAMPING
#else
// wait
@@ -159,11 +160,18 @@ uint8_t nice_delay_ms(uint16_t ms) {
void delay_4ms(uint8_t ms) {
while(ms-- > 0) {
// underclock MCU to save power
- CLKPR = 1<<CLKPCE; CLKPR = 2;
+ clock_prescale_set(clock_div_4);
// wait
_delay_loop_2(BOGOMIPS*98/100);
// restore regular clock speed
- CLKPR = 1<<CLKPCE; CLKPR = 0;
+ clock_prescale_set(clock_div_1);
+ }
+}
+#else
+void delay_4ms(uint8_t ms) {
+ while(ms-- > 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<<WDRF); // reset status flag
- wdt_disable();
- #endif
-
- #ifdef HALFSPEED
- // run at half speed
- CLKPR = 1<<CLKPCE;
- CLKPR = 1;
- #endif
-
+#if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85)
+inline void hw_setup() {
// configure PWM channels
#if PWM_CHANNELS >= 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<<WDRF); // reset status flag
+ wdt_disable();
+}
+#endif
+
+
+int main() {
+ // Don't allow interrupts while booting
+ cli();
+
+ #ifdef USE_REBOOT
+ prevent_reboot_loop();
+ #endif
+
+ hw_setup();
+
+ #if 0
+ #ifdef HALFSPEED
+ // run at half speed
+ // FIXME: not portable (also not needed)
+ CLKPR = 1<<CLKPCE;
+ CLKPR = 1;
+ #endif
+ #endif
#ifdef USE_DEBUG_BLINK
//debug_blink(1);
diff --git a/spaghetti-monster/fsm-misc.c b/spaghetti-monster/fsm-misc.c
index eced482..8e88cbd 100644
--- a/spaghetti-monster/fsm-misc.c
+++ b/spaghetti-monster/fsm-misc.c
@@ -20,6 +20,7 @@
#ifndef FSM_MISC_C
#define FSM_MISC_C
+
#ifdef USE_DYNAMIC_UNDERCLOCKING
void auto_clock_speed() {
uint8_t level = actual_level; // volatile, avoid repeat access
@@ -27,14 +28,14 @@ void auto_clock_speed() {
// run at quarter speed
// note: this only works when executed as two consecutive instructions
// (don't try to combine them or put other stuff between)
- CLKPR = 1<<CLKPCE; CLKPR = 2;
+ clock_prescale_set(clock_div_4);
}
else if (level < HALFSPEED_LEVEL) {
// run at half speed
- CLKPR = 1<<CLKPCE; CLKPR = 1;
+ clock_prescale_set(clock_div_2);
} else {
// run at full speed
- CLKPR = 1<<CLKPCE; CLKPR = 0;
+ clock_prescale_set(clock_div_1);
}
}
#endif
@@ -146,6 +147,34 @@ void indicator_led_auto() {
*/
#endif // USE_INDICATOR_LED
+#ifdef USE_AUX_RGB_LEDS
+void rgb_led_set(uint8_t value) {
+ // value: 0b00BBGGRR
+ uint8_t pins[] = { AUXLED_R_PIN, AUXLED_G_PIN, AUXLED_B_PIN };
+ for (uint8_t i=0; i<3; i++) {
+ uint8_t lvl = (value >> (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<<SWITCH_PIN)) == 0);
+ readings = (readings << 1) | ((SWITCH_PORT & (1<<SWITCH_PIN)) == 0);
// wait a moment
_delay_loop_2(BOGOMIPS/16); // up to 2ms to stabilize
}
@@ -40,21 +40,45 @@ uint8_t button_is_pressed() {
}
inline void PCINT_on() {
- // enable pin change interrupt for pin N
- GIMSK |= (1 << PCIE);
- // only pay attention to the e-switch pin
- //PCMSK = (1 << SWITCH_PCINT);
- // set bits 1:0 to 0b01 (interrupt on rising *and* falling edge) (default)
- // MCUCR &= 0b11111101; MCUCR |= 0b00000001;
+ #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85)
+ // enable pin change interrupt
+ GIMSK |= (1 << PCIE);
+ // only pay attention to the e-switch pin
+ #if 0 // this is redundant; was already done in main()
+ PCMSK = (1 << SWITCH_PCINT);
+ #endif
+ // set bits 1:0 to 0b01 (interrupt on rising *and* falling edge) (default)
+ // MCUCR &= 0b11111101; MCUCR |= 0b00000001;
+ #elif (ATTINY == 1634)
+ // enable pin change interrupt
+ #ifdef SWITCH2_PCIE
+ GIMSK |= ((1 << SWITCH_PCIE) | (1 << SWITCH2_PCIE));
+ #else
+ GIMSK |= (1 << SWITCH_PCIE);
+ #endif
+ #else
+ #error Unrecognized MCU type
+ #endif
}
inline void PCINT_off() {
- // disable all pin-change interrupts
- GIMSK &= ~(1 << PCIE);
+ #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85)
+ // disable all pin-change interrupts
+ GIMSK &= ~(1 << PCIE);
+ #elif (ATTINY == 1634)
+ // disable all pin-change interrupts
+ GIMSK &= ~(1 << SWITCH_PCIE);
+ #else
+ #error Unrecognized MCU type
+ #endif
}
//void button_change_interrupt() {
+#if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 1634)
EMPTY_INTERRUPT(PCINT0_vect);
+#else
+ #error Unrecognized MCU type
+#endif
/*
ISR(PCINT0_vect) {
diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c
index 082f8c9..efa07e4 100644
--- a/spaghetti-monster/fsm-ramping.c
+++ b/spaghetti-monster/fsm-ramping.c
@@ -30,17 +30,25 @@ void set_level(uint8_t level) {
gradual_target = level;
#endif
- #ifdef USE_INDICATOR_LED
#ifdef USE_INDICATOR_LED_WHILE_RAMPING
- if (! go_to_standby)
- indicator_led((level > 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<<WDCE) | (1<<WDE); // Start timed sequence
- WDTCR = (1<<WDIE); // Enable interrupt every 16ms
- //sei(); // Enable interrupts
+ #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85)
+ // interrupt every 16ms
+ //cli(); // Disable interrupts
+ wdt_reset(); // Reset the WDT
+ WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence
+ WDTCR = (1<<WDIE); // Enable interrupt every 16ms
+ //sei(); // Enable interrupts
+ #elif (ATTINY == 1634)
+ wdt_reset(); // Reset the WDT
+ WDTCSR = (1<<WDIE); // Enable interrupt every 16ms
+ #else
+ #error Unrecognized MCU type
+ #endif
}
#ifdef TICK_DURING_STANDBY
inline void WDT_slow()
{
- // interrupt slower
- //cli(); // Disable interrupts
- wdt_reset(); // Reset the WDT
- WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence
- WDTCR = (1<<WDIE) | STANDBY_TICK_SPEED; // Enable interrupt every so often
- //sei(); // Enable interrupts
+ #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85)
+ // interrupt slower
+ //cli(); // Disable interrupts
+ wdt_reset(); // Reset the WDT
+ WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence
+ WDTCR = (1<<WDIE) | STANDBY_TICK_SPEED; // Enable interrupt every so often
+ //sei(); // Enable interrupts
+ #elif (ATTINY == 1634)
+ wdt_reset(); // Reset the WDT
+ WDTCSR = (1<<WDIE) | STANDBY_TICK_SPEED;
+ #else
+ #error Unrecognized MCU type
+ #endif
}
#endif
inline void WDT_off()
{
- //cli(); // Disable interrupts
- wdt_reset(); // Reset the WDT
- MCUSR &= ~(1<<WDRF); // Clear Watchdog reset flag
- WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence
- WDTCR = 0x00; // Disable WDT
- //sei(); // Enable interrupts
+ #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85)
+ //cli(); // Disable interrupts
+ wdt_reset(); // Reset the WDT
+ MCUSR &= ~(1<<WDRF); // Clear Watchdog reset flag
+ WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence
+ WDTCR = 0x00; // Disable WDT
+ //sei(); // Enable interrupts
+ #elif (ATTINY == 1634)
+ cli(); // needed because CCP, below
+ wdt_reset(); // Reset the WDT
+ MCUSR &= ~(1<<WDRF); // clear watchdog reset flag
+ CCP = 0xD8; // enable config changes
+ WDTCSR = 0; // disable and clear all WDT settings
+ sei();
+ #else
+ #error Unrecognized MCU type
+ #endif
}
// clock tick -- this runs every 16ms (62.5 fps)
ISR(WDT_vect) {
+ static uint8_t adc_trigger = 0;
+
#ifdef TICK_DURING_STANDBY
f_wdt = 1; // WDT event happened
@@ -68,9 +95,16 @@ ISR(WDT_vect) {
// wrap around from 65535 to 32768, not 0
sleep_counter = (sleep_counter + 1) | (sleep_counter & 0x8000);
process_emissions();
- return;
+
+ #if defined(USE_SLEEP_LVP)
+ // stop here, usually... but proceed often enough for sleep LVP to work
+ if (0 != (sleep_counter & 0x7f)) return;
+ adc_trigger = 255; // make sure a measurement will happen
+ #else
+ return; // no sleep LVP needed if nothing drains power while off
+ #endif
}
- sleep_counter = 0;
+ else { sleep_counter = 0; }
#endif
// detect and emit button change events
@@ -136,10 +170,14 @@ ISR(WDT_vect) {
#if defined(USE_LVP) || defined(USE_THERMAL_REGULATION)
// start a new ADC measurement every 4 ticks
- static uint8_t adc_trigger = 0;
adc_trigger ++;
if (0 == (adc_trigger & 3)) {
- ADCSRA |= (1 << ADSC) | (1 << ADIE);
+ #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();
adcint_enable = 1;
}
#endif
diff --git a/spaghetti-monster/fsm-wdt.h b/spaghetti-monster/fsm-wdt.h
index 3c395c1..78fe791 100644
--- a/spaghetti-monster/fsm-wdt.h
+++ b/spaghetti-monster/fsm-wdt.h
@@ -27,6 +27,11 @@ inline void WDT_off();
#ifdef TICK_DURING_STANDBY
volatile uint8_t f_wdt = 0;
+
+ #if defined(USE_INDICATOR_LED) || defined(USE_AUX_RGB_LEDS)
+ // measure battery charge while asleep
+ #define USE_SLEEP_LVP
+ #endif
#endif
#endif
diff --git a/spaghetti-monster/rampingios/rampingiosv3.c b/spaghetti-monster/rampingios/rampingiosv3.c
index e4eb2fa..d72e971 100644
--- a/spaghetti-monster/rampingios/rampingiosv3.c
+++ b/spaghetti-monster/rampingios/rampingiosv3.c
@@ -148,9 +148,6 @@ void blink_confirm(uint8_t num);
#if defined(USE_INDICATOR_LED) && defined(TICK_DURING_STANDBY)
void indicator_blink(uint8_t arg);
#endif
-#ifdef USE_INDICATOR_LED
-uint8_t auxled_next_state(Event event, uint16_t arg);
-#endif
// remember stuff even after battery was changed
void load_config();
@@ -347,7 +344,18 @@ uint8_t off_state(Event event, uint16_t arg) {
// 7 clicks: next aux LED mode
else if (event == EV_7clicks) {
blink_confirm(1);
- set_state(auxled_next_state, 0);
+ uint8_t mode = (indicator_led_mode & 3) + 1;
+ #ifdef TICK_DURING_STANDBY
+ mode = mode & 3;
+ #else
+ mode = mode % 3;
+ #endif
+ #ifdef INDICATOR_LED_SKIP_LOW
+ if (mode == 1) { mode ++; }
+ #endif
+ indicator_led_mode = (indicator_led_mode & 0b11111100) | mode;
+ indicator_led(mode);
+ save_config();
return MISCHIEF_MANAGED;
}
#endif
@@ -811,33 +819,6 @@ uint8_t lockout_state(Event event, uint16_t arg) {
}
-#ifdef USE_INDICATOR_LED
-uint8_t auxled_next_state(Event event, uint16_t arg) {
- if (event == EV_enter_state) {
- uint8_t mode = indicator_led_mode & 3;
- #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 + (indicator_led_mode & 0b00001100);
- indicator_led(mode);
- save_config();
- return MISCHIEF_MANAGED;
- }
- else if (event == EV_tick) {
- set_state(off_state, 0);
- return MISCHIEF_MANAGED;
- }
-
- return EVENT_NOT_HANDLED;
-}
-#endif
-
-
uint8_t momentary_state(Event event, uint16_t arg) {
// TODO: momentary strobe here? (for light painting)
diff --git a/spaghetti-monster/spaghetti-monster.h b/spaghetti-monster/spaghetti-monster.h
index 08690b4..853eac3 100644
--- a/spaghetti-monster/spaghetti-monster.h
+++ b/spaghetti-monster/spaghetti-monster.h
@@ -25,6 +25,7 @@
#include "tk-attiny.h"
#include <avr/eeprom.h>
+#include <avr/power.h>
// include project definitions to help with recognizing symbols
#include "fsm-events.h"
diff --git a/tk-attiny.h b/tk-attiny.h
index 3c985f2..947a87c 100644
--- a/tk-attiny.h
+++ b/tk-attiny.h
@@ -28,24 +28,26 @@
/******************** hardware-specific values **************************/
#if (ATTINY == 13)
#define F_CPU 4800000UL
- #define EEPSIZE 64
+ //#define EEPSIZE 64
#define V_REF REFS0
#define BOGOMIPS 950
#define ADMUX_VCC 0b00001100
#define DELAY_ZERO_TIME 252
+ #define SWITCH_PORT PINB // PINA or PINB or PINC
#elif (ATTINY == 25)
// TODO: Use 6.4 MHz instead of 8 MHz?
#define F_CPU 8000000UL
- #define EEPSIZE 128
+ //#define EEPSIZE 128
#define V_REF REFS1
#define BOGOMIPS (F_CPU/4000)
#define ADMUX_VCC 0b00001100
#define ADMUX_THERM 0b10001111
#define DELAY_ZERO_TIME 1020
+ #define SWITCH_PORT PINB // PINA or PINB or PINC
#elif (ATTINY == 85)
// TODO: Use 6.4 MHz instead of 8 MHz?
#define F_CPU 8000000UL
- #define EEPSIZE 512
+ //#define EEPSIZE 512
#define V_REF REFS1
#define BOGOMIPS (F_CPU/4000)
// (1 << V_REF) | (0 << ADLAR) | (VCC_CHANNEL)
@@ -53,10 +55,30 @@
// (1 << V_REF) | (0 << ADLAR) | (THERM_CHANNEL)
#define ADMUX_THERM 0b10001111
#define DELAY_ZERO_TIME 1020
+ #define SWITCH_PORT PINB // PINA or PINB or PINC
+#elif (ATTINY == 1634)
+ #define F_CPU 8000000UL
+ #define V_REF REFS1
+ #define BOGOMIPS (F_CPU/4000)
+ // (1 << V_REF) | (0 << ADLAR) | (VCC_CHANNEL)
+ #define ADMUX_VCC 0b00001101
+ // (1 << V_REF) | (0 << ADLAR) | (THERM_CHANNEL)
+ #define ADMUX_THERM 0b10001110
+ #define DELAY_ZERO_TIME 1020
+ //#define SWITCH_PORT PINA // set this in hwdef
#else
#error Hey, you need to define ATTINY.
#endif
+// auto-detect eeprom size from avr-libc headers
+#ifndef EEPSIZE
+#ifdef E2SIZE
+#define EEPSIZE E2SIZE
+#else
+#define EEPSIZE (E2END+1)
+#endif
+#endif
+
#include <avr/interrupt.h>
@@ -86,4 +108,31 @@
#error Hey, you need to define an I/O pin layout.
#endif
+#if (ATTINY==25) || (ATTINY==45) || (ATTINY==85)
+ // use clock_prescale_set(n) instead; it's safer
+ //#define CLOCK_DIVIDER_SET(n) {CLKPR = 1<<CLKPCE; CLKPR = n;}
+#elif (ATTINY==1634)
+ // make it a NOP for now
+ // FIXME
+ //#define clock_prescale_set(x) ((void)0)
+ //#define clock_prescale_set(n) {cli(); CCP = 0xD8; CLKPR = n; sei();}
+ //#define clock_prescale_set(n) {cli(); CCP = 0xD8; CLKPR = n; sei();}
+ inline void clock_prescale_set(uint8_t n) {cli(); CCP = 0xD8; CLKPR = n; sei();}
+ typedef enum
+ {
+ clock_div_1 = 0,
+ clock_div_2 = 1,
+ clock_div_4 = 2,
+ clock_div_8 = 3,
+ clock_div_16 = 4,
+ clock_div_32 = 5,
+ clock_div_64 = 6,
+ clock_div_128 = 7,
+ clock_div_256 = 8
+ } clock_div_t;
+
+#else
+#error Unable to define MCU macros.
+#endif
+
#endif // TK_ATTINY_H