rtc.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include <arm/NXP/LPC17xx/LPC17xx.h>
  2. #include <arm/bits.h>
  3. #include "config.h"
  4. #include "rtc.h"
  5. #include "uart.h"
  6. #include "timer.h"
  7. #include "power.h"
  8. rtcstate_t rtc_state;
  9. #define CLKEN 0
  10. #define CTCRST 1
  11. uint8_t rtc_isvalid(void) {
  12. if(LPC_RTC->GPREG0 == RTC_MAGIC) {
  13. return RTC_OK;
  14. }
  15. return RTC_INVALID;
  16. }
  17. void rtc_init(void) {
  18. if (LPC_RTC->CCR & BV(CLKEN)) {
  19. rtc_state = RTC_OK;
  20. } else {
  21. rtc_state = RTC_INVALID;
  22. }
  23. }
  24. void read_rtc(struct tm *time) {
  25. do {
  26. time->tm_sec = LPC_RTC->SEC;
  27. time->tm_min = LPC_RTC->MIN;
  28. time->tm_hour = LPC_RTC->HOUR;
  29. time->tm_mday = LPC_RTC->DOM;
  30. time->tm_mon = LPC_RTC->MONTH;
  31. time->tm_year = LPC_RTC->YEAR;
  32. time->tm_wday = LPC_RTC->DOW;
  33. } while (time->tm_sec != LPC_RTC->SEC);
  34. }
  35. uint8_t calc_weekday(struct tm *time) {
  36. int month = time->tm_mon;
  37. int year = time->tm_year;
  38. int day = time->tm_mday;
  39. /* Variation of Sillke for the Gregorian calendar.
  40. * http://www.mathematik.uni-bielefeld.de/~sillke/ALGORITHMS/calendar/weekday.c */
  41. if (month <= 2) {
  42. month += 10;
  43. year--;
  44. } else month -= 2;
  45. return (83*month/32 + day + year + year/4 - year/100 + year/400) % 7;
  46. }
  47. void set_rtc(struct tm *time) {
  48. LPC_RTC->CCR = BV(CTCRST);
  49. LPC_RTC->SEC = time->tm_sec;
  50. LPC_RTC->MIN = time->tm_min;
  51. LPC_RTC->HOUR = time->tm_hour;
  52. LPC_RTC->DOM = time->tm_mday;
  53. LPC_RTC->MONTH = time->tm_mon;
  54. LPC_RTC->YEAR = time->tm_year;
  55. LPC_RTC->DOW = calc_weekday(time);
  56. LPC_RTC->CCR = BV(CLKEN);
  57. LPC_RTC->GPREG0 = RTC_MAGIC;
  58. }
  59. void invalidate_rtc() {
  60. LPC_RTC->GPREG0 = 0;
  61. }
  62. uint32_t get_fattime(void) {
  63. struct tm time;
  64. read_rtc(&time);
  65. return ((uint32_t)time.tm_year-1980) << 25 |
  66. ((uint32_t)time.tm_mon) << 21 |
  67. ((uint32_t)time.tm_mday) << 16 |
  68. ((uint32_t)time.tm_hour) << 11 |
  69. ((uint32_t)time.tm_min) << 5 |
  70. ((uint32_t)time.tm_sec) >> 1;
  71. }
  72. uint64_t get_bcdtime(void) {
  73. struct tm time;
  74. read_rtc(&time);
  75. uint16_t year = time.tm_year;
  76. return ((uint64_t)(time.tm_wday % 7) << 56)
  77. |((uint64_t)((year / 1000) % 10) << 52)
  78. |((uint64_t)((year / 100) % 10) << 48)
  79. |((uint64_t)((year / 10) % 10) << 44)
  80. |((uint64_t)(year % 10) << 40)
  81. |((uint64_t)(time.tm_mon / 10) << 36)
  82. |((uint64_t)(time.tm_mon % 10) << 32)
  83. |((time.tm_mday / 10) << 28)
  84. |((time.tm_mday % 10) << 24)
  85. |((time.tm_hour / 10) << 20)
  86. |((time.tm_hour % 10) << 16)
  87. |((time.tm_min / 10) << 12)
  88. |((time.tm_min % 10) << 8)
  89. |((time.tm_sec / 10) << 4)
  90. |(time.tm_sec % 10);
  91. }
  92. void set_bcdtime(uint64_t btime) {
  93. struct tm time;
  94. time.tm_sec = (btime & 0xf) + ((btime >> 4) & 0xf) * 10;
  95. time.tm_min = ((btime >> 8) & 0xf) + ((btime >> 12) & 0xf) * 10;
  96. time.tm_hour = ((btime >> 16) & 0xf) + ((btime >> 20) & 0xf) * 10;
  97. time.tm_mday = ((btime >> 24) & 0xf) + ((btime >> 28) & 0xf) * 10;
  98. time.tm_mon = ((btime >> 32) & 0xf) + ((btime >> 36) & 0xf) * 10;
  99. time.tm_year = ((btime >> 40) & 0xf) + ((btime >> 44) & 0xf) * 10
  100. + ((btime >> 48) & 0xf) * 100 + ((btime >> 52) & 0xf) * 1000;
  101. printtime(&time);
  102. set_rtc(&time);
  103. }
  104. void printtime(struct tm *time) {
  105. printf("%04d-%02d-%02d %02d:%02d:%02d\n", time->tm_year, time->tm_mon,
  106. time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec);
  107. }
  108. void testbattery() {
  109. printf("%lx\n", LPC_RTC->GPREG0);
  110. LPC_RTC->GPREG0 = RTC_MAGIC;
  111. printf("%lx\n", LPC_RTC->GPREG0);
  112. LPC_RTC->CCR = 0;
  113. BITBAND(LPC_SC->PCONP, PCRTC) = 0;
  114. delay_ms(20000);
  115. BITBAND(LPC_SC->PCONP, PCRTC) = 1;
  116. printf("%lx\n", LPC_RTC->GPREG0);
  117. delay_ms(20);
  118. LPC_RTC->CCR = BV(CLKEN);
  119. }