-
Notifications
You must be signed in to change notification settings - Fork 344
/
Copy pathWatchyRTC.cpp
150 lines (138 loc) · 4.69 KB
/
WatchyRTC.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "WatchyRTC.h"
WatchyRTC::WatchyRTC() : rtc_ds(false) {}
void WatchyRTC::init() {
byte error;
Wire.beginTransmission(RTC_DS_ADDR);
error = Wire.endTransmission();
if (error == 0) {
rtcType = DS3231;
} else {
Wire.beginTransmission(RTC_PCF_ADDR);
error = Wire.endTransmission();
if (error == 0) {
rtcType = PCF8563;
} else {
// RTC Error
}
}
}
void WatchyRTC::config(
String datetime) { // String datetime format is YYYY:MM:DD:HH:MM:SS
if (rtcType == DS3231) {
_DSConfig(datetime);
} else {
_PCFConfig(datetime);
}
}
void WatchyRTC::clearAlarm() {
if (rtcType == DS3231) {
rtc_ds.alarm(DS3232RTC::ALARM_2);
} else {
int nextAlarmMinute = 0;
rtc_pcf.clearAlarm(); // resets the alarm flag in the RTC
nextAlarmMinute = rtc_pcf.getMinute();
nextAlarmMinute =
(nextAlarmMinute == 59)
? 0
: (nextAlarmMinute + 1); // set alarm to trigger 1 minute from now
rtc_pcf.setAlarm(nextAlarmMinute, 99, 99, 99);
}
}
void WatchyRTC::read(tmElements_t &tm) {
if (rtcType == DS3231) {
rtc_ds.read(tm);
} else {
rtc_pcf.getDate();
tm.Year = y2kYearToTm(rtc_pcf.getYear());
tm.Month = rtc_pcf.getMonth();
tm.Day = rtc_pcf.getDay();
tm.Wday =
rtc_pcf.getWeekday() + 1; // TimeLib & DS3231 has Wday range of 1-7, but
// PCF8563 stores day of week in 0-6 range
tm.Hour = rtc_pcf.getHour();
tm.Minute = rtc_pcf.getMinute();
tm.Second = rtc_pcf.getSecond();
}
}
void WatchyRTC::set(tmElements_t tm) {
if (rtcType == DS3231) {
time_t t = makeTime(tm);
rtc_ds.set(t);
} else {
time_t t = makeTime(tm); // make and break to calculate tm.Wday
breakTime(t, tm);
// day, weekday, month, century(1=1900, 0=2000), year(0-99)
rtc_pcf.setDate(
tm.Day, tm.Wday - 1, tm.Month, 0,
tmYearToY2k(tm.Year)); // TimeLib & DS3231 has Wday range of 1-7, but
// PCF8563 stores day of week in 0-6 range
// hr, min, sec
rtc_pcf.setTime(tm.Hour, tm.Minute, tm.Second);
clearAlarm();
}
}
uint8_t WatchyRTC::temperature() {
if (rtcType == DS3231) {
return rtc_ds.temperature();
} else {
return 255; // error
}
}
void WatchyRTC::_DSConfig(
String datetime) { // String datetime is YYYY:MM:DD:HH:MM:SS
if (datetime != "") {
tmElements_t tm;
tm.Year = CalendarYrToTm(_getValue(datetime, ':', 0).toInt()); // YYYY -
// 1970
tm.Month = _getValue(datetime, ':', 1).toInt();
tm.Day = _getValue(datetime, ':', 2).toInt();
tm.Hour = _getValue(datetime, ':', 3).toInt();
tm.Minute = _getValue(datetime, ':', 4).toInt();
tm.Second = _getValue(datetime, ':', 5).toInt();
time_t t = makeTime(tm);
rtc_ds.set(t);
}
// https://github.com/JChristensen/DS3232RTC
rtc_ds.squareWave(DS3232RTC::SQWAVE_NONE); // disable square wave output
rtc_ds.setAlarm(DS3232RTC::ALM2_EVERY_MINUTE, 0, 0, 0,
0); // alarm wakes up Watchy every minute
rtc_ds.alarmInterrupt(DS3232RTC::ALARM_2, true); // enable alarm interrupt
}
void WatchyRTC::_PCFConfig(
String datetime) { // String datetime is YYYY:MM:DD:HH:MM:SS
if (datetime != "") {
tmElements_t tm;
tm.Year = CalendarYrToTm(_getValue(datetime, ':', 0).toInt()); // YYYY -
// 1970
tm.Month = _getValue(datetime, ':', 1).toInt();
tm.Day = _getValue(datetime, ':', 2).toInt();
tm.Hour = _getValue(datetime, ':', 3).toInt();
tm.Minute = _getValue(datetime, ':', 4).toInt();
tm.Second = _getValue(datetime, ':', 5).toInt();
time_t t = makeTime(tm); // make and break to calculate tm.Wday
breakTime(t, tm);
// day, weekday, month, century(1=1900, 0=2000), year(0-99)
rtc_pcf.setDate(
tm.Day, tm.Wday - 1, tm.Month, 0,
tmYearToY2k(tm.Year)); // TimeLib & DS3231 has Wday range of 1-7, but
// PCF8563 stores day of week in 0-6 range
// hr, min, sec
rtc_pcf.setTime(tm.Hour, tm.Minute, tm.Second);
}
// on POR event, PCF8563 sets month to 0, which will give an error since
// months are 1-12
clearAlarm();
}
String WatchyRTC::_getValue(String data, char separator, int index) {
int found = 0;
int strIndex[] = {0, -1};
int maxIndex = data.length() - 1;
for (int i = 0; i <= maxIndex && found <= index; i++) {
if (data.charAt(i) == separator || i == maxIndex) {
found++;
strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i + 1 : i;
}
}
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}