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

Commits on Oct 28, 2020

  1. Copy the full SHA
    c6f6d09 View commit details
  2. Copy the full SHA
    f497877 View commit details
Showing with 120 additions and 76 deletions.
  1. +8 −2 scopeprotocols/DPhyDataDecoder.cpp
  2. +112 −74 scopeprotocols/DPhySymbolDecoder.cpp
10 changes: 8 additions & 2 deletions scopeprotocols/DPhyDataDecoder.cpp
Original file line number Diff line number Diff line change
@@ -122,6 +122,10 @@ void DPhyDataDecoder::Refresh()
STATE_HS_DATA
} state = STATE_UNKNOWN;

//If our data is a single-ended decode, we have to infer some states we can't see.
auto data_decoder = dynamic_cast<DPhySymbolDecoder*>(GetInput(1).m_channel);
bool single_ended_data = data_decoder->GetInput(1).m_channel == NULL;

//Process the data
DPhyDataSymbol samp;
size_t clklen = clk->m_samples.size();
@@ -185,8 +189,10 @@ void DPhyDataDecoder::Refresh()
//Link is idle, wait for a start-of-transmission or escape sequence
case STATE_IDLE:

//LP-01 is a HS-REQUEST
if(cur_data.m_type == DPhySymbol::STATE_LP01)
//LP-01 is a HS-REQUEST.
//If doing a single-ended decode, we can't see the LP-01. We seem to jump straight to LP-00.
if( (cur_data.m_type == DPhySymbol::STATE_LP01) ||
(single_ended_data && (cur_data.m_type == DPhySymbol::STATE_LP00) ) )
{
state = STATE_HS_REQUEST;

186 changes: 112 additions & 74 deletions scopeprotocols/DPhySymbolDecoder.cpp
Original file line number Diff line number Diff line change
@@ -128,64 +128,61 @@ void DPhySymbolDecoder::Refresh()
cap->m_timescale = dp->m_timescale;
cap->m_startTimestamp = dp->m_startTimestamp;
cap->m_startPicoseconds = dp->m_startPicoseconds;
DPhySymbol::type state = DPhySymbol::STATE_LP00;
DPhySymbol::type last_state = DPhySymbol::STATE_HS0;
DPhySymbol::type state = DPhySymbol::STATE_HS0;
DPhySymbol::type nextstate = state;

/*
If we have Dp only, we can decode a restricted subset of line states by cheating a bit.
This isn't truly spec compliant but allows for protocol decoding with only one probe.
for(size_t i=0; i<len; i++)
{
float v = dp->m_samples[i];

HS-1
Dp > 225 mV
Dp < 880 mV
/*
If we have Dp only, we can decode a restricted subset of line states by cheating a bit.
This isn't truly spec compliant but allows for protocol decoding with only one probe.
HS-0
Dp > 50 mV
Dp < 175 mV
HS-1
Dp > 225 mV
Dp < 880 mV
LP-00 or LP-01 (decode as LP-00)
Dp < 50 mV
HS-0
Dp > 50 mV
Dp < 175 mV
LP-10 or LP-11 (decode as LP-11)
Dp > 880 mV
*/
if(!dn)
{
DPhySymbol::type nextstate = state;
for(size_t i=0; i<len; i++)
LP-00 or LP-01 (decode as LP-00)
Dp < 50 mV
LP-10 or LP-11 (decode as LP-11)
Dp > 880 mV
*/
if(!dn)
{
float v = dp->m_samples[i];
//Can only go to a HS state from another HS state or LP00
if( (state == DPhySymbol::STATE_HS0) ||
(state == DPhySymbol::STATE_HS1) ||
(state == DPhySymbol::STATE_LP00) )
{
if(v > 0.88)
nextstate = DPhySymbol::STATE_LP11;
else if(v > 0.225)
nextstate = DPhySymbol::STATE_HS1;
else if(v < 0.025)
nextstate = DPhySymbol::STATE_LP00;
else if(v < 0.175)
nextstate = DPhySymbol::STATE_HS0;
}

if(v > 0.88)
nextstate = DPhySymbol::STATE_LP11;
else if(v > 0.225)
nextstate = DPhySymbol::STATE_HS1;
else if(v < 0.005)
nextstate = DPhySymbol::STATE_LP00;
else if(v < 0.175)
nextstate = DPhySymbol::STATE_HS0;

//If same as existing state, extend it
size_t nsize = cap->m_samples.size();
size_t nlast = nsize-1;
if(nsize && cap->m_samples[nlast].m_type == nextstate)
cap->m_durations[nlast] = dp->m_offsets[i] + dp->m_durations[i] - cap->m_offsets[nlast];

//Nope, create a new sample
//Otherwise, only consider other LP states
else
{
cap->m_offsets.push_back(dp->m_offsets[i]);
cap->m_durations.push_back(dp->m_durations[i]);
cap->m_samples.push_back(nextstate);
if(v > 0.88)
nextstate = DPhySymbol::STATE_LP11;
else if(v < 0.025)
nextstate = DPhySymbol::STATE_LP00;
}

state = nextstate;
}
}

else
{
DPhySymbol::type nextstate = state;
for(size_t i=0; i<len; i++)
//Full differential decode
else
{
float vp = dp->m_samples[i];
float vn = dn->m_samples[i];
@@ -213,44 +210,85 @@ void DPhySymbolDecoder::Refresh()
nextstate = DPhySymbol::STATE_LP10;
else if( (vp > 0.80) && (vn > 0.80) )
nextstate = DPhySymbol::STATE_LP11;
}

//If same as existing state, extend it
size_t nsize = cap->m_samples.size();
size_t nlast = nsize-1;
if(nsize && cap->m_samples[nlast].m_type == nextstate)
cap->m_durations[nlast] = dp->m_offsets[i] + dp->m_durations[i] - cap->m_offsets[nlast];
//See if the state has changed
size_t nsize = cap->m_samples.size();
size_t nlast = nsize-1;
bool samestate = (nsize && cap->m_samples[nlast].m_type == nextstate);

//Nope, create a new sample
else
//Glitch filtering
if(!samestate && nsize)
{
bool last_was_glitch = false;

//If we are transitioning from LP-00 to HS-0, we need to hold in LP-00 state for Ths-prepare first.
//Discard any glitches to HS-0 during the transition period.
if( (state == DPhySymbol::STATE_LP00) && (nextstate == DPhySymbol::STATE_HS0) )
{
//Glitch filter LP states.
//If the previous sample was a LP state, but significantly less than Tlpx long, discard it.
//For now, set the cutoff at 40 ns (40,000 ps)
const int64_t tlpx_cutoff = 40000;
if(nsize && (state != DPhySymbol::STATE_HS0) && (state != DPhySymbol::STATE_HS1) )
//For now, set the cutoff at 30 ns. Per spec it should be 40 ns + 4 UI at the TX,
//but we're decoding combinatorially and don't know the UI yet.
const int64_t thsprepare_cutoff = 30000;
if( (cap->m_durations[nlast] * cap->m_timescale) < thsprepare_cutoff )
{
if( (cap->m_durations[nlast] * cap->m_timescale) < tlpx_cutoff )
{
cap->m_durations.resize(nlast);
cap->m_offsets.resize(nlast);
cap->m_samples.resize(nlast);

//If there was a previous sample, extend it to the start of this one
if(nsize > 1)
{
nlast --;
cap->m_durations[nlast] = dp->m_offsets[i] + dp->m_durations[i] - cap->m_offsets[nlast];
}
}
nextstate = DPhySymbol::STATE_LP00;
samestate = true;
}
}

//Transition from HS-0 to LP-00 isn't allowed.
//This probably means we were never in HS-0 in the first place.
else if( (state == DPhySymbol::STATE_HS0) && (nextstate == DPhySymbol::STATE_LP00) )
last_was_glitch = true;

//If the previous sample was a LP state, but significantly less than Tlpx long, discard it.
else if( (state != DPhySymbol::STATE_HS0) && (state != DPhySymbol::STATE_HS1) )
{
//For now, set the cutoff at 40 ns (40,000 ps).
//This provides some margin on the 50 ns Tlpx in the spec.
const int64_t tlpx_cutoff = 40000;
if( (cap->m_durations[nlast] * cap->m_timescale) < tlpx_cutoff )
last_was_glitch = true;
}

cap->m_offsets.push_back(dp->m_offsets[i]);
cap->m_durations.push_back(dp->m_durations[i]);
cap->m_samples.push_back(nextstate);
if(last_was_glitch)
{
//Delete the glitch sample
cap->m_durations.pop_back();
cap->m_offsets.pop_back();
cap->m_samples.pop_back();

//Update sizes
nsize = cap->m_samples.size();
if(nsize)
{
nlast = nsize-1;
last_state = cap->m_samples[nlast].m_type;
samestate = (nsize && last_state == nextstate);

//If changing, extend the pre-glitch sample to the start of this sample
if(!samestate)
cap->m_durations[nlast] = dp->m_offsets[i] - cap->m_offsets[nlast];
}
else
samestate = false;
}
}

//If same as existing state, extend last one
if(samestate)
cap->m_durations[nlast] = dp->m_offsets[i] + dp->m_durations[i] - cap->m_offsets[nlast];

//Nope, create a new sample
else
{
cap->m_offsets.push_back(dp->m_offsets[i]);
cap->m_durations.push_back(dp->m_durations[i]);
cap->m_samples.push_back(nextstate);
state = nextstate;
}

last_state = state;
}

SetData(cap, 0);