feat: replace lightdriver, and support more chips in ble mesh examples

This commit is contained in:
MinZai97 2023-12-18 20:45:08 +08:00 committed by YuanMingFu
parent c05940a0fb
commit fde5e93ab5
29 changed files with 320 additions and 2614 deletions

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | | Supported Targets | ESP32 | ESP32-C3 | ESP32-S3 | ESP32-H2 | ESP32-C6 |
| ----------------- | ----- | | ----------------- | ----- | -------- | -------- | -------- | -------- |
ESP BLE Mesh AliGenie Example ESP BLE Mesh AliGenie Example
============================= =============================

View File

@ -23,6 +23,7 @@ menu "AliGenie Example Configuration"
menu "light driver config" menu "light driver config"
config LIGHT_GPIO_RED config LIGHT_GPIO_RED
int "Light red pin GPIO number" int "Light red pin GPIO number"
range -1 48 if IDF_TARGET_ESP32S3
range -1 33 range -1 33
default 25 default 25
help help
@ -33,6 +34,7 @@ menu "AliGenie Example Configuration"
config LIGHT_GPIO_GREEN config LIGHT_GPIO_GREEN
int "Light green pin GPIO number" int "Light green pin GPIO number"
range -1 48 if IDF_TARGET_ESP32S3
range -1 33 range -1 33
default 26 default 26
help help
@ -43,6 +45,7 @@ menu "AliGenie Example Configuration"
config LIGHT_GPIO_BLUE config LIGHT_GPIO_BLUE
int "Light blue pin GPIO number" int "Light blue pin GPIO number"
range -1 48 if IDF_TARGET_ESP32S3
range -1 33 range -1 33
default 27 default 27
help help
@ -53,6 +56,7 @@ menu "AliGenie Example Configuration"
config LIGHT_GPIO_COLD config LIGHT_GPIO_COLD
int "Light cold colors pin GPIO number" int "Light cold colors pin GPIO number"
range -1 48 if IDF_TARGET_ESP32S3
range -1 33 range -1 33
default -1 default -1
help help
@ -63,6 +67,7 @@ menu "AliGenie Example Configuration"
config LIGHT_GPIO_WARM config LIGHT_GPIO_WARM
int "Light warm color pin GPIO number" int "Light warm color pin GPIO number"
range -1 48 if IDF_TARGET_ESP32S3
range -1 33 range -1 33
default -1 default -1
help help

View File

@ -37,6 +37,7 @@ static const char *TAG = "genie_demo";
#define MESH_ELEM_COUNT 1 #define MESH_ELEM_COUNT 1
#define MESH_ELEM_STATE_COUNT MESH_ELEM_COUNT #define MESH_ELEM_STATE_COUNT MESH_ELEM_COUNT
#define LIGHT_STATUS_STORE_KEY "light_status"
nvs_handle_t NVS_HANDLE; nvs_handle_t NVS_HANDLE;
@ -416,12 +417,34 @@ void user_genie_event_handle(genie_event_t event, void *p_arg)
switch (event) { switch (event) {
case GENIE_EVT_RESET_BY_REPEAT_NOTIFY: case GENIE_EVT_RESET_BY_REPEAT_NOTIFY:
ESP_LOGI(TAG, "GENIE_EVT_RESET_BY_REPEAT_NOTIFY"); ESP_LOGI(TAG, "GENIE_EVT_RESET_BY_REPEAT_NOTIFY");
light_driver_breath_start(0, 255, 0); /**< green blink */ lightbulb_set_switch(false);
lightbulb_effect_config_t effect1 = {
.red = 0,
.green = 255,
.blue = 0,
.max_brightness = 100,
.min_brightness = 0,
.effect_cycle_ms = CONFIG_LIGHT_BLINK_PERIOD_MS,
.effect_type = EFFECT_BLINK,
.mode = WORK_COLOR,
};
lightbulb_basic_effect_start(&effect1); /**< green blink */
break; break;
case GENIE_EVT_SW_RESET: case GENIE_EVT_SW_RESET:
case GENIE_EVT_HW_RESET_START: case GENIE_EVT_HW_RESET_START:
ESP_LOGI(TAG, "GENIE_EVT_HW_RESET_START"); ESP_LOGI(TAG, "GENIE_EVT_HW_RESET_START");
light_driver_breath_start(0, 255, 0); /**< green blink */ lightbulb_set_switch(false);
lightbulb_effect_config_t effect2 = {
.red = 0,
.green = 255,
.blue = 0,
.max_brightness = 100,
.min_brightness = 0,
.effect_cycle_ms = CONFIG_LIGHT_BLINK_PERIOD_MS,
.effect_type = EFFECT_BLINK,
.mode = WORK_COLOR,
};
lightbulb_basic_effect_start(&effect2); /**< green blink */
ble_mesh_nvs_erase(NVS_HANDLE, LIGHT_STATUS_STORE_KEY); // erase led status ble_mesh_nvs_erase(NVS_HANDLE, LIGHT_STATUS_STORE_KEY); // erase led status
reset_light_para(); reset_light_para();
break; break;
@ -442,7 +465,7 @@ void user_genie_event_handle(genie_event_t event, void *p_arg)
g_indication_flag |= INDICATION_FLAG_CTL; g_indication_flag |= INDICATION_FLAG_CTL;
#endif #endif
ESP_LOGI(TAG, "light_driver_breath_stop %s", __FUNCTION__); ESP_LOGI(TAG, "light_driver_breath_stop %s", __FUNCTION__);
light_driver_breath_stop(); lightbulb_basic_effect_stop();
// update led status // update led status
genie_event(GENIE_EVT_SDK_ANALYZE_MSG, &g_elem_state[0]); genie_event(GENIE_EVT_SDK_ANALYZE_MSG, &g_elem_state[0]);
break; break;
@ -1290,7 +1313,18 @@ static esp_err_t ble_mesh_init(void)
ESP_LOGW(TAG, "node already provisioned"); ESP_LOGW(TAG, "node already provisioned");
} else { } else {
ESP_LOGW(TAG, "node not provisioned"); ESP_LOGW(TAG, "node not provisioned");
light_driver_breath_start(0, 255, 0); /**< green blink */ lightbulb_set_switch(false);
lightbulb_effect_config_t effect3 = {
.red = 0,
.green = 255,
.blue = 0,
.max_brightness = 100,
.min_brightness = 0,
.effect_cycle_ms = CONFIG_LIGHT_BLINK_PERIOD_MS,
.effect_type = EFFECT_BLINK,
.mode = WORK_COLOR,
};
lightbulb_basic_effect_start(&effect3); /**< green blink */
} }
return err; return err;

View File

@ -13,11 +13,15 @@
#include "esp_log.h" #include "esp_log.h"
#include "iot_button.h" #include "iot_button.h"
#include "light_driver.h" #include "lightbulb.h"
#include "genie_event.h" #include "genie_event.h"
#if CONFIG_IDF_TARGET_ESP32C3
#define BUTTON_ON_OFF 9 /* on/off button */
#else
#define BUTTON_ON_OFF 0 /* on/off button */ #define BUTTON_ON_OFF 0 /* on/off button */
#endif
#define BUTTON_ACTIVE_LEVEL 0 #define BUTTON_ACTIVE_LEVEL 0
static const char *TAG = "board"; static const char *TAG = "board";
@ -38,22 +42,37 @@ static void board_led_init(void)
* If the module has SPI flash, GPIOs 6-11 are connected to the modules integrated SPI flash and PSRAM. * If the module has SPI flash, GPIOs 6-11 are connected to the modules integrated SPI flash and PSRAM.
* If the module has PSRAM, GPIOs 16 and 17 are connected to the modules integrated PSRAM. * If the module has PSRAM, GPIOs 16 and 17 are connected to the modules integrated PSRAM.
*/ */
light_driver_config_t driver_config = { lightbulb_config_t config = {
.gpio_red = CONFIG_LIGHT_GPIO_RED, .type = DRIVER_ESP_PWM,
.gpio_green = CONFIG_LIGHT_GPIO_GREEN, .driver_conf.pwm.freq_hz = 4000,
.gpio_blue = CONFIG_LIGHT_GPIO_BLUE, .capability.enable_fades = true,
.gpio_cold = CONFIG_LIGHT_GPIO_COLD, .capability.fades_ms = CONFIG_LIGHT_FADE_PERIOD_MS,
.gpio_warm = CONFIG_LIGHT_GPIO_WARM, .capability.enable_lowpower = false,
.fade_period_ms = CONFIG_LIGHT_FADE_PERIOD_MS, .capability.enable_mix_cct = false,
.blink_period_ms = CONFIG_LIGHT_BLINK_PERIOD_MS, .capability.enable_status_storage = false,
.capability.mode_mask = COLOR_MODE,
.capability.storage_cb = NULL,
.capability.sync_change_brightness_value = true,
.io_conf.pwm_io.red = CONFIG_LIGHT_GPIO_RED,
.io_conf.pwm_io.green = CONFIG_LIGHT_GPIO_GREEN,
.io_conf.pwm_io.blue = CONFIG_LIGHT_GPIO_BLUE,
.io_conf.pwm_io.cold_cct = CONFIG_LIGHT_GPIO_COLD,
.io_conf.pwm_io.warm_brightness = CONFIG_LIGHT_GPIO_WARM,
.external_limit = NULL,
.gamma_conf = NULL,
.init_status.mode = WORK_COLOR,
.init_status.on = true,
.init_status.hue = 0,
.init_status.saturation = 100,
.init_status.value = 100,
}; };
/** /**
* @brief Light driver initialization * @brief Light driver initialization
*/ */
ESP_ERROR_CHECK(light_driver_init(&driver_config)); ESP_ERROR_CHECK(lightbulb_init(&config));
light_driver_set_mode(MODE_HSL); vTaskDelay(pdMS_TO_TICKS(1000) * 1);
// light_driver_set_switch(true); lightbulb_set_switch(true);
button_handle_t dev_on_off_btn = iot_button_create(BUTTON_ON_OFF, BUTTON_ACTIVE_LEVEL); button_handle_t dev_on_off_btn = iot_button_create(BUTTON_ON_OFF, BUTTON_ACTIVE_LEVEL);
iot_button_set_evt_cb(dev_on_off_btn, BUTTON_CB_TAP, button_tap_cb, &dev_on_btn_num); iot_button_set_evt_cb(dev_on_off_btn, BUTTON_CB_TAP, button_tap_cb, &dev_on_btn_num);
@ -64,6 +83,62 @@ void board_init(void)
board_led_init(); board_led_init();
} }
static esp_err_t board_led_hsl2rgb(uint16_t hue, uint8_t saturation, uint8_t lightness,
uint8_t *red, uint8_t *green, uint8_t *blue)
{
uint16_t hi = (hue / 60) % 6;
uint16_t C = (100 - abs(2 * lightness - 100)) * saturation / 100;
uint16_t M = 100 * (lightness - 0.5 * C) / 100;
uint16_t X = C * (100 - abs((hue * 100 / 60 ) % 200 - 100)) / 100;
switch (hi) {
case 0: /* hue 0~60 */
*red = C + M;
*green = X + M;
*blue = M;
break;
case 1: /* hue 60~120 */
*red = X + M;
*green = C + M;
*blue = M;
break;
case 2: /* hue 120~180 */
*red = M;
*green = C + M;
*blue = X + M;
break;
case 3: /* hue 180~240 */
*red = M;
*green = X + M;
*blue = C + M;
break;
case 4: /* hue 240~300 */
*red = X + M;
*green = M;
*blue = C + M;
break;
case 5: /* hue 300~360 */
*red = C + M;
*green = M;
*blue = X + M;
break;
default:
return ESP_FAIL;
}
*red = *red * 255 / 100;
*green = *green * 255 / 100;
*blue = *blue * 255 / 100;
return ESP_OK;
}
/** /**
* hsl * hsl
*/ */
@ -86,8 +161,14 @@ void board_led_hsl(uint8_t elem_index, uint16_t hue, uint16_t saturation, uint16
uint8_t actual_saturation = (float)last_saturation / (UINT16_MAX / 100.0); uint8_t actual_saturation = (float)last_saturation / (UINT16_MAX / 100.0);
uint8_t actual_lightness = (float)last_lightness / (UINT16_MAX / 100.0); uint8_t actual_lightness = (float)last_lightness / (UINT16_MAX / 100.0);
uint8_t r, g, b;
uint16_t h;
uint8_t s, v;
ESP_LOGD(TAG, "hsl: %d, %d, %d operation", actual_hue, actual_saturation, actual_lightness); ESP_LOGD(TAG, "hsl: %d, %d, %d operation", actual_hue, actual_saturation, actual_lightness);
light_driver_set_hsl(actual_hue, actual_saturation, actual_lightness); board_led_hsl2rgb(actual_hue, actual_saturation, actual_lightness, &r, &g, &b);
lightbulb_rgb2hsv(r, g, b, &h, &s, &v);
lightbulb_set_hsv(h, s, v);
} }
} }
@ -105,7 +186,7 @@ void board_led_temperature(uint8_t elem_index, uint16_t temperature)
uint16_t actual_temperature = (float)last_temperature / (UINT16_MAX / 100.0); uint16_t actual_temperature = (float)last_temperature / (UINT16_MAX / 100.0);
ESP_LOGD(TAG, "temperature %d %%%d operation", last_temperature, actual_temperature); ESP_LOGD(TAG, "temperature %d %%%d operation", last_temperature, actual_temperature);
light_driver_set_color_temperature(actual_temperature); lightbulb_set_cct(actual_temperature);
} }
} }
@ -123,7 +204,7 @@ void board_led_lightness(uint8_t elem_index, uint16_t actual)
uint16_t actual_lightness = (float)last_acual / (UINT16_MAX / 100.0); uint16_t actual_lightness = (float)last_acual / (UINT16_MAX / 100.0);
ESP_LOGD(TAG, "lightness %d %%%d operation", last_acual, actual_lightness); ESP_LOGD(TAG, "lightness %d %%%d operation", last_acual, actual_lightness);
light_driver_set_lightness(actual_lightness); lightbulb_set_brightness(actual_lightness);
} }
} }
@ -139,10 +220,10 @@ void board_led_switch(uint8_t elem_index, uint8_t onoff)
last_onoff = onoff; last_onoff = onoff;
if (last_onoff) { if (last_onoff) {
ESP_LOGD(TAG, "onoff %d operation", last_onoff); ESP_LOGD(TAG, "onoff %d operation", last_onoff);
light_driver_set_switch(true); lightbulb_set_switch(true);
} else { } else {
ESP_LOGD(TAG, "onoff %d operation", last_onoff); ESP_LOGD(TAG, "onoff %d operation", last_onoff);
light_driver_set_switch(false); lightbulb_set_switch(false);
} }
} }
} }

