mirror of
https://github.com/esphome/esphome.git
synced 2024-11-24 16:08:10 +01:00
upd
This commit is contained in:
parent
d934ebbd0e
commit
8a077fbe40
5 changed files with 234 additions and 146 deletions
|
@ -13,7 +13,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
|
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
|
||||||
#include "esp32-hw-timer.h"
|
#include "hw_timer_esp_idf.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
@ -195,7 +195,7 @@ void AcDimmer::setup() {
|
||||||
// PWM and AcDimmer can even run at the same time this way
|
// PWM and AcDimmer can even run at the same time this way
|
||||||
setTimer1Callback(&timer_interrupt);
|
setTimer1Callback(&timer_interrupt);
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
|
#ifdef USE_ESP32
|
||||||
// 80 Divider -> 1 count=1µs
|
// 80 Divider -> 1 count=1µs
|
||||||
dimmer_timer = timerBegin(0, 80, true);
|
dimmer_timer = timerBegin(0, 80, true);
|
||||||
timerAttachInterrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr, true);
|
timerAttachInterrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr, true);
|
||||||
|
@ -205,17 +205,8 @@ void AcDimmer::setup() {
|
||||||
timerAlarmWrite(dimmer_timer, 50, true);
|
timerAlarmWrite(dimmer_timer, 50, true);
|
||||||
timerAlarmEnable(dimmer_timer);
|
timerAlarmEnable(dimmer_timer);
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
|
|
||||||
// 80 Divider -> 1 count=1µs
|
|
||||||
dimmer_timer = EspIdfTimer::timerBegin(0, 80, true);
|
|
||||||
EspIdfTimer::timerAttachInterrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr, true);
|
|
||||||
// For ESP32, we can't use dynamic interval calculation because the timerX functions
|
|
||||||
// are not callable from ISR (placed in flash storage).
|
|
||||||
// Here we just use an interrupt firing every 50 µs.
|
|
||||||
EspIdfTimer::timerAlarmWrite(dimmer_timer, 50, true);
|
|
||||||
EspIdfTimer::timerAlarmEnable(dimmer_timer);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AcDimmer::write_state(float state) {
|
void AcDimmer::write_state(float state) {
|
||||||
state = std::acos(1 - (2 * state)) / 3.14159; // RMS power compensation
|
state = std::acos(1 - (2 * state)) / 3.14159; // RMS power compensation
|
||||||
auto new_value = static_cast<uint16_t>(roundf(state * 65535));
|
auto new_value = static_cast<uint16_t>(roundf(state * 65535));
|
||||||
|
@ -223,6 +214,7 @@ void AcDimmer::write_state(float state) {
|
||||||
this->store_.init_cycle = this->init_with_half_cycle_;
|
this->store_.init_cycle = this->init_with_half_cycle_;
|
||||||
this->store_.value = new_value;
|
this->store_.value = new_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AcDimmer::dump_config() {
|
void AcDimmer::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "AcDimmer:");
|
ESP_LOGCONFIG(TAG, "AcDimmer:");
|
||||||
LOG_PIN(" Output Pin: ", this->gate_pin_);
|
LOG_PIN(" Output Pin: ", this->gate_pin_);
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
#include "esp32-hw-timer.h"
|
|
||||||
// #include "soc/soc_caps.h"
|
|
||||||
// #include "esp_clk.h"
|
|
||||||
// #include "esp32/clk.h"
|
|
||||||
|
|
||||||
#include "esphome/core/log.h"
|
|
||||||
|
|
||||||
static const char *const TAG = "esp32-hal-timer";
|
|
||||||
|
|
||||||
namespace esphome {
|
|
||||||
namespace ac_dimmer {
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint32_t reserved0 : 10;
|
|
||||||
uint32_t alarm_en : 1; /*When set alarm is enabled*/
|
|
||||||
uint32_t level_int_en : 1; /*When set level type interrupt will be generated during alarm*/
|
|
||||||
uint32_t edge_int_en : 1; /*When set edge type interrupt will be generated during alarm*/
|
|
||||||
uint32_t divider : 16; /*Timer clock (T0/1_clk) pre-scale value.*/
|
|
||||||
uint32_t autoreload : 1; /*When set timer 0/1 auto-reload at alarming is enabled*/
|
|
||||||
uint32_t increase : 1; /*When set timer 0/1 time-base counter increment. When cleared timer 0 time-base counter
|
|
||||||
decrement.*/
|
|
||||||
uint32_t enable : 1; /*When set timer 0/1 time-base counter is enabled*/
|
|
||||||
};
|
|
||||||
uint32_t val;
|
|
||||||
} timer_cfg_t;
|
|
||||||
|
|
||||||
#define NUM_OF_TIMERS SOC_TIMER_GROUP_TOTAL_TIMERS
|
|
||||||
|
|
||||||
// Works for all chips
|
|
||||||
static hw_timer_t timer_dev[4] = {
|
|
||||||
{TIMER_GROUP_0, TIMER_0}, {TIMER_GROUP_1, TIMER_0}, {TIMER_GROUP_0, TIMER_1}, {TIMER_GROUP_1, TIMER_1}};
|
|
||||||
|
|
||||||
// NOTE: (in IDF 5.0 there wont be need to know groups/numbers
|
|
||||||
// timer_init() will list thru all timers and return free timer handle)
|
|
||||||
|
|
||||||
// uint32_t getApbFrequency() {
|
|
||||||
// // rtc_clk_apb_freq_get();
|
|
||||||
// return esp_clk_apb_freq();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static void _on_apb_change(void *arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb) {
|
|
||||||
// hw_timer_t *timer = (hw_timer_t *) arg;
|
|
||||||
// if (ev_type == APB_BEFORE_CHANGE) {
|
|
||||||
// timerStop(timer);
|
|
||||||
// } else {
|
|
||||||
// old_apb /= 1000000;
|
|
||||||
// new_apb /= 1000000;
|
|
||||||
// uint16_t divider = (new_apb * timerGetDivider(timer)) / old_apb;
|
|
||||||
// timerSetDivider(timer, divider);
|
|
||||||
// timerStart(timer);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
hw_timer_t *EspIdfTimer::timerBegin(uint8_t num, uint16_t divider, bool countUp) {
|
|
||||||
if (num >= NUM_OF_TIMERS) {
|
|
||||||
ESP_LOGE(TAG, "Timer number %u exceeds available number of Timers.", num);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hw_timer_t *timer = &timer_dev[num]; // Get Timer group/num from 0-3 number
|
|
||||||
|
|
||||||
timer_config_t config = {
|
|
||||||
.alarm_en = TIMER_ALARM_DIS,
|
|
||||||
.counter_en = TIMER_PAUSE,
|
|
||||||
.intr_type = TIMER_INTR_LEVEL,
|
|
||||||
.counter_dir = static_cast<timer_count_dir_t>(countUp),
|
|
||||||
.auto_reload = timer_autoreload_t::TIMER_AUTORELOAD_DIS,
|
|
||||||
.divider = divider,
|
|
||||||
};
|
|
||||||
|
|
||||||
timer_init(timer->group, timer->num, &config);
|
|
||||||
timer_set_counter_value(timer->group, timer->num, 0);
|
|
||||||
EspIdfTimer::timerStart(timer);
|
|
||||||
// addApbChangeCallback(timer, _on_apb_change);
|
|
||||||
return timer;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IRAM_ATTR timerFnWrapper(void *arg) {
|
|
||||||
void (*fn)(void) = (void (*)()) arg;
|
|
||||||
fn();
|
|
||||||
|
|
||||||
// some additional logic or handling may be required here to approriately yield or not
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EspIdfTimer::timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge) {
|
|
||||||
if (edge) {
|
|
||||||
ESP_LOGW(TAG, "EDGE timer interrupt is not supported! Setting to LEVEL...");
|
|
||||||
}
|
|
||||||
timer_isr_callback_add(timer->group, timer->num, (bool (*)(void *)) timerFnWrapper, (void *) fn, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EspIdfTimer::timerStart(hw_timer_t *timer) { timer_start(timer->group, timer->num); }
|
|
||||||
|
|
||||||
void EspIdfTimer::timerAlarmEnable(hw_timer_t *timer) { timer_set_alarm(timer->group, timer->num, TIMER_ALARM_EN); }
|
|
||||||
|
|
||||||
void EspIdfTimer::timerAlarmDisable(hw_timer_t *timer) { timer_set_alarm(timer->group, timer->num, TIMER_ALARM_DIS); }
|
|
||||||
|
|
||||||
void EspIdfTimer::timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload) {
|
|
||||||
timer_set_alarm_value(timer->group, timer->num, alarm_value);
|
|
||||||
timerSetAutoReload(timer, autoreload);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EspIdfTimer::timerSetAutoReload(hw_timer_t *timer, bool autoreload) {
|
|
||||||
timer_set_auto_reload(timer->group, timer->num, (timer_autoreload_t) autoreload);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ac_dimmer
|
|
||||||
} // namespace esphome
|
|
|
@ -1,24 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include "driver/timer.h"
|
|
||||||
namespace esphome {
|
|
||||||
namespace ac_dimmer {
|
|
||||||
|
|
||||||
typedef struct hw_timer_s {
|
|
||||||
timer_group_t group;
|
|
||||||
timer_idx_t num;
|
|
||||||
} hw_timer_t;
|
|
||||||
|
|
||||||
class EspIdfTimer {
|
|
||||||
public:
|
|
||||||
static hw_timer_t *timerBegin(uint8_t timer, uint16_t divider, bool countUp);
|
|
||||||
static void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge);
|
|
||||||
|
|
||||||
static void timerAlarmEnable(hw_timer_t *timer);
|
|
||||||
static void timerAlarmDisable(hw_timer_t *timer);
|
|
||||||
static void timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload);
|
|
||||||
static void timerSetAutoReload(hw_timer_t *timer, bool autoreload);
|
|
||||||
|
|
||||||
static void timerStart(hw_timer_t *timer);
|
|
||||||
};
|
|
||||||
} // namespace ac_dimmer
|
|
||||||
} // namespace esphome
|
|
202
esphome/components/ac_dimmer/hw_timer_esp_idf.cpp
Normal file
202
esphome/components/ac_dimmer/hw_timer_esp_idf.cpp
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
|
||||||
|
|
||||||
|
#include "hw_timer_esp_idf.h"
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#include "esp32/clk.h"
|
||||||
|
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
static const char *const TAG = "hw_timer_esp_idf";
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ac_dimmer {
|
||||||
|
|
||||||
|
#define NUM_OF_TIMERS SOC_TIMER_GROUP_TOTAL_TIMERS
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
uint32_t reserved0 : 10;
|
||||||
|
uint32_t alarm_en : 1; /*When set alarm is enabled*/
|
||||||
|
uint32_t level_int_en : 1; /*When set level type interrupt will be generated during alarm*/
|
||||||
|
uint32_t edge_int_en : 1; /*When set edge type interrupt will be generated during alarm*/
|
||||||
|
uint32_t divider : 16; /*Timer clock (T0/1_clk) pre-scale value.*/
|
||||||
|
uint32_t autoreload : 1; /*When set timer 0/1 auto-reload at alarming is enabled*/
|
||||||
|
uint32_t increase : 1; /*When set timer 0/1 time-base counter increment. When cleared timer 0 time-base counter
|
||||||
|
decrement.*/
|
||||||
|
uint32_t enable : 1; /*When set timer 0/1 time-base counter is enabled*/
|
||||||
|
};
|
||||||
|
uint32_t val;
|
||||||
|
} timer_cfg_t;
|
||||||
|
|
||||||
|
// Works for all chips
|
||||||
|
static hw_timer_t timer_dev[4] = {
|
||||||
|
{TIMER_GROUP_0, TIMER_0}, {TIMER_GROUP_1, TIMER_0}, {TIMER_GROUP_0, TIMER_1}, {TIMER_GROUP_1, TIMER_1}};
|
||||||
|
// NOTE: (in IDF 5.0 there wont be need to know groups/numbers
|
||||||
|
// timer_init() will list thru all timers and return free timer handle)
|
||||||
|
|
||||||
|
typedef enum { APB_BEFORE_CHANGE, APB_AFTER_CHANGE } apb_change_ev_t;
|
||||||
|
typedef void (*apb_change_cb_t)(void *arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb);
|
||||||
|
typedef struct apb_change_cb_s {
|
||||||
|
struct apb_change_cb_s *prev;
|
||||||
|
struct apb_change_cb_s *next;
|
||||||
|
void *arg;
|
||||||
|
apb_change_cb_t cb;
|
||||||
|
} apb_change_t;
|
||||||
|
|
||||||
|
static apb_change_t *apb_change_callbacks = NULL;
|
||||||
|
static xSemaphoreHandle apb_change_lock = NULL;
|
||||||
|
|
||||||
|
// Hz
|
||||||
|
uint32_t getApbFrequency() { return esp_clk_apb_freq(); }
|
||||||
|
|
||||||
|
static void _on_apb_change(void *arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb) {
|
||||||
|
hw_timer_t *timer = (hw_timer_t *) arg;
|
||||||
|
if (ev_type == APB_BEFORE_CHANGE) {
|
||||||
|
timerStop(timer);
|
||||||
|
} else {
|
||||||
|
old_apb /= 1000000;
|
||||||
|
new_apb /= 1000000;
|
||||||
|
uint16_t divider = (new_apb * timerGetDivider(timer)) / old_apb;
|
||||||
|
timerSetDivider(timer, divider);
|
||||||
|
timerStart(timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initApbChangeCallback() {
|
||||||
|
static volatile bool initialized = false;
|
||||||
|
if (!initialized) {
|
||||||
|
initialized = true;
|
||||||
|
apb_change_lock = xSemaphoreCreateMutex();
|
||||||
|
if (!apb_change_lock) {
|
||||||
|
initialized = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool addApbChangeCallback(void *arg, apb_change_cb_t cb) {
|
||||||
|
initApbChangeCallback();
|
||||||
|
apb_change_t *c = (apb_change_t *) malloc(sizeof(apb_change_t));
|
||||||
|
if (!c) {
|
||||||
|
ESP_LOGE(TAG, "Callback Object Malloc Failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
c->next = NULL;
|
||||||
|
c->prev = NULL;
|
||||||
|
c->arg = arg;
|
||||||
|
c->cb = cb;
|
||||||
|
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
|
||||||
|
if (apb_change_callbacks == NULL) {
|
||||||
|
apb_change_callbacks = c;
|
||||||
|
} else {
|
||||||
|
apb_change_t *r = apb_change_callbacks;
|
||||||
|
// look for duplicate callbacks
|
||||||
|
while ((r != NULL) && !((r->cb == cb) && (r->arg == arg)))
|
||||||
|
r = r->next;
|
||||||
|
if (r) {
|
||||||
|
ESP_LOGE(TAG, "duplicate func=%8p arg=%8p", c->cb, c->arg);
|
||||||
|
free(c);
|
||||||
|
xSemaphoreGive(apb_change_lock);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
c->next = apb_change_callbacks;
|
||||||
|
apb_change_callbacks->prev = c;
|
||||||
|
apb_change_callbacks = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xSemaphoreGive(apb_change_lock);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hw_timer_t *timerBegin(uint8_t num, uint16_t divider, bool countUp) {
|
||||||
|
if (num >= NUM_OF_TIMERS) {
|
||||||
|
ESP_LOGE(TAG, "Timer number %u exceeds available number of Timers.", num);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hw_timer_t *timer = &timer_dev[num]; // Get Timer group/num from 0-3 number
|
||||||
|
|
||||||
|
timer_config_t config = {
|
||||||
|
.alarm_en = TIMER_ALARM_DIS,
|
||||||
|
.counter_en = TIMER_PAUSE,
|
||||||
|
.intr_type = TIMER_INTR_LEVEL,
|
||||||
|
.counter_dir = static_cast<timer_count_dir_t>(countUp),
|
||||||
|
.auto_reload = timer_autoreload_t::TIMER_AUTORELOAD_DIS,
|
||||||
|
.divider = divider,
|
||||||
|
};
|
||||||
|
|
||||||
|
timer_init(timer->group, timer->num, &config);
|
||||||
|
timer_set_counter_value(timer->group, timer->num, 0);
|
||||||
|
timerStart(timer);
|
||||||
|
addApbChangeCallback(timer, _on_apb_change);
|
||||||
|
return timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRAM_ATTR timerFnWrapper(void *arg) {
|
||||||
|
void (*fn)(void) = (void (*)()) arg;
|
||||||
|
fn();
|
||||||
|
|
||||||
|
// some additional logic or handling may be required here to approriately yield or not
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge) {
|
||||||
|
if (edge) {
|
||||||
|
ESP_LOGW(TAG, "EDGE timer interrupt is not supported! Setting to LEVEL...");
|
||||||
|
}
|
||||||
|
timer_isr_callback_add(timer->group, timer->num, (bool (*)(void *)) timerFnWrapper, (void *) fn, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerStart(hw_timer_t *timer) { timer_start(timer->group, timer->num); }
|
||||||
|
|
||||||
|
void timerStop(hw_timer_t *timer) { timer_pause(timer->group, timer->num); }
|
||||||
|
|
||||||
|
void timerAlarmEnable(hw_timer_t *timer) { timer_set_alarm(timer->group, timer->num, TIMER_ALARM_EN); }
|
||||||
|
|
||||||
|
void timerAlarmDisable(hw_timer_t *timer) { timer_set_alarm(timer->group, timer->num, TIMER_ALARM_DIS); }
|
||||||
|
|
||||||
|
void timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload) {
|
||||||
|
timer_set_alarm_value(timer->group, timer->num, alarm_value);
|
||||||
|
timerSetAutoReload(timer, autoreload);
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerSetAutoReload(hw_timer_t *timer, bool autoreload) {
|
||||||
|
timer_set_auto_reload(timer->group, timer->num, (timer_autoreload_t) autoreload);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t timerGetDivider(hw_timer_t *timer) {
|
||||||
|
timer_cfg_t config;
|
||||||
|
config.val = timerGetConfig(timer);
|
||||||
|
return config.divider;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerSetDivider(hw_timer_t *timer, uint16_t divider) {
|
||||||
|
if (divider < 2) {
|
||||||
|
ESP_LOGE(TAG, "Timer divider must be set in range of 2 to 65535");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
timer_set_divider(timer->group, timer->num, divider);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t timerGetConfig(hw_timer_t *timer) {
|
||||||
|
timer_config_t timer_cfg;
|
||||||
|
timer_get_config(timer->group, timer->num, &timer_cfg);
|
||||||
|
|
||||||
|
// Translate to default uint32_t
|
||||||
|
timer_cfg_t cfg;
|
||||||
|
cfg.alarm_en = timer_cfg.alarm_en;
|
||||||
|
cfg.autoreload = timer_cfg.auto_reload;
|
||||||
|
cfg.divider = timer_cfg.divider;
|
||||||
|
cfg.edge_int_en = timer_cfg.intr_type;
|
||||||
|
cfg.level_int_en = !timer_cfg.intr_type;
|
||||||
|
cfg.enable = timer_cfg.counter_en;
|
||||||
|
cfg.increase = timer_cfg.counter_dir;
|
||||||
|
|
||||||
|
return cfg.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ac_dimmer
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif
|
28
esphome/components/ac_dimmer/hw_timer_esp_idf.h
Normal file
28
esphome/components/ac_dimmer/hw_timer_esp_idf.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
|
||||||
|
#include "driver/timer.h"
|
||||||
|
namespace esphome {
|
||||||
|
namespace ac_dimmer {
|
||||||
|
|
||||||
|
typedef struct hw_timer_s {
|
||||||
|
timer_group_t group;
|
||||||
|
timer_idx_t num;
|
||||||
|
} hw_timer_t;
|
||||||
|
|
||||||
|
hw_timer_t *timerBegin(uint8_t timer, uint16_t divider, bool countUp);
|
||||||
|
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge);
|
||||||
|
void timerAlarmEnable(hw_timer_t *timer);
|
||||||
|
void timerAlarmDisable(hw_timer_t *timer);
|
||||||
|
void timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload);
|
||||||
|
void timerSetAutoReload(hw_timer_t *timer, bool autoreload);
|
||||||
|
void timerStart(hw_timer_t *timer);
|
||||||
|
void timerStop(hw_timer_t *timer);
|
||||||
|
|
||||||
|
uint32_t timerGetConfig(hw_timer_t *timer);
|
||||||
|
uint16_t timerGetDivider(hw_timer_t *timer);
|
||||||
|
void timerSetDivider(hw_timer_t *timer, uint16_t divider);
|
||||||
|
|
||||||
|
} // namespace ac_dimmer
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue