mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-13 22:32:03 +00:00
Eliminates the optionality of a DPLL receiver.
This commit is contained in:
parent
8e3a618619
commit
514141f8c5
@ -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"
|
||||
|
@ -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_);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>())));
|
||||
|
Loading…
x
Reference in New Issue
Block a user