RTClib.cpp 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804
  1. /**************************************************************************/
  2. /*!
  3. @file RTClib.cpp
  4. @mainpage Adafruit RTClib
  5. @section intro Introduction
  6. This is a fork of JeeLab's fantastic real time clock library for Arduino.
  7. For details on using this library with an RTC module like the DS1307, PCF8523,
  8. or DS3231, see the guide at:
  9. https://learn.adafruit.com/ds1307-real-time-clock-breakout-board-kit/overview
  10. Adafruit invests time and resources providing this open source code,
  11. please support Adafruit and open-source hardware by purchasing
  12. products from Adafruit!
  13. @section classes Available classes
  14. This library provides the following classes:
  15. - Classes for manipulating dates, times and durations:
  16. - DateTime represents a specific point in time; this is the data
  17. type used for setting and reading the supported RTCs
  18. - TimeSpan represents the length of a time interval
  19. - Interfacing specific RTC chips:
  20. - RTC_DS1307
  21. - RTC_DS3231
  22. - RTC_PCF8523
  23. - RTC emulated in software; do not expect much accuracy out of these:
  24. - RTC_Millis is based on `millis()`
  25. - RTC_Micros is based on `micros()`; its drift rate can be tuned by
  26. the user
  27. @section license License
  28. Original library by JeeLabs https://jeelabs.org/pub/docs/rtclib/, released to
  29. the public domain.
  30. This version: MIT (see LICENSE)
  31. */
  32. /**************************************************************************/
  33. #ifdef __AVR_ATtiny85__
  34. #include <TinyWireM.h>
  35. #define Wire TinyWireM
  36. #else
  37. #include <Wire.h>
  38. #endif
  39. #include "RTClib.h"
  40. #ifdef __AVR__
  41. #include <avr/pgmspace.h>
  42. #elif defined(ESP8266)
  43. #include <pgmspace.h>
  44. #elif defined(ARDUINO_ARCH_SAMD)
  45. // nothing special needed
  46. #elif defined(ARDUINO_SAM_DUE)
  47. #define PROGMEM
  48. #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
  49. #define Wire Wire1
  50. #endif
  51. #if (ARDUINO >= 100)
  52. #include <Arduino.h> // capital A so it is error prone on case-sensitive filesystems
  53. // Macro to deal with the difference in I2C write functions from old and new
  54. // Arduino versions.
  55. #define _I2C_WRITE write ///< Modern I2C write
  56. #define _I2C_READ read ///< Modern I2C read
  57. #else
  58. #include <WProgram.h>
  59. #define _I2C_WRITE send ///< Legacy I2C write
  60. #define _I2C_READ receive ///< legacy I2C read
  61. #endif
  62. /**************************************************************************/
  63. /*!
  64. @brief Read a byte from an I2C register
  65. @param addr I2C address
  66. @param reg Register address
  67. @return Register value
  68. */
  69. /**************************************************************************/
  70. static uint8_t read_i2c_register(uint8_t addr, uint8_t reg) {
  71. Wire.beginTransmission(addr);
  72. Wire._I2C_WRITE((byte)reg);
  73. Wire.endTransmission();
  74. Wire.requestFrom(addr, (byte)1);
  75. return Wire._I2C_READ();
  76. }
  77. /**************************************************************************/
  78. /*!
  79. @brief Write a byte to an I2C register
  80. @param addr I2C address
  81. @param reg Register address
  82. @param val Value to write
  83. */
  84. /**************************************************************************/
  85. static void write_i2c_register(uint8_t addr, uint8_t reg, uint8_t val) {
  86. Wire.beginTransmission(addr);
  87. Wire._I2C_WRITE((byte)reg);
  88. Wire._I2C_WRITE((byte)val);
  89. Wire.endTransmission();
  90. }
  91. /**************************************************************************/
  92. // utility code, some of this could be exposed in the DateTime API if needed
  93. /**************************************************************************/
  94. /**
  95. Number of days in each month, from January to November. December is not
  96. needed. Omitting it avoids an incompatibility with Paul Stoffregen's Time
  97. library. C.f. https://github.com/adafruit/RTClib/issues/114
  98. */
  99. const uint8_t daysInMonth[] PROGMEM = {31, 28, 31, 30, 31, 30,
  100. 31, 31, 30, 31, 30};
  101. /**************************************************************************/
  102. /*!
  103. @brief Given a date, return number of days since 2000/01/01,
  104. valid for 2000--2099
  105. @param y Year
  106. @param m Month
  107. @param d Day
  108. @return Number of days
  109. */
  110. /**************************************************************************/
  111. static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) {
  112. if (y >= 2000)
  113. y -= 2000;
  114. uint16_t days = d;
  115. for (uint8_t i = 1; i < m; ++i)
  116. days += pgm_read_byte(daysInMonth + i - 1);
  117. if (m > 2 && y % 4 == 0)
  118. ++days;
  119. return days + 365 * y + (y + 3) / 4 - 1;
  120. }
  121. /**************************************************************************/
  122. /*!
  123. @brief Given a number of days, hours, minutes, and seconds, return the
  124. total seconds
  125. @param days Days
  126. @param h Hours
  127. @param m Minutes
  128. @param s Seconds
  129. @return Number of seconds total
  130. */
  131. /**************************************************************************/
  132. static uint32_t time2ulong(uint16_t days, uint8_t h, uint8_t m, uint8_t s) {
  133. return ((days * 24UL + h) * 60 + m) * 60 + s;
  134. }
  135. /**************************************************************************/
  136. /*!
  137. @brief Constructor from
  138. [Unix time](https://en.wikipedia.org/wiki/Unix_time).
  139. This builds a DateTime from an integer specifying the number of seconds
  140. elapsed since the epoch: 1970-01-01 00:00:00. This number is analogous
  141. to Unix time, with two small differences:
  142. - The Unix epoch is specified to be at 00:00:00
  143. [UTC](https://en.wikipedia.org/wiki/Coordinated_Universal_Time),
  144. whereas this class has no notion of time zones. The epoch used in
  145. this class is then at 00:00:00 on whatever time zone the user chooses
  146. to use, ignoring changes in DST.
  147. - Unix time is conventionally represented with signed numbers, whereas
  148. this constructor takes an unsigned argument. Because of this, it does
  149. _not_ suffer from the
  150. [year 2038 problem](https://en.wikipedia.org/wiki/Year_2038_problem).
  151. If called without argument, it returns the earliest time representable
  152. by this class: 2000-01-01 00:00:00.
  153. @see The `unixtime()` method is the converse of this constructor.
  154. @param t Time elapsed in seconds since 1970-01-01 00:00:00.
  155. */
  156. /**************************************************************************/
  157. DateTime::DateTime(uint32_t t) {
  158. t -= SECONDS_FROM_1970_TO_2000; // bring to 2000 timestamp from 1970
  159. ss = t % 60;
  160. t /= 60;
  161. mm = t % 60;
  162. t /= 60;
  163. hh = t % 24;
  164. uint16_t days = t / 24;
  165. uint8_t leap;
  166. for (yOff = 0;; ++yOff) {
  167. leap = yOff % 4 == 0;
  168. if (days < 365U + leap)
  169. break;
  170. days -= 365 + leap;
  171. }
  172. for (m = 1; m < 12; ++m) {
  173. uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1);
  174. if (leap && m == 2)
  175. ++daysPerMonth;
  176. if (days < daysPerMonth)
  177. break;
  178. days -= daysPerMonth;
  179. }
  180. d = days + 1;
  181. }
  182. /**************************************************************************/
  183. /*!
  184. @brief Constructor from (year, month, day, hour, minute, second).
  185. @warning If the provided parameters are not valid (e.g. 31 February),
  186. the constructed DateTime will be invalid.
  187. @see The `isValid()` method can be used to test whether the
  188. constructed DateTime is valid.
  189. @param year Either the full year (range: 2000--2099) or the offset from
  190. year 2000 (range: 0--99).
  191. @param month Month number (1--12).
  192. @param day Day of the month (1--31).
  193. @param hour,min,sec Hour (0--23), minute (0--59) and second (0--59).
  194. */
  195. /**************************************************************************/
  196. DateTime::DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour,
  197. uint8_t min, uint8_t sec) {
  198. if (year >= 2000)
  199. year -= 2000;
  200. yOff = year;
  201. m = month;
  202. d = day;
  203. hh = hour;
  204. mm = min;
  205. ss = sec;
  206. }
  207. /**************************************************************************/
  208. /*!
  209. @brief Copy constructor.
  210. @param copy DateTime to copy.
  211. */
  212. /**************************************************************************/
  213. DateTime::DateTime(const DateTime &copy)
  214. : yOff(copy.yOff), m(copy.m), d(copy.d), hh(copy.hh), mm(copy.mm),
  215. ss(copy.ss) {}
  216. /**************************************************************************/
  217. /*!
  218. @brief Convert a string containing two digits to uint8_t, e.g. "09" returns
  219. 9
  220. @param p Pointer to a string containing two digits
  221. */
  222. /**************************************************************************/
  223. static uint8_t conv2d(const char *p) {
  224. uint8_t v = 0;
  225. if ('0' <= *p && *p <= '9')
  226. v = *p - '0';
  227. return 10 * v + *++p - '0';
  228. }
  229. /**************************************************************************/
  230. /*!
  231. @brief Constructor for generating the build time.
  232. This constructor expects its parameters to be strings in the format
  233. generated by the compiler's preprocessor macros `__DATE__` and
  234. `__TIME__`. Usage:
  235. ```
  236. DateTime buildTime(__DATE__, __TIME__);
  237. ```
  238. @note The `F()` macro can be used to reduce the RAM footprint, see
  239. the next constructor.
  240. @param date Date string, e.g. "Apr 16 2020".
  241. @param time Time string, e.g. "18:34:56".
  242. */
  243. /**************************************************************************/
  244. DateTime::DateTime(const char *date, const char *time) {
  245. yOff = conv2d(date + 9);
  246. // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
  247. switch (date[0]) {
  248. case 'J':
  249. m = (date[1] == 'a') ? 1 : ((date[2] == 'n') ? 6 : 7);
  250. break;
  251. case 'F':
  252. m = 2;
  253. break;
  254. case 'A':
  255. m = date[2] == 'r' ? 4 : 8;
  256. break;
  257. case 'M':
  258. m = date[2] == 'r' ? 3 : 5;
  259. break;
  260. case 'S':
  261. m = 9;
  262. break;
  263. case 'O':
  264. m = 10;
  265. break;
  266. case 'N':
  267. m = 11;
  268. break;
  269. case 'D':
  270. m = 12;
  271. break;
  272. }
  273. d = conv2d(date + 4);
  274. hh = conv2d(time);
  275. mm = conv2d(time + 3);
  276. ss = conv2d(time + 6);
  277. }
  278. /**************************************************************************/
  279. /*!
  280. @brief Memory friendly constructor for generating the build time.
  281. This version is intended to save RAM by keeping the date and time
  282. strings in program memory. Use it with the `F()` macro:
  283. ```
  284. DateTime buildTime(F(__DATE__), F(__TIME__));
  285. ```
  286. @param date Date PROGMEM string, e.g. F("Apr 16 2020").
  287. @param time Time PROGMEM string, e.g. F("18:34:56").
  288. */
  289. /**************************************************************************/
  290. DateTime::DateTime(const __FlashStringHelper *date,
  291. const __FlashStringHelper *time) {
  292. char buff[11];
  293. memcpy_P(buff, date, 11);
  294. yOff = conv2d(buff + 9);
  295. // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
  296. switch (buff[0]) {
  297. case 'J':
  298. m = (buff[1] == 'a') ? 1 : ((buff[2] == 'n') ? 6 : 7);
  299. break;
  300. case 'F':
  301. m = 2;
  302. break;
  303. case 'A':
  304. m = buff[2] == 'r' ? 4 : 8;
  305. break;
  306. case 'M':
  307. m = buff[2] == 'r' ? 3 : 5;
  308. break;
  309. case 'S':
  310. m = 9;
  311. break;
  312. case 'O':
  313. m = 10;
  314. break;
  315. case 'N':
  316. m = 11;
  317. break;
  318. case 'D':
  319. m = 12;
  320. break;
  321. }
  322. d = conv2d(buff + 4);
  323. memcpy_P(buff, time, 8);
  324. hh = conv2d(buff);
  325. mm = conv2d(buff + 3);
  326. ss = conv2d(buff + 6);
  327. }
  328. /**************************************************************************/
  329. /*!
  330. @brief Constructor for creating a DateTime from an ISO8601 date string.
  331. This constructor expects its parameters to be a string in the
  332. https://en.wikipedia.org/wiki/ISO_8601 format, e.g:
  333. "2020-06-25T15:29:37"
  334. Usage:
  335. ```
  336. DateTime dt("2020-06-25T15:29:37");
  337. ```
  338. @note The year must be > 2000, as only the yOff is considered.
  339. @param iso8601dateTime
  340. A dateTime string in iso8601 format,
  341. e.g. "2020-06-25T15:29:37".
  342. */
  343. /**************************************************************************/
  344. DateTime::DateTime(const char *iso8601dateTime) {
  345. char ref[] = "2000-01-01T00:00:00";
  346. memcpy(ref, iso8601dateTime, min(strlen(ref), strlen(iso8601dateTime)));
  347. yOff = conv2d(ref + 2);
  348. m = conv2d(ref + 5);
  349. d = conv2d(ref + 8);
  350. hh = conv2d(ref + 11);
  351. mm = conv2d(ref + 14);
  352. ss = conv2d(ref + 17);
  353. }
  354. /**************************************************************************/
  355. /*!
  356. @brief Check whether this DateTime is valid.
  357. @return true if valid, false if not.
  358. */
  359. /**************************************************************************/
  360. bool DateTime::isValid() const {
  361. if (yOff >= 100)
  362. return false;
  363. DateTime other(unixtime());
  364. return yOff == other.yOff && m == other.m && d == other.d && hh == other.hh &&
  365. mm == other.mm && ss == other.ss;
  366. }
  367. /**************************************************************************/
  368. /*!
  369. @brief Writes the DateTime as a string in a user-defined format.
  370. The _buffer_ parameter should be initialized by the caller with a string
  371. specifying the requested format. This format string may contain any of
  372. the following specifiers:
  373. | specifier | output |
  374. |-----------|--------------------------------------------------------|
  375. | YYYY | the year as a 4-digit number (2000--2099) |
  376. | YY | the year as a 2-digit number (00--99) |
  377. | MM | the month as a 2-digit number (01--12) |
  378. | MMM | the abbreviated English month name ("Jan"--"Dec") |
  379. | DD | the day as a 2-digit number (01--31) |
  380. | DDD | the abbreviated English day of the week ("Mon"--"Sun") |
  381. | AP | either "AM" or "PM" |
  382. | ap | either "am" or "pm" |
  383. | hh | the hour as a 2-digit number (00--23 or 01--12) |
  384. | mm | the minute as a 2-digit number (00--59) |
  385. | ss | the second as a 2-digit number (00--59) |
  386. If either "AP" or "ap" is used, the "hh" specifier uses 12-hour mode
  387. (range: 01--12). Otherwise it works in 24-hour mode (range: 00--23).
  388. The specifiers within _buffer_ will be overwritten with the appropriate
  389. values from the DateTime. Any characters not belonging to one of the
  390. above specifiers are left as-is.
  391. __Example__: The format "DDD, DD MMM YYYY hh:mm:ss" generates an output
  392. of the form "Thu, 16 Apr 2020 18:34:56.
  393. @see The `timestamp()` method provides similar functionnality, but it
  394. returns a `String` object and supports a limited choice of
  395. predefined formats.
  396. @param[in,out] buffer Array of `char` for holding the format description
  397. and the formatted DateTime. Before calling this method, the buffer
  398. should be initialized by the user with the format string. The method
  399. will overwrite the buffer with the formatted date and/or time.
  400. @return A pointer to the provided buffer. This is returned for
  401. convenience, in order to enable idioms such as
  402. `Serial.println(now.toString(buffer));`
  403. */
  404. /**************************************************************************/
  405. char *DateTime::toString(char *buffer) {
  406. uint8_t apTag =
  407. (strstr(buffer, "ap") != nullptr) || (strstr(buffer, "AP") != nullptr);
  408. uint8_t hourReformatted, isPM;
  409. if (apTag) { // 12 Hour Mode
  410. if (hh == 0) { // midnight
  411. isPM = false;
  412. hourReformatted = 12;
  413. } else if (hh == 12) { // noon
  414. isPM = true;
  415. hourReformatted = 12;
  416. } else if (hh < 12) { // morning
  417. isPM = false;
  418. hourReformatted = hh;
  419. } else { // 1 o'clock or after
  420. isPM = true;
  421. hourReformatted = hh - 12;
  422. }
  423. }
  424. for (size_t i = 0; i < strlen(buffer) - 1; i++) {
  425. if (buffer[i] == 'h' && buffer[i + 1] == 'h') {
  426. if (!apTag) { // 24 Hour Mode
  427. buffer[i] = '0' + hh / 10;
  428. buffer[i + 1] = '0' + hh % 10;
  429. } else { // 12 Hour Mode
  430. buffer[i] = '0' + hourReformatted / 10;
  431. buffer[i + 1] = '0' + hourReformatted % 10;
  432. }
  433. }
  434. if (buffer[i] == 'm' && buffer[i + 1] == 'm') {
  435. buffer[i] = '0' + mm / 10;
  436. buffer[i + 1] = '0' + mm % 10;
  437. }
  438. if (buffer[i] == 's' && buffer[i + 1] == 's') {
  439. buffer[i] = '0' + ss / 10;
  440. buffer[i + 1] = '0' + ss % 10;
  441. }
  442. if (buffer[i] == 'D' && buffer[i + 1] == 'D' && buffer[i + 2] == 'D') {
  443. static PROGMEM const char day_names[] = "SunMonTueWedThuFriSat";
  444. const char *p = &day_names[3 * dayOfTheWeek()];
  445. buffer[i] = pgm_read_byte(p);
  446. buffer[i + 1] = pgm_read_byte(p + 1);
  447. buffer[i + 2] = pgm_read_byte(p + 2);
  448. } else if (buffer[i] == 'D' && buffer[i + 1] == 'D') {
  449. buffer[i] = '0' + d / 10;
  450. buffer[i + 1] = '0' + d % 10;
  451. }
  452. if (buffer[i] == 'M' && buffer[i + 1] == 'M' && buffer[i + 2] == 'M') {
  453. static PROGMEM const char month_names[] =
  454. "JanFebMarAprMayJunJulAugSepOctNovDec";
  455. const char *p = &month_names[3 * (m - 1)];
  456. buffer[i] = pgm_read_byte(p);
  457. buffer[i + 1] = pgm_read_byte(p + 1);
  458. buffer[i + 2] = pgm_read_byte(p + 2);
  459. } else if (buffer[i] == 'M' && buffer[i + 1] == 'M') {
  460. buffer[i] = '0' + m / 10;
  461. buffer[i + 1] = '0' + m % 10;
  462. }
  463. if (buffer[i] == 'Y' && buffer[i + 1] == 'Y' && buffer[i + 2] == 'Y' &&
  464. buffer[i + 3] == 'Y') {
  465. buffer[i] = '2';
  466. buffer[i + 1] = '0';
  467. buffer[i + 2] = '0' + (yOff / 10) % 10;
  468. buffer[i + 3] = '0' + yOff % 10;
  469. } else if (buffer[i] == 'Y' && buffer[i + 1] == 'Y') {
  470. buffer[i] = '0' + (yOff / 10) % 10;
  471. buffer[i + 1] = '0' + yOff % 10;
  472. }
  473. if (buffer[i] == 'A' && buffer[i + 1] == 'P') {
  474. if (isPM) {
  475. buffer[i] = 'P';
  476. buffer[i + 1] = 'M';
  477. } else {
  478. buffer[i] = 'A';
  479. buffer[i + 1] = 'M';
  480. }
  481. } else if (buffer[i] == 'a' && buffer[i + 1] == 'p') {
  482. if (isPM) {
  483. buffer[i] = 'p';
  484. buffer[i + 1] = 'm';
  485. } else {
  486. buffer[i] = 'a';
  487. buffer[i + 1] = 'm';
  488. }
  489. }
  490. }
  491. return buffer;
  492. }
  493. /**************************************************************************/
  494. /*!
  495. @brief Return the hour in 12-hour format.
  496. @return Hour (1--12).
  497. */
  498. /**************************************************************************/
  499. uint8_t DateTime::twelveHour() const {
  500. if (hh == 0 || hh == 12) { // midnight or noon
  501. return 12;
  502. } else if (hh > 12) { // 1 o'clock or later
  503. return hh - 12;
  504. } else { // morning
  505. return hh;
  506. }
  507. }
  508. /**************************************************************************/
  509. /*!
  510. @brief Return the day of the week.
  511. @return Day of week as an integer from 0 (Sunday) to 6 (Saturday).
  512. */
  513. /**************************************************************************/
  514. uint8_t DateTime::dayOfTheWeek() const {
  515. uint16_t day = date2days(yOff, m, d);
  516. return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6
  517. }
  518. /**************************************************************************/
  519. /*!
  520. @brief Return Unix time: seconds since 1 Jan 1970.
  521. @see The `DateTime::DateTime(uint32_t)` constructor is the converse of
  522. this method.
  523. @return Number of seconds since 1970-01-01 00:00:00.
  524. */
  525. /**************************************************************************/
  526. uint32_t DateTime::unixtime(void) const {
  527. uint32_t t;
  528. uint16_t days = date2days(yOff, m, d);
  529. t = time2ulong(days, hh, mm, ss);
  530. t += SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000
  531. return t;
  532. }
  533. /**************************************************************************/
  534. /*!
  535. @brief Convert the DateTime to seconds since 1 Jan 2000
  536. The result can be converted back to a DateTime with:
  537. ```cpp
  538. DateTime(SECONDS_FROM_1970_TO_2000 + value)
  539. ```
  540. @return Number of seconds since 2000-01-01 00:00:00.
  541. */
  542. /**************************************************************************/
  543. uint32_t DateTime::secondstime(void) const {
  544. uint32_t t;
  545. uint16_t days = date2days(yOff, m, d);
  546. t = time2ulong(days, hh, mm, ss);
  547. return t;
  548. }
  549. /**************************************************************************/
  550. /*!
  551. @brief Add a TimeSpan to the DateTime object
  552. @param span TimeSpan object
  553. @return New DateTime object with span added to it.
  554. */
  555. /**************************************************************************/
  556. DateTime DateTime::operator+(const TimeSpan &span) {
  557. return DateTime(unixtime() + span.totalseconds());
  558. }
  559. /**************************************************************************/
  560. /*!
  561. @brief Subtract a TimeSpan from the DateTime object
  562. @param span TimeSpan object
  563. @return New DateTime object with span subtracted from it.
  564. */
  565. /**************************************************************************/
  566. DateTime DateTime::operator-(const TimeSpan &span) {
  567. return DateTime(unixtime() - span.totalseconds());
  568. }
  569. /**************************************************************************/
  570. /*!
  571. @brief Subtract one DateTime from another
  572. @note Since a TimeSpan cannot be negative, the subtracted DateTime
  573. should be less (earlier) than or equal to the one it is
  574. subtracted from.
  575. @param right The DateTime object to subtract from self (the left object)
  576. @return TimeSpan of the difference between DateTimes.
  577. */
  578. /**************************************************************************/
  579. TimeSpan DateTime::operator-(const DateTime &right) {
  580. return TimeSpan(unixtime() - right.unixtime());
  581. }
  582. /**************************************************************************/
  583. /*!
  584. @author Anton Rieutskyi
  585. @brief Test if one DateTime is less (earlier) than another.
  586. @warning if one or both DateTime objects are invalid, returned value is
  587. meaningless
  588. @see use `isValid()` method to check if DateTime object is valid
  589. @param right Comparison DateTime object
  590. @return True if the left DateTime is earlier than the right one,
  591. false otherwise.
  592. */
  593. /**************************************************************************/
  594. bool DateTime::operator<(const DateTime &right) const {
  595. return (yOff + 2000 < right.year() ||
  596. (yOff + 2000 == right.year() &&
  597. (m < right.month() ||
  598. (m == right.month() &&
  599. (d < right.day() ||
  600. (d == right.day() &&
  601. (hh < right.hour() ||
  602. (hh == right.hour() &&
  603. (mm < right.minute() ||
  604. (mm == right.minute() && ss < right.second()))))))))));
  605. }
  606. /**************************************************************************/
  607. /*!
  608. @author Anton Rieutskyi
  609. @brief Test if two DateTime objects are equal.
  610. @warning if one or both DateTime objects are invalid, returned value is
  611. meaningless
  612. @see use `isValid()` method to check if DateTime object is valid
  613. @param right Comparison DateTime object
  614. @return True if both DateTime objects are the same, false otherwise.
  615. */
  616. /**************************************************************************/
  617. bool DateTime::operator==(const DateTime &right) const {
  618. return (right.year() == yOff + 2000 && right.month() == m &&
  619. right.day() == d && right.hour() == hh && right.minute() == mm &&
  620. right.second() == ss);
  621. }
  622. /**************************************************************************/
  623. /*!
  624. @brief Return a ISO 8601 timestamp as a `String` object.
  625. The generated timestamp conforms to one of the predefined, ISO
  626. 8601-compatible formats for representing the date (if _opt_ is
  627. `TIMESTAMP_DATE`), the time (`TIMESTAMP_TIME`), or both
  628. (`TIMESTAMP_FULL`).
  629. @see The `toString()` method provides more general string formatting.
  630. @param opt Format of the timestamp
  631. @return Timestamp string, e.g. "2020-04-16T18:34:56".
  632. */
  633. /**************************************************************************/
  634. String DateTime::timestamp(timestampOpt opt) {
  635. char buffer[25]; // large enough for any DateTime, including invalid ones
  636. // Generate timestamp according to opt
  637. switch (opt) {
  638. case TIMESTAMP_TIME:
  639. // Only time
  640. sprintf(buffer, "%02d:%02d:%02d", hh, mm, ss);
  641. break;
  642. case TIMESTAMP_DATE:
  643. // Only date
  644. sprintf(buffer, "%d-%02d-%02d", 2000 + yOff, m, d);
  645. break;
  646. default:
  647. // Full
  648. sprintf(buffer, "%d-%02d-%02dT%02d:%02d:%02d", 2000 + yOff, m, d, hh, mm,
  649. ss);
  650. }
  651. return String(buffer);
  652. }
  653. /**************************************************************************/
  654. /*!
  655. @brief Create a new TimeSpan object in seconds
  656. @param seconds Number of seconds
  657. */
  658. /**************************************************************************/
  659. TimeSpan::TimeSpan(int32_t seconds) : _seconds(seconds) {}
  660. /**************************************************************************/
  661. /*!
  662. @brief Create a new TimeSpan object using a number of
  663. days/hours/minutes/seconds e.g. Make a TimeSpan of 3 hours and 45 minutes:
  664. new TimeSpan(0, 3, 45, 0);
  665. @param days Number of days
  666. @param hours Number of hours
  667. @param minutes Number of minutes
  668. @param seconds Number of seconds
  669. */
  670. /**************************************************************************/
  671. TimeSpan::TimeSpan(int16_t days, int8_t hours, int8_t minutes, int8_t seconds)
  672. : _seconds((int32_t)days * 86400L + (int32_t)hours * 3600 +
  673. (int32_t)minutes * 60 + seconds) {}
  674. /**************************************************************************/
  675. /*!
  676. @brief Copy constructor, make a new TimeSpan using an existing one
  677. @param copy The TimeSpan to copy
  678. */
  679. /**************************************************************************/
  680. TimeSpan::TimeSpan(const TimeSpan &copy) : _seconds(copy._seconds) {}
  681. /**************************************************************************/
  682. /*!
  683. @brief Add two TimeSpans
  684. @param right TimeSpan to add
  685. @return New TimeSpan object, sum of left and right
  686. */
  687. /**************************************************************************/
  688. TimeSpan TimeSpan::operator+(const TimeSpan &right) {
  689. return TimeSpan(_seconds + right._seconds);
  690. }
  691. /**************************************************************************/
  692. /*!
  693. @brief Subtract a TimeSpan
  694. @param right TimeSpan to subtract
  695. @return New TimeSpan object, right subtracted from left
  696. */
  697. /**************************************************************************/
  698. TimeSpan TimeSpan::operator-(const TimeSpan &right) {
  699. return TimeSpan(_seconds - right._seconds);
  700. }
  701. /**************************************************************************/
  702. /*!
  703. @brief Convert a binary coded decimal value to binary. RTC stores time/date
  704. values as BCD.
  705. @param val BCD value
  706. @return Binary value
  707. */
  708. /**************************************************************************/
  709. static uint8_t bcd2bin(uint8_t val) { return val - 6 * (val >> 4); }
  710. /**************************************************************************/
  711. /*!
  712. @brief Convert a binary value to BCD format for the RTC registers
  713. @param val Binary value
  714. @return BCD value
  715. */
  716. /**************************************************************************/
  717. static uint8_t bin2bcd(uint8_t val) { return val + 6 * (val / 10); }
  718. /**************************************************************************/
  719. /*!
  720. @brief Start I2C for the DS1307 and test succesful connection
  721. @return True if Wire can find DS1307 or false otherwise.
  722. */
  723. /**************************************************************************/
  724. boolean RTC_DS1307::begin(void) {
  725. Wire.begin();
  726. Wire.beginTransmission(DS1307_ADDRESS);
  727. if (Wire.endTransmission() == 0)
  728. return true;
  729. return false;
  730. }
  731. /**************************************************************************/
  732. /*!
  733. @brief Is the DS1307 running? Check the Clock Halt bit in register 0
  734. @return 1 if the RTC is running, 0 if not
  735. */
  736. /**************************************************************************/
  737. uint8_t RTC_DS1307::isrunning(void) {
  738. Wire.beginTransmission(DS1307_ADDRESS);
  739. Wire._I2C_WRITE((byte)0);
  740. Wire.endTransmission();
  741. Wire.requestFrom(DS1307_ADDRESS, 1);
  742. uint8_t ss = Wire._I2C_READ();
  743. return !(ss >> 7);
  744. }
  745. /**************************************************************************/
  746. /*!
  747. @brief Set the date and time in the DS1307
  748. @param dt DateTime object containing the desired date/time
  749. */
  750. /**************************************************************************/
  751. void RTC_DS1307::adjust(const DateTime &dt) {
  752. Wire.beginTransmission(DS1307_ADDRESS);
  753. Wire._I2C_WRITE((byte)0); // start at location 0
  754. Wire._I2C_WRITE(bin2bcd(dt.second()));
  755. Wire._I2C_WRITE(bin2bcd(dt.minute()));
  756. Wire._I2C_WRITE(bin2bcd(dt.hour()));
  757. Wire._I2C_WRITE(bin2bcd(0));
  758. Wire._I2C_WRITE(bin2bcd(dt.day()));
  759. Wire._I2C_WRITE(bin2bcd(dt.month()));
  760. Wire._I2C_WRITE(bin2bcd(dt.year() - 2000));
  761. Wire.endTransmission();
  762. }
  763. /**************************************************************************/
  764. /*!
  765. @brief Get the current date and time from the DS1307
  766. @return DateTime object containing the current date and time
  767. */
  768. /**************************************************************************/
  769. DateTime RTC_DS1307::now() {
  770. Wire.beginTransmission(DS1307_ADDRESS);
  771. Wire._I2C_WRITE((byte)0);
  772. Wire.endTransmission();
  773. Wire.requestFrom(DS1307_ADDRESS, 7);
  774. uint8_t ss = bcd2bin(Wire._I2C_READ() & 0x7F);
  775. uint8_t mm = bcd2bin(Wire._I2C_READ());
  776. uint8_t hh = bcd2bin(Wire._I2C_READ());
  777. Wire._I2C_READ();
  778. uint8_t d = bcd2bin(Wire._I2C_READ());
  779. uint8_t m = bcd2bin(Wire._I2C_READ());
  780. uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000;
  781. return DateTime(y, m, d, hh, mm, ss);
  782. }
  783. /**************************************************************************/
  784. /*!
  785. @brief Read the current mode of the SQW pin
  786. @return Mode as Ds1307SqwPinMode enum
  787. */
  788. /**************************************************************************/
  789. Ds1307SqwPinMode RTC_DS1307::readSqwPinMode() {
  790. int mode;
  791. Wire.beginTransmission(DS1307_ADDRESS);
  792. Wire._I2C_WRITE(DS1307_CONTROL);
  793. Wire.endTransmission();
  794. Wire.requestFrom((uint8_t)DS1307_ADDRESS, (uint8_t)1);
  795. mode = Wire._I2C_READ();
  796. mode &= 0x93;
  797. return static_cast<Ds1307SqwPinMode>(mode);
  798. }
  799. /**************************************************************************/
  800. /*!
  801. @brief Change the SQW pin mode
  802. @param mode The mode to use
  803. */
  804. /**************************************************************************/
  805. void RTC_DS1307::writeSqwPinMode(Ds1307SqwPinMode mode) {
  806. Wire.beginTransmission(DS1307_ADDRESS);
  807. Wire._I2C_WRITE(DS1307_CONTROL);
  808. Wire._I2C_WRITE(mode);
  809. Wire.endTransmission();
  810. }
  811. /**************************************************************************/
  812. /*!
  813. @brief Read data from the DS1307's NVRAM
  814. @param buf Pointer to a buffer to store the data - make sure it's large
  815. enough to hold size bytes
  816. @param size Number of bytes to read
  817. @param address Starting NVRAM address, from 0 to 55
  818. */
  819. /**************************************************************************/
  820. void RTC_DS1307::readnvram(uint8_t *buf, uint8_t size, uint8_t address) {
  821. int addrByte = DS1307_NVRAM + address;
  822. Wire.beginTransmission(DS1307_ADDRESS);
  823. Wire._I2C_WRITE(addrByte);
  824. Wire.endTransmission();
  825. Wire.requestFrom((uint8_t)DS1307_ADDRESS, size);
  826. for (uint8_t pos = 0; pos < size; ++pos) {
  827. buf[pos] = Wire._I2C_READ();
  828. }
  829. }
  830. /**************************************************************************/
  831. /*!
  832. @brief Write data to the DS1307 NVRAM
  833. @param address Starting NVRAM address, from 0 to 55
  834. @param buf Pointer to buffer containing the data to write
  835. @param size Number of bytes in buf to write to NVRAM
  836. */
  837. /**************************************************************************/
  838. void RTC_DS1307::writenvram(uint8_t address, uint8_t *buf, uint8_t size) {
  839. int addrByte = DS1307_NVRAM + address;
  840. Wire.beginTransmission(DS1307_ADDRESS);
  841. Wire._I2C_WRITE(addrByte);
  842. for (uint8_t pos = 0; pos < size; ++pos) {
  843. Wire._I2C_WRITE(buf[pos]);
  844. }
  845. Wire.endTransmission();
  846. }
  847. /**************************************************************************/
  848. /*!
  849. @brief Shortcut to read one byte from NVRAM
  850. @param address NVRAM address, 0 to 55
  851. @return The byte read from NVRAM
  852. */
  853. /**************************************************************************/
  854. uint8_t RTC_DS1307::readnvram(uint8_t address) {
  855. uint8_t data;
  856. readnvram(&data, 1, address);
  857. return data;
  858. }
  859. /**************************************************************************/
  860. /*!
  861. @brief Shortcut to write one byte to NVRAM
  862. @param address NVRAM address, 0 to 55
  863. @param data One byte to write
  864. */
  865. /**************************************************************************/
  866. void RTC_DS1307::writenvram(uint8_t address, uint8_t data) {
  867. writenvram(address, &data, 1);
  868. }
  869. /** Alignment between the milis() timescale and the Unix timescale. These
  870. two variables are updated on each call to now(), which prevents
  871. rollover issues. Note that lastMillis is **not** the millis() value
  872. of the last call to now(): it's the millis() value corresponding to
  873. the last **full second** of Unix time. */
  874. uint32_t RTC_Millis::lastMillis;
  875. uint32_t RTC_Millis::lastUnix;
  876. /**************************************************************************/
  877. /*!
  878. @brief Set the current date/time of the RTC_Millis clock.
  879. @param dt DateTime object with the desired date and time
  880. */
  881. /**************************************************************************/
  882. void RTC_Millis::adjust(const DateTime &dt) {
  883. lastMillis = millis();
  884. lastUnix = dt.unixtime();
  885. }
  886. /**************************************************************************/
  887. /*!
  888. @brief Return a DateTime object containing the current date/time.
  889. Note that computing (millis() - lastMillis) is rollover-safe as long
  890. as this method is called at least once every 49.7 days.
  891. @return DateTime object containing current time
  892. */
  893. /**************************************************************************/
  894. DateTime RTC_Millis::now() {
  895. uint32_t elapsedSeconds = (millis() - lastMillis) / 1000;
  896. lastMillis += elapsedSeconds * 1000;
  897. lastUnix += elapsedSeconds;
  898. return lastUnix;
  899. }
  900. /** Number of microseconds reported by micros() per "true" (calibrated) second.
  901. */
  902. uint32_t RTC_Micros::microsPerSecond = 1000000;
  903. /** The timing logic is identical to RTC_Millis. */
  904. uint32_t RTC_Micros::lastMicros;
  905. uint32_t RTC_Micros::lastUnix;
  906. /**************************************************************************/
  907. /*!
  908. @brief Set the current date/time of the RTC_Micros clock.
  909. @param dt DateTime object with the desired date and time
  910. */
  911. /**************************************************************************/
  912. void RTC_Micros::adjust(const DateTime &dt) {
  913. lastMicros = micros();
  914. lastUnix = dt.unixtime();
  915. }
  916. /**************************************************************************/
  917. /*!
  918. @brief Adjust the RTC_Micros clock to compensate for system clock drift
  919. @param ppm Adjustment to make
  920. */
  921. /**************************************************************************/
  922. // A positive adjustment makes the clock faster.
  923. void RTC_Micros::adjustDrift(int ppm) { microsPerSecond = 1000000 - ppm; }
  924. /**************************************************************************/
  925. /*!
  926. @brief Get the current date/time from the RTC_Micros clock.
  927. @return DateTime object containing the current date/time
  928. */
  929. /**************************************************************************/
  930. DateTime RTC_Micros::now() {
  931. uint32_t elapsedSeconds = (micros() - lastMicros) / microsPerSecond;
  932. lastMicros += elapsedSeconds * microsPerSecond;
  933. lastUnix += elapsedSeconds;
  934. return lastUnix;
  935. }
  936. /**************************************************************************/
  937. /*!
  938. @brief Start I2C for the PCF8523 and test succesful connection
  939. @return True if Wire can find PCF8523 or false otherwise.
  940. */
  941. /**************************************************************************/
  942. boolean RTC_PCF8523::begin(void) {
  943. Wire.begin();
  944. Wire.beginTransmission(PCF8523_ADDRESS);
  945. if (Wire.endTransmission() == 0)
  946. return true;
  947. return false;
  948. }
  949. /**************************************************************************/
  950. /*!
  951. @brief Check the status register Oscillator Stop flag to see if the PCF8523
  952. stopped due to power loss
  953. @details When battery or external power is first applied, the PCF8523's
  954. crystal oscillator takes up to 2s to stabilize. During this time adjust()
  955. cannot clear the 'OS' flag. See datasheet OS flag section for details.
  956. @return True if the bit is set (oscillator is or has stopped) and false only
  957. after the bit is cleared, for instance with adjust()
  958. */
  959. /**************************************************************************/
  960. boolean RTC_PCF8523::lostPower(void) {
  961. return (read_i2c_register(PCF8523_ADDRESS, PCF8523_STATUSREG) >> 7);
  962. }
  963. /**************************************************************************/
  964. /*!
  965. @brief Check control register 3 to see if we've run adjust() yet (setting
  966. the date/time and battery switchover mode)
  967. @return True if the PCF8523 has been set up, false if not
  968. */
  969. /**************************************************************************/
  970. boolean RTC_PCF8523::initialized(void) {
  971. Wire.beginTransmission(PCF8523_ADDRESS);
  972. Wire._I2C_WRITE((byte)PCF8523_CONTROL_3);
  973. Wire.endTransmission();
  974. Wire.requestFrom(PCF8523_ADDRESS, 1);
  975. uint8_t ss = Wire._I2C_READ();
  976. return ((ss & 0xE0) != 0xE0); // 0xE0 = standby mode, set after power out
  977. }
  978. /**************************************************************************/
  979. /*!
  980. @brief Set the date and time, set battery switchover mode
  981. @param dt DateTime to set
  982. */
  983. /**************************************************************************/
  984. void RTC_PCF8523::adjust(const DateTime &dt) {
  985. Wire.beginTransmission(PCF8523_ADDRESS);
  986. Wire._I2C_WRITE((byte)3); // start at location 3
  987. Wire._I2C_WRITE(bin2bcd(dt.second()));
  988. Wire._I2C_WRITE(bin2bcd(dt.minute()));
  989. Wire._I2C_WRITE(bin2bcd(dt.hour()));
  990. Wire._I2C_WRITE(bin2bcd(dt.day()));
  991. Wire._I2C_WRITE(bin2bcd(0)); // skip weekdays
  992. Wire._I2C_WRITE(bin2bcd(dt.month()));
  993. Wire._I2C_WRITE(bin2bcd(dt.year() - 2000));
  994. Wire.endTransmission();
  995. // set to battery switchover mode
  996. Wire.beginTransmission(PCF8523_ADDRESS);
  997. Wire._I2C_WRITE((byte)PCF8523_CONTROL_3);
  998. Wire._I2C_WRITE((byte)0x00);
  999. Wire.endTransmission();
  1000. }
  1001. /**************************************************************************/
  1002. /*!
  1003. @brief Get the current date/time
  1004. @return DateTime object containing the current date/time
  1005. */
  1006. /**************************************************************************/
  1007. DateTime RTC_PCF8523::now() {
  1008. Wire.beginTransmission(PCF8523_ADDRESS);
  1009. Wire._I2C_WRITE((byte)3);
  1010. Wire.endTransmission();
  1011. Wire.requestFrom(PCF8523_ADDRESS, 7);
  1012. uint8_t ss = bcd2bin(Wire._I2C_READ() & 0x7F);
  1013. uint8_t mm = bcd2bin(Wire._I2C_READ());
  1014. uint8_t hh = bcd2bin(Wire._I2C_READ());
  1015. uint8_t d = bcd2bin(Wire._I2C_READ());
  1016. Wire._I2C_READ(); // skip 'weekdays'
  1017. uint8_t m = bcd2bin(Wire._I2C_READ());
  1018. uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000;
  1019. return DateTime(y, m, d, hh, mm, ss);
  1020. }
  1021. /**************************************************************************/
  1022. /*!
  1023. @brief Resets the STOP bit in register Control_1
  1024. */
  1025. /**************************************************************************/
  1026. void RTC_PCF8523::start(void) {
  1027. uint8_t ctlreg = read_i2c_register(PCF8523_ADDRESS, PCF8523_CONTROL_1);
  1028. if (ctlreg & (1 << 5)) {
  1029. write_i2c_register(PCF8523_ADDRESS, PCF8523_CONTROL_1, ctlreg & ~(1 << 5));
  1030. }
  1031. }
  1032. /**************************************************************************/
  1033. /*!
  1034. @brief Sets the STOP bit in register Control_1
  1035. */
  1036. /**************************************************************************/
  1037. void RTC_PCF8523::stop(void) {
  1038. uint8_t ctlreg = read_i2c_register(PCF8523_ADDRESS, PCF8523_CONTROL_1);
  1039. if (!(ctlreg & (1 << 5))) {
  1040. write_i2c_register(PCF8523_ADDRESS, PCF8523_CONTROL_1, ctlreg | (1 << 5));
  1041. }
  1042. }
  1043. /**************************************************************************/
  1044. /*!
  1045. @brief Is the PCF8523 running? Check the STOP bit in register Control_1
  1046. @return 1 if the RTC is running, 0 if not
  1047. */
  1048. /**************************************************************************/
  1049. uint8_t RTC_PCF8523::isrunning() {
  1050. uint8_t ctlreg = read_i2c_register(PCF8523_ADDRESS, PCF8523_CONTROL_1);
  1051. return !((ctlreg >> 5) & 1);
  1052. }
  1053. /**************************************************************************/
  1054. /*!
  1055. @brief Read the mode of the INT/SQW pin on the PCF8523
  1056. @return SQW pin mode as a #Pcf8523SqwPinMode enum
  1057. */
  1058. /**************************************************************************/
  1059. Pcf8523SqwPinMode RTC_PCF8523::readSqwPinMode() {
  1060. int mode;
  1061. Wire.beginTransmission(PCF8523_ADDRESS);
  1062. Wire._I2C_WRITE(PCF8523_CLKOUTCONTROL);
  1063. Wire.endTransmission();
  1064. Wire.requestFrom((uint8_t)PCF8523_ADDRESS, (uint8_t)1);
  1065. mode = Wire._I2C_READ();
  1066. mode >>= 3;
  1067. mode &= 0x7;
  1068. return static_cast<Pcf8523SqwPinMode>(mode);
  1069. }
  1070. /**************************************************************************/
  1071. /*!
  1072. @brief Set the INT/SQW pin mode on the PCF8523
  1073. @param mode The mode to set, see the #Pcf8523SqwPinMode enum for options
  1074. */
  1075. /**************************************************************************/
  1076. void RTC_PCF8523::writeSqwPinMode(Pcf8523SqwPinMode mode) {
  1077. Wire.beginTransmission(PCF8523_ADDRESS);
  1078. Wire._I2C_WRITE(PCF8523_CLKOUTCONTROL);
  1079. Wire._I2C_WRITE(mode << 3); // disables other timers
  1080. Wire.endTransmission();
  1081. }
  1082. /**************************************************************************/
  1083. /*!
  1084. @brief Enable the Second Timer (1Hz) Interrupt on the PCF8523.
  1085. @details The INT/SQW pin will pull low for a brief pulse once per second.
  1086. */
  1087. /**************************************************************************/
  1088. void RTC_PCF8523::enableSecondTimer() {
  1089. // Leave compatible settings intact
  1090. uint8_t ctlreg = read_i2c_register(PCF8523_ADDRESS, PCF8523_CONTROL_1);
  1091. uint8_t clkreg = read_i2c_register(PCF8523_ADDRESS, PCF8523_CLKOUTCONTROL);
  1092. // TAM pulse int. mode (shared with Timer A), CLKOUT (aka SQW) disabled
  1093. write_i2c_register(PCF8523_ADDRESS, PCF8523_CLKOUTCONTROL, clkreg | 0xB8);
  1094. // SIE Second timer int. enable
  1095. write_i2c_register(PCF8523_ADDRESS, PCF8523_CONTROL_1, ctlreg | (1 << 2));
  1096. }
  1097. /**************************************************************************/
  1098. /*!
  1099. @brief Disable the Second Timer (1Hz) Interrupt on the PCF8523.
  1100. */
  1101. /**************************************************************************/
  1102. void RTC_PCF8523::disableSecondTimer() {
  1103. // Leave compatible settings intact
  1104. uint8_t ctlreg = read_i2c_register(PCF8523_ADDRESS, PCF8523_CONTROL_1);
  1105. // SIE Second timer int. disable
  1106. write_i2c_register(PCF8523_ADDRESS, PCF8523_CONTROL_1, ctlreg & ~(1 << 2));
  1107. }
  1108. /**************************************************************************/
  1109. /*!
  1110. @brief Enable the Countdown Timer Interrupt on the PCF8523.
  1111. @details The INT/SQW pin will be pulled low at the end of a specified
  1112. countdown period ranging from 244 microseconds to 10.625 days.
  1113. Uses PCF8523 Timer B. Any existing CLKOUT square wave, configured with
  1114. writeSqwPinMode(), will halt. The interrupt low pulse width is adjustable
  1115. from 3/64ths (default) to 14/64ths of a second.
  1116. @param clkFreq One of the PCF8523's Timer Source Clock Frequencies.
  1117. See the #PCF8523TimerClockFreq enum for options and associated time ranges.
  1118. @param numPeriods The number of clkFreq periods (1-255) to count down.
  1119. @param lowPulseWidth Optional: the length of time for the interrupt pin
  1120. low pulse. See the #PCF8523TimerIntPulse enum for options.
  1121. */
  1122. /**************************************************************************/
  1123. void RTC_PCF8523::enableCountdownTimer(PCF8523TimerClockFreq clkFreq,
  1124. uint8_t numPeriods,
  1125. uint8_t lowPulseWidth) {
  1126. // Datasheet cautions against updating countdown value while it's running,
  1127. // so disabling allows repeated calls with new values to set new countdowns
  1128. disableCountdownTimer();
  1129. // Leave compatible settings intact
  1130. uint8_t ctlreg = read_i2c_register(PCF8523_ADDRESS, PCF8523_CONTROL_2);
  1131. uint8_t clkreg = read_i2c_register(PCF8523_ADDRESS, PCF8523_CLKOUTCONTROL);
  1132. // CTBIE Countdown Timer B Interrupt Enabled
  1133. write_i2c_register(PCF8523_ADDRESS, PCF8523_CONTROL_2, ctlreg |= 0x01);
  1134. // Timer B source clock frequency, optionally int. low pulse width
  1135. write_i2c_register(PCF8523_ADDRESS, PCF8523_TIMER_B_FRCTL,
  1136. lowPulseWidth << 4 | clkFreq);
  1137. // Timer B value (number of source clock periods)
  1138. write_i2c_register(PCF8523_ADDRESS, PCF8523_TIMER_B_VALUE, numPeriods);
  1139. // TBM Timer B pulse int. mode, CLKOUT (aka SQW) disabled, TBC start Timer B
  1140. write_i2c_register(PCF8523_ADDRESS, PCF8523_CLKOUTCONTROL, clkreg | 0x79);
  1141. }
  1142. /**************************************************************************/
  1143. /*!
  1144. @overload
  1145. @brief Enable Countdown Timer using default interrupt low pulse width.
  1146. @param clkFreq One of the PCF8523's Timer Source Clock Frequencies.
  1147. See the #PCF8523TimerClockFreq enum for options and associated time ranges.
  1148. @param numPeriods The number of clkFreq periods (1-255) to count down.
  1149. */
  1150. /**************************************************************************/
  1151. void RTC_PCF8523::enableCountdownTimer(PCF8523TimerClockFreq clkFreq,
  1152. uint8_t numPeriods) {
  1153. enableCountdownTimer(clkFreq, numPeriods, 0);
  1154. }
  1155. /**************************************************************************/
  1156. /*!
  1157. @brief Disable the Countdown Timer Interrupt on the PCF8523.
  1158. @details For simplicity, this function strictly disables Timer B by setting
  1159. TBC to 0. The datasheet describes TBC as the Timer B on/off switch.
  1160. Timer B is the only countdown timer implemented at this time.
  1161. The following flags have no effect while TBC is off, they are *not* cleared:
  1162. - TBM: Timer B will still be set to pulsed mode.
  1163. - CTBIE: Timer B interrupt would be triggered if TBC were on.
  1164. - CTBF: Timer B flag indicates that interrupt was triggered. Though
  1165. typically used for non-pulsed mode, user may wish to query this later.
  1166. */
  1167. /**************************************************************************/
  1168. void RTC_PCF8523::disableCountdownTimer() {
  1169. // Leave compatible settings intact
  1170. uint8_t clkreg = read_i2c_register(PCF8523_ADDRESS, PCF8523_CLKOUTCONTROL);
  1171. // TBC disable to stop Timer B clock
  1172. write_i2c_register(PCF8523_ADDRESS, PCF8523_CLKOUTCONTROL, ~1 & clkreg);
  1173. }
  1174. /**************************************************************************/
  1175. /*!
  1176. @brief Stop all timers, clear their flags and settings on the PCF8523.
  1177. @details This includes the Countdown Timer, Second Timer, and any CLKOUT
  1178. square wave configured with writeSqwPinMode().
  1179. */
  1180. /**************************************************************************/
  1181. void RTC_PCF8523::deconfigureAllTimers() {
  1182. disableSecondTimer(); // Surgically clears CONTROL_1
  1183. write_i2c_register(PCF8523_ADDRESS, PCF8523_CONTROL_2, 0);
  1184. write_i2c_register(PCF8523_ADDRESS, PCF8523_CLKOUTCONTROL, 0);
  1185. write_i2c_register(PCF8523_ADDRESS, PCF8523_TIMER_B_FRCTL, 0);
  1186. write_i2c_register(PCF8523_ADDRESS, PCF8523_TIMER_B_VALUE, 0);
  1187. }
  1188. /**************************************************************************/
  1189. /*!
  1190. @brief Use an offset to calibrate the PCF8523.
  1191. @details This can be used for:
  1192. - Aging adjustment
  1193. - Temperature compensation
  1194. - Accuracy tuning
  1195. @param mode The offset mode to use, once every two hours or once every
  1196. minute. See the #Pcf8523OffsetMode enum.
  1197. @param offset Offset value from -64 to +63. See the datasheet for exact ppm
  1198. values.
  1199. */
  1200. /**************************************************************************/
  1201. void RTC_PCF8523::calibrate(Pcf8523OffsetMode mode, int8_t offset) {
  1202. uint8_t reg = (uint8_t)offset & 0x7F;
  1203. reg |= mode;
  1204. Wire.beginTransmission(PCF8523_ADDRESS);
  1205. Wire._I2C_WRITE(PCF8523_OFFSET);
  1206. Wire._I2C_WRITE(reg);
  1207. Wire.endTransmission();
  1208. }
  1209. // START RTC_PCF8563 implementation
  1210. /**************************************************************************/
  1211. /*!
  1212. @brief Start I2C for the PCF8563 and test succesful connection
  1213. @return True if Wire can find PCF8563 or false otherwise.
  1214. */
  1215. /**************************************************************************/
  1216. boolean RTC_PCF8563::begin(void) {
  1217. Wire.begin();
  1218. Wire.beginTransmission(PCF8563_ADDRESS);
  1219. if (Wire.endTransmission() == 0)
  1220. return true;
  1221. return false;
  1222. }
  1223. /**************************************************************************/
  1224. /*!
  1225. @brief Check the status of the VL bit in the VL_SECONDS register.
  1226. @details The PCF8563 has an on-chip voltage-low detector. When VDD drops
  1227. below Vlow, bit VL in the VL_seconds register is set to indicate that
  1228. the integrity of the clock information is no longer guaranteed.
  1229. @return True if the bit is set (VDD droped below Vlow) indicating that
  1230. the clock integrity is not guaranteed and false only after the bit is
  1231. cleared using adjust()
  1232. */
  1233. /**************************************************************************/
  1234. boolean RTC_PCF8563::lostPower(void) {
  1235. return (read_i2c_register(PCF8563_ADDRESS, PCF8563_VL_SECONDS) >> 7);
  1236. }
  1237. /**************************************************************************/
  1238. /*!
  1239. @brief Set the date and time
  1240. @param dt DateTime to set
  1241. */
  1242. /**************************************************************************/
  1243. void RTC_PCF8563::adjust(const DateTime &dt) {
  1244. Wire.beginTransmission(PCF8563_ADDRESS);
  1245. Wire._I2C_WRITE(PCF8563_VL_SECONDS); // start at location 2, VL_SECONDS
  1246. Wire._I2C_WRITE(bin2bcd(dt.second()));
  1247. Wire._I2C_WRITE(bin2bcd(dt.minute()));
  1248. Wire._I2C_WRITE(bin2bcd(dt.hour()));
  1249. Wire._I2C_WRITE(bin2bcd(dt.day()));
  1250. Wire._I2C_WRITE(bin2bcd(0)); // skip weekdays
  1251. Wire._I2C_WRITE(bin2bcd(dt.month()));
  1252. Wire._I2C_WRITE(bin2bcd(dt.year() - 2000));
  1253. Wire.endTransmission();
  1254. }
  1255. /**************************************************************************/
  1256. /*!
  1257. @brief Get the current date/time
  1258. @return DateTime object containing the current date/time
  1259. */
  1260. /**************************************************************************/
  1261. DateTime RTC_PCF8563::now() {
  1262. Wire.beginTransmission(PCF8563_ADDRESS);
  1263. Wire._I2C_WRITE((byte)2);
  1264. Wire.endTransmission();
  1265. Wire.requestFrom(PCF8563_ADDRESS, 7);
  1266. uint8_t ss = bcd2bin(Wire._I2C_READ() & 0x7F);
  1267. uint8_t mm = bcd2bin(Wire._I2C_READ() & 0x7F);
  1268. uint8_t hh = bcd2bin(Wire._I2C_READ() & 0x3F);
  1269. uint8_t d = bcd2bin(Wire._I2C_READ() & 0x3F);
  1270. Wire._I2C_READ(); // skip 'weekdays'
  1271. uint8_t m = bcd2bin(Wire._I2C_READ() & 0x1F);
  1272. uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000;
  1273. return DateTime (y, m, d, hh, mm, ss);
  1274. }
  1275. /**************************************************************************/
  1276. /*!
  1277. @brief Resets the STOP bit in register Control_1
  1278. */
  1279. /**************************************************************************/
  1280. void RTC_PCF8563::start(void) {
  1281. uint8_t ctlreg = read_i2c_register(PCF8563_ADDRESS, PCF8563_CONTROL_1);
  1282. if (ctlreg & (1 << 5)) {
  1283. write_i2c_register(PCF8563_ADDRESS, PCF8563_CONTROL_1, ctlreg & ~(1 << 5));
  1284. }
  1285. }
  1286. /**************************************************************************/
  1287. /*!
  1288. @brief Sets the STOP bit in register Control_1
  1289. */
  1290. /**************************************************************************/
  1291. void RTC_PCF8563::stop(void) {
  1292. uint8_t ctlreg = read_i2c_register(PCF8563_ADDRESS, PCF8563_CONTROL_1);
  1293. if (!(ctlreg & (1 << 5))) {
  1294. write_i2c_register(PCF8523_ADDRESS, PCF8563_CONTROL_1, ctlreg | (1 << 5));
  1295. }
  1296. }
  1297. /**************************************************************************/
  1298. /*!
  1299. @brief Is the PCF8563 running? Check the STOP bit in register Control_1
  1300. @return 1 if the RTC is running, 0 if not
  1301. */
  1302. /**************************************************************************/
  1303. uint8_t RTC_PCF8563::isrunning() {
  1304. uint8_t ctlreg = read_i2c_register(PCF8563_ADDRESS, PCF8563_CONTROL_1);
  1305. return !((ctlreg >> 5) & 1);
  1306. }
  1307. /**************************************************************************/
  1308. /*!
  1309. @brief Read the mode of the CLKOUT pin on the PCF8563
  1310. @return CLKOUT pin mode as a #Pcf8563SClkOutMode enum
  1311. */
  1312. /**************************************************************************/
  1313. Pcf8563SqwPinMode RTC_PCF8563::readSqwPinMode() {
  1314. int mode;
  1315. Wire.beginTransmission(PCF8563_ADDRESS);
  1316. Wire._I2C_WRITE(PCF8563_CLKOUTCONTROL);
  1317. Wire.endTransmission();
  1318. Wire.requestFrom((uint8_t)PCF8563_ADDRESS, (uint8_t)1);
  1319. mode = Wire._I2C_READ();
  1320. return static_cast<Pcf8563SqwPinMode>(mode & PCF8563_CLKOUT_MASK);
  1321. }
  1322. /**************************************************************************/
  1323. /*!
  1324. @brief Set the CLKOUT pin mode on the PCF8563
  1325. @param mode The mode to set, see the #Pcf8563ClkOutMode enum for options
  1326. */
  1327. /**************************************************************************/
  1328. void RTC_PCF8563::writeSqwPinMode(Pcf8563SqwPinMode mode) {
  1329. Wire.beginTransmission(PCF8563_ADDRESS);
  1330. Wire._I2C_WRITE(PCF8563_CLKOUTCONTROL);
  1331. Wire._I2C_WRITE(mode);
  1332. Wire.endTransmission();
  1333. }
  1334. // END RTC_PCF8563 implementation
  1335. /**************************************************************************/
  1336. /*!
  1337. @brief Convert the day of the week to a representation suitable for
  1338. storing in the DS3231: from 1 (Monday) to 7 (Sunday).
  1339. @param d Day of the week as represented by the library:
  1340. from 0 (Sunday) to 6 (Saturday).
  1341. */
  1342. /**************************************************************************/
  1343. static uint8_t dowToDS3231(uint8_t d) { return d == 0 ? 7 : d; }
  1344. /**************************************************************************/
  1345. /*!
  1346. @brief Start I2C for the DS3231 and test succesful connection
  1347. @return True if Wire can find DS3231 or false otherwise.
  1348. */
  1349. /**************************************************************************/
  1350. boolean RTC_DS3231::begin(void) {
  1351. Wire.begin();
  1352. Wire.beginTransmission(DS3231_ADDRESS);
  1353. if (Wire.endTransmission() == 0)
  1354. return true;
  1355. return false;
  1356. }
  1357. /**************************************************************************/
  1358. /*!
  1359. @brief Check the status register Oscillator Stop Flag to see if the DS3231
  1360. stopped due to power loss
  1361. @return True if the bit is set (oscillator stopped) or false if it is
  1362. running
  1363. */
  1364. /**************************************************************************/
  1365. bool RTC_DS3231::lostPower(void) {
  1366. return (read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG) >> 7);
  1367. }
  1368. /**************************************************************************/
  1369. /*!
  1370. @brief Set the date and flip the Oscillator Stop Flag
  1371. @param dt DateTime object containing the date/time to set
  1372. */
  1373. /**************************************************************************/
  1374. void RTC_DS3231::adjust(const DateTime &dt) {
  1375. Wire.beginTransmission(DS3231_ADDRESS);
  1376. Wire._I2C_WRITE((byte)DS3231_TIME); // start at location 0
  1377. Wire._I2C_WRITE(bin2bcd(dt.second()));
  1378. Wire._I2C_WRITE(bin2bcd(dt.minute()));
  1379. Wire._I2C_WRITE(bin2bcd(dt.hour()));
  1380. // The RTC must know the day of the week for the weekly alarms to work.
  1381. Wire._I2C_WRITE(bin2bcd(dowToDS3231(dt.dayOfTheWeek())));
  1382. Wire._I2C_WRITE(bin2bcd(dt.day()));
  1383. Wire._I2C_WRITE(bin2bcd(dt.month()));
  1384. Wire._I2C_WRITE(bin2bcd(dt.year() - 2000));
  1385. Wire.endTransmission();
  1386. uint8_t statreg = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG);
  1387. statreg &= ~0x80; // flip OSF bit
  1388. write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, statreg);
  1389. }
  1390. /**************************************************************************/
  1391. /*!
  1392. @brief Get the current date/time
  1393. @return DateTime object with the current date/time
  1394. */
  1395. /**************************************************************************/
  1396. DateTime RTC_DS3231::now() {
  1397. Wire.beginTransmission(DS3231_ADDRESS);
  1398. Wire._I2C_WRITE((byte)0);
  1399. Wire.endTransmission();
  1400. Wire.requestFrom(DS3231_ADDRESS, 7);
  1401. uint8_t ss = bcd2bin(Wire._I2C_READ() & 0x7F);
  1402. uint8_t mm = bcd2bin(Wire._I2C_READ());
  1403. uint8_t hh = bcd2bin(Wire._I2C_READ());
  1404. Wire._I2C_READ();
  1405. uint8_t d = bcd2bin(Wire._I2C_READ());
  1406. uint8_t m = bcd2bin(Wire._I2C_READ());
  1407. uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000;
  1408. return DateTime(y, m, d, hh, mm, ss);
  1409. }
  1410. /**************************************************************************/
  1411. /*!
  1412. @brief Read the SQW pin mode
  1413. @return Pin mode, see Ds3231SqwPinMode enum
  1414. */
  1415. /**************************************************************************/
  1416. Ds3231SqwPinMode RTC_DS3231::readSqwPinMode() {
  1417. int mode;
  1418. Wire.beginTransmission(DS3231_ADDRESS);
  1419. Wire._I2C_WRITE(DS3231_CONTROL);
  1420. Wire.endTransmission();
  1421. Wire.requestFrom((uint8_t)DS3231_ADDRESS, (uint8_t)1);
  1422. mode = Wire._I2C_READ();
  1423. mode &= 0x93;
  1424. return static_cast<Ds3231SqwPinMode>(mode);
  1425. }
  1426. /**************************************************************************/
  1427. /*!
  1428. @brief Set the SQW pin mode
  1429. @param mode Desired mode, see Ds3231SqwPinMode enum
  1430. */
  1431. /**************************************************************************/
  1432. void RTC_DS3231::writeSqwPinMode(Ds3231SqwPinMode mode) {
  1433. uint8_t ctrl;
  1434. ctrl = read_i2c_register(DS3231_ADDRESS, DS3231_CONTROL);
  1435. ctrl &= ~0x04; // turn off INTCON
  1436. ctrl &= ~0x18; // set freq bits to 0
  1437. if (mode == DS3231_OFF) {
  1438. ctrl |= 0x04; // turn on INTCN
  1439. } else {
  1440. ctrl |= mode;
  1441. }
  1442. write_i2c_register(DS3231_ADDRESS, DS3231_CONTROL, ctrl);
  1443. // Serial.println( read_i2c_register(DS3231_ADDRESS, DS3231_CONTROL), HEX);
  1444. }
  1445. /**************************************************************************/
  1446. /*!
  1447. @brief Get the current temperature from the DS3231's temperature sensor
  1448. @return Current temperature (float)
  1449. */
  1450. /**************************************************************************/
  1451. float RTC_DS3231::getTemperature() {
  1452. uint8_t lsb;
  1453. int8_t msb;
  1454. Wire.beginTransmission(DS3231_ADDRESS);
  1455. Wire._I2C_WRITE(DS3231_TEMPERATUREREG);
  1456. Wire.endTransmission();
  1457. Wire.requestFrom(DS3231_ADDRESS, 2);
  1458. msb = Wire._I2C_READ();
  1459. lsb = Wire._I2C_READ();
  1460. // Serial.print("msb=");
  1461. // Serial.print(msb,HEX);
  1462. // Serial.print(", lsb=");
  1463. // Serial.println(lsb,HEX);
  1464. return (float)msb + (lsb >> 6) * 0.25f;
  1465. }
  1466. /**************************************************************************/
  1467. /*!
  1468. @brief Set alarm 1 for DS3231
  1469. @param dt DateTime object
  1470. @param alarm_mode Desired mode, see Ds3231Alarm1Mode enum
  1471. @return False if control register is not set, otherwise true
  1472. */
  1473. /**************************************************************************/
  1474. bool RTC_DS3231::setAlarm1(const DateTime &dt, Ds3231Alarm1Mode alarm_mode) {
  1475. uint8_t ctrl = read_i2c_register(DS3231_ADDRESS, DS3231_CONTROL);
  1476. if (!(ctrl & 0x04)) {
  1477. return false;
  1478. }
  1479. uint8_t A1M1 = (alarm_mode & 0x01) << 7; // Seconds bit 7.
  1480. uint8_t A1M2 = (alarm_mode & 0x02) << 6; // Minutes bit 7.
  1481. uint8_t A1M3 = (alarm_mode & 0x04) << 5; // Hour bit 7.
  1482. uint8_t A1M4 = (alarm_mode & 0x08) << 4; // Day/Date bit 7.
  1483. uint8_t DY_DT = (alarm_mode & 0x10)
  1484. << 2; // Day/Date bit 6. Date when 0, day of week when 1.
  1485. Wire.beginTransmission(DS3231_ADDRESS);
  1486. Wire._I2C_WRITE(DS3231_ALARM1);
  1487. Wire._I2C_WRITE(bin2bcd(dt.second()) | A1M1);
  1488. Wire._I2C_WRITE(bin2bcd(dt.minute()) | A1M2);
  1489. Wire._I2C_WRITE(bin2bcd(dt.hour()) | A1M3);
  1490. if (DY_DT) {
  1491. Wire._I2C_WRITE(bin2bcd(dowToDS3231(dt.dayOfTheWeek())) | A1M4 | DY_DT);
  1492. } else {
  1493. Wire._I2C_WRITE(bin2bcd(dt.day()) | A1M4 | DY_DT);
  1494. }
  1495. Wire.endTransmission();
  1496. ctrl |= 0x01; // AI1E
  1497. write_i2c_register(DS3231_ADDRESS, DS3231_CONTROL, ctrl);
  1498. return true;
  1499. }
  1500. /**************************************************************************/
  1501. /*!
  1502. @brief Set alarm 2 for DS3231
  1503. @param dt DateTime object
  1504. @param alarm_mode Desired mode, see Ds3231Alarm2Mode enum
  1505. @return False if control register is not set, otherwise true
  1506. */
  1507. /**************************************************************************/
  1508. bool RTC_DS3231::setAlarm2(const DateTime &dt, Ds3231Alarm2Mode alarm_mode) {
  1509. uint8_t ctrl = read_i2c_register(DS3231_ADDRESS, DS3231_CONTROL);
  1510. if (!(ctrl & 0x04)) {
  1511. return false;
  1512. }
  1513. uint8_t A2M2 = (alarm_mode & 0x01) << 7; // Minutes bit 7.
  1514. uint8_t A2M3 = (alarm_mode & 0x02) << 6; // Hour bit 7.
  1515. uint8_t A2M4 = (alarm_mode & 0x04) << 5; // Day/Date bit 7.
  1516. uint8_t DY_DT = (alarm_mode & 0x8)
  1517. << 3; // Day/Date bit 6. Date when 0, day of week when 1.
  1518. Wire.beginTransmission(DS3231_ADDRESS);
  1519. Wire._I2C_WRITE(DS3231_ALARM2);
  1520. Wire._I2C_WRITE(bin2bcd(dt.minute()) | A2M2);
  1521. Wire._I2C_WRITE(bin2bcd(dt.hour()) | A2M3);
  1522. if (DY_DT) {
  1523. Wire._I2C_WRITE(bin2bcd(dowToDS3231(dt.dayOfTheWeek())) | A2M4 | DY_DT);
  1524. } else {
  1525. Wire._I2C_WRITE(bin2bcd(dt.day()) | A2M4 | DY_DT);
  1526. }
  1527. Wire.endTransmission();
  1528. ctrl |= 0x02; // AI2E
  1529. write_i2c_register(DS3231_ADDRESS, DS3231_CONTROL, ctrl);
  1530. return true;
  1531. }
  1532. /**************************************************************************/
  1533. /*!
  1534. @brief Disable alarm
  1535. @param alarm_num Alarm number to disable
  1536. */
  1537. /**************************************************************************/
  1538. void RTC_DS3231::disableAlarm(uint8_t alarm_num) {
  1539. uint8_t ctrl = read_i2c_register(DS3231_ADDRESS, DS3231_CONTROL);
  1540. ctrl &= ~(1 << (alarm_num - 1));
  1541. write_i2c_register(DS3231_ADDRESS, DS3231_CONTROL, ctrl);
  1542. }
  1543. /**************************************************************************/
  1544. /*!
  1545. @brief Clear status of alarm
  1546. @param alarm_num Alarm number to clear
  1547. */
  1548. /**************************************************************************/
  1549. void RTC_DS3231::clearAlarm(uint8_t alarm_num) {
  1550. uint8_t status = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG);
  1551. status &= ~(0x1 << (alarm_num - 1));
  1552. write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, status);
  1553. }
  1554. /**************************************************************************/
  1555. /*!
  1556. @brief Get status of alarm
  1557. @param alarm_num Alarm number to check status of
  1558. @return True if alarm has been fired otherwise false
  1559. */
  1560. /**************************************************************************/
  1561. bool RTC_DS3231::alarmFired(uint8_t alarm_num) {
  1562. uint8_t status = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG);
  1563. return (status >> (alarm_num - 1)) & 0x1;
  1564. }
  1565. /**************************************************************************/
  1566. /*!
  1567. @brief Enable 32KHz Output
  1568. @details The 32kHz output is enabled by default. It requires an external
  1569. pull-up resistor to function correctly
  1570. */
  1571. /**************************************************************************/
  1572. void RTC_DS3231::enable32K(void) {
  1573. uint8_t status = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG);
  1574. status |= (0x1 << 0x03);
  1575. write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, status);
  1576. // Serial.println(read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG), BIN);
  1577. }
  1578. /**************************************************************************/
  1579. /*!
  1580. @brief Disable 32KHz Output
  1581. */
  1582. /**************************************************************************/
  1583. void RTC_DS3231::disable32K(void) {
  1584. uint8_t status = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG);
  1585. status &= ~(0x1 << 0x03);
  1586. write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, status);
  1587. // Serial.println(read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG), BIN);
  1588. }
  1589. /**************************************************************************/
  1590. /*!
  1591. @brief Get status of 32KHz Output
  1592. @return True if enabled otherwise false
  1593. */
  1594. /**************************************************************************/
  1595. bool RTC_DS3231::isEnabled32K(void) {
  1596. uint8_t status = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG);
  1597. return (status >> 0x03) & 0x1;
  1598. }