From 442986ee2c81f52e3dd1afa6de5a1478e8d628b5 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 1 Dec 2016 20:12:22 -0500 Subject: [PATCH] Introduced a head loading path for 1793 machines. --- Components/1770/1770.cpp | 51 ++++++++++++++++++++++++++++++++++--- Components/1770/1770.hpp | 14 +++++++--- Machines/Oric/Microdisc.cpp | 7 +++++ Machines/Oric/Microdisc.hpp | 1 + 4 files changed, 66 insertions(+), 7 deletions(-) diff --git a/Components/1770/1770.cpp b/Components/1770/1770.cpp index 61e3a67e1..cdc9bb54a 100644 --- a/Components/1770/1770.cpp +++ b/Components/1770/1770.cpp @@ -33,7 +33,8 @@ WD1770::WD1770(Personality p) : is_awaiting_marker_value_(false), is_reading_data_(false), delegate_(nullptr), - personality_(p) + personality_(p), + head_is_loaded_(false) { set_is_double_density(false); posit_event(Event::Command); @@ -255,6 +256,12 @@ void WD1770::process_index_hole() { set_motor_on(false); } + + // head unload + if(index_hole_count_ == 15 && !status_.busy && has_head_load_line()) + { + set_head_load_request(false); + } } // +------+----------+-------------------------+ @@ -301,6 +308,7 @@ void WD1770::process_index_hole() WAIT_FOR_EVENT(Event::IndexHoleTarget); \ status_.spin_up = true; + void WD1770::posit_event(Event new_event_type) { if(!(interesting_event_mask_ & (int)new_event_type)) return; @@ -356,9 +364,24 @@ void WD1770::posit_event(Event new_event_type) status.data_request = false; }); - if((command_&0x08) || get_motor_on() || !has_motor_on_line()) goto test_type1_type; + if(!has_motor_on_line() && !has_head_load_line()) goto test_type1_type; - // Perform spin up. + if(has_motor_on_line()) goto begin_type1_spin_up; + goto begin_type1_load_head; + + begin_type1_load_head: + if(!(command_&0x08)) + { + set_head_load_request(false); + goto test_type1_type; + } + set_head_load_request(true); + if(head_is_loaded_) goto test_type1_type; + WAIT_FOR_EVENT(Event::HeadLoaded); + goto test_type1_type; + + begin_type1_spin_up: + if((command_&0x08) || get_motor_on()) goto test_type1_type; SPIN_UP(); test_type1_type: @@ -457,8 +480,20 @@ void WD1770::posit_event(Event new_event_type) }); distance_into_section_ = 0; - if((command_&0x08) || get_motor_on() || !has_motor_on_line()) goto test_type2_delay; + if((command_&0x08) && has_motor_on_line()) goto test_type2_delay; + if(!has_motor_on_line() && !has_head_load_line()) goto test_type2_delay; + if(has_motor_on_line()) goto begin_type2_spin_up; + goto begin_type2_load_head; + + begin_type2_load_head: + set_head_load_request(true); + if(head_is_loaded_) goto test_type2_delay; + WAIT_FOR_EVENT(Event::HeadLoaded); + goto test_type2_delay; + + begin_type2_spin_up: + if(get_motor_on()) goto test_type2_delay; // Perform spin up. SPIN_UP(); @@ -580,3 +615,11 @@ void WD1770::update_status(std::function updater) } else updater(status_); } + +void WD1770::set_head_load_request(bool head_load) {} + +void WD1770::set_head_loaded(bool head_loaded) +{ + head_is_loaded_ = head_loaded; + if(head_loaded) posit_event(Event::HeadLoaded); +} diff --git a/Components/1770/1770.hpp b/Components/1770/1770.hpp index d9e012bf5..3ad6c72a2 100644 --- a/Components/1770/1770.hpp +++ b/Components/1770/1770.hpp @@ -52,6 +52,10 @@ class WD1770: public Storage::Disk::Controller { }; inline void set_delegate(Delegate *delegate) { delegate_ = delegate; } + protected: + virtual void set_head_load_request(bool head_load); + void set_head_loaded(bool head_loaded); + private: Personality personality_; inline bool has_motor_on_line() { return (personality_ != P1793 ) && (personality_ != P1773); } @@ -102,9 +106,10 @@ class WD1770: public Storage::Disk::Controller { Command = (1 << 0), // Indicates receipt of a new command. Token = (1 << 1), // Indicates recognition of a new token in the flux stream. Interrogate latest_token_ for details. IndexHole = (1 << 2), // Indicates the passing of a physical index hole. + HeadLoaded = (1 << 3), // Indicates the head has been loaded (1973 only). - Timer = (1 << 3), // Indicates that the delay_time_-powered timer has timed out. - IndexHoleTarget = (1 << 4) // Indicates that index_hole_count_ has reached index_hole_count_target_. + Timer = (1 << 4), // Indicates that the delay_time_-powered timer has timed out. + IndexHoleTarget = (1 << 5) // Indicates that index_hole_count_ has reached index_hole_count_target_. }; void posit_event(Event type); int interesting_event_mask_; @@ -114,7 +119,10 @@ class WD1770: public Storage::Disk::Controller { // ID buffer uint8_t header_[6]; - // output line statuses + // 1793 head-loading logic + bool head_is_loaded_; + + // delegate Delegate *delegate_; // Storage::Disk::Controller diff --git a/Machines/Oric/Microdisc.cpp b/Machines/Oric/Microdisc.cpp index 5c74829e4..5ea84f3c7 100644 --- a/Machines/Oric/Microdisc.cpp +++ b/Machines/Oric/Microdisc.cpp @@ -77,3 +77,10 @@ uint8_t Microdisc::get_data_request_register() { return 0x7f | (get_data_request_line() ? 0x00 : 0x80); } + +void Microdisc::set_head_load_request(bool head_load) +{ + set_motor_on(head_load); + // TODO: delay + set_head_loaded(head_load); +} diff --git a/Machines/Oric/Microdisc.hpp b/Machines/Oric/Microdisc.hpp index 12533d3ff..4b460c215 100644 --- a/Machines/Oric/Microdisc.hpp +++ b/Machines/Oric/Microdisc.hpp @@ -37,6 +37,7 @@ class Microdisc: public WD::WD1770 { inline int get_paging_flags() { return paging_flags_; } private: + void set_head_load_request(bool head_load); std::shared_ptr drives_[4]; int selected_drive_; bool irq_enable_;