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

Commits on Jun 12, 2020

  1. Copy the full SHA
    529be21 View commit details
  2. EthernetRGMIIDecoder: now correctly use single or double-rate samplin…

    …g depending on clock rate. Fixes #150.
    azonenberg committed Jun 12, 2020
    Copy the full SHA
    a7c62c9 View commit details
Showing with 116 additions and 21 deletions.
  1. +1 −0 scopehal/LeCroyOscilloscope.cpp
  2. +25 −8 scopeprotocols/EthernetProtocolDecoder.cpp
  3. +8 −0 scopeprotocols/EthernetProtocolDecoder.h
  4. +82 −13 scopeprotocols/EthernetRGMIIDecoder.cpp
1 change: 1 addition & 0 deletions scopehal/LeCroyOscilloscope.cpp
Original file line number Diff line number Diff line change
@@ -1909,6 +1909,7 @@ vector<uint64_t> LeCroyOscilloscope::GetSampleDepthsNonInterleaved()
ret.push_back(5 * k);
ret.push_back(10 * k);
ret.push_back(20 * k);
ret.push_back(40 * k); //hdo9 uses this sometimes
ret.push_back(50 * k);
ret.push_back(100 * k);
ret.push_back(200 * k);
33 changes: 25 additions & 8 deletions scopeprotocols/EthernetProtocolDecoder.cpp
Original file line number Diff line number Diff line change
@@ -337,8 +337,8 @@ Gdk::Color EthernetProtocolDecoder::GetColor(int i)
switch(data->m_samples[i].m_type)
{
//Preamble/SFD: gray (not interesting)
case EthernetFrameSegment::TYPE_INBAND_STATUS:
case EthernetFrameSegment::TYPE_PREAMBLE:
return m_standardColors[COLOR_PREAMBLE];
case EthernetFrameSegment::TYPE_SFD:
return m_standardColors[COLOR_PREAMBLE];

@@ -374,6 +374,8 @@ string EthernetProtocolDecoder::GetText(int i)
if(i >= (int)data->m_samples.size())
return "";

char tmp[128];

auto sample = data->m_samples[i];
switch(sample.m_type)
{
@@ -391,7 +393,6 @@ string EthernetProtocolDecoder::GetText(int i)
if(sample.m_data.size() != 6)
return "[invalid dest MAC length]";

char tmp[32];
snprintf(tmp, sizeof(tmp), "Dest MAC: %02x:%02x:%02x:%02x:%02x:%02x",
sample.m_data[0],
sample.m_data[1],
@@ -407,7 +408,6 @@ string EthernetProtocolDecoder::GetText(int i)
if(sample.m_data.size() != 6)
return "[invalid src MAC length]";

char tmp[32];
snprintf(tmp, sizeof(tmp), "Src MAC: %02x:%02x:%02x:%02x:%02x:%02x",
sample.m_data[0],
sample.m_data[1],
@@ -425,7 +425,6 @@ string EthernetProtocolDecoder::GetText(int i)

string type = "Type: ";

char tmp[32];
uint16_t ethertype = (sample.m_data[0] << 8) | sample.m_data[1];
switch(ethertype)
{
@@ -459,8 +458,6 @@ string EthernetProtocolDecoder::GetText(int i)
break;
}

//TODO: look up a table of common Ethertype values

return type;
}

@@ -469,19 +466,39 @@ string EthernetProtocolDecoder::GetText(int i)
string ret;
for(auto b : sample.m_data)
{
char tmp[32];
snprintf(tmp, sizeof(tmp), "%02x ", b);
ret += tmp;
}
return ret;
}

case EthernetFrameSegment::TYPE_INBAND_STATUS:
{
int status = sample.m_data[0];

int up = status & 1;
int rawspeed = (status >> 1) & 3;
int duplex = (status >> 3) & 1;

int speed = 10;
if(rawspeed == 1)
speed = 100;
else if(rawspeed == 2)
speed = 1000;

snprintf(tmp, sizeof(tmp), "%s, %s duplex, %d Mbps",
up ? "up" : "down",
duplex ? "full" : "half",
speed
);
return tmp;
}

case EthernetFrameSegment::TYPE_FCS:
{
if(sample.m_data.size() != 4)
return "[invalid FCS length]";

char tmp[32];
snprintf(tmp, sizeof(tmp), "CRC: %02x%02x%02x%02x",
sample.m_data[0],
sample.m_data[1],
8 changes: 8 additions & 0 deletions scopeprotocols/EthernetProtocolDecoder.h
Original file line number Diff line number Diff line change
@@ -55,11 +55,19 @@ class EthernetFrameSegment
TYPE_VLAN_TAG,
TYPE_PAYLOAD,
TYPE_FCS,
TYPE_INBAND_STATUS, //RGMII or similar
TYPE_NO_CARRIER
} m_type;

std::vector<uint8_t> m_data;

EthernetFrameSegment()
{}

EthernetFrameSegment(SegmentType type, uint8_t value)
: m_type(type)
{ m_data.push_back(value); }

bool operator==(const EthernetFrameSegment& rhs) const
{
return (m_data == rhs.m_data) && (m_type == rhs.m_type);
95 changes: 82 additions & 13 deletions scopeprotocols/EthernetRGMIIDecoder.cpp
Original file line number Diff line number Diff line change
@@ -122,25 +122,69 @@ void EthernetRGMIIDecoder::Refresh()
SampleOnAnyEdges(data, clk, ddata);

//Need a reasonable number of samples or there's no point in decoding.
//Cut off the last sample since we're DDR.
//Cut off the last few samples because we might be either DDR or SDR and need to seek past our current position.
size_t len = min(dctl.m_samples.size(), ddata.m_samples.size());
if(len < 100)
{
SetData(NULL);
return;
}
len --;
len -= 4;

//Create the output capture
auto cap = new EthernetWaveform;
cap->m_timescale = 1;
cap->m_startTimestamp = data->m_startTimestamp;
cap->m_startPicoseconds = data->m_startPicoseconds;

for(size_t i=0; i < len; i++)
//skip first 2 samples so we can get a full clock cycle before starting
for(size_t i=2; i < len; i++)
{
//Not sending a frame. Decode in-band status
if(!dctl.m_samples[i])
{
//Extract in-band status
uint8_t status = 0;
for(size_t j=0; j<4; j++)
{
if(ddata.m_samples[i][j])
status |= (1 << j);
}

//Same status? Merge samples
bool extend = false;
size_t last = cap->m_samples.size() - 1;
if(!cap->m_samples.empty())
{
auto& sample = cap->m_samples[last];
if( (sample.m_type == EthernetFrameSegment::TYPE_INBAND_STATUS) &&
(sample.m_data[0] == status) )
{
extend = true;
}
}

//Decode
if(extend)
cap->m_durations[last] = ddata.m_offsets[i] + ddata.m_durations[i] - cap->m_offsets[last];
else
{
cap->m_offsets.push_back(ddata.m_offsets[i]);
cap->m_durations.push_back(ddata.m_durations[i]);
cap->m_samples.push_back(EthernetFrameSegment(EthernetFrameSegment::TYPE_INBAND_STATUS, status));
}

continue;
}

//We're processing a frame.
//Figure out the clock period.
//Need to do this cycle-by-cycle in case the link speed changes during a deep capture
//TODO: alert if clock isn't close to one of the three legal frequencies
int64_t clkperiod = dctl.m_offsets[i] - dctl.m_offsets[i-2];
bool ddr = false; //Default to 2.5/25 MHz SDR.
if(clkperiod < 10000) //Faster than 100 MHz? assume it's 125 MHz DDR.
ddr = true;

//Set of recovered bytes and timestamps
vector<uint8_t> bytes;
@@ -153,24 +197,49 @@ void EthernetRGMIIDecoder::Refresh()
//Start time
starts.push_back(ddata.m_offsets[i]);

//Convert bits to bytes
uint8_t dval = 0;
for(size_t j=0; j<8; j++)
if(ddr)
{
if(j < 4)
//Convert bits to bytes
uint8_t dval = 0;
for(size_t j=0; j<8; j++)
{
if(ddata.m_samples[i][j])
if(j < 4)
{
if(ddata.m_samples[i][j])
dval |= (1 << j);
}
else if(ddata.m_samples[i+1][j-4])
dval |= (1 << j);
}
else if(ddata.m_samples[i+1][j-4])
dval |= (1 << j);
bytes.push_back(dval);

ends.push_back(ddata.m_offsets[i+1] + ddata.m_durations[i+1]);
i += 2;
}
bytes.push_back(dval);

ends.push_back(ddata.m_offsets[i+1] + ddata.m_durations[i+1]);
i += 2;
else
{
//Convert bits to bytes
uint8_t dval = 0;
for(size_t j=0; j<8; j++)
{
if(j < 4)
{
if(ddata.m_samples[i][j])
dval |= (1 << j);
}
else if(ddata.m_samples[i+2][j-4])
dval |= (1 << j);
}
bytes.push_back(dval);

ends.push_back(ddata.m_offsets[i+3] + ddata.m_durations[i+3]);
i += 4;
}
}

LogDebug("\n");

//Crunch the data
BytesToFrames(bytes, starts, ends, cap);
}