aboutsummaryrefslogtreecommitdiff
path: root/spaghetti-monster
diff options
context:
space:
mode:
authorSelene ToyKeeper2021-09-08 17:14:53 -0600
committerSelene ToyKeeper2021-09-08 17:14:53 -0600
commit49f4475b2e45b2110b46cd6d44cc967f637c07fc (patch)
tree1a17018a7c17f4038d1943084f968af91b89127b /spaghetti-monster
parentcopied k9.3 config for new d4sv2-tintramp (diff)
downloadanduril-49f4475b2e45b2110b46cd6d44cc967f637c07fc.tar.gz
anduril-49f4475b2e45b2110b46cd6d44cc967f637c07fc.tar.bz2
anduril-49f4475b2e45b2110b46cd6d44cc967f637c07fc.zip
got D4Sv2 tint ramping to work, with dynamic PWM (PFM)
and (maybe) thermal regulation (untested) (also broke BLF LT1 in the process; need to fix that now) Rewrote how tint ramping works, so it provides a virtual "PWM1_LVL" for other code to use, and it translates that internally into actual hardware controls. This should, in theory, allow smooth thermal regulation (gradual_tick) to work on tint-ramp lights.
Diffstat (limited to '')
-rw-r--r--spaghetti-monster/anduril/cfg-emisar-d4sv2-tintramp.h63
-rw-r--r--spaghetti-monster/fsm-ramping.c108
-rw-r--r--spaghetti-monster/fsm-ramping.h8
3 files changed, 107 insertions, 72 deletions
diff --git a/spaghetti-monster/anduril/cfg-emisar-d4sv2-tintramp.h b/spaghetti-monster/anduril/cfg-emisar-d4sv2-tintramp.h
index f3a6cdd..c808cd5 100644
--- a/spaghetti-monster/anduril/cfg-emisar-d4sv2-tintramp.h
+++ b/spaghetti-monster/anduril/cfg-emisar-d4sv2-tintramp.h
@@ -1,19 +1,12 @@
-// Noctigon K9.3 config options for Anduril
-#define MODEL_NUMBER "0261"
-#include "hwdef-Noctigon_K9.3.h"
+// Emisar D4S V2 tint-ramping config options for Anduril (based on Noctigon K9.3)
+#define MODEL_NUMBER "0135"
+#include "hwdef-Emisar_D4Sv2-tintramp.h"
#include "hank-cfg.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
// 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
@@ -25,24 +18,22 @@ inline void set_level_override(uint8_t level);
// 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
+// how much to increase total brightness at middle tint
+// (0 = 100% brightness, 64 = 200% brightness)
+#define TINT_RAMPING_CORRECTION 0 // none, linear regulator doesn't need it
// main LEDs
-// max regulated: ~1750 lm
-// FET: ~8000 lm
+// output: unknown, 2000 lm?
+// FET: absent / unused?
// 2nd LEDs
-// max regulated: ~1500 lm
-// maxreg at 120: level_calc.py cube 2 150 7135 0 2.5 1740 FET 1 10 3190
+// output: unknown, 2000 lm?
#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
+// level_calc.py 5.01 1 150 7135 1 0.2 2000 --pwm dyn:80:16383:255
+// abstract ramp (power is split between both sets of LEDs)
+#define PWM1_LEVELS 1,1,1,2,2,2,3,4,4,5,6,6,7,8,9,10,12,13,14,16,17,19,21,23,25,27,29,31,33,36,38,41,44,47,50,53,56,59,62,66,69,73,76,80,83,87,90,94,98,101,104,108,111,114,117,120,122,125,127,129,130,131,132,132,132,131,130,128,125,122,118,113,108,101,93,84,75,63,51,37,22,23,24,26,27,28,29,30,32,33,34,36,37,39,40,42,44,46,47,49,51,53,55,57,60,62,64,66,69,71,74,77,80,82,85,88,91,95,98,101,105,108,112,116,120,123,128,132,136,140,145,149,154,159,164,169,174,180,185,191,197,203,209,215,221,228,234,241,248,255
+#define PWM_TOPS 16383,13682,10747,15453,11909,8095,12781,14776,12231,13453,14029,11886,12249,12339,12249,12032,12939,12468,11964,12288,11697,11793,11770,11661,11489,11268,11012,10729,10425,10411,10063,9968,9833,9668,9479,9273,9054,8825,8590,8482,8233,8097,7843,7691,7439,7278,7033,6869,6702,6470,6245,6085,5872,5668,5470,5280,5056,4882,4678,4485,4268,4064,3872,3664,3468,3260,3066,2863,2652,2457,2257,2054,1866,1659,1453,1248,1060,847,651,448,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,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 DEFAULT_LEVEL 70
+#define MAX_1x7135 150
#define HALFSPEED_LEVEL 10
#define QUARTERSPEED_LEVEL 2
@@ -50,9 +41,9 @@ inline void set_level_override(uint8_t level);
//#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_SMOOTH_FLOOR 10 // level 1 is unreliable (?)
+#define RAMP_SMOOTH_CEIL 130
+// 10, 30, 50, [70], 90, 110, [130]
#define RAMP_DISCRETE_FLOOR 10
#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL
#define RAMP_DISCRETE_STEPS 7
@@ -62,21 +53,29 @@ inline void set_level_override(uint8_t level);
#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
+// stop panicking at ~1500 lm
+#define THERM_FASTER_LEVEL 140
+#define MIN_THERM_STEPDOWN 80
// 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
+// the default of 26 looks a bit flat, so increase it
+#define CANDLE_AMPLITUDE 40
+
+// the power regulator is a bit slow, so push it harder for a quick response from off
+#define DEFAULT_JUMP_START_LEVEL 21
+#define BLINK_BRIGHTNESS DEFAULT_LEVEL
#define BLINK_ONCE_TIME 12 // longer blink, since main LEDs are slow
#define THERM_CAL_OFFSET 5
+#ifdef BLINK_AT_RAMP_MIDDLE
+#undef BLINK_AT_RAMP_MIDDLE
+#endif
+
// for consistency with KR4 (not otherwise necessary though)
#define USE_SOFT_FACTORY_RESET
diff --git a/spaghetti-monster/fsm-ramping.c b/spaghetti-monster/fsm-ramping.c
index 54ca45c..c3a5147 100644
--- a/spaghetti-monster/fsm-ramping.c
+++ b/spaghetti-monster/fsm-ramping.c
@@ -89,6 +89,10 @@ void set_level(uint8_t level) {
#if PWM_CHANNELS >= 4
PWM4_LVL = 0;
#endif
+ #ifdef USE_TINT_RAMPING
+ TINT1_LVL = 0;
+ TINT2_LVL = 0;
+ #endif
// disable the power channel, if relevant
#ifdef LED_ENABLE_PIN
LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN);
@@ -117,44 +121,6 @@ void set_level(uint8_t level) {
// PWM array index = level - 1
level --;
- #ifdef USE_TINT_RAMPING
- #ifndef TINT_RAMPING_CORRECTION
- #define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint
- #endif
- // calculate actual PWM levels based on a single-channel ramp
- // and a global tint value
- uint8_t brightness = PWM_GET(pwm1_levels, level);
- uint8_t warm_PWM, cool_PWM;
-
- // auto-tint modes
- uint8_t mytint;
- #if 1
- // perceptual by ramp level
- if (tint == 0) { mytint = 255 * (uint16_t)level / RAMP_SIZE; }
- else if (tint == 255) { mytint = 255 - (255 * (uint16_t)level / RAMP_SIZE); }
- #else
- // linear with power level
- //if (tint == 0) { mytint = brightness; }
- //else if (tint == 255) { mytint = 255 - brightness; }
- #endif
- // stretch 1-254 to fit 0-255 range (hits every value except 98 and 198)
- else { mytint = (tint * 100 / 99) - 1; }
-
- // middle tints sag, so correct for that effect
- uint16_t base_PWM = brightness;
- // correction is only necessary when PWM is fast
- if (level > HALFSPEED_LEVEL) {
- base_PWM = brightness
- + ((((uint16_t)brightness) * TINT_RAMPING_CORRECTION / 64) * triangle_wave(mytint) / 255);
- }
-
- cool_PWM = (((uint16_t)mytint * (uint16_t)base_PWM) + 127) / 255;
- warm_PWM = base_PWM - cool_PWM;
-
- PWM1_LVL = warm_PWM;
- PWM2_LVL = cool_PWM;
- #else // ifdef USE_TINT_RAMPING
-
#if PWM_CHANNELS >= 1
PWM1_LVL = PWM_GET(pwm1_levels, level);
#endif
@@ -168,8 +134,6 @@ void set_level(uint8_t level) {
PWM4_LVL = PWM_GET(pwm4_levels, level);
#endif
- #endif // ifdef USE_TINT_RAMPING
-
#ifdef USE_DYN_PWM
uint16_t top = PWM_GET(pwm_tops, level);
#ifdef PWM1_CNT
@@ -214,6 +178,10 @@ void set_level(uint8_t level) {
}
#endif
}
+ #ifdef USE_TINT_RAMPING
+ update_tint();
+ #endif
+
#ifdef PWM1_CNT
prev_level = api_level;
#endif
@@ -289,6 +257,9 @@ void gradual_tick() {
{
actual_level = gt + 1;
}
+ #ifdef USE_TINT_RAMPING
+ update_tint();
+ #endif
#ifdef USE_DYNAMIC_UNDERCLOCKING
auto_clock_speed();
#endif
@@ -296,5 +267,62 @@ void gradual_tick() {
#endif // ifdef OVERRIDE_GRADUAL_TICK
#endif // ifdef USE_SET_LEVEL_GRADUALLY
+
+#ifdef USE_TINT_RAMPING
+void update_tint() {
+ #ifndef TINT_RAMPING_CORRECTION
+ #define TINT_RAMPING_CORRECTION 26 // 140% brightness at middle tint
+ #endif
+
+ // calculate actual PWM levels based on a single-channel ramp
+ // and a global tint value
+ //PWM_DATATYPE brightness = PWM_GET(pwm1_levels, level);
+ PWM_DATATYPE brightness = PWM1_LVL;
+ PWM_DATATYPE warm_PWM, cool_PWM;
+
+ // auto-tint modes
+ uint8_t mytint;
+ uint8_t level = actual_level - 1;
+ #if 1
+ // perceptual by ramp level
+ if (tint == 0) { mytint = 255 * (uint16_t)level / RAMP_SIZE; }
+ else if (tint == 255) { mytint = 255 - (255 * (uint16_t)level / RAMP_SIZE); }
+ #else
+ // linear with power level
+ //if (tint == 0) { mytint = brightness; }
+ //else if (tint == 255) { mytint = 255 - brightness; }
+ #endif
+ // stretch 1-254 to fit 0-255 range (hits every value except 98 and 198)
+ else { mytint = (tint * 100 / 99) - 1; }
+
+ // middle tints sag, so correct for that effect
+ PWM_DATATYPE2 base_PWM = brightness;
+ // correction is only necessary when PWM is fast
+ #if defined(TINT_RAMPING_CORRECTION) && (TINT_RAMPING_CORRECTION > 0)
+ if (level > HALFSPEED_LEVEL) {
+ base_PWM = brightness
+ + ((((PWM_DATATYPE2)brightness) * TINT_RAMPING_CORRECTION / 64) * triangle_wave(mytint) / 255);
+ }
+ #endif
+
+ cool_PWM = (((PWM_DATATYPE2)mytint * (PWM_DATATYPE2)base_PWM) + 127) / 255;
+ warm_PWM = base_PWM - cool_PWM;
+
+ TINT1_LVL = warm_PWM;
+ TINT2_LVL = cool_PWM;
+
+ // disable the power channel, if relevant
+ #ifdef LED_ENABLE_PIN
+ if (! warm_PWM)
+ LED_ENABLE_PORT &= ~(1 << LED_ENABLE_PIN);
+ #endif
+ #ifdef LED2_ENABLE_PIN
+ if (! cool_PWM)
+ LED2_ENABLE_PORT &= ~(1 << LED2_ENABLE_PIN);
+ #endif
+}
+#endif // ifdef USE_TINT_RAMPING
+
+
#endif // ifdef USE_RAMPING
#endif
diff --git a/spaghetti-monster/fsm-ramping.h b/spaghetti-monster/fsm-ramping.h
index 7a4fa3b..d8aad18 100644
--- a/spaghetti-monster/fsm-ramping.h
+++ b/spaghetti-monster/fsm-ramping.h
@@ -42,6 +42,10 @@ inline void set_level_gradually(uint8_t lvl);
void gradual_tick();
#endif
+#ifdef USE_TINT_RAMPING
+void update_tint();
+#endif
+
// auto-detect the data type for PWM tables
#ifndef PWM_BITS
#define PWM_BITS 8
@@ -49,10 +53,14 @@ void gradual_tick();
#endif
#if PWM_BITS <= 8
#define PWM_DATATYPE uint8_t
+#define PWM_DATATYPE2 uint16_t
#define PWM_TOP 255
#define PWM_GET(x,y) pgm_read_byte(x+y)
#else
#define PWM_DATATYPE uint16_t
+#ifndef PWM_DATATYPE2
+#define PWM_DATATYPE2 uint32_t
+#endif
#ifndef PWM_TOP
#define PWM_TOP 1023 // 10 bits by default
#endif