implemented sim timer and clock

This commit is contained in:
Irmen de Jong 2019-09-09 04:51:18 +02:00
parent bdcd10512f
commit 2cf9af4a6e
3 changed files with 166 additions and 13 deletions

View File

@ -25,20 +25,37 @@ private fun startSimulator(args: Array<String>) {
val ram = Ram(0, 0xffff)
ram[RESET_vector] = 0x00
ram[RESET_vector + 1] = 0x10
// // read the RTC and write the date+time to $2000
// for(b in listOf(0xa0, 0x00, 0xb9, 0x00, 0xd1, 0x99, 0x00, 0x20, 0xc8, 0xc0, 0x09, 0xd0, 0xf5, 0x00).withIndex()) {
// ram[0x1000+b.index] = b.value.toShort()
// }
// set the timer to $22aa00 and enable it on regular irq
for(b in listOf(0xa9, 0x00, 0x8d, 0x00, 0xd2, 0xa9, 0x00, 0x8d, 0x01, 0xd2, 0xa9, 0xaa, 0x8d, 0x02,
0xd2, 0xa9, 0x22, 0x8d, 0x03, 0xd2, 0xa9, 0x01, 0x8d, 0x00, 0xd2, 0x4c, 0x19, 0x10).withIndex()) {
ram[0x1000+b.index] = b.value.toShort()
}
val parallel = ParallelPort(0xd000, 0xd001)
val timer = Timer(0xd100, 0xd103)
val clock = RealTimeClock(0xd100, 0xd108)
val timer = Timer(0xd200, 0xd203)
val bus = Bus()
bus.add(cpu)
bus.add(parallel)
bus.add(clock)
bus.add(timer)
bus.add(ram)
bus.reset()
cpu.tracing = true
while (true) {
bus.clock()
try {
while (true) {
bus.clock()
}
} catch (ix: InstructionError) {
// ignore
}
ram.hexDump(0x2000, 0x2008)
}

View File

@ -0,0 +1,79 @@
package sim65.components
import java.util.*
/**
* A real-time clock (time of day clock).
* byte value
* 00 year (lsb)
* 01 year (msb)
* 02 month, 1-12
* 03 day, 1-31
* 04 hour, 0-23
* 05 minute, 0-59
* 06 second, 0-59
* 07 millisecond, 0-999 (lsb)
* 08 millisecond, 0-999 (msb)
*/
class RealTimeClock(startAddress: Address, endAddress: Address) : MemMappedComponent(startAddress, endAddress) {
val calendar = Calendar.getInstance()
init {
require(endAddress - startAddress + 1 == 9) { "rtc needs exactly 9 memory bytes" }
}
override fun clock() {
/* not updated on clock pulse */
}
override fun reset() {
/* never reset */
}
override operator fun get(address: Address): UByte {
when (address - startAddress) {
0 -> {
val year = calendar.get(Calendar.YEAR)
return (year and 255).toShort()
}
1 -> {
val year = calendar.get(Calendar.YEAR)
return (year ushr 8).toShort()
}
2 -> {
val month = calendar.get(Calendar.MONTH) + 1
return month.toShort()
}
3 -> {
val day = calendar.get(Calendar.DAY_OF_MONTH)
return day.toShort()
}
4 -> {
val hour = calendar.get(Calendar.HOUR_OF_DAY)
return hour.toShort()
}
5 -> {
val minute = calendar.get(Calendar.MINUTE)
return minute.toShort()
}
6 -> {
val second = calendar.get(Calendar.SECOND)
return second.toShort()
}
7 -> {
val ms = calendar.get(Calendar.MILLISECOND)
return (ms and 255).toShort()
}
8 -> {
val ms = calendar.get(Calendar.MILLISECOND)
return (ms ushr 8).toShort()
}
else -> return 0
}
}
override operator fun set(address: Address, data: UByte) {
/* real time clock can't be set */
}
}

View File

@ -1,28 +1,85 @@
package sim65.components
class Timer(startAddress: Address, endAddress: Address): MemMappedComponent(startAddress, endAddress) {
private var counter: Long = 0
/**
* A programmable timer. Causes an IRQ or NMI at specified 24-bits intervals.
* byte value
* 00 control register bit 0=enable bit 1=nmi (instead of irq)
* 01 24 bits interval value, bits 0-7 (lo)
* 02 24 bits interval value, bits 8-15 (mid)
* 03 24 bits interval value, bits 16-23 (hi)
*/
class Timer(startAddress: Address, endAddress: Address) : MemMappedComponent(startAddress, endAddress) {
private var counter: Int = 0
private var interval: Int = 0
private var enabled = false
private var nmi = false
init {
require(endAddress - startAddress + 1 == 4) { "timer needs exactly 4 memory bytes" }
}
override fun clock() {
counter++
if (counter > 0xffffffff)
counter = 0
println("TIMER CLOCK $counter")
if (enabled && interval > 0) {
counter++
if (counter == interval) {
if (nmi)
println("TODO: timer causes CPU nmi $counter") // TODO
else
println("TODO: timer causes CPU irq $counter") // TODO
counter = 0
}
}
}
override fun reset() {
counter = 0
interval = 0
enabled = false
nmi = false
}
override operator fun get(address: Address): UByte {
TODO("timer read $address")
when (address - startAddress) {
0 -> {
var data = 0
if (enabled) data = data or 0b00000001
if (nmi) data = data or 0b00000010
return data.toShort()
}
1 -> {
return (counter and 0xff).toShort()
}
2 -> {
return ((counter ushr 8) and 0xff).toShort()
}
3 -> {
return ((counter ushr 16) and 0xff).toShort()
}
else -> return 0
}
}
override operator fun set(address: Address, data: UByte) {
TODO("timer write $address = $data")
when (address - startAddress) {
0 -> {
val i = data.toInt()
val newEnabled = (i and 0b00000001) != 0
nmi = (i and 0b00000010) != 0
if(newEnabled && !enabled) {
// timer is set to enabled (was disabled) - reset the counter
counter = 0
}
enabled = newEnabled
}
1 -> {
interval = (interval and 0x7fffff00) or data.toInt()
}
2 -> {
interval = (interval and 0x7fff00ff) or (data.toInt() shl 8)
}
3 -> {
interval = (interval and 0x7f00ffff) or (data.toInt() shl 16)
}
}
}
}