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: 1e547eb97b63
Choose a base ref
...
head repository: ngscopeclient/scopehal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ab823c457478
Choose a head ref
  • 3 commits
  • 4 files changed
  • 1 contributor

Commits on May 7, 2019

  1. Copy the full SHA
    1a4a0fa View commit details
  2. Copy the full SHA
    2e5f2d3 View commit details
  3. Various tweaks to clock recovery decoder to handle lower frequency in…

    …puts better. Added support for gating when the input stops toggling.
    azonenberg committed May 7, 2019
    Copy the full SHA
    ab823c4 View commit details
Showing with 53 additions and 20 deletions.
  1. +6 −0 scopehal/ProtocolDecoder.h
  2. +46 −16 scopeprotocols/ClockRecoveryDecoder.cpp
  3. +1 −0 scopeprotocols/ClockRecoveryDecoder.h
  4. +0 −4 scopeprotocols/EyeDecoder2.cpp
6 changes: 6 additions & 0 deletions scopehal/ProtocolDecoder.h
Original file line number Diff line number Diff line change
@@ -46,6 +46,7 @@ class ProtocolDecoderParameter
{
TYPE_FLOAT,
TYPE_INT,
TYPE_BOOL,
TYPE_FILENAME
};

@@ -54,10 +55,15 @@ class ProtocolDecoderParameter
void ParseString(std::string str);
std::string ToString();

bool GetBoolVal()
{ return (m_intval != 0); }

int GetIntVal();
float GetFloatVal();
std::string GetFileName();

void SetBoolVal(bool b)
{ m_intval = b; }
void SetIntVal(int i);
void SetFloatVal(float f);
void SetFileName(std::string f);
62 changes: 46 additions & 16 deletions scopeprotocols/ClockRecoveryDecoder.cpp
Original file line number Diff line number Diff line change
@@ -51,6 +51,10 @@ ClockRecoveryDecoder::ClockRecoveryDecoder(string color)
m_threshname = "Threshold";
m_parameters[m_threshname] = ProtocolDecoderParameter(ProtocolDecoderParameter::TYPE_FLOAT);
m_parameters[m_threshname].SetFloatVal(0);

m_gatename = "Gate after";
m_parameters[m_gatename] = ProtocolDecoderParameter(ProtocolDecoderParameter::TYPE_INT);
m_parameters[m_gatename].SetIntVal(0);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -137,6 +141,8 @@ void ClockRecoveryDecoder::Refresh()
//Timestamps of the edges
vector<int64_t> edges;

int gateAfter = m_parameters[m_gatename].GetIntVal();

//Find times of the zero crossings
bool first = true;
bool last = false;
@@ -172,52 +178,76 @@ void ClockRecoveryDecoder::Refresh()

double dt = GetTime() - start;
start = GetTime();
LogTrace("Zero crossing: %.3f ms\n", dt * 1000);
//LogTrace("Zero crossing: %.3f ms\n", dt * 1000);

//The actual PLL NCO
//TODO: use the real fibre channel PLL.
int64_t tend = din->m_samples[din->m_samples.size() - 1].m_offset * din->m_timescale;
float period = ps;
size_t nedge = 1;
//LogDebug("n,period,phase_error\n");
double edgepos = (edges[0] + period/2);
//LogDebug("n,delta,period\n");
double edgepos = edges[0];
bool value = false;
double total_error = 0;
cap->m_samples.reserve(edges.size());
int cycles_since_edge = 0;
bool gating = false;
for(; (edgepos < tend) && (nedge < edges.size()-1); edgepos += period)
{
float center = period/2;
double edgepos_orig = edgepos;

//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.
int64_t tnext = edges[nedge];
while(tnext < edgepos)
bool has_edge = false;
while(tnext + center < edgepos)
{
//Find phase error
int64_t delta = edgepos - tnext;
int64_t phase_error = center - delta;
total_error += fabs(phase_error);
int64_t delta = (edgepos - tnext) - period;
total_error += fabs(delta);

//If the clock is currently gated, re-sync to the center of the UI
cycles_since_edge = 0;
if(gating)
{
gating = false;
edgepos = tnext + period;
delta = 0;
}

//Check sign of phase and do bang-bang feedback (constant shift regardless of error magnitude)
if(phase_error < 0)
else if(delta > 0)
{
period -= 0.005;
edgepos -= 0.5;
period -= 0.00005 * period;
edgepos -= 0.005 * period;
}
else
{
period += 0.005;
edgepos += 0.5;
period += 0.00005 * period;
edgepos += 0.005 * period;
}

//LogDebug("%ld,%.2f,%ld\n", nedge, period, phase_error);
//LogDebug("%ld,%ld,%.2f\n", nedge, delta, period);
tnext = edges[++nedge];
has_edge = true;
}

//Add the sample
value = !value;
cap->m_samples.push_back(DigitalSample((int64_t)edgepos, (int64_t)period, value));
//Keep count of idle time with no edges
if(!has_edge)
cycles_since_edge ++;

//Add the sample. Gate if it's been a while and the user requested gating
if(gateAfter && cycles_since_edge >= gateAfter)
gating = true;
else if(!gating)
{
value = !value;
cap->m_samples.push_back(DigitalSample(
static_cast<int64_t>(round(edgepos_orig + period/2 - din->m_timescale*1.5)),
(int64_t)period, value));
}
}

dt = GetTime() - start;
1 change: 1 addition & 0 deletions scopeprotocols/ClockRecoveryDecoder.h
Original file line number Diff line number Diff line change
@@ -60,6 +60,7 @@ class ClockRecoveryDecoder : public ProtocolDecoder
protected:
std::string m_baudname;
std::string m_threshname;
std::string m_gatename;
};

#endif
4 changes: 0 additions & 4 deletions scopeprotocols/EyeDecoder2.cpp
Original file line number Diff line number Diff line change
@@ -218,7 +218,6 @@ void EyeDecoder2::Refresh()
double awidth = 0;
int64_t nwidth = 0;
float yscale = m_height / m_channels[0]->GetVoltageRange();
float tfix = 1.5 * waveform->m_timescale;
float fwidth = m_width / 2.0f;
float ymid = m_height / 2;
for(auto& samp : waveform->m_samples)
@@ -245,9 +244,6 @@ void EyeDecoder2::Refresh()
offset = tstart - tend;
}

//TODO: figure out where this is creeping in
offset += tfix;

//Find (and sanity check) the Y coordinate
size_t pixel_y = (samp.m_sample * yscale) + ymid;
if(pixel_y >= m_height)