📄 rtc.java
字号:
{ RTC.this.periodicUpdate(); } public boolean initialised() {return true;} public void acceptComponent(HardwareComponent component){} public void reset(){} public void dumpState(DataOutput output) throws IOException {} public void loadState(DataInput input) throws IOException {} } private class SecondCallback extends AbstractHardwareComponent { public void timerCallback() { RTC.this.secondUpdate(); } public boolean initialised() {return true;} public void acceptComponent(HardwareComponent component){} public void reset(){} public void dumpState(DataOutput output) throws IOException {} public void loadState(DataInput input) throws IOException {} } private class DelayedSecondCallback extends AbstractHardwareComponent { public void timerCallback() { RTC.this.delayedSecondUpdate(); } public boolean initialised() {return true;} public void acceptComponent(HardwareComponent component){} public void reset(){} public void dumpState(DataOutput output) throws IOException {} public void loadState(DataInput input) throws IOException {} } private void periodicUpdate() { this.timerUpdate(nextPeriodicTime); cmosData[RTC_REG_C] |= 0xc0; irqDevice.setIRQ(irq, 1); } private void secondUpdate() { if ((cmosData[RTC_REG_A] & 0x70) != 0x20) { nextSecondTime += timeSource.getTickRate(); secondTimer.setExpiry(nextSecondTime); } else { this.nextSecond(); if (0 == (cmosData[RTC_REG_B] & REG_B_SET)) /* update in progress bit */ cmosData[RTC_REG_A] |= REG_A_UIP; /* should be 244us = 8 / 32768 second, but currently the timers do not have the necessary resolution. */ long delay = (timeSource.getTickRate() * 1) / 100; if (delay < 1) delay = 1; delayedSecondTimer.setExpiry(nextSecondTime + delay); } } private void delayedSecondUpdate() { if (0 == (cmosData[RTC_REG_B] & REG_B_SET)) this.timeToMemory(); /* check alarm */ if (0 != (cmosData[RTC_REG_B] & REG_B_AIE)) { if (((cmosData[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 || cmosData[RTC_SECONDS_ALARM] == currentTime.get(Calendar.SECOND)) && ((cmosData[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 || cmosData[RTC_MINUTES_ALARM] == currentTime.get(Calendar.MINUTE)) && ((cmosData[RTC_HOURS_ALARM] & 0xc0) == 0xc0 || cmosData[RTC_HOURS_ALARM] == currentTime.get(Calendar.HOUR_OF_DAY))) { cmosData[RTC_REG_C] |= 0xa0; irqDevice.setIRQ(irq, 1); } } /* update ended interrupt */ if (0 != (cmosData[RTC_REG_B] & REG_B_UIE)) { cmosData[RTC_REG_C] |= 0x90; irqDevice.setIRQ(irq, 1); } /* clear update in progress bit */ cmosData[RTC_REG_A] &= ~REG_A_UIP; nextSecondTime += timeSource.getTickRate(); secondTimer.setExpiry(nextSecondTime); } private void timerUpdate(long currentTime) { int periodCode = cmosData[RTC_REG_A] & 0x0f; if ((periodCode != 0) && (0 != (cmosData[RTC_REG_B] & REG_B_PIE))) { if (periodCode <= 2) periodCode += 7; /* period in 32 kHz cycles */ int period = 1 << (periodCode -1); /* compute 32 kHz clock */ long currentClock = scale64(currentTime, 32768, (int)timeSource.getTickRate()); long nextIRQClock = (currentClock & ~(period - 1)) + period; nextPeriodicTime = scale64(nextIRQClock, (int)timeSource.getTickRate(), 32768) + 1; periodicTimer.setExpiry(nextPeriodicTime); } else periodicTimer.setStatus(false); } private void nextSecond() { //currentTime = Calendar.getInstance(); currentTime.add(Calendar.SECOND,1); } private void cmosIOPortWrite(int address, int data) { if ((address & 1) == 0) { cmosIndex = (byte)(data & 0x7f); } else { switch(this.cmosIndex) { case RTC_SECONDS_ALARM: case RTC_MINUTES_ALARM: case RTC_HOURS_ALARM: /* XXX: not supported */ cmosData[this.cmosIndex] = (byte)data; break; case RTC_SECONDS: case RTC_MINUTES: case RTC_HOURS: case RTC_DAY_OF_WEEK: case RTC_DAY_OF_MONTH: case RTC_MONTH: case RTC_YEAR: cmosData[this.cmosIndex] = (byte)data; /* if in set mode, do not update the time */ if (0 == (cmosData[RTC_REG_B] & REG_B_SET)) this.memoryToTime(); break; case RTC_REG_A: /* UIP bit is read only */ cmosData[RTC_REG_A] = (byte)((data & ~REG_A_UIP) | (cmosData[RTC_REG_A] & REG_A_UIP)); this.timerUpdate(timeSource.getTime()); break; case RTC_REG_B: if (0 != (data & REG_B_SET)) { /* set mode: reset UIP mode */ cmosData[RTC_REG_A] &= ~REG_A_UIP; data &= ~REG_B_UIE; } else { /* if disabling set mode, update the time */ if (0 != (cmosData[RTC_REG_B] & REG_B_SET)) this.memoryToTime(); } cmosData[RTC_REG_B] = (byte)data; this.timerUpdate(timeSource.getTime()); break; case RTC_REG_C: case RTC_REG_D: /* cannot write to them */ break; default: cmosData[this.cmosIndex] = (byte)data; break; } } } private int cmosIOPortRead(int address) { if ((address & 1) == 0) return 0xff; else { switch(this.cmosIndex) { case RTC_SECONDS: case RTC_MINUTES: case RTC_HOURS: case RTC_DAY_OF_WEEK: case RTC_DAY_OF_MONTH: case RTC_MONTH: case RTC_YEAR: return cmosData[this.cmosIndex]; case RTC_REG_A: return cmosData[this.cmosIndex]; case RTC_REG_C: int ret = cmosData[this.cmosIndex]; irqDevice.setIRQ(irq, 0); cmosData[RTC_REG_C] = (byte)0x00; return ret; default: return cmosData[this.cmosIndex]; } } } private void setTime(Calendar date) { this.currentTime = Calendar.getInstance(date.getTimeZone()); this.currentTime.setTime(date.getTime()); this.timeToMemory(); } private void memoryToTime() { currentTime.set(Calendar.SECOND, this.fromBCD(cmosData[RTC_SECONDS])); currentTime.set(Calendar.MINUTE, this.fromBCD(cmosData[RTC_MINUTES])); currentTime.set(Calendar.HOUR_OF_DAY, this.fromBCD(cmosData[RTC_HOURS] & 0x7f)); if (0 == (cmosData[RTC_REG_B] & 0x02) && 0 != (cmosData[RTC_HOURS] & 0x80)) currentTime.add(Calendar.HOUR_OF_DAY, 12); currentTime.set(Calendar.DAY_OF_WEEK, this.fromBCD(cmosData[RTC_DAY_OF_WEEK])); currentTime.set(Calendar.DAY_OF_MONTH, this.fromBCD(cmosData[RTC_DAY_OF_MONTH])); currentTime.set(Calendar.MONTH, this.fromBCD(cmosData[RTC_MONTH]) - 1); currentTime.set(Calendar.YEAR, this.fromBCD(cmosData[RTC_YEAR]) + 2000); //is this offset correct? } private void timeToMemory() { cmosData[RTC_SECONDS] = (byte)this.toBCD(currentTime.get(Calendar.SECOND)); cmosData[RTC_MINUTES] = (byte)this.toBCD(currentTime.get(Calendar.MINUTE)); if (0 != (cmosData[RTC_REG_B] & 0x02)) /* 24 hour format */ cmosData[RTC_HOURS] = (byte)this.toBCD(currentTime.get(Calendar.HOUR_OF_DAY)); else { /* 12 hour format */ cmosData[RTC_HOURS] = (byte)this.toBCD(currentTime.get(Calendar.HOUR)); if(currentTime.get(Calendar.AM_PM) == Calendar.PM) cmosData[RTC_HOURS] |= 0x80; } cmosData[RTC_DAY_OF_WEEK] = (byte)this.toBCD(currentTime.get(Calendar.DAY_OF_WEEK)); cmosData[RTC_DAY_OF_MONTH] = (byte)this.toBCD(currentTime.get(Calendar.DAY_OF_MONTH)); cmosData[RTC_MONTH] = (byte)this.toBCD(currentTime.get(Calendar.MONTH) + 1); cmosData[RTC_YEAR] = (byte)this.toBCD(currentTime.get(Calendar.YEAR) % 100); } private int toBCD(int a) //Binary Coded Decimal { if (0 != (cmosData[RTC_REG_B] & 0x04)) return a; else return ((a / 10) << 4) | (a % 10); } private int fromBCD(int a) //Binary Coded Decimal { if (0 != (cmosData[RTC_REG_B] & 0x04)) return a; else return ((a >> 4) * 10) + (a & 0x0f); } public boolean initialised() { return ((irqDevice != null) && (timeSource != null) && ioportRegistered && drivesInited && floppiesInited && (bootType >= 0)); } public void reset() { irqDevice = null; timeSource = null; ioportRegistered = false; drivesInited = false; floppiesInited = false; bootType = -1; cmosData = new byte[128]; cmosData[RTC_REG_A] = 0x26; cmosData[RTC_REG_B] = 0x02; cmosData[RTC_REG_C] = 0x00; cmosData[RTC_REG_D] = (byte)0x80; periodicCallback = new PeriodicCallback(); secondCallback = new SecondCallback(); delayedSecondCallback = new DelayedSecondCallback(); } public boolean updated() { return (irqDevice.updated() && timeSource.updated() && ioportRegistered); } public void updateComponent(HardwareComponent component) { if ((component instanceof IOPortHandler) && component.updated()) { ((IOPortHandler)component).registerIOPortCapable(this); ioportRegistered = true; } } public void acceptComponent(HardwareComponent component) { if ((component instanceof InterruptController) && component.initialised()) irqDevice = (InterruptController)component; if ((component instanceof Clock) && component.initialised()) timeSource = (Clock)component; if ((component instanceof IOPortHandler) && component.initialised()) { ((IOPortHandler)component).registerIOPortCapable(this); ioportRegistered = true; } if ((component instanceof DriveSet) && component.initialised()) { this.cmosInitHD((DriveSet)component); drivesInited = true; } if ((component instanceof FloppyController) && component.initialised()) { this.cmosInitFloppy((FloppyController)component); floppiesInited = true; } if (component instanceof DriveSet) bootType = ((DriveSet) component).getBootType(); if (this.initialised()) { init(); periodicTimer = timeSource.newTimer(periodicCallback); secondTimer = timeSource.newTimer(secondCallback); delayedSecondTimer = timeSource.newTimer(delayedSecondCallback); nextSecondTime = timeSource.getTime() + (99 * timeSource.getTickRate())/100; delayedSecondTimer.setExpiry(nextSecondTime); } } public String toString() { return "MC146818 RealTime Clock"; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -