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

Introduces a track to segment decoder.

This will be needed to make formats like G64 and HFE writeable, but probably also will be usable to speed up static analysis.
This commit is contained in:
Thomas Harte 2017-09-23 22:39:19 -04:00
parent a295b42497
commit f789ee4ff0
2 changed files with 73 additions and 0 deletions

View File

@ -680,6 +680,7 @@
4B8805FA1DCFF807003085B1 /* Oric.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Oric.hpp; path = Parsers/Oric.hpp; sourceTree = "<group>"; };
4B8805FC1DD02552003085B1 /* Tape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Tape.cpp; path = ../../StaticAnalyser/Oric/Tape.cpp; sourceTree = "<group>"; };
4B8805FD1DD02552003085B1 /* Tape.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Tape.hpp; path = ../../StaticAnalyser/Oric/Tape.hpp; sourceTree = "<group>"; };
4B8D287E1F77207100645199 /* TrackSerialiser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TrackSerialiser.hpp; sourceTree = "<group>"; };
4B8E4ECD1DCE483D003716C3 /* KeyboardMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = KeyboardMachine.hpp; sourceTree = "<group>"; };
4B8FE2141DA19D5F0090D3CE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/Atari2600Options.xib"; sourceTree = SOURCE_ROOT; };
4B8FE2161DA19D5F0090D3CE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/MachineDocument.xib"; sourceTree = SOURCE_ROOT; };
@ -1415,6 +1416,7 @@
4B4518771F75E91800926311 /* UnformattedTrack.cpp */,
4B4518781F75E91800926311 /* UnformattedTrack.hpp */,
4B4518881F75ECB100926311 /* Track.hpp */,
4B8D287E1F77207100645199 /* TrackSerialiser.hpp */,
);
path = Track;
sourceTree = "<group>";

View File

@ -0,0 +1,71 @@
//
// TrackSerialiser.hpp
// Clock Signal
//
// Created by Thomas Harte on 23/09/2017.
// Copyright © 2017 Thomas Harte. All rights reserved.
//
#ifndef TrackSerialiser_h
#define TrackSerialiser_h
#include "../DPLL/DigitalPhaseLockedLoop.hpp"
namespace Storage {
namespace Disk {
/*!
Instantiates a PLL with a target bit length of @c length_of_a_bit and provides a complete
serialisation of @c track, starting from the index hole.
This feature is offered for the benefit of various parts of the code that need to make
sense of a track **other than emulation**, as it renders a one-off image of the track,
which can be inaccurate. However there are many occasions where a single rendering is
desireable e.g. file formats that apply that constraint, or static analysis prior to
emulation launch, which works with broad strokes.
@param track The track to serialise.
@param length_of_a_bit The expected length of a single bit, as a proportion of the
track length.
*/
template <typename T> PCMSegment track_serialisation(T &track, Time length_of_a_bit) {
DigitalPhaseLockedLoop pll(100, 16);
struct ResultAccumulator: public DigitalPhaseLockedLoop::Delegate {
PCMSegment result;
void digital_phase_locked_loop_output_bit(int value) {
result.data.resize(1 + (result.number_of_bits >> 3));
if(value) result.data[result.number_of_bits >> 3] |= 0x80 >> (result.number_of_bits & 7);
result.number_of_bits++;
}
} result_accumulator;
pll.set_delegate(&result_accumulator);
result_accumulator.result.number_of_bits = 0;
result_accumulator.result.length_of_a_bit = length_of_a_bit;
Time length_multiplier = Time(100*length_of_a_bit.clock_rate, length_of_a_bit.length);
length_multiplier.simplify();
// start at the index hole
track.seek_to(Time(0));
// grab events until the next index hole
Time time_error = Time(0);
while(true) {
Track::Event next_event = track.get_next_event();
if(next_event.type == Track::Event::IndexHole) break;
Time extended_length = next_event.length * length_multiplier + time_error;
time_error.clock_rate = extended_length.clock_rate;
time_error.length = extended_length.length % extended_length.clock_rate;
pll.run_for(Cycles((int)extended_length.get_unsigned_int()));
pll.add_pulse();
}
return result_accumulator.result;
}
}
}
#endif /* TrackSerialiser_h */