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,22 +113,17 @@ void RTC::setEpoch(uint32_t _epoch)
94113 */
95114uint32_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 ();
112-
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 ;
126+
113127 return (uint32_t )(mktime (&_t));
114128}
115129
@@ -118,22 +132,7 @@ uint32_t RTC::getEpoch()
118132 */
119133void 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 */
144143uint8_t RTC::getSecond ()
145144{
145+ updateTime ();
146146 return Second;
147147}
148148
@@ -153,6 +153,7 @@ uint8_t RTC::getSecond()
153153 */
154154uint8_t RTC::getMinute ()
155155{
156+ updateTime ();
156157 return Minute;
157158}
158159
@@ -163,6 +164,7 @@ uint8_t RTC::getMinute()
163164 */
164165uint8_t RTC::getHour ()
165166{
167+ updateTime ();
166168 return Hour;
167169}
168170
@@ -173,6 +175,7 @@ uint8_t RTC::getHour()
173175 */
174176uint8_t RTC::getDay ()
175177{
178+ updateTime ();
176179 return Day;
177180}
178181
@@ -183,6 +186,7 @@ uint8_t RTC::getDay()
183186 */
184187uint8_t RTC::getWeekday ()
185188{
189+ updateTime ();
186190 return Weekday;
187191}
188192
@@ -193,6 +197,7 @@ uint8_t RTC::getWeekday()
193197 */
194198uint8_t RTC::getMonth ()
195199{
200+ updateTime ();
196201 return Month;
197202}
198203
@@ -203,9 +208,21 @@ uint8_t RTC::getMonth()
203208 */
204209uint16_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 *
0 commit comments