mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-25 18:30:21 +00:00
Started devolving timed event loop logic down to the drives, moving them closer to modelling real life.
This commit is contained in:
parent
fed2bc9fc9
commit
90c7056d12
@ -103,7 +103,7 @@ class i8272: public Storage::Disk::MFMController {
|
||||
|
||||
Drive() :
|
||||
head_position(0), phase(NotSeeking),
|
||||
drive(new Storage::Disk::Drive),
|
||||
drive(new Storage::Disk::Drive(8000000, 300)), // TODO: these constants can't live here.
|
||||
head_is_loaded{false, false},
|
||||
head_unload_delay{0, 0} {};
|
||||
} drives_[4];
|
||||
|
@ -82,7 +82,7 @@ void Machine::set_rom(const std::vector<uint8_t> &rom) {
|
||||
}
|
||||
|
||||
void Machine::set_disk(std::shared_ptr<Storage::Disk::Disk> disk) {
|
||||
std::shared_ptr<Storage::Disk::Drive> drive(new Storage::Disk::Drive);
|
||||
std::shared_ptr<Storage::Disk::Drive> drive(new Storage::Disk::Drive(1000000, 300));
|
||||
drive->set_disk(disk);
|
||||
set_drive(drive);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ Plus3::Plus3() : WD1770(P1770) {
|
||||
|
||||
void Plus3::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive) {
|
||||
if(!drives_[drive]) {
|
||||
drives_[drive].reset(new Storage::Disk::Drive);
|
||||
drives_[drive].reset(new Storage::Disk::Drive(8000000, 300));
|
||||
if(drive == selected_drive_) set_drive(drives_[drive]);
|
||||
}
|
||||
drives_[drive]->set_disk(disk);
|
||||
|
@ -30,7 +30,7 @@ Microdisc::Microdisc() :
|
||||
|
||||
void Microdisc::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive) {
|
||||
if(!drives_[drive]) {
|
||||
drives_[drive].reset(new Storage::Disk::Drive);
|
||||
drives_[drive].reset(new Storage::Disk::Drive(8000000, 300));
|
||||
if(drive == selected_drive_) set_drive(drives_[drive]);
|
||||
}
|
||||
drives_[drive]->set_disk(disk);
|
||||
|
@ -22,7 +22,7 @@ class CommodoreGCRParser: public Storage::Disk::Controller {
|
||||
std::shared_ptr<Storage::Disk::Drive> drive;
|
||||
|
||||
CommodoreGCRParser() : Storage::Disk::Controller(4000000, 1, 300), shift_register_(0), track_(1) {
|
||||
drive.reset(new Storage::Disk::Drive);
|
||||
drive.reset(new Storage::Disk::Drive(4000000, 300));
|
||||
set_drive(drive);
|
||||
set_motor_on(true);
|
||||
}
|
||||
|
@ -47,7 +47,6 @@ class Controller: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop
|
||||
Advances the drive by @c number_of_cycles cycles.
|
||||
*/
|
||||
void run_for(const Cycles cycles);
|
||||
using TimedEventLoop::run_for;
|
||||
|
||||
/*!
|
||||
Sets the current drive.
|
||||
|
@ -11,8 +11,10 @@
|
||||
|
||||
using namespace Storage::Disk;
|
||||
|
||||
Drive::Drive()
|
||||
: head_position_(0), head_(0), has_disk_(false) {}
|
||||
Drive::Drive(unsigned int input_clock_rate, int revolutions_per_minute):
|
||||
Storage::TimedEventLoop(input_clock_rate),
|
||||
rotational_multiplier_(60, revolutions_per_minute) {
|
||||
}
|
||||
|
||||
void Drive::set_disk(const std::shared_ptr<Disk> &disk) {
|
||||
disk_ = disk;
|
||||
@ -33,7 +35,7 @@ bool Drive::has_disk() {
|
||||
}
|
||||
|
||||
bool Drive::is_sleeping() {
|
||||
return !has_disk_;
|
||||
return !motor_is_on_ || !has_disk_;
|
||||
}
|
||||
|
||||
bool Drive::get_is_track_zero() {
|
||||
@ -41,8 +43,22 @@ bool Drive::get_is_track_zero() {
|
||||
}
|
||||
|
||||
void Drive::step(int direction) {
|
||||
int old_head_position = head_position_;
|
||||
head_position_ = std::max(head_position_ + direction, 0);
|
||||
printf("Head -> %d\n", head_position_);
|
||||
|
||||
// If the head moved and this drive has a real disk in it, flush the old track.
|
||||
if(head_position_ != old_head_position && disk_ != nullptr) {
|
||||
track_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Storage::Time Drive::get_time_into_track() {
|
||||
// `result` will initially be amount of time since the index hole was seen as a
|
||||
// proportion of a second; convert it into proportion of a rotation, simplify and return.
|
||||
Time result(cycles_since_index_hole_, 8000000);
|
||||
result /= rotational_multiplier_;
|
||||
result.simplify();
|
||||
return result;
|
||||
}
|
||||
|
||||
void Drive::set_head(unsigned int head) {
|
||||
@ -68,3 +84,15 @@ std::shared_ptr<Track> Drive::get_track() {
|
||||
void Drive::set_track(const std::shared_ptr<Track> &track) {
|
||||
if(disk_) disk_->set_track_at_position(head_, (unsigned int)head_position_, track);
|
||||
}
|
||||
|
||||
void Drive::set_motor_on(bool motor_is_on) {
|
||||
motor_is_on_ = motor_is_on;
|
||||
update_sleep_observer();
|
||||
}
|
||||
|
||||
void Drive::process_next_event() {
|
||||
if(event_delegate_) event_delegate_->process_event(current_event_);
|
||||
}
|
||||
|
||||
void Drive::run_for(const Cycles cycles) {
|
||||
}
|
||||
|
@ -13,13 +13,14 @@
|
||||
|
||||
#include "Disk.hpp"
|
||||
#include "../../ClockReceiver/Sleeper.hpp"
|
||||
#include "../TimedEventLoop.hpp"
|
||||
|
||||
namespace Storage {
|
||||
namespace Disk {
|
||||
|
||||
class Drive: public Sleeper {
|
||||
class Drive: public Sleeper, public TimedEventLoop {
|
||||
public:
|
||||
Drive();
|
||||
Drive(unsigned int input_clock_rate, int revolutions_per_minute);
|
||||
|
||||
/*!
|
||||
Replaces whatever is in the drive with @c disk.
|
||||
@ -72,15 +73,47 @@ class Drive: public Sleeper {
|
||||
*/
|
||||
bool get_is_ready();
|
||||
|
||||
/*!
|
||||
Sets whether the disk motor is on.
|
||||
*/
|
||||
void set_motor_on(bool);
|
||||
|
||||
/*!
|
||||
Advances the drive by @c number_of_cycles cycles.
|
||||
*/
|
||||
void run_for(const Cycles cycles);
|
||||
|
||||
/*!
|
||||
Provides a mechanism to receive track events as they occur.
|
||||
*/
|
||||
struct EventDelegate {
|
||||
virtual void process_event(const Track::Event &event) = 0;
|
||||
};
|
||||
|
||||
/// Sets the current event delegate.
|
||||
void set_event_delegate(EventDelegate *);
|
||||
|
||||
// As per Sleeper.
|
||||
bool is_sleeping();
|
||||
|
||||
private:
|
||||
std::shared_ptr<Track> track_;
|
||||
std::shared_ptr<Disk> disk_;
|
||||
bool has_disk_;
|
||||
int head_position_;
|
||||
unsigned int head_;
|
||||
int cycles_since_index_hole_ = 0;
|
||||
Time rotational_multiplier_;
|
||||
|
||||
bool has_disk_ = false;
|
||||
|
||||
int head_position_ = 0;
|
||||
unsigned int head_ = 0;
|
||||
|
||||
void process_next_event();
|
||||
void get_next_event(const Time &duration_already_passed);
|
||||
Track::Event current_event_;
|
||||
bool motor_is_on_ = false;
|
||||
|
||||
Time get_time_into_track();
|
||||
EventDelegate *event_delegate_ = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
@ -243,7 +243,7 @@ Parser::Parser(bool is_mfm) :
|
||||
bit_length.clock_rate = is_mfm ? 500000 : 250000; // i.e. 250 kbps (including clocks)
|
||||
set_expected_bit_length(bit_length);
|
||||
|
||||
drive_.reset(new Storage::Disk::Drive);
|
||||
drive_.reset(new Storage::Disk::Drive(4000000, 300));
|
||||
set_drive(drive_);
|
||||
set_motor_on(true);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user