mirror of https://github.com/arendst/Tasmota.git
Support for BM8563 RTC chip (I2C) found in M5Stack Core2 and M5StickC
This commit is contained in:
parent
90330a5000
commit
c1f82141b9
|
@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
|
||||||
## [9.4.0.4]
|
## [9.4.0.4]
|
||||||
### Added
|
### Added
|
||||||
- Version bump to signal new features to Hass
|
- Version bump to signal new features to Hass
|
||||||
|
- Support for BM8563 RTC chip (I2C) found in M5Stack Core2 and M5StickC
|
||||||
|
|
||||||
## [9.4.0.3] 20210515
|
## [9.4.0.3] 20210515
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -92,3 +92,4 @@ Index | Define | Driver | Device | Address(es) | Description
|
||||||
56 | USE_SEESAW_SOIL | xsns_81 | SEESOIL | 0x36 - 0x39 | Adafruit seesaw soil moisture sensor
|
56 | USE_SEESAW_SOIL | xsns_81 | SEESOIL | 0x36 - 0x39 | Adafruit seesaw soil moisture sensor
|
||||||
57 | USE_TOF10120 | xsns_84 | TOF10120 | 0x52 | Time-of-flight (ToF) distance sensor
|
57 | USE_TOF10120 | xsns_84 | TOF10120 | 0x52 | Time-of-flight (ToF) distance sensor
|
||||||
58 | USE_MPU6886 | xsns_85 | MPU6886 | 0x68 | MPU6886 M5Stack
|
58 | USE_MPU6886 | xsns_85 | MPU6886 | 0x68 | MPU6886 M5Stack
|
||||||
|
59 | USE_BM8563 | xdrv_56 | BM8563 | 0x51 | BM8563 RTC from M5Stack
|
|
@ -0,0 +1,9 @@
|
||||||
|
name=BME8563
|
||||||
|
version=
|
||||||
|
author=
|
||||||
|
maintainer=
|
||||||
|
sentence=Driver for BM8563 RTC
|
||||||
|
paragraph=Driver for BM8563 RTC
|
||||||
|
category=Driver
|
||||||
|
url=
|
||||||
|
architectures=esp8266,esp32
|
|
@ -0,0 +1,352 @@
|
||||||
|
#include "BM8563.h"
|
||||||
|
|
||||||
|
BM8563::BM8563()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void BM8563::begin(void)
|
||||||
|
{
|
||||||
|
WriteReg(0x00,0x00);
|
||||||
|
WriteReg(0x01,0x00);
|
||||||
|
WriteReg(0x0D,0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BM8563::WriteReg(uint8_t reg, uint8_t data)
|
||||||
|
{
|
||||||
|
myWire->beginTransmission(BM8563_ADRESS);
|
||||||
|
myWire->write(reg);
|
||||||
|
myWire->write(data);
|
||||||
|
myWire->endTransmission();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t BM8563::ReadReg(uint8_t reg)
|
||||||
|
{
|
||||||
|
myWire->beginTransmission(BM8563_ADRESS);
|
||||||
|
myWire->write(reg);
|
||||||
|
myWire->endTransmission();
|
||||||
|
myWire->requestFrom(BM8563_ADRESS, 1);
|
||||||
|
return myWire->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BM8563::GetBm8563Time(void)
|
||||||
|
{
|
||||||
|
myWire->beginTransmission(BM8563_ADRESS);
|
||||||
|
myWire->write(0x02);
|
||||||
|
myWire->endTransmission();
|
||||||
|
myWire->requestFrom(BM8563_ADRESS, 7);
|
||||||
|
while (myWire->available())
|
||||||
|
{
|
||||||
|
|
||||||
|
trdata[0] = myWire->read();
|
||||||
|
trdata[1] = myWire->read();
|
||||||
|
trdata[2] = myWire->read();
|
||||||
|
trdata[3] = myWire->read();
|
||||||
|
trdata[4] = myWire->read();
|
||||||
|
trdata[5] = myWire->read();
|
||||||
|
trdata[6] = myWire->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
DataMask();
|
||||||
|
Bcd2asc();
|
||||||
|
Str2Time();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BM8563::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::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::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::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(RTC_TimeTypeDef *RTC_TimeStruct)
|
||||||
|
{
|
||||||
|
|
||||||
|
//if()
|
||||||
|
uint8_t buf[3] = {0};
|
||||||
|
|
||||||
|
myWire->beginTransmission(BM8563_ADRESS);
|
||||||
|
myWire->write(0x02);
|
||||||
|
myWire->endTransmission();
|
||||||
|
myWire->requestFrom(BM8563_ADRESS, 3);
|
||||||
|
|
||||||
|
while (myWire->available())
|
||||||
|
{
|
||||||
|
|
||||||
|
buf[0] = myWire->read();
|
||||||
|
buf[1] = myWire->read();
|
||||||
|
buf[2] = myWire->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
RTC_TimeStruct->Seconds = Bcd2ToByte(buf[0] & 0x7f); //秒
|
||||||
|
RTC_TimeStruct->Minutes = Bcd2ToByte(buf[1] & 0x7f); //分
|
||||||
|
RTC_TimeStruct->Hours = Bcd2ToByte(buf[2] & 0x3f); //时
|
||||||
|
}
|
||||||
|
|
||||||
|
void BM8563::SetTime(RTC_TimeTypeDef *RTC_TimeStruct)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (RTC_TimeStruct == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
myWire->beginTransmission(BM8563_ADRESS);
|
||||||
|
myWire->write(0x02);
|
||||||
|
myWire->write(ByteToBcd2(RTC_TimeStruct->Seconds));
|
||||||
|
myWire->write(ByteToBcd2(RTC_TimeStruct->Minutes));
|
||||||
|
myWire->write(ByteToBcd2(RTC_TimeStruct->Hours));
|
||||||
|
myWire->endTransmission();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BM8563::GetDate(RTC_DateTypeDef *RTC_DateStruct)
|
||||||
|
{
|
||||||
|
|
||||||
|
uint8_t buf[4] = {0};
|
||||||
|
|
||||||
|
myWire->beginTransmission(BM8563_ADRESS);
|
||||||
|
myWire->write(0x05);
|
||||||
|
myWire->endTransmission();
|
||||||
|
myWire->requestFrom(BM8563_ADRESS, 4);
|
||||||
|
|
||||||
|
while (myWire->available())
|
||||||
|
{
|
||||||
|
|
||||||
|
buf[0] = myWire->read();
|
||||||
|
buf[1] = myWire->read();
|
||||||
|
buf[2] = myWire->read();
|
||||||
|
buf[3] = myWire->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::SetDate(RTC_DateTypeDef *RTC_DateStruct)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (RTC_DateStruct == NULL)
|
||||||
|
return;
|
||||||
|
myWire->beginTransmission(BM8563_ADRESS);
|
||||||
|
myWire->write(0x05);
|
||||||
|
myWire->write(ByteToBcd2(RTC_DateStruct->Date));
|
||||||
|
myWire->write(ByteToBcd2(RTC_DateStruct->WeekDay));
|
||||||
|
|
||||||
|
if (RTC_DateStruct->Year < 2000)
|
||||||
|
{
|
||||||
|
|
||||||
|
myWire->write(ByteToBcd2(RTC_DateStruct->Month) | 0x80);
|
||||||
|
myWire->write(ByteToBcd2((uint8_t)(RTC_DateStruct->Year % 100)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* code */
|
||||||
|
myWire->write(ByteToBcd2(RTC_DateStruct->Month) | 0x00);
|
||||||
|
myWire->write(ByteToBcd2((uint8_t)(RTC_DateStruct->Year % 100)));
|
||||||
|
}
|
||||||
|
|
||||||
|
myWire->endTransmission();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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::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::clearIRQ()
|
||||||
|
{
|
||||||
|
uint8_t data = ReadReg(0x01);
|
||||||
|
WriteReg(0x01, data & 0xf3);
|
||||||
|
}
|
||||||
|
void BM8563::disableIRQ()
|
||||||
|
{
|
||||||
|
clearIRQ();
|
||||||
|
uint8_t data = ReadReg(0x01);
|
||||||
|
WriteReg(0x01, data & 0xfC);
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
#ifndef __MB8563_H__
|
||||||
|
#define __MB8563_H__
|
||||||
|
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
#define BM8563_ADRESS 0x51
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t Hours;
|
||||||
|
uint8_t Minutes;
|
||||||
|
uint8_t Seconds;
|
||||||
|
}RTC_TimeTypeDef;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t WeekDay;
|
||||||
|
uint8_t Month;
|
||||||
|
uint8_t Date;
|
||||||
|
uint16_t Year;
|
||||||
|
}RTC_DateTypeDef;
|
||||||
|
|
||||||
|
class BM8563 {
|
||||||
|
public:
|
||||||
|
BM8563();
|
||||||
|
#ifdef ESP32
|
||||||
|
void setBus(uint32_t _bus) { myWire = _bus ? &Wire1 : &Wire; };
|
||||||
|
#else
|
||||||
|
void setBus(uint32_t _bus) { myWire = &Wire; };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void begin(void);
|
||||||
|
void GetBm8563Time(void);
|
||||||
|
|
||||||
|
void SetTime(RTC_TimeTypeDef* RTC_TimeStruct);
|
||||||
|
void SetDate(RTC_DateTypeDef* RTC_DateStruct);
|
||||||
|
|
||||||
|
void GetTime(RTC_TimeTypeDef* RTC_TimeStruct);
|
||||||
|
void GetDate(RTC_DateTypeDef* RTC_DateStruct);
|
||||||
|
|
||||||
|
int SetAlarmIRQ(int afterSeconds);
|
||||||
|
int SetAlarmIRQ( const RTC_TimeTypeDef &RTC_TimeStruct);
|
||||||
|
int SetAlarmIRQ( const RTC_DateTypeDef &RTC_DateStruct, const RTC_TimeTypeDef &RTC_TimeStruct);
|
||||||
|
|
||||||
|
void clearIRQ();
|
||||||
|
void disableIRQ();
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint8_t Second;
|
||||||
|
uint8_t Minute;
|
||||||
|
uint8_t Hour;
|
||||||
|
uint8_t Week;
|
||||||
|
uint8_t Day;
|
||||||
|
uint8_t Month;
|
||||||
|
uint8_t Year;
|
||||||
|
uint8_t DateString[9];
|
||||||
|
uint8_t TimeString[9];
|
||||||
|
|
||||||
|
uint8_t asc[14];
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
TwoWire * myWire = &Wire; // default to Wire (bus 0)
|
||||||
|
void Bcd2asc(void);
|
||||||
|
void DataMask();
|
||||||
|
void Str2Time(void);
|
||||||
|
void WriteReg(uint8_t reg, uint8_t data);
|
||||||
|
uint8_t ReadReg(uint8_t reg);
|
||||||
|
uint8_t Bcd2ToByte(uint8_t Value);
|
||||||
|
uint8_t ByteToBcd2(uint8_t Value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/*Define an array to store the time data read */
|
||||||
|
uint8_t trdata[7];
|
||||||
|
/* Define an array to store the converted asc code time data */
|
||||||
|
//uint8_t asc[14];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __MB8563_H__
|
|
@ -628,7 +628,8 @@
|
||||||
// #define USE_EZORGB // [I2cDriver55] Enable support for EZO's RGB sensor (+0k5 code) - Shared EZO code required for any EZO device (+1k2 code)
|
// #define USE_EZORGB // [I2cDriver55] Enable support for EZO's RGB sensor (+0k5 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||||
// #define USE_EZOPMP // [I2cDriver55] Enable support for EZO's PMP sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code)
|
// #define USE_EZOPMP // [I2cDriver55] Enable support for EZO's PMP sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||||
// #define USE_SEESAW_SOIL // [I2cDriver56] Enable Capacitice Soil Moisture & Temperature Sensor (I2C addresses 0x36 - 0x39) (+1k3 code)
|
// #define USE_SEESAW_SOIL // [I2cDriver56] Enable Capacitice Soil Moisture & Temperature Sensor (I2C addresses 0x36 - 0x39) (+1k3 code)
|
||||||
// #define USE_MPU6886 // [I2cDriver58] Enable MPU6886 - found in M5Stack - support 2 I2C buses on ESP32 (I2C address 0x68) (+2k code)
|
// #define USE_MPU6886 // [I2cDriver58] Enable MPU6886 - found in M5Stack - support both I2C buses on ESP32 (I2C address 0x68) (+2k code)
|
||||||
|
// #define USE_BM8563 // [I2cDriver58] Enable BM8563 RTC - found in M5Stack - support both I2C buses on ESP32 (I2C address 0x51) (+2.5k code)
|
||||||
|
|
||||||
// #define USE_DISPLAY // Add I2C Display Support (+2k code)
|
// #define USE_DISPLAY // Add I2C Display Support (+2k code)
|
||||||
#define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0
|
#define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
xdrv_52_9_berry.ino - Berry scripting language
|
||||||
|
|
||||||
|
Copyright (C) 2021 Stephan Hadinger, Berry language by Guan Wenliang https://github.com/Skiars/berry
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_I2C
|
||||||
|
#ifdef USE_BM8563
|
||||||
|
|
||||||
|
#define XDRV_56 56
|
||||||
|
#define XI2C_59 59 // See I2CDEVICES.md
|
||||||
|
|
||||||
|
#include "BM8563.h"
|
||||||
|
|
||||||
|
struct {
|
||||||
|
BM8563 Rtc;
|
||||||
|
bool rtc_ready = false;
|
||||||
|
bool ntp_time_ok = false;
|
||||||
|
} bm8563_driver;
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
*
|
||||||
|
*
|
||||||
|
\*********************************************************************************************/
|
||||||
|
void BM8563Detect(void) {
|
||||||
|
#ifdef ESP32
|
||||||
|
if (!I2cSetDevice(BM8563_ADRESS, 0)) {
|
||||||
|
if (!I2cSetDevice(BM8563_ADRESS, 1)) { return; } // check on bus 1
|
||||||
|
bm8563_driver.Rtc.setBus(1); // switch to bus 1
|
||||||
|
I2cSetActiveFound(BM8563_ADRESS, "BM8563", 1);
|
||||||
|
} else {
|
||||||
|
I2cSetActiveFound(BM8563_ADRESS, "BM8563", 0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!I2cSetDevice(BM8563_ADRESS)) { return; }
|
||||||
|
I2cSetActiveFound(BM8563_ADRESS, "BM8563");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bm8563_driver.Rtc.begin();
|
||||||
|
bm8563_driver.rtc_ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t BM8563GetUtc(void) {
|
||||||
|
if (!bm8563_driver.rtc_ready) return 0;
|
||||||
|
RTC_TimeTypeDef RTCtime;
|
||||||
|
// 1. read has errors ???
|
||||||
|
bm8563_driver.Rtc.GetTime(&RTCtime);
|
||||||
|
// core2_globs.Rtc.GetTime(&RTCtime);
|
||||||
|
RTC_DateTypeDef RTCdate;
|
||||||
|
bm8563_driver.Rtc.GetDate(&RTCdate);
|
||||||
|
TIME_T tm;
|
||||||
|
tm.second = RTCtime.Seconds;
|
||||||
|
tm.minute = RTCtime.Minutes;
|
||||||
|
tm.hour = RTCtime.Hours;
|
||||||
|
tm.day_of_week = RTCdate.WeekDay;
|
||||||
|
tm.day_of_month = RTCdate.Date;
|
||||||
|
tm.month = RTCdate.Month;
|
||||||
|
tm.year = RTCdate.Year - 1970;
|
||||||
|
return MakeTime(tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BM8563SetUtc(uint32_t epoch_time) {
|
||||||
|
if (!bm8563_driver.rtc_ready) return;
|
||||||
|
TIME_T tm;
|
||||||
|
BreakTime(epoch_time, tm);
|
||||||
|
RTC_TimeTypeDef RTCtime;
|
||||||
|
RTCtime.Hours = tm.hour;
|
||||||
|
RTCtime.Minutes = tm.minute;
|
||||||
|
RTCtime.Seconds = tm.second;
|
||||||
|
bm8563_driver.Rtc.SetTime(&RTCtime);
|
||||||
|
RTC_DateTypeDef RTCdate;
|
||||||
|
RTCdate.WeekDay = tm.day_of_week;
|
||||||
|
RTCdate.Month = tm.month;
|
||||||
|
RTCdate.Date = tm.day_of_month;
|
||||||
|
RTCdate.Year = tm.year + 1970;
|
||||||
|
bm8563_driver.Rtc.SetDate(&RTCdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitTimeFromRTC(void) {
|
||||||
|
if (bm8563_driver.rtc_ready && Rtc.utc_time < START_VALID_TIME) {
|
||||||
|
// set rtc from chip
|
||||||
|
Rtc.utc_time = BM8563GetUtc();
|
||||||
|
|
||||||
|
TIME_T tmpTime;
|
||||||
|
TasmotaGlobal.ntp_force_sync = true; // Force to sync with ntp
|
||||||
|
BreakTime(Rtc.utc_time, tmpTime);
|
||||||
|
Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year);
|
||||||
|
Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year);
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("I2C: Set time from BM8563 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"),
|
||||||
|
GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str());
|
||||||
|
if (Rtc.local_time < START_VALID_TIME) { // 2016-01-01
|
||||||
|
TasmotaGlobal.rules_flag.time_init = 1;
|
||||||
|
} else {
|
||||||
|
TasmotaGlobal.rules_flag.time_set = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BM8563EverySecond(void) {
|
||||||
|
if (bm8563_driver.rtc_ready) {
|
||||||
|
if (!bm8563_driver.ntp_time_ok && Rtc.utc_time > START_VALID_TIME && abs(Rtc.utc_time - BM8563GetUtc()) > 3) {
|
||||||
|
BM8563SetUtc(Rtc.utc_time);
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("I2C: Write Time TO BM8563 from NTP (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"),
|
||||||
|
GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str());
|
||||||
|
bm8563_driver.ntp_time_ok = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
bool Xdrv56(uint8_t function)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
if (!I2cEnabled(XI2C_59)) { return false; }
|
||||||
|
|
||||||
|
switch (function) {
|
||||||
|
// case FUNC_PRE_INIT: // we start Berry in pre_init so that other modules can call Berry in their init methods
|
||||||
|
case FUNC_INIT:
|
||||||
|
BM8563Detect();
|
||||||
|
InitTimeFromRTC();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FUNC_EVERY_SECOND:
|
||||||
|
BM8563EverySecond();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FUNC_SAVE_BEFORE_RESTART:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_BM8563
|
||||||
|
#endif // USE_I2C
|
Loading…
Reference in New Issue