// convert broken time to calendar time (seconds since 1970) time_t mktime(struct tm *timeptr) { int year=timeptr->tm_year+1900, month=timeptr->tm_mon, i; long seconds; CheckTime(timeptr); // seconds from 1970 till 1 jan 00:00:00 this year seconds= (year-1970)*(60*60*24L*365); // add extra days for leap years for (i=1970; i<year; i++) { if (LEAP_YEAR(i)) { seconds+= 60*60*24L; } } // add days for this year for (i=0; i<month; i++) { if (i==1 && LEAP_YEAR(year)) { seconds+= 60*60*24L*29; } else { seconds+= 60*60*24L*monthDays[i]; } } seconds+= (timeptr->tm_mday-1)*60*60*24L; seconds+= timeptr->tm_hour*60*60L; seconds+= timeptr->tm_min*60; seconds+= timeptr->tm_sec; return seconds; }
// ---------------------------------------------------------------------------- xpcc::UnixTime xpcc::Date::toUnixTimestamp() const { uint16_t currentYear = this->year + 1900; uint32_t seconds; // Seconds from 1970 till 1 Januar 00:00:00 this year seconds = (currentYear - 1970) * (SECONDS_PER_DAY * 365); // Add extra days for leap years for (uint_fast16_t i = 1970; i < currentYear; i++) { if (LEAP_YEAR(i)) { seconds += SECONDS_PER_DAY; } } // Add days for this year for (uint_fast8_t i = 0; i < this->month; i++) { if (i == 1 && LEAP_YEAR(currentYear)) { seconds += SECONDS_PER_DAY * 29; } else { seconds += SECONDS_PER_DAY * monthDays[i]; } } seconds += (this->day - 1) * SECONDS_PER_DAY; seconds += this->hour * 60 * 60; seconds += this->minute * 60; seconds += this->second; return seconds; }
/* Still UNTESTED: create Unix like long representing the date/time */ uint32_t RTCCValue::getTimestamp() { int i; uint32_t tseconds; uint32_t yr = year() + 2000 - 1970; // seconds from 1970 till 1 jan 00:00:00 of the given year tseconds= yr*(SECS_PER_DAY * 365); for (i = 0; i < yr; i++) { if (LEAP_YEAR(i)) { tseconds += SECS_PER_DAY; // add extra days for leap years } } // add days for this year, months start from 1 for (i = 1; i < month(); i++) { if ( (i == 2) && LEAP_YEAR(yr)) { tseconds += SECS_PER_DAY * 29; } else { tseconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0 } } tseconds+= (day()-1) * SECS_PER_DAY; tseconds+= hours() * SECS_PER_HOUR; tseconds+= minutes() * SECS_PER_MIN; tseconds+= seconds(); return tseconds; }
time_t DateTime::convertToUnixTime(int8_t sec, int8_t min, int8_t hour, int8_t day, int8_t month, int16_t year ) { // converts time components to time_t // note year argument is full four digit year (or digits since 2000), i.e.1975, (year 8 is 2008) int i; time_t seconds; if(year < 69) year+= 2000; // seconds from 1970 till 1 jan 00:00:00 this year seconds= (year-1970)*(60*60*24L*365); // add extra days for leap years for (i=1970; i<year; i++) { if (LEAP_YEAR(i)) { seconds+= 60*60*24L; } } // add days for this year for (i=0; i<month; i++) { if (i==1 && LEAP_YEAR(year)) { seconds+= 60*60*24L*29; } else { seconds+= 60*60*24L*monthDays[i]; } } seconds+= (day-1)*3600*24L; seconds+= hour*3600L; seconds+= min*60L; seconds+= sec; return seconds; }
int main(int argc, char **argv) { long num, temp; int year, month; int i, index, cur_m; while(scanf("%ld", &num)!=EOF && num!=-1) { year = 2000; month = 1; index = LEAP_YEAR(year); temp = num; while(num >= diffs[index]) { num -= diffs[index]; ++year; index = LEAP_YEAR(year); } i = 0; cur_m = (*(m_points[index]+i)); while(num >= cur_m) { num -= cur_m; ++i; cur_m = (*(m_points[index]+i)); } printf("%d-%02d-%02ld %s\n", year, i+1, num+1, days[((temp)+6)%7]); } }
time_t makeTime(tmElements_t &tm){ // assemble time elements into time_t // note year argument is offset from 1970 (see macros in time.h to convert to other formats) // previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9 int i; uint32_t seconds; // seconds from 1970 till 1 jan 00:00:00 of the given year seconds= tm.Year*(SECS_PER_DAY * 365); for (i = 0; i < tm.Year; i++) { if (LEAP_YEAR(i)) { seconds += SECS_PER_DAY; // add extra days for leap years } } // add days for this year, months start from 1 for (i = 1; i < tm.Month; i++) { if ( (i == 2) && LEAP_YEAR(tm.Year)) { seconds += SECS_PER_DAY * 29; } else { seconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0 } } seconds+= (tm.Day-1) * SECS_PER_DAY; seconds+= tm.Hour * SECS_PER_HOUR; seconds+= tm.Minute * SECS_PER_MIN; seconds+= tm.Second; return (time_t)seconds; }
/** calc daylight_saving * calculate once on startup if we have to add one addition hour */ bool speedo_clock::is_winter_time(uint8_t year,uint8_t month,uint8_t day,uint8_t hour,uint8_t minute,uint8_t second){ // note year argument is offset from 1970 (see macros in time.h to convert to other formats) // previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9 bool winter; // Sommerzeit berechnen if (month < 3 || month > 10) {// 11, 12, 1 und 2 haben keine Sommerzeit winter = true; } else { uint16_t i; uint32_t seconds; // leap year calulator expects year argument as years offset from 1970 static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0 // GPS commits 13 for 2013, lear year expects offset 1970 => for 2013: 13+30 = 43 year+=30; // seconds from 1970 till 1 jan 00:00:00 of the given year, including all COMPLETED leap years seconds= year*(SECS_PER_DAY * 365); for (i = 0; i < year; i++) { if (LEAP_YEAR(i)) { seconds += SECS_PER_DAY; // add extra days for leap years } } // add days for THIS year, months start from 1 for (i = 1; i < month; i++) { seconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0 if ((i == 2) && LEAP_YEAR(year)) { seconds += SECS_PER_DAY; // add extra day } } // add seconds for this day seconds+= (day-1) * SECS_PER_DAY; //seconds+= hour * SECS_PER_HOUR; //seconds+= minute * SECS_PER_MIN; //seconds+= second; hour+=GMT_TIME_CORRECTION; uint8_t weekday= (seconds / SECS_PER_DAY + 4) % 7; winter = false; // gehen wir mal davon aus das sommerzeit ist if (month == 3) { if ((((int8_t)day - (int8_t)weekday) >= 25) && (weekday || hour >= 2)) { winter = false; // Sommerzeit } else { winter = true; } } else if (month == 10) { if ((((int8_t)day - (int8_t)weekday) >= 25) && (weekday || hour >= 3)) { winter = true; } else { winter = false; } } } return winter; // add DST }
void ICACHE_FLASH_ATTR convertTime() { // given myrtc as time in Linux format break into time components // this is a more compact version of the C library localtime function // note that internally the year is offset from 1970 - compensated at the end uint8_t year; uint8_t month, monthLength; uint32_t time; unsigned long days; time = (uint32_t) myrtc; rtcTime.Second = time % 60; time /= 60; // now it is minutes rtcTime.Minute = time % 60; time /= 60; // now it is hours rtcTime.Hour = time % 24; time /= 24; // now it is days rtcTime.Wday = ((time + 4) % 7) + 1; // Sunday is day 1 year = 0; days = 0; while ((unsigned) (days += (LEAP_YEAR(year) ? 366 : 365)) <= time) { year++; } rtcTime.Year = year; // year is offset from 1970 days -= LEAP_YEAR(year) ? 366 : 365; time -= days; // now it is days in this year, starting at 0 days = 0; month = 0; monthLength = 0; for (month = 0; month < 12; month++) { if (month == 1) { // february if (LEAP_YEAR(year)) { monthLength = 29; } else { monthLength = 28; } } else { monthLength = monthDays[month]; } if (time >= monthLength) { time -= monthLength; } else { break; } } rtcTime.Month = month + 1; // jan is month 1 rtcTime.Day = time + 1; // day of month rtcTime.Year = rtcTime.Year + 1970; }
// NOT IMPLEMENTED BUT WOULD BE NICE ! void RTCCValue::setTimestamp(uint32_t unixTime) { // break the given time_t into time components // this is a more compact version of the C library localtime function // note that year is offset from 1970 !!! uint8_t _year; uint8_t _month, _monthLength; uint32_t _time; unsigned long _days; _time = (uint32_t)unixTime; seconds(_time % 60); _time /= 60; // now it is minutes minutes(_time % 60); _time /= 60; // now it is hours hours(_time % 24); _time /= 24; // now it is days dayOfWeek(((_time + 4) % 7) + 1); // Sunday is day 1 _year = 0; _days = 0; while((unsigned)(_days += (LEAP_YEAR(_year) ? 366 : 365)) <= _time) { _year++; } year((1970 + _year) % 100); // year is offset from 1970 _days -= LEAP_YEAR(_year) ? 366 : 365; _time -= _days; // now it is days in this year, starting at 0 _days=0; _month=0; _monthLength=0; for (_month=0; _month<12; _month++) { if (_month==1) { // february if (LEAP_YEAR(_year)) { _monthLength=29; } else { _monthLength=28; } } else { _monthLength = monthDays[_month]; } if (_time >= _monthLength) { _time -= _monthLength; } else { break; } } month(_month + 1); // jan is month 1 day(_time + 1); // day of month }
void DateTime::convertFromUnixTime(time_t timep, int8_t *psec, int8_t *pmin, int8_t *phour, int8_t *pday, int8_t *pwday, int8_t *pmonth, int16_t *pyear) { // convert the given time_t to time components // this is a more compact version of the C library localtime function time_t long epoch=timep; int8_t year; int8_t month, monthLength; unsigned long days; *psec=epoch%60; epoch/=60; // now it is minutes *pmin=epoch%60; epoch/=60; // now it is hours *phour=epoch%24; epoch/=24; // now it is days *pwday=(epoch+4)%7; year=70; days=0; while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= epoch) { year++; } *pyear=year + 1900; // *pyear is returned as years from 1900 days -= LEAP_YEAR(year) ? 366 : 365; epoch -= days; // now it is days in this year, starting at 0 //*pdayofyear=epoch; // days since jan 1 this year days=0; month=0; monthLength=0; for (month=0; month<12; month++) { if (month==1) { // february if (LEAP_YEAR(year)) { monthLength=29; } else { monthLength=28; } } else { monthLength = monthDays[month]; } if (epoch>=monthLength) { epoch-=monthLength; } else { break; } } *pmonth=month; // jan is month 0 *pday=epoch+1; // day of month }
struct tm *gmtime(time_t *timep) { unsigned long epoch=*timep; unsigned int year; unsigned char month, monthLength; unsigned long days; lastTime.tm_sec=epoch%60; epoch/=60; // now it is minutes lastTime.tm_min=epoch%60; epoch/=60; // now it is hours lastTime.tm_hour=epoch%24; epoch/=24; // now it is days lastTime.tm_wday=(epoch+4)%7; year=1970; days=0; while((days += (LEAP_YEAR(year) ? 366 : 365)) <= epoch) { year++; } lastTime.tm_year=year-1900; days -= LEAP_YEAR(year) ? 366 : 365; epoch -= days; // now it is days in this year, starting at 0 lastTime.tm_yday=epoch; days=0; month=0; monthLength=0; for (month=0; month<12; month++) { if (month==1) { // februari if (LEAP_YEAR(year)) { monthLength=29; } else { monthLength=28; } } else { monthLength = monthDays[month]; } if (epoch>=monthLength) { epoch-=monthLength; } else { break; } } lastTime.tm_mon=month; lastTime.tm_mday=epoch+1; lastTime.tm_isdst=0; return &lastTime; }
void breakTime(time_t timeInput, tmElements_t &tm){ // break the given time_t into time components // this is a more compact version of the C library localtime function // note that year is offset from 1970 !!! uint8_t year; uint8_t month, monthLength; uint32_t time; unsigned long days; time = (uint32_t)timeInput; tm.Second = time % 60; time /= 60; // now it is minutes tm.Minute = time % 60; time /= 60; // now it is hours tm.Hour = time % 24; time /= 24; // now it is days tm.Wday = ((time + 4) % 7) + 1; // Sunday is day 1 year = 0; days = 0; while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) { year++; } tm.Year = year; // year is offset from 1970 days -= LEAP_YEAR(year) ? 366 : 365; time -= days; // now it is days in this year, starting at 0 days=0; month=0; monthLength=0; for (month=0; month<12; month++) { if (month==1) { // february if (LEAP_YEAR(year)) { monthLength=29; } else { monthLength=28; } } else { monthLength = monthDays[month]; } if (time >= monthLength) { time -= monthLength; } else { break; } } tm.Month = month + 1; // jan is month 1 tm.Day = time + 1; // day of month }
// ---------------------------------------------------------------------------- void xpcc::UnixTime::toDate(xpcc::Date* date) const { uint32_t seconds = time; date->second = seconds % 60; seconds /= 60; // now it is minutes date->minute = seconds % 60; seconds /= 60; // now it is hours date->hour = seconds % 24; seconds /= 24; // now it is days // January 1, 1970 was a Thursday. date->dayOfTheWeek = (seconds + 4) % 7; uint16_t year = 1970; uint32_t days = 0; while ((days += (LEAP_YEAR(year) ? 366 : 365)) <= seconds) { year++; } date->year = year - 1900; days -= LEAP_YEAR(year) ? 366 : 365; seconds -= days; // now it is days in this year, starting at 0 date->dayOfTheYear = seconds; uint8_t month; uint8_t monthLength; for (month = 0; month < 12; month++) { if (month == 1) { // Februar if (LEAP_YEAR(year)) { monthLength = 29; } else { monthLength = 28; } } else { monthLength = monthDays[month]; } if (seconds >= monthLength) { seconds -= monthLength; } else { break; } } date->month = month; date->day = seconds + 1; }
// Converts a unix time stamp to a strDateTime structure strDateTime NTPtime::ConvertUnixTimestamp( unsigned long _tempTimeStamp) { strDateTime _tempDateTime; uint8_t _year, _month, _monthLength; uint32_t _time; unsigned long _days; _time = (uint32_t)_tempTimeStamp; _tempDateTime.second = _time % 60; _time /= 60; // now it is minutes _tempDateTime.minute = _time % 60; _time /= 60; // now it is hours _tempDateTime.hour = _time % 24; _time /= 24; // now it is _days _tempDateTime.dayofWeek = ((_time + 4) % 7) + 1; // Sunday is day 1 _year = 0; _days = 0; while ((unsigned)(_days += (LEAP_YEAR(_year) ? 366 : 365)) <= _time) { _year++; } _tempDateTime.year = _year; // year is offset from 1970 _days -= LEAP_YEAR(_year) ? 366 : 365; _time -= _days; // now it is days in this year, starting at 0 _days = 0; _month = 0; _monthLength = 0; for (_month = 0; _month < 12; _month++) { if (_month == 1) { // february if (LEAP_YEAR(_year)) { _monthLength = 29; } else { _monthLength = 28; } } else { _monthLength = _monthDays[_month]; } if (_time >= _monthLength) { _time -= _monthLength; } else { break; } } _tempDateTime.month = _month + 1; // jan is month 1 _tempDateTime.day = _time + 1; // day of month _tempDateTime.year += 1970; return _tempDateTime; }
int rtc_to_tm(int tim, struct rtc_time *tm) { int month_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; register int i; register long hms, day; day = tim / SECDAY; hms = tim % SECDAY; /* Hours, minutes, seconds are easy */ tm->hour = hms / 3600; tm->min = (hms % 3600) / 60; 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->year = i; /* Number of months in days left */ if (LEAP_YEAR(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->mon = i; /* Days are what is left over (+1) from all that */ tm->mday = day + 1; /* Determine the day of week */ return rtc_calc_weekday(tm); }
// dateS minus fixed day, dateS's format(20130915) bool TimeFormat::jianDay(const std::string& dateS, std::string& dateD, const int fixed) { if (dateS.length() != 8) { return false; } int year = 0; int month = 0; int day = 0; try { year = boost::lexical_cast<int>(dateS.substr(0,4)); month = boost::lexical_cast<int>(dateS.substr(4,2)); day = boost::lexical_cast<int>(dateS.substr(6,2)); } catch (const boost::bad_lexical_cast&) { return false; } if (year <= 0 || month <= 0 || month > 12 || day <= 0 || day > 31) { return false; } int fixedT = fixed; while (fixedT) { if (day <= fixedT) { fixedT -= day; if (month > 1) { --month; day = DAYOFMONTH[month]; if (month == 2 && LEAP_YEAR(year)) { day += 1; } } else { year -= 1; month = 12; day = 31; } } else { day -= fixedT; fixedT = 0; break; } } dateD = MAKE_DATE(year, month, day); return true; }
int main() { int year; printf("\ninput year:"); scanf("%d",&year); if(LEAP_YEAR(year)) printf("%d is a leap year.\n",year); else printf("%d is not a leap year. \n",year); return 0; }
int dayofyear(int iyear, int imonth, int idate) { int leap; int idays; int i; leap = LEAP_YEAR(iyear); for (i = 0, idays = 0; i < imonth - 1; i++) { idays += *(*(days_of_month + leap) +i); } idays += idate; return idays; }
int daysofyear(struct tag_date mydate) { int leap; int days; int i; leap = LEAP_YEAR(mydate.nyear); days = 0; for (i = 0; i < mydate.nmonth - 1; i++) { days += days_of_month[leap][i]; } days += mydate.nday; return days; }
/* * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. * Added support for other years than 1970 * needed for example for Palm PDAs */ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) { register int days, month, year; days = time / 86400; time -= days * 86400; /* day of the week, 1970-01-01 was a Thursday */ /* and between 1970-01-01 and EPOCH_YEAR was EPOCH_YEAR_DAYS_DIFFERENCE days */ tm->tm_wday = (days + EPOCH_YEAR_DAYS_DIFFERENCE + 4) % 7; year = EPOCH_YEAR + days / 365; days -= (year - EPOCH_YEAR) * 365 + LEAPS_THRU_END_OF(year - 1) - LEAPS_THRU_END_OF(EPOCH_YEAR - 1); if (days < 0) { year -= 1; days += 365 + LEAP_YEAR(year); } tm->tm_year = year - 1900; tm->tm_yday = days + 1; for (month = 0; month < 11; month++) { int newdays; newdays = days - rtc_month_days(month, year); if (newdays < 0) break; days = newdays; } tm->tm_mon = month; tm->tm_mday = days + 1; tm->tm_hour = time / 3600; time -= tm->tm_hour * 3600; tm->tm_min = time / 60; tm->tm_sec = time - tm->tm_min * 60; }
/* * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. * For PMU59040, 00 in RTCY register means year 2000. */ static void rtc59040_utc_to_tm(unsigned long time, struct rtc_time *tm) { unsigned int month, year; int days; days = time / 86400; //1 day = 86400s time -= (unsigned int) days * 86400; /* day of the week, 1970-01-01 was a Thursday */ tm->tm_wday = (days + 4) % 7; year = 1970 + days / 365; days -= (year - 1970) * 365 + LEAPS_THRU_END_OF(year - 1) - LEAPS_THRU_END_OF(1970 - 1); if (days < 0) { year -= 1; days += 365 + LEAP_YEAR(year); } tm->tm_year = year - 2000; tm->tm_yday = days + 1; for (month = 0; month < 11; month++) { int newdays; newdays = days - rtc_month_days(month, year); if (newdays < 0) break; days = newdays; } tm->tm_mon = month + 1; tm->tm_mday = days + 1; tm->tm_hour = time / 3600; time -= tm->tm_hour * 3600; tm->tm_min = time / 60; tm->tm_sec = time - tm->tm_min * 60; }
/* * convert seconds since 01-01-1970 00:00:00 to gregorian date. */ void rtc_to_time(unsigned long time, struct time *tm) { u32_t month, year; s32_t days; s32_t newdays; days = time / 86400; time -= (u32_t) days * 86400; /* day of the week, 1970-01-01 was a thursday */ tm->week = (days + 4) % 7; year = 1970 + days / 365; days -= (year - 1970) * 365 + LEAPS_THRU_END_OF(year - 1) - LEAPS_THRU_END_OF(1970 - 1); if(days < 0) { year -= 1; days += 365 + LEAP_YEAR(year); } tm->year = year; tm->day = days + 1; for(month = 1; month < 12; month++) { newdays = days - rtc_month_days(year, month); if(newdays < 0) break; days = newdays; } tm->mon = month; tm->day = days + 1; tm->hour = time / 3600; time -= tm->hour * 3600; tm->min = time / 60; tm->sec = time - tm->min * 60; }
static void rtc_to_time(unsigned long time, struct rtc_time_t * rt) { u32_t month, year; s32_t days; s32_t newdays; days = time / 86400; time -= (u32_t) days * 86400; rt->week = (days + 4) % 7; year = 1970 + days / 365; days -= (year - 1970) * 365 + LEAPS_THRU_END_OF(year - 1) - LEAPS_THRU_END_OF(1970 - 1); if(days < 0) { year -= 1; days += 365 + LEAP_YEAR(year); } rt->year = year; rt->day = days + 1; for(month = 1; month < 12; month++) { newdays = days - rtc_month_days(year, month); if(newdays < 0) break; days = newdays; } rt->mon = month; rt->day = days + 1; rt->hour = time / 3600; time -= rt->hour * 3600; rt->min = time / 60; rt->sec = time - rt->min * 60; }
/* * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. */ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) { int days, month, year; days = time / 86400; time -= days * 86400; tm->tm_wday = (days + 4) % 7; year = 1970 + days / 365; days -= (year - 1970) * 365 + LEAPS_THRU_END_OF(year - 1) - LEAPS_THRU_END_OF(1970 - 1); if (days < 0) { year -= 1; days += 365 + LEAP_YEAR(year); } tm->tm_year = year - 1900; tm->tm_yday = days + 1; for (month = 0; month < 11; month++) { int newdays; newdays = days - month_days(month, year); if (newdays < 0) break; days = newdays; } tm->tm_mon = month; tm->tm_mday = days + 1; tm->tm_hour = time / 3600; time -= tm->tm_hour * 3600; tm->tm_min = time / 60; tm->tm_sec = time - tm->tm_min * 60; }
/* * the number of days since January 1. (0 to 365) */ u32_t rtc_year_days(u32_t year, u32_t month, u32_t day) { return rtc_ydays[LEAP_YEAR(year)][month] + day-1; }
static int month_days(unsigned int month, unsigned int year) { return days_in_month[month] + (LEAP_YEAR(year) && month == 1); }
/* * The number of days since January 1. (0 to 365) */ int rtc_year_days(unsigned int day, unsigned int month, unsigned int year) { return rtc_ydays[LEAP_YEAR(year)][month] + day-1; }
static u32_t rtc_month_days(u32_t year, u32_t month) { return rtc_days_in_month[month] + (LEAP_YEAR(year) && month == 2); }
void RP5C01::write_io8(uint32 addr, uint32 data) { addr &= 0x0f; if(addr <= 0x0c) { #ifndef HAS_RP5C15 switch(regs[0x0d] & 3) { #else switch(regs[0x0d] & 1) { #endif case 0: if(time[addr] != data) { time[addr] = data; write_to_cur_time(); } return; #ifndef HAS_RP5C15 case 2: ram[addr] = data; return; case 3: ram[addr + 13] = data; return; #endif } } uint8 tmp = regs[addr] ^ data; regs[addr] = data; if(addr == 0x0a) { if(tmp & 1) { // am/pm is changed read_from_cur_time(); } } else if(addr == 0x0f) { #ifndef HAS_RP5C15 switch(regs[0x0d] & 3) { #else switch(regs[0x0d] & 1) { #endif case 0: if(data & 3) { // timer reset } break; case 1: #ifndef HAS_RP5C15 case 2: case 3: #endif if(data & 2) { // timer reset } if(data & 1) { if(alarm) { alarm = false; update_pulse(); } } break; } } } uint32 RP5C01::read_io8(uint32 addr) { addr &= 0x0f; if(addr <= 0x0c) { #ifndef HAS_RP5C15 switch(regs[0x0d] & 3) { #else switch(regs[0x0d] & 1) { #endif case 0: return time[addr]; #ifndef HAS_RP5C15 case 2: return ram[addr]; case 3: return ram[addr + 13]; #endif } } if(addr == 0x0b) { for(int i = 0; i < 3; i++) { if(LEAP_YEAR(cur_time.year - i)) { return i; } } return 3; } return regs[addr]; } void RP5C01::event_callback(int event_id, int err) { if(event_id == EVENT_1SEC) { if(cur_time.initialized) { cur_time.increment(); } else { emu->get_host_time(&cur_time); // resync cur_time.initialized = true; } if(regs[0x0d] & 8) { read_from_cur_time(); if(regs[0x0d] & 4) { update_pulse(); } } } else if(event_id == EVENT_16HZ) { bool update = false; // 1Hz if(++count_16hz == 16) { pulse_1hz = !pulse_1hz; if(!(regs[0x0f] & 8)) { update = true; } count_16hz = 0; } // 16Hz pulse_16hz = !pulse_16hz; if(!(regs[0x0f] & 4)) { update = true; } if(update) { update_pulse(); } } // update signal } void RP5C01::update_pulse() { bool pulse = false; if(regs[0x0d] & 4) { pulse |= alarm; } if(!(regs[0x0f] & 8)) { pulse |= pulse_1hz; } if(!(regs[0x0f] & 4)) { pulse |= pulse_16hz; } write_signals(&outputs_pulse, pulse ? 0 : 0xffffffff); } #define MODE_12H !(regs[0x0a] & 1) void RP5C01::read_from_cur_time() { int hour = MODE_12H ? (cur_time.hour % 12) : cur_time.hour; int ampm = (MODE_12H && cur_time.hour >= 12) ? 2 : 0; time[ 0] = TO_BCD_LO(cur_time.second); time[ 1] = TO_BCD_HI(cur_time.second); time[ 2] = TO_BCD_LO(cur_time.minute); time[ 3] = TO_BCD_HI(cur_time.minute); time[ 4] = TO_BCD_LO(hour); time[ 5] = TO_BCD_HI(hour) | ampm; time[ 6] = cur_time.day_of_week; time[ 7] = TO_BCD_LO(cur_time.day); time[ 8] = TO_BCD_HI(cur_time.day); time[ 9] = TO_BCD_LO(cur_time.month); time[10] = TO_BCD_HI(cur_time.month); time[11] = TO_BCD_LO(cur_time.year); time[12] = TO_BCD_HI(cur_time.year); // check alarm static uint8 mask[9] = {0, 0, 0x0f, 0x07, 0x0f, 0x03, 0x07, 0x0f, 0x03}; bool tmp = true; for(int i = 3; i < 9; i++) { if((time[i] & mask[i]) != (regs[i] & mask[i])) { tmp = false; break; } } if(tmp) { alarm = true; } }