Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 045b4a56b266
Choose a base ref
...
head repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a1cb05500e6e
Choose a head ref
  • 1 commit
  • 2 files changed
  • 1 contributor

Commits on Nov 28, 2020

  1. ClockRecoveryFilter: converted to integer math in inner loop rather t…

    …han switching from float to integer and back all the time, now that we have high resolution timebase
    azonenberg committed Nov 28, 2020
    Copy the full SHA
    a1cb055 View commit details
Showing with 21 additions and 25 deletions.
  1. +21 −22 scopeprotocols/ClockRecoveryFilter.cpp
  2. +0 −3 scopeprotocols/ClockRecoveryFilter.h
43 changes: 21 additions & 22 deletions scopeprotocols/ClockRecoveryFilter.cpp
Original file line number Diff line number Diff line change
@@ -49,8 +49,6 @@ ClockRecoveryFilter::ClockRecoveryFilter(const string& color)
m_threshname = "Threshold";
m_parameters[m_threshname] = FilterParameter(FilterParameter::TYPE_FLOAT, Unit(Unit::UNIT_VOLTS));
m_parameters[m_threshname].SetFloatVal(0);

m_nominalPeriod = 0;
}

ClockRecoveryFilter::~ClockRecoveryFilter()
@@ -130,19 +128,16 @@ void ClockRecoveryFilter::Refresh()
auto gate = GetDigitalInputWaveform(1);

//Timestamps of the edges
vector<double> edges;
vector<int64_t> edges;
FindZeroCrossings(din, m_parameters[m_threshname].GetFloatVal(), edges);
if(edges.empty())
{
SetData(NULL, 0);
return;
}

//Convert nominal baud period to fs
//Round nominal period to nearest fs, but use the floating point value for the CDR PLL
float period = FS_PER_SECOND / m_parameters[m_baudname].GetFloatVal();
int64_t fs = round(period);
m_nominalPeriod = fs;
//Get nominal period used for the first cycle of the NCO
int64_t period = round(FS_PER_SECOND / m_parameters[m_baudname].GetFloatVal());

//Create the output waveform and copy our timescales
auto cap = new DigitalWaveform;
@@ -156,17 +151,17 @@ void ClockRecoveryFilter::Refresh()
int64_t tend = din->m_offsets[din->m_offsets.size() - 1] * din->m_timescale;
size_t nedge = 1;
//LogDebug("n, delta, period, freq_ghz\n");
double edgepos = edges[0];
int64_t edgepos = edges[0];
bool value = false;
double total_error = 0;
int64_t total_error = 0;
cap->m_samples.reserve(edges.size());
size_t igate = 0;
bool gating = false;
int cycles_open_loop = 0;
for(; (edgepos < tend) && (nedge < edges.size()-1); edgepos += period)
{
float center = period/2;
double edgepos_orig = edgepos;
int64_t edgepos_orig = edgepos;

//See if the current edge position is within a gating region
bool was_gating = gating;
@@ -200,12 +195,12 @@ void ClockRecoveryFilter::Refresh()
//See if the next edge occurred in this UI.
//If not, just run the NCO open loop.
//Allow multiple edges in the UI if the frequency is way off.
double tnext = edges[nedge];
int64_t tnext = edges[nedge];
cycles_open_loop ++;
while( (tnext + center < edgepos) && (nedge+1 < edges.size()) )
{
//Find phase error
double delta = (edgepos - tnext) - period;
int64_t delta = (edgepos - tnext) - period;
total_error += fabs(delta);

//If the clock is currently gated, re-sync to the edge
@@ -214,15 +209,19 @@ void ClockRecoveryFilter::Refresh()

//Check sign of phase and do bang-bang feedback (constant shift regardless of error magnitude)
//If we skipped some edges, apply a larger correction
else if(delta > 0)
{
period -= 0.000025 * period * cycles_open_loop;
edgepos -= 0.0025 * period * cycles_open_loop;
}
else
{
period += 0.000025 * period * cycles_open_loop;
edgepos += 0.0025 * period * cycles_open_loop;
int64_t cperiod = period * cycles_open_loop;
if(delta > 0)
{
period -= cperiod / 40000;
edgepos -= cperiod / 400;
}
else
{
period += cperiod / 40000;
edgepos += cperiod / 400;
}
}

cycles_open_loop = 0;
@@ -236,14 +235,14 @@ void ClockRecoveryFilter::Refresh()
{
value = !value;

cap->m_offsets.push_back(static_cast<int64_t>(round(edgepos_orig + period/2 - din->m_timescale*1.5)));
cap->m_offsets.push_back(edgepos_orig + period/2 - din->m_timescale*1.5);
cap->m_durations.push_back(period);
cap->m_samples.push_back(value);
}
}

total_error /= edges.size();
LogTrace("average phase error %.1f\n", total_error);
LogTrace("average phase error %zu\n", total_error);

SetData(cap, 0);
}
3 changes: 0 additions & 3 deletions scopeprotocols/ClockRecoveryFilter.h
Original file line number Diff line number Diff line change
@@ -55,9 +55,6 @@ class ClockRecoveryFilter : public Filter

PROTOCOL_DECODER_INITPROC(ClockRecoveryFilter)

//Debug
int64_t m_nominalPeriod;

protected:
std::string m_baudname;
std::string m_threshname;