ds1307rtc.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. * Copyright (C) 2006 by egnite Software GmbH and Christian Welzel.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the copyright holders nor the names of
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  21. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  22. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  23. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  24. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  25. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  26. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  27. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  28. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. *
  31. * For additional information see http://www.ethernut.de/
  32. *
  33. */
  34. /*!
  35. * \file dev/ds1307rtc.c
  36. * \brief RTC and RAM routines for the Dallas DS1307 clock chip.
  37. *
  38. * \verbatim
  39. *
  40. * $Log$
  41. * Revision 1.6 2008/08/11 06:59:42 haraldkipp
  42. * BSD types replaced by stdint types (feature request #1282721).
  43. *
  44. * Revision 1.5 2007/09/11 17:32:30 haraldkipp
  45. * Last minute fix (bug #1786271)
  46. *
  47. * Revision 1.4 2006/10/08 16:39:33 haraldkipp
  48. * Corrected range check in DS1307RamRead(). Thanks to Helmut Holbach.
  49. *
  50. * Revision 1.3 2006/10/05 17:18:49 haraldkipp
  51. * Hardware independant RTC layer added.
  52. *
  53. * Revision 1.2 2006/08/25 13:42:55 olereinhardt
  54. * avr-gcc 3.4 does not understand binary representation of numbers,
  55. * changed to hex
  56. *
  57. * Revision 1.1 2006/06/30 22:05:51 christianwelzel
  58. * Initial check in.
  59. *
  60. *
  61. * \endverbatim
  62. */
  63. #include <cfg/os.h>
  64. #include <dev/twif.h>
  65. #include <sys/event.h>
  66. #include <sys/timer.h>
  67. #include <stdlib.h>
  68. #include <string.h>
  69. #include <dev/ds1307rtc.h>
  70. #ifndef I2C_SLA_RTC
  71. #define I2C_SLA_RTC 0x68 // 7 bit address!
  72. #endif
  73. /*!
  74. * \brief Read RTC registers.
  75. *
  76. * \param reg The first register to read.
  77. * \param buff Pointer to a buffer that receives the register contents.
  78. * \param cnt The number of registers to read.
  79. *
  80. * \return 0 on success or -1 in case of an error.
  81. */
  82. int DS1307RtcReadRegs(uint8_t reg, uint8_t *buff, size_t cnt)
  83. {
  84. int rc = -1;
  85. uint8_t wbuf[1];
  86. wbuf[0] = reg;
  87. if (TwMasterTransact(I2C_SLA_RTC, wbuf, 1, buff, cnt, NUT_WAIT_INFINITE) == cnt) {
  88. rc = 0;
  89. }
  90. return rc;
  91. }
  92. /*!
  93. * \brief Write to RTC registers.
  94. *
  95. * \param buff This buffer must contain all bytes to be transfered to
  96. * the RTC chip, including the register address.
  97. * \param cnt Number of valid bytes in the buffer.
  98. *
  99. * \return 0 on success or -1 in case of an error.
  100. */
  101. int DS1307RtcWrite(const uint8_t *buff, size_t cnt)
  102. {
  103. int rc;
  104. rc = TwMasterTransact(I2C_SLA_RTC, buff, cnt, 0, 0, NUT_WAIT_INFINITE);
  105. return rc;
  106. }
  107. /*!
  108. * \brief Get date and time from an DS1307 hardware clock.
  109. *
  110. * \param tm Points to a structure that receives the date and time
  111. * information.
  112. *
  113. * \return 0 on success or -1 in case of an error.
  114. */
  115. int DS1307RtcGetClock(NUTRTC *rtc, struct _tm *tm)
  116. {
  117. int rc;
  118. uint8_t data[7];
  119. if ((rc = DS1307RtcReadRegs(0x00, data, 7)) == 0) {
  120. tm->tm_sec = BCD2BIN(data[0]);
  121. tm->tm_min = BCD2BIN(data[1]);
  122. tm->tm_hour = BCD2BIN(data[2] & 0x3F);
  123. tm->tm_mday = BCD2BIN(data[4]);
  124. tm->tm_mon = BCD2BIN(data[5]) - 1;
  125. tm->tm_year = BCD2BIN(data[6]) + 100;
  126. tm->tm_wday = data[3] - 1;
  127. }
  128. return rc;
  129. }
  130. /*!
  131. * \brief Set the DS1307 hardware clock.
  132. *
  133. * \param tm Points to a structure which contains the date and time
  134. * information.
  135. *
  136. * \return 0 on success or -1 in case of an error.
  137. */
  138. int DS1307RtcSetClock(NUTRTC *rtc, const struct _tm *tm)
  139. {
  140. uint8_t data[8];
  141. memset(data, 0, sizeof(data));
  142. if (tm) {
  143. data[0] = 0x00; // adress 0
  144. data[1] = BIN2BCD(tm->tm_sec);
  145. data[2] = BIN2BCD(tm->tm_min);
  146. data[3] = BIN2BCD(tm->tm_hour) & 0x3f; // 24 hour mode
  147. data[5] = BIN2BCD(tm->tm_mday);
  148. data[6] = BIN2BCD(tm->tm_mon + 1);
  149. data[7] = BIN2BCD(tm->tm_year - 100);
  150. data[4] = tm->tm_wday + 1;
  151. }
  152. return DS1307RtcWrite(data, 8);
  153. }
  154. /*!
  155. * \brief Read contents from DS1307 RAM.
  156. *
  157. * \param addr Start location.
  158. * \param buff Points to a buffer that receives the contents.
  159. * \param cnt Number of bytes to read.
  160. *
  161. * \return 0 on success or -1 in case of an error.
  162. */
  163. int DS1307RamRead(uint8_t addr, uint8_t *buff, size_t cnt)
  164. {
  165. int rc = -1;
  166. // Range check
  167. if ((addr>=0x08) && (addr<=0x3F)) {
  168. rc = DS1307RtcReadRegs(addr, buff, cnt);
  169. }
  170. return rc;
  171. }
  172. /*!
  173. * \brief Store buffer contents in DS1307 RAM.
  174. *
  175. * \param addr Storage start location.
  176. * \param buff Points to a buffer that contains the bytes to store.
  177. * \param len Number of valid bytes in the buffer.
  178. *
  179. * \return 0 on success or -1 in case of an error.
  180. */
  181. int DS1307RamWrite(uint8_t addr, const void *buff, size_t len)
  182. {
  183. int rc = 0;
  184. uint8_t *wbuf;
  185. const uint8_t *wp = buff;
  186. /* Allocate and set a TWI write buffer. */
  187. if ((wbuf = malloc(len + 1)) == 0) {
  188. rc = -1;
  189. } else {
  190. wbuf[0] = addr;
  191. memcpy(wbuf + 1, wp, len);
  192. /* Send the write buffer. */
  193. rc = TwMasterTransact(I2C_SLA_RTC, wbuf, len + 1, 0, 0, NUT_WAIT_INFINITE);
  194. /* Release the buffer. */
  195. free(wbuf);
  196. }
  197. return rc;
  198. }
  199. /*!
  200. * \brief Initialize the interface to an Dallas DS1307 hardware clock.
  201. *
  202. * \return 0 on success or -1 in case of an error.
  203. *
  204. */
  205. int DS1307Init(NUTRTC *rtc)
  206. {
  207. int rc;
  208. uint8_t data;
  209. uint8_t buff[2];
  210. if ((rc = TwInit(0)) == 0 ) {
  211. // Enable Oszillator
  212. if ((rc = DS1307RtcReadRegs(0x00, &data, 1)) == 0) {
  213. buff[0] = 0x00;
  214. buff[1] = data & 0x7F; //0b01111111;
  215. rc = DS1307RtcWrite(buff, 2);
  216. }
  217. // Enable 24h Mode
  218. if ((rc = DS1307RtcReadRegs(0x02, &data, 1)) == 0) {
  219. buff[0] = 0x02;
  220. buff[1] = data & 0xBF; //0b10111111;
  221. rc = DS1307RtcWrite(buff, 2);
  222. }
  223. }
  224. return rc;
  225. }
  226. NUTRTC rtcDs1307 = {
  227. /*.dcb = */ NULL, /*!< Driver control block */
  228. /*.rtc_init = */ DS1307Init, /*!< Hardware initializatiuon, rtc_init */
  229. /*.rtc_gettime = */ DS1307RtcGetClock, /*!< Read date and time, rtc_gettime */
  230. /*.rtc_settime = */ DS1307RtcSetClock, /*!< Set date and time, rtc_settime */
  231. /*.rtc_getalarm = */ NULL, /*!< Read alarm date and time, rtc_getalarm */
  232. /*.rtc_setalarm = */ NULL, /*!< Set alarm date and time, rtc_setalarm */
  233. /*.rtc_getstatus = */ NULL, /*!< Read status flags, rtc_getstatus */
  234. /*.rtc_clrstatus = */ NULL, /*!< Clear status flags, rtc_clrstatus */
  235. /*.alarm = */ NULL, /*!< Handle for alarm event queue, not supported right now */
  236. };