1
0
mirror of https://github.com/TomHarte/CLK.git synced 2026-04-22 08:16:42 +00:00

Attempts to pull drive ownership into DiskController.

For the sake of being more intelligent as to drive clocking, hopefully. And, eventually, to support multiple drive selection.
This commit is contained in:
Thomas Harte
2020-02-11 21:59:13 -05:00
parent 654f5b0478
commit 05bcd73f82
17 changed files with 157 additions and 138 deletions
+27 -20
View File
@@ -14,9 +14,9 @@ Controller::Controller(Cycles clock_rate) :
clock_rate_multiplier_(128000000 / clock_rate.as_integral()),
clock_rate_(clock_rate.as_integral() * clock_rate_multiplier_),
pll_(100, *this),
empty_drive_(new Drive(int(clock_rate.as_integral()), 1, 1)) {
empty_drive_(int(clock_rate.as_integral()), 1, 1),
drive_(&empty_drive_) {
set_expected_bit_length(Time(1));
set_drive(empty_drive_);
}
void Controller::set_component_prefers_clocking(ClockingHint::Source *component, ClockingHint::Preference clocking) {
@@ -32,7 +32,7 @@ void Controller::run_for(const Cycles cycles) {
}
Drive &Controller::get_drive() {
return *drive_.get();
return *drive_;
}
// MARK: - Drive::EventDelegate
@@ -71,26 +71,33 @@ void Controller::digital_phase_locked_loop_output_bit(int value) {
if(is_reading_) process_input_bit(value);
}
void Controller::set_drive(std::shared_ptr<Drive> drive) {
if(drive_ != drive) {
ClockingHint::Preference former_prefernece = preferred_clocking();
// invalidate_track();
void Controller::set_drive(int index_mask) {
if(drive_selection_mask_ == index_mask) {
return;
}
if(drive_) {
drive_->set_event_delegate(nullptr);
drive_->set_clocking_hint_observer(nullptr);
}
drive_ = drive;
if(drive_) {
drive_->set_event_delegate(this);
drive_->set_clocking_hint_observer(this);
} else {
drive_ = empty_drive_;
}
ClockingHint::Preference former_prefernece = preferred_clocking();
// invalidate_track();
if(preferred_clocking() != former_prefernece) {
update_clocking_observer();
get_drive().set_event_delegate(nullptr);
get_drive().set_clocking_hint_observer(nullptr);
if(!index_mask) {
drive_ = &empty_drive_;
} else {
size_t index = 0;
while(!(index_mask&1)) {
index_mask >>= 1;
++index;
}
drive_ = &drives_[index];
}
get_drive().set_event_delegate(this);
get_drive().set_clocking_hint_observer(this);
if(preferred_clocking() != former_prefernece) {
update_clocking_observer();
}
}
+34 -5
View File
@@ -49,9 +49,25 @@ class Controller:
void run_for(const Cycles cycles);
/*!
Sets the current drive. This drive is the one the PLL listens to.
Sets the current drive(s). Normally this will be exactly one, but some machines allow
zero or multiple drives to be attached, with useless results.
*/
void set_drive(std::shared_ptr<Drive> drive);
void set_drive(int index_mask);
/*!
Adds a new drive to the attached list, returning its index.
*/
template<typename... Args> size_t emplace_drive(Args&&... args) {
drives_.emplace_back(std::forward<Args>(args)...);
return drives_.size() - 1;
}
template<typename... Args> size_t emplace_drives(size_t count, Args&&... args) {
while(count--) {
drives_.emplace_back(std::forward<Args>(args)...);
}
return drives_.size() - 1;
}
/*!
Should be implemented by subclasses; communicates each bit that the PLL recognises.
@@ -98,6 +114,18 @@ class Controller:
*/
Drive &get_drive();
Drive &get_drive(size_t index) {
return drives_[index];
}
void for_all_drives(const std::function<void(Drive &, size_t)> &func) {
size_t index = 0;
for(auto &drive: drives_) {
func(drive, index);
++index;
}
}
/*!
As per ClockingHint::Source.
*/
@@ -113,9 +141,10 @@ class Controller:
DigitalPhaseLockedLoop<Controller> pll_;
friend DigitalPhaseLockedLoop<Controller>;
std::shared_ptr<Drive> drive_;
std::shared_ptr<Drive> empty_drive_;
Drive empty_drive_;
std::vector<Drive> drives_;
Drive *drive_;
int drive_selection_mask_ = 0xff;
// ClockingHint::Observer.
void set_component_prefers_clocking(ClockingHint::Source *component, ClockingHint::Preference clocking) final;