#include #include #include "config.h" #include "rtc.h" #include "uart.h" #include "timer.h" #include "power.h" rtcstate_t rtc_state; #define CLKEN 0 #define CTCRST 1 uint8_t rtc_isvalid(void) { if(LPC_RTC->GPREG0 == RTC_MAGIC) { return RTC_OK; } return RTC_INVALID; } void rtc_init(void) { if (LPC_RTC->CCR & BV(CLKEN)) { rtc_state = RTC_OK; } else { rtc_state = RTC_INVALID; } } void read_rtc(struct tm *time) { do { time->tm_sec = LPC_RTC->SEC; time->tm_min = LPC_RTC->MIN; time->tm_hour = LPC_RTC->HOUR; time->tm_mday = LPC_RTC->DOM; time->tm_mon = LPC_RTC->MONTH; time->tm_year = LPC_RTC->YEAR; time->tm_wday = LPC_RTC->DOW; } while (time->tm_sec != LPC_RTC->SEC); } uint8_t calc_weekday(struct tm *time) { int month = time->tm_mon; int year = time->tm_year; int day = time->tm_mday; /* Variation of Sillke for the Gregorian calendar. * http://www.mathematik.uni-bielefeld.de/~sillke/ALGORITHMS/calendar/weekday.c */ if (month <= 2) { month += 10; year--; } else month -= 2; return (83*month/32 + day + year + year/4 - year/100 + year/400) % 7; } void set_rtc(struct tm *time) { LPC_RTC->CCR = BV(CTCRST); LPC_RTC->SEC = time->tm_sec; LPC_RTC->MIN = time->tm_min; LPC_RTC->HOUR = time->tm_hour; LPC_RTC->DOM = time->tm_mday; LPC_RTC->MONTH = time->tm_mon; LPC_RTC->YEAR = time->tm_year; LPC_RTC->DOW = calc_weekday(time); LPC_RTC->CCR = BV(CLKEN); LPC_RTC->GPREG0 = RTC_MAGIC; } void invalidate_rtc() { LPC_RTC->GPREG0 = 0; } uint32_t get_fattime(void) { struct tm time; read_rtc(&time); return ((uint32_t)time.tm_year-1980) << 25 | ((uint32_t)time.tm_mon) << 21 | ((uint32_t)time.tm_mday) << 16 | ((uint32_t)time.tm_hour) << 11 | ((uint32_t)time.tm_min) << 5 | ((uint32_t)time.tm_sec) >> 1; } uint64_t get_bcdtime(void) { struct tm time; read_rtc(&time); uint16_t year = time.tm_year; return ((uint64_t)(time.tm_wday % 7) << 56) |((uint64_t)((year / 1000) % 10) << 52) |((uint64_t)((year / 100) % 10) << 48) |((uint64_t)((year / 10) % 10) << 44) |((uint64_t)(year % 10) << 40) |((uint64_t)(time.tm_mon / 10) << 36) |((uint64_t)(time.tm_mon % 10) << 32) |((time.tm_mday / 10) << 28) |((time.tm_mday % 10) << 24) |((time.tm_hour / 10) << 20) |((time.tm_hour % 10) << 16) |((time.tm_min / 10) << 12) |((time.tm_min % 10) << 8) |((time.tm_sec / 10) << 4) |(time.tm_sec % 10); } void set_bcdtime(uint64_t btime) { struct tm time; time.tm_sec = (btime & 0xf) + ((btime >> 4) & 0xf) * 10; time.tm_min = ((btime >> 8) & 0xf) + ((btime >> 12) & 0xf) * 10; time.tm_hour = ((btime >> 16) & 0xf) + ((btime >> 20) & 0xf) * 10; time.tm_mday = ((btime >> 24) & 0xf) + ((btime >> 28) & 0xf) * 10; time.tm_mon = ((btime >> 32) & 0xf) + ((btime >> 36) & 0xf) * 10; time.tm_year = ((btime >> 40) & 0xf) + ((btime >> 44) & 0xf) * 10 + ((btime >> 48) & 0xf) * 100 + ((btime >> 52) & 0xf) * 1000; printtime(&time); set_rtc(&time); } void printtime(struct tm *time) { printf("%04d-%02d-%02d %02d:%02d:%02d\n", time->tm_year, time->tm_mon, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec); } void testbattery() { printf("%lx\n", LPC_RTC->GPREG0); LPC_RTC->GPREG0 = RTC_MAGIC; printf("%lx\n", LPC_RTC->GPREG0); LPC_RTC->CCR = 0; BITBAND(LPC_SC->PCONP, PCRTC) = 0; delay_ms(20000); BITBAND(LPC_SC->PCONP, PCRTC) = 1; printf("%lx\n", LPC_RTC->GPREG0); delay_ms(20); LPC_RTC->CCR = BV(CLKEN); }