11/*
2- * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
2+ * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
33 *
44 * SPDX-License-Identifier: Apache-2.0
55 */
@@ -62,6 +62,12 @@ typedef struct {
6262 TimerHandle_t effect_timer ; // Timer handle related to the flashing, fading
6363 SemaphoreHandle_t mutex ; // For multi-thread protection
6464
65+ // Structure containing pointers to gamma correction tables for color and white
66+ struct {
67+ uint16_t * color_gamma_table ; // Pointer to the color gamma correction table (for RGB)
68+ uint16_t * white_gamma_table ; // Pointer to the white gamma correction table (for CCT)
69+ } gamma_correction ;
70+
6571 // Structure containing flags related to effects
6672 struct {
6773 bool allow_interrupt : 1 ; // Flag indicating if the effect can be interrupted
@@ -304,23 +310,22 @@ static void cct_and_brightness_convert_and_power_limit(lightbulb_led_beads_comb_
304310 hal_get_driver_feature (QUERY_MAX_INPUT_VALUE , & max_value );
305311
306312 if (led_beads == LED_BEADS_1CH_C || led_beads == LED_BEADS_4CH_RGBC || led_beads == LED_BEADS_4CH_RGBCC ) {
307- uint16_t value = brightness / 100.0 * max_value ;
308- hal_get_linear_table_value (( uint8_t ) value , & white_value [3 ]);
313+ uint16_t value = brightness * max_value / 100 ;
314+ hal_get_curve_table_value ( value , & white_value [3 ]);
309315 if (led_beads == LED_BEADS_4CH_RGBCC ) {
310- hal_get_linear_table_value (( uint8_t ) value , & white_value [4 ]);
316+ hal_get_curve_table_value ( value , & white_value [4 ]);
311317 }
312318 } else if (led_beads == LED_BEADS_1CH_W || led_beads == LED_BEADS_4CH_RGBW || led_beads == LED_BEADS_4CH_RGBWW ) {
313- uint16_t value = brightness / 100.0 * max_value ;
314- hal_get_linear_table_value (value , & white_value [4 ]);
315-
319+ uint16_t value = brightness * max_value / 100 ;
320+ hal_get_curve_table_value (value , & white_value [4 ]);
316321 if (led_beads == LED_BEADS_4CH_RGBWW ) {
317- hal_get_linear_table_value (( uint8_t ) value , & white_value [3 ]);
322+ hal_get_curve_table_value ( value , & white_value [3 ]);
318323 }
319324 } else if ((led_beads == LED_BEADS_2CH_CW || led_beads == LED_BEADS_5CH_RGBCW ) && IS_WHITE_OUTPUT_HARDWARE_MIXED ()) {
320- uint16_t value1 = cct / 100.0 * max_value ;
321- uint16_t value2 = brightness / 100.0 * max_value ;
322- hal_get_linear_table_value (( uint8_t ) value1 , & white_value [3 ]);
323- hal_get_linear_table_value (( uint8_t ) value2 , & white_value [4 ]);
325+ uint16_t value1 = cct * max_value / 100 ;
326+ uint16_t value2 = brightness * max_value / 100 ;
327+ hal_get_curve_table_value ( value1 , & white_value [3 ]);
328+ hal_get_curve_table_value ( value2 , & white_value [4 ]);
324329 } else if (led_beads == LED_BEADS_2CH_CW || ((led_beads == LED_BEADS_5CH_RGBCW ) && (s_lb_obj -> cap .enable_precise_cct_control == false))) {
325330 float max_power ;
326331 float _c = cct / 100.0 ;
@@ -330,8 +335,8 @@ static void cct_and_brightness_convert_and_power_limit(lightbulb_led_beads_comb_
330335 max_power = MIN (max_value * multiple , max_value / baseline );
331336 _c = max_power * _c * (brightness / 100.0 );
332337 _w = max_power * _w * (brightness / 100.0 );
333- hal_get_linear_table_value (( uint16_t ) _c , & white_value [3 ]);
334- hal_get_linear_table_value (( uint16_t ) _w , & white_value [4 ]);
338+ hal_get_curve_table_value ( _c , & white_value [3 ]);
339+ hal_get_curve_table_value ( _w , & white_value [4 ]);
335340 } else {
336341 float max_power ;
337342 lightbulb_cct_mapping_data_t data = search_mapping_cct_data (cct );
@@ -344,7 +349,8 @@ static void cct_and_brightness_convert_and_power_limit(lightbulb_led_beads_comb_
344349 max_power = MIN (max_value * multiple , max_value / baseline );
345350 ESP_LOGD (TAG , "%f, %d, %f" , max_power , max_value , baseline );
346351 for (int i = 0 ; i < 5 ; i ++ ) {
347- white_value [i ] = round (max_power * data .rgbcw [i ] * (brightness / 100.0 ));
352+ float value = round (max_power * data .rgbcw [i ] * (brightness / 100.0 ));
353+ hal_get_curve_table_value ((uint16_t )value , & white_value [i ]);
348354 }
349355 }
350356}
@@ -371,7 +377,9 @@ static uint8_t process_color_value_limit(uint8_t value)
371377 float percentage = value / 100.0 ;
372378
373379 uint8_t result = (s_lb_obj -> power .color_max_value - s_lb_obj -> power .color_min_value ) * percentage + s_lb_obj -> power .color_min_value ;
380+ result = s_lb_obj -> gamma_correction .color_gamma_table [result ];
374381 ESP_LOGD (TAG , "color_value convert input:%d output:%d" , value , result );
382+
375383 return result ;
376384}
377385
@@ -397,7 +405,9 @@ static uint8_t process_white_brightness_limit(uint8_t brightness)
397405 float percentage = brightness / 100.0 ;
398406
399407 uint8_t result = (s_lb_obj -> power .white_max_brightness - s_lb_obj -> power .white_min_brightness ) * percentage + s_lb_obj -> power .white_min_brightness ;
408+ result = s_lb_obj -> gamma_correction .white_gamma_table [result ];
400409 ESP_LOGD (TAG , "white_brightness_output input:%d output:%d" , brightness , result );
410+
401411 return result ;
402412}
403413
@@ -428,7 +438,8 @@ static void process_color_power_limit(float multiple, float rgbcw[5], uint16_t v
428438 max_power = MIN (max_power , max_value / baseline );
429439 ESP_LOGD (TAG , "%f, %d, %f" , max_power , max_value , baseline );
430440 for (int i = 0 ; i < 5 ; i ++ ) {
431- out [i ] = round (max_power * rgbcw [i ] * (value / 100.0 ));
441+ float value = round (max_power * rgbcw [i ]);
442+ hal_get_curve_table_value ((uint16_t )value , & out [i ]);
432443 }
433444}
434445
@@ -911,6 +922,20 @@ esp_err_t lightbulb_init(lightbulb_config_t *config)
911922 s_lb_obj -> cap .fade_time_ms = MAX (MIN_FADE_MS , s_lb_obj -> cap .fade_time_ms );
912923 }
913924
925+ //Gamma table create
926+ float color_coe = 1.0 ;
927+ float white_coe = 1.0 ;
928+ if (config -> gamma_conf ) {
929+ color_coe = config -> gamma_conf -> color_curve_coefficient ;
930+ white_coe = config -> gamma_conf -> white_curve_coefficient ;
931+ }
932+ s_lb_obj -> gamma_correction .color_gamma_table = calloc (101 , sizeof (uint16_t ));
933+ LIGHTBULB_CHECK (s_lb_obj -> gamma_correction .color_gamma_table , "curve table buffer alloc fail" , goto EXIT );
934+ s_lb_obj -> gamma_correction .white_gamma_table = calloc (101 , sizeof (uint16_t ));
935+ LIGHTBULB_CHECK (s_lb_obj -> gamma_correction .white_gamma_table , "curve table buffer alloc fail" , goto EXIT );
936+ hal_gamma_table_create (s_lb_obj -> gamma_correction .color_gamma_table , 101 , color_coe , 100 );
937+ hal_gamma_table_create (s_lb_obj -> gamma_correction .white_gamma_table , 101 , white_coe , 100 );
938+
914939 // Low power check
915940 if (config -> capability .enable_lowpower ) {
916941 /* Make sure the fade is done and the flash operation is done, then enable light sleep */
@@ -991,6 +1016,15 @@ esp_err_t lightbulb_deinit(void)
9911016 s_lb_obj -> color_manager .mix_table = NULL ;
9921017 }
9931018
1019+ if (s_lb_obj -> gamma_correction .color_gamma_table ) {
1020+ free (s_lb_obj -> gamma_correction .color_gamma_table );
1021+ s_lb_obj -> gamma_correction .color_gamma_table = NULL ;
1022+ }
1023+ if (s_lb_obj -> gamma_correction .white_gamma_table ) {
1024+ free (s_lb_obj -> gamma_correction .white_gamma_table );
1025+ s_lb_obj -> gamma_correction .white_gamma_table = NULL ;
1026+ }
1027+
9941028 free (s_lb_obj );
9951029 s_lb_obj = NULL ;
9961030
@@ -1196,11 +1230,11 @@ static esp_err_t lightbulb_hsv2rgb_adjusted(uint16_t hue, uint8_t saturation, ui
11961230 }
11971231 }
11981232
1199- * red = interpolated_rgbcw [0 ];
1200- * green = interpolated_rgbcw [1 ];
1201- * blue = interpolated_rgbcw [2 ];
1202- * cold = interpolated_rgbcw [3 ];
1203- * warm = interpolated_rgbcw [4 ];
1233+ * red = interpolated_rgbcw [0 ] * value / 100.0 ;
1234+ * green = interpolated_rgbcw [1 ] * value / 100.0 ;
1235+ * blue = interpolated_rgbcw [2 ] * value / 100.0 ;
1236+ * cold = interpolated_rgbcw [3 ] * value / 100.0 ;
1237+ * warm = interpolated_rgbcw [4 ] * value / 100.0 ;
12041238
12051239 return ESP_OK ;
12061240}
0 commit comments