Skip to content

Commit 03a29f3

Browse files
committed
feat(underglow): Convert HSB changes to absolute.
* Public type for HSB led color. * New API for calculating "next" HSB based on current state. * Update behavior to convert the increment/decrement commands to absolute command as well.
1 parent 9fe6967 commit 03a29f3

File tree

4 files changed

+129
-71
lines changed

4 files changed

+129
-71
lines changed

app/include/dt-bindings/zmk/rgb.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@
3232
#define RGB_SPD RGB_SPD_CMD 0
3333
#define RGB_EFF RGB_EFF_CMD 0
3434
#define RGB_EFR RGB_EFR_CMD 0
35-
#define RGB_COLOR_HSB(h, s, v) RGB_COLOR_HSB_CMD(((h) << 16) + ((s) << 8) + (v))
35+
#define RGB_COLOR_HSB_VAL(h, s, v) (((h) << 16) + ((s) << 8) + (v))
36+
#define RGB_COLOR_HSB(h, s, v) RGB_COLOR_HSB_CMD##(RGB_COLOR_HSB_VAL(h, s, v))
3637
#define RGB_COLOR_HSV RGB_COLOR_HSB

app/include/zmk/rgb_underglow.h

+10-1
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,22 @@
66

77
#pragma once
88

9+
struct zmk_led_hsb {
10+
uint16_t h;
11+
uint8_t s;
12+
uint8_t b;
13+
};
14+
915
int zmk_rgb_underglow_toggle();
1016
int zmk_rgb_underglow_get_state(bool *state);
1117
int zmk_rgb_underglow_on();
1218
int zmk_rgb_underglow_off();
1319
int zmk_rgb_underglow_cycle_effect(int direction);
20+
struct zmk_led_hsb zmk_rgb_underglow_calc_hue(int direction);
21+
struct zmk_led_hsb zmk_rgb_underglow_calc_sat(int direction);
22+
struct zmk_led_hsb zmk_rgb_underglow_calc_brt(int direction);
1423
int zmk_rgb_underglow_change_hue(int direction);
1524
int zmk_rgb_underglow_change_sat(int direction);
1625
int zmk_rgb_underglow_change_brt(int direction);
1726
int zmk_rgb_underglow_change_spd(int direction);
18-
int zmk_rgb_underglow_set_hsb(uint16_t hue, uint8_t saturation, uint8_t brightness);
27+
int zmk_rgb_underglow_set_hsb(struct zmk_led_hsb color);

app/src/behaviors/behavior_rgb_underglow.c

+50-4
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,57 @@ on_keymap_binding_convert_central_state_dependent_params(struct zmk_behavior_bin
3131
}
3232

3333
binding->param1 = state ? RGB_OFF_CMD : RGB_ON_CMD;
34-
LOG_DBG("RGB relative toggle convert to absolute %s", state ? "OFF" : "ON");
35-
return 0;
34+
break;
35+
}
36+
case RGB_BRI_CMD: {
37+
struct zmk_led_hsb color = zmk_rgb_underglow_calc_brt(1);
38+
39+
binding->param1 = RGB_COLOR_HSB_CMD;
40+
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
41+
break;
42+
}
43+
case RGB_BRD_CMD: {
44+
struct zmk_led_hsb color = zmk_rgb_underglow_calc_brt(-1);
45+
46+
binding->param1 = RGB_COLOR_HSB_CMD;
47+
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
48+
break;
49+
}
50+
case RGB_HUI_CMD: {
51+
struct zmk_led_hsb color = zmk_rgb_underglow_calc_hue(1);
52+
53+
binding->param1 = RGB_COLOR_HSB_CMD;
54+
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
55+
break;
56+
}
57+
case RGB_HUD_CMD: {
58+
struct zmk_led_hsb color = zmk_rgb_underglow_calc_hue(-1);
59+
60+
binding->param1 = RGB_COLOR_HSB_CMD;
61+
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
62+
break;
63+
}
64+
case RGB_SAI_CMD: {
65+
struct zmk_led_hsb color = zmk_rgb_underglow_calc_sat(1);
66+
67+
binding->param1 = RGB_COLOR_HSB_CMD;
68+
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
69+
break;
70+
}
71+
case RGB_SAD_CMD: {
72+
struct zmk_led_hsb color = zmk_rgb_underglow_calc_sat(-1);
73+
74+
binding->param1 = RGB_COLOR_HSB_CMD;
75+
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
76+
break;
3677
}
3778
default:
3879
return 0;
3980
}
81+
82+
LOG_DBG("RGB relative convert to absolute (%d/%d)", binding->param1, binding->param2);
83+
84+
return 0;
4085
};
4186

