mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
implemented sim timer and clock
This commit is contained in:
parent
bdcd10512f
commit
2cf9af4a6e
@ -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)
|
||||
}
|
||||
|
79
sim65/src/components/RealTimeClock.kt
Normal file
79
sim65/src/components/RealTimeClock.kt
Normal 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 */
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user