//! \file rtc.c //! \author tkl //! \date Jul 8, 2012 //! \brief Source file of the architecture independent rtc implementation. #include #include #include #include "rtc.h" //----------------------------------------------------------------------------- int rtc_open(const struct rtc *device) { if(NULL == device) { return (-1); } rtc_fp_open_t open = device->fp->open; return (open(device->arch_dep_device)); } //----------------------------------------------------------------------------- int rtc_close(const struct rtc *device) { if(NULL == device) { return (-1); } rtc_fp_close_t close = device->fp->close; return (close(device->arch_dep_device)); } //----------------------------------------------------------------------------- void rtc_set_time(const struct rtc *device, const struct loki_time *time) { if(NULL == device) { return; } rtc_fp_set_time_t set_time = device->fp->set_time; set_time(device->arch_dep_device, time); } //----------------------------------------------------------------------------- struct loki_time *rtc_get_time(const struct rtc *device, struct loki_time *time) { if(NULL == device) { return (NULL); } rtc_fp_get_time_t get_time = device->fp->get_time; return (get_time(device->arch_dep_device, time)); } #ifndef __isleap //! Nonzero if YEAR is a leap year (every 4 years, except every 100th isn't, and every 400th is). #define __isleap(year) \ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) #endif //! Seconds per hour. #define SECS_PER_HOUR (long)(60 * 60) //! Seconds per day. #define SECS_PER_DAY (long)(SECS_PER_HOUR * 24) //! Clocks per sec. #define CLOCKS_PER_SEC 1000 static const uint8_t __mon_lengths[2][12] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, /* Normal years. */ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } /* Leap years. */ }; //----------------------------------------------------------------------------- uint32_t time_to_tick(const struct loki_time *time) { if(NULL == time) { return (0); } uint32_t ret = 0; uint32_t year = time->year - 1970; ret = time->sec + time->min * 60 + time->hour * 3600; uint32_t days_in_year = 0; switch(time->mon) { case 1: days_in_year = time->day; break; case 2: days_in_year = time->day + 31; break; case 3: days_in_year = time->day + 31 + 28; break; case 4: days_in_year = time->day + 31 + 28 + 31; break; case 5: days_in_year = time->day + 31 + 28 + 31 + 30; break; case 6: days_in_year = time->day + 31 + 28 + 31 + 30 + 31; break; case 7: days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30; break; case 8: days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31; break; case 9: days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31; break; case 10: days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30; break; case 11: days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31; break; case 12: days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30; break; } if(days_in_year > 0) { days_in_year--; } uint32_t leap_days = 0; uint32_t y = time->year; while(y >= 1970) { leap_days += __isleap(y) ? 1 : 0; y--; } if(__isleap(time->year)) { if(days_in_year < 59) { if(leap_days > 0) { leap_days--; } } } ret += (days_in_year + leap_days) * 60 * 60 * 24; ret += (year * 60 * 60 * 24 * 365); return (ret); } //----------------------------------------------------------------------------- struct loki_time tick_to_time(uint32_t tick) { struct loki_time ret; uint32_t days, rem; uint32_t y; char *ip; days = tick / SECS_PER_DAY; rem = tick % SECS_PER_DAY; while (rem < 0) { rem += SECS_PER_DAY; --days; } while (rem >= SECS_PER_DAY) { rem -= SECS_PER_DAY; ++days; } ret.hour = rem / SECS_PER_HOUR; rem %= SECS_PER_HOUR; ret.min = rem / 60; ret.sec = rem % 60; y = 1970; while (days >= (rem = __isleap(y) ? 366 : 365)) { ++y; days -= rem; } while (days < 0) { --y; days += __isleap(y) ? 366 : 365; } ret.year = y; ip = (char *)__mon_lengths[__isleap(y)]; for (y = 0; days >= ip[y]; ++y) days -= ip[y]; ret.mon = y + 1; ret.day = days + 1; return (ret); } //----------------------------------------------------------------------------- int rtc_start_interval_event(const struct rtc *device, enum rtc_interval interval, const void *callback, const void *argument) { if(NULL == device) { return (-1); } rtc_fp_start_interval_event start_interval = device->fp->start_interval; return (start_interval(device->arch_dep_device, interval, callback, argument)); } //----------------------------------------------------------------------------- int rtc_stop_interval_event(const struct rtc *device) { if(NULL == device) { return (-1); } rtc_fp_stop_interval_event stop_interval = device->fp->stop_interval; return (stop_interval(device->arch_dep_device)); } //----------------------------------------------------------------------------- int rtc_start_alarm_event(const struct rtc *device, const struct loki_time *alarm_time, enum rtc_alarm_mask alarm_mask, const void *callback, const void *argument) { if(NULL == device) { return (-1); } rtc_fp_start_alarm_event start_alarm = device->fp->start_alarm; return (start_alarm(device->arch_dep_device, alarm_time, alarm_mask, callback, argument)); } //----------------------------------------------------------------------------- int rtc_stop_alarm_event(const struct rtc *device) { if(NULL == device) { return (-1); } rtc_fp_stop_alarm_event stop_alarm = device->fp->stop_alarm; return (stop_alarm(device->arch_dep_device)); }