static void europc_rtc_timer(int param) { int month, year; europc_rtc.data[0]=bcd_adjust(europc_rtc.data[0]+1); if (europc_rtc.data[0]>=0x60) { europc_rtc.data[0]=0; europc_rtc.data[1]=bcd_adjust(europc_rtc.data[1]+1); if (europc_rtc.data[1]>=0x60) { europc_rtc.data[1]=0; europc_rtc.data[2]=bcd_adjust(europc_rtc.data[2]+1); if (europc_rtc.data[2]>=0x24) { europc_rtc.data[2]=0; europc_rtc.data[3]=bcd_adjust(europc_rtc.data[3]+1); month=bcd_2_dec(europc_rtc.data[4]); year=bcd_2_dec(europc_rtc.data[5])+2000; /* save for julian_days_in_month_calculation */ if (europc_rtc.data[3]> gregorian_days_in_month(month, year)) { europc_rtc.data[3]=1; europc_rtc.data[4]=bcd_adjust(europc_rtc.data[4]+1); if (europc_rtc.data[4]>0x12) { europc_rtc.data[4]=1; europc_rtc.data[5]=bcd_adjust(europc_rtc.data[5]+1)&0xff; } } } } } }
Gregorian Gregorian::add_months(Gregorian const& date, month_t n) { /*auto m = date.month() + n; auto y = date.year() + (m - 1) / 12; m = (m - 1) % 12 + 1; auto d = gregorian_days_in_month(m, is_gregorian_leapyear(y)); if (date.day() < d) d = date.day();*/ year_t y = date.year() + n / 12; month_t m = date.month() + n % 12; auto adjust = (m - 1) / 12 + (m - 12) / 12; y = y + adjust; m = m - adjust * 12; day_t d = min(date.day(), gregorian_days_in_month(m, is_gregorian_leapyear(y))); return Gregorian(y, month_t(m), d, date.hour(), date.minute(), date.second()); }
Gregorian Gregorian::subtract_months(Gregorian const& date, month_t n) { //auto m = date.month() - n; //auto y = date.year() - (m - 1) / 12; //m = (m - 1) % 12 + 1; //auto d = gregorian_days_in_month(m, is_gregorian_leapyear(y)); //if (date.day() < d) // d = date.day(); //return Gregorian(y, month_t(m), d, date.hour(), date.minute(), date.second()); year_t y = date.year() - n / 12; month_t m = date.month() - n % 12; auto adjust = (m - 1) / 12 + (m - 12) / 12; y = y + adjust; m = m - adjust * 12; day_t d = min(date.day(), gregorian_days_in_month(m, is_gregorian_leapyear(y))); return Gregorian(y, month_t(m), d, date.hour(), date.minute(), date.second()); }
void cms_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { int month, year; switch (id) { case TIMER_RTC: m_rtc_data[0] = bcd_adjust(m_rtc_data[0] + 1); if (m_rtc_data[0] >= 0x60) { m_rtc_data[0] = 0; m_rtc_data[1] = bcd_adjust(m_rtc_data[1] + 1); if (m_rtc_data[1] >= 0x60) { m_rtc_data[1] = 0; m_rtc_data[2] = bcd_adjust(m_rtc_data[2] + 1); if (m_rtc_data[2] >= 0x24) { m_rtc_data[2] = 0; m_rtc_data[3] = bcd_adjust(m_rtc_data[3] + 1); month = bcd_2_dec(m_rtc_data[4]); year = bcd_2_dec(m_rtc_data[5]) + 2000; // save for julian_days_in_month_calculation if (m_rtc_data[3]> gregorian_days_in_month(month, year)) { m_rtc_data[3] = 1; m_rtc_data[4] = bcd_adjust(m_rtc_data[4] + 1); if (m_rtc_data[4]>0x12) { m_rtc_data[4] = 1; m_rtc_data[5] = bcd_adjust(m_rtc_data[5] + 1) & 0xff; } } } } } break; } }
void mc146818_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { int year/*, month*/; if (id == TIMER_PERIODIC) { m_data[0x0c] |= 0xc0; if (!m_out_irq_func.isnull()) m_out_irq_func(CLEAR_LINE); return; } if (m_type == MC146818_UTC) { // hack: set correct real time even for overloaded emulation // (at least for apollo) static osd_ticks_t t0 = 0; osd_ticks_t t1 = osd_ticks(); int n_seconds; if (t0 == 0) { t0 = t1; } n_seconds = (t1 - t0) / osd_ticks_per_second(); t0 = t1 - (t1 - t0) % osd_ticks_per_second(); if (n_seconds <= 0) { // we were called to early return; } m_data[0] += n_seconds; } else { m_data[0] += 1; } if (BCD_MODE) { m_data[0]=bcd_adjust(m_data[0]/*+1*/); if (m_data[0]>=0x60) { m_data[0]=0; m_data[2]=bcd_adjust(m_data[2]+1); if (m_data[2]>=0x60) { m_data[2]=0; m_data[4]=bcd_adjust(m_data[4]+1); // different handling of hours if (m_data[4]>=0x24) { m_data[4]=0; WEEK_DAY=bcd_adjust(WEEK_DAY+1)%7; DAY=bcd_adjust(DAY+1); //month=bcd_2_dec(MONTH); year=bcd_2_dec(YEAR); if (m_type!=MC146818_IGNORE_CENTURY) year+=bcd_2_dec(CENTURY)*100; else year+=2000; // save for julian_days_in_month calculation DAY=bcd_adjust(DAY+1); if (DAY>gregorian_days_in_month(MONTH, year)) { DAY=1; MONTH=bcd_adjust(MONTH+1); if (MONTH>0x12) { MONTH=1; YEAR=year=bcd_adjust(YEAR+1); if (m_type!=MC146818_IGNORE_CENTURY) { if (year>=0x100) { CENTURY=bcd_adjust(CENTURY+1); } } } } } } } } else { /*m_data[0]=m_data[0]+1;*/ if (m_data[0]>=60) { m_data[0] -= 60; m_data[2]=m_data[2]+1; if (m_data[2]>=60) { m_data[2]=0; m_data[4]=m_data[4]+1; // different handling of hours //? if (m_data[4]>=24) { m_data[4]=0; WEEK_DAY=(WEEK_DAY+1)%7; year=YEAR; if (m_type!=MC146818_IGNORE_CENTURY) year+=CENTURY*100; else year+=2000; // save for julian_days_in_month calculation if (++DAY>gregorian_days_in_month(MONTH, year)) { DAY=1; if (++MONTH>12) { MONTH=1; YEAR++; if (m_type!=MC146818_IGNORE_CENTURY) { if (YEAR>=100) { CENTURY++;YEAR=0; } } else { YEAR%=100; } } } } } } } if (m_data[1] == m_data[0] && // m_data[3] == m_data[2] && // m_data[5] == m_data[4]) { // set the alarm interrupt flag AF m_data[0x0c] |= 0x20; } else { // clear the alarm interrupt flag AF m_data[0x0c] &= ~0x20; if ((m_data[0x0c] & 0x70) == 0) { // clear IRQF m_data[0x0c] &= ~0x80; } } // set the update-ended interrupt Flag UF m_data[0x0c] |= 0x10; // set the interrupt request flag IRQF // FIXME: should throw IRQ line as well if ((m_data[0x0b] & m_data[0x0c] & 0x30) != 0) { m_data[0x0c] |= 0x80; } // IRQ line is active low if (!m_out_irq_func.isnull()) m_out_irq_func((m_data[0x0c] & 0x80) ? CLEAR_LINE : ASSERT_LINE); m_updated = true; /* clock has been updated */ m_last_refresh = machine().time(); }
void mc146818_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { switch (id) { case TIMER_PERIODIC: m_data[REG_C] |= REG_C_PF; update_irq(); break; case TIMER_CLOCK: if (!(m_data[REG_B] & REG_B_SET)) { /// TODO: find out how the real chip deals with updates when binary/bcd values are already outside the normal range int seconds = get_seconds() + 1; if (seconds < 60) { set_seconds(seconds); } else { set_seconds(0); int minutes = get_minutes() + 1; if (minutes < 60) { set_minutes(minutes); } else { set_minutes(0); int hours = get_hours() + 1; if (hours < 24) { set_hours(hours); } else { set_hours(0); int dayofweek = get_dayofweek() + 1; if (dayofweek <= 7) { set_dayofweek(dayofweek); } else { set_dayofweek(1); } int dayofmonth = get_dayofmonth() + 1; if (dayofmonth <= gregorian_days_in_month(get_month(), get_year() + 2000)) { set_dayofmonth(dayofmonth); } else { set_dayofmonth(1); int month = get_month() + 1; if (month <= 12) { set_month(month); } else { set_month(1); set_year((get_year() + 1) % 100); } } } } } if ((m_data[REG_ALARM_SECONDS] == m_data[REG_SECONDS] || (m_data[REG_ALARM_SECONDS] & ALARM_DONTCARE) == ALARM_DONTCARE) && (m_data[REG_ALARM_MINUTES] == m_data[REG_MINUTES] || (m_data[REG_ALARM_MINUTES] & ALARM_DONTCARE) == ALARM_DONTCARE) && (m_data[REG_ALARM_HOURS] == m_data[REG_HOURS] || (m_data[REG_ALARM_HOURS] & ALARM_DONTCARE) == ALARM_DONTCARE)) { // set the alarm interrupt flag AF m_data[REG_C] |= REG_C_AF; } // set the update-ended interrupt Flag UF m_data[REG_C] |= REG_C_UF; update_irq(); m_last_refresh = machine().time(); } break; } }
static TIMER_CALLBACK( mc146818_timer ) { int year/*, month*/; if (BCD_MODE) { mc146818->data[0]=bcd_adjust(mc146818->data[0]+1); if (mc146818->data[0]>=0x60) { mc146818->data[0]=0; mc146818->data[2]=bcd_adjust(mc146818->data[2]+1); if (mc146818->data[2]>=0x60) { mc146818->data[2]=0; mc146818->data[4]=bcd_adjust(mc146818->data[4]+1); // different handling of hours if (mc146818->data[4]>=0x24) { mc146818->data[4]=0; WEEK_DAY=bcd_adjust(WEEK_DAY+1)%7; DAY=bcd_adjust(DAY+1); //month=bcd_2_dec(MONTH); year=bcd_2_dec(YEAR); if (mc146818->type!=MC146818_IGNORE_CENTURY) year+=bcd_2_dec(CENTURY)*100; else year+=2000; // save for julian_days_in_month calculation DAY=bcd_adjust(DAY+1); if (DAY>gregorian_days_in_month(MONTH, year)) { DAY=1; MONTH=bcd_adjust(MONTH+1); if (MONTH>0x12) { MONTH=1; YEAR=year=bcd_adjust(YEAR+1); if (mc146818->type!=MC146818_IGNORE_CENTURY) { if (year>=0x100) { CENTURY=bcd_adjust(CENTURY+1); } } } } } } } } else { mc146818->data[0]=mc146818->data[0]+1; if (mc146818->data[0]>=60) { mc146818->data[0]=0; mc146818->data[2]=mc146818->data[2]+1; if (mc146818->data[2]>=60) { mc146818->data[2]=0; mc146818->data[4]=mc146818->data[4]+1; // different handling of hours //? if (mc146818->data[4]>=24) { mc146818->data[4]=0; WEEK_DAY=(WEEK_DAY+1)%7; year=YEAR; if (mc146818->type!=MC146818_IGNORE_CENTURY) year+=CENTURY*100; else year+=2000; // save for julian_days_in_month calculation if (++DAY>gregorian_days_in_month(MONTH, year)) { DAY=1; if (++MONTH>12) { MONTH=1; YEAR++; if (mc146818->type!=MC146818_IGNORE_CENTURY) { if (YEAR>=100) { CENTURY++;YEAR=0; } } else { YEAR%=100; } } } } } } } mc146818->updated = 1; /* clock has been updated */ mc146818->last_refresh = timer_get_time(machine); }
void hp98035_io_card::clock_short_press(void) { LOG(("Short press:%u\n" , m_clock_keys)); bool regen = false; int tmp; switch (m_clock_state) { case CLOCK_OFF: if (m_clock_keys == KEY_READ_MASK) { m_clock_state = CLOCK_HHMM; regen = true; } else if (m_clock_keys == KEY_SET_MASK) { m_clock_state = CLOCK_HH; regen = true; } break; case CLOCK_SS: if (m_clock_keys == KEY_SET_MASK) { m_clock_state = CLOCK_HH; regen = true; } else if (m_clock_keys == (KEY_CHG_MASK | KEY_READ_MASK)) { tmp = get_clock_register(RTC_SECOND); tmp++; if (tmp >= 60) { tmp = 0; } set_clock_register(RTC_SECOND , tmp); log_current_time(); //m_clock_1s_div = 0; regen = true; } break; case CLOCK_HH: if (m_clock_keys == KEY_SET_MASK) { m_clock_state = CLOCK_MIN; regen = true; } else if (m_clock_keys == (KEY_CHG_MASK | KEY_READ_MASK)) { tmp = get_clock_register(RTC_HOUR); tmp++; if (tmp >= 24) { tmp = 0; } set_clock_register(RTC_HOUR , tmp); log_current_time(); regen = true; } break; case CLOCK_MIN: if (m_clock_keys == KEY_SET_MASK) { m_clock_state = CLOCK_MON; regen = true; } else if (m_clock_keys == (KEY_CHG_MASK | KEY_READ_MASK)) { tmp = get_clock_register(RTC_MINUTE); tmp++; if (tmp >= 60) { tmp = 0; } set_clock_register(RTC_MINUTE , tmp); set_clock_register(RTC_SECOND , 0); //m_clock_1s_div = 0; log_current_time(); regen = true; } break; case CLOCK_MON: if (m_clock_keys == KEY_SET_MASK) { m_clock_state = CLOCK_DOM; regen = true; } else if (m_clock_keys == (KEY_CHG_MASK | KEY_READ_MASK)) { tmp = get_clock_register(RTC_MONTH); tmp++; if (tmp >= 13) { tmp = 1; } set_clock_register(RTC_MONTH , tmp); log_current_time(); regen = true; } break; case CLOCK_DOM: if (m_clock_keys == KEY_SET_MASK) { m_clock_state = CLOCK_OFF; regen = true; } else if (m_clock_keys == (KEY_CHG_MASK | KEY_READ_MASK)) { tmp = get_clock_register(RTC_DAY); tmp++; if (tmp > gregorian_days_in_month(get_clock_register(RTC_MONTH) , 0)) { tmp = 1; } set_clock_register(RTC_DAY , tmp); log_current_time(); regen = true; } break; default: break; } if (regen) { regen_clock_image(); } }
bool hp98035_io_card::parse_datetime(const uint8_t*& p, uint8_t *out) const { unsigned n_fields = 0; // Fill all fields with EMPTY_FIELD for (unsigned i = 0; i < 5; i++) { out[ i ] = EMPTY_FIELD; } while (n_fields < 5 && *p >= '0' && *p <= '9') { unsigned tmp = *p - '0'; p++; if (*p < '0' || *p > '9') { return false; } // Shift all fields one position to the left memmove(&out[ 0 ] , &out[ 1 ] , 4 * sizeof(out[ 0 ])); // Put the new field in the last position out[ 4 ] = (uint8_t)(tmp * 10 + *p - '0'); n_fields++; p++; } if (n_fields == 0) { return false; } // Seconds if (out[ 4 ] >= 60) { return false; } if (n_fields == 1) { return true; } // Minutes if (out[ 3 ] >= 60) { return false; } if (n_fields == 2) { return true; } // Hours if (out[ 2 ] >= 24) { return false; } if (n_fields == 3) { return true; } // Month uint8_t month; if (n_fields == 4) { month = m_mon; } else { if (out[ 0 ] < 1 || out[ 0 ] > 12) { return false; } month = out[ 0 ]; } // Day of month // Use year 0 here to allow for February 29th if (out[ 1 ] < 1 || out[ 1 ] > gregorian_days_in_month(month , 0)) { return false; } return true; }
void hp98035_io_card::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { if (id == MSEC_TMR_ID) { // Update real time m_msec++; if (m_msec >= 1000) { m_msec = 0; m_sec++; if (m_sec >= 60) { m_sec = 0; m_min++; if (m_min >= 60) { m_min = 0; m_hrs++; if (m_hrs >= 24) { m_hrs = 0; m_dom++; // Use year 1: this RTC doesn't know the year and so it never advances // the date to february 29th if (m_dom > gregorian_days_in_month(m_mon , 1)) { m_dom = 1; m_mon++; if (m_mon > 12) { m_mon = 1; } } } } } // Every second: check if new real time matches in any active output unit for (timer_unit_t& unit : m_units) { if (!unit.m_input && unit.m_state == UNIT_ACTIVE && m_sec == unit.m_match_datetime[ 3 ] && (unit.m_match_datetime[ 2 ] == EMPTY_FIELD || (m_min == unit.m_match_datetime[ 2 ] && (unit.m_match_datetime[ 1 ] == EMPTY_FIELD || (m_hrs == unit.m_match_datetime[ 1 ] && (unit.m_match_datetime[ 0 ] == EMPTY_FIELD || m_dom == unit.m_match_datetime[ 0 ])))))) { // Matched unit.adv_state(); LOG(("matched %02u:%03u %p %d %u\n" , m_sec , m_msec , &unit , unit.m_state , unit.m_value)); } } } // Every ms: advance active units uint8_t triggered = 0; for (timer_unit_t& unit : m_units) { if (unit.m_state != UNIT_IDLE) { if (unit.m_input && unit.m_state == UNIT_ACTIVE) { // Input unit: it just counts msecs // In the real 98035 there is a limit value of 1E+10: not simulated here unit.m_value++; } else if (!unit.m_input && unit.m_state == UNIT_WAIT_FOR_TO && (unit.m_value == 0 || --unit.m_value == 0)) { // Output unit that is not waiting for real time match and that just reached timeout // Triggered! LOG(("triggered %02u:%03u %p\n" , m_sec , m_msec , &unit)); BIT_SET(triggered, unit.m_port - 1); unit.adv_state(); if (unit.m_value == 0) { LOG(("deact %p\n" , &unit)); unit.deactivate(); } } } } // Generate IRQ if (triggered) { // Store which output(s) triggered m_triggered = triggered; if (m_inten) { m_irq = true; update_irq(); LOG(("IRQ %02x\n" , m_triggered)); } else if (m_intflag) { set_error(ERR_MASK_INT_MISSED); // Record lost interrupts m_lost_irq = triggered; LOG(("lost %02x\n" , m_triggered)); } } } }
void mc146818_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { int year/*, month*/; if (id == TIMER_PERIODIC) { m_data[0x0c] |= 0xc0; m_write_irq(CLEAR_LINE); return; } if (BCD_MODE) { m_data[0]=bcd_adjust(m_data[0]+1); if (m_data[0]>=0x60) { m_data[0]=0; m_data[2]=bcd_adjust(m_data[2]+1); if (m_data[2]>=0x60) { m_data[2]=0; m_data[4]=bcd_adjust(m_data[4]+1); // different handling of hours if (m_data[4]>=0x24) { m_data[4]=0; WEEK_DAY=bcd_adjust(WEEK_DAY+1)%7; DAY=bcd_adjust(DAY+1); //month=bcd_2_dec(MONTH); year=bcd_2_dec(YEAR); if (m_type!=MC146818_IGNORE_CENTURY) year+=bcd_2_dec(CENTURY)*100; else year+=2000; // save for julian_days_in_month calculation DAY=bcd_adjust(DAY+1); if (DAY>gregorian_days_in_month(MONTH, year)) { DAY=1; MONTH=bcd_adjust(MONTH+1); if (MONTH>0x12) { MONTH=1; YEAR=year=bcd_adjust(YEAR+1); if (m_type!=MC146818_IGNORE_CENTURY) { if (year>=0x100) { CENTURY=bcd_adjust(CENTURY+1); } } } } } } } } else { m_data[0]=m_data[0]+1; if (m_data[0]>=60) { m_data[0]=0; m_data[2]=m_data[2]+1; if (m_data[2]>=60) { m_data[2]=0; m_data[4]=m_data[4]+1; // different handling of hours //? if (m_data[4]>=24) { m_data[4]=0; WEEK_DAY=(WEEK_DAY+1)%7; year=YEAR; if (m_type!=MC146818_IGNORE_CENTURY) year+=CENTURY*100; else year+=2000; // save for julian_days_in_month calculation if (++DAY>gregorian_days_in_month(MONTH, year)) { DAY=1; if (++MONTH>12) { MONTH=1; YEAR++; if (m_type!=MC146818_IGNORE_CENTURY) { if (YEAR>=100) { CENTURY++;YEAR=0; } } else { YEAR%=100; } } } } } } } if (m_data[1] == m_data[0] && // m_data[3] == m_data[2] && // m_data[5] == m_data[4]) { // set the alarm interrupt flag AF m_data[0x0c] |= 0x20; } else { // clear the alarm interrupt flag AF m_data[0x0c] &= ~0x20; if ((m_data[0x0c] & 0x70) == 0) { // clear IRQF m_data[0x0c] &= ~0x80; } } // set the update-ended interrupt Flag UF m_data[0x0c] |= 0x10; // set the interrupt request flag IRQF // FIXME: should throw IRQ line as well if ((m_data[0x0b] & m_data[0x0c] & 0x30) != 0) { m_data[0x0c] |= 0x80; } // IRQ line is active low m_write_irq((m_data[0x0c] & 0x80) ? CLEAR_LINE : ASSERT_LINE); m_updated = true; /* clock has been updated */ m_last_refresh = machine().time(); }