1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-23 20:29:42 +00:00

Attempted a different implementation of the PLL, that responds to changes only once.

This commit is contained in:
Thomas Harte 2017-07-16 16:49:04 -04:00
parent 004d6da9fb
commit 51177e4e1f
2 changed files with 29 additions and 6 deletions

View File

@ -18,9 +18,12 @@ DigitalPhaseLockedLoop::DigitalPhaseLockedLoop(int clocks_per_bit, int tolerance
phase_(0),
window_length_(clocks_per_bit),
phase_error_pointer_(0),
phase_error_history_(length_of_history, 0) {}
phase_error_history_(length_of_history, 0),
offset_history_(length_of_history, 0),
offset_(0) {}
void DigitalPhaseLockedLoop::run_for_cycles(int number_of_cycles) {
offset_ += number_of_cycles;
phase_ += number_of_cycles;
if(phase_ >= window_length_) {
int windows_crossed = phase_ / window_length_;
@ -41,16 +44,33 @@ void DigitalPhaseLockedLoop::add_pulse() {
if(!window_was_filled_) {
if(delegate_) delegate_->digital_phase_locked_loop_output_bit(1);
window_was_filled_ = true;
post_phase_error(phase_ - (window_length_ >> 1));
post_phase_offset(phase_, offset_);
offset_ = 0;
}
}
void DigitalPhaseLockedLoop::post_phase_error(int error) {
void DigitalPhaseLockedLoop::post_phase_offset(int phase, int offset) {
offset_history_[phase_error_pointer_] = offset;
phase_error_pointer_ = (phase_error_pointer_ + 1) % offset_history_.size();
int total_spacing = 0;
int total_divisor = 0;
for(int offset : offset_history_) {
int multiple = (offset + (clocks_per_bit_ >> 1)) / clocks_per_bit_;
if(!multiple) continue;
total_divisor += multiple;
total_spacing += offset;
}
window_length_ = total_spacing / total_divisor;
window_length_ = std::max(std::min(window_length_, clocks_per_bit_ + tolerance_), clocks_per_bit_ - tolerance_);
int error = phase - (window_length_ >> 1);
// use a simple spring mechanism as a lowpass filter for phase
phase_ -= (error + 1) >> 1;
// use the average of the last few errors to affect frequency
size_t phase_error_history_size = phase_error_history_.size();
/* size_t phase_error_history_size = phase_error_history_.size();
phase_error_history_[phase_error_pointer_] = error;
phase_error_pointer_ = (phase_error_pointer_ + 1)%phase_error_history_size;
@ -61,5 +81,5 @@ void DigitalPhaseLockedLoop::post_phase_error(int error) {
}
int denominator = (int)(phase_error_history_size * 4);
window_length_ += (total_error + (denominator >> 1)) / denominator;
window_length_ = std::max(std::min(window_length_, clocks_per_bit_ + tolerance_), clocks_per_bit_ - tolerance_);
window_length_ = std::max(std::min(window_length_, clocks_per_bit_ + tolerance_), clocks_per_bit_ - tolerance_);*/
}

View File

@ -51,10 +51,13 @@ class DigitalPhaseLockedLoop {
private:
Delegate *delegate_;
void post_phase_error(int error);
void post_phase_offset(int phase, int offset);
std::vector<int> phase_error_history_;
size_t phase_error_pointer_;
std::vector<int> offset_history_;
int offset_;
int phase_;
int window_length_;
bool window_was_filled_;