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:
parent
004d6da9fb
commit
51177e4e1f
@ -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_);*/
|
||||
}
|
||||
|
@ -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_;
|
||||
|
Loading…
Reference in New Issue
Block a user