aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSelene ToyKeeper2023-08-25 16:21:04 -0600
committerSelene ToyKeeper2023-08-25 16:21:04 -0600
commitd53ba0d8cb2f491f95adabf7b37cf195ae1fe5e6 (patch)
tree818702217e01029d67f759a2b43ee912e370ef77
parentadded emisar-d4k-3ch build (diff)
downloadanduril-d53ba0d8cb2f491f95adabf7b37cf195ae1fe5e6.tar.gz
anduril-d53ba0d8cb2f491f95adabf7b37cf195ae1fe5e6.tar.bz2
anduril-d53ba0d8cb2f491f95adabf7b37cf195ae1fe5e6.zip
made custom 3H handler system work, added circular HSV ramping,
fixed some minor issues with LEDs not getting turned off in corner cases (strobe on channel 1 -> strobe on channel 2, 1 might not get turned off)
Diffstat (limited to '')
-rw-r--r--hwdef-emisar-d4k-3ch.c33
-rw-r--r--hwdef-emisar-d4k-3ch.h2
-rw-r--r--spaghetti-monster/anduril/channel-modes.c51
-rw-r--r--spaghetti-monster/anduril/channel-modes.h8
-rw-r--r--spaghetti-monster/fsm-channels.c11
5 files changed, 88 insertions, 17 deletions
diff --git a/hwdef-emisar-d4k-3ch.c b/hwdef-emisar-d4k-3ch.c
index 1042d9e..1955b59 100644
--- a/hwdef-emisar-d4k-3ch.c
+++ b/hwdef-emisar-d4k-3ch.c
@@ -3,6 +3,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
+#include "spaghetti-monster/anduril/channel-modes.h" //for circular_tint_3h()
#include "chan-rgbaux.c"
@@ -69,15 +70,21 @@ Channel channels[] = {
RGB_AUX_CHANNELS
};
+// HSV mode needs a different 3H handler
+StatePtr channel_3H_modes[NUM_CHANNEL_MODES] = {
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, circular_tint_3h, NULL,
+};
// LEDs 1+2 are 8-bit
// this 8-bit channel may be LEDs 1+2 or LED 4, depending on wiring
void set_level_main2(uint8_t level) {
+ LED3_ENABLE_PORT &= ~(1 << LED3_ENABLE_PIN ); // turn off unused LEDs
+ LED4_ENABLE_PORT &= ~(1 << LED4_ENABLE_PIN ); // turn off unused LEDs
+
if (level == 0) {
MAIN2_PWM_LVL = 0;
MAIN2_ENABLE_PORT &= ~(1 << MAIN2_ENABLE_PIN); // turn off opamp
- LED3_ENABLE_PORT &= ~(1 << LED3_ENABLE_PIN ); // turn off opamp
- LED4_ENABLE_PORT &= ~(1 << LED4_ENABLE_PIN ); // turn off opamp
} else {
level --;
MAIN2_ENABLE_PORT |= (1 << MAIN2_ENABLE_PIN);
@@ -87,12 +94,13 @@ void set_level_main2(uint8_t level) {
// LED 3 is 16-bit
void set_level_led3(uint8_t level) {
+ MAIN2_ENABLE_PORT &= ~(1 << MAIN2_ENABLE_PIN); // turn off unused LEDs
+ LED4_ENABLE_PORT &= ~(1 << LED4_ENABLE_PIN ); // turn off unused LEDs
+
if (level == 0) {
LED3_PWM_LVL = 0;
PWM_CNT = 0;
- MAIN2_ENABLE_PORT &= ~(1 << MAIN2_ENABLE_PIN); // turn off opamp
LED3_ENABLE_PORT &= ~(1 << LED3_ENABLE_PIN ); // turn off opamp
- LED4_ENABLE_PORT &= ~(1 << LED4_ENABLE_PIN ); // turn off opamp
} else {
level --;
LED3_ENABLE_PORT |= (1 << LED3_ENABLE_PIN);
@@ -106,11 +114,12 @@ void set_level_led3(uint8_t level) {
// this 16-bit channel may be LED 4 or LEDs 1+2, depending on wiring
void set_level_led4(uint8_t level) {
+ MAIN2_ENABLE_PORT &= ~(1 << MAIN2_ENABLE_PIN); // turn off unused LEDs
+ LED3_ENABLE_PORT &= ~(1 << LED3_ENABLE_PIN ); // turn off unused LEDs
+
if (level == 0) {
LED4_PWM_LVL = 0;
PWM_CNT = 0; // reset phase
- MAIN2_ENABLE_PORT &= ~(1 << MAIN2_ENABLE_PIN); // turn off opamp
- LED3_ENABLE_PORT &= ~(1 << LED3_ENABLE_PIN ); // turn off opamp
LED4_ENABLE_PORT &= ~(1 << LED4_ENABLE_PIN ); // turn off opamp
} else {
level --; // PWM array index = level - 1
@@ -159,11 +168,12 @@ void set_level_all(uint8_t level) {
// 8/16/16 wiring, mix 16+16
void set_level_led34a_blend(uint8_t level) {
+ MAIN2_ENABLE_PORT &= ~(1 << MAIN2_ENABLE_PIN); // turn off unused LEDs
+
if (level == 0) {
LED3_PWM_LVL = 0;
LED4_PWM_LVL = 0;
PWM_CNT = 0; // reset phase
- MAIN2_ENABLE_PORT &= ~(1 << MAIN2_ENABLE_PIN); // turn off opamp
LED3_ENABLE_PORT &= ~(1 << LED3_ENABLE_PIN ); // turn off opamp
LED4_ENABLE_PORT &= ~(1 << LED4_ENABLE_PIN ); // turn off opamp
return;
@@ -189,13 +199,14 @@ void set_level_led34a_blend(uint8_t level) {
// 16/16/8 wiring, mix 16+8
void set_level_led34b_blend(uint8_t level) {
+ LED4_ENABLE_PORT &= ~(1 << LED4_ENABLE_PIN ); // turn off unused LEDs
+
if (level == 0) {
- LED3_PWM_LVL = 0;
- LED4_PWM_LVL = 0;
- PWM_CNT = 0; // reset phase
+ MAIN2_PWM_LVL = 0;
+ LED3_PWM_LVL = 0;
+ PWM_CNT = 0; // reset phase
MAIN2_ENABLE_PORT &= ~(1 << MAIN2_ENABLE_PIN); // turn off opamp
LED3_ENABLE_PORT &= ~(1 << LED3_ENABLE_PIN ); // turn off opamp
- LED4_ENABLE_PORT &= ~(1 << LED4_ENABLE_PIN ); // turn off opamp
return;
}
diff --git a/hwdef-emisar-d4k-3ch.h b/hwdef-emisar-d4k-3ch.h
index 4a3134e..538e3f6 100644
--- a/hwdef-emisar-d4k-3ch.h
+++ b/hwdef-emisar-d4k-3ch.h
@@ -72,6 +72,8 @@ enum channel_modes_e {
#define USE_CHANNEL_MODE_ARGS
// _, _, _, _, 128=middle CCT, 128=middle CCT, 213=purple, _
#define CHANNEL_MODE_ARGS 0,0,0,0,128,128,213,0,RGB_AUX_CM_ARGS
+#define USE_CUSTOM_CHANNEL_3H_MODES
+#define USE_CIRCULAR_TINT_3H
// can use some of the common handlers
#define USE_CALC_2CH_BLEND
diff --git a/spaghetti-monster/anduril/channel-modes.c b/spaghetti-monster/anduril/channel-modes.c
index f7e90bd..b2fc8d1 100644
--- a/spaghetti-monster/anduril/channel-modes.c
+++ b/spaghetti-monster/anduril/channel-modes.c
@@ -53,10 +53,12 @@ uint8_t channel_mode_state(Event event, uint16_t arg) {
#ifdef USE_CUSTOM_CHANNEL_3H_MODES
// defer to mode-specific function if defined
- if (tint_ramp_modes[channel_mode]) {
+ if (channel_3H_modes[channel_mode]) {
StatePtr tint_func = channel_3H_modes[channel_mode];
- return tint_func(channel_mode);
- } else
+ uint8_t err = tint_func(event, arg);
+ if (EVENT_HANDLED == err) return EVENT_HANDLED;
+ // else let the default handler run
+ }
#endif
#ifdef USE_CHANNEL_MODE_ARGS
#ifndef DONT_USE_DEFAULT_CHANNEL_ARG_MODE
@@ -190,3 +192,46 @@ uint8_t nearest_tint_value(const int16_t target) {
}
#endif
+#ifdef USE_CIRCULAR_TINT_3H
+uint8_t circular_tint_3h(Event event, uint16_t arg) {
+ static int8_t tint_ramp_direction = 1;
+ // bugfix: click-click-hold from off to strobes would invoke tint ramping
+ // in addition to changing state... so ignore any tint-ramp events which
+ // don't look like they were meant to be here
+ static uint8_t active = 0;
+ uint8_t tint = cfg.channel_mode_args[channel_mode];
+
+ // click, click, hold: change the current channel's arg (like tint)
+ if (event == EV_click3_hold) {
+ ///// adjust value from 0 to 255 in a circle
+ // reset at beginning of movement
+ if (! arg) {
+ active = 1; // first frame means this is for us
+ }
+ // ignore event if we weren't the ones who handled the first frame
+ if (! active) return EVENT_NOT_HANDLED;
+
+ // smooth tint ramping only
+ tint += tint_ramp_direction;
+
+ cfg.channel_mode_args[channel_mode] = tint;
+ set_level(actual_level);
+ return EVENT_HANDLED;
+ }
+
+ // click, click, hold, release: reverse direction for next ramp
+ else if (event == EV_click3_hold_release) {
+ active = 0; // ignore next hold if it wasn't meant for us
+ // reverse
+ tint_ramp_direction = -tint_ramp_direction;
+ // remember tint after battery change
+ save_config();
+ // bug?: for some reason, brightness can seemingly change
+ // from 1/150 to 2/150 without this next line... not sure why
+ set_level(actual_level);
+ return EVENT_HANDLED;
+ }
+
+ return EVENT_NOT_HANDLED;
+}
+#endif
diff --git a/spaghetti-monster/anduril/channel-modes.h b/spaghetti-monster/anduril/channel-modes.h
index 4c16281..b51721d 100644
--- a/spaghetti-monster/anduril/channel-modes.h
+++ b/spaghetti-monster/anduril/channel-modes.h
@@ -16,3 +16,11 @@ uint8_t channel_mode_config_state(Event event, uint16_t arg);
uint8_t nearest_tint_value(const int16_t target);
#endif
+#ifdef USE_CUSTOM_CHANNEL_3H_MODES
+StatePtr channel_3H_modes[NUM_CHANNEL_MODES];
+#endif
+
+#ifdef USE_CIRCULAR_TINT_3H
+uint8_t circular_tint_3h(Event event, uint16_t arg);
+#endif
+
diff --git a/spaghetti-monster/fsm-channels.c b/spaghetti-monster/fsm-channels.c
index 944bdcb..69add93 100644
--- a/spaghetti-monster/fsm-channels.c
+++ b/spaghetti-monster/fsm-channels.c
@@ -86,21 +86,26 @@ void calc_2ch_blend(
RGB_t hsv2rgb(uint8_t h, uint8_t s, uint8_t v) {
RGB_t color;
- uint16_t region, fpart, high, low, rising, falling;
-
if (s == 0) { // grey
color.r = color.g = color.b = v;
return color;
}
- // make hue 0-5
+ uint8_t region;
+ uint16_t fpart;
+ uint16_t high, low, rising, falling;
+
+ // hue has 6 segments, 0-5
region = ((uint16_t)h * 6) >> 8;
// find remainder part, make it from 0-255
fpart = ((uint16_t)h * 6) - (region << 8);
// calculate graph segments, doing integer multiplication
+ // TODO: calculate 16-bit results, not 8-bit
high = v;
low = (v * (255 - s)) >> 8;
+ // TODO: use a cosine crossfade instead of linear
+ // (because it looks better and feels more natural)
falling = (v * (255 - ((s * fpart) >> 8))) >> 8;
rising = (v * (255 - ((s * (255 - fpart)) >> 8))) >> 8;