1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-10-07 06:57:15 +00:00

Merge pull request #727 from TomHarte/RDYs

Adds emulation of non-default types of floppy drive RDY output
This commit is contained in:
Thomas Harte 2020-01-16 22:07:41 -05:00 committed by GitHub
commit cb8a7a4137
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 15 deletions

View File

@ -10,7 +10,7 @@
using namespace Oric; using namespace Oric;
BD500::BD500() : DiskController(P1793, 9000000) { BD500::BD500() : DiskController(P1793, 9000000, Storage::Disk::Drive::ReadyType::ShugartModifiedRDY) {
disable_basic_rom_ = true; disable_basic_rom_ = true;
select_paged_item(); select_paged_item();
set_is_double_density(true); set_is_double_density(true);

View File

@ -13,13 +13,13 @@ namespace Oric {
class DiskController: public WD::WD1770 { class DiskController: public WD::WD1770 {
public: public:
DiskController(WD::WD1770::Personality personality, int clock_rate) : DiskController(WD::WD1770::Personality personality, int clock_rate, Storage::Disk::Drive::ReadyType ready_type) :
WD::WD1770(personality), clock_rate_(clock_rate) {} WD::WD1770(personality), clock_rate_(clock_rate), ready_type_(ready_type) {}
void set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int d) { void set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int d) {
const size_t drive = size_t(d); const size_t drive = size_t(d);
if(!drives_[drive]) { if(!drives_[drive]) {
drives_[drive] = std::make_unique<Storage::Disk::Drive>(clock_rate_, 300, 2); drives_[drive] = std::make_unique<Storage::Disk::Drive>(clock_rate_, 300, 2, ready_type_);
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);
@ -67,6 +67,7 @@ class DiskController: public WD::WD1770 {
private: private:
PagedItem paged_item_ = PagedItem::DiskROM; PagedItem paged_item_ = PagedItem::DiskROM;
int clock_rate_; int clock_rate_;
Storage::Disk::Drive::ReadyType ready_type_;
inline void set_paged_item(PagedItem item) { inline void set_paged_item(PagedItem item) {
if(paged_item_ == item) return; if(paged_item_ == item) return;

View File

@ -12,7 +12,7 @@ using namespace Oric;
// NB: there's some controversy here on WD1770 versus WD1772, but between those two I think // NB: there's some controversy here on WD1770 versus WD1772, but between those two I think
// the only difference is stepping rates, and it says 1770 on the schematic I'm looking at. // the only difference is stepping rates, and it says 1770 on the schematic I'm looking at.
Jasmin::Jasmin() : DiskController(P1770, 8000000) { Jasmin::Jasmin() : DiskController(P1770, 8000000, Storage::Disk::Drive::ReadyType::ShugartRDY) {
set_is_double_density(true); set_is_double_density(true);
select_paged_item(); select_paged_item();
} }

View File

@ -18,7 +18,7 @@ namespace {
const Cycles::IntType head_load_request_counter_target = 7653333; const Cycles::IntType head_load_request_counter_target = 7653333;
} }
Microdisc::Microdisc() : DiskController(P1793, 8000000) { Microdisc::Microdisc() : DiskController(P1793, 8000000, Storage::Disk::Drive::ReadyType::ShugartRDY) {
set_control_register(last_control_, 0xff); set_control_register(last_control_, 0xff);
} }

View File

@ -18,9 +18,10 @@
using namespace Storage::Disk; using namespace Storage::Disk;
Drive::Drive(int input_clock_rate, int revolutions_per_minute, int number_of_heads): Drive::Drive(int input_clock_rate, int revolutions_per_minute, int number_of_heads, ReadyType rdy_type):
Storage::TimedEventLoop(input_clock_rate), Storage::TimedEventLoop(input_clock_rate),
available_heads_(number_of_heads) { available_heads_(number_of_heads),
ready_type_(rdy_type) {
set_rotation_speed(revolutions_per_minute); set_rotation_speed(revolutions_per_minute);
const auto seed = static_cast<std::default_random_engine::result_type>(std::chrono::system_clock::now().time_since_epoch().count()); const auto seed = static_cast<std::default_random_engine::result_type>(std::chrono::system_clock::now().time_since_epoch().count());
@ -35,7 +36,7 @@ Drive::Drive(int input_clock_rate, int revolutions_per_minute, int number_of_hea
} }
} }
Drive::Drive(int input_clock_rate, int number_of_heads) : Drive(input_clock_rate, 300, number_of_heads) {} Drive::Drive(int input_clock_rate, int number_of_heads, ReadyType rdy_type) : Drive(input_clock_rate, 300, number_of_heads, rdy_type) {}
void Drive::set_rotation_speed(float revolutions_per_minute) { void Drive::set_rotation_speed(float revolutions_per_minute) {
// Rationalise the supplied speed so that cycles_per_revolution_ is exact. // Rationalise the supplied speed so that cycles_per_revolution_ is exact.
@ -54,6 +55,9 @@ Drive::~Drive() {
} }
void Drive::set_disk(const std::shared_ptr<Disk> &disk) { void Drive::set_disk(const std::shared_ptr<Disk> &disk) {
if(ready_type_ == ReadyType::ShugartModifiedRDY || ready_type_ == ReadyType::IBMRDY) {
is_ready_ = false;
}
if(disk_) disk_->flush_tracks(); if(disk_) disk_->flush_tracks();
disk_ = disk; disk_ = disk;
has_disk_ = !!disk_; has_disk_ = !!disk_;
@ -76,6 +80,10 @@ bool Drive::get_is_track_zero() const {
} }
void Drive::step(HeadPosition offset) { void Drive::step(HeadPosition offset) {
if(ready_type_ == ReadyType::IBMRDY) {
is_ready_ = true;
}
HeadPosition old_head_position = head_position_; HeadPosition old_head_position = head_position_;
head_position_ += offset; head_position_ += offset;
if(head_position_ < HeadPosition(0)) { if(head_position_ < HeadPosition(0)) {
@ -142,7 +150,7 @@ bool Drive::get_is_read_only() const {
} }
bool Drive::get_is_ready() const { bool Drive::get_is_ready() const {
return ready_index_count_ == 2; return is_ready_;
} }
void Drive::set_motor_on(bool motor_is_on) { void Drive::set_motor_on(bool motor_is_on) {
@ -303,7 +311,10 @@ void Drive::get_next_event(float duration_already_passed) {
void Drive::process_next_event() { void Drive::process_next_event() {
if(current_event_.type == Track::Event::IndexHole) { if(current_event_.type == Track::Event::IndexHole) {
if(ready_index_count_ < 2) ready_index_count_++; ++ready_index_count_;
if(ready_index_count_ == 2 && (ready_type_ == ReadyType::ShugartRDY || ready_type_ == ReadyType::ShugartModifiedRDY)) {
is_ready_ = true;
}
cycles_since_index_hole_ = 0; cycles_since_index_hole_ = 0;
} }
if( if(
@ -427,6 +438,9 @@ void Drive::set_disk_is_rotating(bool is_rotating) {
} }
if(!is_rotating) { if(!is_rotating) {
if(ready_type_ == ReadyType::ShugartRDY) {
is_ready_ = false;
}
ready_index_count_ = 0; ready_index_count_ = 0;
if(disk_) disk_->flush_tracks(); if(disk_) disk_->flush_tracks();
} }

View File

@ -24,12 +24,21 @@ namespace Disk {
class Drive: public ClockingHint::Source, public TimedEventLoop { class Drive: public ClockingHint::Source, public TimedEventLoop {
public: public:
Drive(int input_clock_rate, int revolutions_per_minute, int number_of_heads); enum class ReadyType {
Drive(int input_clock_rate, int number_of_heads); /// Indicates that RDY will go active when the motor is on and two index holes have passed; it will go inactive when the motor is off.
ShugartRDY,
/// Indicates that RDY will go active when the motor is on and two index holes have passed; it will go inactive when the disk is ejected.
ShugartModifiedRDY,
/// Indicates that RDY will go active when the head steps; it will go inactive when the disk is ejected.
IBMRDY,
};
Drive(int input_clock_rate, int revolutions_per_minute, int number_of_heads, ReadyType rdy_type = ReadyType::ShugartRDY);
Drive(int input_clock_rate, int number_of_heads, ReadyType rdy_type = ReadyType::ShugartRDY);
~Drive(); ~Drive();
/*! /*!
Replaces whatever is in the drive with @c disk. Replaces whatever is in the drive with @c disk. Supply @c nullptr to eject any current disk and leave none inserted.
*/ */
void set_disk(const std::shared_ptr<Disk> &disk); void set_disk(const std::shared_ptr<Disk> &disk);
@ -232,8 +241,10 @@ class Drive: public ClockingHint::Source, public TimedEventLoop {
PCMSegment write_segment_; PCMSegment write_segment_;
Time write_start_time_; Time write_start_time_;
// Indicates progress towards drive ready state. // Indicates progress towards Shugart-style drive ready states.
int ready_index_count_ = 0; int ready_index_count_ = 0;
ReadyType ready_type_;
bool is_ready_ = false;
// Maintains appropriate counting to know when to indicate that writing // Maintains appropriate counting to know when to indicate that writing
// is complete. // is complete.