aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hwdef-Noctigon_K1-12V.h6
-rw-r--r--hwdef-Noctigon_K9.3.h164
-rw-r--r--spaghetti-monster/anduril/MODELS2
-rw-r--r--spaghetti-monster/anduril/anduril.c5
-rw-r--r--spaghetti-monster/anduril/aux-leds.c9
-rw-r--r--spaghetti-monster/anduril/cfg-noctigon-k9.3-nofet.h54
-rw-r--r--spaghetti-monster/anduril/cfg-noctigon-k9.3.c102
-rw-r--r--spaghetti-monster/anduril/cfg-noctigon-k9.3.h89
-rw-r--r--spaghetti-monster/anduril/misc.c5
-rw-r--r--spaghetti-monster/anduril/off-mode.c3
-rw-r--r--spaghetti-monster/anduril/ramp-mode.h10
-rw-r--r--spaghetti-monster/anduril/tint-ramping.c28
-rw-r--r--spaghetti-monster/fsm-eeprom.c8
-rw-r--r--spaghetti-monster/fsm-ramping.c19
-rw-r--r--spaghetti-monster/fsm-ramping.h4
15 files changed, 492 insertions, 16 deletions
diff --git a/hwdef-Noctigon_K1-12V.h b/hwdef-Noctigon_K1-12V.h
index 8781d8e..b17aad0 100644
--- a/hwdef-Noctigon_K1-12V.h
+++ b/hwdef-Noctigon_K1-12V.h
@@ -56,8 +56,8 @@
#define LED_ENABLE_PIN PB0 // pin 19, Opamp power
#define LED_ENABLE_PORT PORTB // control port for PB0
-#define LED_ENABLE2_PIN PC0 // pin 15, boost PMIC enable
-#define LED_ENABLE2_PORT PORTC // control port for PC0
+#define LED2_ENABLE_PIN PC0 // pin 15, boost PMIC enable
+#define LED2_ENABLE_PORT PORTC // control port for PC0
#define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened
@@ -103,7 +103,7 @@
inline void hwdef_setup() {
// enable output ports
// boost PMIC on/off
- DDRC = (1 << LED_ENABLE2_PIN);
+ DDRC = (1 << LED2_ENABLE_PIN);
// Opamp level and Opamp on/off
DDRB = (1 << PWM1_PIN)
| (1 << LED_ENABLE_PIN);
diff --git a/hwdef-Noctigon_K9.3.h b/hwdef-Noctigon_K9.3.h
new file mode 100644
index 0000000..6032b4c
--- /dev/null
+++ b/hwdef-Noctigon_K9.3.h
@@ -0,0 +1,164 @@
+#ifndef HWDEF_NOCTIGON_K93_H
+#define HWDEF_NOCTIGON_K93_H
+
+/* Noctigon K9.3 driver layout (attiny1634)
+ *
+ * Pin / Name / Function
+ * 1 PA6 2nd LED PWM (linear) (PWM1B)
+ * 2 PA5 R: red aux LED (PWM0B)
+ * 3 PA4 G: green aux LED
+ * 4 PA3 B: blue aux LED
+ * 5 PA2 button LED
+ * 6 PA1 Opamp 2 enable (2nd LEDs)
+ * 7 PA0 Opamp 1 enable (main LEDs)
+ * 8 GND GND
+ * 9 VCC VCC
+ * 10 PC5 (none)
+ * 11 PC4 (none)
+ * 12 PC3 RESET
+ * 13 PC2 (none)
+ * 14 PC1 SCK
+ * 15 PC0 main LED PWM (FET) (PWM0A)
+ * 16 PB3 main LED PWM (linear) (PWM1A)
+ * 17 PB2 MISO
+ * 18 PB1 MOSI / battery voltage (ADC6)
+ * 19 PB0 (none)
+ * 20 PA7 e-switch (PCINT7)
+ * ADC12 thermal sensor
+ *
+ * Main LED power uses one pin to turn the Opamp on/off,
+ * and one pin to control Opamp power level.
+ * Main brightness control uses the power level pin, with 4 kHz 10-bit PWM.
+ * The on/off pin is only used to turn the main LED on and off,
+ * not to change brightness.
+ * Some models also have a direct-drive FET for turbo.
+ */
+
+#ifdef ATTINY
+#undef ATTINY
+#endif
+#define ATTINY 1634
+#include <avr/io.h>
+
+#define PWM_CHANNELS 3 // 2 for main LEDs, 1 for 2nd LEDs
+#define PWM_BITS 10 // 0 to 1023 at 4 kHz, not 0 to 255 at 16 kHz
+#define PWM_TOP 1023
+
+#define SWITCH_PIN PA7 // pin 20
+#define SWITCH_PCINT PCINT7 // pin 20 pin change interrupt
+#define SWITCH_PCIE PCIE0 // PCIE1 is for PCINT[7:0]
+#define SWITCH_PCMSK PCMSK0 // PCMSK1 is for PCINT[7:0]
+#define SWITCH_PORT PINA // PINA or PINB or PINC
+#define PCINT_vect PCINT0_vect // ISR for PCINT[7:0]
+
+#define PWM1_PIN PB3 // pin 16, Opamp reference
+#define PWM1_LVL OCR1A // OCR1A is the output compare register for PB3
+
+#define PWM2_PIN PC0 // pin 15, DD FET PWM
+#define PWM2_LVL OCR0A // OCR0A is the output compare register for PC0
+
+#define PWM3_PIN PA6 // pin 1, 2nd LED Opamp reference
+#define PWM3_LVL OCR1B // OCR1B is the output compare register for PA6
+
+#define LED_ENABLE_PIN PA0 // pin 7, Opamp power
+#define LED_ENABLE_PORT PORTA // control port for PA0
+
+#define LED2_ENABLE_PIN PA1 // pin 6, Opamp power
+#define LED2_ENABLE_PORT PORTA // control port for PA1
+
+
+#define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened
+#define VOLTAGE_PIN PB1 // Pin 18 / PB1 / ADC6
+// pin to ADC mappings are in DS table 19-4
+#define VOLTAGE_ADC ADC6D // digital input disable pin for PB1
+// DIDR0/DIDR1 mappings are in DS section 19.13.5, 19.13.6
+#define VOLTAGE_ADC_DIDR DIDR1 // DIDR channel for ADC6D
+// DS tables 19-3, 19-4
+// Bit 7 6 5 4 3 2 1 0
+// REFS1 REFS0 REFEN ADC0EN MUX3 MUX2 MUX1 MUX0
+// MUX[3:0] = 0, 1, 1, 0 for ADC6 / PB1
+// divided by ...
+// REFS[1:0] = 1, 0 for internal 1.1V reference
+// other bits reserved
+#define ADMUX_VOLTAGE_DIVIDER 0b10000110
+#define ADC_PRSCL 0x07 // clk/128
+
+// Raw ADC readings at 4.4V and 2.2V
+// calibrate the voltage readout here
+// estimated / calculated values are:
+// (voltage - D1) * (R2/(R2+R1) * 1024 / 1.1)
+// D1, R1, R2 = 0, 330, 100
+#ifndef ADC_44
+//#define ADC_44 981 // raw value at 4.40V
+#define ADC_44 967 // manually tweaked so 4.16V will blink out 4.2
+#endif
+#ifndef ADC_22
+//#define ADC_22 489 // raw value at 2.20V
+#define ADC_22 482 // manually tweaked so 4.16V will blink out 4.2
+#endif
+
+// 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
+
+#define BUTTON_LED_PIN PA2 // pin 5
+#define BUTTON_LED_PORT PORTA // for all "PA" pins
+#define BUTTON_LED_DDR DDRA // for all "PA" pins
+#define BUTTON_LED_PUE PUEA // for all "PA" pins
+
+// 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
+ DDRC = (1 << PWM2_PIN);
+ DDRB = (1 << PWM1_PIN);
+ DDRA = (1 << PWM3_PIN)
+ | (1 << AUXLED_R_PIN)
+ | (1 << AUXLED_G_PIN)
+ | (1 << AUXLED_B_PIN)
+ | (1 << BUTTON_LED_PIN)
+ | (1 << LED_ENABLE_PIN)
+ | (1 << LED2_ENABLE_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
+ // Linear opamp PWM for both main and 2nd LEDs (10-bit)
+ // WGM1[3:0]: 0,0,1,1: PWM, Phase Correct, 10-bit (DS table 12-5)
+ // CS1[2:0]: 0,0,1: clk/1 (No prescaling) (DS table 12-6)
+ // COM1A[1:0]: 1,0: PWM OC1A in the normal direction (DS table 12-4)
+ // COM1B[1:0]: 1,0: PWM OC1B in the normal direction (DS table 12-4)
+ TCCR1A = (1<<WGM11) | (1<<WGM10) // 10-bit (TOP=0x03FF) (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)
+ ;
+
+ // FET PWM (8-bit; this channel can't do 10-bit)
+ // WGM0[2:0]: 0,0,1: PWM, Phase Correct, 8-bit (DS table 11-8)
+ // CS0[2:0]: 0,0,1: clk/1 (No prescaling) (DS table 11-9)
+ // COM0A[1:0]: 1,0: PWM OC0A in the normal direction (DS table 11-4)
+ // COM0B[1:0]: 1,0: PWM OC0B in the normal direction (DS table 11-7)
+ TCCR0A = (0<<WGM01) | (1<<WGM00) // 8-bit (TOP=0xFF) (DS table 11-8)
+ | (1<<COM0A1) | (0<<COM0A0) // PWM 0A in normal direction (DS table 11-4)
+ //| (1<<COM0B1) | (0<<COM0B0) // PWM 0B in normal direction (DS table 11-7)
+ ;
+ TCCR0B = (0<<CS02) | (0<<CS01) | (1<<CS00) // clk/1 (no prescaling) (DS table 11-9)
+ | (0<<WGM02) // phase-correct PWM (DS table 11-8)
+ ;
+
+ // set up e-switch
+ 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/MODELS b/spaghetti-monster/anduril/MODELS
index 78453a9..4dda62f 100644
--- a/spaghetti-monster/anduril/MODELS
+++ b/spaghetti-monster/anduril/MODELS
@@ -18,6 +18,8 @@ Model numbers:
0251 noctigon-k1
0252 noctigon-k1-sbt90
0253 noctigon-k1-12v
+0261 noctigon-k9.3
+0262 noctigon-k9.3-nofet
0311 fw3a
0312 fw3a-219
0313 fw3a-nofet
diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c
index f632229..de9b332 100644
--- a/spaghetti-monster/anduril/anduril.c
+++ b/spaghetti-monster/anduril/anduril.c
@@ -91,6 +91,11 @@
#include "spaghetti-monster.h"
+/********* does this build target have special code to include? *********/
+#ifdef OVERRIDES_FILE
+#include incfile(OVERRIDES_FILE)
+#endif
+
/********* Include all the regular app headers *********/
diff --git a/spaghetti-monster/anduril/aux-leds.c b/spaghetti-monster/anduril/aux-leds.c
index c819bd7..73d163e 100644
--- a/spaghetti-monster/anduril/aux-leds.c
+++ b/spaghetti-monster/anduril/aux-leds.c
@@ -99,6 +99,15 @@ void rgb_led_update(uint8_t mode, uint8_t arg) {
const uint8_t *colors = rgb_led_colors;
uint8_t actual_color = 0;
if (color < 7) { // normal color
+ #ifdef USE_K93_LOCKOUT_KLUDGE
+ // FIXME: jank alert: this is dumb
+ // this clause does nothing; it just uses up clock cycles
+ // because without it, the K9.3's lockout mode fails and returns
+ // to "off" after ~5 to 15 seconds when configured for a blinking
+ // single color, even though there is no code path from lockout to
+ // "off", and it doesn't act like a reboot either (no boot-up blink)
+ rainbow = (rainbow + 1 + pseudo_rand() % 5) % 6;
+ #endif
actual_color = pgm_read_byte(colors + color);
}
else if (color == 7) { // disco
diff --git a/spaghetti-monster/anduril/cfg-noctigon-k9.3-nofet.h b/spaghetti-monster/anduril/cfg-noctigon-k9.3-nofet.h
new file mode 100644
index 0000000..e91ebc4
--- /dev/null
+++ b/spaghetti-monster/anduril/cfg-noctigon-k9.3-nofet.h
@@ -0,0 +1,54 @@
+// Noctigon K9.3 (noFET) config options for Anduril
+#include "cfg-noctigon-k9.3.h"
+#undef MODEL_NUMBER
+#define MODEL_NUMBER "0262"
+// ATTINY: 1634
+
+// don't use the highest power channel
+#define K93_NO_FET
+
+// main LEDs
+#undef PWM1_LEVELS
+#undef PWM2_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
+// FET channel: unused, all zeroes
+#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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+// 2nd LEDs
+#undef PWM3_LEVELS
+#define PWM3_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 DEFAULT_LEVEL
+#define DEFAULT_LEVEL 50
+#undef MAX_1x7135
+#undef MAX_Nx7135
+#define MAX_1x7135 150
+#define MAX_Nx7135 MAX_1x7135
+
+#undef RAMP_SMOOTH_FLOOR
+#undef RAMP_SMOOTH_CEIL
+#undef RAMP_DISCRETE_FLOOR
+#undef RAMP_DISCRETE_CEIL
+#undef RAMP_DISCRETE_STEPS
+
+#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
+#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL
+#define RAMP_DISCRETE_STEPS 7
+
+// safe limit same as full UI
+#undef SIMPLE_UI_FLOOR
+#undef SIMPLE_UI_CEIL
+#define SIMPLE_UI_FLOOR RAMP_DISCRETE_FLOOR
+#define SIMPLE_UI_CEIL RAMP_DISCRETE_CEIL
+
+
+// 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 143
+#undef MIN_THERM_STEPDOWN
+#define MIN_THERM_STEPDOWN DEFAULT_LEVEL
+
diff --git a/spaghetti-monster/anduril/cfg-noctigon-k9.3.c b/spaghetti-monster/anduril/cfg-noctigon-k9.3.c
new file mode 100644
index 0000000..5ce5c5a
--- /dev/null
+++ b/spaghetti-monster/anduril/cfg-noctigon-k9.3.c
@@ -0,0 +1,102 @@
+/*
+ * K9.3 has unusual power channels, so it must override some of FSM's code.
+ * There are two sets of LEDs:
+ * 1. Main LEDs: (9 x white LEDs)
+ * PWM1 (10-bit, linear)
+ * PWM2 (8-bit, FET, only used on some K9.3 models)
+ * 2. 2nd LEDs: (3 x white or color LEDs)
+ * PWM3 (10-bit, linear)
+ *
+ * The two sets are not used at the same time... just one or the other,
+ * depending on the "tint" variable. (0 = main LEDs, other value = 2nd LEDs)
+ */
+// if the gradual adjustment mechanism doesn't work, disable it here:
+//#ifdef USE_SET_LEVEL_GRADUALLY
+//#undef USE_SET_LEVEL_GRADUALLY
+//#endif
+
+// this is inserted into fsm-ramping.c :: set_level()
+// (it overrides part of the function, but not all of it)
+inline void set_level_override(uint8_t level) {
+ if (level == 0) { // off
+ PWM1_LVL = 0;
+ PWM2_LVL = 0;
+ PWM3_LVL = 0;
+ // disable both power channels
+ LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN);
+ LED2_ENABLE_PORT &= ~(1 << LED2_ENABLE_PIN);
+ } else {
+ level --;
+
+ if (! tint) { // main LEDs
+ // enable this power channel
+ LED_ENABLE_PORT |= (1 << LED_ENABLE_PIN);
+ // disable other power channel
+ LED2_ENABLE_PORT &= ~(1 << LED2_ENABLE_PIN);
+ // set levels
+ PWM1_LVL = PWM_GET(pwm1_levels, level);
+ #ifndef K93_NO_FET
+ PWM2_LVL = (uint8_t)(PWM_GET(pwm2_levels, level) >> 2); // 8 bits
+ #endif
+ PWM3_LVL = 0;
+ } else { // 2nd LEDs
+ // disable other power channel
+ LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN);
+ // enable this power channel
+ LED2_ENABLE_PORT |= (1 << LED2_ENABLE_PIN);
+ // set levels
+ PWM1_LVL = 0;
+ PWM2_LVL = 0;
+ PWM3_LVL = PWM_GET(pwm3_levels, level);
+ }
+ }
+}
+
+// override fsm-ramping.c :: gradual_tick()
+// (because the power handling on this light is weird)
+// call this every frame or every few frames to change brightness very smoothly
+void gradual_tick() {
+ // go by only one ramp level at a time instead of directly to the target
+ uint8_t gt = gradual_target;
+ if (gt < actual_level) gt = actual_level - 1;
+ else if (gt > actual_level) gt = actual_level + 1;
+
+ gt --; // convert 1-based number to 0-based
+
+ PWM_DATATYPE target;
+
+ if (! tint) { // main LED channel
+ 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 == PWM_TOP)) PWM1_LVL = PWM_TOP;
+ else if (PWM1_LVL < target) PWM1_LVL ++;
+ else if (PWM1_LVL > target) PWM1_LVL --;
+
+ #ifndef K93_NO_FET // skip this on E21A model
+ target = PWM_GET(pwm2_levels, gt) >> 2; // 8 bits, not 10
+ if (PWM2_LVL < target) PWM2_LVL ++;
+ else if (PWM2_LVL > target) PWM2_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 == PWM_GET(pwm1_levels, gt))
+ #ifndef K93_NO_FET
+ && (PWM2_LVL == (PWM_GET(pwm2_levels, gt) >> 2))
+ #endif
+ )
+ { actual_level = gt + 1; }
+ } else { // 2nd LED channel
+ target = PWM_GET(pwm3_levels, gt);
+ if (PWM3_LVL < target) PWM3_LVL ++;
+ else if (PWM3_LVL > target) PWM3_LVL --;
+
+ // did we go far enough to hit the next defined ramp level?
+ // if so, update the main ramp level tracking var
+ if ( PWM3_LVL == PWM_GET(pwm3_levels, gt) )
+ { actual_level = gt + 1; }
+ }
+
+}
+
diff --git a/spaghetti-monster/anduril/cfg-noctigon-k9.3.h b/spaghetti-monster/anduril/cfg-noctigon-k9.3.h
new file mode 100644
index 0000000..e61ea13
--- /dev/null
+++ b/spaghetti-monster/anduril/cfg-noctigon-k9.3.h
@@ -0,0 +1,89 @@
+// Noctigon K9.3 config options for Anduril
+#define MODEL_NUMBER "0261"
+#include "hwdef-Noctigon_K9.3.h"
+// ATTINY: 1634
+// this model requires some special code
+#define OVERRIDES_FILE cfg-noctigon-k9.3.c
+#define OVERRIDE_SET_LEVEL
+#define OVERRIDE_GRADUAL_TICK
+inline void set_level_override(uint8_t level);
+
+
+// this light has three aux LED channels: R, G, B
+#define USE_AUX_RGB_LEDS
+#define RGB_LED_OFF_DEFAULT 0x18 // low, rainbow
+// the aux LEDs are front-facing, so turn them off while main LEDs are on
+//#define USE_AUX_RGB_LEDS_WHILE_ON
+// it also has an independent LED in the button
+#define USE_BUTTON_LED
+// TODO: the whole "indicator LED" thing needs to be refactored into
+// "aux LED(s)" and "button LED(s)" since they work a bit differently
+// enabling this option breaks the button LED on D4v2.5
+#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
+
+// has two channels of independent LEDs
+#define USE_TINT_RAMPING
+// ... but it doesn't make sense to ramp between; only toggle
+#define TINT_RAMP_TOGGLE_ONLY
+
+// main LEDs
+// max regulated: ~1750 lm
+// FET: ~8000 lm
+// 2nd LEDs
+// max regulated: ~1500 lm
+// maxreg at 120: level_calc.py cube 2 150 7135 0 2.5 1740 FET 1 10 3190
+#define RAMP_LENGTH 150
+// main LEDs
+#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
+// 2nd LEDs
+#define PWM3_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
+#define DEFAULT_LEVEL 46
+#define MAX_1x7135 120
+#define MAX_Nx7135 MAX_1x7135
+#define HALFSPEED_LEVEL 10
+#define QUARTERSPEED_LEVEL 2
+
+#define USE_MANUAL_MEMORY_TIMER_FOR_TINT
+//#define DEFAULT_MANUAL_MEMORY DEFAULT_LEVEL
+//#define DEFAULT_MANUAL_MEMORY_TIMER 10
+
+#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
+
+// safe limit highest regulated power (no FET or turbo)
+#define SIMPLE_UI_FLOOR RAMP_DISCRETE_FLOOR
+#define SIMPLE_UI_CEIL RAMP_DISCRETE_CEIL
+#define SIMPLE_UI_STEPS 5
+
+// 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 // accumulate less error before adjusting
+//#define THERM_RESPONSE_MAGNITUDE 128 // bigger adjustments
+
+// use the brightest setting for strobe
+#define STROBE_BRIGHTNESS MAX_LEVEL
+// slow down party strobe; this driver can't pulse for 1ms or less
+#define PARTY_STROBE_ONTIME 2
+
+#define BLINK_ONCE_TIME 12 // longer blink, since main LEDs are slow
+
+#define THERM_CAL_OFFSET 5
+
+// for consistency with KR4 (not otherwise necessary though)
+#define USE_SOFT_FACTORY_RESET
+
+
+// work around bizarre bug: lockout mode fails when set to solid color blinking
+#define USE_K93_LOCKOUT_KLUDGE
diff --git a/spaghetti-monster/anduril/misc.c b/spaghetti-monster/anduril/misc.c
index 63b8f48..523bbf0 100644
--- a/spaghetti-monster/anduril/misc.c
+++ b/spaghetti-monster/anduril/misc.c
@@ -38,13 +38,16 @@ void blink_confirm(uint8_t num) {
// make a short, visible pulse
// (either brighter or darker, depending on current brightness)
+#ifndef BLINK_ONCE_TIME
+#define BLINK_ONCE_TIME 10
+#endif
void blink_once() {
uint8_t brightness = actual_level;
uint8_t bump = brightness + (MAX_LEVEL/6);
if (bump > MAX_LEVEL) bump = 0;
set_level(bump);
- delay_4ms(10/4);
+ delay_4ms(BLINK_ONCE_TIME/4);
set_level(brightness);
}
diff --git a/spaghetti-monster/anduril/off-mode.c b/spaghetti-monster/anduril/off-mode.c
index 5ebaa1d..34d9e6d 100644
--- a/spaghetti-monster/anduril/off-mode.c
+++ b/spaghetti-monster/anduril/off-mode.c
@@ -133,6 +133,9 @@ uint8_t off_state(Event event, uint16_t arg) {
&& (off_time >= (manual_memory_timer * SLEEP_TICKS_PER_MINUTE))
#endif
) {
+ #if defined(USE_MANUAL_MEMORY_TIMER_FOR_TINT) && defined(USE_TINT_RAMPING) && defined(TINT_RAMP_TOGGLE_ONLY)
+ tint = 0;
+ #endif
set_level(nearest_level(manual_memory));
} else
#endif
diff --git a/spaghetti-monster/anduril/ramp-mode.h b/spaghetti-monster/anduril/ramp-mode.h
index b772407..ed806bd 100644
--- a/spaghetti-monster/anduril/ramp-mode.h
+++ b/spaghetti-monster/anduril/ramp-mode.h
@@ -148,9 +148,15 @@ void set_level_and_therm_target(uint8_t level);
// brightness control
uint8_t memorized_level = DEFAULT_LEVEL;
#ifdef USE_MANUAL_MEMORY
-uint8_t manual_memory = 0;
+#ifndef DEFAULT_MANUAL_MEMORY
+#define DEFAULT_MANUAL_MEMORY 0
+#endif
+uint8_t manual_memory = DEFAULT_MANUAL_MEMORY;
#ifdef USE_MANUAL_MEMORY_TIMER
-uint8_t manual_memory_timer = 0;
+#ifndef DEFAULT_MANUAL_MEMORY_TIMER
+#define DEFAULT_MANUAL_MEMORY_TIMER 0
+#endif
+uint8_t manual_memory_timer = DEFAULT_MANUAL_MEMORY_TIMER;
#endif
#endif
#ifdef USE_SIMPLE_UI
diff --git a/spaghetti-monster/anduril/tint-ramping.c b/spaghetti-monster/anduril/tint-ramping.c
index 0196bc7..0b077ef 100644
--- a/spaghetti-monster/anduril/tint-ramping.c
+++ b/spaghetti-monster/anduril/tint-ramping.c
@@ -22,6 +22,32 @@
#include "tint-ramping.h"
+#ifdef TINT_RAMP_TOGGLE_ONLY
+
+uint8_t tint_ramping_state(Event event, uint16_t arg) {
+ // click, click, hold: change the tint
+ if (event == EV_click3_hold) {
+ // toggle once on first frame; ignore other frames
+ if (! arg) {
+ tint = !tint;
+ set_level(actual_level);
+ blink_once();
+ }
+ return EVENT_HANDLED;
+ }
+
+ // click, click, hold, release: save config
+ else if (event == EV_click3_hold_release) {
+ // remember tint after battery change
+ save_config();
+ return EVENT_HANDLED;
+ }
+
+ return EVENT_NOT_HANDLED;
+}
+
+#else // no TINT_RAMP_TOGGLE_ONLY
+
uint8_t tint_ramping_state(Event event, uint16_t arg) {
static int8_t tint_ramp_direction = 1;
static uint8_t prev_tint = 0;
@@ -82,6 +108,8 @@ uint8_t tint_ramping_state(Event event, uint16_t arg) {
return EVENT_NOT_HANDLED;
}
+#endif // ifdef TINT_RAMP_TOGGLE_ONLY
+
#endif
diff --git a/spaghetti-monster/fsm-eeprom.c b/spaghetti-monster/fsm-eeprom.c
index 0de7e05..4c734a2 100644
--- a/spaghetti-monster/fsm-eeprom.c
+++ b/spaghetti-monster/fsm-eeprom.c
@@ -30,7 +30,7 @@ uint8_t eeprom[EEPROM_BYTES];
#endif
uint8_t load_eeprom() {
- #ifdef LED_ENABLE_PIN
+ #if defined(LED_ENABLE_PIN) || defined(LED2_ENABLE_PIN)
delay_4ms(2); // wait for power to stabilize
#endif
@@ -48,7 +48,7 @@ uint8_t load_eeprom() {
}
void save_eeprom() {
- #ifdef LED_ENABLE_PIN
+ #if defined(LED_ENABLE_PIN) || defined(LED2_ENABLE_PIN)
delay_4ms(2); // wait for power to stabilize
#endif
@@ -70,7 +70,7 @@ uint8_t eeprom_wl[EEPROM_WL_BYTES];
uint8_t * eep_wl_prev_offset;
uint8_t load_eeprom_wl() {
- #ifdef LED_ENABLE_PIN
+ #if defined(LED_ENABLE_PIN) || defined(LED2_ENABLE_PIN)
delay_4ms(2); // wait for power to stabilize
#endif
@@ -99,7 +99,7 @@ uint8_t load_eeprom_wl() {
}
void save_eeprom_wl() {
- #ifdef LED_ENABLE_PIN
+ #if defined(LED_ENABLE_PIN) || defined(LED2_ENABLE_PIN)
delay_4ms(2); // wait for power to stabilize
#endif
diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c
index 8ad4b65..d6a14ef 100644
--- a/spaghetti-monster/fsm-ramping.c
+++ b/spaghetti-monster/fsm-ramping.c
@@ -54,6 +54,10 @@ void set_level(uint8_t level) {
#endif
#endif
+ #ifdef OVERRIDE_SET_LEVEL
+ set_level_override(level);
+ #else
+
//TCCR0A = PHASE;
if (level == 0) {
#if PWM_CHANNELS >= 1
@@ -72,8 +76,8 @@ 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);
+ #ifdef LED2_ENABLE_PIN
+ LED2_ENABLE_PORT &= ~(1 << LED2_ENABLE_PIN);
#endif
} else {
// enable the power channel, if relevant
@@ -89,8 +93,8 @@ void set_level(uint8_t level) {
LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN);
#endif
#endif
- #ifdef LED_ENABLE2_PIN
- LED_ENABLE2_PORT |= (1 << LED_ENABLE2_PIN);
+ #ifdef LED2_ENABLE_PIN
+ LED2_ENABLE_PORT |= (1 << LED2_ENABLE_PIN);
#endif
level --;
@@ -131,7 +135,7 @@ void set_level(uint8_t level) {
PWM1_LVL = warm_PWM;
PWM2_LVL = cool_PWM;
- #else
+ #else // ifdef USE_TINT_RAMPING
#if PWM_CHANNELS >= 1
PWM1_LVL = PWM_GET(pwm1_levels, level);
@@ -148,6 +152,7 @@ void set_level(uint8_t level) {
#endif // ifdef USE_TINT_RAMPING
}
+ #endif // ifdef OVERRIDE_SET_LEVEL
#ifdef USE_DYNAMIC_UNDERCLOCKING
auto_clock_speed();
#endif
@@ -158,6 +163,7 @@ inline void set_level_gradually(uint8_t lvl) {
gradual_target = lvl;
}
+#ifndef OVERRIDE_GRADUAL_TICK
// call this every frame or every few frames to change brightness very smoothly
void gradual_tick() {
// go by only one ramp level at a time instead of directly to the target
@@ -222,7 +228,8 @@ void gradual_tick() {
auto_clock_speed();
#endif
}
-#endif
+#endif // ifdef OVERRIDE_GRADUAL_TICK
+#endif // ifdef USE_SET_LEVEL_GRADUALLY
#endif // ifdef USE_RAMPING
#endif
diff --git a/spaghetti-monster/fsm-ramping.h b/spaghetti-monster/fsm-ramping.h
index f177db9..8fd89c7 100644
--- a/spaghetti-monster/fsm-ramping.h
+++ b/spaghetti-monster/fsm-ramping.h
@@ -27,7 +27,11 @@
uint8_t actual_level = 0;
#ifdef USE_TINT_RAMPING
+#ifdef TINT_RAMP_TOGGLE_ONLY
+uint8_t tint = 0;
+#else
uint8_t tint = 128;
+#endif
#define USE_TRIANGLE_WAVE
#endif