diff options
| -rw-r--r-- | hwdef-emisar-d4k-3ch.c | 33 | ||||
| -rw-r--r-- | hwdef-emisar-d4k-3ch.h | 2 | ||||
| -rw-r--r-- | spaghetti-monster/anduril/channel-modes.c | 51 | ||||
| -rw-r--r-- | spaghetti-monster/anduril/channel-modes.h | 8 | ||||
| -rw-r--r-- | spaghetti-monster/fsm-channels.c | 11 |
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; |
