2021-07-03 03:41:19 +00:00
|
|
|
//
|
|
|
|
// EnterpriseDaveTests.m
|
|
|
|
// Clock SignalTests
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 02/07/2021.
|
|
|
|
// Copyright © 2021 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#import <XCTest/XCTest.h>
|
|
|
|
|
|
|
|
#include "../../../Machines/Enterprise/Dave.hpp"
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
@interface EnterpriseDaveTests : XCTestCase
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation EnterpriseDaveTests {
|
|
|
|
std::unique_ptr<Enterprise::Dave::TimedInterruptSource> _interruptSource;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setUp {
|
|
|
|
[super setUp];
|
|
|
|
_interruptSource = std::make_unique<Enterprise::Dave::TimedInterruptSource>();
|
|
|
|
}
|
|
|
|
|
2021-07-07 00:25:32 +00:00
|
|
|
- (void)performTestExpectedInterrupts:(int)expectedInterrupts {
|
2021-07-03 03:41:19 +00:00
|
|
|
// Check that the programmable timer flag toggles at a rate
|
|
|
|
// of 2kHz, causing 1000 interrupts, and that sequence points
|
|
|
|
// are properly predicted.
|
|
|
|
int toggles = 0;
|
|
|
|
int interrupts = 0;
|
2021-07-07 00:12:44 +00:00
|
|
|
uint8_t dividerState = _interruptSource->get_divider_state() & 1;
|
2021-07-03 03:41:19 +00:00
|
|
|
int nextSequencePoint = _interruptSource->get_next_sequence_point().as<int>();
|
2021-07-07 00:12:44 +00:00
|
|
|
|
2021-07-03 03:41:19 +00:00
|
|
|
for(int c = 0; c < 250000; c++) {
|
2021-07-07 00:12:44 +00:00
|
|
|
// Advance one cycle. Clock is 500,000 Hz.
|
|
|
|
_interruptSource->run_for(Cycles(2));
|
2021-07-07 00:28:32 +00:00
|
|
|
--nextSequencePoint;
|
2021-07-03 03:41:19 +00:00
|
|
|
|
2021-07-07 00:28:32 +00:00
|
|
|
// Check for a status bit change.
|
2021-07-03 03:41:19 +00:00
|
|
|
const uint8_t newDividerState = _interruptSource->get_divider_state();
|
2021-07-07 00:25:32 +00:00
|
|
|
const bool didToggle = (dividerState^newDividerState)&0x1;
|
2021-07-03 03:41:19 +00:00
|
|
|
dividerState = newDividerState;
|
2021-07-07 00:28:32 +00:00
|
|
|
toggles += didToggle;
|
2021-07-03 03:41:19 +00:00
|
|
|
|
|
|
|
// Check for the relevant interrupt.
|
|
|
|
const uint8_t newInterrupts = _interruptSource->get_new_interrupts();
|
2021-07-07 00:28:32 +00:00
|
|
|
if(newInterrupts) {
|
2021-07-03 03:41:19 +00:00
|
|
|
XCTAssertEqual(nextSequencePoint, 0);
|
|
|
|
nextSequencePoint = _interruptSource->get_next_sequence_point().as<int>();
|
|
|
|
|
2021-07-07 00:28:32 +00:00
|
|
|
if(newInterrupts & 0x02) {
|
|
|
|
++interrupts;
|
|
|
|
XCTAssertTrue(didToggle);
|
|
|
|
} else {
|
|
|
|
// Failing that, confirm that the other interrupt happend.
|
|
|
|
XCTAssertTrue(newInterrupts & 0x08);
|
|
|
|
}
|
2021-07-03 03:41:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
XCTAssertEqual(nextSequencePoint, _interruptSource->get_next_sequence_point().as<int>(), @"At cycle %d", c);
|
|
|
|
}
|
|
|
|
|
2021-07-07 00:25:32 +00:00
|
|
|
XCTAssertEqual(toggles, expectedInterrupts);
|
|
|
|
XCTAssertEqual(interrupts, expectedInterrupts);
|
2021-07-03 03:41:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)test1kHzTimer {
|
|
|
|
// Set 1kHz timer.
|
|
|
|
_interruptSource->write(7, 0 << 5);
|
2021-07-07 00:25:32 +00:00
|
|
|
[self performTestExpectedInterrupts:1000];
|
2021-07-03 03:41:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)test50HzTimer {
|
|
|
|
// Set 50Hz timer.
|
|
|
|
_interruptSource->write(7, 1 << 5);
|
2021-07-07 00:25:32 +00:00
|
|
|
[self performTestExpectedInterrupts:50];
|
2021-07-03 03:41:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)testTone0Timer {
|
|
|
|
// Set tone generator 0 as the interrupt source, with a divider of 137;
|
|
|
|
// apply sync momentarily.
|
|
|
|
_interruptSource->write(7, 2 << 5);
|
|
|
|
_interruptSource->write(0, 137);
|
2021-07-03 03:57:11 +00:00
|
|
|
_interruptSource->write(1, 0);
|
2021-07-03 03:41:19 +00:00
|
|
|
|
2021-07-07 00:25:32 +00:00
|
|
|
[self performTestExpectedInterrupts:250000/(138 * 2)];
|
2021-07-03 03:41:19 +00:00
|
|
|
}
|
|
|
|
|
2021-07-03 03:57:11 +00:00
|
|
|
- (void)testTone1Timer {
|
|
|
|
// Set tone generator 1 as the interrupt source, with a divider of 961;
|
|
|
|
// apply sync momentarily.
|
|
|
|
_interruptSource->write(7, 3 << 5);
|
|
|
|
_interruptSource->write(2, 961 & 0xff);
|
|
|
|
_interruptSource->write(3, (961 >> 8) & 0xff);
|
|
|
|
|
2021-07-07 00:25:32 +00:00
|
|
|
[self performTestExpectedInterrupts:250000/(961 * 2)];
|
2021-07-03 03:57:11 +00:00
|
|
|
}
|
|
|
|
|
2021-07-03 03:41:19 +00:00
|
|
|
@end
|