1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-27 18:55:48 +00:00

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.

This commit is contained in:
Thomas Harte 2017-08-06 09:45:16 -04:00
parent 25fd3f7e50
commit 29288b690e
7 changed files with 51 additions and 10 deletions

View File

@ -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) {
}

View File

@ -9,17 +9,24 @@
#ifndef i8272_hpp
#define i8272_hpp
#include "../../Storage/Disk/MFMDiskController.hpp"
#include <cstdint>
#include <vector>
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<uint8_t> command_;
};

View File

@ -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<i8255PortHandler> i8255_;
Intel::i8272 i8272_;
FDC fdc_;
InterruptTimer interrupt_timer_;
Storage::Tape::BinaryTapePlayer tape_player_;

View File

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

View File

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

View File

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

View File

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