From dca13dd292856ece18438006ea182637316de4a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Odd=20Str=C3=A5b=C3=B8?= Date: Sun, 20 Aug 2023 03:14:01 +0000 Subject: [PATCH] Implement pcf85063 clear_timer_flag, clear_alarm_flag and clockout_frequency --- esphome/components/pcf85063/pcf85063.cpp | 38 +++++++++++-- esphome/components/pcf85063/pcf85063.h | 21 ++++++++ esphome/components/pcf85063/time.py | 68 +++++++++++++++++++++++- 3 files changed, 121 insertions(+), 6 deletions(-) diff --git a/esphome/components/pcf85063/pcf85063.cpp b/esphome/components/pcf85063/pcf85063.cpp index b402f6e..7abb243 100644 --- a/esphome/components/pcf85063/pcf85063.cpp +++ b/esphome/components/pcf85063/pcf85063.cpp @@ -116,6 +116,39 @@ bool PCF85063Component::write_timer_interval(uint16_t interval_seconds) { return this->write_timer_(); } +#define PCF85063_READ_REG(reg, len) \ + if (!this->read_bytes(reg, &this->pcf85063_.raw[reg], len)) { \ + ESP_LOGE(TAG, "Can't read I2C data."); \ + return false; \ + } + +#define PCF85063_WRITE_REG(reg, len) \ + if (!this->write_bytes(reg, &this->pcf85063_.raw[reg], len)) { \ + ESP_LOGE(TAG, "Can't write I2C data."); \ + return false; \ + } + +bool PCF85063Component::clear_timer_flag() { + PCF85063_READ_REG(0x01, 1); + this->pcf85063_.reg.timer_flag = 0; + PCF85063_WRITE_REG(0x01, 1); + return true; +} + +bool PCF85063Component::clear_alarm_flag() { + PCF85063_READ_REG(0x01, 1); + this->pcf85063_.reg.alarm_flag = 0; + PCF85063_WRITE_REG(0x01, 1); + return true; +} + +bool PCF85063Component::write_clockout_frequency(uint8_t freq) { + PCF85063_READ_REG(0x01, 1); + this->pcf85063_.reg.clkout_control = freq & 0b111; + PCF85063_WRITE_REG(0x01, 1); + return true; +} + void PCF85063Component::set_timer_interrupt_enable_(bool state) { pcf85063_.reg.timer_interrupt_enable = state; } @@ -125,10 +158,7 @@ void PCF85063Component::set_timer_interrupt_mode_(PCF85063ATimerInterruptMode_t } bool PCF85063Component::write_timer_() { - if (!this->write_bytes(0x10, &this->pcf85063_.raw[0x10], 2)) { - ESP_LOGE(TAG, "Can't write I2C data."); - return false; - } + PCF85063_WRITE_REG(0x10, 2); ESP_LOGD(TAG, "Write timer %s %0u CLOCK=%0u IR=%s %0u", ONOFF(pcf85063_.reg.timer_enable), pcf85063_.reg.timer_value, pcf85063_.reg.timer_clock_frequency, ONOFF(pcf85063_.reg.timer_interrupt_enable), pcf85063_.reg.timer_interrupt_mode); diff --git a/esphome/components/pcf85063/pcf85063.h b/esphome/components/pcf85063/pcf85063.h index 036d783..3643764 100644 --- a/esphome/components/pcf85063/pcf85063.h +++ b/esphome/components/pcf85063/pcf85063.h @@ -32,6 +32,9 @@ class PCF85063Component : public time::RealTimeClock, public i2c::I2CDevice { //bool set_timer_interval_us(uint64_t interval_us); bool write_timer_interval(uint16_t interval); + bool clear_timer_flag(); + bool clear_alarm_flag(); + bool write_clockout_frequency(uint8_t freq); void set_timer_interrupt_enable_(bool state); void set_timer_interrupt_mode_(PCF85063ATimerInterruptMode_t mode); @@ -152,6 +155,24 @@ template class StartTimerAction : public Action, public P } }; +template class SetClockoutFrequencyAction : public Action, public Parented { + public: + TEMPLATABLE_VALUE(uint8_t, freq); + void play(Ts... x) override { + this->parent_->write_clockout_frequency(this->freq_.value(x...)); + } +}; + +template class ClearTimerFlagAction : public Action, public Parented { + public: + void play(Ts... x) override { this->parent_->clear_timer_flag(); } +}; + +template class ClearAlarmFlagAction : public Action, public Parented { + public: + void play(Ts... x) override { this->parent_->clear_alarm_flag(); } +}; + template class WriteAction : public Action, public Parented { public: void play(Ts... x) override { this->parent_->write_time(); } diff --git a/esphome/components/pcf85063/time.py b/esphome/components/pcf85063/time.py index 75cd96a..14c7637 100644 --- a/esphome/components/pcf85063/time.py +++ b/esphome/components/pcf85063/time.py @@ -2,7 +2,7 @@ import esphome.config_validation as cv import esphome.codegen as cg from esphome import automation from esphome.components import i2c, time -from esphome.const import CONF_ID, CONF_INTERVAL +from esphome.const import CONF_ID, CONF_INTERVAL, CONF_VALUE CODEOWNERS = ["@brogon"] @@ -14,7 +14,9 @@ PCF85063Component = pcf85063_ns.class_( WriteAction = pcf85063_ns.class_("WriteAction", automation.Action) ReadAction = pcf85063_ns.class_("ReadAction", automation.Action) StartTimerAction = pcf85063_ns.class_("StartTimerAction", automation.Action) - +ClearTimerFlagAction = pcf85063_ns.class_("ClearTimerFlagAction", automation.Action) +ClearAlarmFlagAction = pcf85063_ns.class_("ClearAlarmFlagAction", automation.Action) +SetClockoutFrequencyAction = pcf85063_ns.class_("SetClockoutFrequencyAction", automation.Action) CONFIG_SCHEMA = time.TIME_SCHEMA.extend( { @@ -22,6 +24,7 @@ CONFIG_SCHEMA = time.TIME_SCHEMA.extend( } ).extend(i2c.i2c_device_schema(0x51)) +##### @automation.register_action( "pcf85063.write_time", @@ -37,6 +40,7 @@ async def pcf85063_write_time_to_code(config, action_id, template_arg, args): await cg.register_parented(var, config[CONF_ID]) return var +##### @automation.register_action( "pcf85063.read_time", @@ -52,6 +56,7 @@ async def pcf85063_read_time_to_code(config, action_id, template_arg, args): await cg.register_parented(var, config[CONF_ID]) return var +##### def validate_timer_seconds(value): value: cv.TimePeriodSeconds = cv.positive_time_period_seconds(value) @@ -87,6 +92,65 @@ async def pcf85063_start_timer_to_code(config, action_id, template_arg, args): await cg.register_parented(var, config[CONF_ID]) return var +##### + +def validate_clockout_frequency(value): + value = cv.int_range(0b000, 0b111)(value) + return value + +@automation.register_action( + "pcf85063.clockout_frequency", + SetClockoutFrequencyAction, + cv.Schema( + { + cv.GenerateID(): cv.use_id(PCF85063Component), + cv.Required(CONF_VALUE): cv.templatable(validate_clockout_frequency), + } + ), +) +async def pcf85063_clockout_frequency_to_code(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + + template_ = await cg.templatable(config[CONF_VALUE], args, type(int)) + cg.add(var.set_freq(template_)) + + await cg.register_parented(var, config[CONF_ID]) + return var + +##### + +@automation.register_action( + "pcf85063.clear_timer_flag", + ClearTimerFlagAction, + cv.Schema( + { + cv.GenerateID(): cv.use_id(PCF85063Component), + } + ), +) +async def pcf85063_clear_timer_flag_to_code(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + return var + +##### + +@automation.register_action( + "pcf85063.clear_alarm_flag", + ClearAlarmFlagAction, + cv.Schema( + { + cv.GenerateID(): cv.use_id(PCF85063Component), + } + ), +) +async def pcf85063_clear_alarm_flag_to_code(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + return var + +##### + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID])