Skip to content

Commit 98c2c9b

Browse files
committed
2 parents 1f79e9a + 0bb0f07 commit 98c2c9b

2 files changed

Lines changed: 150 additions & 48 deletions

File tree

src/features/rtc/rtc.cpp

Lines changed: 136 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,33 @@
2626
* @param uint8_t rtcMinute Set the minutes
2727
* @param uint8_t rtcSecond Set the seconds
2828
*/
29-
void RTC::setTime(uint8_t rtcHour, uint8_t rtcMinute, uint8_t rtcSecond)
29+
void RTC::setTime(uint8_t rtcHour, uint8_t rtcMinute, uint8_t rtcSecond, bool isPM)
3030
{
31+
if (_12hMode && rtcHour > 12) // user passed 24h value
32+
{
33+
_isPM = true;
34+
rtcHour = rtcHour - 12;
35+
}
36+
else if (_12hMode && rtcHour == 0) // midnight edge case
37+
{
38+
_isPM = false;
39+
rtcHour = 12;
40+
}
41+
else
42+
{
43+
_isPM = isPM;
44+
}
45+
46+
uint8_t hourBcd = decToBcd(rtcHour);
47+
if (_12hMode && isPM)
48+
hourBcd |= (1 << 5);
49+
3150
Wire.beginTransmission(I2C_ADDR);
3251
Wire.write(RTC_RAM_by);
33-
Wire.write(170); // Write in RAM 170 to know that RTC is set
52+
Wire.write(RTC_SET); // Write in RAM to know that RTC is set
3453
Wire.write(decToBcd(rtcSecond));
3554
Wire.write(decToBcd(rtcMinute));
36-
Wire.write(decToBcd(rtcHour));
55+
Wire.write(hourBcd);
3756
Wire.endTransmission();
3857
}
3958

