From aceb7e3b6b91b0899e4a29cfcbc19323b51996e2 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 25 Dec 2016 12:31:38 -0500 Subject: [PATCH] Started implementing write sector on the 1770, immediately deciding it would be useful to have a callback for end-of-queued-data-written from disk controller. So had a go at implementing that, naively. More investigation required. --- Components/1770/1770.cpp | 38 +++++++++++++++++++++++++++++++-- Storage/Disk/DiskController.cpp | 33 +++++++++++++++++++++++++++- Storage/Disk/DiskController.hpp | 11 +++++++++- 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/Components/1770/1770.cpp b/Components/1770/1770.cpp index 807af746a..f739115fb 100644 --- a/Components/1770/1770.cpp +++ b/Components/1770/1770.cpp @@ -11,6 +11,8 @@ using namespace WD; +unsigned int counter = 0; + WD1770::Status::Status() : type(Status::One), write_protect(false), @@ -74,7 +76,12 @@ void WD1770::set_register(int address, uint8_t value) break; case 1: track_ = value; break; case 2: sector_ = value; break; - case 3: data_ = value; break; + case 3: + data_ = value; + update_status([] (Status &status) { + status.data_request = false; + }); + break; } } @@ -136,6 +143,7 @@ uint8_t WD1770::get_register(int address) void WD1770::run_for_cycles(unsigned int number_of_cycles) { + counter += number_of_cycles; Storage::Disk::Controller::run_for_cycles((int)number_of_cycles); if(delay_time_) @@ -288,6 +296,7 @@ void WD1770::process_index_hole() #define WAIT_FOR_EVENT(mask) resume_point_ = __LINE__; interesting_event_mask_ = mask; return; case __LINE__: #define WAIT_FOR_TIME(ms) resume_point_ = __LINE__; interesting_event_mask_ = Event::Timer; delay_time_ = ms * 8000; if(delay_time_) return; case __LINE__: +#define WAIT_FOR_BYTES(count) resume_point_ = __LINE__; interesting_event_mask_ = Event::Token; distance_into_section_ = 0; return; case __LINE__: if(latest_token_.type == Token::Byte) distance_into_section_++; if(distance_into_section_ < count) { interesting_event_mask_ = Event::Token; return; } #define BEGIN_SECTION() switch(resume_point_) { default: #define END_SECTION() 0; } @@ -586,7 +595,32 @@ void WD1770::posit_event(Event new_event_type) type2_write_data: - printf("!!!TODO: data portion of sector!!!\n"); + WAIT_FOR_BYTES(2); + update_status([] (Status &status) { + status.data_request = true; + }); + WAIT_FOR_BYTES(9); + if(status_.data_request) + { + update_status([] (Status &status) { + status.lost_data = true; + }); + goto wait_for_command; + } + WAIT_FOR_BYTES(1); + if(is_double_density_) + { + WAIT_FOR_BYTES(11); + } + + begin_writing(); + for(int c = 0; c < (is_double_density_ ? 12 : 6); c++) + { + // zero is encoded the same way in both FM and MFM + for(int b = 0; b < 16; b++) + write_bit(!(b&1)); + } + end_writing(); begin_type_3: update_status([] (Status &status) { diff --git a/Storage/Disk/DiskController.cpp b/Storage/Disk/DiskController.cpp index fe7378129..a8f0d4991 100644 --- a/Storage/Disk/DiskController.cpp +++ b/Storage/Disk/DiskController.cpp @@ -7,6 +7,7 @@ // #include "DiskController.hpp" +#include "../../NumberTheory/Factors.hpp" using namespace Storage::Disk; @@ -55,6 +56,8 @@ void Controller::setup_track() void Controller::run_for_cycles(int number_of_cycles) { + Time zero(0); + if(drive_ && drive_->has_disk() && motor_is_on_) { if(!track_) setup_track(); @@ -64,11 +67,31 @@ void Controller::run_for_cycles(int number_of_cycles) { int cycles_until_next_event = (int)get_cycles_until_next_event(); int cycles_to_run_for = std::min(cycles_until_next_event, number_of_cycles); + if(!is_reading_ && cycles_until_bits_written_ > zero) cycles_to_run_for = std::min(cycles_to_run_for, (int)cycles_until_bits_written_.get_unsigned_int()); cycles_since_index_hole_ += (unsigned int)cycles_to_run_for; number_of_cycles -= cycles_to_run_for; - if(is_reading_) pll_->run_for_cycles(cycles_to_run_for); + if(is_reading_) + { + pll_->run_for_cycles(cycles_to_run_for); + } + else + { + if(cycles_until_bits_written_ > Storage::Time(0)) + { + Storage::Time number_of_cycles_time(number_of_cycles); + if(cycles_until_bits_written_ < number_of_cycles_time) + { + cycles_until_bits_written_.set_zero(); + process_write_completed(); + } + else + { + cycles_until_bits_written_ -= number_of_cycles_time; + } + } + } TimedEventLoop::run_for_cycles(cycles_to_run_for); } } @@ -136,6 +159,8 @@ void Controller::write_bit(bool value) if(needs_new_byte) write_segment_.data.push_back(0); if(value) write_segment_.data[write_segment_.number_of_bits >> 3] |= 0x80 >> (write_segment_.number_of_bits & 7); write_segment_.number_of_bits++; + + cycles_until_bits_written_ += cycles_per_bit_; } void Controller::end_writing() @@ -155,6 +180,8 @@ void Controller::set_expected_bit_length(Time bit_length) { bit_length_ = bit_length; + cycles_per_bit_ = Storage::Time(8000000) * (bit_length * rotational_multiplier_); + // this conversion doesn't need to be exact because there's a lot of variation to be taken // account of in rotation speed, air turbulence, etc, so a direct conversion will do int clocks_per_bit = (int)((bit_length.length * clock_rate_) / bit_length.clock_rate); @@ -213,3 +240,7 @@ void Controller::invalidate_track() { track_ = nullptr; } + +void Controller::process_write_completed() +{ +} diff --git a/Storage/Disk/DiskController.hpp b/Storage/Disk/DiskController.hpp index 367259776..1ab09adde 100644 --- a/Storage/Disk/DiskController.hpp +++ b/Storage/Disk/DiskController.hpp @@ -86,10 +86,16 @@ class Controller: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop virtual void process_input_bit(int value, unsigned int cycles_since_index_hole) = 0; /*! - Should be implemented by subcalsses; communicates that the index hole has been reached. + Should be implemented by subclasses; communicates that the index hole has been reached. */ virtual void process_index_hole() = 0; + /*! + Should be implemented by subclasses if they implement writing; communicates that + all bits supplied to write_bit have now been written. + */ + virtual void process_write_completed(); + // for TimedEventLoop virtual void process_next_event(); @@ -122,6 +128,9 @@ class Controller: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop PCMSegment write_segment_; Time write_start_time_; + Time cycles_until_bits_written_; + Time cycles_per_bit_; + void setup_track(); Time get_time_into_track(); };