9static const char *
const TAG =
"bm8563";
11static constexpr uint8_t CONTROL_STATUS_1_REG = 0x00;
12static constexpr uint8_t CONTROL_STATUS_2_REG = 0x01;
13static constexpr uint8_t TIME_FIRST_REG = 0x02;
14static constexpr uint8_t DATE_FIRST_REG = 0x05;
15static constexpr uint8_t TIMER_CONTROL_REG = 0x0E;
16static constexpr uint8_t TIMER_VALUE_REG = 0x0F;
17static constexpr uint8_t CLOCK_1_HZ = 0x82;
18static constexpr uint8_t CLOCK_1_60_HZ = 0x83;
20static constexpr uint32_t MAX_TIMER_DURATION_S = 255 * 60;
32 ESP_LOGCONFIG(TAG,
"BM8563:");
35 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
41 this->set_timer_irq_(duration_s);
47 ESP_LOGE(TAG,
"Invalid system time, not syncing to RTC.");
60 this->get_time_(rtc_time);
61 this->get_date_(rtc_time);
62 ESP_LOGD(TAG,
"Read time: %i-%i-%i %i, %i:%i:%i", rtc_time.
year, rtc_time.
month, rtc_time.
day_of_month,
67 ESP_LOGE(TAG,
"Invalid RTC time, not syncing to system clock.");
73uint8_t BM8563::bcd2_to_byte_(uint8_t value) {
74 const uint8_t tmp = ((value & 0xF0) >> 0x4) * 10;
75 return tmp + (value & 0x0F);
78uint8_t BM8563::byte_to_bcd2_(uint8_t value) {
79 const uint8_t bcdhigh = value / 10;
80 value -= bcdhigh * 10;
81 return (bcdhigh << 4) | value;
84void BM8563::get_time_(ESPTime &time) {
88 time.second = this->bcd2_to_byte_(buf[0] & 0x7f);
89 time.minute = this->bcd2_to_byte_(buf[1] & 0x7f);
90 time.hour = this->bcd2_to_byte_(buf[2] & 0x3f);
93void BM8563::set_time_(
const ESPTime &time) {
94 uint8_t buf[3] = {this->byte_to_bcd2_(time.second), this->byte_to_bcd2_(time.minute), this->byte_to_bcd2_(time.hour)};
95 this->write_register_(TIME_FIRST_REG, buf, 3);
98void BM8563::get_date_(ESPTime &time) {
102 time.day_of_month = this->bcd2_to_byte_(buf[0] & 0x3f);
103 time.day_of_week = this->bcd2_to_byte_(buf[1] & 0x07);
104 time.month = this->bcd2_to_byte_(buf[2] & 0x1f);
106 uint8_t year_byte = this->bcd2_to_byte_(buf[3] & 0xff);
109 time.year = 1900 + year_byte;
111 time.year = 2000 + year_byte;
115void BM8563::set_date_(
const ESPTime &time) {
117 this->byte_to_bcd2_(time.day_of_month),
118 this->byte_to_bcd2_(time.day_of_week),
119 this->byte_to_bcd2_(time.month),
120 this->byte_to_bcd2_(time.year % 100),
123 if (time.year < 2000) {
124 buf[2] = buf[2] | 0x80;
127 this->write_register_(DATE_FIRST_REG, buf, 4);
130void BM8563::write_byte_(uint8_t reg, uint8_t value) {
132 ESP_LOGE(TAG,
"Failed to write byte 0x%02X with value 0x%02X",
reg, value);
136void BM8563::write_register_(uint8_t reg,
const uint8_t *data,
size_t len) {
138 ESP_LOGE(TAG,
"Failed to write register 0x%02X with %zu bytes",
reg,
len);
142optional<uint8_t> BM8563::read_register_(uint8_t reg) {
145 ESP_LOGE(TAG,
"Failed to read register 0x%02X",
reg);
151void BM8563::set_timer_irq_(
uint32_t duration_s) {
152 ESP_LOGI(TAG,
"Timer Duration: %" PRIu32
" s", duration_s);
154 if (duration_s > MAX_TIMER_DURATION_S) {
155 ESP_LOGW(TAG,
"Timer duration %" PRIu32
" s exceeds maximum %" PRIu32
" s", duration_s, MAX_TIMER_DURATION_S);
159 if (duration_s > 255) {
160 uint8_t duration_minutes = duration_s / 60;
161 this->write_byte_(TIMER_VALUE_REG, duration_minutes);
162 this->write_byte_(TIMER_CONTROL_REG, CLOCK_1_60_HZ);
164 this->write_byte_(TIMER_VALUE_REG, duration_s);
165 this->write_byte_(TIMER_CONTROL_REG, CLOCK_1_HZ);
168 auto maybe_ctrl_status_2 = this->read_register_(CONTROL_STATUS_2_REG);
169 if (!maybe_ctrl_status_2.has_value()) {
170 ESP_LOGE(TAG,
"Failed to read CONTROL_STATUS_2_REG");
173 uint8_t ctrl_status_2_reg_value = maybe_ctrl_status_2.value();
174 ctrl_status_2_reg_value |= (1 << 0);
175 ctrl_status_2_reg_value &= ~(1 << 7);
176 this->write_byte_(CONTROL_STATUS_2_REG, ctrl_status_2_reg_value);
179void BM8563::clear_irq_() {
180 auto maybe_data = this->read_register_(CONTROL_STATUS_2_REG);
181 if (!maybe_data.has_value()) {
182 ESP_LOGE(TAG,
"Failed to read CONTROL_STATUS_2_REG");
185 uint8_t
data = maybe_data.value();
186 this->write_byte_(CONTROL_STATUS_2_REG, data & 0xf3);
189void BM8563::disable_irq_() {
191 auto maybe_data = this->read_register_(CONTROL_STATUS_2_REG);
192 if (!maybe_data.has_value()) {
193 ESP_LOGE(TAG,
"Failed to read CONTROL_STATUS_2_REG");
196 uint8_t
data = maybe_data.value();
197 this->write_byte_(CONTROL_STATUS_2_REG, data & 0xfc);