View File

@ -14,7 +14,7 @@ extern "C" {
#endif /**< __cplusplus */ #endif /**< __cplusplus */
#include "driver/gpio.h" #include "driver/gpio.h"
#include "light_driver.h" #include "lightbulb.h"
#define LED_ON 1 #define LED_ON 1
#define LED_OFF 0 #define LED_OFF 0

View File

@ -35,3 +35,9 @@ CONFIG_BLE_MESH_MODEL_KEY_COUNT=5
CONFIG_BLE_MESH_MODEL_GROUP_COUNT=5 CONFIG_BLE_MESH_MODEL_GROUP_COUNT=5
CONFIG_BLE_MESH_MSG_CACHE_SIZE=20 CONFIG_BLE_MESH_MSG_CACHE_SIZE=20
CONFIG_BLE_MESH_ADV_BUF_COUNT=256 CONFIG_BLE_MESH_ADV_BUF_COUNT=256
#
# light driver config
#
CONFIG_PWM_ENABLE_HW_FADE=n
# end of light driver config

View File

@ -1,15 +1,3 @@
#
# Partition Table
#
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
#
# Serial flasher config
#
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
# Override some defaults so BT stack is enabled # Override some defaults so BT stack is enabled
# by default in this example # by default in this example
CONFIG_BT_ENABLED=y CONFIG_BT_ENABLED=y
@ -18,20 +6,8 @@ CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN=y
CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y
CONFIG_BT_BTU_TASK_STACK_SIZE=4512 CONFIG_BT_BTU_TASK_STACK_SIZE=4512
CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y
CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n
# Override some defaults of ESP BLE Mesh CONFIG_BT_LE_50_FEATURE_SUPPORT=n
CONFIG_BLE_MESH=y
CONFIG_BLE_MESH_NODE=y
CONFIG_BLE_MESH_PB_GATT=y
CONFIG_BLE_MESH_TX_SEG_MSG_COUNT=10
CONFIG_BLE_MESH_RX_SEG_MSG_COUNT=10
CONFIG_BLE_MESH_SETTINGS=y
CONFIG_BLE_MESH_SUBNET_COUNT=5
CONFIG_BLE_MESH_APP_KEY_COUNT=5
CONFIG_BLE_MESH_MODEL_KEY_COUNT=5
CONFIG_BLE_MESH_MODEL_GROUP_COUNT=5
CONFIG_BLE_MESH_MSG_CACHE_SIZE=20
CONFIG_BLE_MESH_ADV_BUF_COUNT=256
# #
# light driver config # light driver config

View File

@ -0,0 +1,19 @@
# Override some defaults so BT stack is enabled
# by default in this example
CONFIG_BT_ENABLED=y
CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y
CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y
CONFIG_BT_BTU_TASK_STACK_SIZE=4512
CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y
CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n
CONFIG_BT_LE_50_FEATURE_SUPPORT=n
#
# light driver config
#
CONFIG_LIGHT_GPIO_RED=4
CONFIG_LIGHT_GPIO_GREEN=5
CONFIG_LIGHT_GPIO_BLUE=6
CONFIG_LIGHT_GPIO_COLD=7
CONFIG_LIGHT_GPIO_WARM=10
# end of light driver config

View File

@ -0,0 +1,19 @@
# Override some defaults so BT stack is enabled
# by default in this example
CONFIG_BT_ENABLED=y
CONFIG_BT_LE_SCAN_DUPL_TYPE_DATA_DEVICE=y
CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y
CONFIG_BT_BTU_TASK_STACK_SIZE=4512
CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y
CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n
CONFIG_BT_LE_50_FEATURE_SUPPORT=n
#
# light driver config
#
CONFIG_LIGHT_GPIO_RED=4
CONFIG_LIGHT_GPIO_GREEN=5
CONFIG_LIGHT_GPIO_BLUE=11
CONFIG_LIGHT_GPIO_COLD=12
CONFIG_LIGHT_GPIO_WARM=10
# end of light driver config

View File

@ -0,0 +1,21 @@
# Override some defaults so BT stack is enabled
# by default in this example
CONFIG_BT_ENABLED=y
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n
CONFIG_BTDM_CTRL_MODE_BTDM=n
CONFIG_CTRL_BTDM_MODEM_SLEEP=n
CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE=y
CONFIG_BTDM_BLE_MESH_SCAN_DUPL_EN=y
CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL=y
CONFIG_BT_BTU_TASK_STACK_SIZE=4512
#
# light driver config
#
CONFIG_LIGHT_GPIO_RED=14
CONFIG_LIGHT_GPIO_GREEN=13
CONFIG_LIGHT_GPIO_BLUE=12
CONFIG_LIGHT_GPIO_COLD=11
CONFIG_LIGHT_GPIO_WARM=10
# end of light driver config

View File

@ -1,12 +1,5 @@
set(COMPONENT_SRCS
"light_driver.c"
"iot_led.c"
"led_strip_encoder.c")
set(COMPONENT_ADD_INCLUDEDIRS ". include")
# requirements can't depend on config # requirements can't depend on config
set(COMPONENT_REQUIRES example_nvs driver) set(COMPONENT_REQUIRES example_nvs driver lightbulb_driver)
register_component() register_component()

View File

@ -1,22 +1,3 @@
# Component: Light # Source
* This component defines a light as a well encapsulated object. The `light_driver` component is taken from https://github.com/espressif/esp-iot-solution/tree/master/components/led/lightbulb_driver via idf_component.yml
* A light device is defined by:
* ledc timer which is used to control the pwm channels of light
* mode of the ledc timer
* frequency of the ledc timer
* pwm channel number of the light
* bit number of the ledc timer
* A light device can provide:
* iot_light_channel_regist function to add channel to corresponding channel id
* iot_light_duty_write function to set the duty of corresponding channel and it support setting duty directly or gradually
* iot_light_breath_write function to set the corresponding channel to breath mode and breath period can be set
* iot_light_blink_starte and iot_light_blink_stop function to make some of channels to blink in appointed period. Note that if any channel works in blink mode, all the other channels would be turned off.
* To use the light device, you need to:
* create a light object returned by iot_light_create()
* regist the light channels according the channel number by iot_light_channel_regist()
* To free the object, you can call iot_light_delete to delete the button object and free the memory.
### NOTE:
> If any channel(s) work(s) in blink mode, all the other channels would be turned off. iot_light_blink_stop() must be called before setting any channel to other mode(write duty or breath).

View File

@ -0,0 +1,3 @@
## IDF Component Manager Manifest File
dependencies:
espressif/lightbulb_driver: "==0.5.5"

View File

@ -1,167 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __IOT_LED_H__
#define __IOT_LED_H__
#include "driver/ledc.h"
#ifdef __cplusplus
extern "C" {
#endif
#define GAMMA_CORRECTION 0.8 /**< Gamma curve parameter */
#define GAMMA_TABLE_SIZE 256 /**< Gamma table size, used for led fade*/
#define DUTY_SET_CYCLE (20) /**< Set duty cycle */
/**
* Macro which can be used to check the error code,
* and terminate the program in case the code is not ESP_OK.
* Prints the error code, error location, and the failed statement to serial output.
*
* Disabled if assertions are disabled.
*/
#define LIGHT_ERROR_CHECK(con, err, format, ...) do { \
if (con) { \
if(*format != '\0') \
ESP_LOGW(TAG, "<%s> " format, esp_err_to_name(err), ##__VA_ARGS__); \
return err; \
} \
} while(0)
#define LIGHT_PARAM_CHECK(con) do { \
if (!(con)) { \
ESP_LOGE(TAG, "<ESP_ERR_INVALID_ARG> !(%s)", #con); \
return ESP_ERR_INVALID_ARG; \
} \
} while(0)
/**
* @brief Initialize and set the ledc timer for the iot led
*
* @param timer_num The timer index of ledc timer group used for iot led
* This parameter can be one of LEDC_TIMER_x where x can be (0 .. 3)
*
* @param speed_mode speed mode of ledc timer
* This parameter can be one of LEDC_x_SPEED_MODE where x can be (LOW, HIGH)
*
* @param freq_hz frequency of ledc timer
* This parameter must be less than 5000
*
* @return
* - ESP_OK if sucess
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL Can not find a proper pre-divider number base on the given frequency
* and the current duty_resolution.
*/
esp_err_t iot_led_init(ledc_timer_t timer_num, ledc_mode_t speed_mode, uint32_t freq_hz);
/**
* @brief DeInitializes the iot led and free resource
*
* @return
* - ESP_OK if sucess
*/
esp_err_t iot_led_deinit(void);
/**
* @brief Set the ledc channel used by iot led and associate the gpio port used
* for output
*
* @param channel The ledc channel
* This parameter can be LEDC_CHANNEL_x where x can be (0 .. 15)
* @param gpio_num the ledc output gpio_num
* This parameter can be GPIO_NUM_x where x can be (0, 33)
*
* @note If the operation of esp32 depends on SPI FLASH or PSRAM, then these related
* pins should not be set to output.
*
* @return
* - ESP_OK if sucess
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t iot_led_regist_channel(ledc_channel_t channel, gpio_num_t gpio_num);
/**
* @brief Returns the channel value
* @note before calling this function, you need to call iot_led_regist_channel() to
* set the channel
*
* @param channel The ledc channel
* This parameter can be LEDC_CHANNEL_x where x can be (0 .. 15)
* @param dst The address where the channel value is stored
* @return
* - ESP_OK if sucess
* - ESP_ERR_INVALID_ARG if dst is NULL
*/
esp_err_t iot_led_get_channel(ledc_channel_t channel, uint8_t *dst);
/**
* @brief Set the fade state for the specified channel
* @note before calling this function, you need to call iot_led_regist_channel() to
* set the channel
*
* @param channel The ledc channel
* This parameter can be LEDC_CHANNEL_x where x can be (0 .. 15)
* @param value The target output brightness of iot led
* This parameter can be (0 .. 255)
* @param fade_ms The time from the current value to the target value
* @return
* - ESP_OK if sucess
*/
esp_err_t iot_led_set_channel(ledc_channel_t channel, uint8_t value, uint32_t fade_ms);
/**
* @brief Set the blink state or loop fade for the specified channel
* @note before calling this function, you need to call iot_led_regist_channel() to
* set the channel
*
* @param channel The ledc channel
* This parameter can be LEDC_CHANNEL_x where x can be (0 .. 15)
* @param value The output brightness of iot led
* This parameter can be (0 .. 255)
* @param period_ms Blink cycle
* @param fade_flag select loop fade or blink
* 1 for loop fade
* 0 for blink
* @return
* - ESP_OK if sucess
*/
esp_err_t iot_led_start_blink(ledc_channel_t channel, uint8_t value, uint32_t period_ms, bool fade_flag);
/**
* @brief Stop the blink state or loop fade for the specified channel
*
* @param channel The ledc channel
* This parameter can be LEDC_CHANNEL_x where x can be (0 .. 15)
* @return
* - ESP_OK if sucess
*/
esp_err_t iot_led_stop_blink(ledc_channel_t channel);
/**
* @brief Set the specified gamma_table to control the fade effect, usually
* no need to set
*
* @param gamma_table[GAMMA_TABLE_SIZE] Expected gamma table value
*
* @note Gamma_table is the dimming curve used by the iot_led driver.
* The element type is uint16_t. Each element is treated as a binary
* fixed-point number. The decimal point is before the eighth bit
* and after the ninth bit, so the range of expressions can be
* 0x00.00 ~ 0xff.ff.
* @note default gamma_table is created in iot_led_init()
*
* @return
* - ESP_OK if sucess
*/
esp_err_t iot_led_set_gamma_table(const uint16_t gamma_table[GAMMA_TABLE_SIZE]);
#ifdef __cplusplus
}
#endif
#endif /**< __IOT_LED_H__ */

View File

@ -1,142 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __IOT_LIGHT_H__
#define __IOT_LIGHT_H__
#include "driver/ledc.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void *light_handle_t;
#define DUTY_SET_CYCLE (20) /**< Set duty cycle */
#define DUTY_SET_GAMMA (0.6) /**< Set the Gamma value for the fade curve, default value is 0.6 */
#define LIGHT_MAX_CHANNEL_NUM (5)
/**
* @brief light initialize
*
* @param timer the LEDC timer used by light
* @param speed_mode speed mode of LEDC timer
* @param freq_hz frequency of LEDC timer
* @param channel_num decide how many channels the light contains
* @param timer_bit LEDC PWM duty resolution
*
* @return the handle of light
*/
light_handle_t iot_light_create(ledc_timer_t timer, ledc_mode_t speed_mode, uint32_t freq_hz, uint8_t channel_num, ledc_timer_bit_t timer_bit);
/**
* @brief add an output channel to light
*
* @param light_handle light handle
* @param channel_idx the id of channel (0 ~ channel_num-1)
* @param io_num the IO number use to output LEDC PWM
* @param channel the ledc channel you want to use
*
* @return
* - ESP_OK: succeed
* - others: fail
*/
esp_err_t iot_light_channel_regist(light_handle_t light_handle, uint8_t channel_idx, gpio_num_t io_num, ledc_channel_t channel);
/**
* @brief free the memory of light
*
* @param light_handle light handle
*
* @return
* - ESP_OK: succeed
* - others: fail
*/
esp_err_t iot_light_delete(light_handle_t light_handle);
/**
* @brief get channel duty
*
* @param light_handle light handle
* @param channel_id the id of channel (0 ~ channel_num-1)
*
* @return
* - LEDC_ERR_DUTY if parameter error
* - Others Current LEDC duty
*/
uint32_t iot_light_duty_get(light_handle_t light_handle, uint8_t channel_id);
/**
* @brief set light fade with time. if set fade_period_ms as 0, set the duty directly.
*
* @param light_handle light handle
* @param channel_id the id of channel (0 ~ channel_num-1)
* @param duty target duty
* @param fade_period_ms fade time (uint: ms)
*
* @return
* - ESP_OK: succeed
* - others: fail
*/
esp_err_t iot_light_fade_with_time(light_handle_t light_handle, uint8_t channel_id, uint32_t duty, uint32_t fade_period_ms);
/**
* @brief set breath config of a light channel, call `iot_light_operate_start` to start breath operation
*
* @param light_handle light handle
* @param channel_id the id of channel (0 ~ channel_num-1)
* @param duty the maximum duty when breath
* @param breath_period_ms breath period (uint: ms)
*
* @return
* - ESP_OK: succeed
* - others: fail
*/
esp_err_t iot_light_breath_config(light_handle_t light_handle, uint8_t channel_id, uint32_t duty, uint32_t breath_period_ms);
/**
* @brief set blink config of a light channel, call `iot_light_operate_start` to start blink operation
*
* @param light_handle light handle
* @param channel_id the id of channel (0 ~ channel_num-1)
* @param blink_period_ms blink period (uint: ms)
*
* @return
* - ESP_OK: succeed
* - others: fail
*/
esp_err_t iot_light_blink_config(light_handle_t light_handle, uint8_t channel_id, uint32_t blink_period_ms);
/**
* @brief start breath or blink operation, user need to set breath or blink config before call this API
*
* @param light_handle light handle
* @param channel_id the id of channel (0 ~ channel_num-1)
*
* @return
* - ESP_OK: succeed
* - others: fail
*/
esp_err_t iot_light_operate_start(light_handle_t light_handle, uint8_t channel_id);
/**
* @brief stop breath or blink operation
*
* @param light_handle light handle
* @param channel_id the id of channel (0 ~ channel_num-1)
*
* @return
* - ESP_OK: succeed
* - others: fail
*/
esp_err_t iot_light_operate_stop(light_handle_t light_handle, uint8_t channel_id);
#ifdef __cplusplus
}
#endif
#endif /**< __IOT_LIGHT_H__ */

