LPCOpen Platform for LPC112X microcontrollers  112X
LPCOpen Platform for the NXP LPC112X family of Microcontrollers
rtc_ut.c
Go to the documentation of this file.
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 
34 #include "rtc_ut.h"
35 
36 /*****************************************************************************
37  * Private types/enumerations/variables
38  ****************************************************************************/
39 
40 #define SECSPERMIN (60)
41 #define MINSPERHOUR (60)
42 #define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
43 #define HOURSPERDAY (24)
44 #define SECSPERDAY (SECSPERMIN * MINSPERHOUR * HOURSPERDAY)
45 #define DAYSPERWEEK (7)
46 #define MONETHSPERYEAR (12)
47 #define DAYSPERYEAR (365)
48 #define DAYSPERLEAPYEAR (366)
49 
50 /* Days per month, LY is special */
51 static uint8_t daysPerMonth[2][MONETHSPERYEAR] = {
52  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, /* Normal year */
53  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, /* Leap year */
54 };
55 
56 /*****************************************************************************
57  * Public types/enumerations/variables
58  ****************************************************************************/
59 
60 /*****************************************************************************
61  * Private functions
62  ****************************************************************************/
63 
64 /* Converts the number of days offset from the start year to real year
65  data accounting for leap years */
66 static void GetDMLY(int dayOff, struct tm *pTime)
67 {
68  bool YearFound = false;
69  int daysYear = dayOff;
70  int leapYear, curLeapYear, year = TM_YEAR_BASE, monthYear = 0;
71  bool MonthFound = false;
72 
73  /* Leap year check for less than 1 year time */
74  if ((year % 4) == 0) {
75  curLeapYear = 1;
76  }
77  else {
78  curLeapYear = 0;
79  }
80 
81  /* Determine offset of years from days offset */
82  while (YearFound == false) {
83  if ((year % 4) == 0) {
84  /* Leap year, 366 days */
85  daysYear = DAYSPERLEAPYEAR;
86  leapYear = 1;
87  }
88  else {
89  /* Leap year, 365 days */
90  daysYear = DAYSPERYEAR;
91  leapYear = 0;
92  }
93 
94  if (dayOff > daysYear) {
95  dayOff -= daysYear;
96  year++;
97  }
98  else {
99  YearFound = true;
100  curLeapYear = leapYear; /* In a leap year */
101  }
102  }
103 
104  /* Save relative year and day into year */
105  pTime->tm_year = year - TM_YEAR_BASE; /* Base year relative */
106  pTime->tm_yday = dayOff;/* 0 relative */
107 
108  /* Determine offset of months from days offset */
109  while (MonthFound == false) {
110  if ((dayOff + 1) > daysPerMonth[curLeapYear][monthYear]) {
111  /* Next month */
112  dayOff -= daysPerMonth[curLeapYear][monthYear];
113  monthYear++;
114  }
115  else {
116  /* Month found */
117  MonthFound = true;
118  }
119  }
120 
121  pTime->tm_mday = dayOff + 1;/* 1 relative */
122  pTime->tm_mon = monthYear; /* 0 relative */
123 }
124 
125 /*****************************************************************************
126  * Public functions
127  ****************************************************************************/
128 
129 /* Converts an RTC tick time to Universal time */
130 void ConvertRtcTime(uint32_t rtcTick, struct tm *pTime)
131 {
132  int daySeconds, dayNum;
133 
134  /* Get day offset and seconds since start */
135  dayNum = (int) (rtcTick / SECSPERDAY);
136  daySeconds = (int) (rtcTick % SECSPERDAY);
137 
138  /* Fill in secs, min, hours */
139  pTime->tm_sec = daySeconds % 60;
140  pTime->tm_hour = daySeconds / SECSPERHOUR;
141  pTime->tm_min = (daySeconds - (pTime->tm_hour * SECSPERHOUR)) / SECSPERMIN;
142 
143  /* Weekday, 0 = Sunday, 6 = Saturday */
144  pTime->tm_wday = (dayNum + TM_DAYOFWEEK) % DAYSPERWEEK;
145 
146  /* Get year, month, day of month, and day of year */
147  GetDMLY(dayNum, pTime);
148 
149  /* Not supported in this driver */
150  pTime->tm_isdst = 0;
151 }
152 
153 /* Converts a Universal time to RTC tick time */
154 void ConvertTimeRtc(struct tm *pTime, uint32_t *rtcTick)
155 {
156  int leapYear, year = pTime->tm_year + TM_YEAR_BASE;
157  uint32_t dayOff, monthOff, monthCur, rtcTicks = 0;
158 
159  /* Leap year check for less than 1 year time */
160  if ((year % 4) == 0) {
161  leapYear = 1;
162  }
163  else {
164  leapYear = 0;
165  }
166 
167  /* Add days for each year and leap year */
168  while (year > TM_YEAR_BASE) {
169  if ((year % 4) == 0) {
170  /* Leap year, 366 days */
171  rtcTicks += DAYSPERLEAPYEAR * SECSPERDAY;
172  leapYear = 1;
173  }
174  else {
175  /* Leap year, 365 days */
176  rtcTicks += DAYSPERYEAR * SECSPERDAY;
177  leapYear = 0;
178  }
179 
180  year--;
181  }
182 
183  /* Day and month are 0 relative offsets since day and month
184  start at 1 */
185  dayOff = (uint32_t) pTime->tm_mday - 1;
186  monthOff = (uint32_t) pTime->tm_mon;
187 
188  /* Add in seconds for passed months */
189  for (monthCur = 0; monthCur < monthOff; monthCur++) {
190  rtcTicks += (uint32_t) (daysPerMonth[leapYear][monthCur] * SECSPERDAY);
191  }
192 
193  /* Add in seconds for day offset into the current month */
194  rtcTicks += (dayOff * SECSPERDAY);
195 
196  /* Add in seconds for hours, minutes, and seconds */
197  rtcTicks += (uint32_t) (pTime->tm_hour * SECSPERHOUR);
198  rtcTicks += (uint32_t) (pTime->tm_min * SECSPERMIN);
199  rtcTicks += (uint32_t) pTime->tm_sec;
200 
201  *rtcTick = rtcTicks;
202 }