Tasmota/lib/libesp32/CORE2_Library/BM8563_RTC.cpp

354 lines
7.5 KiB
C++
Raw Normal View History

2020-12-18 09:35:14 +00:00
#include "BM8563_RTC.h"
BM8563_RTC::BM8563_RTC()
{
}
void BM8563_RTC::begin(void)
{
Wire1.begin(21, 22);
WriteReg(0x00,0x00);
WriteReg(0x01,0x00);
WriteReg(0x0D,0x00);
}
void BM8563_RTC::WriteReg(uint8_t reg, uint8_t data)
{
Wire1.beginTransmission(RTC_ADRESS);
Wire1.write(reg);
Wire1.write(data);
Wire1.endTransmission();
}
uint8_t BM8563_RTC::ReadReg(uint8_t reg)
{
Wire1.beginTransmission(0x51);
Wire1.write(reg);
Wire1.endTransmission();
Wire1.requestFrom(0x51, 1);
return Wire1.read();
}
void BM8563_RTC::GetBm8563Time(void)
{
Wire1.beginTransmission(0x51);
Wire1.write(0x02);
Wire1.endTransmission();
Wire1.requestFrom(0x51, 7);
while (Wire1.available())
{
trdata[0] = Wire1.read();
trdata[1] = Wire1.read();
trdata[2] = Wire1.read();
trdata[3] = Wire1.read();
trdata[4] = Wire1.read();
trdata[5] = Wire1.read();
trdata[6] = Wire1.read();
}
DataMask();
Bcd2asc();
Str2Time();
}
void BM8563_RTC::Str2Time(void)
{
Second = (asc[0] - 0x30) * 10 + asc[1] - 0x30;
Minute = (asc[2] - 0x30) * 10 + asc[3] - 0x30;
Hour = (asc[4] - 0x30) * 10 + asc[5] - 0x30;
/*
uint8_t Hour;
uint8_t Week;
uint8_t Day;
uint8_t Month;
uint8_t Year;
*/
}
void BM8563_RTC::DataMask()
{
trdata[0] = trdata[0] & 0x7f; //秒
trdata[1] = trdata[1] & 0x7f; //分
trdata[2] = trdata[2] & 0x3f; //时
trdata[3] = trdata[3] & 0x3f; //日
trdata[4] = trdata[4] & 0x07; //星期
trdata[5] = trdata[5] & 0x1f; //月
trdata[6] = trdata[6] & 0xff; //年
}
/********************************************************************
void Bcd2asc(void)
bcd asc Lcd显示用
***********************************************************************/
void BM8563_RTC::Bcd2asc(void)
{
uint8_t i, j;
for (j = 0, i = 0; i < 7; i++)
{
asc[j++] = (trdata[i] & 0xf0) >> 4 | 0x30; /*格式为: 秒 分 时 日 月 星期 年 */
asc[j++] = (trdata[i] & 0x0f) | 0x30;
}
}
uint8_t BM8563_RTC::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_RTC::ByteToBcd2(uint8_t Value)
{
uint8_t bcdhigh = 0;
while (Value >= 10)
{
bcdhigh++;
Value -= 10;
}
return ((uint8_t)(bcdhigh << 4) | Value);
}
void BM8563_RTC::GetTime(RTC_TimeTypeDef *RTC_TimeStruct)
{
//if()
uint8_t buf[3] = {0};
Wire1.beginTransmission(0x51);
Wire1.write(0x02);
Wire1.endTransmission();
Wire1.requestFrom(0x51, 3);
while (Wire1.available())
{
buf[0] = Wire1.read();
buf[1] = Wire1.read();
buf[2] = Wire1.read();
}
RTC_TimeStruct->Seconds = Bcd2ToByte(buf[0] & 0x7f); //秒
RTC_TimeStruct->Minutes = Bcd2ToByte(buf[1] & 0x7f); //分
RTC_TimeStruct->Hours = Bcd2ToByte(buf[2] & 0x3f); //时
}
void BM8563_RTC::SetTime(RTC_TimeTypeDef *RTC_TimeStruct)
{
if (RTC_TimeStruct == NULL)
return;
Wire1.beginTransmission(0x51);
Wire1.write(0x02);
Wire1.write(ByteToBcd2(RTC_TimeStruct->Seconds));
Wire1.write(ByteToBcd2(RTC_TimeStruct->Minutes));
Wire1.write(ByteToBcd2(RTC_TimeStruct->Hours));
Wire1.endTransmission();
}
void BM8563_RTC::GetDate(RTC_DateTypeDef *RTC_DateStruct)
{
uint8_t buf[4] = {0};
Wire1.beginTransmission(0x51);
Wire1.write(0x05);
Wire1.endTransmission();
Wire1.requestFrom(0x51, 4);
while (Wire1.available())
{
buf[0] = Wire1.read();
buf[1] = Wire1.read();
buf[2] = Wire1.read();
buf[3] = Wire1.read();
}
RTC_DateStruct->Date = Bcd2ToByte(buf[0] & 0x3f);
RTC_DateStruct->WeekDay = Bcd2ToByte(buf[1] & 0x07);
RTC_DateStruct->Month = Bcd2ToByte(buf[2] & 0x1f);
if (buf[2] & 0x80)
{
RTC_DateStruct->Year = 1900 + Bcd2ToByte(buf[3] & 0xff);
}
else
{
RTC_DateStruct->Year = 2000 + Bcd2ToByte(buf[3] & 0xff);
}
}
void BM8563_RTC::SetDate(RTC_DateTypeDef *RTC_DateStruct)
{
if (RTC_DateStruct == NULL)
return;
Wire1.beginTransmission(0x51);
Wire1.write(0x05);
Wire1.write(ByteToBcd2(RTC_DateStruct->Date));
Wire1.write(ByteToBcd2(RTC_DateStruct->WeekDay));
if (RTC_DateStruct->Year < 2000)
{
Wire1.write(ByteToBcd2(RTC_DateStruct->Month) | 0x80);
Wire1.write(ByteToBcd2((uint8_t)(RTC_DateStruct->Year % 100)));
}
else
{
/* code */
Wire1.write(ByteToBcd2(RTC_DateStruct->Month) | 0x00);
Wire1.write(ByteToBcd2((uint8_t)(RTC_DateStruct->Year % 100)));
}
Wire1.endTransmission();
}
int BM8563_RTC::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_RTC::SetAlarmIRQ(const RTC_TimeTypeDef &RTC_TimeStruct)
{
uint8_t irq_enable = false;
uint8_t out_buf[4] = {0x80, 0x80, 0x80, 0x80};
if (RTC_TimeStruct.Minutes >= 0)
{
irq_enable = true;
out_buf[0] = ByteToBcd2(RTC_TimeStruct.Minutes) & 0x7f;
}
if (RTC_TimeStruct.Hours >= 0)
{
irq_enable = true;
out_buf[1] = ByteToBcd2(RTC_TimeStruct.Hours) & 0x3f;
}
2020-12-26 08:44:01 +00:00
//out_buf[2] = 0x00;
//out_buf[3] = 0x00;
2020-12-18 09:35:14 +00:00
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_RTC::SetAlarmIRQ(const RTC_DateTypeDef &RTC_DateStruct, const RTC_TimeTypeDef &RTC_TimeStruct)
{
uint8_t irq_enable = false;
uint8_t out_buf[4] = {0x80, 0x80, 0x80, 0x80};
if (RTC_TimeStruct.Minutes >= 0)
{
irq_enable = true;
out_buf[0] = ByteToBcd2(RTC_TimeStruct.Minutes) & 0x7f;
}
if (RTC_TimeStruct.Hours >= 0)
{
irq_enable = true;
out_buf[1] = ByteToBcd2(RTC_TimeStruct.Hours) & 0x3f;
}
if (RTC_DateStruct.Date >= 0)
{
irq_enable = true;
out_buf[2] = ByteToBcd2(RTC_DateStruct.Date) & 0x3f;
}
if (RTC_DateStruct.WeekDay >= 0)
{
irq_enable = true;
out_buf[3] = ByteToBcd2(RTC_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_RTC::clearIRQ()
{
uint8_t data = ReadReg(0x01);
WriteReg(0x01, data & 0xf3);
}
void BM8563_RTC::disableIRQ()
{
clearIRQ();
uint8_t data = ReadReg(0x01);
WriteReg(0x01, data & 0xfC);
}