mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-28 22:30:30 +00:00
178 lines
5.3 KiB
Swift
178 lines
5.3 KiB
Swift
//
|
|
// 6532Tests.swift
|
|
// Clock Signal
|
|
//
|
|
// Created by Thomas Harte on 19/06/2016.
|
|
// Copyright 2016 Thomas Harte. All rights reserved.
|
|
//
|
|
|
|
import XCTest
|
|
import Foundation
|
|
|
|
class MOS6532Tests: XCTestCase {
|
|
|
|
fileprivate func with6532(_ action: (MOS6532Bridge) -> ()) {
|
|
let bridge = MOS6532Bridge()
|
|
action(bridge)
|
|
}
|
|
|
|
// MARK: Timer tests
|
|
func testOneTickTimer() {
|
|
with6532 {
|
|
// set a count of 128 at single-clock intervals
|
|
$0.setValue(128, forRegister:0x14)
|
|
XCTAssertEqual($0.value(forRegister: 4), 128)
|
|
|
|
// run for one more clock and the count should now be 127
|
|
$0.run(forCycles: 1)
|
|
XCTAssertEqual($0.value(forRegister: 4), 127)
|
|
|
|
// run for 127 clocks and the timer should be zero, but the timer flag will not yet be set
|
|
$0.run(forCycles: 127)
|
|
XCTAssertEqual($0.value(forRegister: 5) & 0x80, 0)
|
|
XCTAssertEqual($0.value(forRegister: 4), 0)
|
|
|
|
// after one more cycle the counter should be 255 and the timer flag will now be set
|
|
$0.run(forCycles: 1)
|
|
XCTAssertEqual($0.value(forRegister: 5) & 0x80, 0x80)
|
|
XCTAssertEqual($0.value(forRegister: 4), 255)
|
|
|
|
// run for a further 55 clock counts; timer should reach -200
|
|
$0.run(forCycles: 55)
|
|
XCTAssertEqual($0.value(forRegister: 4), 200)
|
|
}
|
|
}
|
|
|
|
// TODO: the tests below makes the assumption that divider phase is flexible; verify
|
|
func testEightTickTimer() {
|
|
with6532 {
|
|
// set a count of 28 at eight-clock intervals
|
|
$0.setValue(28, forRegister:0x15)
|
|
XCTAssertEqual($0.value(forRegister: 4), 28)
|
|
|
|
// one further cycle and the timer should hit 27
|
|
$0.run(forCycles: 1)
|
|
XCTAssertEqual($0.value(forRegister: 4), 27)
|
|
|
|
// run for seven clock and the count should still be 27
|
|
$0.run(forCycles: 7)
|
|
XCTAssertEqual($0.value(forRegister: 4), 27)
|
|
|
|
// run for a further clock and the count should now be 26
|
|
$0.run(forCycles: 1)
|
|
XCTAssertEqual($0.value(forRegister: 4), 26)
|
|
|
|
// run for another 26 * 8 = 208 cycles and the count should hit zero without setting the timer flag, and
|
|
// stay there for seven more cycles
|
|
$0.run(forCycles: 208)
|
|
for _ in 0 ..< 8 {
|
|
XCTAssertEqual($0.value(forRegister: 5) & 0x80, 0)
|
|
XCTAssertEqual($0.value(forRegister: 4), 0)
|
|
$0.run(forCycles: 1)
|
|
}
|
|
|
|
// run six more, and the timer should reach 249, with the interrupt flag set
|
|
$0.run(forCycles: 6)
|
|
XCTAssertEqual($0.value(forRegister: 5) & 0x80, 0x80)
|
|
XCTAssertEqual($0.value(forRegister: 4), 249)
|
|
|
|
// timer should now resume dividing by eight
|
|
$0.run(forCycles: 7)
|
|
XCTAssertEqual($0.value(forRegister: 4), 249)
|
|
|
|
$0.run(forCycles: 1)
|
|
XCTAssertEqual($0.value(forRegister: 4), 248)
|
|
}
|
|
}
|
|
|
|
func testTimerInterrupt() {
|
|
with6532 {
|
|
// set a count of 1 at single-clock intervals
|
|
$0.setValue(1, forRegister:0x1c)
|
|
$0.run(forCycles: 1)
|
|
|
|
// interrupt shouldn't be signalled yet, bit should not be set
|
|
XCTAssert(!$0.irqLine, "IRQ line should not be set")
|
|
XCTAssert($0.value(forRegister: 5) == 0x00, "Counter interrupt should not be set")
|
|
|
|
// run for one more clock
|
|
$0.run(forCycles: 1)
|
|
|
|
// the interrupt line and bit should now be set
|
|
XCTAssert($0.irqLine, "IRQ line should be set")
|
|
XCTAssert($0.value(forRegister: 5) == 0x80, "Counter interrupt should be set")
|
|
|
|
// writing again to the timer should clear both
|
|
$0.setValue(1, forRegister:0x1c)
|
|
XCTAssert(!$0.irqLine, "IRQ line should be clear")
|
|
XCTAssert($0.value(forRegister: 5) == 0x00, "Counter interrupt should not be set")
|
|
}
|
|
}
|
|
|
|
|
|
// MARK: PA7 interrupt tests
|
|
func testPA7InterruptDisabled() {
|
|
with6532 {
|
|
// disable edge detection
|
|
$0.setValue(0, forRegister:4)
|
|
|
|
// set output mode for port a
|
|
$0.setValue(0xff, forRegister:1)
|
|
|
|
// toggle bit 7 of port a in both directions
|
|
$0.setValue(0x80, forRegister:0)
|
|
$0.setValue(0x00, forRegister:0)
|
|
$0.setValue(0x80, forRegister:0)
|
|
|
|
// confirm that the interrupt flag is set but the line is not
|
|
XCTAssert(!$0.irqLine, "IRQ line should not be set")
|
|
XCTAssert($0.value(forRegister: 5) == 0x40, "Timer interrupt bit should be set")
|
|
|
|
// reading the status register should have reset the interrupt flag
|
|
XCTAssert($0.value(forRegister: 5) == 0x00, "Timer interrupt bit should be reset")
|
|
}
|
|
}
|
|
|
|
func testPA7LeadingEdge() {
|
|
with6532 {
|
|
// seed port a is high; ensure interrupt bit is clear
|
|
$0.setValue(0x00, forRegister:0)
|
|
$0.value(forRegister: 5)
|
|
|
|
// enable leading edge detection
|
|
$0.setValue(0, forRegister:7)
|
|
|
|
// set output mode for port a
|
|
$0.setValue(0xff, forRegister:1)
|
|
|
|
// toggle bit 7 of port a in a leading direction
|
|
$0.setValue(0x80, forRegister:0)
|
|
|
|
// confirm that both the interrupt flag are the line are set
|
|
XCTAssert($0.irqLine, "IRQ line should be set")
|
|
XCTAssert($0.value(forRegister: 5) == 0x40, "Timer interrupt bit should be set")
|
|
}
|
|
}
|
|
|
|
func testPA7TrailingEdge() {
|
|
with6532 {
|
|
// seed port a is high; ensure interrupt bit is clear
|
|
$0.setValue(0x80, forRegister:0)
|
|
$0.value(forRegister: 5)
|
|
|
|
// enable trailing edge detection
|
|
$0.setValue(0, forRegister:6)
|
|
|
|
// set output mode for port a
|
|
$0.setValue(0xff, forRegister:1)
|
|
|
|
// toggle bit 7 of port a in a rising direction
|
|
$0.setValue(0x00, forRegister:0)
|
|
|
|
// confirm that both the interrupt flag are the line are set
|
|
XCTAssert($0.irqLine, "IRQ line should be set")
|
|
XCTAssert($0.value(forRegister: 5) == 0x40, "Timer interrupt bit should be set")
|
|
}
|
|
}
|
|
}
|