1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-26 09:29:45 +00:00

Started devolving timed event loop logic down to the drives, moving them closer to modelling real life.

This commit is contained in:
Thomas Harte 2017-09-10 14:43:20 -04:00
parent fed2bc9fc9
commit 90c7056d12
9 changed files with 76 additions and 16 deletions

View File

@ -103,7 +103,7 @@ class i8272: public Storage::Disk::MFMController {
Drive() : Drive() :
head_position(0), phase(NotSeeking), 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_is_loaded{false, false},
head_unload_delay{0, 0} {}; head_unload_delay{0, 0} {};
} drives_[4]; } drives_[4];

View File

@ -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) { 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); drive->set_disk(disk);
set_drive(drive); set_drive(drive);
} }

View File

@ -16,7 +16,7 @@ Plus3::Plus3() : WD1770(P1770) {
void Plus3::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive) { void Plus3::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive) {
if(!drives_[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]); if(drive == selected_drive_) set_drive(drives_[drive]);
} }
drives_[drive]->set_disk(disk); drives_[drive]->set_disk(disk);

View File

@ -30,7 +30,7 @@ Microdisc::Microdisc() :
void Microdisc::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive) { void Microdisc::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive) {
if(!drives_[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]); if(drive == selected_drive_) set_drive(drives_[drive]);
} }
drives_[drive]->set_disk(disk); drives_[drive]->set_disk(disk);

View File

@ -22,7 +22,7 @@ class CommodoreGCRParser: public Storage::Disk::Controller {
std::shared_ptr<Storage::Disk::Drive> drive; std::shared_ptr<Storage::Disk::Drive> drive;
CommodoreGCRParser() : Storage::Disk::Controller(4000000, 1, 300), shift_register_(0), track_(1) { 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_drive(drive);
set_motor_on(true); set_motor_on(true);
} }

View File

@ -47,7 +47,6 @@ class Controller: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop
Advances the drive by @c number_of_cycles cycles. Advances the drive by @c number_of_cycles cycles.
*/ */
void run_for(const Cycles cycles); void run_for(const Cycles cycles);
using TimedEventLoop::run_for;
/*! /*!
Sets the current drive. Sets the current drive.

View File

@ -11,8 +11,10 @@
using namespace Storage::Disk; using namespace Storage::Disk;
Drive::Drive() Drive::Drive(unsigned int input_clock_rate, int revolutions_per_minute):
: head_position_(0), head_(0), has_disk_(false) {} Storage::TimedEventLoop(input_clock_rate),
rotational_multiplier_(60, revolutions_per_minute) {
}
void Drive::set_disk(const std::shared_ptr<Disk> &disk) { void Drive::set_disk(const std::shared_ptr<Disk> &disk) {
disk_ = disk; disk_ = disk;
@ -33,7 +35,7 @@ bool Drive::has_disk() {
} }
bool Drive::is_sleeping() { bool Drive::is_sleeping() {
return !has_disk_; return !motor_is_on_ || !has_disk_;
} }
bool Drive::get_is_track_zero() { bool Drive::get_is_track_zero() {
@ -41,8 +43,22 @@ bool Drive::get_is_track_zero() {
} }
void Drive::step(int direction) { void Drive::step(int direction) {
int old_head_position = head_position_;
head_position_ = std::max(head_position_ + direction, 0); 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) { 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) { void Drive::set_track(const std::shared_ptr<Track> &track) {
if(disk_) disk_->set_track_at_position(head_, (unsigned int)head_position_, 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) {
}

View File

@ -13,13 +13,14 @@
#include "Disk.hpp" #include "Disk.hpp"
#include "../../ClockReceiver/Sleeper.hpp" #include "../../ClockReceiver/Sleeper.hpp"
#include "../TimedEventLoop.hpp"
namespace Storage { namespace Storage {
namespace Disk { namespace Disk {
class Drive: public Sleeper { class Drive: public Sleeper, public TimedEventLoop {
public: public:
Drive(); Drive(unsigned int input_clock_rate, int revolutions_per_minute);
/*! /*!
Replaces whatever is in the drive with @c disk. Replaces whatever is in the drive with @c disk.
@ -72,15 +73,47 @@ class Drive: public Sleeper {
*/ */
bool get_is_ready(); 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. // As per Sleeper.
bool is_sleeping(); bool is_sleeping();
private: private:
std::shared_ptr<Track> track_; std::shared_ptr<Track> track_;
std::shared_ptr<Disk> disk_; std::shared_ptr<Disk> disk_;
bool has_disk_; int cycles_since_index_hole_ = 0;
int head_position_; Time rotational_multiplier_;
unsigned int head_;
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;
}; };

View File

@ -243,7 +243,7 @@ Parser::Parser(bool is_mfm) :
bit_length.clock_rate = is_mfm ? 500000 : 250000; // i.e. 250 kbps (including clocks) bit_length.clock_rate = is_mfm ? 500000 : 250000; // i.e. 250 kbps (including clocks)
set_expected_bit_length(bit_length); set_expected_bit_length(bit_length);
drive_.reset(new Storage::Disk::Drive); drive_.reset(new Storage::Disk::Drive(4000000, 300));
set_drive(drive_); set_drive(drive_);
set_motor_on(true); set_motor_on(true);
} }