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:
parent
901f19f89c
commit
aceb7e3b6b
@ -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) {
|
||||
|
@ -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()
|
||||
{
|
||||
}
|
||||
|
@ -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();
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user