rtc_ut.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * @brief RTC tick to (a more) Universal Time
  3. * Adds conversion functions to use an RTC that only provides a
  4. * seconds capability to provide "struct tm" support.
  5. *
  6. * @note
  7. * Copyright(C) NXP Semiconductors, 2014
  8. * All rights reserved.
  9. *
  10. * @par
  11. * Software that is described herein is for illustrative purposes only
  12. * which provides customers with programming information regarding the
  13. * LPC products. This software is supplied "AS IS" without any warranties of
  14. * any kind, and NXP Semiconductors and its licensor disclaim any and
  15. * all warranties, express or implied, including all implied warranties of
  16. * merchantability, fitness for a particular purpose and non-infringement of
  17. * intellectual property rights. NXP Semiconductors assumes no responsibility
  18. * or liability for the use of the software, conveys no license or rights under any
  19. * patent, copyright, mask work right, or any other intellectual property rights in
  20. * or to any products. NXP Semiconductors reserves the right to make changes
  21. * in the software without notification. NXP Semiconductors also makes no
  22. * representation or warranty that such application will be suitable for the
  23. * specified use without further testing or modification.
  24. *
  25. * @par
  26. * Permission to use, copy, modify, and distribute this software and its
  27. * documentation is hereby granted, under NXP Semiconductors' and its
  28. * licensor's relevant copyrights in the software, without fee, provided that it
  29. * is used in conjunction with NXP Semiconductors microcontrollers. This
  30. * copyright, permission, and disclaimer notice must appear in all copies of
  31. * this code.
  32. */
  33. #include "rtc_ut.h"
  34. /*****************************************************************************
  35. * Private types/enumerations/variables
  36. ****************************************************************************/
  37. #define SECSPERMIN (60)
  38. #define MINSPERHOUR (60)
  39. #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
  40. #define HOURSPERDAY (24)
  41. #define SECSPERDAY (SECSPERMIN * MINSPERHOUR * HOURSPERDAY)
  42. #define DAYSPERWEEK (7)
  43. #define MONETHSPERYEAR (12)
  44. #define DAYSPERYEAR (365)
  45. #define DAYSPERLEAPYEAR (366)
  46. /* Days per month, LY is special */
  47. static uint8_t daysPerMonth[2][MONETHSPERYEAR] = {
  48. {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, /* Normal year */
  49. {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, /* Leap year */
  50. };
  51. /*****************************************************************************
  52. * Public types/enumerations/variables
  53. ****************************************************************************/
  54. /*****************************************************************************
  55. * Private functions
  56. ****************************************************************************/
  57. /* Converts the number of days offset from the start year to real year
  58. data accounting for leap years */
  59. static void GetDMLY(int dayOff, struct tm *pTime)
  60. {
  61. bool YearFound = false;
  62. int daysYear = dayOff;
  63. int leapYear, curLeapYear, year = TM_YEAR_BASE, monthYear = 0;
  64. bool MonthFound = false;
  65. /* Leap year check for less than 1 year time */
  66. if ((year % 4) == 0) {
  67. curLeapYear = 1;
  68. }
  69. else {
  70. curLeapYear = 0;
  71. }
  72. /* Determine offset of years from days offset */
  73. while (YearFound == false) {
  74. if ((year % 4) == 0) {
  75. /* Leap year, 366 days */
  76. daysYear = DAYSPERLEAPYEAR;
  77. leapYear = 1;
  78. }
  79. else {
  80. /* Leap year, 365 days */
  81. daysYear = DAYSPERYEAR;
  82. leapYear = 0;
  83. }
  84. if (dayOff > daysYear) {
  85. dayOff -= daysYear;
  86. year++;
  87. }
  88. else {
  89. YearFound = true;
  90. curLeapYear = leapYear; /* In a leap year */
  91. }
  92. }
  93. /* Save relative year and day into year */
  94. pTime->tm_year = year - TM_YEAR_BASE; /* Base year relative */
  95. pTime->tm_yday = dayOff;/* 0 relative */
  96. /* Determine offset of months from days offset */
  97. while (MonthFound == false) {
  98. if ((dayOff + 1) > daysPerMonth[curLeapYear][monthYear]) {
  99. /* Next month */
  100. dayOff -= daysPerMonth[curLeapYear][monthYear];
  101. monthYear++;
  102. }
  103. else {
  104. /* Month found */
  105. MonthFound = true;
  106. }
  107. }
  108. pTime->tm_mday = dayOff + 1;/* 1 relative */
  109. pTime->tm_mon = monthYear; /* 0 relative */
  110. }
  111. /*****************************************************************************
  112. * Public functions
  113. ****************************************************************************/
  114. /* Converts an RTC tick time to Universal time */
  115. void ConvertRtcTime(uint32_t rtcTick, struct tm *pTime)
  116. {
  117. int daySeconds, dayNum;
  118. /* Get day offset and seconds since start */
  119. dayNum = (int) (rtcTick / SECSPERDAY);
  120. daySeconds = (int) (rtcTick % SECSPERDAY);
  121. /* Fill in secs, min, hours */
  122. pTime->tm_sec = daySeconds % 60;
  123. pTime->tm_hour = daySeconds / SECSPERHOUR;
  124. pTime->tm_min = (daySeconds - (pTime->tm_hour * SECSPERHOUR)) / SECSPERMIN;
  125. /* Weekday, 0 = Sunday, 6 = Saturday */
  126. pTime->tm_wday = (dayNum + TM_DAYOFWEEK) % DAYSPERWEEK;
  127. /* Get year, month, day of month, and day of year */
  128. GetDMLY(dayNum, pTime);
  129. /* Not supported in this driver */
  130. pTime->tm_isdst = 0;
  131. }
  132. /* Converts a Universal time to RTC tick time */
  133. void ConvertTimeRtc(struct tm *pTime, uint32_t *rtcTick)
  134. {
  135. int leapYear, year = pTime->tm_year + TM_YEAR_BASE;
  136. uint32_t dayOff, monthOff, monthCur, rtcTicks = 0;
  137. /* Leap year check for less than 1 year time */
  138. if ((year % 4) == 0) {
  139. leapYear = 1;
  140. }
  141. else {
  142. leapYear = 0;
  143. }
  144. /* Add days for each year and leap year */
  145. while (year > TM_YEAR_BASE) {
  146. if ((year % 4) == 0) {
  147. /* Leap year, 366 days */
  148. rtcTicks += DAYSPERLEAPYEAR * SECSPERDAY;
  149. leapYear = 1;
  150. }
  151. else {
  152. /* Leap year, 365 days */
  153. rtcTicks += DAYSPERYEAR * SECSPERDAY;
  154. leapYear = 0;
  155. }
  156. year--;
  157. }
  158. /* Day and month are 0 relative offsets since day and month
  159. start at 1 */
  160. dayOff = (uint32_t) pTime->tm_mday - 1;
  161. monthOff = (uint32_t) pTime->tm_mon;
  162. /* Add in seconds for passed months */
  163. for (monthCur = 0; monthCur < monthOff; monthCur++) {
  164. rtcTicks += (uint32_t) (daysPerMonth[leapYear][monthCur] * SECSPERDAY);
  165. }
  166. /* Add in seconds for day offset into the current month */
  167. rtcTicks += (dayOff * SECSPERDAY);
  168. /* Add in seconds for hours, minutes, and seconds */
  169. rtcTicks += (uint32_t) (pTime->tm_hour * SECSPERHOUR);
  170. rtcTicks += (uint32_t) (pTime->tm_min * SECSPERMIN);
  171. rtcTicks += (uint32_t) pTime->tm_sec;
  172. *rtcTick = rtcTicks;
  173. }