pre-calculated brightness table
This commit is contained in:
@@ -6,19 +6,25 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include <stdbool.h>
|
||||
#include <math.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;
|
||||
/* tweakable stuff */
|
||||
static const uint8_t light_gpio = 2;
|
||||
static const uint16_t light_pwm_freq = 65000;
|
||||
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 const double light_lowest_duty_pct = 0.05; // lowest duty percentage where the LEDs still light up nice
|
||||
|
||||
/* no need to tweak this stuff */
|
||||
static const ledc_channel_t light_ledc_channel = LEDC_CHANNEL_0;
|
||||
static const ledc_mode_t light_ledc_speed_mode = LEDC_LOW_SPEED_MODE;
|
||||
static const uint32_t light_brightness_steps = (1 << light_pwm_resolution) - 1;
|
||||
|
||||
/* global vars */
|
||||
static bool light_init_done = false;
|
||||
static uint8_t light_current_level = 0;
|
||||
static uint16_t gamma_lut[ZIGBEE_LIGHT_LEVELS + 1];
|
||||
|
||||
esp_err_t light_driver_set_level(const uint8_t level, const uint16_t transition_ms) {
|
||||
if (!light_init_done) {
|
||||
@@ -27,12 +33,11 @@ esp_err_t light_driver_set_level(const uint8_t level, const uint16_t transition_
|
||||
}
|
||||
|
||||
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));
|
||||
const uint16_t duty = gamma_lut[light_current_level];
|
||||
ESP_ERROR_CHECK(ledc_fade_stop(light_ledc_speed_mode, light_ledc_channel));
|
||||
ESP_ERROR_CHECK(ledc_set_fade_with_time(light_ledc_speed_mode, light_ledc_channel, duty, transition_ms));
|
||||
ESP_ERROR_CHECK(ledc_fade_start(light_ledc_speed_mode, light_ledc_channel, LEDC_FADE_NO_WAIT));
|
||||
ESP_LOGI(TAG, "led set to %d, max is %d", duty, light_brightness_steps);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -42,7 +47,7 @@ esp_err_t light_driver_set_power(const bool power, const uint16_t transition_ms)
|
||||
|
||||
esp_err_t light_driver_init(const bool default_state) {
|
||||
const ledc_timer_config_t ledc_timer = {
|
||||
.speed_mode = light_ledc_mode,
|
||||
.speed_mode = light_ledc_speed_mode,
|
||||
.duty_resolution = light_pwm_resolution,
|
||||
.timer_num = LEDC_TIMER_2,
|
||||
.freq_hz = light_pwm_freq,
|
||||
@@ -57,10 +62,21 @@ esp_err_t light_driver_init(const bool default_state) {
|
||||
.duty = 0, // Set duty to 0%
|
||||
.hpoint = 0
|
||||
};
|
||||
|
||||
for (uint8_t i = 0; i <= ZIGBEE_LIGHT_LEVELS; i++) {
|
||||
const double brightness_pct = (double)i / (double)ZIGBEE_LIGHT_LEVELS;
|
||||
const double gamma_corrected = pow(brightness_pct, 2.2);
|
||||
const double scaled = (double)light_brightness_steps * gamma_corrected * (1 - light_lowest_duty_pct);
|
||||
gamma_lut[i] = (uint16_t)scaled + (uint16_t)((double)light_brightness_steps * light_lowest_duty_pct) + 1;
|
||||
}
|
||||
gamma_lut[0] = 0; // 0 is always completely off
|
||||
if (gamma_lut[ZIGBEE_LIGHT_LEVELS] > light_brightness_steps) gamma_lut[ZIGBEE_LIGHT_LEVELS] = light_brightness_steps;
|
||||
ESP_LOGI(TAG, "pre-computed brightness lookup table");
|
||||
|
||||
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);
|
||||
ESP_LOGI(TAG, "ledc driver initialized, f=%d Hz, %d step resolution", light_pwm_freq, light_brightness_steps);
|
||||
light_init_done = true;
|
||||
light_driver_set_power(default_state, 100);
|
||||
return ESP_OK;
|
||||
|
||||
Reference in New Issue
Block a user