Tasmota/lib/libesp32/CORE2_Library/BM8563_RTC.cpp

354 lines
7.5 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}
//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_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);
}