@ -17,11 +17,17 @@
# include <drivers/led_strip.h>
# include <drivers/led_strip.h>
# include <drivers/ext_power.h>
# include <drivers/ext_power.h>
# include <zmk/rgb_underglow.h>
LOG_MODULE_DECLARE ( zmk , CONFIG_ZMK_LOG_LEVEL ) ;
LOG_MODULE_DECLARE ( zmk , CONFIG_ZMK_LOG_LEVEL ) ;
# define STRIP_LABEL DT_LABEL(DT_CHOSEN(zmk_underglow))
# define STRIP_LABEL DT_LABEL(DT_CHOSEN(zmk_underglow))
# define STRIP_NUM_PIXELS DT_PROP(DT_CHOSEN(zmk_underglow), chain_length)
# define STRIP_NUM_PIXELS DT_PROP(DT_CHOSEN(zmk_underglow), chain_length)
# define HUE_MAX 360
# define SAT_MAX 100
# define BRT_MAX 100
enum rgb_underglow_effect {
enum rgb_underglow_effect {
UNDERGLOW_EFFECT_SOLID ,
UNDERGLOW_EFFECT_SOLID ,
UNDERGLOW_EFFECT_BREATHE ,
UNDERGLOW_EFFECT_BREATHE ,
@ -30,16 +36,8 @@ enum rgb_underglow_effect {
UNDERGLOW_EFFECT_NUMBER // Used to track number of underglow effects
UNDERGLOW_EFFECT_NUMBER // Used to track number of underglow effects
} ;
} ;
struct led_hsb {
uint16_t h ;
uint8_t s ;
uint8_t b ;
} ;
struct rgb_underglow_state {
struct rgb_underglow_state {
uint16_t hue ;
struct zmk_led_hsb color ;
uint8_t saturation ;
uint8_t brightness ;
uint8_t animation_speed ;
uint8_t animation_speed ;
uint8_t current_effect ;
uint8_t current_effect ;
uint16_t animation_step ;
uint16_t animation_step ;
@ -56,13 +54,13 @@ static struct rgb_underglow_state state;
static const struct device * ext_power ;
static const struct device * ext_power ;
# endif
# endif
static struct led_rgb hsb_to_rgb ( struct led_hsb hsb ) {
static struct led_rgb hsb_to_rgb ( struct zmk_ led_hsb hsb ) {
double r , g , b ;
double r , g , b ;
uint8_t i = hsb . h / 60 ;
uint8_t i = hsb . h / 60 ;
double v = hsb . b / 100.0 ;
double v = hsb . b / ( ( float ) BRT_MAX ) ;
double s = hsb . s / 100.0 ;
double s = hsb . s / ( ( float ) SAT_MAX ) ;
double f = hsb . h / 360.0 * 6 - i ;
double f = hsb . h / ( ( float ) HUE_MAX ) * 6 - i ;
double p = v * ( 1 - s ) ;
double p = v * ( 1 - s ) ;
double q = v * ( 1 - f * s ) ;
double q = v * ( 1 - f * s ) ;
double t = v * ( 1 - ( 1 - f ) * s ) ;
double t = v * ( 1 - ( 1 - f ) * s ) ;
@ -107,23 +105,14 @@ static struct led_rgb hsb_to_rgb(struct led_hsb hsb) {
static void zmk_rgb_underglow_effect_solid ( ) {
static void zmk_rgb_underglow_effect_solid ( ) {
for ( int i = 0 ; i < STRIP_NUM_PIXELS ; i + + ) {
for ( int i = 0 ; i < STRIP_NUM_PIXELS ; i + + ) {
int hue = state . hue ;
pixels [ i ] = hsb_to_rgb ( state . color ) ;
int sat = state . saturation ;
int brt = state . brightness ;
struct led_hsb hsb = { hue , sat , brt } ;
pixels [ i ] = hsb_to_rgb ( hsb ) ;
}
}
}
}
static void zmk_rgb_underglow_effect_breathe ( ) {
static void zmk_rgb_underglow_effect_breathe ( ) {
for ( int i = 0 ; i < STRIP_NUM_PIXELS ; i + + ) {
for ( int i = 0 ; i < STRIP_NUM_PIXELS ; i + + ) {
int hue = state . hue ;
struct zmk_led_hsb hsb = state . color ;
int sat = state . saturation ;
hsb . b = abs ( state . animation_step - 1200 ) / 12 ;
int brt = abs ( state . animation_step - 1200 ) / 12 ;
struct led_hsb hsb = { hue , sat , brt } ;
pixels [ i ] = hsb_to_rgb ( hsb ) ;
pixels [ i ] = hsb_to_rgb ( hsb ) ;
}
}
@ -137,32 +126,26 @@ static void zmk_rgb_underglow_effect_breathe() {
static void zmk_rgb_underglow_effect_spectrum ( ) {
static void zmk_rgb_underglow_effect_spectrum ( ) {
for ( int i = 0 ; i < STRIP_NUM_PIXELS ; i + + ) {
for ( int i = 0 ; i < STRIP_NUM_PIXELS ; i + + ) {
int hue = state . animation_step ;
struct zmk_led_hsb hsb = state . color ;
int sat = state . saturation ;
hsb . h = state . animation_step ;
int brt = state . brightness ;
struct led_hsb hsb = { hue , sat , brt } ;
pixels [ i ] = hsb_to_rgb ( hsb ) ;
pixels [ i ] = hsb_to_rgb ( hsb ) ;
}
}
state . animation_step + = state . animation_speed ;
state . animation_step + = state . animation_speed ;
state . animation_step = state . animation_step % 360 ;
state . animation_step = state . animation_step % HUE_MAX ;
}
}
static void zmk_rgb_underglow_effect_swirl ( ) {
static void zmk_rgb_underglow_effect_swirl ( ) {
for ( int i = 0 ; i < STRIP_NUM_PIXELS ; i + + ) {
for ( int i = 0 ; i < STRIP_NUM_PIXELS ; i + + ) {
int hue = ( 360 / STRIP_NUM_PIXELS * i + state . animation_step ) % 360 ;
struct zmk_led_hsb hsb = state . color ;
int sat = state . saturation ;
hsb . h = ( HUE_MAX / STRIP_NUM_PIXELS * i + state . animation_step ) % HUE_MAX ;
int brt = state . brightness ;
struct led_hsb hsb = { hue , sat , brt } ;
pixels [ i ] = hsb_to_rgb ( hsb ) ;
pixels [ i ] = hsb_to_rgb ( hsb ) ;
}
}
state . animation_step + = state . animation_speed * 2 ;
state . animation_step + = state . animation_speed * 2 ;
state . animation_step = state . animation_step % 360 ;
state . animation_step = state . animation_step % HUE_MAX ;
}
}
static void zmk_rgb_underglow_tick ( struct k_work * work ) {
static void zmk_rgb_underglow_tick ( struct k_work * work ) {
@ -243,9 +226,11 @@ static int zmk_rgb_underglow_init(const struct device *_arg) {
# endif
# endif
state = ( struct rgb_underglow_state ) {
state = ( struct rgb_underglow_state ) {
hue : CONFIG_ZMK_RGB_UNDERGLOW_HUE_START ,
color : {
saturation : CONFIG_ZMK_RGB_UNDERGLOW_SAT_START ,
h : CONFIG_ZMK_RGB_UNDERGLOW_HUE_START ,
brightness : CONFIG_ZMK_RGB_UNDERGLOW_BRT_START ,
s : CONFIG_ZMK_RGB_UNDERGLOW_SAT_START ,
b : CONFIG_ZMK_RGB_UNDERGLOW_BRT_START ,
} ,
animation_speed : CONFIG_ZMK_RGB_UNDERGLOW_SPD_START ,
animation_speed : CONFIG_ZMK_RGB_UNDERGLOW_SPD_START ,
current_effect : CONFIG_ZMK_RGB_UNDERGLOW_EFF_START ,
current_effect : CONFIG_ZMK_RGB_UNDERGLOW_EFF_START ,
animation_step : 0 ,
animation_step : 0 ,
@ -337,16 +322,8 @@ int zmk_rgb_underglow_cycle_effect(int direction) {
if ( ! led_strip )
if ( ! led_strip )
return - ENODEV ;
return - ENODEV ;
if ( state . current_effect = = 0 & & direction < 0 ) {
state . current_effect + = UNDERGLOW_EFFECT_NUMBER + direction ;
state . current_effect = UNDERGLOW_EFFECT_NUMBER - 1 ;
state . current_effect % = UNDERGLOW_EFFECT_NUMBER ;
return 0 ;
}
state . current_effect + = direction ;
if ( state . current_effect > = UNDERGLOW_EFFECT_NUMBER ) {
state . current_effect = 0 ;
}
state . animation_step = 0 ;
state . animation_step = 0 ;
@ -357,64 +334,76 @@ int zmk_rgb_underglow_toggle() {
return state . on ? zmk_rgb_underglow_off ( ) : zmk_rgb_underglow_on ( ) ;
return state . on ? zmk_rgb_underglow_off ( ) : zmk_rgb_underglow_on ( ) ;
}
}
int zmk_rgb_underglow_set_hsb ( uint16_t hue , uint8_t saturation , uint8_t brightness ) {
int zmk_rgb_underglow_set_hsb ( struct zmk_led_hsb color ) {
if ( hue > 360 | | saturation > 100 | | brightness > 100 ) {
if ( color . h > HUE_MAX | | color . s > SAT_MAX | | color . b > BRT_MAX ) {
return - ENOTSUP ;
return - ENOTSUP ;
}
}
state . hue = hue ;
state . color = color ;
state . saturation = saturation ;
state . brightness = brightness ;
return 0 ;
return 0 ;
}
}
int zmk_rgb_underglow_change_hue ( int direction ) {
struct zmk_led_hsb zmk_rgb_underglow_calc_hue ( int direction ) {
if ( ! led_strip )
struct zmk_led_hsb color = state . color ;
return - ENODEV ;
if ( state . hue = = 0 & & direction < 0 ) {
color . h + = HUE_MAX + ( direction * CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP ) ;
state . hue = 360 - CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP ;
color . h % = HUE_MAX ;
return 0 ;
return color ;
}
}
state . hue + = direction * CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP ;
struct zmk_led_hsb zmk_rgb_underglow_calc_sat ( int direction ) {
struct zmk_led_hsb color = state . color ;
state . hue = state . hue % 360 ;
int s = color . s + ( direction * CONFIG_ZMK_RGB_UNDERGLOW_SAT_STEP ) ;
if ( s < 0 ) {
s = 0 ;
} else if ( s > SAT_MAX ) {
s = SAT_MAX ;
}
color . s = s ;
return zmk_rgb_underglow_save_state ( ) ;
return color ;
}
}
int zmk_rgb_underglow_change_sat ( int direction ) {
struct zmk_led_hsb zmk_rgb_underglow_calc_brt ( int direction ) {
if ( ! led_strip )
struct zmk_led_hsb color = state . color ;
return - ENODEV ;
if ( state . saturation = = 0 & & direction < 0 ) {
int b = color . b + ( direction * CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP ) ;
return 0 ;
if ( b < 0 ) {
b = 0 ;
} else if ( b > BRT_MAX ) {
b = BRT_MAX ;
}
}
color . b = b ;
state . saturation + = direction * CONFIG_ZMK_RGB_UNDERGLOW_SAT_STEP ;
return color ;
if ( state . saturation > 100 ) {
state . saturation = 100 ;
}
}
int zmk_rgb_underglow_change_hue ( int direction ) {
if ( ! led_strip )
return - ENODEV ;
state . color = zmk_rgb_underglow_calc_hue ( direction ) ;
return zmk_rgb_underglow_save_state ( ) ;
return zmk_rgb_underglow_save_state ( ) ;
}
}
int zmk_rgb_underglow_change_brt ( int direction ) {
int zmk_rgb_underglow_change_sa t ( int direction ) {
if ( ! led_strip )
if ( ! led_strip )
return - ENODEV ;
return - ENODEV ;
if ( state . brightness = = 0 & & direction < 0 ) {
state . color = zmk_rgb_underglow_calc_sat ( direction ) ;
return 0 ;
return zmk_rgb_underglow_save_state ( ) ;
}
}
state . brightness + = direction * CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP ;
int zmk_rgb_underglow_change_brt ( int direction ) {
if ( ! led_strip )
return - ENODEV ;
if ( state . brightness > 100 ) {
state . color = zmk_rgb_underglow_calc_brt ( direction ) ;
state . brightness = 100 ;
}
return zmk_rgb_underglow_save_state ( ) ;
return zmk_rgb_underglow_save_state ( ) ;
}
}