mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 20:29:42 +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:
parent
25fd3f7e50
commit
29288b690e
@ -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) {
|
||||
}
|
||||
|
@ -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_;
|
||||
};
|
||||
|
@ -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_;
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user