View File

@ -1,41 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "driver/rmt_encoder.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Type of led strip encoder configuration
*/
typedef struct {
uint32_t resolution; /*!< Encoder resolution, in Hz */
} led_strip_encoder_config_t;
/**
* @brief Create RMT encoder for encoding LED strip pixels into RMT symbols
*
* @param[in] config Encoder configuration
* @param[out] ret_encoder Returned encoder handle
* @return
* - ESP_ERR_INVALID_ARG for any invalid arguments
* - ESP_ERR_NO_MEM out of memory when creating led strip encoder
* - ESP_OK if creating encoder successfully
*/
esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder);
void rmt_encoder_init(void);
void rmt_led_set(uint8_t red, uint8_t green, uint8_t blue);
#ifdef __cplusplus
}
#endif

View File

@ -1,158 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __LIGHT_DRIVER_H__
#define __LIGHT_DRIVER_H__
#include "iot_led.h"
#ifdef __cplusplus
extern "C" {
#endif
#define LIGHT_STATUS_STORE_KEY "light_status"
/**
* @brief The mode of the five-color light
*/
typedef enum light_mode {
MODE_NONE = 0,
MODE_RGB = 1,
MODE_HSV = 2,
MODE_CTB = 3,
MODE_ON = 4,
MODE_OFF = 5,
MODE_HUE_INCREASE = 4,
MODE_HUE_DECREASE = 5,
MODE_WARM_INCREASE = 6,
MODE_WARM_DECREASE = 7,
MODE_BRIGHTNESS_INCREASE = 8,
MODE_BRIGHTNESS_DECREASE = 9,
MODE_HSL = 10,
} light_mode_t;
/**
* @brief Light driven configuration
*/
typedef struct {
gpio_num_t gpio_red; /**< Red corresponds to GPIO */
gpio_num_t gpio_green; /**< Green corresponds to GPIO */
gpio_num_t gpio_blue; /**< Blue corresponds to GPIO */
gpio_num_t gpio_cold; /**< Cool corresponds to GPIO */
gpio_num_t gpio_warm; /**< Warm corresponds to GPIO */
uint32_t fade_period_ms; /**< The time from the current color to the next color */
uint32_t blink_period_ms; /**< Period of flashing lights */
} light_driver_config_t;
/**
* @brief Light initialize
*
* @param config [description]
*
* @return
* - ESP_OK
* - ESP_ERR_INVALID_ARG
*/
esp_err_t light_driver_init(light_driver_config_t *config);
/**
* @brief Light deinitialize
*
* @return
* - ESP_OK
* - ESP_ERR_INVALID_ARG
*/
esp_err_t light_driver_deinit(void);
/**
* @brief Set the fade time of the light
*
* @param fade_period_ms The time from the current color to the next color
* @param blink_period_ms Light flashing frequency
*
* @return
* - ESP_OK
* - ESP_FAIL
*/
esp_err_t light_driver_config(uint32_t fade_period_ms, uint32_t blink_period_ms);
/**@{*/
/**
* @brief Set the status of the light
*
*
* @return
* - ESP_OK
* - ESP_ERR_INVALID_ARG
*/
esp_err_t light_driver_set_hue(uint16_t hue);
esp_err_t light_driver_set_saturation(uint8_t saturation);
esp_err_t light_driver_set_value(uint8_t value);
esp_err_t light_driver_set_color_temperature(uint8_t color_temperature);
esp_err_t light_driver_set_brightness(uint8_t brightness);
esp_err_t light_driver_set_hsv(uint16_t hue, uint8_t saturation, uint8_t value);
esp_err_t light_driver_set_hsl(uint16_t hue, uint8_t saturation, uint8_t lightness);
esp_err_t light_driver_set_lightness(uint8_t lightness);
esp_err_t light_driver_set_ctb(uint8_t color_temperature, uint8_t brightness);
esp_err_t light_driver_set_switch(bool status);
esp_err_t light_driver_set_mode(light_mode_t mode);
/**@}*/
/**@{*/
/**
* @brief Set the status of the light
*/
uint16_t light_driver_get_hue(void);
uint8_t light_driver_get_saturation(void);
uint8_t light_driver_get_value(void);
esp_err_t light_driver_get_hsv(uint16_t *hue, uint8_t *saturation, uint8_t *value);
uint8_t light_driver_get_lightness(void);
esp_err_t light_driver_get_hsl(uint16_t *hue, uint8_t *saturation, uint8_t *lightness);
uint8_t light_driver_get_color_temperature(void);
uint8_t light_driver_get_brightness(void);
esp_err_t light_driver_get_ctb(uint8_t *color_temperature, uint8_t *brightness);
bool light_driver_get_switch(void);
uint8_t light_driver_get_mode(void);
/**@}*/
/**@{*/
/**
* @brief Used to indicate the operating mode, such as configuring the network mode, upgrading mode
*
* @note The state of the light is not saved in nvs
*
* @return
* - ESP_OK
* - ESP_ERR_INVALID_ARG
*/
esp_err_t light_driver_set_rgb(uint8_t red, uint8_t green, uint8_t blue);
esp_err_t light_driver_breath_start(uint8_t red, uint8_t green, uint8_t blue);
esp_err_t light_driver_breath_stop(void);
esp_err_t light_driver_blink_start(uint8_t red, uint8_t green, uint8_t blue);
esp_err_t light_driver_blink_stop(void);
/**@}*/
/**@{*/
/**
* @brief Color gradient
*
* @return
* - ESP_OK
* - ESP_ERR_INVALID_ARG
*/
esp_err_t light_driver_fade_brightness(uint8_t brightness);
esp_err_t light_driver_fade_hue(uint16_t hue);
esp_err_t light_driver_fade_warm(uint8_t color_temperature);
esp_err_t light_driver_fade_stop(void);
/**@}*/
#ifdef __cplusplus
}
#endif
#endif/**< __LIGHT_DRIVER_H__ */

View File

