1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Improves shift register connection, towards having the keyboard function properly.

It now seems not to receive a command terminator, but is at least getting a command.
This commit is contained in:
Thomas Harte 2019-06-08 23:04:55 -04:00
parent 697e094a4e
commit 0e16c67805

View File

@ -94,9 +94,15 @@ template <typename T> void MOS6522<T>::set_register(int address, uint8_t value)
break; break;
// Control // Control
case 0xb: case 0xb: {
registers_.auxiliary_control = value; registers_.auxiliary_control = value;
break;
// TODO: what happens if the peripheral control register is doing something with CB2 also?
if(value & 0x10) {
// One of the shift out modes is activated, so set CB2 output appropriately.
set_control_line_output(Port::B, Line::Two, !!(registers_.shift & 0x80), false);
}
} break;
case 0xc: { case 0xc: {
// const auto old_peripheral_control = registers_.peripheral_control; // const auto old_peripheral_control = registers_.peripheral_control;
registers_.peripheral_control = value; registers_.peripheral_control = value;
@ -107,25 +113,25 @@ template <typename T> void MOS6522<T>::set_register(int address, uint8_t value)
switch((value >> shift) & 0x0e) { switch((value >> shift) & 0x0e) {
default: break; default: break;
case 0x00: // Negative interrupt input; set CA2 interrupt on negative CA2 transition, clear on access to Port A register. case 0x00: // Negative interrupt input; set Cx2 interrupt on negative Cx2 transition, clear on access to Port x register.
case 0x02: // Independent negative interrupt input; set CA2 interrupt on negative transition, don't clear automatically. case 0x02: // Independent negative interrupt input; set Cx2 interrupt on negative transition, don't clear automatically.
case 0x04: // Positive interrupt input; set CA2 interrupt on positive CA2 transition, clear on access to Port A register. case 0x04: // Positive interrupt input; set Cx2 interrupt on positive Cx2 transition, clear on access to Port x register.
case 0x06: // Independent positive interrupt input; set CA2 interrupt on positive transition, don't clear automatically. case 0x06: // Independent positive interrupt input; set Cx2 interrupt on positive transition, don't clear automatically.
break; break;
case 0x08: // Handshake: set CA2 to low on any read or write of Port A; set to high on an active transition of CA1. case 0x08: // Handshake: set Cx2 to low on any read or write of Port x; set to high on an active transition of Cx1.
handshake_modes_[port] = HandshakeMode::Handshake; handshake_modes_[port] = HandshakeMode::Handshake;
break; break;
case 0x0a: // Pulse output: CA2 is low for one cycle following a read or write of Port A. case 0x0a: // Pulse output: Cx2 is low for one cycle following a read or write of Port x.
handshake_modes_[port] = HandshakeMode::Pulse; handshake_modes_[port] = HandshakeMode::Pulse;
break; break;
case 0x0c: // Manual output: CA2 low. case 0x0c: // Manual output: Cx2 low.
set_control_line_output(Port(port), Line::Two, false); set_control_line_output(Port(port), Line::Two, false);
break; break;
case 0x0e: // Manual output: CA2 high. case 0x0e: // Manual output: Cx2 high.
set_control_line_output(Port(port), Line::Two, true); set_control_line_output(Port(port), Line::Two, true);
break; break;
} }
@ -233,11 +239,13 @@ template <typename T> void MOS6522<T>::set_control_line_input(Port port, Line li
} }
// If this is a low-to-high transition, consider updating the shift register. // If this is a low-to-high transition, consider updating the shift register.
if(value) { if(port == Port::B) {
switch((registers_.auxiliary_control >> 2)&7) { if(value) {
default: break; switch((registers_.auxiliary_control >> 2)&7) {
case 3: shift_in(); break; default: break;
case 7: shift_out(); break; case 3: shift_in(); break;
case 7: shift_out(); break;
}
} }
} }
} }
@ -384,9 +392,10 @@ template <typename T> void MOS6522<T>::set_control_line_output(Port port, Line l
return; return;
// Store the value as the intended output, announce it only if this // Store the value as the intended output, announce it only if this
// control line is actually in output mode. // control line is actually in output mode, or if this is CB2 and
// the shift register is in output mode.
control_outputs_[port].lines[line] = value; control_outputs_[port].lines[line] = value;
if(registers_.peripheral_control & (0x08 << (port * 4))) { if(registers_.peripheral_control & (0x08 << (port * 4)) || (port == Port::B && line == Line::Two && registers_.auxiliary_control&0x10)) {
bus_handler_.run_for(time_since_bus_handler_call_.flush()); bus_handler_.run_for(time_since_bus_handler_call_.flush());
bus_handler_.set_control_line_output(port, line, value); bus_handler_.set_control_line_output(port, line, value);
} }
@ -403,7 +412,10 @@ template <typename T> void MOS6522<T>::shift_in() {
template <typename T> void MOS6522<T>::shift_out() { template <typename T> void MOS6522<T>::shift_out() {
set_control_line_output(Port::B, Line::Two, registers_.shift & 0x80); set_control_line_output(Port::B, Line::Two, registers_.shift & 0x80);
registers_.shift <<= 1;
// When shifting out, the shift register rotates rather than strictly shifts.
registers_.shift = uint8_t((registers_.shift << 1) | (registers_.shift >> 7));
--shift_bits_remaining_; --shift_bits_remaining_;
if(!shift_bits_remaining_) { if(!shift_bits_remaining_) {
registers_.interrupt_flags |= InterruptFlag::ShiftRegister; registers_.interrupt_flags |= InterruptFlag::ShiftRegister;