1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-27 06:35:04 +00:00

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.

This commit is contained in:
Thomas Harte 2016-12-25 12:31:38 -05:00
parent 901f19f89c
commit aceb7e3b6b
3 changed files with 78 additions and 4 deletions

View File

@ -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) {

View File

@ -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()
{
}

View File

@ -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();
};