1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-04 18:29:40 +00:00

Fixes the 6522 sufficiently to fix keyboard input.

This commit is contained in:
Thomas Harte 2019-07-08 15:29:34 -04:00
parent 210bcaa56d
commit 28de629c08
4 changed files with 29 additions and 35 deletions

View File

@ -91,13 +91,14 @@ template <typename T> void MOS6522<T>::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 <typename T> void MOS6522<T>::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 <typename T> void MOS6522<T>::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 <typename T> void MOS6522<T>::do_phase1() {
@ -303,11 +311,11 @@ template <typename T> void MOS6522<T>::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 <typename T> void MOS6522<T>::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 <typename T> void MOS6522<T>::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 <typename T> void MOS6522<T>::shift_in() {
template <typename T> void MOS6522<T>::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();

View File

@ -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);

View File

@ -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.

View File

@ -511,7 +511,6 @@ template <Analyser::Static::Macintosh::Target::Model model> 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));