@@ -51,7 +70,7 @@ void RTC::setDate(uint8_t rtcWeekday, uint8_t rtcDay, uint8_t rtcMonth, uint16_t
5170

5271
Wire.beginTransmission(I2C_ADDR);
5372
Wire.write(RTC_RAM_by);
54-
Wire.write(170); // Write in RAM 170 to know that RTC is set
73+
Wire.write(RTC_SET); // Write in RAM to know that RTC is set
5574
Wire.endTransmission();
5675

5776
Wire.beginTransmission(I2C_ADDR);
@@ -76,7 +95,7 @@ void RTC::setEpoch(uint32_t _epoch)
7695

7796
Wire.beginTransmission(I2C_ADDR);
7897
Wire.write(RTC_RAM_by);
79-
Wire.write(170);
98+
Wire.write(RTC_SET);
8099
Wire.write(decToBcd(_t.tm_sec));
81100
Wire.write(decToBcd(_t.tm_min));
82101
Wire.write(decToBcd(_t.tm_hour));
@@ -94,21 +113,16 @@ void RTC::setEpoch(uint32_t _epoch)
94113
*/
95114
uint32_t RTC::getEpoch()
96115
{
116+
updateTime();
97117
struct tm _t;
98118

99-
Wire.beginTransmission(I2C_ADDR);
100-
Wire.write(RTC_SECOND_ADDR);
101-
Wire.endTransmission();
102-
103-
Wire.requestFrom(I2C_ADDR, 7); // ignore bit 7
104-
_t.tm_sec = bcdToDec(Wire.read() & 0x7F);
105-
_t.tm_min = bcdToDec(Wire.read() & 0x7F);
106-
_t.tm_hour = bcdToDec(Wire.read() & 0x3F);
107-
_t.tm_mday = bcdToDec(Wire.read() & 0x3F);
108-
_t.tm_wday = bcdToDec(Wire.read() & 0x07);
109-
_t.tm_mon = bcdToDec(Wire.read() & 0x1F) - 1;
110-
_t.tm_year = bcdToDec(Wire.read()) + 2000 - 1900;
111-
Wire.endTransmission();
119+
_t.tm_sec = Second;
120+
_t.tm_min = Minute;
121+
_t.tm_hour = _12hMode ? (Hour % 12) + (_isPM ? 12 : 0) : Hour; // convert to 0-23
122+
_t.tm_mday = Day;
123+
_t.tm_wday = Weekday;
124+
_t.tm_mon = Month - 1;
125+
_t.tm_year = Year - 1900;
112126

113127
return (uint32_t)(mktime(&_t));
114128
}
@@ -118,22 +132,7 @@ uint32_t RTC::getEpoch()
118132
*/
119133
void RTC::getRtcData()
120134
{
121-
Wire.beginTransmission(I2C_ADDR);
122-
Wire.write(RTC_SECOND_ADDR); // datasheet 8.4.
123-
Wire.endTransmission();
124-
125-
Wire.requestFrom(I2C_ADDR, 7);
126-
127-
while (Wire.available())
128-
{
129-
Second = bcdToDec(Wire.read() & 0x7F); // ignore bit 7
130-
Minute = bcdToDec(Wire.read() & 0x7F);
131-
Hour = bcdToDec(Wire.read() & 0x3F); // ignore bits 7 & 6
132-
Day = bcdToDec(Wire.read() & 0x3F);
133-
Weekday = bcdToDec(Wire.read() & 0x07); // ignore bits 7,6,5,4 & 3
134-
Month = bcdToDec(Wire.read() & 0x1F); // ignore bits 7,6 & 5
135-
Year = bcdToDec(Wire.read()) + 2000;
136-
}
135+
updateTime();
137136
}
138137

139138
/**
@@ -143,6 +142,7 @@ void RTC::getRtcData()
143142
*/
144143
uint8_t RTC::getSecond()
145144
{
145+
updateTime();
146146
return Second;
147147
}
148148

@@ -153,6 +153,7 @@ uint8_t RTC::getSecond()
153153
*/
154154
uint8_t RTC::getMinute()
155155
{
156+
updateTime();
156157
return Minute;
157158
}
158159

@@ -163,6 +164,7 @@ uint8_t RTC::getMinute()
163164
*/
164165
uint8_t RTC::getHour()
165166
{
167+
updateTime();
166168
return Hour;
167169
}
168170

@@ -173,6 +175,7 @@ uint8_t RTC::getHour()
173175
*/
174176
uint8_t RTC::getDay()
175177
{
178+
updateTime();
176179
return Day;
177180
}
178181

@@ -183,6 +186,7 @@ uint8_t RTC::getDay()
183186
*/
184187
uint8_t RTC::getWeekday()
185188
{
189+
updateTime();
186190
return Weekday;
187191
}
188192

@@ -193,6 +197,7 @@ uint8_t RTC::getWeekday()
193197
*/
194198
uint8_t RTC::getMonth()
195199
{
200+
updateTime();
196201
return Month;
197202
}
198203

@@ -203,9 +208,21 @@ uint8_t RTC::getMonth()
203208
*/
204209
uint16_t RTC::getYear()
205210
{
211+
updateTime();
206212
return Year;
207213
}
208214

215+
/**
216+
* @brief Small user method
217+
*
218+
* @returns uint8_t Returns hour status (AM or PM)
219+
*/
220+
bool RTC::isPM()
221+
{
222+
updateTime();
223+
return _isPM;
224+
}
225+
209226
/**
210227
* @brief Enables the alarm of the RTC
211228
*/
@@ -256,11 +273,28 @@ void RTC::setAlarm(uint8_t AlarmSecond, uint8_t AlarmMinute, uint8_t AlarmHour,
256273
AlarmMinute |= RTC_ALARM;
257274
}
258275

276+
// handle hour format conversion
259277
if (AlarmHour < 99)
260-
{ // rtcHour
261-
AlarmHour = constrain(AlarmHour, 0, 23);
262-
AlarmHour = decToBcd(AlarmHour);
263-
AlarmHour &= ~RTC_ALARM;
278+
{
279+
if (_12hMode && AlarmHour > 12) // user passed 24h value but is using 12h mode
280+
{
281+
AlarmHour = AlarmHour - 12;
282+
AlarmHour = decToBcd(AlarmHour);
283+
AlarmHour |= (1 << 5); // set PM bit
284+
AlarmHour &= ~RTC_ALARM;
285+
}
286+
else if (_12hMode && AlarmHour == 0) // midnight edge case
287+
{
288+
AlarmHour = 12;
289+
AlarmHour = decToBcd(AlarmHour);
290+
AlarmHour &= ~RTC_ALARM; // AM, no PM bit
291+
}
292+
else
293+
{
294+
AlarmHour = constrain(AlarmHour, 0, 23);
295+
AlarmHour = decToBcd(AlarmHour);
296+
AlarmHour &= ~RTC_ALARM;
297+
}
264298
}
265299
else
266300
{
@@ -456,7 +490,7 @@ uint8_t RTC::getAlarmWeekday()
456490
* @param rtcCountdownSrcClock source_clock
457491
* timer clock frequency
458492
*
459-
* @param timer clock frequency
493+
* @param uint8_t value
460494
* value to write in timer register
461495
*
462496
* @param bool int_enable
@@ -598,6 +632,36 @@ void RTC::disableTimer()
598632
Wire.endTransmission();
599633
}
600634

635+
/**
636+
* @brief Toggles RTC time format between 24H and 12H
637+
*
638+
* @returns bool Returns false for 24H format, true for 12H
639+
*/
640+
bool RTC::changeTimeFormat()
641+
{
642+
uint8_t reg;
643+
644+
Wire.beginTransmission(I2C_ADDR);
645+
Wire.write(RTC_CTRL_1);
646+
Wire.endTransmission();
647+
Wire.requestFrom(I2C_ADDR, 1);
648+
reg = Wire.read();
649+
650+
_12hMode = !_12hMode;
651+
652+
if (_12hMode)
653+
reg |= (1 << 3); // set 12_24 bit
654+
else
655+
reg &= ~(1 << 3); // clear 12_24 bit
656+
657+
Wire.beginTransmission(I2C_ADDR);
658+
Wire.write(RTC_CTRL_1);
659+
Wire.write(reg);
660+
Wire.endTransmission();
661+
662+
return _12hMode;
663+
}
664+
601665
/**
602666
* @brief Check if the RTC is already set
603667
*
@@ -612,7 +676,7 @@ bool RTC::isSet()
612676

613677
Wire.requestFrom(I2C_ADDR, 1);
614678
_ramByte = Wire.read();
615-
return ((_ramByte == 170) ? true : false);
679+
return _ramByte == 170;
616680
}
617681

618682
/**
@@ -622,7 +686,7 @@ void RTC::reset() // datasheet 8.2.1.3.
622686
{
623687
Wire.beginTransmission(I2C_ADDR);
624688
Wire.write(RTC_CTRL_1);
625-
Wire.write(0x58);
689+
Wire.write(RTC_CTRL_1_DEFAULT);
626690
Wire.endTransmission();
627691
}
628692

@@ -709,6 +773,37 @@ void RTC::setClockOffset(bool mode, int offsetValue)
709773
Wire.endTransmission();
710774
}
711775

776+
/**
777+
* @brief Reads raw time/date registers from RTC via I2C into member variables
778+
*/
779+
void RTC::updateTime()
780+
{
781+
Wire.beginTransmission(I2C_ADDR);
782+
Wire.write(RTC_SECOND_ADDR);
783+
Wire.endTransmission();
784+
Wire.requestFrom(I2C_ADDR, 7);
785+
786+
Second = bcdToDec(Wire.read() & 0x7F);
787+
Minute = bcdToDec(Wire.read() & 0x7F);
788+
789+
uint8_t hourReg = Wire.read();
790+
if (_12hMode)
791+
{
792+
// bit 5 defines the time format
793+
_isPM = (hourReg >> 5) & 0x01;
794+
Hour = bcdToDec(hourReg & 0x1F);
795+
}
796+
else
797+
{
798+
Hour = bcdToDec(hourReg & 0x3F);
799+
}
800+
801+
Day = bcdToDec(Wire.read() & 0x3F);
802+
Weekday = bcdToDec(Wire.read() & 0x07);
803+
Month = bcdToDec(Wire.read() & 0x1F);
804+
Year = bcdToDec(Wire.read()) + 2000;
805+
}
806+
712807
/**
713808
* @brief Converts decimal to BCD
714809
*

src/features/rtc/rtc.h

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@
2323
#define I2C_ADDR 0x51
2424

2525
// registar overview - crtl & status reg
26-
#define RTC_CTRL_1 0x0
27-
#define RTC_CTRL_2 0x01
28-
#define RTC_OFFSET 0x02
29-
#define RTC_RAM_by 0x03
26+
#define RTC_CTRL_1 0x00
27+
#define RTC_CTRL_1_DEFAULT 0x58
28+
#define RTC_CTRL_2 0x01
29+
#define RTC_OFFSET 0x02
30+
#define RTC_RAM_by 0x03
31+
32+
#define RTC_SET 0xAA
3033
// registar overview - time & data reg
3134
#define RTC_SECOND_ADDR 0x04
3235
#define RTC_MINUTE_ADDR 0x05
@@ -80,7 +83,7 @@ class RTC
8083
TIMER_CLOCK_1PER60HZ = 3
8184
};
8285

83-
void setTime(uint8_t hour, uint8_t minute, uint8_t sec);
86+
void setTime(uint8_t hour, uint8_t minute, uint8_t sec, bool isPM = false);
8487
void setDate(uint8_t weekday, uint8_t day, uint8_t month, uint16_t yr);
8588
void setEpoch(uint32_t _epoch);
8689
uint32_t getEpoch();
@@ -99,7 +102,7 @@ class RTC
99102
void disableTimer();
100103
bool isSet();
101104
void reset();
102-
void setInternalCapacitor(bool);
105+
void setInternalCapacitor(bool val);
103106
void setClockOffset(bool mode, int offsetValue);
104107
/* read RTC times */
105108
uint8_t getSecond();
@@ -109,6 +112,7 @@ class RTC
109112
uint8_t getWeekday();
110113
uint8_t getMonth();
111114
uint16_t getYear();
115+
bool isPM();
112116
/* read alarm times */ // if return = 99, no alarm
113117
uint8_t getAlarmSecond();
114118
uint8_t getAlarmMinute();
@@ -118,8 +122,11 @@ class RTC
118122

119123

120124
private:
125+
void updateTime();
121126
uint8_t decToBcd(uint8_t val);
122127
uint8_t bcdToDec(uint8_t val);
128+
bool _12hMode = false;
129+
bool _isPM = false;
123130
/* alarm */
124131
uint8_t AlarmSecond;
125132
uint8_t AlarmMinute;
@@ -137,4 +144,4 @@ class RTC
137144
uint8_t Month;
138145
uint16_t Year;
139146
};
140-
#endif
147+
#endif

0 commit comments

Comments
 (0)