1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-01 10:05:55 +00:00
CLK/OSBindings/Mac/Clock SignalTests/6532Tests.swift
2018-05-13 15:19:52 -04:00

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")
}
}
}