4287
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
@@ -69,8 +114,9 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
69114
case RGB_EFR_CMD:
70115
return zmk_rgb_underglow_cycle_effect(-1);
71116
case RGB_COLOR_HSB_CMD:
72-
return zmk_rgb_underglow_set_hsb((binding->param2 >> 16) & 0xFFFF,
73-
(binding->param2 >> 8) & 0xFF, binding->param2 & 0xFF);
117+
return zmk_rgb_underglow_set_hsb((struct zmk_led_hsb){.h = (binding->param2 >> 16) & 0xFFFF,
118+
.s = (binding->param2 >> 8) & 0xFF,
119+
.b = binding->param2 & 0xFF});
74120
}
75121

76122
return -ENOTSUP;

app/src/rgb_underglow.c

+67-65
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include <drivers/led_strip.h>
1818
#include <drivers/ext_power.h>
1919

20+
#include <zmk/rgb_underglow.h>
21+
2022
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
2123

2224
#define STRIP_LABEL DT_LABEL(DT_CHOSEN(zmk_underglow))
@@ -30,16 +32,8 @@ enum rgb_underglow_effect {
3032
UNDERGLOW_EFFECT_NUMBER // Used to track number of underglow effects
3133
};
3234

33-
struct led_hsb {
34-
uint16_t h;
35-
uint8_t s;
36-
uint8_t b;
37-
};
38-
3935
struct rgb_underglow_state {
40-
uint16_t hue;
41-
uint8_t saturation;
42-
uint8_t brightness;
36+
struct zmk_led_hsb color;
4337
uint8_t animation_speed;
4438
uint8_t current_effect;
4539
uint16_t animation_step;
@@ -56,7 +50,7 @@ static struct rgb_underglow_state state;
5650
static const struct device *ext_power;
5751
#endif
5852

59-
static struct led_rgb hsb_to_rgb(struct led_hsb hsb) {
53+
static struct led_rgb hsb_to_rgb(struct zmk_led_hsb hsb) {
6054
double r, g, b;
6155

6256
uint8_t i = hsb.h / 60;
@@ -107,23 +101,14 @@ static struct led_rgb hsb_to_rgb(struct led_hsb hsb) {
107101

108102
static void zmk_rgb_underglow_effect_solid() {
109103
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
110-
int hue = state.hue;
111-
int sat = state.saturation;
112-
int brt = state.brightness;
113-
114-
struct led_hsb hsb = {hue, sat, brt};
115-
116-
pixels[i] = hsb_to_rgb(hsb);
104+
pixels[i] = hsb_to_rgb(state.color);
117105
}
118106
}
119107

120108
static void zmk_rgb_underglow_effect_breathe() {
121109
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
122-
int hue = state.hue;
123-
int sat = state.saturation;
124-
int brt = abs(state.animation_step - 1200) / 12;
125-
126-
struct led_hsb hsb = {hue, sat, brt};
110+
struct zmk_led_hsb hsb = state.color;
111+
hsb.b = abs(state.animation_step - 1200) / 12;
127112

128113
pixels[i] = hsb_to_rgb(hsb);
129114
}
@@ -137,11 +122,8 @@ static void zmk_rgb_underglow_effect_breathe() {
137122

138123
static void zmk_rgb_underglow_effect_spectrum() {
139124
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
140-
int hue = state.animation_step;
141-
int sat = state.saturation;
142-
int brt = state.brightness;
143-
144-
struct led_hsb hsb = {hue, sat, brt};
125+
struct zmk_led_hsb hsb = state.color;
126+
hsb.h = state.animation_speed;
145127

146128
pixels[i] = hsb_to_rgb(hsb);
147129
}
@@ -152,11 +134,8 @@ static void zmk_rgb_underglow_effect_spectrum() {
152134

153135
static void zmk_rgb_underglow_effect_swirl() {
154136
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
155-
int hue = (360 / STRIP_NUM_PIXELS * i + state.animation_step) % 360;
156-
int sat = state.saturation;
157-
int brt = state.brightness;
158-
159-
struct led_hsb hsb = {hue, sat, brt};
137+
struct zmk_led_hsb hsb = state.color;
138+
hsb.h = (360 / STRIP_NUM_PIXELS * i + state.animation_step) % 360;
160139

161140
pixels[i] = hsb_to_rgb(hsb);
162141
}
@@ -243,9 +222,11 @@ static int zmk_rgb_underglow_init(const struct device *_arg) {
243222
#endif
244223

245224
state = (struct rgb_underglow_state){
246-
hue : CONFIG_ZMK_RGB_UNDERGLOW_HUE_START,
247-
saturation : CONFIG_ZMK_RGB_UNDERGLOW_SAT_START,
248-
brightness : CONFIG_ZMK_RGB_UNDERGLOW_BRT_START,
225+
color : {
226+
h : CONFIG_ZMK_RGB_UNDERGLOW_HUE_START,
227+
s : CONFIG_ZMK_RGB_UNDERGLOW_SAT_START,
228+
b : CONFIG_ZMK_RGB_UNDERGLOW_BRT_START,
229+
},
249230
animation_speed : CONFIG_ZMK_RGB_UNDERGLOW_SPD_START,
250231
current_effect : CONFIG_ZMK_RGB_UNDERGLOW_EFF_START,
251232
animation_step : 0,
@@ -357,64 +338,85 @@ int zmk_rgb_underglow_toggle() {
357338
return state.on ? zmk_rgb_underglow_off() : zmk_rgb_underglow_on();
358339
}
359340

360-
int zmk_rgb_underglow_set_hsb(uint16_t hue, uint8_t saturation, uint8_t brightness) {
361-
if (hue > 360 || saturation > 100 || brightness > 100) {
341+
int zmk_rgb_underglow_set_hsb(struct zmk_led_hsb color) {
342+
if (color.h > 360 || color.s > 100 || color.b > 100) {
362343
return -ENOTSUP;
363344
}
364345

365-
state.hue = hue;
366-
state.saturation = saturation;
367-
state.brightness = brightness;
346+
state.color = color;
368347

369348
return 0;
370349
}
371350

372-
int zmk_rgb_underglow_change_hue(int direction) {
373-
if (!led_strip)
374-
return -ENODEV;
351+
struct zmk_led_hsb zmk_rgb_underglow_calc_hue(int direction) {
352+
struct zmk_led_hsb color = state.color;
375353

376-
if (state.hue == 0 && direction < 0) {
377-
state.hue = 360 - CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP;
378-
return 0;
354+
if (color.h == 0 && direction < 0) {
355+
return color;
379356
}
380357

381-
state.hue += direction * CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP;
358+
color.h += direction * CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP;
382359

383-
state.hue = state.hue % 360;
360+
color.h = color.h % 360;
384361

385-
return zmk_rgb_underglow_save_state();
362+
return color;
386363
}
387364

388-
int zmk_rgb_underglow_change_sat(int direction) {
389-
if (!led_strip)
390-
return -ENODEV;
365+
struct zmk_led_hsb zmk_rgb_underglow_calc_sat(int direction) {
366+
struct zmk_led_hsb color = state.color;
391367

392-
if (state.saturation == 0 && direction < 0) {
393-
return 0;
368+
if (color.s == 0 && direction < 0) {
369+
return color;
370+
}
371+
372+
color.s += direction * CONFIG_ZMK_RGB_UNDERGLOW_SAT_STEP;
373+
374+
if (color.s > 100) {
375+
color.s = 100;
376+
}
377+
378+
return color;
379+
}
380+
381+
struct zmk_led_hsb zmk_rgb_underglow_calc_brt(int direction) {
382+
struct zmk_led_hsb color = state.color;
383+
384+
if (color.b == 0 && direction < 0) {
385+
return color;
394386
}
395387

396-
state.saturation += direction * CONFIG_ZMK_RGB_UNDERGLOW_SAT_STEP;
388+
color.b += direction * CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP;
397389

398-
if (state.saturation > 100) {
399-
state.saturation = 100;
390+
if (color.b > 100) {
391+
color.b = 100;
400392
}
401393

394+
return color;
395+
}
396+
397+
int zmk_rgb_underglow_change_hue(int direction) {
398+
if (!led_strip)
399+
return -ENODEV;
400+
401+
state.color = zmk_rgb_underglow_calc_hue(direction);
402+
402403
return zmk_rgb_underglow_save_state();
403404
}
404405

405-
int zmk_rgb_underglow_change_brt(int direction) {
406+
int zmk_rgb_underglow_change_sat(int direction) {
406407
if (!led_strip)
407408
return -ENODEV;
408409

409-
if (state.brightness == 0 && direction < 0) {
410-
return 0;
411-
}
410+
state.color = zmk_rgb_underglow_calc_sat(direction);
412411

413-
state.brightness += direction * CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP;
412+
return zmk_rgb_underglow_save_state();
413+
}
414414

415-
if (state.brightness > 100) {
416-
state.brightness = 100;
417-
}
415+
int zmk_rgb_underglow_change_brt(int direction) {
416+
if (!led_strip)
417+
return -ENODEV;
418+
419+
state.color = zmk_rgb_underglow_calc_brt(direction);
418420

419421
return zmk_rgb_underglow_save_state();
420422
}

0 commit comments

Comments
 (0)