浏览代码

add functions such as GregorianDay and rt_rtc_time_to_tm

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@513 bbd45198-f89e-11dd-88c7-29a3b14d5316
gary.li.wenchao.4 15 年之前
父节点
当前提交
d1fe6cff06
共有 2 个文件被更改,包括 97 次插入8 次删除
  1. 81 0
      libcpu/arm/s3c24x0/rtc.c
  2. 16 8
      libcpu/arm/s3c24x0/rtc.h

+ 81 - 0
libcpu/arm/s3c24x0/rtc.c

@@ -10,6 +10,8 @@
  * Change Logs:
  * Date           Author       Notes
  * 2009-04-26     yi.qiu       first version
+ * 2010-03-18     Gary Lee     add functions such as GregorianDay
+ *                             and rt_rtc_time_to_tm
  */
 
 #include <rtthread.h>
@@ -94,6 +96,85 @@ void rt_hw_rtc_reset (void)
 	RTCCON &= ~(0x08|0x01);
 }
 
+/*
+ * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
+ */
+void GregorianDay(struct rtc_time * tm)
+{
+	int leapsToDate;
+	int lastYear;
+	int day;
+	int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
+
+	lastYear=tm->tm_year-1;
+
+	/*
+	 * Number of leap corrections to apply up to end of last year
+	 */
+	leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
+
+	/*
+	 * This year is a leap year if it is divisible by 4 except when it is
+	 * divisible by 100 unless it is divisible by 400
+	 *
+	 * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
+	 */
+	if((tm->tm_year%4==0) &&
+	   ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
+	   (tm->tm_mon>2)) {
+		/*
+		 * We are past Feb. 29 in a leap year
+		 */
+		day=1;
+	} else {
+		day=0;
+	}
+
+	day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday;
+
+	tm->tm_wday=day%7;
+}
+
+void rt_rtc_time_to_tm(rt_uint32_t tim, struct rtc_time *tm)
+{
+	register int    i;
+	register long   hms, day;
+
+	day = tim / SECDAY;
+	hms = tim % SECDAY;
+
+	/* Hours, minutes, seconds are easy */
+	tm->tm_hour = hms / 3600;
+	tm->tm_min = (hms % 3600) / 60;
+	tm->tm_sec = (hms % 3600) % 60;
+
+	/* Number of years in days */
+	for (i = STARTOFTIME; day >= days_in_year(i); i++) {
+		day -= days_in_year(i);
+	}
+	tm->tm_year = i;
+
+	/* Number of months in days left */
+	if (LEAP_YEAR(tm->tm_year)) {
+		days_in_month(FEBRUARY) = 29;
+	}
+	for (i = 1; day >= days_in_month(i); i++) {
+		day -= days_in_month(i);
+	}
+	days_in_month(FEBRUARY) = 28;
+	tm->tm_mon = i;
+
+	/* Days are what is left over (+1) from all that. */
+	tm->tm_mday = day + 1;
+
+	/*
+	 * Determine the day of week
+	 */
+	GregorianDay(tm);
+}
+
+
+
 static struct rt_device rtc;
 static rt_err_t rt_rtc_open(rt_device_t dev, rt_uint16_t oflag)
 {

+ 16 - 8
libcpu/arm/s3c24x0/rtc.h

@@ -8,16 +8,23 @@
 
 #define RTC_DEBUG
 
-#define	RTC_ENABLE()		(RTCCON |=  0x01)	//RTC read and write enable
-#define	RTC_DISABLE()		(RTCCON &= ~0x01)	//RTC read and write disable
+#define	RTC_ENABLE()		    (RTCCON |=  0x01)	//RTC read and write enable
+#define	RTC_DISABLE()		    (RTCCON &= ~0x01)	//RTC read and write disable
 
-#define BCD2BIN(n)			 (((((n) >> 4) & 0x0F) * 10) + ((n) & 0x0F))
-#define BIN2BCD(n)			 ((((n) / 10) << 4) | ((n) % 10))
+#define BCD2BIN(n)			    (((((n) >> 4) & 0x0F) * 10) + ((n) & 0x0F))
+#define BIN2BCD(n)			    ((((n) / 10) << 4) | ((n) % 10))
 
-#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
-#define LEAP_YEAR(year) 	 ((!(year % 4) && (year % 100)) || !(year % 400))
+#define LEAPS_THRU_END_OF(y)    ((y)/4 - (y)/100 + (y)/400)
+#define LEAP_YEAR(year) 	    ((!(year % 4) && (year % 100)) || !(year % 400))
 
-static const unsigned char days_in_month[] = 
+#define FEBRUARY		        2
+#define	STARTOFTIME		        1970
+#define SECDAY			        86400L
+#define SECYR			        (SECDAY * 365)
+#define	days_in_year(a)		    (LEAP_YEAR(a) ? 366 : 365)
+#define	days_in_month(a)	    (month_days[(a) - 1])
+
+static unsigned char month_days[] = 
 {
 	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
 };
@@ -38,6 +45,7 @@ struct rtc_time
 void rt_hw_rtc_get (struct rtc_time *tmp);
 void rt_hw_rtc_set (struct rtc_time *tmp);
 void rt_hw_rtc_reset (void);
-void rt_rtc_time_to_tm(rt_uint32_t time, struct tm *tm);
+void GregorianDay (struct rtc_time *);
+void rt_rtc_time_to_tm(rt_uint32_t tim, struct rtc_time *tm);
 
 #endif