PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

219 line
5.9KB

  1. /*
  2. * DS1307RTC.h - library for DS1307 RTC
  3. Copyright (c) Michael Margolis 2009
  4. This library is intended to be uses with Arduino Time library functions
  5. The library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with this library; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. 30 Dec 2009 - Initial release
  17. 5 Sep 2011 updated for Arduino 1.0
  18. */
  19. #if defined (__AVR_ATtiny84__) || defined(__AVR_ATtiny85__) || (__AVR_ATtiny2313__)
  20. #include <TinyWireM.h>
  21. #define Wire TinyWireM
  22. #else
  23. #include <Wire.h>
  24. #endif
  25. #include "DS1307RTC.h"
  26. #define DS1307_CTRL_ID 0x68
  27. DS1307RTC::DS1307RTC()
  28. {
  29. Wire.begin();
  30. }
  31. // PUBLIC FUNCTIONS
  32. time_t DS1307RTC::get() // Aquire data from buffer and convert to time_t
  33. {
  34. tmElements_t tm;
  35. if (read(tm) == false) return 0;
  36. return(makeTime(tm));
  37. }
  38. bool DS1307RTC::set(time_t t)
  39. {
  40. tmElements_t tm;
  41. breakTime(t, tm);
  42. return write(tm);
  43. }
  44. // Aquire data from the RTC chip in BCD format
  45. bool DS1307RTC::read(tmElements_t &tm)
  46. {
  47. uint8_t sec;
  48. Wire.beginTransmission(DS1307_CTRL_ID);
  49. #if ARDUINO >= 100
  50. Wire.write((uint8_t)0x00);
  51. #else
  52. Wire.send(0x00);
  53. #endif
  54. if (Wire.endTransmission() != 0) {
  55. exists = false;
  56. return false;
  57. }
  58. exists = true;
  59. // request the 7 data fields (secs, min, hr, dow, date, mth, yr)
  60. Wire.requestFrom(DS1307_CTRL_ID, tmNbrFields);
  61. if (Wire.available() < tmNbrFields) return false;
  62. #if ARDUINO >= 100
  63. sec = Wire.read();
  64. tm.Second = bcd2dec(sec & 0x7f);
  65. tm.Minute = bcd2dec(Wire.read() );
  66. tm.Hour = bcd2dec(Wire.read() & 0x3f); // mask assumes 24hr clock
  67. tm.Wday = bcd2dec(Wire.read() );
  68. tm.Day = bcd2dec(Wire.read() );
  69. tm.Month = bcd2dec(Wire.read() );
  70. tm.Year = y2kYearToTm((bcd2dec(Wire.read())));
  71. #else
  72. sec = Wire.receive();
  73. tm.Second = bcd2dec(sec & 0x7f);
  74. tm.Minute = bcd2dec(Wire.receive() );
  75. tm.Hour = bcd2dec(Wire.receive() & 0x3f); // mask assumes 24hr clock
  76. tm.Wday = bcd2dec(Wire.receive() );
  77. tm.Day = bcd2dec(Wire.receive() );
  78. tm.Month = bcd2dec(Wire.receive() );
  79. tm.Year = y2kYearToTm((bcd2dec(Wire.receive())));
  80. #endif
  81. if (sec & 0x80) return false; // clock is halted
  82. return true;
  83. }
  84. bool DS1307RTC::write(tmElements_t &tm)
  85. {
  86. // To eliminate any potential race conditions,
  87. // stop the clock before writing the values,
  88. // then restart it after.
  89. Wire.beginTransmission(DS1307_CTRL_ID);
  90. #if ARDUINO >= 100
  91. Wire.write((uint8_t)0x00); // reset register pointer
  92. Wire.write((uint8_t)0x80); // Stop the clock. The seconds will be written last
  93. Wire.write(dec2bcd(tm.Minute));
  94. Wire.write(dec2bcd(tm.Hour)); // sets 24 hour format
  95. Wire.write(dec2bcd(tm.Wday));
  96. Wire.write(dec2bcd(tm.Day));
  97. Wire.write(dec2bcd(tm.Month));
  98. Wire.write(dec2bcd(tmYearToY2k(tm.Year)));
  99. #else
  100. Wire.send(0x00); // reset register pointer
  101. Wire.send(0x80); // Stop the clock. The seconds will be written last
  102. Wire.send(dec2bcd(tm.Minute));
  103. Wire.send(dec2bcd(tm.Hour)); // sets 24 hour format
  104. Wire.send(dec2bcd(tm.Wday));
  105. Wire.send(dec2bcd(tm.Day));
  106. Wire.send(dec2bcd(tm.Month));
  107. Wire.send(dec2bcd(tmYearToY2k(tm.Year)));
  108. #endif
  109. if (Wire.endTransmission() != 0) {
  110. exists = false;
  111. return false;
  112. }
  113. exists = true;
  114. // Now go back and set the seconds, starting the clock back up as a side effect
  115. Wire.beginTransmission(DS1307_CTRL_ID);
  116. #if ARDUINO >= 100
  117. Wire.write((uint8_t)0x00); // reset register pointer
  118. Wire.write(dec2bcd(tm.Second)); // write the seconds, with the stop bit clear to restart
  119. #else
  120. Wire.send(0x00); // reset register pointer
  121. Wire.send(dec2bcd(tm.Second)); // write the seconds, with the stop bit clear to restart
  122. #endif
  123. if (Wire.endTransmission() != 0) {
  124. exists = false;
  125. return false;
  126. }
  127. exists = true;
  128. return true;
  129. }
  130. unsigned char DS1307RTC::isRunning()
  131. {
  132. Wire.beginTransmission(DS1307_CTRL_ID);
  133. #if ARDUINO >= 100
  134. Wire.write((uint8_t)0x00);
  135. #else
  136. Wire.send(0x00);
  137. #endif
  138. Wire.endTransmission();
  139. // Just fetch the seconds register and check the top bit
  140. Wire.requestFrom(DS1307_CTRL_ID, 1);
  141. #if ARDUINO >= 100
  142. return !(Wire.read() & 0x80);
  143. #else
  144. return !(Wire.receive() & 0x80);
  145. #endif
  146. }
  147. void DS1307RTC::setCalibration(char calValue)
  148. {
  149. unsigned char calReg = abs(calValue) & 0x1f;
  150. if (calValue >= 0) calReg |= 0x20; // S bit is positive to speed up the clock
  151. Wire.beginTransmission(DS1307_CTRL_ID);
  152. #if ARDUINO >= 100
  153. Wire.write((uint8_t)0x07); // Point to calibration register
  154. Wire.write(calReg);
  155. #else
  156. Wire.send(0x07); // Point to calibration register
  157. Wire.send(calReg);
  158. #endif
  159. Wire.endTransmission();
  160. }
  161. char DS1307RTC::getCalibration()
  162. {
  163. Wire.beginTransmission(DS1307_CTRL_ID);
  164. #if ARDUINO >= 100
  165. Wire.write((uint8_t)0x07);
  166. #else
  167. Wire.send(0x07);
  168. #endif
  169. Wire.endTransmission();
  170. Wire.requestFrom(DS1307_CTRL_ID, 1);
  171. #if ARDUINO >= 100
  172. unsigned char calReg = Wire.read();
  173. #else
  174. unsigned char calReg = Wire.receive();
  175. #endif
  176. char out = calReg & 0x1f;
  177. if (!(calReg & 0x20)) out = -out; // S bit clear means a negative value
  178. return out;
  179. }
  180. // PRIVATE FUNCTIONS
  181. // Convert Decimal to Binary Coded Decimal (BCD)
  182. uint8_t DS1307RTC::dec2bcd(uint8_t num)
  183. {
  184. return ((num/10 * 16) + (num % 10));
  185. }
  186. // Convert Binary Coded Decimal (BCD) to Decimal
  187. uint8_t DS1307RTC::bcd2dec(uint8_t num)
  188. {
  189. return ((num/16 * 10) + (num % 16));
  190. }
  191. bool DS1307RTC::exists = false;
  192. DS1307RTC RTC = DS1307RTC(); // create an instance for the user