From 28de629c08e9534569a7eca913421dd133ceb9d1 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 8 Jul 2019 15:29:34 -0400 Subject: [PATCH] Fixes the 6522 sufficiently to fix keyboard input. --- .../Implementation/6522Implementation.hpp | 41 ++++++++++--------- .../6522/Implementation/6522Storage.hpp | 14 +++---- Machines/Apple/Macintosh/Keyboard.hpp | 8 +--- Machines/Apple/Macintosh/Macintosh.cpp | 1 - 4 files changed, 29 insertions(+), 35 deletions(-) diff --git a/Components/6522/Implementation/6522Implementation.hpp b/Components/6522/Implementation/6522Implementation.hpp index 71df5fe59..b6de5fab4 100644 --- a/Components/6522/Implementation/6522Implementation.hpp +++ b/Components/6522/Implementation/6522Implementation.hpp @@ -91,13 +91,14 @@ template void MOS6522::set_register(int address, uint8_t value) case 0xa: registers_.shift = value; shift_bits_remaining_ = 8; + registers_.interrupt_flags &= ~InterruptFlag::ShiftRegister; break; // Control - case 0xb: { + case 0xb: registers_.auxiliary_control = value; evaluate_cb2_output(); - } break; + break; case 0xc: { // const auto old_peripheral_control = registers_.peripheral_control; registers_.peripheral_control = value; @@ -239,10 +240,10 @@ template void MOS6522::set_control_line_input(Port port, Line li // If this is a transition on CB1, consider updating the shift register. // TODO: and at least one full clock since the shift register was written? if(port == Port::B) { - switch((registers_.auxiliary_control >> 2)&7) { - default: break; - case 3: if(value) shift_in(); break; // Shifts in are captured on a low-to-high transition. - case 7: if(!value) shift_out(); break; // Shifts out are updated on a high-to-low transition. + switch(shift_mode()) { + default: break; + case ShiftMode::InUnderCB1: if(value) shift_in(); break; // Shifts in are captured on a low-to-high transition. + case ShiftMode::OutUnderCB1: if(!value) shift_out(); break; // Shifts out are updated on a high-to-low transition. } } } @@ -292,6 +293,13 @@ template void MOS6522::do_phase2() { if(handshake_modes_[0] == HandshakeMode::Pulse) { set_control_line_output(Port::A, Line::Two, LineState::On); } + + // If the shift register is shifting according to the input clock, do a shift. + switch(shift_mode()) { + default: break; + case ShiftMode::InUnderPhase2: shift_in(); break; + case ShiftMode::OutUnderPhase2: shift_out(); break; + } } template void MOS6522::do_phase1() { @@ -303,11 +311,11 @@ template void MOS6522::do_phase1() { // If the shift register is shifting according to this timer, do a shift. // TODO: "shift register is driven by only the low order 8 bits of timer 2"? - switch((registers_.auxiliary_control >> 2)&7) { - default: break; - case 1: shift_in(); break; - case 4: shift_out(); break; - case 5: shift_out(); break; // TODO: present a clock on CB1. + switch(shift_mode()) { + default: break; + case ShiftMode::InUnderT2: shift_in(); break; + case ShiftMode::OutUnderT2FreeRunning: shift_out(); break; + case ShiftMode::OutUnderT2: shift_out(); break; // TODO: present a clock on CB1. } registers_.interrupt_flags |= InterruptFlag::Timer2; @@ -331,13 +339,6 @@ template void MOS6522::do_phase1() { bus_handler_.set_port_output(Port::B, registers_.output[1], registers_.data_direction[1]); } } - - // If the shift register is shifting according to the input clock, do a shift. - switch((registers_.auxiliary_control >> 2)&7) { - default: break; - case 2: shift_in(); break; - case 6: shift_out(); break; - } } /*! Runs for a specified number of half cycles. */ @@ -389,7 +390,7 @@ template void MOS6522::evaluate_cb2_output() { // peripheral control register. // My guess: other CB2 functions work only if the shift register is disabled (?). - if((registers_.auxiliary_control >> 2)&7) { + if(shift_mode() != ShiftMode::Disabled) { // Shift register is enabled, one way or the other; but announce only output. if(is_shifting_out()) { // Output mode; set the level according to the current top of the shift register. @@ -435,7 +436,7 @@ template void MOS6522::shift_in() { template void MOS6522::shift_out() { // When shifting out, the shift register rotates rather than strictly shifts. // TODO: is that true for all modes? - if(shift_mode() == ShiftMode::ShiftOutUnderT2FreeRunning || shift_bits_remaining_) { + if(shift_mode() == ShiftMode::OutUnderT2FreeRunning || shift_bits_remaining_) { registers_.shift = uint8_t((registers_.shift << 1) | (registers_.shift >> 7)); evaluate_cb2_output(); diff --git a/Components/6522/Implementation/6522Storage.hpp b/Components/6522/Implementation/6522Storage.hpp index 818710e9f..da9e30981 100644 --- a/Components/6522/Implementation/6522Storage.hpp +++ b/Components/6522/Implementation/6522Storage.hpp @@ -71,13 +71,13 @@ class MOS6522Storage { enum class ShiftMode { Disabled = 0, - ShiftInUnderT2 = 1, - ShiftInUnderPhase2 = 2, - ShiftInUnderCB1 = 3, - ShiftOutUnderT2FreeRunning = 4, - ShiftOutUnderT2 = 5, - ShiftOutUnderPhase2 = 6, - ShiftOutUnderCB1 = 7 + InUnderT2 = 1, + InUnderPhase2 = 2, + InUnderCB1 = 3, + OutUnderT2FreeRunning = 4, + OutUnderT2 = 5, + OutUnderPhase2 = 6, + OutUnderCB1 = 7 }; ShiftMode shift_mode() const { return ShiftMode((registers_.auxiliary_control >> 2) & 7); diff --git a/Machines/Apple/Macintosh/Keyboard.hpp b/Machines/Apple/Macintosh/Keyboard.hpp index d74358e35..427697332 100644 --- a/Machines/Apple/Macintosh/Keyboard.hpp +++ b/Machines/Apple/Macintosh/Keyboard.hpp @@ -28,7 +28,6 @@ class Keyboard { computer signals that it is ready to begin communication by pulling the Keyboard Data line low." */ if(!data) { -// printf("Accepting new command\n"); mode_ = Mode::AcceptingCommand; phase_ = 0; command_ = 0; @@ -85,7 +84,6 @@ class Keyboard { clock_output_ = offset >= 18; if(offset == 26) { -// printf("Latched %d\n", (data_input_ ? 1 : 0)); command_ = (command_ << 1) | (data_input_ ? 1 : 0); } @@ -99,12 +97,12 @@ class Keyboard { case Mode::AwaitingEndOfCommand: // Time out if the end-of-command seems not to be forthcoming. + // This is an elaboration on my part; a guess. ++phase_; if(phase_ == 1000) { clock_output_ = false; mode_ = Mode::Waiting; phase_ = 0; -// printf("Timed out\n"); } return; @@ -116,7 +114,6 @@ class Keyboard { if(phase_ == 25000 || command_ != 0x10 || response_ != 0x7b) { mode_ = Mode::SendingResponse; phase_ = 0; -// printf("Starting response\n"); } } break; @@ -139,7 +136,6 @@ class Keyboard { clock_output_ = false; mode_ = Mode::Waiting; phase_ = 0; -// printf("Waiting\n"); } } break; } @@ -154,8 +150,6 @@ class Keyboard { private: int perform_command(int command) { -// printf("Keyboard: %02x\n", command); - switch(command) { case 0x10: // Inquiry. case 0x14: { // Instant. diff --git a/Machines/Apple/Macintosh/Macintosh.cpp b/Machines/Apple/Macintosh/Macintosh.cpp index 199403411..2b4ccc5e3 100644 --- a/Machines/Apple/Macintosh/Macintosh.cpp +++ b/Machines/Apple/Macintosh/Macintosh.cpp @@ -511,7 +511,6 @@ template class ConcreteMachin CA1 is used for receiving vsync. */ if(port == Port::B && line == Line::Two) { - printf("Keyboard input: %c\n", value ? 't' : 'f'); keyboard_.set_input(value); } else printf("Unhandled control line output: %c %d\n", port ? 'B' : 'A', int(line));