mirror of
https://github.com/randybb/esphome-configs.git
synced 2026-01-02 19:47:29 +01:00
242 lines
5.7 KiB
C++
242 lines
5.7 KiB
C++
#include "esphome/core/log.h"
|
|
#include "esphome/components/i2c/i2c_bus.h"
|
|
#include "bm8563.h"
|
|
|
|
namespace esphome {
|
|
namespace bm8563 {
|
|
|
|
static const char *TAG = "bm8563.sensor";
|
|
|
|
void BM8563::setup(){
|
|
this->write_byte_16(0,0);
|
|
this->setupComplete = true;
|
|
if (this->sleep_duration_.has_value()) {
|
|
SetAlarmIRQ(*this->sleep_duration_);
|
|
}
|
|
}
|
|
|
|
void BM8563::loop(){
|
|
// if(!this->setupComplete){
|
|
// return;
|
|
// }
|
|
// BM8563_TimeTypeDef BM8563_TimeStruct;
|
|
// getTime(&BM8563_TimeStruct);
|
|
// this->publish_state(BM8563_TimeStruct.seconds);
|
|
}
|
|
|
|
void BM8563::dump_config(){
|
|
ESP_LOGCONFIG(TAG, "BM8563:");
|
|
ESP_LOGCONFIG(TAG, " Address: 0x%02X", this->address_);
|
|
ESP_LOGCONFIG(TAG, " setupComplete: %s", this->setupComplete ? "true" : "false");
|
|
if (this->sleep_duration_.has_value()) {
|
|
uint32_t duration = *this->sleep_duration_;
|
|
ESP_LOGCONFIG(TAG, " Sleep Duration: %u ms", duration);
|
|
}
|
|
}
|
|
|
|
void BM8563::set_sleep_duration(uint32_t time_s) {
|
|
this->sleep_duration_ = uint64_t(time_s);
|
|
if (this->sleep_duration_.has_value()) {
|
|
SetAlarmIRQ(*this->sleep_duration_);
|
|
}
|
|
}
|
|
|
|
bool BM8563::getVoltLow() {
|
|
uint8_t data = ReadReg(0x02);
|
|
return data & 0x80; // RTCC_VLSEC_MASK
|
|
}
|
|
|
|
uint8_t BM8563::bcd2ToByte(uint8_t value) {
|
|
uint8_t tmp = 0;
|
|
tmp = ((uint8_t)(value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10;
|
|
return (tmp + (value & (uint8_t)0x0F));
|
|
}
|
|
|
|
uint8_t BM8563::byteToBcd2(uint8_t value) {
|
|
uint8_t bcdhigh = 0;
|
|
|
|
while (value >= 10) {
|
|
bcdhigh++;
|
|
value -= 10;
|
|
}
|
|
|
|
return ((uint8_t)(bcdhigh << 4) | value);
|
|
}
|
|
|
|
void BM8563::getTime(BM8563_TimeTypeDef* BM8563_TimeStruct) {
|
|
uint8_t buf[3] = {0};
|
|
|
|
this->read_register(0x02, buf, 3);
|
|
|
|
BM8563_TimeStruct->seconds = bcd2ToByte(buf[0] & 0x7f);
|
|
BM8563_TimeStruct->minutes = bcd2ToByte(buf[1] & 0x7f);
|
|
BM8563_TimeStruct->hours = bcd2ToByte(buf[2] & 0x3f);
|
|
}
|
|
|
|
void BM8563::setTime(BM8563_TimeTypeDef* BM8563_TimeStruct) {
|
|
if (BM8563_TimeStruct == NULL) {
|
|
return;
|
|
}
|
|
uint8_t buf[3] = {byteToBcd2(BM8563_TimeStruct->seconds), byteToBcd2(BM8563_TimeStruct->minutes), byteToBcd2(BM8563_TimeStruct->hours)};
|
|
|
|
this->write_register(0x02, buf, 3);
|
|
}
|
|
|
|
void BM8563::getDate(BM8563_DateTypeDef* BM8563_DateStruct) {
|
|
uint8_t buf[4] = {0};
|
|
this->read_register(0x05, buf, 4);
|
|
|
|
BM8563_DateStruct->date = bcd2ToByte(buf[0] & 0x3f);
|
|
BM8563_DateStruct->weekDay = bcd2ToByte(buf[1] & 0x07);
|
|
BM8563_DateStruct->month = bcd2ToByte(buf[2] & 0x1f);
|
|
|
|
if (buf[2] & 0x80) {
|
|
BM8563_DateStruct->year = 1900 + bcd2ToByte(buf[3] & 0xff);
|
|
} else {
|
|
BM8563_DateStruct->year = 2000 + bcd2ToByte(buf[3] & 0xff);
|
|
}
|
|
}
|
|
|
|
void BM8563::setDate(BM8563_DateTypeDef* BM8563_DateStruct) {
|
|
if (BM8563_DateStruct == NULL) {
|
|
return;
|
|
}
|
|
uint8_t buf[4] = {byteToBcd2(BM8563_DateStruct->date), byteToBcd2(BM8563_DateStruct->weekDay), 0, byteToBcd2((uint8_t)(BM8563_DateStruct->year % 100))};
|
|
|
|
|
|
if (BM8563_DateStruct->year < 2000) {
|
|
buf[3] = byteToBcd2(BM8563_DateStruct->month) | 0x80;
|
|
} else {
|
|
buf[3] = byteToBcd2(BM8563_DateStruct->month) | 0x00;
|
|
}
|
|
|
|
this->write_register(0x05, buf, 4);
|
|
}
|
|
|
|
void BM8563::WriteReg(uint8_t reg, uint8_t data) {
|
|
this->write_byte(reg, data);
|
|
}
|
|
|
|
uint8_t BM8563::ReadReg(uint8_t reg) {
|
|
uint8_t data;
|
|
this->read_register(reg, &data, 1);
|
|
return data;
|
|
}
|
|
|
|
int BM8563::SetAlarmIRQ(int afterSeconds) {
|
|
uint8_t reg_value = 0;
|
|
reg_value = ReadReg(0x01);
|
|
|
|
if (afterSeconds < 0) {
|
|
reg_value &= ~(1 << 0);
|
|
WriteReg(0x01, reg_value);
|
|
reg_value = 0x03;
|
|
WriteReg(0x0E, reg_value);
|
|
return -1;
|
|
}
|
|
|
|
uint8_t type_value = 2;
|
|
uint8_t div = 1;
|
|
if (afterSeconds > 255) {
|
|
div = 60;
|
|
type_value = 0x83;
|
|
} else {
|
|
type_value = 0x82;
|
|
}
|
|
|
|
afterSeconds = (afterSeconds / div) & 0xFF;
|
|
WriteReg(0x0F, afterSeconds);
|
|
WriteReg(0x0E, type_value);
|
|
|
|
reg_value |= (1 << 0);
|
|
reg_value &= ~(1 << 7);
|
|
WriteReg(0x01, reg_value);
|
|
return afterSeconds * div;
|
|
}
|
|
|
|
int BM8563::SetAlarmIRQ(const BM8563_TimeTypeDef &BM8563_TimeStruct) {
|
|
uint8_t irq_enable = false;
|
|
uint8_t out_buf[4] = {0x80, 0x80, 0x80, 0x80};
|
|
|
|
if (BM8563_TimeStruct.minutes >= 0) {
|
|
irq_enable = true;
|
|
out_buf[0] = byteToBcd2(BM8563_TimeStruct.minutes) & 0x7f;
|
|
}
|
|
|
|
if (BM8563_TimeStruct.hours >= 0) {
|
|
irq_enable = true;
|
|
out_buf[1] = byteToBcd2(BM8563_TimeStruct.hours) & 0x3f;
|
|
}
|
|
|
|
out_buf[2] = 0x00;
|
|
out_buf[3] = 0x00;
|
|
|
|
uint8_t reg_value = ReadReg(0x01);
|
|
|
|
if (irq_enable) {
|
|
reg_value |= (1 << 1);
|
|
} else {
|
|
reg_value &= ~(1 << 1);
|
|
}
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
WriteReg(0x09 + i, out_buf[i]);
|
|
}
|
|
WriteReg(0x01, reg_value);
|
|
|
|
return irq_enable ? 1 : 0;
|
|
}
|
|
|
|
int BM8563::SetAlarmIRQ(const BM8563_DateTypeDef &BM8563_DateStruct, const BM8563_TimeTypeDef &BM8563_TimeStruct) {
|
|
uint8_t irq_enable = false;
|
|
uint8_t out_buf[4] = {0x80, 0x80, 0x80, 0x80};
|
|
|
|
if (BM8563_TimeStruct.minutes >= 0) {
|
|
irq_enable = true;
|
|
out_buf[0] = byteToBcd2(BM8563_TimeStruct.minutes) & 0x7f;
|
|
}
|
|
|
|
if (BM8563_TimeStruct.hours >= 0) {
|
|
irq_enable = true;
|
|
out_buf[1] = byteToBcd2(BM8563_TimeStruct.hours) & 0x3f;
|
|
}
|
|
|
|
if (BM8563_DateStruct.date >= 0) {
|
|
irq_enable = true;
|
|
out_buf[2] = byteToBcd2(BM8563_DateStruct.date) & 0x3f;
|
|
}
|
|
|
|
if (BM8563_DateStruct.weekDay >= 0) {
|
|
irq_enable = true;
|
|
out_buf[3] = byteToBcd2(BM8563_DateStruct.weekDay) & 0x07;
|
|
}
|
|
|
|
uint8_t reg_value = ReadReg(0x01);
|
|
|
|
if (irq_enable) {
|
|
reg_value |= (1 << 1);
|
|
} else {
|
|
reg_value &= ~(1 << 1);
|
|
}
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
WriteReg(0x09 + i, out_buf[i]);
|
|
}
|
|
WriteReg(0x01, reg_value);
|
|
|
|
return irq_enable ? 1 : 0;
|
|
}
|
|
|
|
void BM8563::clearIRQ() {
|
|
uint8_t data = ReadReg(0x01);
|
|
WriteReg(0x01, data & 0xf3);
|
|
}
|
|
|
|
void BM8563::disableIRQ() {
|
|
clearIRQ();
|
|
uint8_t data = ReadReg(0x01);
|
|
WriteReg(0x01, data & 0xfC);
|
|
}
|
|
|
|
} // namespace bm8563
|
|
} // namespace esphome
|