@ -1,481 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include "soc/ledc_reg.h"
#include "soc/timer_group_struct.h"
#include "soc/ledc_struct.h"
#include "driver/gptimer.h"
#include "driver/ledc.h"
#include "esp_attr.h"
#include "iot_led.h"
#include "esp_log.h"
#define LEDC_FADE_MARGIN (10)
#define LEDC_VALUE_TO_DUTY(value) (value * ((1 << LEDC_TIMER_13_BIT) - 1) / UINT16_MAX)
#define LEDC_DUTY_TO_VALUE(value) (value * UINT16_MAX / ((1 << LEDC_TIMER_13_BIT) - 1) )
#define LEDC_FIXED_Q (8)
#define FLOATINT_2_FIXED(X, Q) ((int)((X)*(0x1U << Q)))
#define FIXED_2_FLOATING(X, Q) ((int)((X)/(0x1U << Q)))
#define GET_FIXED_INTEGER_PART(X, Q) (X >> Q)
#define GET_FIXED_DECIMAL_PART(X, Q) (X & ((0x1U << Q) - 1))
#define GPTIMER_RESOLUTION_HZ 1000000 // 1MHz, 1 tick=1us
#if (CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3)
typedef struct {
int cur;
int final;
int step;
int cycle;
size_t num;
} ledc_fade_data_t;
typedef struct {
ledc_fade_data_t fade_data[LEDC_CHANNEL_MAX];
ledc_mode_t speed_mode;
ledc_timer_t timer_num;
gptimer_handle_t gptimer;
} iot_light_t;
static const char *TAG = "iot_light";
static DRAM_ATTR iot_light_t *g_light_config = NULL;
static DRAM_ATTR uint16_t *g_gamma_table = NULL;
static DRAM_ATTR bool g_hw_timer_started = false;
static bool fade_timercb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx);
static void iot_timer_start(gptimer_handle_t gptimer)
{
gptimer_alarm_config_t alarm_config = {
.reload_count = 0,
.alarm_count = DUTY_SET_CYCLE / 1000 * GPTIMER_RESOLUTION_HZ,
.flags.auto_reload_on_alarm = true,
};
gptimer_set_alarm_action(gptimer, &alarm_config);
gptimer_start(gptimer);
g_hw_timer_started = true;
}
static IRAM_ATTR void iot_timer_stop(gptimer_handle_t gptimer)
{
gptimer_stop(gptimer);
g_hw_timer_started = false;
}
static IRAM_ATTR esp_err_t iot_ledc_duty_config(ledc_mode_t speed_mode, ledc_channel_t channel, int hpoint_val, int duty_val,
uint32_t duty_direction, uint32_t duty_num, uint32_t duty_cycle, uint32_t duty_scale)
{
if (hpoint_val >= 0) {
#if CONFIG_IDF_TARGET_ESP32C3
LEDC.channel_group[speed_mode].channel[channel].hpoint.hpoint = hpoint_val & LEDC_HPOINT_LSCH1_V;
#elif CONFIG_IDF_TARGET_ESP32
LEDC.channel_group[speed_mode].channel[channel].hpoint.hpoint = hpoint_val & LEDC_HPOINT_HSCH1_V;
#endif
}
if (duty_val >= 0) {
LEDC.channel_group[speed_mode].channel[channel].duty.duty = duty_val;
}
#if CONFIG_IDF_TARGET_ESP32C3
LEDC.channel_group[speed_mode].channel[channel].conf1.val = ((duty_direction & LEDC_DUTY_INC_LSCH0_V) << LEDC_DUTY_INC_LSCH0_S) |
((duty_num & LEDC_DUTY_NUM_LSCH0_V) << LEDC_DUTY_NUM_LSCH0_S) |
((duty_cycle & LEDC_DUTY_CYCLE_LSCH0_V) << LEDC_DUTY_CYCLE_LSCH0_S) |
((duty_scale & LEDC_DUTY_SCALE_LSCH0_V) << LEDC_DUTY_SCALE_LSCH0_S);
#elif CONFIG_IDF_TARGET_ESP32
LEDC.channel_group[speed_mode].channel[channel].conf1.val = ((duty_direction & LEDC_DUTY_INC_HSCH0_V) << LEDC_DUTY_INC_HSCH0_S) |
((duty_num & LEDC_DUTY_NUM_HSCH0_V) << LEDC_DUTY_NUM_HSCH0_S) |
((duty_cycle & LEDC_DUTY_CYCLE_HSCH0_V) << LEDC_DUTY_CYCLE_HSCH0_S) |
((duty_scale & LEDC_DUTY_SCALE_HSCH0_V) << LEDC_DUTY_SCALE_HSCH0_S);
#endif
LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 1;
LEDC.channel_group[speed_mode].channel[channel].conf1.duty_start = 1;
if (speed_mode == LEDC_LOW_SPEED_MODE) {
LEDC.channel_group[speed_mode].channel[channel].conf0.low_speed_update = 1;
}
return ESP_OK;
}
static IRAM_ATTR esp_err_t _iot_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int scale, int cycle_num)
{
uint32_t duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> 4;
int step_num = 0;
int dir = LEDC_DUTY_DIR_DECREASE;
if (scale > 0) {
if (duty_cur > target_duty) {
step_num = (duty_cur - target_duty) / scale;
step_num = step_num > 1023 ? 1023 : step_num;
scale = (step_num == 1023) ? (duty_cur - target_duty) / step_num : scale;
} else {
dir = LEDC_DUTY_DIR_INCREASE;
step_num = (target_duty - duty_cur) / scale;
step_num = step_num > 1023 ? 1023 : step_num;
scale = (step_num == 1023) ? (target_duty - duty_cur) / step_num : scale;
}
}
if (scale > 0 && step_num > 0) {
iot_ledc_duty_config(speed_mode, channel, -1, duty_cur << 4, dir, step_num, cycle_num, scale);
} else {
iot_ledc_duty_config(speed_mode, channel, -1, target_duty << 4, dir, 0, 1, 0);
}
return ESP_OK;
}
static IRAM_ATTR esp_err_t _iot_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms)
{
uint32_t freq = 0;
uint32_t duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> 4;
uint32_t duty_delta = target_duty > duty_cur ? target_duty - duty_cur : duty_cur - target_duty;
uint32_t timer_source_clk = LEDC.timer_group[speed_mode].timer[g_light_config->timer_num].conf.tick_sel;
uint32_t duty_resolution = LEDC.timer_group[speed_mode].timer[g_light_config->timer_num].conf.duty_resolution;
uint32_t clock_divider = LEDC.timer_group[speed_mode].timer[g_light_config->timer_num].conf.clock_divider;
uint32_t precision = (0x1U << duty_resolution);
if (timer_source_clk == LEDC_APB_CLK) {
freq = ((uint64_t)APB_CLK_FREQ << 8) / precision / clock_divider;
} else {
freq = ((uint64_t)REF_CLK_FREQ << 8) / precision / clock_divider;
}
if (duty_delta == 0) {
return _iot_set_fade_with_step(speed_mode, channel, target_duty, 0, 0);
}
int total_cycles = max_fade_time_ms * freq / 1000;
if (total_cycles == 0) {
return _iot_set_fade_with_step(speed_mode, channel, target_duty, 0, 0);
}
int scale, cycle_num;
if (total_cycles > duty_delta) {
scale = 1;
cycle_num = total_cycles / duty_delta;
#if CONFIG_IDF_TARGET_ESP32C3
if (cycle_num > LEDC_DUTY_NUM_LSCH0_V) {
cycle_num = LEDC_DUTY_NUM_LSCH0_V;
}
#elif CONFIG_IDF_TARGET_ESP32
if (cycle_num > LEDC_DUTY_NUM_HSCH0_V) {
cycle_num = LEDC_DUTY_NUM_HSCH0_V;
}
#endif
} else {
cycle_num = 1;
scale = duty_delta / total_cycles;
#if CONFIG_IDF_TARGET_ESP32C3
if (scale > LEDC_DUTY_SCALE_LSCH0_V) {
scale = LEDC_DUTY_SCALE_LSCH0_V;
}
#elif CONFIG_IDF_TARGET_ESP32
if (scale > LEDC_DUTY_SCALE_HSCH0_V) {
scale = LEDC_DUTY_SCALE_HSCH0_V;
}
#endif
}
return _iot_set_fade_with_step(speed_mode, channel, target_duty, scale, cycle_num);
}
static IRAM_ATTR esp_err_t _iot_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel)
{
LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 1;
LEDC.channel_group[speed_mode].channel[channel].conf1.duty_start = 1;
if (speed_mode == LEDC_LOW_SPEED_MODE) {
LEDC.channel_group[speed_mode].channel[channel].conf0.low_speed_update = 1;
}
return ESP_OK;
}
static IRAM_ATTR esp_err_t iot_ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty)
{
return iot_ledc_duty_config(speed_mode,
channel, // uint32_t chan_num,
-1,
duty << 4, // uint32_t duty_val,the least 4 bits are decimal part
1, // uint32_t increase,
1, // uint32_t duty_num,
1, // uint32_t duty_cycle,
0 // uint32_t duty_scale
);
}
static void gamma_table_create(uint16_t *gamma_table, float correction)
{
float value_tmp = 0;
/**
* @brief gamma curve formula: y=a*x^(1/gm)
* x (0,(GAMMA_TABLE_SIZE-1)/GAMMA_TABLE_SIZE)
* a = GAMMA_TABLE_SIZE
*/
for (int i = 0; i < GAMMA_TABLE_SIZE; i++) {
value_tmp = (float)(i) / GAMMA_TABLE_SIZE;
value_tmp = powf(value_tmp, 1.0f / correction);
gamma_table[i] = (uint16_t)FLOATINT_2_FIXED((value_tmp * GAMMA_TABLE_SIZE), LEDC_FIXED_Q);
}
}
static IRAM_ATTR uint32_t gamma_value_to_duty(int value)
{
uint32_t tmp_q = GET_FIXED_INTEGER_PART(value, LEDC_FIXED_Q);
uint32_t tmp_r = GET_FIXED_DECIMAL_PART(value, LEDC_FIXED_Q);
uint16_t cur = LEDC_VALUE_TO_DUTY(g_gamma_table[tmp_q]);
uint16_t next = LEDC_VALUE_TO_DUTY(g_gamma_table[tmp_q + 1]);
return (cur + (next - cur) * tmp_r / (0x1U << LEDC_FIXED_Q));
}
static IRAM_ATTR bool fade_timercb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
int idle_channel_num = 0;
for (int channel = 0; channel < LEDC_CHANNEL_MAX; channel++) {
ledc_fade_data_t *fade_data = g_light_config->fade_data + channel;
if (fade_data->num > 0) {
fade_data->num--;
if (fade_data->step) {
fade_data->cur += fade_data->step;
if (fade_data->num != 0) {
_iot_set_fade_with_time(g_light_config->speed_mode, channel,
gamma_value_to_duty(fade_data->cur),
DUTY_SET_CYCLE - LEDC_FADE_MARGIN);
} else {
iot_ledc_set_duty(g_light_config->speed_mode, channel, gamma_value_to_duty(fade_data->cur));
}
_iot_update_duty(g_light_config->speed_mode, channel);
} else {
iot_ledc_set_duty(g_light_config->speed_mode, channel, gamma_value_to_duty(fade_data->cur));
_iot_update_duty(g_light_config->speed_mode, channel);
}
} else if (fade_data->cycle) {
fade_data->num = fade_data->cycle - 1;
if (fade_data->step) {
fade_data->step *= -1;
fade_data->cur += fade_data->step;
} else {
fade_data->cur = (fade_data->cur == fade_data->final) ? 0 : fade_data->final;
}
_iot_set_fade_with_time(g_light_config->speed_mode, channel,
gamma_value_to_duty(fade_data->cur),
DUTY_SET_CYCLE - LEDC_FADE_MARGIN);
_iot_update_duty(g_light_config->speed_mode, channel);
} else {
idle_channel_num++;
}
}
if (idle_channel_num >= LEDC_CHANNEL_MAX) {
iot_timer_stop(timer);
}
return false;
}
esp_err_t iot_led_init(ledc_timer_t timer_num, ledc_mode_t speed_mode, uint32_t freq_hz)
{
esp_err_t ret = ESP_OK;
const ledc_timer_config_t ledc_time_config = {
.speed_mode = speed_mode,
.timer_num = timer_num,
.freq_hz = freq_hz,
.duty_resolution = LEDC_TIMER_13_BIT,
};
ret = ledc_timer_config(&ledc_time_config);
if (ret != ESP_OK) {
ESP_LOGW(TAG, "LEDC timer configuration");
return ret;
}
if (g_gamma_table == NULL) {
g_gamma_table = calloc(GAMMA_TABLE_SIZE, sizeof(uint16_t));
gamma_table_create(g_gamma_table, GAMMA_CORRECTION);
} else {
ESP_LOGE(TAG, "gamma_table has been initialized");
}
if (g_light_config == NULL) {
g_light_config = calloc(1, sizeof(iot_light_t));
g_light_config->timer_num = timer_num;
g_light_config->speed_mode = speed_mode;
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = GPTIMER_RESOLUTION_HZ,
};
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &g_light_config->gptimer));
gptimer_event_callbacks_t cbs = {
.on_alarm = fade_timercb,
};
ESP_ERROR_CHECK(gptimer_register_event_callbacks(g_light_config->gptimer, &cbs, NULL));
ESP_ERROR_CHECK(gptimer_enable(g_light_config->gptimer));
} else {
ESP_LOGE(TAG, "g_light_config has been initialized");
}
return ESP_OK;
}
esp_err_t iot_led_deinit(void)
{
if (g_gamma_table) {
free(g_gamma_table);
}
if (g_light_config) {
gptimer_disable(g_light_config->gptimer);
gptimer_del_timer(g_light_config->gptimer);
free(g_light_config);
}
return ESP_OK;
}
esp_err_t iot_led_regist_channel(ledc_channel_t channel, gpio_num_t gpio_num)
{
esp_err_t ret = ESP_OK;
if (g_light_config == NULL) {
ESP_LOGW(TAG, "iot_led_init() must be called first");
return ESP_ERR_NOT_FOUND;
}
#ifdef CONFIG_SPIRAM_SUPPORT
if (gpio_num != GPIO_NUM_16 || gpio_num != GPIO_NUM_17) {
ESP_LOGW(TAG, "gpio_num must not conflict to PSRAM(IO16 && IO17)");
return ESP_ERR_INVALID_ARG;
}
#endif
const ledc_channel_config_t ledc_ch_config = {
.gpio_num = gpio_num,
.channel = channel,
.intr_type = LEDC_INTR_DISABLE,
.speed_mode = g_light_config->speed_mode,
.timer_sel = g_light_config->timer_num,
};
ret = ledc_channel_config(&ledc_ch_config);
if (ret != ESP_OK) {
ESP_LOGW(TAG, "LEDC channel configuration");
return ret;
}
return ESP_OK;
}
esp_err_t iot_led_get_channel(ledc_channel_t channel, uint8_t *dst)
{
if (g_light_config == NULL || dst == NULL) {
ESP_LOGW(TAG, "iot_led_init() must be called first or dst should not be NULL");
return ESP_ERR_INVALID_ARG;
}
int cur = g_light_config->fade_data[channel].cur;
*dst = FIXED_2_FLOATING(cur, LEDC_FIXED_Q);
return ESP_OK;
}
esp_err_t iot_led_set_channel(ledc_channel_t channel, uint8_t value, uint32_t fade_ms)
{
if (g_light_config == NULL) {
ESP_LOGW(TAG, "iot_led_init() must be called first");
return ESP_ERR_INVALID_ARG;
}
ledc_fade_data_t *fade_data = g_light_config->fade_data + channel;
fade_data->final = FLOATINT_2_FIXED(value, LEDC_FIXED_Q);
if (fade_ms < DUTY_SET_CYCLE) {
fade_data->num = 1;
} else {
fade_data->num = fade_ms / DUTY_SET_CYCLE;
}
fade_data->step = abs(fade_data->cur - fade_data->final) / fade_data->num;
if (fade_data->cur > fade_data->final) {
fade_data->step *= -1;
}
if (fade_data->cycle != 0) {
fade_data->cycle = 0;
}
if (g_hw_timer_started != true) {
iot_timer_start(g_light_config->gptimer);
}
return ESP_OK;
}
esp_err_t iot_led_start_blink(ledc_channel_t channel, uint8_t value, uint32_t period_ms, bool fade_flag)
{
if (g_light_config == NULL) {
ESP_LOGW(TAG, "iot_led_init() must be called first");
return ESP_ERR_INVALID_ARG;
}
ledc_fade_data_t *fade_data = g_light_config->fade_data + channel;
fade_data->final = fade_data->cur = FLOATINT_2_FIXED(value, LEDC_FIXED_Q);
fade_data->cycle = period_ms / 2 / DUTY_SET_CYCLE;
fade_data->num = (fade_flag) ? period_ms / 2 / DUTY_SET_CYCLE : 0;
fade_data->step = (fade_flag) ? fade_data->cur / fade_data->num * -1 : 0;
if (g_hw_timer_started != true) {
iot_timer_start(g_light_config->gptimer);
}
return ESP_OK;
}
esp_err_t iot_led_stop_blink(ledc_channel_t channel)
{
if (g_light_config == NULL) {
ESP_LOGW(TAG, "iot_led_init() must be called first");
return ESP_ERR_INVALID_ARG;
}
ledc_fade_data_t *fade_data = g_light_config->fade_data + channel;
fade_data->cycle = fade_data->num = 0;
return ESP_OK;
}
esp_err_t iot_led_set_gamma_table(const uint16_t gamma_table[GAMMA_TABLE_SIZE])
{
if (g_gamma_table == NULL) {
ESP_LOGW(TAG, "iot_led_init() must be called first");
return ESP_ERR_INVALID_ARG;
}
memcpy(g_gamma_table, gamma_table, GAMMA_TABLE_SIZE * sizeof(uint16_t));
return ESP_OK;
}
#endif /* (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S3) */

View File

