Files
2024-05-23 21:24:52 +02:00

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