1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-22 12:33:29 +00:00

Strips Controller of all capabilities now housed on the Drive.

This commit is contained in:
Thomas Harte 2017-09-10 19:23:23 -04:00
parent 523e1288fa
commit 0622187ddf
16 changed files with 124 additions and 295 deletions

View File

@ -75,7 +75,7 @@ uint8_t WD1770::get_register(int address) {
switch(status_.type) {
case Status::One:
status |=
(get_is_track_zero() ? Flag::TrackZero : 0) |
(get_drive().get_is_track_zero() ? Flag::TrackZero : 0) |
(status_.seek_error ? Flag::SeekError : 0);
// TODO: index hole
break;
@ -91,11 +91,11 @@ uint8_t WD1770::get_register(int address) {
}
if(!has_motor_on_line()) {
status |= get_drive_is_ready() ? 0 : Flag::NotReady;
status |= get_drive().get_is_ready() ? 0 : Flag::NotReady;
if(status_.type == Status::One)
status |= (head_is_loaded_ ? Flag::HeadLoaded : 0);
} else {
status |= (get_motor_on() ? Flag::MotorOn : 0);
status |= (get_drive().get_motor_on() ? Flag::MotorOn : 0);
if(status_.type == Status::One)
status |= (status_.spin_up ? Flag::SpinUp : 0);
}
@ -145,7 +145,7 @@ void WD1770::run_for(const Cycles cycles) {
#define LINE_LABEL INDIRECT_CONCATENATE(label, __LINE__)
#define SPIN_UP() \
set_motor_on(true); \
get_drive().set_motor_on(true); \
index_hole_count_ = 0; \
index_hole_count_target_ = 6; \
WAIT_FOR_EVENT(Event1770::IndexHoleTarget); \
@ -178,7 +178,7 @@ void WD1770::posit_event(int new_event_type) {
// motor power-down
if(index_hole_count_ == 9 && !status_.busy && has_motor_on_line()) {
set_motor_on(false);
get_drive().set_motor_on(false);
}
// head unload
@ -257,7 +257,7 @@ void WD1770::posit_event(int new_event_type) {
goto test_type1_type;
begin_type1_spin_up:
if((command_&0x08) || get_motor_on()) goto test_type1_type;
if((command_&0x08) || get_drive().get_motor_on()) goto test_type1_type;
SPIN_UP();
test_type1_type:
@ -280,11 +280,11 @@ void WD1770::posit_event(int new_event_type) {
if(step_direction_) track_++; else track_--;
perform_step:
if(!step_direction_ && get_is_track_zero()) {
if(!step_direction_ && get_drive().get_is_track_zero()) {
track_ = 0;
goto verify;
}
step(step_direction_ ? 1 : -1);
get_drive().step(step_direction_ ? 1 : -1);
unsigned int time_to_wait;
switch(command_ & 3) {
default:
@ -376,7 +376,7 @@ void WD1770::posit_event(int new_event_type) {
goto test_type2_delay;
begin_type2_spin_up:
if(get_motor_on()) goto test_type2_delay;
if(get_drive().get_motor_on()) goto test_type2_delay;
// Perform spin up.
SPIN_UP();
@ -386,7 +386,7 @@ void WD1770::posit_event(int new_event_type) {
WAIT_FOR_TIME(30);
test_type2_write_protection:
if(command_&0x20 && get_drive_is_read_only()) {
if(command_&0x20 && get_drive().get_is_read_only()) {
update_status([] (Status &status) {
status.write_protect = true;
});
@ -541,7 +541,7 @@ void WD1770::posit_event(int new_event_type) {
});
WAIT_FOR_EVENT(Event::DataWritten);
if(status_.data_request) {
end_writing();
get_drive().end_writing();
update_status([] (Status &status) {
status.lost_data = true;
});
@ -554,7 +554,7 @@ void WD1770::posit_event(int new_event_type) {
write_crc();
write_byte(0xff);
WAIT_FOR_EVENT(Event::DataWritten);
end_writing();
get_drive().end_writing();
if(command_ & 0x10) {
sector_++;
@ -594,7 +594,7 @@ void WD1770::posit_event(int new_event_type) {
goto type3_test_delay;
begin_type3_spin_up:
if((command_&0x08) || get_motor_on()) goto type3_test_delay;
if((command_&0x08) || get_drive().get_motor_on()) goto type3_test_delay;
SPIN_UP();
type3_test_delay:
@ -675,7 +675,7 @@ void WD1770::posit_event(int new_event_type) {
});
write_track_test_write_protect:
if(get_drive_is_read_only()) {
if(get_drive().get_is_read_only()) {
update_status([] (Status &status) {
status.write_protect = true;
});
@ -755,11 +755,11 @@ void WD1770::posit_event(int new_event_type) {
update_status([] (Status &status) {
status.lost_data = true;
});
end_writing();
get_drive().end_writing();
goto wait_for_command;
}
if(index_hole_count_) {
end_writing();
get_drive().end_writing();
goto wait_for_command;
}

View File

@ -236,9 +236,8 @@ void i8272::set_disk(std::shared_ptr<Storage::Disk::Disk> disk, int drive) {
active_drive_ = command_[1]&3; \
active_head_ = (command_[1] >> 2)&1; \
set_drive(drives_[active_drive_].drive); \
drives_[active_drive_].drive->set_head((unsigned int)active_head_); \
set_is_double_density(command_[0] & 0x40); \
invalidate_track();
get_drive().set_head((unsigned int)active_head_); \
set_is_double_density(command_[0] & 0x40);
#define WAIT_FOR_BYTES(n) \
distance_into_section_ = 0; \
@ -527,7 +526,7 @@ void i8272::posit_event(int event_type) {
WAIT_FOR_EVENT(Event::DataWritten);
if(!has_input_) {
SetOverrun();
end_writing();
get_drive().end_writing();
goto abort;
}
write_byte(input_);
@ -542,7 +541,7 @@ void i8272::posit_event(int event_type) {
write_crc();
expects_input_ = false;
WAIT_FOR_EVENT(Event::DataWritten);
end_writing();
get_drive().end_writing();
if(sector_ != command_[6]) {
sector_++;
@ -648,7 +647,7 @@ void i8272::posit_event(int event_type) {
switch(event_type) {
case (int)Event::IndexHole:
SetOverrun();
end_writing();
get_drive().end_writing();
goto abort;
break;
case (int)Event::DataWritten:
@ -685,7 +684,7 @@ void i8272::posit_event(int event_type) {
WAIT_FOR_EVENT((int)Event::DataWritten | (int)Event::IndexHole);
if(event_type != (int)Event::IndexHole) goto format_track_pad;
end_writing();
get_drive().end_writing();
cylinder_ = header_[0];
head_ = header_[1];

View File

@ -587,7 +587,8 @@ class FDC: public Intel::i8272::i8272 {
FDC() : i8272(bus_handler_, Cycles(8000000), 16, 300) {}
void set_motor_on(bool on) {
Intel::i8272::i8272::set_motor_on(on);
// TODO: should set all motors on, not just the one active drive.
get_drive().set_motor_on(on);
}
};

View File

@ -91,7 +91,7 @@ void Machine::run_for(const Cycles cycles) {
m6502_.run_for(cycles);
bool drive_motor = drive_VIA_port_handler_.get_motor_enabled();
set_motor_on(drive_motor);
get_drive().set_motor_on(drive_motor);
if(drive_motor)
Storage::Disk::Controller::run_for(cycles);
}
@ -105,7 +105,7 @@ void MachineBase::mos6522_did_change_interrupt_status(void *mos6522) {
#pragma mark - Disk drive
void MachineBase::process_input_bit(int value, unsigned int cycles_since_index_hole) {
void MachineBase::process_input_bit(int value) {
shift_register_ = (shift_register_ << 1) | value;
if((shift_register_ & 0x3ff) == 0x3ff) {
drive_VIA_port_handler_.set_sync_detected(true);
@ -130,7 +130,7 @@ void MachineBase::process_index_hole() {}
#pragma mak - Drive VIA delegate
void MachineBase::drive_via_did_step_head(void *driveVIA, int direction) {
step(direction);
get_drive().step(direction);
}
void MachineBase::drive_via_did_set_data_density(void *driveVIA, int density) {

View File

@ -147,7 +147,7 @@ class MachineBase:
MOS::MOS6522::MOS6522<SerialPortVIA> serial_port_VIA_;
int shift_register_, bit_window_offset_;
virtual void process_input_bit(int value, unsigned int cycles_since_index_hole);
virtual void process_input_bit(int value);
virtual void process_index_hole();
};

View File

@ -42,7 +42,6 @@ void Plus3::set_control_register(uint8_t control, uint8_t changes) {
}
}
if(changes & 0x04) {
invalidate_track();
if(drives_[0]) drives_[0]->set_head((control & 0x04) ? 1 : 0);
if(drives_[1]) drives_[1]->set_head((control & 0x04) ? 1 : 0);
}

View File

@ -95,7 +95,7 @@ uint8_t Microdisc::get_data_request_register() {
}
void Microdisc::set_head_load_request(bool head_load) {
set_motor_on(head_load);
get_drive().set_motor_on(head_load);
if(head_load) {
head_load_request_counter_ = 0;
} else {

View File

@ -24,7 +24,7 @@ class CommodoreGCRParser: public Storage::Disk::Controller {
CommodoreGCRParser() : Storage::Disk::Controller(4000000, 1, 300), shift_register_(0), track_(1) {
drive.reset(new Storage::Disk::Drive(4000000, 300));
set_drive(drive);
set_motor_on(true);
get_drive().set_motor_on(true);
}
struct Sector {
@ -47,7 +47,7 @@ class CommodoreGCRParser: public Storage::Disk::Controller {
int direction = difference < 0 ? -1 : 1;
difference *= 2 * direction;
for(int c = 0; c < difference; c++) step(direction);
for(int c = 0; c < difference; c++) get_drive().step(direction);
unsigned int zone = 3;
if(track >= 18) zone = 2;
@ -66,7 +66,7 @@ class CommodoreGCRParser: public Storage::Disk::Controller {
uint8_t track_;
std::shared_ptr<Sector> sector_cache_[65536];
void process_input_bit(int value, unsigned int cycles_since_index_hole) {
void process_input_bit(int value) {
shift_register_ = ((shift_register_ << 1) | (unsigned int)value) & 0x3ff;
bit_count_++;
}

View File

@ -7,43 +7,19 @@
//
#include "DiskController.hpp"
#include "UnformattedTrack.hpp"
#include "../../NumberTheory/Factors.hpp"
#include <cassert>
using namespace Storage::Disk;
Controller::Controller(Cycles clock_rate, int clock_rate_multiplier, int revolutions_per_minute) :
clock_rate_(clock_rate.as_int() * clock_rate_multiplier),
clock_rate_multiplier_(clock_rate_multiplier),
rotational_multiplier_(60, revolutions_per_minute),
cycles_since_index_hole_(0),
motor_is_on_(false),
is_reading_(true),
TimedEventLoop((unsigned int)(clock_rate.as_int() * clock_rate_multiplier)) {
empty_drive_(new Drive((unsigned int)clock_rate.as_int(), 1)) {
// seed this class with a PLL, any PLL, so that it's safe to assume non-nullptr later
Time one(1);
set_expected_bit_length(one);
}
void Controller::setup_track() {
track_ = drive_->get_track();
if(!track_) {
track_.reset(new UnformattedTrack);
}
Time offset;
Time track_time_now = get_time_into_track();
assert(track_time_now >= Time(0) && current_event_.length <= Time(1));
Time time_found = track_->seek_to(track_time_now);
assert(time_found >= Time(0) && time_found <= track_time_now);
offset = track_time_now - time_found;
get_next_event(offset);
set_drive(empty_drive_);
}
void Controller::set_component_is_sleeping(void *component, bool is_sleeping) {
@ -51,125 +27,32 @@ void Controller::set_component_is_sleeping(void *component, bool is_sleeping) {
}
bool Controller::is_sleeping() {
return !(drive_ && drive_->has_disk() && motor_is_on_);
return !drive_ || drive_->is_sleeping();
}
void Controller::run_for(const Cycles cycles) {
Time zero(0);
if(drive_) drive_->run_for(cycles);
}
if(drive_ && drive_->has_disk() && motor_is_on_) {
if(!track_) setup_track();
Drive &Controller::get_drive() {
return *drive_.get();
}
int number_of_cycles = clock_rate_multiplier_ * cycles.as_int();
while(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) {
int write_cycles_target = (int)cycles_until_bits_written_.get_unsigned_int();
if(cycles_until_bits_written_.length % cycles_until_bits_written_.clock_rate) write_cycles_target++;
cycles_to_run_for = std::min(cycles_to_run_for, write_cycles_target);
}
#pragma mark - Drive::EventDelegate
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));
} else {
if(cycles_until_bits_written_ > zero) {
Storage::Time cycles_to_run_for_time(cycles_to_run_for);
if(cycles_until_bits_written_ <= cycles_to_run_for_time) {
process_write_completed();
if(cycles_until_bits_written_ <= cycles_to_run_for_time)
cycles_until_bits_written_.set_zero();
else
cycles_until_bits_written_ -= cycles_to_run_for_time;
} else {
cycles_until_bits_written_ -= cycles_to_run_for_time;
}
}
}
TimedEventLoop::run_for(Cycles(cycles_to_run_for));
}
void Controller::process_event(const Track::Event &event) {
switch(event.type) {
case Track::Event::FluxTransition: pll_->add_pulse(); break;
case Track::Event::IndexHole: process_index_hole(); break;
}
}
#pragma mark - Track timed event loop
void Controller::get_next_event(const Time &duration_already_passed) {
if(track_) {
current_event_ = track_->get_next_event();
} else {
current_event_.length.length = 1;
current_event_.length.clock_rate = 1;
current_event_.type = Track::Event::IndexHole;
}
// divide interval, which is in terms of a single rotation of the disk, by rotation speed to
// convert it into revolutions per second; this is achieved by multiplying by rotational_multiplier_
assert(current_event_.length <= Time(1) && current_event_.length >= Time(0));
Time interval = (current_event_.length - duration_already_passed) * rotational_multiplier_;
set_next_event_time_interval(interval);
void Controller::advance(const Cycles cycles) {
pll_->run_for(cycles);
}
void Controller::process_next_event()
{
switch(current_event_.type) {
case Track::Event::FluxTransition:
if(is_reading_) pll_->add_pulse();
break;
case Track::Event::IndexHole:
// printf("%p %d [/%d = %d]\n", this, cycles_since_index_hole_, clock_rate_multiplier_, cycles_since_index_hole_ / clock_rate_multiplier_);
cycles_since_index_hole_ = 0;
process_index_hole();
break;
}
get_next_event(Time(0));
}
Storage::Time Controller::get_time_into_track() {
// this is proportion of a second
Time result(cycles_since_index_hole_, 8000000 * clock_rate_multiplier_);
result /= rotational_multiplier_;
result.simplify();
return result;
}
#pragma mark - Writing
void Controller::begin_writing(bool clamp_to_index_hole) {
is_reading_ = false;
clamp_writing_to_index_hole_ = clamp_to_index_hole;
write_segment_.length_of_a_bit = bit_length_ / rotational_multiplier_;
write_segment_.data.clear();
write_segment_.number_of_bits = 0;
write_start_time_ = get_time_into_track();
}
void Controller::write_bit(bool value) {
bool needs_new_byte = !(write_segment_.number_of_bits&7);
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() {
is_reading_ = true;
if(!patched_track_) {
// Avoid creating a new patched track if this one is already patched
patched_track_ = std::dynamic_pointer_cast<PCMPatchedTrack>(track_);
if(!patched_track_) {
patched_track_.reset(new PCMPatchedTrack(track_));
}
}
patched_track_->add_segment(write_start_time_, write_segment_, clamp_writing_to_index_hole_);
cycles_since_index_hole_ %= 8000000 * clock_rate_multiplier_;
invalidate_track(); // TEMPORARY: to force a seek
void Controller::process_write_completed() {
// Provided for subclasses to override.
}
#pragma mark - PLL control and delegate
@ -178,66 +61,43 @@ void Controller::set_expected_bit_length(Time bit_length) {
bit_length_ = bit_length;
bit_length_.simplify();
cycles_per_bit_ = Storage::Time(clock_rate_) * bit_length;
cycles_per_bit_.simplify();
Time cycles_per_bit = Storage::Time(clock_rate_) * bit_length;
cycles_per_bit.simplify();
// 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)cycles_per_bit_.get_unsigned_int();
int clocks_per_bit = (int)cycles_per_bit.get_unsigned_int();
pll_.reset(new DigitalPhaseLockedLoop(clocks_per_bit, 3));
pll_->set_delegate(this);
}
void Controller::digital_phase_locked_loop_output_bit(int value) {
process_input_bit(value, (unsigned int)cycles_since_index_hole_);
}
#pragma mark - Drive actions
bool Controller::get_is_track_zero() {
if(!drive_) return false;
return drive_->get_is_track_zero();
}
bool Controller::get_drive_is_ready() {
if(!drive_) return false;
return drive_->has_disk();
}
bool Controller::get_drive_is_read_only() {
if(!drive_) return false;
return drive_->get_is_read_only();
}
void Controller::step(int direction) {
invalidate_track();
if(drive_) drive_->step(direction);
}
void Controller::set_motor_on(bool motor_on) {
motor_is_on_ = motor_on;
update_sleep_observer();
}
bool Controller::get_motor_on() {
return motor_is_on_;
process_input_bit(value);
}
void Controller::set_drive(std::shared_ptr<Drive> drive) {
if(drive_ != drive) {
invalidate_track();
bool was_sleeping = is_sleeping();
// invalidate_track();
if(drive_) {
drive_->set_event_delegate(nullptr);
drive_->set_sleep_observer(nullptr);
}
drive_ = drive;
drive->set_sleep_observer(this);
update_sleep_observer();
if(drive_) {
drive_->set_event_delegate(this);
drive_->set_sleep_observer(this);
} else {
drive_ = empty_drive_;
}
if(is_sleeping() != was_sleeping) {
update_sleep_observer();
}
}
}
void Controller::invalidate_track() {
track_ = nullptr;
if(patched_track_) {
drive_->set_track(patched_track_);
patched_track_ = nullptr;
}
void Controller::begin_writing(bool clamp_to_index_hole) {
get_drive().begin_writing(bit_length_, clamp_to_index_hole);
}
void Controller::process_write_completed() {}

View File

@ -13,7 +13,6 @@
#include "DigitalPhaseLockedLoop.hpp"
#include "PCMSegment.hpp"
#include "PCMPatchedTrack.hpp"
#include "../TimedEventLoop.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
#include "../../ClockReceiver/Sleeper.hpp"
@ -30,7 +29,7 @@ namespace Disk {
TODO: communication of head size and permissible stepping extents, appropriate simulation of gain.
*/
class Controller: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop, public Sleeper, public Sleeper::SleepObserver {
class Controller: public DigitalPhaseLockedLoop::Delegate, public Drive::EventDelegate, public Sleeper, public Sleeper::SleepObserver {
protected:
/*!
Constructs a @c DiskDrive that will be run at @c clock_rate and runs its PLL at @c clock_rate*clock_rate_multiplier,
@ -49,51 +48,14 @@ class Controller: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop
void run_for(const Cycles cycles);
/*!
Sets the current drive.
Sets the current drive. This drive is the one the PLL listens to.
*/
void set_drive(std::shared_ptr<Drive> drive);
/*!
Announces that the track the drive sees is about to change for a reason unknownt to the controller.
Should be implemented by subclasses; communicates each bit that the PLL recognises.
*/
void invalidate_track();
/*!
Enables or disables the disk motor.
*/
void set_motor_on(bool motor_on);
/*!
@returns @c true if the motor is on; @c false otherwise.
*/
bool get_motor_on();
/*!
Begins write mode, initiating a PCM sampled region of data. Bits should be written via
@c write_bit. They will be written with the length set via @c set_expected_bit_length.
It is acceptable to supply a backlog of bits. Flux transition events will not be reported
while writing.
@param clamp_to_index_hole If @c true then writing will automatically be truncated by
the index hole. Writing will continue over the index hole otherwise.
*/
void begin_writing(bool clamp_to_index_hole);
/*!
Writes the bit @c value as the next in the PCM stream initiated by @c begin_writing.
*/
void write_bit(bool value);
/*!
Ends write mode, switching back to read mode. The drive will stop overwriting events.
*/
void end_writing();
/*!
Should be implemented by subclasses; communicates each bit that the PLL recognises, also specifying
the amount of time since the index hole was last seen.
*/
virtual void process_input_bit(int value, unsigned int cycles_since_index_hole) = 0;
virtual void process_input_bit(int value) = 0;
/*!
Should be implemented by subclasses; communicates that the index hole has been reached.
@ -106,16 +68,19 @@ class Controller: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop
*/
virtual void process_write_completed();
// for TimedEventLoop
virtual void process_next_event();
/*!
Puts the drive returned by get_drive() into write mode, supplying the current bit length.
// to satisfy DigitalPhaseLockedLoop::Delegate
void digital_phase_locked_loop_output_bit(int value);
@param clamp_to_index_hole If @c true then writing will automatically be truncated by
the index hole. Writing will continue over the index hole otherwise.
*/
void begin_writing(bool clamp_to_index_hole);
bool get_is_track_zero();
void step(int direction);
virtual bool get_drive_is_ready();
bool get_drive_is_read_only();
/*!
Returns the connected drive or, if none is connected, an invented one. No guarantees are
made about the lifetime or the exclusivity of the invented drive.
*/
Drive &get_drive();
bool is_sleeping();
@ -127,26 +92,17 @@ class Controller: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop
std::shared_ptr<DigitalPhaseLockedLoop> pll_;
std::shared_ptr<Drive> drive_;
std::shared_ptr<Track> track_;
int cycles_since_index_hole_;
inline void get_next_event(const Time &duration_already_passed);
Track::Event current_event_;
bool motor_is_on_;
bool is_reading_;
bool clamp_writing_to_index_hole_;
std::shared_ptr<PCMPatchedTrack> patched_track_;
PCMSegment write_segment_;
Time write_start_time_;
Time cycles_until_bits_written_;
Time cycles_per_bit_;
void setup_track();
Time get_time_into_track();
std::shared_ptr<Drive> empty_drive_;
void set_component_is_sleeping(void *component, bool is_sleeping);
// for Drive::EventDelegate
void process_event(const Track::Event &event);
void advance(const Cycles cycles);
// to satisfy DigitalPhaseLockedLoop::Delegate
void digital_phase_locked_loop_output_bit(int value);
};
}

View File

@ -83,6 +83,14 @@ void Drive::set_motor_on(bool motor_is_on) {
update_sleep_observer();
}
bool Drive::get_motor_on() {
return motor_is_on_;
}
void Drive::set_event_delegate(Storage::Disk::Drive::EventDelegate *delegate) {
event_delegate_ = delegate;
}
void Drive::run_for(const Cycles cycles) {
Time zero(0);
@ -178,6 +186,10 @@ void Drive::setup_track() {
void Drive::invalidate_track() {
track_ = nullptr;
if(patched_track_) {
set_track(patched_track_);
patched_track_ = nullptr;
}
}
#pragma mark - Writing
@ -186,6 +198,9 @@ void Drive::begin_writing(Time bit_length, bool clamp_to_index_hole) {
is_reading_ = false;
clamp_writing_to_index_hole_ = clamp_to_index_hole;
cycles_per_bit_ = Storage::Time(get_input_clock_rate()) * bit_length;
cycles_per_bit_.simplify();
write_segment_.length_of_a_bit = bit_length / rotational_multiplier_;
write_segment_.data.clear();
write_segment_.number_of_bits = 0;

View File

@ -109,10 +109,10 @@ class Drive: public Sleeper, public TimedEventLoop {
If the drive is in write mode, announces that all queued bits have now been written.
If the controller provides further bits now then there will be no gap in written data.
*/
virtual void process_write_completed() {}
virtual void process_write_completed() = 0;
/// Informs the delegate of the passing of @c cycles.
virtual void advance(const Cycles cycles) {}
virtual void advance(const Cycles cycles) = 0;
};
/// Sets the current event delegate.

View File

@ -246,7 +246,7 @@ Parser::Parser(bool is_mfm) :
drive_.reset(new Storage::Disk::Drive(4000000, 300));
set_drive(drive_);
set_motor_on(true);
drive_->set_motor_on(true);
}
Parser::Parser(bool is_mfm, const std::shared_ptr<Storage::Disk::Disk> &disk) :
@ -267,7 +267,7 @@ void Parser::seek_to_track(uint8_t track) {
int direction = difference < 0 ? -1 : 1;
difference *= direction;
for(int c = 0; c < difference; c++) step(direction);
for(int c = 0; c < difference; c++) drive_->step(direction);
}
}
@ -275,7 +275,6 @@ std::shared_ptr<Sector> Parser::get_sector(uint8_t head, uint8_t track, uint8_t
// Switch head and track if necessary.
if(head_ != head) {
drive_->set_head(head);
invalidate_track();
}
seek_to_track(track);
int track_index = get_index(head, track, 0);
@ -315,7 +314,7 @@ std::vector<uint8_t> Parser::get_track(uint8_t track) {
return get_track();
}
void Parser::process_input_bit(int value, unsigned int cycles_since_index_hole) {
void Parser::process_input_bit(int value) {
shift_register_ = ((shift_register_ << 1) | (unsigned int)value) & 0xffff;
bit_count_++;
}

View File

@ -129,7 +129,7 @@ class Parser: public Storage::Disk::Controller {
bool is_mfm_;
void seek_to_track(uint8_t track);
void process_input_bit(int value, unsigned int cycles_since_index_hole);
void process_input_bit(int value);
void process_index_hole();
uint8_t get_next_byte();

View File

@ -53,7 +53,7 @@ NumberTheory::CRC16 &MFMController::get_crc_generator() {
return crc_generator_;
}
void MFMController::process_input_bit(int value, unsigned int cycles_since_index_hole) {
void MFMController::process_input_bit(int value) {
if(data_mode_ == DataMode::Writing) return;
shift_register_ = (shift_register_ << 1) | value;
@ -156,12 +156,12 @@ void MFMController::process_input_bit(int value, unsigned int cycles_since_index
void MFMController::write_bit(int bit) {
if(is_double_density_) {
Controller::write_bit(!bit && !last_bit_);
Controller::write_bit(!!bit);
get_drive().write_bit(!bit && !last_bit_);
get_drive().write_bit(!!bit);
last_bit_ = bit;
} else {
Controller::write_bit(true);
Controller::write_bit(!!bit);
get_drive().write_bit(true);
get_drive().write_bit(!!bit);
}
}
@ -172,7 +172,7 @@ void MFMController::write_byte(uint8_t byte) {
void MFMController::write_raw_short(uint16_t value) {
for(int c = 0; c < 16; c++) {
Controller::write_bit(!!((value << c)&0x8000));
get_drive().write_bit(!!((value << c)&0x8000));
}
}

View File

@ -146,7 +146,7 @@ class MFMController: public Controller {
private:
// Storage::Disk::Controller
virtual void process_input_bit(int value, unsigned int cycles_since_index_hole);
virtual void process_input_bit(int value);
virtual void process_index_hole();
virtual void process_write_completed();