1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-08-12 09:25:19 +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" buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableAddressSanitizer = "YES"
enableASanStackUseAfterReturn = "YES" enableASanStackUseAfterReturn = "YES"
enableUBSanitizer = "YES"
disableMainThreadChecker = "YES" disableMainThreadChecker = "YES"
launchStyle = "0" launchStyle = "0"
useCustomWorkingDirectory = "NO" useCustomWorkingDirectory = "NO"

View File

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

View File

@@ -21,6 +21,7 @@ namespace Storage {
/*! /*!
Template parameters: 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. @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 { 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. @param clocks_per_bit The expected number of cycles between each bit of input.
*/ */
DigitalPhaseLockedLoop(int clocks_per_bit) : DigitalPhaseLockedLoop(int clocks_per_bit, BitHandler &handler) :
window_length_(clocks_per_bit), clocks_per_bit_(clocks_per_bit) {} bit_handler_(handler), window_length_(clocks_per_bit), clocks_per_bit_(clocks_per_bit) {}
/*! /*!
Changes the expected window length. Changes the expected window length.
@@ -51,12 +52,10 @@ template <typename BitHandler, size_t length_of_history = 3> class DigitalPhaseL
if(phase_ >= window_length_) { if(phase_ >= window_length_) {
auto windows_crossed = phase_ / window_length_; auto windows_crossed = phase_ / window_length_;
// check whether this triggers any 0s, if anybody cares // Check whether this triggers any 0s.
if(delegate_) { if(window_was_filled_) --windows_crossed;
if(window_was_filled_) --windows_crossed; for(int c = 0; c < windows_crossed; c++)
for(int c = 0; c < windows_crossed; c++) bit_handler_.digital_phase_locked_loop_output_bit(0);
delegate_->digital_phase_locked_loop_output_bit(0);
}
window_was_filled_ = false; window_was_filled_ = false;
phase_ %= window_length_; phase_ %= window_length_;
@@ -68,22 +67,15 @@ template <typename BitHandler, size_t length_of_history = 3> class DigitalPhaseL
*/ */
void add_pulse() { void add_pulse() {
if(!window_was_filled_) { 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; window_was_filled_ = true;
post_phase_offset(phase_, offset_); post_phase_offset(phase_, offset_);
offset_ = 0; offset_ = 0;
} }
} }
/*!
A receiver for PCM output data; called upon every recognised bit.
*/
void set_delegate(BitHandler *delegate) {
delegate_ = delegate;
}
private: private:
BitHandler *delegate_ = nullptr; BitHandler &bit_handler_;
void post_phase_offset(Cycles::IntType new_phase, Cycles::IntType new_offset) { void post_phase_offset(Cycles::IntType new_phase, Cycles::IntType new_offset) {
// Erase the effect of whatever is currently in this slot. // 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. // its PCMSegment.
struct ResultAccumulator { struct ResultAccumulator {
PCMSegment result; PCMSegment result;
bool is_recording = false;
void digital_phase_locked_loop_output_bit(int value) { 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_accumulator.result.length_of_a_bit = length_of_a_bit; 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 // Obtain a length multiplier which is 100 times the reciprocal
// of the expected bit length. So a perfect bit length from // 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) { if(!history_size) {
track_copy->seek_to(Time(0)); track_copy->seek_to(Time(0));
time_error.set_zero(); 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() : Shifter::Shifter() :
pll_(PLLClockRate / 4800), pll_(PLLClockRate / 4800, *this),
was_high_(false), was_high_(false),
input_pattern_(0), input_pattern_(0),
input_bit_counter_(0), input_bit_counter_(0),
delegate_(nullptr) { delegate_(nullptr) {}
pll_.set_delegate(this);
}
void Shifter::process_pulse(const Storage::Tape::Tape::Pulse &pulse) { 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>()))); pll_.run_for(Cycles(static_cast<int>(static_cast<float>(PLLClockRate) * pulse.length.get<float>())));