@ -1,459 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "esp_log.h"
#include "soc/ledc_reg.h"
#include "soc/timer_group_struct.h"
#include "soc/ledc_struct.h"
#include "driver/gptimer.h"
#include "driver/ledc.h"
#include "iot_light.h"
static const char *TAG = "light";
#define IOT_CHECK(tag, a, ret) if(!(a)) { \
return (ret); \
}
#define ERR_ASSERT(tag, param, ret) IOT_CHECK(tag, (param) == ESP_OK, ret)
#define POINT_ASSERT(tag, param) IOT_CHECK(tag, (param) != NULL, ESP_FAIL)
#define LIGHT_NUM_MAX 4
#define GPTIMER_RESOLUTION_HZ 1000000 // 1MHz, 1 tick=1us
typedef enum {
LIGHT_CH_NUM_1 = 1, /*!< Light channel number */
LIGHT_CH_NUM_2 = 2, /*!< Light channel number */
LIGHT_CH_NUM_3 = 3, /*!< Light channel number */
LIGHT_CH_NUM_4 = 4, /*!< Light channel number */
LIGHT_CH_NUM_5 = 5, /*!< Light channel number */
LIGHT_CH_NUM_MAX, /*!< user shouldn't use this */
} light_channel_num_t;
typedef struct {
gpio_num_t io_num;
ledc_mode_t mode;
ledc_channel_t channel;
int breath_period;
int blink_period;
uint32_t fade_step_num;
uint32_t *fade_duty_step;
int fade_duty_counter;
bool fade_step_up;
bool fade_once;
bool fade_start;
} light_channel_t;
typedef struct {
uint8_t channel_num;
ledc_mode_t mode;
ledc_timer_t ledc_timer;
uint32_t full_duty;
uint32_t freq_hz;
ledc_timer_bit_t timer_bit;
gptimer_handle_t gptimer;
light_channel_t *channel_group[];
} light_t;
static bool g_fade_installed = false;
static bool g_hw_timer_started = false;
static light_t *g_light_group[LIGHT_NUM_MAX] = {NULL};
static esp_err_t iot_light_duty_set(light_handle_t light_handle, uint8_t channel_id, uint32_t duty);
static IRAM_ATTR void iot_ledc_ls_channel_update(ledc_mode_t speed_mode, ledc_channel_t channel_num)
{
if (speed_mode == LEDC_LOW_SPEED_MODE) {
LEDC.channel_group[speed_mode].channel[channel_num].conf0.low_speed_update = 1;
}
}
static IRAM_ATTR esp_err_t iot_ledc_duty_config(ledc_mode_t speed_mode, ledc_channel_t channel_num, int hpoint_val, int duty_val,
uint32_t duty_direction, uint32_t duty_num, uint32_t duty_cycle, uint32_t duty_scale)
{
if (hpoint_val >= 0) {
LEDC.channel_group[speed_mode].channel[channel_num].hpoint.hpoint = hpoint_val & LEDC_HPOINT_HSCH1_V;
}
if (duty_val >= 0) {
LEDC.channel_group[speed_mode].channel[channel_num].duty.duty = duty_val;
}
LEDC.channel_group[speed_mode].channel[channel_num].conf1.val = ((duty_direction & LEDC_DUTY_INC_HSCH0_V) << LEDC_DUTY_INC_HSCH0_S) |
((duty_num & LEDC_DUTY_NUM_HSCH0_V) << LEDC_DUTY_NUM_HSCH0_S) |
((duty_cycle & LEDC_DUTY_CYCLE_HSCH0_V) << LEDC_DUTY_CYCLE_HSCH0_S) |
((duty_scale & LEDC_DUTY_SCALE_HSCH0_V) << LEDC_DUTY_SCALE_HSCH0_S);
iot_ledc_ls_channel_update(speed_mode, channel_num);
return ESP_OK;
}
static IRAM_ATTR esp_err_t iot_ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty)
{
return iot_ledc_duty_config(speed_mode,
channel, //uint32_t chan_num,
-1,
duty << 4, //uint32_t duty_val,the least 4 bits are decimal part
1, //uint32_t increase,
1, //uint32_t duty_num,
1, //uint32_t duty_cycle,
0 //uint32_t duty_scale
);
}
static IRAM_ATTR esp_err_t iot_ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel)
{
LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 1;
LEDC.channel_group[speed_mode].channel[channel].conf1.duty_start = 1;
iot_ledc_ls_channel_update(speed_mode, channel);
return ESP_OK;
}
static IRAM_ATTR bool breath_timer_callback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
{
for (int i = 0; i < LIGHT_NUM_MAX; i++) {
if (g_light_group[i] != NULL) {
light_t *light = g_light_group[i];
for (int j = 0; j < light->channel_num; j++) {
light_channel_t *l_chn = light->channel_group[j];
if (l_chn->fade_start == true) {
if (l_chn->fade_step_up == true) {
l_chn->fade_duty_counter++;
} else {
l_chn->fade_duty_counter--;
}
if ((l_chn->fade_duty_counter >= 0) && (l_chn->fade_duty_counter < l_chn->fade_step_num)) {
iot_ledc_set_duty(l_chn->mode, l_chn->channel, l_chn->fade_duty_step[l_chn->fade_duty_counter]);
iot_ledc_update_duty(l_chn->mode, l_chn->channel);
} else {
if (l_chn->fade_once != true) {
l_chn->fade_step_up = 1 - l_chn->fade_step_up;
} else {
l_chn->fade_start = false;
}
}
}
}
}
}
return false;
}
static light_channel_t *light_channel_create(gpio_num_t io_num, ledc_channel_t channel, ledc_mode_t mode, ledc_timer_t timer)
{
ledc_channel_config_t ledc_channel = {
.channel = channel,
.duty = 0,
.gpio_num = io_num,
.intr_type = LEDC_INTR_FADE_END,
.speed_mode = mode,
.timer_sel = timer
};
ERR_ASSERT(TAG, ledc_channel_config(&ledc_channel), NULL);
light_channel_t *pwm = (light_channel_t *)calloc(1, sizeof(light_channel_t));
pwm->io_num = io_num;
pwm->channel = channel;
pwm->mode = mode;
pwm->breath_period = 0;
pwm->blink_period = 0;
pwm->fade_step_num = 0;
pwm->fade_duty_step = NULL;
pwm->fade_duty_counter = 0;
pwm->fade_step_up = true;
pwm->fade_once = false;
pwm->fade_start = false;
return pwm;
}
static esp_err_t light_channel_delete(light_channel_t *light_channel)
{
POINT_ASSERT(TAG, light_channel);
if (light_channel->fade_duty_step != NULL) {
heap_caps_free(light_channel->fade_duty_step);
light_channel->fade_duty_step = NULL;
}
free(light_channel);
return ESP_OK;
}
static esp_err_t light_channel_fade_clear(light_channel_t *light_channel)
{
light_channel->fade_start = false;
light_channel->fade_step_num = 0;
light_channel->fade_duty_counter = 0;
light_channel->fade_step_up = true;
light_channel->fade_once = false;
if (light_channel->fade_duty_step != NULL) {
heap_caps_free(light_channel->fade_duty_step);
light_channel->fade_duty_step = NULL;
}
return ESP_OK;
}
light_handle_t iot_light_create(ledc_timer_t timer, ledc_mode_t speed_mode, uint32_t freq_hz, uint8_t channel_num, ledc_timer_bit_t timer_bit)
{
IOT_CHECK(TAG, channel_num != 0, NULL);
ledc_timer_config_t timer_conf = {
.timer_num = timer,
.speed_mode = speed_mode,
.freq_hz = freq_hz,
.bit_num = timer_bit
};
ERR_ASSERT(TAG, ledc_timer_config(&timer_conf), NULL);
light_t *light_ptr = (light_t *)calloc(1, sizeof(light_t) + sizeof(light_channel_t *) * channel_num);
light_ptr->channel_num = channel_num;
light_ptr->ledc_timer = timer;
light_ptr->full_duty = (1 << timer_bit) - 1;
light_ptr->freq_hz = freq_hz;
light_ptr->mode = speed_mode;
light_ptr->timer_bit = timer_bit;
if (g_hw_timer_started == false) {
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = GPTIMER_RESOLUTION_HZ,
};
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &light_ptr->gptimer));
gptimer_alarm_config_t alarm_config = {
.alarm_count = DUTY_SET_CYCLE / 1000 * GPTIMER_RESOLUTION_HZ,
.reload_count = 0,
.flags.auto_reload_on_alarm = true,
};
gptimer_event_callbacks_t cbs = {
.on_alarm = breath_timer_callback,
};
gptimer_register_event_callbacks(light_ptr->gptimer, &cbs, NULL);
gptimer_set_alarm_action(light_ptr->gptimer, &alarm_config);
gptimer_enable(light_ptr->gptimer);
gptimer_start(light_ptr->gptimer);
g_hw_timer_started = true;
}
for (int i = 0; i < channel_num; i++) {
light_ptr->channel_group[i] = NULL;
}
for (int i = 0; i < LIGHT_NUM_MAX; i++) {
if (g_light_group[i] == NULL) {
g_light_group[i] = light_ptr;
break;
}
}
return (light_handle_t)light_ptr;
}
esp_err_t iot_light_delete(light_handle_t light_handle)
{
light_t *light = (light_t *)light_handle;
POINT_ASSERT(TAG, light_handle);
for (int i = 0; i < light->channel_num; i++) {
if (light->channel_group[i] != NULL) {
iot_light_duty_set(light, i, 0);
light_channel_delete(light->channel_group[i]);
}
}
for (int i = 0; i < LIGHT_NUM_MAX; i++) {
if (g_light_group[i] == light) {
g_light_group[i] = NULL;
break;
}
}
for (int i = 0; i < LIGHT_NUM_MAX; i++) {
if (g_light_group[i] != NULL) {
goto FREE_MEM;
}
}
ledc_fade_func_uninstall();
g_fade_installed = false;
g_hw_timer_started = false;
gptimer_stop(light->gptimer);
gptimer_disable(light->gptimer);
gptimer_del_timer(light->gptimer);
FREE_MEM:
free(light_handle);
return ESP_OK;
}
esp_err_t iot_light_channel_regist(light_handle_t light_handle, uint8_t channel_idx, gpio_num_t io_num, ledc_channel_t channel)
{
light_t *light = (light_t *)light_handle;
POINT_ASSERT(TAG, light_handle);
IOT_CHECK(TAG, channel_idx < light->channel_num, FAIL);
if (light->channel_group[channel_idx] != NULL) {
ESP_LOGE(TAG, "this channel index has been registered");
return ESP_FAIL;
}
light->channel_group[channel_idx] = light_channel_create(io_num, channel, light->mode, light->ledc_timer);
if (g_fade_installed == false) {
ledc_fade_func_install(0);
g_fade_installed = true;
}
return ESP_OK;
}
static esp_err_t iot_light_duty_set(light_handle_t light_handle, uint8_t channel_id, uint32_t duty)
{
light_t *light = (light_t *)light_handle;
POINT_ASSERT(TAG, light_handle);
IOT_CHECK(TAG, channel_id < light->channel_num, ESP_FAIL);
POINT_ASSERT(TAG, light->channel_group[channel_id]);
light_channel_t *l_chn = light->channel_group[channel_id];
light_channel_fade_clear(l_chn);
iot_ledc_set_duty(l_chn->mode, l_chn->channel, duty);
iot_ledc_update_duty(l_chn->mode, l_chn->channel);
return ESP_OK;
}
uint32_t iot_light_duty_get(light_handle_t light_handle, uint8_t channel_id)
{
light_t *light = (light_t *)light_handle;
POINT_ASSERT(TAG, light_handle);
IOT_CHECK(TAG, channel_id < light->channel_num, ESP_FAIL);
POINT_ASSERT(TAG, light->channel_group[channel_id]);
light_channel_t *l_chn = light->channel_group[channel_id];
return ledc_get_duty(l_chn->mode, l_chn->channel);
}
esp_err_t iot_light_fade_with_time(light_handle_t light_handle, uint8_t channel_id, uint32_t duty, uint32_t fade_period_ms)
{
light_t *light = (light_t *)light_handle;
POINT_ASSERT(TAG, light_handle);
IOT_CHECK(TAG, channel_id < light->channel_num, ESP_FAIL);
POINT_ASSERT(TAG, light->channel_group[channel_id]);
light_channel_t *l_chn = light->channel_group[channel_id];
if (fade_period_ms == 0) {
return iot_light_duty_set(light, channel_id, duty);
}
light_channel_fade_clear(l_chn);
l_chn->fade_step_num = fade_period_ms / DUTY_SET_CYCLE + 1;
l_chn->fade_duty_step = (uint32_t *)heap_caps_malloc(l_chn->fade_step_num * sizeof(uint32_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint32_t duty_cur = iot_light_duty_get(light, channel_id);
int duty_delta = duty - duty_cur;
if (duty_delta > 0) {
float coe = (duty_delta / pow((double)l_chn->fade_step_num, (double)1 / DUTY_SET_GAMMA));
for (int i = 0; i < l_chn->fade_step_num; i++) {
l_chn->fade_duty_step[i] = duty_cur + (int)(coe * pow((double)i, (double)1 / DUTY_SET_GAMMA));
}
l_chn->fade_step_up = true;
} else {
duty_delta = 0 - duty_delta;
float coe = (duty_delta / pow((double)l_chn->fade_step_num, (double)1 / DUTY_SET_GAMMA));
for (int i = 0; i < l_chn->fade_step_num; i++) {
l_chn->fade_duty_step[i] = duty + (int)(coe * pow((double)i, (double)1 / DUTY_SET_GAMMA));
}
l_chn->fade_duty_counter = l_chn->fade_step_num;
l_chn->fade_step_up = false;
}
l_chn->fade_once = true;
l_chn->fade_start = true;
return ESP_OK;
}
esp_err_t iot_light_breath_config(light_handle_t light_handle, uint8_t channel_id, uint32_t duty, uint32_t breath_period_ms)
{
light_t *light = (light_t *)light_handle;
POINT_ASSERT(TAG, light_handle);
IOT_CHECK(TAG, channel_id < light->channel_num, ESP_FAIL);
POINT_ASSERT(TAG, light->channel_group[channel_id]);
light_channel_t *l_chn = light->channel_group[channel_id];
light_channel_fade_clear(l_chn);
/**
* @brief control light with nonlinearity fade, the duty and the fade step
* conform to gamma curve. gamma curve formula: y=a*x^(1/gm) firstly,
* use the target duty and step number to calculate coefficient `a`,
* secondly, calculate the duty for every step
*/
l_chn->fade_step_num = (breath_period_ms / 2) / DUTY_SET_CYCLE + 1;
float coe = (duty / pow((double)l_chn->fade_step_num, (double)1 / DUTY_SET_GAMMA));
l_chn->fade_duty_step = (uint32_t *)heap_caps_malloc(l_chn->fade_step_num * sizeof(uint32_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
for (int i = 0; i < l_chn->fade_step_num; i++) {
l_chn->fade_duty_step[i] = (int)(coe * pow((double)i, (double)1 / DUTY_SET_GAMMA));
}
return ESP_OK;
}
esp_err_t iot_light_blink_config(light_handle_t light_handle, uint8_t channel_id, uint32_t blink_period_ms)
{
light_t *light = (light_t *)light_handle;
POINT_ASSERT(TAG, light_handle);
IOT_CHECK(TAG, channel_id < light->channel_num, ESP_FAIL);
light_channel_t *l_chn = light->channel_group[channel_id];
light_channel_fade_clear(l_chn);
l_chn->fade_step_num = (blink_period_ms / 2) / DUTY_SET_CYCLE;
l_chn->fade_duty_step = (uint32_t *)heap_caps_malloc(l_chn->fade_step_num * sizeof(uint32_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
int i = 0;
for (i = 0; i < (l_chn->fade_step_num / 2); i++) {
l_chn->fade_duty_step[i] = 0;
}
for (; i < l_chn->fade_step_num; i++) {
l_chn->fade_duty_step[i] = light->full_duty;
}
return ESP_OK;
}
esp_err_t iot_light_operate_start(light_handle_t light_handle, uint8_t channel_id)
{
light_t *light = (light_t *)light_handle;
POINT_ASSERT(TAG, light_handle);
IOT_CHECK(TAG, channel_id < light->channel_num, ESP_FAIL);
light->channel_group[channel_id]->fade_start = true;
return ESP_OK;
}
esp_err_t iot_light_operate_stop(light_handle_t light_handle, uint8_t channel_id)
{
light_t *light = (light_t *)light_handle;
POINT_ASSERT(TAG, light_handle);
IOT_CHECK(TAG, channel_id < light->channel_num, ESP_FAIL);
light->channel_group[channel_id]->fade_start = false;
// iot_light_duty_set(light, channel_id, 0);
return ESP_OK;
}

View File

@ -1,178 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_check.h"
#include "led_strip_encoder.h"
#include "driver/rmt_tx.h"
#include "portmacro.h"
static const char *TAG = "led_encoder";
typedef struct {
rmt_encoder_t base;
rmt_encoder_t *bytes_encoder;
rmt_encoder_t *copy_encoder;
int state;
rmt_symbol_word_t reset_code;
} rmt_led_strip_encoder_t;
static size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
{
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder;
rmt_encoder_handle_t copy_encoder = led_encoder->copy_encoder;
rmt_encode_state_t session_state = RMT_ENCODING_RESET;
rmt_encode_state_t state = RMT_ENCODING_RESET;
size_t encoded_symbols = 0;
switch (led_encoder->state) {
case 0: // send RGB data
encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, primary_data, data_size, &session_state);
if (session_state & RMT_ENCODING_COMPLETE) {
led_encoder->state = 1; // switch to next state when current encoding session finished
}
if (session_state & RMT_ENCODING_MEM_FULL) {
state |= RMT_ENCODING_MEM_FULL;
goto out; // yield if there's no free space for encoding artifacts
}
// fall-through
case 1: // send reset code
encoded_symbols += copy_encoder->encode(copy_encoder, channel, &led_encoder->reset_code,
sizeof(led_encoder->reset_code), &session_state);
if (session_state & RMT_ENCODING_COMPLETE) {
led_encoder->state = RMT_ENCODING_RESET; // back to the initial encoding session
state |= RMT_ENCODING_COMPLETE;
}
if (session_state & RMT_ENCODING_MEM_FULL) {
state |= RMT_ENCODING_MEM_FULL;
goto out; // yield if there's no free space for encoding artifacts
}
}
out:
*ret_state = state;
return encoded_symbols;
}
static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t *encoder)
{
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
rmt_del_encoder(led_encoder->bytes_encoder);
rmt_del_encoder(led_encoder->copy_encoder);
free(led_encoder);
return ESP_OK;
}
static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t *encoder)
{
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
rmt_encoder_reset(led_encoder->bytes_encoder);
rmt_encoder_reset(led_encoder->copy_encoder);
led_encoder->state = RMT_ENCODING_RESET;
return ESP_OK;
}
esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder)
{
esp_err_t ret = ESP_OK;
rmt_led_strip_encoder_t *led_encoder = NULL;
ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
led_encoder = calloc(1, sizeof(rmt_led_strip_encoder_t));
ESP_GOTO_ON_FALSE(led_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for led strip encoder");
led_encoder->base.encode = rmt_encode_led_strip;
led_encoder->base.del = rmt_del_led_strip_encoder;
led_encoder->base.reset = rmt_led_strip_encoder_reset;
// different led strip might have its own timing requirements, following parameter is for WS2812
rmt_bytes_encoder_config_t bytes_encoder_config = {
.bit0 = {
.level0 = 1,
.duration0 = 0.3 * config->resolution / 1000000, // T0H=0.3us
.level1 = 0,
.duration1 = 0.9 * config->resolution / 1000000, // T0L=0.9us
},
.bit1 = {
.level0 = 1,
.duration0 = 0.9 * config->resolution / 1000000, // T1H=0.9us
.level1 = 0,
.duration1 = 0.3 * config->resolution / 1000000, // T1L=0.3us
},
.flags.msb_first = 1 // WS2812 transfer bit order: G7...G0R7...R0B7...B0
};
ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder(&bytes_encoder_config, &led_encoder->bytes_encoder), err, TAG, "create bytes encoder failed");
rmt_copy_encoder_config_t copy_encoder_config = {};
ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(&copy_encoder_config, &led_encoder->copy_encoder), err, TAG, "create copy encoder failed");
uint32_t reset_ticks = config->resolution / 1000000 * 50 / 2; // reset code duration defaults to 50us
led_encoder->reset_code = (rmt_symbol_word_t) {
.level0 = 0,
.duration0 = reset_ticks,
.level1 = 0,
.duration1 = reset_ticks,
};
*ret_encoder = &led_encoder->base;
return ESP_OK;
err:
if (led_encoder) {
if (led_encoder->bytes_encoder) {
rmt_del_encoder(led_encoder->bytes_encoder);
}
if (led_encoder->copy_encoder) {
rmt_del_encoder(led_encoder->copy_encoder);
}
free(led_encoder);
}
return ret;
}
#define RMT_LED_STRIP_RESOLUTION_HZ 10000000 // 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution)
#ifndef BLE_MESH_LED_STRIP_IO
#define RMT_LED_STRIP_GPIO_NUM 8
#else
#define RMT_LED_STRIP_GPIO_NUM BLE_MESH_LED_STRIP_IO
#endif
#define EXAMPLE_LED_NUMBERS 1
#define EXAMPLE_CHASE_SPEED_MS 10
static uint8_t led_strip_pixels[EXAMPLE_LED_NUMBERS * 3];
rmt_channel_handle_t led_chan = NULL;
rmt_encoder_handle_t led_encoder = NULL;
rmt_transmit_config_t tx_config;
void rmt_encoder_init()
{
led_chan = NULL;
rmt_tx_channel_config_t tx_chan_config = {
.clk_src = RMT_CLK_SRC_DEFAULT, // select source clock
.gpio_num = RMT_LED_STRIP_GPIO_NUM,
.mem_block_symbols = 64, // increase the block size can make the LED less flickering
.resolution_hz = RMT_LED_STRIP_RESOLUTION_HZ,
.trans_queue_depth = 4, // set the number of transactions that can be pending in the background
};
ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &led_chan));
ESP_LOGI(TAG, "Install led strip encoder");
led_encoder = NULL;
led_strip_encoder_config_t encoder_config = {
.resolution = RMT_LED_STRIP_RESOLUTION_HZ,
};
ESP_ERROR_CHECK(rmt_new_led_strip_encoder(&encoder_config, &led_encoder));
ESP_LOGI(TAG, "Enable RMT TX channel");
ESP_ERROR_CHECK(rmt_enable(led_chan));
tx_config.loop_count = 0; // no transfer loop
}
void rmt_led_set(uint8_t red, uint8_t green, uint8_t blue)
{
led_strip_pixels[0] = green;
led_strip_pixels[1] = red;
led_strip_pixels[2] = blue;
ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels, sizeof(led_strip_pixels), &tx_config));
ESP_ERROR_CHECK(rmt_tx_wait_all_done(led_chan, portMAX_DELAY));
}

