mirror of
https://github.com/esphome/esphome.git
synced 2024-11-28 01:34:18 +01:00
ac_dimmer esp-idf
This commit is contained in:
parent
894d81c577
commit
d934ebbd0e
5 changed files with 150 additions and 9 deletions
|
@ -1,4 +1,3 @@
|
|||
#ifdef USE_ARDUINO
|
||||
|
||||
#include "ac_dimmer.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
|
@ -8,10 +7,15 @@
|
|||
#ifdef USE_ESP8266
|
||||
#include <core_esp8266_waveform.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
|
||||
#include <esp32-hal-timer.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
|
||||
#include "esp32-hw-timer.h"
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace ac_dimmer {
|
||||
|
||||
|
@ -191,7 +195,7 @@ void AcDimmer::setup() {
|
|||
// PWM and AcDimmer can even run at the same time this way
|
||||
setTimer1Callback(&timer_interrupt);
|
||||
#endif
|
||||
#ifdef USE_ESP32
|
||||
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
|
||||
// 80 Divider -> 1 count=1µs
|
||||
dimmer_timer = timerBegin(0, 80, true);
|
||||
timerAttachInterrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr, true);
|
||||
|
@ -201,6 +205,16 @@ void AcDimmer::setup() {
|
|||
timerAlarmWrite(dimmer_timer, 50, true);
|
||||
timerAlarmEnable(dimmer_timer);
|
||||
#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) {
|
||||
state = std::acos(1 - (2 * state)) / 3.14159; // RMS power compensation
|
||||
|
@ -229,5 +243,3 @@ void AcDimmer::dump_config() {
|
|||
|
||||
} // namespace ac_dimmer
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_ARDUINO
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef USE_ARDUINO
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/components/output/float_output.h"
|
||||
|
@ -66,5 +64,3 @@ class AcDimmer : public output::FloatOutput, public Component {
|
|||
|
||||
} // namespace ac_dimmer
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_ARDUINO
|
||||
|
|
110
esphome/components/ac_dimmer/esp32-hw-timer.cpp
Normal file
110
esphome/components/ac_dimmer/esp32-hw-timer.cpp
Normal file
|
@ -0,0 +1,110 @@
|
|||
#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
|
24
esphome/components/ac_dimmer/esp32-hw-timer.h
Normal file
24
esphome/components/ac_dimmer/esp32-hw-timer.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#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
|
|
@ -31,7 +31,6 @@ CONFIG_SCHEMA = cv.All(
|
|||
),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA),
|
||||
cv.only_with_arduino,
|
||||
)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue