diff --git a/Components/6522/6522.hpp b/Components/6522/6522.hpp index ecb118d91..4ec1fde0a 100644 --- a/Components/6522/6522.hpp +++ b/Components/6522/6522.hpp @@ -364,7 +364,7 @@ class MOS6522IRQDelegate { virtual void mos6522_did_change_interrupt_status(void *mos6522) = 0; }; - void set_delegate(Delegate *delegate) + void set_interrupt_delegate(Delegate *delegate) { _delegate = delegate; } diff --git a/Machines/Commodore/1540/C1540.cpp b/Machines/Commodore/1540/C1540.cpp index 79adb774e..0e0e3455b 100644 --- a/Machines/Commodore/1540/C1540.cpp +++ b/Machines/Commodore/1540/C1540.cpp @@ -25,7 +25,8 @@ Machine::Machine() : _serialPortVIA->set_serial_port(_serialPort); // set this instance as the delegate to receive interrupt requests from both VIAs - _serialPortVIA->set_delegate(this); + _serialPortVIA->set_interrupt_delegate(this); + _driveVIA.set_interrupt_delegate(this); _driveVIA.set_delegate(this); // set a bit rate @@ -40,10 +41,10 @@ void Machine::set_serial_bus(std::shared_ptr<::Commodore::Serial::Bus> serial_bu unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value) { // static bool log = false; -// if(operation == CPU6502::BusOperation::ReadOpcode) printf("%04x\n", address); -// if(operation == CPU6502::BusOperation::ReadOpcode && (address == 0xf3be)) log = true; +// if(operation == CPU6502::BusOperation::ReadOpcode && (address == 0xF3C0)) log = true; // if(operation == CPU6502::BusOperation::ReadOpcode && log) printf("%04x\n", address); -// if(operation == CPU6502::BusOperation::ReadOpcode && (address >= 0xF556 && address <= 0xF56D)) printf("%04x\n", address); +// if(operation == CPU6502::BusOperation::ReadOpcode) printf("%04x\n", address); +// if(operation == CPU6502::BusOperation::ReadOpcode && (address >= 0xF510 && address <= 0xF553)) printf("%04x\n", address); // if(operation == CPU6502::BusOperation::ReadOpcode && (address == 0xE887)) printf("A: %02x\n", get_value_of_register(CPU6502::Register::A)); /* static bool log = false; @@ -121,8 +122,15 @@ void Machine::mos6522_did_change_interrupt_status(void *mos6522) void Machine::process_input_bit(int value, unsigned int cycles_since_index_hole) { _shift_register = (_shift_register << 1) | value; - _driveVIA.set_sync_detected((_shift_register & 0x3ff) == 0x3ff); - if((_shift_register & 0x7ff) == 0x7fe) _bit_window_offset = 0; + if((_shift_register & 0x3ff) == 0x3ff) + { + _driveVIA.set_sync_detected(true); + _bit_window_offset = -1; + } + else + { + _driveVIA.set_sync_detected(false); + } _bit_window_offset++; if(_bit_window_offset == 8) { @@ -139,3 +147,15 @@ void Machine::process_input_bit(int value, unsigned int cycles_since_index_hole) // the 1540 does not recognise index holes void Machine::process_index_hole() {} + +#pragma mak - Drive VIA delegate + +void Machine::drive_via_did_step_head(void *driveVIA, int direction) +{ + step(direction); +} + +void Machine::drive_via_did_set_data_density(void *driveVIA, int density) +{ + set_expected_bit_length(Storage::Encodings::CommodoreGCR::length_of_a_bit_in_time_zone((unsigned int)density)); +} diff --git a/Machines/Commodore/1540/C1540.hpp b/Machines/Commodore/1540/C1540.hpp index e377fd8ad..7082e7a3f 100644 --- a/Machines/Commodore/1540/C1540.hpp +++ b/Machines/Commodore/1540/C1540.hpp @@ -115,10 +115,20 @@ class SerialPortVIA: public MOS::MOS6522, public MOS::MOS6522IRQD */ class DriveVIA: public MOS::MOS6522, public MOS::MOS6522IRQDelegate { public: + class Delegate { + public: + virtual void drive_via_did_step_head(void *driveVIA, int direction) = 0; + virtual void drive_via_did_set_data_density(void *driveVIA, int density) = 0; + }; + void set_delegate(Delegate *delegate) + { + _delegate = delegate; + } + using MOS6522IRQDelegate::set_interrupt_status; // write protect tab uncovered - DriveVIA() : _port_b(0xff), _port_a(0xff) {} + DriveVIA() : _port_b(0xff), _port_a(0xff), _delegate(nullptr) {} uint8_t get_port_input(Port port) { return port ? _port_b : _port_a; @@ -152,10 +162,23 @@ class DriveVIA: public MOS::MOS6522, public MOS::MOS6522IRQDelegate { _drive_motor = !!(value&4); // if(value&4) // { - printf("Head step: %d\n", value&3); + + int step_difference = ((value&3) - (_previous_port_b_output&3))&3; + if(step_difference) + { + if(_delegate) _delegate->drive_via_did_step_head(this, (step_difference == 1) ? 1 : -1); + } + + int density_difference = (_previous_port_b_output^value) & (3 << 5); + if(density_difference && _delegate) + { + _delegate->drive_via_did_set_data_density(this, (value >> 5)&3); + } // printf("LED: %s\n", value&8 ? "On" : "Off"); // printf("Density: %d\n", (value >> 5)&3); // } + + _previous_port_b_output = value; } } @@ -163,6 +186,8 @@ class DriveVIA: public MOS::MOS6522, public MOS::MOS6522IRQDelegate { uint8_t _port_b, _port_a; bool _should_set_overflow; bool _drive_motor; + uint8_t _previous_port_b_output; + Delegate *_delegate; }; /*! @@ -189,6 +214,7 @@ class SerialPort : public ::Commodore::Serial::Port { class Machine: public CPU6502::Processor, public MOS::MOS6522IRQDelegate::Delegate, + public DriveVIA::Delegate, public Storage::DiskDrive { public: @@ -217,6 +243,10 @@ class Machine: // to satisfy MOS::MOS6522::Delegate virtual void mos6522_did_change_interrupt_status(void *mos6522); + // to satisfy DriveVIA::Delegate + void drive_via_did_step_head(void *driveVIA, int direction); + void drive_via_did_set_data_density(void *driveVIA, int density); + private: uint8_t _ram[0x800]; uint8_t _rom[0x4000]; diff --git a/Machines/Commodore/Vic-20/Vic20.cpp b/Machines/Commodore/Vic-20/Vic20.cpp index fd1b80b9f..03b24f7ff 100644 --- a/Machines/Commodore/Vic-20/Vic20.cpp +++ b/Machines/Commodore/Vic-20/Vic20.cpp @@ -30,8 +30,8 @@ Machine::Machine() : _serialPort->set_user_port_via(_userPortVIA); // wire up the 6522s, tape and machine - _userPortVIA->set_delegate(this); - _keyboardVIA->set_delegate(this); + _userPortVIA->set_interrupt_delegate(this); + _keyboardVIA->set_interrupt_delegate(this); _tape.set_delegate(this); // establish the memory maps