1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-02 16:38:51 +00:00

Adds the CNT input.

This commit is contained in:
Thomas Harte 2021-08-03 22:19:41 -04:00
parent 738999a8b7
commit b4ec9d70da
4 changed files with 26 additions and 16 deletions

View File

@ -60,6 +60,9 @@ template <typename PortHandlerT, Personality personality> class MOS6526:
/// @returns @c true if the interrupt output is active, @c false otherwise.
bool get_interrupt_line();
/// Sets the current state of the CNT input.
void set_cnt_input(bool active);
private:
PortHandlerT &port_handler_;
TODStorage<personality == Personality::P8250> tod_;

View File

@ -48,6 +48,12 @@ bool MOS6526<BusHandlerT, personality>::get_interrupt_line() {
return interrupt_state_ & 0x80;
}
template <typename BusHandlerT, Personality personality>
void MOS6526<BusHandlerT, personality>::set_cnt_input(bool active) {
cnt_edge_ = active && !cnt_state_;
cnt_state_ = active;
}
template <typename BusHandlerT, Personality personality>
void MOS6526<BusHandlerT, personality>::write(int address, uint8_t value) {
address &= 0xf;
@ -166,11 +172,13 @@ void MOS6526<BusHandlerT, personality>::run_for(const HalfCycles half_cycles) {
pending_ &= PendingClearMask;
// TODO: use CNT potentially to clock timer A, elimiante conditional above.
const bool timer1_did_reload = counter_[0].template advance<false>(false);
const bool timer1_did_reload = counter_[0].template advance<false>(false, cnt_state_, cnt_edge_);
const bool timer1_carry = timer1_did_reload && (counter_[1].control & 0x60) == 0x40;
const bool timer2_did_reload = counter_[1].template advance<true>(timer1_carry);
const bool timer2_did_reload = counter_[1].template advance<true>(timer1_carry, cnt_state_, cnt_edge_);
posit_interrupt((timer1_did_reload ? 0x01 : 0x00) | (timer2_did_reload ? 0x02 : 0x00));
cnt_edge_ = false;
}
}

View File

@ -174,6 +174,8 @@ template <> class TODStorage<true>: public TODBase {
};
struct MOS6526Storage {
bool cnt_state_ = false; // Inactive by default.
bool cnt_edge_ = false;
HalfCycles half_divider_;
uint8_t output_[2] = {0, 0};
@ -206,7 +208,7 @@ struct MOS6526Storage {
control = v;
}
template <bool is_counter_2> bool advance(bool chained_input) {
template <bool is_counter_2> bool advance(bool chained_input, bool cnt_state, bool cnt_edge) {
// TODO: remove most of the conditionals here in favour of bit shuffling.
pending = (pending & PendingClearMask) << 1;
@ -222,27 +224,31 @@ struct MOS6526Storage {
control &= ~0x10;
}
// Keep a history of the one-shot bit.
if(control & 0x08) {
pending |= OneShotInOne;
}
// Determine whether an input clock is applicable.
if constexpr(is_counter_2) {
switch(control&0x60) {
case 0x00: // Count Phi2 pulses.
pending |= TestInputNow;
break;
case 0x20: // Count negative CNTs, with an extra cycle of delay.
pending |= cnt_edge ? TestInputInOne : 0;
break;
case 0x40: // Count timer A reloads.
pending |= chained_input ? TestInputNow : 0;
break;
case 0x20: // Count negative CNTs.
case 0x60: // Count timer A transitions when CNT is low.
default:
// TODO: all other forms of input.
assert(false);
pending |= chained_input && cnt_edge ? TestInputNow : 0;
break;
}
} else {
if(!(control&0x20)) {
pending |= TestInputNow;
} else if (chained_input) { // TODO: check CNT directly, probably?
} else if (cnt_edge) {
pending |= TestInputInOne;
}
}
@ -250,11 +256,6 @@ struct MOS6526Storage {
pending |= ApplyClockInTwo;
}
// Keep a history of the one-shot bit.
if(control & 0x08) {
pending |= OneShotInOne | OneShotNow;
}
//
// Perform a timer tick and decide whether a reload is prompted.

View File

@ -288,7 +288,6 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler {
}
func testCIALoadTH() {
// TODO: Uses one of the CNT input modes of timer B.
runTest("loadth", suffixes: [""], processor: .processor6502)
}
@ -313,7 +312,6 @@ class WolfgangLorenzTests: XCTestCase, CSTestMachineTrapHandler {
}
func testCIACNTDefault() {
// TODO: Uses one of the CNT input modes of timer B.
runTest("cntdef", suffixes: [""], processor: .processor6502)
}