diff --git a/Storage/Disk/DiskDrive.cpp b/Storage/Disk/DiskDrive.cpp index d8d8efdfa..acfb70755 100644 --- a/Storage/Disk/DiskDrive.cpp +++ b/Storage/Disk/DiskDrive.cpp @@ -33,7 +33,7 @@ void DiskDrive::set_expected_bit_length(Time bit_length) void DiskDrive::set_disk(std::shared_ptr disk) { _disk = disk; - set_track(); + set_track(Time()); } bool DiskDrive::has_disk() @@ -49,31 +49,30 @@ bool DiskDrive::get_is_track_zero() void DiskDrive::step(int direction) { _head_position = std::max(_head_position + direction, 0); - - // TODO: add fractional part to _time_into_track _time_into_track += get_time_into_next_event(); - // TODO: probably a better implementation of the empty track? -// Time offset; -// if(_track) -// { -// Time time_found = _track->seek_to(_time_into_track); -// offset = _time_into_track - time_found; -// } -// else -// { -// offset = _time_into_track; -// } - - // TODO: apply offset - set_track(); + set_track(_time_into_track); } -void DiskDrive::set_track() +void DiskDrive::set_track(Time initial_offset) { - // TODO: accept and apply offset _track = _disk->get_track_at_position((unsigned int)_head_position); + // TODO: probably a better implementation of the empty track? + Time offset; + if(_track) + { + Time time_found = _track->seek_to(_time_into_track); + offset = _time_into_track - time_found; + _time_into_track = time_found; + } + else + { + offset = _time_into_track; + _time_into_track.set_zero(); + } + reset_timer(); get_next_event(); + reset_timer_to_offset(offset); } void DiskDrive::run_for_cycles(int number_of_cycles) diff --git a/Storage/Disk/DiskDrive.hpp b/Storage/Disk/DiskDrive.hpp index 581b34998..15fea8639 100644 --- a/Storage/Disk/DiskDrive.hpp +++ b/Storage/Disk/DiskDrive.hpp @@ -99,7 +99,7 @@ class DiskDrive: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop std::shared_ptr _track; int _head_position; unsigned int _cycles_since_index_hole; - void set_track(); + void set_track(Time initial_offset); inline void get_next_event(); Track::Event _current_event; diff --git a/Storage/TimedEventLoop.cpp b/Storage/TimedEventLoop.cpp index 2b3019957..4a35527bd 100644 --- a/Storage/TimedEventLoop.cpp +++ b/Storage/TimedEventLoop.cpp @@ -29,6 +29,18 @@ void TimedEventLoop::reset_timer() _stepper.reset(); } +void TimedEventLoop::reset_timer_to_offset(Time offset) +{ + unsigned int common_clock_rate = NumberTheory::least_common_multiple(offset.clock_rate, _event_interval.clock_rate); + _time_into_interval = offset.length * (common_clock_rate / offset.clock_rate); + _event_interval.length *= common_clock_rate / _event_interval.clock_rate; + _event_interval.clock_rate = common_clock_rate; + if(common_clock_rate != _stepper->get_output_rate()) + { + _stepper.reset(new SignalProcessing::Stepper(_event_interval.clock_rate, _input_clock_rate)); + } +} + void TimedEventLoop::jump_to_next_event() { reset_timer(); diff --git a/Storage/TimedEventLoop.hpp b/Storage/TimedEventLoop.hpp index aaf63712b..431464853 100644 --- a/Storage/TimedEventLoop.hpp +++ b/Storage/TimedEventLoop.hpp @@ -66,6 +66,11 @@ namespace Storage { */ void reset_timer(); + /*! + Sets the amount of time into the current event to @c offset. + */ + void reset_timer_to_offset(Time offset); + /*! Causes an immediate call to @c process_next_event and a call to @c reset_timer with the net effect of processing the current event immediately and fast forwarding exactly to the