1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-27 18:55:48 +00:00

Eliminates the optionality of a DPLL receiver.

This commit is contained in:
Thomas Harte 2020-01-12 17:45:02 -05:00
parent 8e3a618619
commit 514141f8c5
5 changed files with 16 additions and 28 deletions

View File

@ -70,9 +70,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableAddressSanitizer = "YES"
enableASanStackUseAfterReturn = "YES"
enableUBSanitizer = "YES"
disableMainThreadChecker = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"

View File

@ -15,9 +15,8 @@ using namespace Storage::Disk;
Controller::Controller(Cycles clock_rate) :
clock_rate_multiplier_(128000000 / clock_rate.as_integral()),
clock_rate_(clock_rate.as_integral() * clock_rate_multiplier_),
pll_(100),
pll_(100, *this),
empty_drive_(new Drive(int(clock_rate.as_integral()), 1, 1)) {
pll_.set_delegate(this);
set_expected_bit_length(Time(1));
set_drive(empty_drive_);
}

View File

@ -21,6 +21,7 @@ namespace Storage {
/*!
Template parameters:
@c bit_handler A class that must implement a method, digital_phase_locked_loop_output_bit(int) for receving bits from the DPLL.
@c length_of_history The number of historic pulses to consider in locking to phase.
*/
template <typename BitHandler, size_t length_of_history = 3> class DigitalPhaseLockedLoop {
@ -30,8 +31,8 @@ template <typename BitHandler, size_t length_of_history = 3> class DigitalPhaseL
@param clocks_per_bit The expected number of cycles between each bit of input.
*/
DigitalPhaseLockedLoop(int clocks_per_bit) :
window_length_(clocks_per_bit), clocks_per_bit_(clocks_per_bit) {}
DigitalPhaseLockedLoop(int clocks_per_bit, BitHandler &handler) :
bit_handler_(handler), window_length_(clocks_per_bit), clocks_per_bit_(clocks_per_bit) {}
/*!
Changes the expected window length.
@ -51,12 +52,10 @@ template <typename BitHandler, size_t length_of_history = 3> class DigitalPhaseL
if(phase_ >= window_length_) {
auto windows_crossed = phase_ / window_length_;
// check whether this triggers any 0s, if anybody cares
if(delegate_) {
if(window_was_filled_) --windows_crossed;
for(int c = 0; c < windows_crossed; c++)
delegate_->digital_phase_locked_loop_output_bit(0);
}
// Check whether this triggers any 0s.
if(window_was_filled_) --windows_crossed;
for(int c = 0; c < windows_crossed; c++)
bit_handler_.digital_phase_locked_loop_output_bit(0);
window_was_filled_ = false;
phase_ %= window_length_;
@ -68,22 +67,15 @@ template <typename BitHandler, size_t length_of_history = 3> class DigitalPhaseL
*/
void add_pulse() {
if(!window_was_filled_) {
if(delegate_) delegate_->digital_phase_locked_loop_output_bit(1);
bit_handler_.digital_phase_locked_loop_output_bit(1);
window_was_filled_ = true;
post_phase_offset(phase_, offset_);
offset_ = 0;
}
}
/*!
A receiver for PCM output data; called upon every recognised bit.
*/
void set_delegate(BitHandler *delegate) {
delegate_ = delegate;
}
private:
BitHandler *delegate_ = nullptr;
BitHandler &bit_handler_;
void post_phase_offset(Cycles::IntType new_phase, Cycles::IntType new_offset) {
// Erase the effect of whatever is currently in this slot.

View File

@ -20,12 +20,13 @@ Storage::Disk::PCMSegment Storage::Disk::track_serialisation(const Track &track,
// its PCMSegment.
struct ResultAccumulator {
PCMSegment result;
bool is_recording = false;
void digital_phase_locked_loop_output_bit(int value) {
result.data.push_back(!!value);
if(is_recording) result.data.push_back(!!value);
}
} result_accumulator;
result_accumulator.result.length_of_a_bit = length_of_a_bit;
DigitalPhaseLockedLoop<ResultAccumulator> pll(100);
DigitalPhaseLockedLoop<ResultAccumulator> pll(100, result_accumulator);
// Obtain a length multiplier which is 100 times the reciprocal
// of the expected bit length. So a perfect bit length from
@ -55,7 +56,7 @@ Storage::Disk::PCMSegment Storage::Disk::track_serialisation(const Track &track,
if(!history_size) {
track_copy->seek_to(Time(0));
time_error.set_zero();
pll.set_delegate(&result_accumulator);
result_accumulator.is_recording = true;
}
}
}

View File

@ -66,13 +66,11 @@ void Parser::process_pulse(const Storage::Tape::Tape::Pulse &pulse) {
Shifter::Shifter() :
pll_(PLLClockRate / 4800),
pll_(PLLClockRate / 4800, *this),
was_high_(false),
input_pattern_(0),
input_bit_counter_(0),
delegate_(nullptr) {
pll_.set_delegate(this);
}
delegate_(nullptr) {}
void Shifter::process_pulse(const Storage::Tape::Tape::Pulse &pulse) {
pll_.run_for(Cycles(static_cast<int>(static_cast<float>(PLLClockRate) * pulse.length.get<float>())));