1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Switches disk seeking logic fully to floating point.

This commit is contained in:
Thomas Harte 2020-07-17 22:08:58 -04:00
parent cbb0594e6b
commit 4ee29b3266
8 changed files with 26 additions and 22 deletions

View File

@ -80,6 +80,10 @@ bool Drive::get_is_track_zero() const {
} }
void Drive::step(HeadPosition offset) { void Drive::step(HeadPosition offset) {
if(offset == HeadPosition(0)) {
return;
}
if(ready_type_ == ReadyType::IBMRDY) { if(ready_type_ == ReadyType::IBMRDY) {
is_ready_ = true; is_ready_ = true;
} }
@ -94,7 +98,7 @@ void Drive::step(HeadPosition offset) {
} }
// If the head moved, flush the old track. // If the head moved, flush the old track.
if(head_position_ != old_head_position) { if(disk_ && disk_->tracks_differ(Track::Address(head_, head_position_), Track::Address(head_, old_head_position))) {
track_ = nullptr; track_ = nullptr;
} }
@ -355,8 +359,8 @@ void Drive::setup_track() {
} }
float offset = 0.0f; float offset = 0.0f;
const auto track_time_now = get_time_into_track(); const float track_time_now = get_time_into_track();
const auto time_found = track_->seek_to(Time(track_time_now)).get<float>(); const float time_found = track_->seek_to(track_time_now);
// `time_found` can be greater than `track_time_now` if limited precision caused rounding. // `time_found` can be greater than `track_time_now` if limited precision caused rounding.
if(time_found <= track_time_now) { if(time_found <= track_time_now) {

View File

@ -109,9 +109,9 @@ Storage::Time PCMSegmentEventSource::get_length() {
return segment_->length_of_a_bit * unsigned(segment_->data.size()); return segment_->length_of_a_bit * unsigned(segment_->data.size());
} }
Storage::Time PCMSegmentEventSource::seek_to(const Time &time_from_start) { float PCMSegmentEventSource::seek_to(float time_from_start) {
// test for requested time being beyond the end // test for requested time being beyond the end
const Time length = get_length(); const float length = get_length().get<float>();
if(time_from_start >= length) { if(time_from_start >= length) {
next_event_.type = Track::Event::IndexHole; next_event_.type = Track::Event::IndexHole;
bit_pointer_ = segment_->data.size()+1; bit_pointer_ = segment_->data.size()+1;
@ -122,21 +122,21 @@ Storage::Time PCMSegmentEventSource::seek_to(const Time &time_from_start) {
next_event_.type = Track::Event::FluxTransition; next_event_.type = Track::Event::FluxTransition;
// test for requested time being before the first bit // test for requested time being before the first bit
Time half_bit_length = segment_->length_of_a_bit; const float bit_length = segment_->length_of_a_bit.get<float>();
half_bit_length.length >>= 1; const float half_bit_length = bit_length / 2.0f;
if(time_from_start < half_bit_length) { if(time_from_start < half_bit_length) {
bit_pointer_ = 0; bit_pointer_ = 0;
return Storage::Time(0); return 0.0f;
} }
// adjust for time to get to bit zero and determine number of bits in; // adjust for time to get to bit zero and determine number of bits in;
// bit_pointer_ always records _the next bit_ that might trigger an event, // bit_pointer_ always records _the next bit_ that might trigger an event,
// so should be one beyond the one reached by a seek. // so should be one beyond the one reached by a seek.
const Time relative_time = time_from_start - half_bit_length; const float relative_time = time_from_start + half_bit_length; // the period [0, 0.5) should map to window 0; [0.5, 1.5) should map to window 1; etc.
bit_pointer_ = 1 + (relative_time / segment_->length_of_a_bit).get<unsigned int>(); bit_pointer_ = 1 + size_t(relative_time / bit_length);
// map up to the correct amount of time // map up to the correct amount of time
return half_bit_length + segment_->length_of_a_bit * unsigned(bit_pointer_ - 1); return half_bit_length + segment_->length_of_a_bit.get<float>() * float(bit_pointer_ - 1);
} }
const PCMSegment &PCMSegmentEventSource::segment() const { const PCMSegment &PCMSegmentEventSource::segment() const {

View File

@ -183,7 +183,7 @@ class PCMSegmentEventSource {
@returns the time the source is now at. @returns the time the source is now at.
*/ */
Time seek_to(const Time &time_from_start); float seek_to(float time_from_start);
/*! /*!
@returns the total length of the stream of data that the source will provide. @returns the total length of the stream of data that the source will provide.

View File

@ -121,17 +121,17 @@ Track::Event PCMTrack::get_next_event() {
return event; return event;
} }
Storage::Time PCMTrack::seek_to(const Time &time_since_index_hole) { float PCMTrack::seek_to(float time_since_index_hole) {
// initial condition: no time yet accumulated, the whole thing requested yet to navigate // initial condition: no time yet accumulated, the whole thing requested yet to navigate
Storage::Time accumulated_time; float accumulated_time = 0.0f;
Storage::Time time_left_to_seek = time_since_index_hole; float time_left_to_seek = time_since_index_hole;
// search from the first segment // search from the first segment
segment_pointer_ = 0; segment_pointer_ = 0;
do { do {
// if this segment extends beyond the amount of time left to seek, trust it to complete // if this segment extends beyond the amount of time left to seek, trust it to complete
// the seek // the seek
Storage::Time segment_time = segment_event_sources_[segment_pointer_].get_length(); const float segment_time = segment_event_sources_[segment_pointer_].get_length().get<float>();
if(segment_time > time_left_to_seek) { if(segment_time > time_left_to_seek) {
return accumulated_time + segment_event_sources_[segment_pointer_].seek_to(time_left_to_seek); return accumulated_time + segment_event_sources_[segment_pointer_].seek_to(time_left_to_seek);
} }

View File

@ -50,7 +50,7 @@ class PCMTrack: public Track {
// as per @c Track // as per @c Track
Event get_next_event() final; Event get_next_event() final;
Time seek_to(const Time &time_since_index_hole) final; float seek_to(float time_since_index_hole) final;
Track *clone() const final; Track *clone() const final;
// Obtains a copy of this track, flattened to a single PCMSegment, which // Obtains a copy of this track, flattened to a single PCMSegment, which

View File

@ -35,7 +35,7 @@ Storage::Disk::PCMSegment Storage::Disk::track_serialisation(const Track &track,
length_multiplier.simplify(); length_multiplier.simplify();
// start at the index hole // start at the index hole
track_copy->seek_to(Time(0)); track_copy->seek_to(0.0f);
// grab events until the next index hole // grab events until the next index hole
Time time_error = Time(0); Time time_error = Time(0);
@ -54,7 +54,7 @@ Storage::Disk::PCMSegment Storage::Disk::track_serialisation(const Track &track,
if(history_size) { if(history_size) {
history_size--; history_size--;
if(!history_size) { if(!history_size) {
track_copy->seek_to(Time(0)); track_copy->seek_to(0.0f);
time_error.set_zero(); time_error.set_zero();
result_accumulator.is_recording = true; result_accumulator.is_recording = true;
} }

View File

@ -17,8 +17,8 @@ Track::Event UnformattedTrack::get_next_event() {
return event; return event;
} }
Storage::Time UnformattedTrack::seek_to(const Time &) { float UnformattedTrack::seek_to(float) {
return Time(0); return 0.0f;
} }
Track *UnformattedTrack::clone() const { Track *UnformattedTrack::clone() const {

View File

@ -20,7 +20,7 @@ namespace Disk {
class UnformattedTrack: public Track { class UnformattedTrack: public Track {
public: public:
Event get_next_event() final; Event get_next_event() final;
Time seek_to(const Time &time_since_index_hole) final; float seek_to(float time_since_index_hole) final;
Track *clone() const final; Track *clone() const final;
}; };