View File

@ -1,891 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "errno.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "freertos/event_groups.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_partition.h"
#include "lwip/sockets.h"
#include "lwip/netdb.h"
#include "lwip/sockets.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "driver/i2c.h"
#include "sys/param.h"
#include "driver/gpio.h"
#include "light_driver.h"
#include "ble_mesh_example_nvs.h"
/**
* @brief The state of the five-color light
*/
typedef struct {
uint8_t mode;
uint8_t on;
uint16_t hue;
uint8_t saturation;
uint8_t value;
uint8_t lightness;
uint8_t color_temperature;
uint8_t brightness;
uint32_t fade_period_ms;
uint32_t blink_period_ms;
} light_status_t;
/**
* @brief The channel of the five-color light
*/
enum light_channel {
CHANNEL_ID_RED = 0,
CHANNEL_ID_GREEN,
CHANNEL_ID_BLUE,
CHANNEL_ID_WARM,
CHANNEL_ID_COLD,
};
#define LIGHT_FADE_PERIOD_MAX_MS (3 * 1000)
static const char *TAG = "light_driver";
static light_status_t g_light_status = {0};
static bool g_light_blink_flag = false;
static TimerHandle_t g_fade_timer = NULL;
static int g_fade_mode = MODE_NONE;
static uint16_t g_fade_hue = 0;
extern nvs_handle_t NVS_HANDLE;
esp_err_t light_driver_init(light_driver_config_t *config)
{
LIGHT_PARAM_CHECK(config);
bool exist = false;
if (ble_mesh_nvs_restore(NVS_HANDLE, LIGHT_STATUS_STORE_KEY, &g_light_status, sizeof(light_status_t), &exist) != ESP_OK) {
memset(&g_light_status, 0, sizeof(light_status_t));
g_light_status.mode = MODE_HSV;
g_light_status.on = 1;
g_light_status.hue = 360;
g_light_status.saturation = 0;
g_light_status.value = 100;
g_light_status.lightness = 100;
g_light_status.color_temperature = 0;
g_light_status.brightness = 30;
}
#if CONFIG_IDF_TARGET_ESP32C3
iot_led_init(LEDC_TIMER_0, LEDC_LOW_SPEED_MODE, 1000);
#elif CONFIG_IDF_TARGET_ESP32
iot_led_init(LEDC_TIMER_0, LEDC_HIGH_SPEED_MODE, 1000);
#endif
g_light_status.fade_period_ms = config->fade_period_ms;
g_light_status.blink_period_ms = config->blink_period_ms;
iot_led_regist_channel(CHANNEL_ID_RED, config->gpio_red);
iot_led_regist_channel(CHANNEL_ID_GREEN, config->gpio_green);
iot_led_regist_channel(CHANNEL_ID_BLUE, config->gpio_blue);
iot_led_regist_channel(CHANNEL_ID_WARM, config->gpio_warm);
iot_led_regist_channel(CHANNEL_ID_COLD, config->gpio_cold);
ESP_LOGI(TAG, "hue: %d, saturation: %d, value: %d, lightness: %d",
g_light_status.hue, g_light_status.saturation, g_light_status.value, g_light_status.lightness);
ESP_LOGI(TAG, "brightness: %d, color_temperature: %d",
g_light_status.brightness, g_light_status.color_temperature);
return ESP_OK;
}
esp_err_t light_driver_deinit(void)
{
esp_err_t ret = ESP_OK;
iot_led_deinit();
return ret;
}
esp_err_t light_driver_config(uint32_t fade_period_ms, uint32_t blink_period_ms)
{
g_light_status.fade_period_ms = fade_period_ms;
g_light_status.blink_period_ms = blink_period_ms;
return ESP_OK;
}
esp_err_t light_driver_set_rgb(uint8_t red, uint8_t green, uint8_t blue)
{
esp_err_t ret = 0;
ret = iot_led_set_channel(CHANNEL_ID_RED, red, 0);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_GREEN, green, 0);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_BLUE, blue, 0);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_WARM, 0, 0);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_COLD, 0, 0);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
return ESP_OK;
}
static esp_err_t light_driver_hsv2rgb(uint16_t hue, uint8_t saturation, uint8_t value,
uint8_t *red, uint8_t *green, uint8_t *blue)
{
uint16_t hi = (hue / 60) % 6;
uint16_t F = 100 * hue / 60 - 100 * hi;
uint16_t P = value * (100 - saturation) / 100;
uint16_t Q = value * (10000 - F * saturation) / 10000;
uint16_t T = value * (10000 - saturation * (100 - F)) / 10000;
switch (hi) {
case 0:
*red = value;
*green = T;
*blue = P;
break;
case 1:
*red = Q;
*green = value;
*blue = P;
break;
case 2:
*red = P;
*green = value;
*blue = T;
break;
case 3:
*red = P;
*green = Q;
*blue = value;
break;
case 4:
*red = T;
*green = P;
*blue = value;
break;
case 5:
*red = value;
*green = P;
*blue = Q;
break;
default:
return ESP_FAIL;
}
*red = *red * 255 / 100;
*green = *green * 255 / 100;
*blue = *blue * 255 / 100;
return ESP_OK;
}
static void light_driver_rgb2hsv(uint16_t red, uint16_t green, uint16_t blue,
uint16_t *h, uint8_t *s, uint8_t *v)
{
double hue, saturation, value;
double m_max = MAX(red, MAX(green, blue));
double m_min = MIN(red, MIN(green, blue));
double m_delta = m_max - m_min;
value = m_max / 255.0;
if (m_delta == 0) {
hue = 0;
saturation = 0;
} else {
saturation = m_delta / m_max;
if (red == m_max) {
hue = (green - blue) / m_delta;
} else if (green == m_max) {
hue = 2 + (blue - red) / m_delta;
} else {
hue = 4 + (red - green) / m_delta;
}
hue = hue * 60;
if (hue < 0) {
hue = hue + 360;
}
}
*h = (int)(hue + 0.5);
*s = (int)(saturation * 100 + 0.5);
*v = (int)(value * 100 + 0.5);
}
// refence: https://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
static esp_err_t light_driver_hsl2rgb(uint16_t hue, uint8_t saturation, uint8_t lightness,
uint8_t *red, uint8_t *green, uint8_t *blue)
{
uint16_t hi = (hue / 60) % 6;
uint16_t C = (100 - abs(2 * lightness - 100)) * saturation / 100;
uint16_t M = 100 * (lightness - 0.5 * C) / 100;
uint16_t X = C * (100 - abs((hue * 100 / 60 ) % 200 - 100)) / 100;
switch (hi) {
case 0: /* hue 0~60 */
*red = C + M;
*green = X + M;
*blue = M;
break;
case 1: /* hue 60~120 */
*red = X + M;
*green = C + M;
*blue = M;
break;
case 2: /* hue 120~180 */
*red = M;
*green = C + M;
*blue = X + M;
break;
case 3: /* hue 180~240 */
*red = M;
*green = X + M;
*blue = C + M;
break;
case 4: /* hue 240~300 */
*red = X + M;
*green = M;
*blue = C + M;
break;
case 5: /* hue 300~360 */
*red = C + M;
*green = M;
*blue = X + M;
break;
default:
return ESP_FAIL;
}
*red = *red * 255 / 100;
*green = *green * 255 / 100;
*blue = *blue * 255 / 100;
return ESP_OK;
}
esp_err_t light_driver_set_hsv(uint16_t hue, uint8_t saturation, uint8_t value)
{
LIGHT_PARAM_CHECK(hue <= 360);
LIGHT_PARAM_CHECK(saturation <= 100);
LIGHT_PARAM_CHECK(value <= 100);
esp_err_t ret = ESP_OK;
uint8_t red = 0;
uint8_t green = 0;
uint8_t blue = 0;
ret = light_driver_hsv2rgb(hue, saturation, value, &red, &green, &blue);
LIGHT_ERROR_CHECK(ret < 0, ret, "light_driver_hsv2rgb, ret: %d", ret);
ESP_LOGV(TAG, "red: %d, green: %d, blue: %d", red, green, blue);
ret = iot_led_set_channel(CHANNEL_ID_RED, red, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_GREEN, green, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_BLUE, blue, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
if (g_light_status.mode != MODE_HSV) {
ret = iot_led_set_channel(CHANNEL_ID_WARM, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_COLD, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
}
g_light_status.mode = MODE_HSV;
g_light_status.on = 1;
g_light_status.hue = hue;
g_light_status.value = value;
g_light_status.saturation = saturation;
ret = ble_mesh_nvs_store(NVS_HANDLE, LIGHT_STATUS_STORE_KEY, &g_light_status, sizeof(light_status_t));
LIGHT_ERROR_CHECK(ret < 0, ret, "ble_mesh_nvs_store, ret: %d", ret);
return ESP_OK;
}
esp_err_t light_driver_set_hue(uint16_t hue)
{
if (g_light_status.mode == MODE_HSV) {
return light_driver_set_hsv(hue, g_light_status.saturation, g_light_status.value);
} else if (g_light_status.mode == MODE_HSL) {
return light_driver_set_hsl(hue, g_light_status.saturation, g_light_status.lightness);
} else {
return ESP_FAIL;
}
}
esp_err_t light_driver_set_saturation(uint8_t saturation)
{
if (g_light_status.mode == MODE_HSV) {
return light_driver_set_hsv(g_light_status.hue, saturation, g_light_status.value);
} else if (g_light_status.mode == MODE_HSL) {
return light_driver_set_hsl(g_light_status.hue, saturation, g_light_status.lightness);
} else {
return ESP_FAIL;
}
}
esp_err_t light_driver_set_value(uint8_t value)
{
return light_driver_set_hsv(g_light_status.hue, g_light_status.saturation, value);
}
esp_err_t light_driver_get_hsv(uint16_t *hue, uint8_t *saturation, uint8_t *value)
{
LIGHT_PARAM_CHECK(hue);
LIGHT_PARAM_CHECK(saturation);
LIGHT_PARAM_CHECK(value);
*hue = g_light_status.hue;
*saturation = g_light_status.saturation;
*value = g_light_status.value;
return ESP_OK;
}
uint16_t light_driver_get_hue(void)
{
return g_light_status.hue;
}
uint8_t light_driver_get_saturation(void)
{
return g_light_status.saturation;
}
uint8_t light_driver_get_value(void)
{
return g_light_status.value;
}
uint8_t light_driver_get_mode(void)
{
return g_light_status.mode;
}
esp_err_t light_driver_set_ctb(uint8_t color_temperature, uint8_t brightness)
{
LIGHT_PARAM_CHECK(brightness <= 100);
LIGHT_PARAM_CHECK(color_temperature <= 100);
esp_err_t ret = ESP_OK;
uint8_t warm_tmp = color_temperature * brightness / 100;
uint8_t cold_tmp = (100 - color_temperature) * brightness / 100;
warm_tmp = warm_tmp < 15 ? warm_tmp : 14 + warm_tmp * 86 / 100;
cold_tmp = cold_tmp < 15 ? cold_tmp : 14 + cold_tmp * 86 / 100;
ret = iot_led_set_channel(CHANNEL_ID_COLD,
cold_tmp * 255 / 100, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_WARM,
warm_tmp * 255 / 100, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
if (g_light_status.mode != MODE_CTB) {
ret = iot_led_set_channel(CHANNEL_ID_RED, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_GREEN, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_BLUE, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
}
g_light_status.mode = MODE_CTB;
g_light_status.on = 1;
g_light_status.brightness = brightness;
g_light_status.color_temperature = color_temperature;
ret = ble_mesh_nvs_store(NVS_HANDLE, LIGHT_STATUS_STORE_KEY, &g_light_status, sizeof(light_status_t));
LIGHT_ERROR_CHECK(ret < 0, ret, "ble_mesh_nvs_store, ret: %d", ret);
return ESP_OK;
}
esp_err_t light_driver_set_color_temperature(uint8_t color_temperature)
{
return light_driver_set_ctb(color_temperature, g_light_status.brightness);
}
esp_err_t light_driver_set_brightness(uint8_t brightness)
{
return light_driver_set_ctb(g_light_status.color_temperature, brightness);
}
esp_err_t light_driver_get_ctb(uint8_t *color_temperature, uint8_t *brightness)
{
LIGHT_PARAM_CHECK(color_temperature);
LIGHT_PARAM_CHECK(brightness);
*brightness = g_light_status.brightness;
*color_temperature = g_light_status.color_temperature;
return ESP_OK;
}
uint8_t light_driver_get_color_temperature(void)
{
return g_light_status.color_temperature;
}
uint8_t light_driver_get_brightness(void)
{
return g_light_status.brightness;
}
esp_err_t light_driver_set_hsl(uint16_t hue, uint8_t saturation, uint8_t lightness)
{
LIGHT_PARAM_CHECK(hue <= 360);
LIGHT_PARAM_CHECK(saturation <= 100);
LIGHT_PARAM_CHECK(lightness <= 100);
esp_err_t ret = ESP_OK;
uint8_t red = 0;
uint8_t green = 0;
uint8_t blue = 0;
ret = light_driver_hsl2rgb(hue, saturation, lightness, &red, &green, &blue);
LIGHT_ERROR_CHECK(ret < 0, ret, "light_driver_hsl2rgb, ret: %d", ret);
ESP_LOGV(TAG, "red: %d, green: %d, blue: %d", red, green, blue);
ret = iot_led_set_channel(CHANNEL_ID_RED, red, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_GREEN, green, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_BLUE, blue, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
if (g_light_status.mode != MODE_HSL) {
ret = iot_led_set_channel(CHANNEL_ID_WARM, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_COLD, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
}
g_light_status.mode = MODE_HSL;
g_light_status.on = 1;
g_light_status.hue = hue;
g_light_status.saturation = saturation;
g_light_status.lightness = lightness;
ret = ble_mesh_nvs_store(NVS_HANDLE, LIGHT_STATUS_STORE_KEY, &g_light_status, sizeof(light_status_t));
LIGHT_ERROR_CHECK(ret < 0, ret, "ble_mesh_nvs_store, ret: %d", ret);
return ESP_OK;
}
esp_err_t light_driver_set_lightness(uint8_t lightness)
{
return light_driver_set_hsl(g_light_status.hue, g_light_status.saturation, lightness);
}
uint8_t light_driver_get_lightness(void)
{
return g_light_status.lightness;
}
esp_err_t light_driver_get_hsl(uint16_t *hue, uint8_t *saturation, uint8_t *lightness)
{
LIGHT_PARAM_CHECK(hue);
LIGHT_PARAM_CHECK(saturation);
LIGHT_PARAM_CHECK(lightness);
*hue = g_light_status.hue;
*saturation = g_light_status.saturation;
*lightness = g_light_status.lightness;
return ESP_OK;
}
esp_err_t light_driver_set_switch(bool on)
{
esp_err_t ret = ESP_OK;
g_light_status.on = on;
if (!g_light_status.on) {
ret = iot_led_set_channel(CHANNEL_ID_RED, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_GREEN, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_BLUE, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_COLD, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_WARM, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_set_channel, ret: %d", ret);
} else {
switch (g_light_status.mode) {
case MODE_HSV:
g_light_status.value = (g_light_status.value) ? g_light_status.value : 100;
ret = light_driver_set_hsv(g_light_status.hue, g_light_status.saturation, g_light_status.value);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "light_driver_set_hsv, ret: %d", ret);
break;
case MODE_HSL:
g_light_status.lightness = (g_light_status.lightness) ? g_light_status.lightness : 100;
ret = light_driver_set_hsl(g_light_status.hue, g_light_status.saturation, g_light_status.lightness);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "light_driver_set_hsl, ret: %d", ret);
break;
case MODE_CTB:
g_light_status.brightness = (g_light_status.brightness) ? g_light_status.brightness : 100;
ret = light_driver_set_ctb(g_light_status.color_temperature, g_light_status.brightness);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "light_driver_set_ctb, ret: %d", ret);
break;
default:
ESP_LOGW(TAG, "This operation is not supported");
break;
}
}
ret = ble_mesh_nvs_store(NVS_HANDLE, LIGHT_STATUS_STORE_KEY, &g_light_status, sizeof(light_status_t));
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "ble_mesh_nvs_store, ret: %d", ret);
return ESP_OK;
}
esp_err_t light_driver_set_mode(light_mode_t mode)
{
g_light_status.mode = mode;
return ESP_OK;
}
bool light_driver_get_switch(void)
{
return g_light_status.on;
}
esp_err_t light_driver_breath_start(uint8_t red, uint8_t green, uint8_t blue)
{
esp_err_t ret = ESP_OK;
ret = iot_led_start_blink(CHANNEL_ID_RED,
red, g_light_status.blink_period_ms, true);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_start_blink, ret: %d", ret);
ret = iot_led_start_blink(CHANNEL_ID_GREEN,
green, g_light_status.blink_period_ms, true);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_start_blink, ret: %d", ret);
ret = iot_led_start_blink(CHANNEL_ID_BLUE,
blue, g_light_status.blink_period_ms, true);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_start_blink, ret: %d", ret);
g_light_blink_flag = true;
return ESP_OK;
}
esp_err_t light_driver_breath_stop(void)
{
esp_err_t ret = ESP_OK;
if (g_light_blink_flag == false) {
return ESP_OK;
}
ret = iot_led_stop_blink(CHANNEL_ID_RED);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_stop_blink, ret: %d", ret);
ret = iot_led_stop_blink(CHANNEL_ID_GREEN);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_stop_blink, ret: %d", ret);
ret = iot_led_stop_blink(CHANNEL_ID_BLUE);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_stop_blink, ret: %d", ret);
light_driver_set_switch(true);
return ESP_OK;
}
esp_err_t light_driver_fade_brightness(uint8_t brightness)
{
esp_err_t ret = ESP_OK;
g_fade_mode = MODE_ON;
uint32_t fade_period_ms = 0;
if (g_light_status.mode == MODE_HSV) {
uint8_t red = 0;
uint8_t green = 0;
uint8_t blue = 0;
ret = light_driver_hsv2rgb(g_light_status.hue, g_light_status.saturation, g_light_status.value, &red, &green, &blue);
LIGHT_ERROR_CHECK(ret < 0, ret, "light_driver_hsv2rgb, ret: %d", ret);
if (brightness != 0) {
ret = iot_led_get_channel((ledc_channel_t)CHANNEL_ID_RED, &red);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_get_channel, ret: %d", ret);
ret = iot_led_get_channel((ledc_channel_t)CHANNEL_ID_GREEN, &green);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_get_channel, ret: %d", ret);
ret = iot_led_get_channel((ledc_channel_t)CHANNEL_ID_BLUE, &blue);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_get_channel, ret: %d", ret);
uint8_t max_color = MAX(MAX(red, green), blue);
uint8_t change_value = brightness * 255 / 100 - max_color;
fade_period_ms = LIGHT_FADE_PERIOD_MAX_MS * change_value / 255;
} else {
fade_period_ms = LIGHT_FADE_PERIOD_MAX_MS * MAX(MAX(red, green), blue) / 255;
red = 0;
}
g_light_status.value = brightness;
light_driver_hsv2rgb(g_light_status.hue, g_light_status.saturation, g_light_status.value, &red, &green, &blue);
ret = iot_led_set_channel(CHANNEL_ID_RED, red, fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_GREEN, green, fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_BLUE, blue, fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
} else if (g_light_status.mode == MODE_CTB) {
uint8_t warm_tmp = 0;
uint8_t cold_tmp = 0;
fade_period_ms = LIGHT_FADE_PERIOD_MAX_MS * g_light_status.brightness / 100;
if (brightness != 0) {
uint8_t change_value = brightness - g_light_status.brightness;
warm_tmp = g_light_status.color_temperature;
cold_tmp = (brightness - g_light_status.color_temperature);
fade_period_ms = LIGHT_FADE_PERIOD_MAX_MS * change_value / 100;
}
ret = iot_led_set_channel(CHANNEL_ID_COLD,
cold_tmp * 255 / 100, fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_WARM,
warm_tmp * 255 / 100, fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
g_light_status.brightness = brightness;
}
ret = ble_mesh_nvs_store(NVS_HANDLE, LIGHT_STATUS_STORE_KEY, &g_light_status, sizeof(light_status_t));
LIGHT_ERROR_CHECK(ret < 0, ret, "ble_mesh_nvs_store, ret: %d", ret);
return ESP_OK;
}
static void light_fade_timer_stop(void)
{
if (!g_fade_timer) {
return ;
}
if (!xTimerStop(g_fade_timer, portMAX_DELAY)) {
ESP_LOGW(TAG, "xTimerStop timer: %p", g_fade_timer);
}
if (!xTimerDelete(g_fade_timer, portMAX_DELAY)) {
ESP_LOGW(TAG, "xTimerDelete timer: %p", g_fade_timer);
}
g_fade_timer = NULL;
}
static void light_fade_timer_cb(TimerHandle_t timer)
{
uint8_t red = 0;
uint8_t green = 0;
uint8_t blue = 0;
uint32_t fade_period_ms = LIGHT_FADE_PERIOD_MAX_MS * 2 / 6;
int variety = (g_fade_hue > 180) ? 60 : -60;
if (g_light_status.hue >= 360 || g_light_status.hue <= 0) {
light_fade_timer_stop();
}
g_light_status.hue = g_light_status.hue >= 360 ? 360 : g_light_status.hue + variety;
g_light_status.hue = g_light_status.hue <= 60 ? 0 : g_light_status.hue + variety;
light_driver_hsv2rgb(g_light_status.hue, g_light_status.saturation, g_light_status.value, &red, &green, &blue);
iot_led_set_channel(CHANNEL_ID_RED, red, fade_period_ms);
iot_led_set_channel(CHANNEL_ID_GREEN, green, fade_period_ms);
iot_led_set_channel(CHANNEL_ID_BLUE, blue, fade_period_ms);
}
esp_err_t light_driver_fade_hue(uint16_t hue)
{
esp_err_t ret = ESP_OK;
g_fade_mode = MODE_HSV;
g_fade_hue = hue;
light_fade_timer_stop();
if (g_light_status.mode != MODE_HSV) {
ret = iot_led_set_channel(CHANNEL_ID_WARM, 0, 0);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_COLD, 0, 0);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
}
g_light_status.mode = MODE_HSV;
g_light_status.value = (g_light_status.value == 0) ? 100 : g_light_status.value;
uint32_t fade_period_ms = LIGHT_FADE_PERIOD_MAX_MS * 2 / 6;
light_fade_timer_cb(NULL);
g_fade_timer = xTimerCreate("light_timer", fade_period_ms,
true, NULL, light_fade_timer_cb);
xTimerStart(g_fade_timer, 0);
return ESP_OK;
}
esp_err_t light_driver_fade_warm(uint8_t color_temperature)
{
esp_err_t ret = ESP_OK;
g_fade_mode = MODE_CTB;
if (g_light_status.mode != MODE_CTB) {
ret = iot_led_set_channel(CHANNEL_ID_RED, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_GREEN, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_BLUE, 0, g_light_status.fade_period_ms);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
}
uint8_t warm_tmp = color_temperature * g_light_status.brightness / 100;
uint8_t cold_tmp = (100 - color_temperature) * g_light_status.brightness / 100;
ret = iot_led_set_channel(CHANNEL_ID_COLD, cold_tmp * 255 / 100, LIGHT_FADE_PERIOD_MAX_MS);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
ret = iot_led_set_channel(CHANNEL_ID_WARM, warm_tmp * 255 / 100, LIGHT_FADE_PERIOD_MAX_MS);
LIGHT_ERROR_CHECK(ret < 0, ret, "iot_led_set_channel, ret: %d", ret);
g_light_status.mode = MODE_CTB;
g_light_status.color_temperature = color_temperature;
ret = ble_mesh_nvs_store(NVS_HANDLE, LIGHT_STATUS_STORE_KEY, &g_light_status, sizeof(light_status_t));
LIGHT_ERROR_CHECK(ret < 0, ret, "ble_mesh_nvs_store, ret: %d", ret);
return ESP_OK;
}
esp_err_t light_driver_fade_stop(void)
{
esp_err_t ret = ESP_OK;
light_fade_timer_stop();
if (g_light_status.mode != MODE_CTB) {
uint16_t hue = 0;
uint8_t saturation = 0;
uint8_t value = 0;
ret = iot_led_stop_blink(CHANNEL_ID_RED);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_stop_blink, ret: %d", ret);
ret = iot_led_stop_blink(CHANNEL_ID_GREEN);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_stop_blink, ret: %d", ret);
ret = iot_led_stop_blink(CHANNEL_ID_BLUE);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_stop_blink, ret: %d", ret);
uint8_t red, green, blue;
ret = iot_led_get_channel(CHANNEL_ID_RED, &red);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_get_channel, ret: %d", ret);
ret = iot_led_get_channel(CHANNEL_ID_GREEN, &green);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_get_channel, ret: %d", ret);
ret = iot_led_get_channel(CHANNEL_ID_BLUE, &blue);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_get_channel, ret: %d", ret);
light_driver_rgb2hsv(red, green, blue, &hue, &saturation, &value);
g_light_status.hue = (g_fade_mode == MODE_HSV) ? hue : g_light_status.hue;
g_light_status.value = (g_fade_mode == MODE_OFF || g_fade_mode == MODE_ON) ? value : g_light_status.value;
} else {
uint8_t color_temperature = 0;
uint8_t brightness = 0;
ret = iot_led_stop_blink(CHANNEL_ID_COLD);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_stop_blink, ret: %d", ret);
ret = iot_led_stop_blink(CHANNEL_ID_WARM);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_stop_blink, ret: %d", ret);
uint8_t warm_tmp, cold_tmp;
uint8_t tmp;
ret = iot_led_get_channel(CHANNEL_ID_WARM, &tmp);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_get_channel, ret: %d", ret);
warm_tmp = (int32_t)tmp * 100 / 255;
ret = iot_led_get_channel(CHANNEL_ID_COLD, &tmp);
LIGHT_ERROR_CHECK(ret < 0, ESP_FAIL, "iot_led_get_channel, ret: %d", ret);
cold_tmp = (int32_t)tmp * 100 / 255;
color_temperature = (!warm_tmp) ? 0 : 100 / (cold_tmp / warm_tmp + 1);
brightness = (!color_temperature) ? cold_tmp : warm_tmp * 100 / color_temperature;
g_light_status.brightness = (g_fade_mode == MODE_OFF || g_fade_mode == MODE_ON) ? brightness : g_light_status.brightness;
g_light_status.color_temperature = (g_fade_mode == MODE_CTB) ? color_temperature : g_light_status.color_temperature;
}
ret = ble_mesh_nvs_store(NVS_HANDLE, LIGHT_STATUS_STORE_KEY, &g_light_status, sizeof(light_status_t));
LIGHT_ERROR_CHECK(ret < 0, ret, "ble_mesh_nvs_store, ret: %d", ret);
g_fade_mode = MODE_NONE;
return ESP_OK;
}

View File

@ -15,7 +15,7 @@
#include "iot_button.h" #include "iot_button.h"
#include "board.h" #include "board.h"
#include "esp_timer.h" #include "esp_timer.h"
#include "led_strip_encoder.h" #include "lightbulb.h"
#define TAG "BOARD" #define TAG "BOARD"
@ -28,7 +28,7 @@ esp_timer_handle_t led_timer_hdl;
void board_led_operation(uint8_t r, uint8_t g, uint8_t b) void board_led_operation(uint8_t r, uint8_t g, uint8_t b)
{ {
rmt_led_set(r,g,b); ws2812_set_rgb_channel(r, g, b);
} }
static void led_timer_callback(void* arg) static void led_timer_callback(void* arg)
@ -57,7 +57,24 @@ void board_led_operation_auto_close(uint8_t r, uint8_t g, uint8_t b, uint32_t ms
static void board_led_init(void) static void board_led_init(void)
{ {
rmt_encoder_init(); lightbulb_config_t config = {
.type = DRIVER_WS2812,
.driver_conf.ws2812.led_num = 3,
.driver_conf.ws2812.ctrl_io = 8,
.capability.enable_fades = true,
.capability.fades_ms = 800,
.capability.enable_status_storage = false,
.capability.mode_mask = COLOR_MODE,
.capability.storage_cb = NULL,
.external_limit = NULL,
.gamma_conf = NULL,
.init_status.mode = WORK_COLOR,
.init_status.on = false,
.init_status.hue = 0,
.init_status.saturation = 100,
.init_status.value = 100,
};
lightbulb_init(&config);
esp_led_timer_init(); esp_led_timer_init();
} }

View File

@ -14,7 +14,7 @@
#include "esp_log.h" #include "esp_log.h"
#include "board.h" #include "board.h"
#include "esp_timer.h" #include "esp_timer.h"
#include "led_strip_encoder.h" #include "lightbulb.h"
#include "iot_button.h" #include "iot_button.h"
#include "mesh/adapter.h" #include "mesh/adapter.h"
@ -26,7 +26,7 @@ esp_timer_handle_t led_timer_hdl;
void board_led_operation(uint8_t r, uint8_t g, uint8_t b) void board_led_operation(uint8_t r, uint8_t g, uint8_t b)
{ {
rmt_led_set(r,g,b); ws2812_set_rgb_channel(r, g, b);
} }
static void led_timer_callback(void* arg) static void led_timer_callback(void* arg)
@ -54,7 +54,24 @@ void board_led_operation_auto_close(uint8_t r, uint8_t g, uint8_t b, uint32_t ms
static void board_led_init(void) static void board_led_init(void)
{ {
rmt_encoder_init(); lightbulb_config_t config = {
.type = DRIVER_WS2812,
.driver_conf.ws2812.led_num = 3,
.driver_conf.ws2812.ctrl_io = 8,
.capability.enable_fades = true,
.capability.fades_ms = 800,
.capability.enable_status_storage = false,
.capability.mode_mask = COLOR_MODE,
.capability.storage_cb = NULL,
.external_limit = NULL,
.gamma_conf = NULL,
.init_status.mode = WORK_COLOR,
.init_status.on = false,
.init_status.hue = 0,
.init_status.saturation = 100,
.init_status.value = 100,
};
lightbulb_init(&config);
esp_led_timer_init(); esp_led_timer_init();
} }

View File

@ -11,6 +11,7 @@
#include "iot_button.h" #include "iot_button.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "lightbulb.h"
#include "esp_log.h" #include "esp_log.h"
#include "board.h" #include "board.h"
@ -25,7 +26,7 @@ extern void example_ble_mesh_send_remote_provisioning_scan_start(void);
void board_led_operation(uint8_t r, uint8_t g, uint8_t b) void board_led_operation(uint8_t r, uint8_t g, uint8_t b)
{ {
#ifdef BLE_MESH_LED_STRIP_IO #ifdef BLE_MESH_LED_STRIP_IO
rmt_led_set(r, g, b); ws2812_set_rgb_channel(r, g, b);
#else #else
gpio_set_level(LED_R, r); gpio_set_level(LED_R, r);
gpio_set_level(LED_G, g); gpio_set_level(LED_G, g);
@ -36,8 +37,25 @@ void board_led_operation(uint8_t r, uint8_t g, uint8_t b)
static void board_led_init(void) static void board_led_init(void)
{ {
#ifdef BLE_MESH_LED_STRIP_IO #ifdef BLE_MESH_LED_STRIP_IO
rmt_encoder_init(); lightbulb_config_t config = {
rmt_led_set(LED_OFF,LED_OFF,LED_OFF); .type = DRIVER_WS2812,
.driver_conf.ws2812.led_num = 3,
.driver_conf.ws2812.ctrl_io = 8,
.capability.enable_fades = true,
.capability.fades_ms = 800,
.capability.enable_status_storage = false,
.capability.mode_mask = COLOR_MODE,
.capability.storage_cb = NULL,
.external_limit = NULL,
.gamma_conf = NULL,
.init_status.mode = WORK_COLOR,
.init_status.on = false,
.init_status.hue = 0,
.init_status.saturation = 100,
.init_status.value = 100,
};
lightbulb_init(&config);
ws2812_set_rgb_channel(LED_OFF, LED_OFF, LED_OFF);
#else #else
gpio_set_level(LED_R, LED_OFF); gpio_set_level(LED_R, LED_OFF);
gpio_set_level(LED_G, LED_OFF); gpio_set_level(LED_G, LED_OFF);

View File

@ -15,7 +15,6 @@ extern "C" {
#endif /**< __cplusplus */ #endif /**< __cplusplus */
#include "driver/gpio.h" #include "driver/gpio.h"
#include "led_strip_encoder.h"
#if defined(CONFIG_BLE_MESH_ESP_WROOM_32) #if defined(CONFIG_BLE_MESH_ESP_WROOM_32)
#define LED_R GPIO_NUM_25 #define LED_R GPIO_NUM_25

View File

@ -10,6 +10,7 @@
#include <stdio.h> #include <stdio.h>
#include "driver/gpio.h" #include "driver/gpio.h"
#include "lightbulb.h"
#include "esp_log.h" #include "esp_log.h"
#include "board.h" #include "board.h"
@ -18,7 +19,7 @@
void board_led_operation(uint8_t r, uint8_t g, uint8_t b) void board_led_operation(uint8_t r, uint8_t g, uint8_t b)
{ {
#ifdef BLE_MESH_LED_STRIP_IO #ifdef BLE_MESH_LED_STRIP_IO
rmt_led_set(r, g, b); ws2812_set_rgb_channel(r, g, b);
#else #else
gpio_set_level(LED_R, r); gpio_set_level(LED_R, r);
gpio_set_level(LED_G, g); gpio_set_level(LED_G, g);
@ -29,8 +30,25 @@ void board_led_operation(uint8_t r, uint8_t g, uint8_t b)
static void board_led_init(void) static void board_led_init(void)
{ {
#ifdef BLE_MESH_LED_STRIP_IO #ifdef BLE_MESH_LED_STRIP_IO
rmt_encoder_init(); lightbulb_config_t config = {
rmt_led_set(LED_OFF,LED_OFF,LED_OFF); .type = DRIVER_WS2812,
.driver_conf.ws2812.led_num = 3,
.driver_conf.ws2812.ctrl_io = 8,
.capability.enable_fades = true,
.capability.fades_ms = 800,
.capability.enable_status_storage = false,
.capability.mode_mask = COLOR_MODE,
.capability.storage_cb = NULL,
.external_limit = NULL,
.gamma_conf = NULL,
.init_status.mode = WORK_COLOR,
.init_status.on = false,
.init_status.hue = 0,
.init_status.saturation = 100,
.init_status.value = 100,
};
lightbulb_init(&config);
ws2812_set_rgb_channel(LED_OFF, LED_OFF, LED_OFF);
#else #else
gpio_set_level(LED_R, LED_OFF); gpio_set_level(LED_R, LED_OFF);
gpio_set_level(LED_G, LED_OFF); gpio_set_level(LED_G, LED_OFF);

View File

@ -15,7 +15,6 @@ extern "C" {
#endif /**< __cplusplus */ #endif /**< __cplusplus */
#include "driver/gpio.h" #include "driver/gpio.h"
#include "led_strip_encoder.h"
#if defined(CONFIG_BLE_MESH_ESP_WROOM_32) #if defined(CONFIG_BLE_MESH_ESP_WROOM_32)
#define LED_R GPIO_NUM_25 #define LED_R GPIO_NUM_25

View File

@ -10,6 +10,7 @@
#include <stdio.h> #include <stdio.h>
#include "driver/gpio.h" #include "driver/gpio.h"
#include "lightbulb.h"
#include "esp_log.h" #include "esp_log.h"
#include "board.h" #include "board.h"
@ -18,7 +19,7 @@
void board_led_operation(uint8_t r, uint8_t g, uint8_t b) void board_led_operation(uint8_t r, uint8_t g, uint8_t b)
{ {
#ifdef BLE_MESH_LED_STRIP_IO #ifdef BLE_MESH_LED_STRIP_IO
rmt_led_set(r, g, b); ws2812_set_rgb_channel(r, g, b);
#else #else
gpio_set_level(LED_R, r); gpio_set_level(LED_R, r);
gpio_set_level(LED_G, g); gpio_set_level(LED_G, g);
@ -29,8 +30,25 @@ void board_led_operation(uint8_t r, uint8_t g, uint8_t b)
static void board_led_init(void) static void board_led_init(void)
{ {
#ifdef BLE_MESH_LED_STRIP_IO #ifdef BLE_MESH_LED_STRIP_IO
rmt_encoder_init(); lightbulb_config_t config = {
rmt_led_set(LED_OFF,LED_OFF,LED_OFF); .type = DRIVER_WS2812,
.driver_conf.ws2812.led_num = 3,
.driver_conf.ws2812.ctrl_io = 8,
.capability.enable_fades = true,
.capability.fades_ms = 800,
.capability.enable_status_storage = false,
.capability.mode_mask = COLOR_MODE,
.capability.storage_cb = NULL,
.external_limit = NULL,
.gamma_conf = NULL,
.init_status.mode = WORK_COLOR,
.init_status.on = false,
.init_status.hue = 0,
.init_status.saturation = 100,
.init_status.value = 100,
};
lightbulb_init(&config);
ws2812_set_rgb_channel(LED_OFF, LED_OFF, LED_OFF);
#else #else
gpio_set_level(LED_R, LED_OFF); gpio_set_level(LED_R, LED_OFF);
gpio_set_level(LED_G, LED_OFF); gpio_set_level(LED_G, LED_OFF);

View File

@ -15,7 +15,6 @@ extern "C" {
#endif /**< __cplusplus */ #endif /**< __cplusplus */
#include "driver/gpio.h" #include "driver/gpio.h"
#include "led_strip_encoder.h"
#if defined(CONFIG_BLE_MESH_ESP_WROOM_32) #if defined(CONFIG_BLE_MESH_ESP_WROOM_32)
#define LED_R GPIO_NUM_25 #define LED_R GPIO_NUM_25