diff --git a/Storage/Disk/DiskDrive.cpp b/Storage/Disk/DiskDrive.cpp index acfb70755..12c2d5c55 100644 --- a/Storage/Disk/DiskDrive.cpp +++ b/Storage/Disk/DiskDrive.cpp @@ -17,7 +17,11 @@ DiskDrive::DiskDrive(unsigned int clock_rate, unsigned int clock_rate_multiplier _head_position(0), TimedEventLoop(clock_rate * clock_rate_multiplier) -{} +{ + _rotational_multiplier.length = 60; + _rotational_multiplier.clock_rate = revolutions_per_minute; + _rotational_multiplier.simplify(); +} void DiskDrive::set_expected_bit_length(Time bit_length) { @@ -49,7 +53,9 @@ bool DiskDrive::get_is_track_zero() void DiskDrive::step(int direction) { _head_position = std::max(_head_position + direction, 0); - _time_into_track += get_time_into_next_event(); + Time extra_time = get_time_into_next_event() / _rotational_multiplier; + extra_time.simplify(); + _time_into_track += extra_time; set_track(_time_into_track); } @@ -58,10 +64,10 @@ void DiskDrive::set_track(Time initial_offset) _track = _disk->get_track_at_position((unsigned int)_head_position); // TODO: probably a better implementation of the empty track? Time offset; - if(_track) + if(_track && _time_into_track.length > 0) { - Time time_found = _track->seek_to(_time_into_track); - offset = _time_into_track - time_found; + Time time_found = _track->seek_to(_time_into_track).simplify(); + offset = (_time_into_track - time_found).simplify(); _time_into_track = time_found; } else @@ -72,7 +78,7 @@ void DiskDrive::set_track(Time initial_offset) reset_timer(); get_next_event(); - reset_timer_to_offset(offset); + reset_timer_to_offset(offset * _rotational_multiplier); } void DiskDrive::run_for_cycles(int number_of_cycles) @@ -104,11 +110,7 @@ void DiskDrive::get_next_event() // divide interval, which is in terms of a rotation of the disk, by rotation speed, and // convert it into revolutions per second - Time event_interval = _current_event.length; - event_interval.length *= 60; - event_interval.clock_rate *= _revolutions_per_minute; - event_interval.simplify(); - set_next_event_time_interval(event_interval); + set_next_event_time_interval(_current_event.length * _rotational_multiplier); } void DiskDrive::process_next_event() diff --git a/Storage/Disk/DiskDrive.hpp b/Storage/Disk/DiskDrive.hpp index 15fea8639..ee7674d0b 100644 --- a/Storage/Disk/DiskDrive.hpp +++ b/Storage/Disk/DiskDrive.hpp @@ -93,6 +93,7 @@ class DiskDrive: public DigitalPhaseLockedLoop::Delegate, public TimedEventLoop unsigned int _clock_rate; unsigned int _clock_rate_multiplier; unsigned int _revolutions_per_minute; + Time _rotational_multiplier; std::shared_ptr _pll; std::shared_ptr _disk; diff --git a/Storage/Disk/PCMTrack.cpp b/Storage/Disk/PCMTrack.cpp index 81cdb803c..2a8d53f56 100644 --- a/Storage/Disk/PCMTrack.cpp +++ b/Storage/Disk/PCMTrack.cpp @@ -86,7 +86,7 @@ Time PCMTrack::seek_to(Time time_since_index_hole) unsigned int time_found = time_remaining - (time_remaining % bit_length); // resolve that into the stateful bit count - _bit_pointer = time_remaining / bit_length; + _bit_pointer = 1 + (time_remaining / bit_length); // update and return the time sought to time_so_far.length += time_found; diff --git a/Storage/Storage.hpp b/Storage/Storage.hpp index 439ed67a4..c5aa45f8d 100644 --- a/Storage/Storage.hpp +++ b/Storage/Storage.hpp @@ -25,11 +25,12 @@ struct Time { Reduces this @c Time to its simplest form — eliminates all common factors from @c length and @c clock_rate. */ - inline void simplify() + inline Time &simplify() { unsigned int common_divisor = NumberTheory::greatest_common_divisor(length, clock_rate); length /= common_divisor; clock_rate /= common_divisor; + return *this; } /*! @@ -40,12 +41,12 @@ struct Time { return (float)length / (float)clock_rate; } - inline bool operator<(Time other) + inline bool operator < (Time other) { return other.clock_rate * length < clock_rate * other.length; } - inline Time operator+(Time other) + inline Time operator + (Time other) { Time result; result.clock_rate = NumberTheory::least_common_multiple(clock_rate, other.clock_rate); @@ -53,7 +54,7 @@ struct Time { return result; } - inline Time &operator +=(Time other) + inline Time &operator += (Time other) { unsigned int combined_clock_rate = NumberTheory::least_common_multiple(clock_rate, other.clock_rate); length = length * (combined_clock_rate / clock_rate) + other.length * (combined_clock_rate / other.clock_rate); @@ -61,7 +62,7 @@ struct Time { return *this; } - inline Time operator-(Time other) + inline Time operator - (Time other) { Time result; result.clock_rate = NumberTheory::least_common_multiple(clock_rate, other.clock_rate); @@ -69,6 +70,44 @@ struct Time { return result; } + inline Time operator -= (Time other) + { + unsigned int combined_clock_rate = NumberTheory::least_common_multiple(clock_rate, other.clock_rate); + length = length * (combined_clock_rate / clock_rate) - other.length * (combined_clock_rate / other.clock_rate); + clock_rate = combined_clock_rate; + return *this; + } + + inline Time operator * (Time other) + { + Time result; + result.clock_rate = clock_rate * other.clock_rate; + result.length = length * other.length; + return result; + } + + inline Time &operator *= (Time other) + { + length *= other.length; + clock_rate *= other.clock_rate; + return *this; + } + + inline Time operator / (Time other) + { + Time result; + result.clock_rate = clock_rate * other.length; + result.length = length * other.clock_rate; + return result; + } + + inline Time &operator /= (Time other) + { + length *= other.clock_rate; + clock_rate *= other.length; + return *this; + } + inline void set_zero() { length = 0;