From 29288b690e8f63aa3bbc09dc4fba1b86fc8721bf Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 6 Aug 2017 09:45:16 -0400 Subject: [PATCH] Switched disk controllers to be instantiated explicitly in terms of cycles, created an Amstrad-specific subclass of the 8272 to record the direct programmatic availability of all disk motors bundled together, and otherwise adjusted to ensure the thing is clocked and that the motor is enabled and disabled appropriately. The 8272 is also now formally a subclass of the incoming MDM controller. --- Components/8272/i8272.cpp | 11 +++++++++++ Components/8272/i8272.hpp | 9 ++++++++- Machines/AmstradCPC/AmstradCPC.cpp | 27 ++++++++++++++++++++++++--- Storage/Disk/DiskController.cpp | 6 +++--- Storage/Disk/DiskController.hpp | 3 ++- Storage/Disk/MFMDiskController.cpp | 2 +- Storage/Disk/MFMDiskController.hpp | 3 ++- 7 files changed, 51 insertions(+), 10 deletions(-) diff --git a/Components/8272/i8272.cpp b/Components/8272/i8272.cpp index f970e94f9..f127e37cf 100644 --- a/Components/8272/i8272.cpp +++ b/Components/8272/i8272.cpp @@ -12,6 +12,14 @@ using namespace Intel; +i8272::i8272(Cycles clock_rate, int clock_rate_multiplier, int revolutions_per_minute) : + Storage::Disk::MFMController(clock_rate, clock_rate_multiplier, revolutions_per_minute) { +} + +void i8272::run_for(Cycles cycles) { + Storage::Disk::MFMController::run_for(cycles); +} + void i8272::set_register(int address, uint8_t value) { if(!address) return; @@ -87,3 +95,6 @@ uint8_t i8272::get_register(int address) { return 0x80; } } + +void i8272::posit_event(Event type) { +} diff --git a/Components/8272/i8272.hpp b/Components/8272/i8272.hpp index aa3033ecb..ca7275691 100644 --- a/Components/8272/i8272.hpp +++ b/Components/8272/i8272.hpp @@ -9,17 +9,24 @@ #ifndef i8272_hpp #define i8272_hpp +#include "../../Storage/Disk/MFMDiskController.hpp" + #include #include namespace Intel { -class i8272 { +class i8272: public Storage::Disk::MFMController { public: + i8272(Cycles clock_rate, int clock_rate_multiplier, int revolutions_per_minute); + + void run_for(Cycles); + void set_register(int address, uint8_t value); uint8_t get_register(int address); private: + void posit_event(Event type); uint8_t status_; std::vector command_; }; diff --git a/Machines/AmstradCPC/AmstradCPC.cpp b/Machines/AmstradCPC/AmstradCPC.cpp index 92b6d5887..024017916 100644 --- a/Machines/AmstradCPC/AmstradCPC.cpp +++ b/Machines/AmstradCPC/AmstradCPC.cpp @@ -428,6 +428,19 @@ struct KeyboardState { uint8_t rows[10]; }; +/*! + Wraps the 8272 so as to provide proper clocking and RPM counts, and just directly + exposes motor control, applying the same value to all drives. +*/ +class FDC: public Intel::i8272 { + public: + FDC() : i8272(Cycles(8000000), 16, 300) {} + + void set_motor_on(bool on) { + Intel::i8272::set_motor_on(on); + } +}; + /*! Provides the mechanism of receipt for input and output of the 8255's various ports. */ @@ -546,6 +559,9 @@ class ConcreteMachine: // Pump the AY. ay_.run_for(cycle.length); + // Clock the FDC, if connected, using a lazy scale by two + if(has_fdc_) fdc_.run_for(Cycles(cycle.length.as_int())); + // Stop now if no action is strictly required. if(!cycle.is_terminal()) return HalfCycles(0); @@ -605,7 +621,12 @@ class ConcreteMachine: // Check for an FDC access if(has_fdc_ && (address & 0x580) == 0x100) { - i8272_.set_register(address & 1, *cycle.value); + fdc_.set_register(address & 1, *cycle.value); + } + + // Check for a disk motor access + if(has_fdc_ && !(address & 0x580)) { + fdc_.set_motor_on(!!(*cycle.value)); } break; case CPU::Z80::PartialMachineCycle::Input: @@ -628,7 +649,7 @@ class ConcreteMachine: // Check for an FDC access if(has_fdc_ && (address & 0x580) == 0x100) { - *cycle.value = i8272_.get_register(address & 1); + *cycle.value = fdc_.get_register(address & 1); } break; @@ -748,7 +769,7 @@ class ConcreteMachine: i8255PortHandler i8255_port_handler_; Intel::i8255::i8255 i8255_; - Intel::i8272 i8272_; + FDC fdc_; InterruptTimer interrupt_timer_; Storage::Tape::BinaryTapePlayer tape_player_; diff --git a/Storage/Disk/DiskController.cpp b/Storage/Disk/DiskController.cpp index 46098ea74..5429da94f 100644 --- a/Storage/Disk/DiskController.cpp +++ b/Storage/Disk/DiskController.cpp @@ -11,8 +11,8 @@ using namespace Storage::Disk; -Controller::Controller(int clock_rate, int clock_rate_multiplier, int revolutions_per_minute) : - clock_rate_(clock_rate * clock_rate_multiplier), +Controller::Controller(Cycles clock_rate, int clock_rate_multiplier, int revolutions_per_minute) : + clock_rate_(clock_rate.as_int() * clock_rate_multiplier), clock_rate_multiplier_(clock_rate_multiplier), rotational_multiplier_(60, revolutions_per_minute), @@ -21,7 +21,7 @@ Controller::Controller(int clock_rate, int clock_rate_multiplier, int revolution is_reading_(true), - TimedEventLoop((unsigned int)(clock_rate * clock_rate_multiplier)) { + TimedEventLoop((unsigned int)(clock_rate.as_int() * clock_rate_multiplier)) { // seed this class with a PLL, any PLL, so that it's safe to assume non-nullptr later Time one(1); set_expected_bit_length(one); diff --git a/Storage/Disk/DiskController.hpp b/Storage/Disk/DiskController.hpp index 311e9b3d5..59c111f59 100644 --- a/Storage/Disk/DiskController.hpp +++ b/Storage/Disk/DiskController.hpp @@ -14,6 +14,7 @@ #include "PCMSegment.hpp" #include "PCMPatchedTrack.hpp" #include "../TimedEventLoop.hpp" +#include "../../ClockReceiver/ClockReceiver.hpp" namespace Storage { namespace Disk { @@ -33,7 +34,7 @@ class Controller: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop Constructs a @c DiskDrive that will be run at @c clock_rate and runs its PLL at @c clock_rate*clock_rate_multiplier, spinning inserted disks at @c revolutions_per_minute. */ - Controller(int clock_rate, int clock_rate_multiplier, int revolutions_per_minute); + Controller(Cycles clock_rate, int clock_rate_multiplier, int revolutions_per_minute); /*! Communicates to the PLL the expected length of a bit as a fraction of a second. diff --git a/Storage/Disk/MFMDiskController.cpp b/Storage/Disk/MFMDiskController.cpp index 299556937..91909d24d 100644 --- a/Storage/Disk/MFMDiskController.cpp +++ b/Storage/Disk/MFMDiskController.cpp @@ -12,7 +12,7 @@ using namespace Storage::Disk; -MFMController::MFMController(int clock_rate, int clock_rate_multiplier, int revolutions_per_minute) : +MFMController::MFMController(Cycles clock_rate, int clock_rate_multiplier, int revolutions_per_minute) : Storage::Disk::Controller(clock_rate, clock_rate_multiplier, revolutions_per_minute), crc_generator_(0x1021, 0xffff), data_mode_(DataMode::Scanning), diff --git a/Storage/Disk/MFMDiskController.hpp b/Storage/Disk/MFMDiskController.hpp index 27e0b86c1..acdb9afbe 100644 --- a/Storage/Disk/MFMDiskController.hpp +++ b/Storage/Disk/MFMDiskController.hpp @@ -11,6 +11,7 @@ #include "DiskController.hpp" #include "../../NumberTheory/CRC.hpp" +#include "../../ClockReceiver/ClockReceiver.hpp" namespace Storage { namespace Disk { @@ -21,7 +22,7 @@ namespace Disk { */ class MFMController: public Controller { public: - MFMController(int clock_rate, int clock_rate_multiplier, int revolutions_per_minute); + MFMController(Cycles clock_rate, int clock_rate_multiplier, int revolutions_per_minute); protected: void set_is_double_density(bool);