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:
parent
fed2bc9fc9
commit
90c7056d12
@ -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];
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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) {
|
||||||
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user