Files
zigbeelight/main/light_driver.c
2026-03-15 22:07:15 +01:00

67 lines
2.5 KiB
C

#include "light_driver.h"
#include <esp_zigbee_core.h>
#include "driver/ledc.h"
#include "esp_log.h"
#include "esp_err.h"
#include <stdbool.h>
static const char* TAG = "light_driver";
static const uint8_t light_gpio = 15;
static const uint16_t light_pwm_freq = 20000;
static const ledc_channel_t light_ledc_channel = LEDC_CHANNEL_0;
static const ledc_mode_t light_ledc_mode = LEDC_LOW_SPEED_MODE;
static const ledc_timer_bit_t light_pwm_resolution = LEDC_TIMER_10_BIT;
static const uint32_t light_max_brightness = (1 << light_pwm_resolution) - 1;
static const uint32_t light_max_level = 254; // zigbee light level, goes from 0 to 254
static bool light_init_done = false;
static uint8_t light_current_level = 0;
esp_err_t light_driver_set_level(const uint8_t level, const uint16_t transition_ms) {
if (!light_init_done) {
ESP_LOGW(TAG, "light driver not ready!");
return ESP_FAIL;
}
light_current_level = level;
double brightness = (double)light_current_level / (double)light_max_level;
if (brightness > 1) brightness = 1;
if (brightness < 0) brightness = 0;
const uint32_t duty = (uint32_t)(light_max_brightness * brightness * brightness); // brightness^2 for fast gamma correction
ESP_ERROR_CHECK(ledc_set_fade_with_time(light_ledc_mode, light_ledc_channel, duty, transition_ms));
ESP_ERROR_CHECK(ledc_fade_start(light_ledc_mode, light_ledc_channel, LEDC_FADE_NO_WAIT));
return ESP_OK;
}
esp_err_t light_driver_set_power(const bool power, const uint16_t transition_ms) {
return light_driver_set_level(power ? light_current_level : 0, transition_ms);
}
esp_err_t light_driver_init(const bool default_state) {
const ledc_timer_config_t ledc_timer = {
.speed_mode = light_ledc_mode,
.duty_resolution = light_pwm_resolution,
.timer_num = LEDC_TIMER_2,
.freq_hz = light_pwm_freq,
.clk_cfg = LEDC_AUTO_CLK
};
const ledc_channel_config_t ledc_channel = {
.speed_mode = ledc_timer.speed_mode,
.channel = light_ledc_channel,
.timer_sel = ledc_timer.timer_num,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = light_gpio,
.duty = 0, // Set duty to 0%
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
ESP_ERROR_CHECK(ledc_fade_func_install(0));
ESP_LOGI(TAG, "light driver inited, f=%d Hz", light_pwm_freq);
light_init_done = true;
light_driver_set_power(default_state, 100);
return ESP_OK;
}