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

Commits on Sep 9, 2020

  1. Copy the full SHA
    634e8ea View commit details

Commits on Sep 10, 2020

  1. Copy the full SHA
    dae8361 View commit details
Showing with 107 additions and 25 deletions.
  1. +46 −6 scopehal/LeCroyOscilloscope.cpp
  2. +61 −19 scopeprotocols/SPIDecoder.cpp
52 changes: 46 additions & 6 deletions scopehal/LeCroyOscilloscope.cpp
Original file line number Diff line number Diff line change
@@ -1554,7 +1554,7 @@ map<int, DigitalWaveform*> LeCroyOscilloscope::ProcessDigitalWaveform(string& da

tmp = data.substr(data.find("<NumSamples>") + 12);
tmp = tmp.substr(0, tmp.find("</NumSamples>"));
int num_samples = atoi(tmp.c_str());
size_t num_samples = atoi(tmp.c_str());
//LogDebug("Expecting %d samples\n", num_samples);

//Extract the raw trigger timestamp (nanoseconds since Jan 1 2000)
@@ -1604,6 +1604,7 @@ map<int, DigitalWaveform*> LeCroyOscilloscope::ProcessDigitalWaveform(string& da
base64_decode_block(tmp.c_str(), tmp.length(), (char*)block, &bstate);

//We have each channel's data from start to finish before the next (no interleaving).
//TODO: Multithread across waveforms
unsigned int icapchan = 0;
for(unsigned int i=0; i<m_digitalChannelCount; i++)
{
@@ -1615,16 +1616,55 @@ map<int, DigitalWaveform*> LeCroyOscilloscope::ProcessDigitalWaveform(string& da
//Capture timestamp
cap->m_startTimestamp = start_time;
cap->m_startPicoseconds = start_ps;

//Preallocate memory assuming no deduplication possible
cap->Resize(num_samples);

//TODO: AVX this
for(int j=0; j<num_samples; j++)
//Save the first sample (can't merge with sample -1 because that doesn't exist)
size_t base = icapchan*num_samples;
size_t k = 0;
cap->m_offsets[0] = 0;
cap->m_durations[0] = 1;
cap->m_samples[0] = block[base];

//Read and de-duplicate the other samples
//TODO: can we vectorize this somehow?
bool last = block[base];
for(size_t j=1; j<num_samples; j++)
{
cap->m_offsets[j] = j;
cap->m_durations[j] = 1;
cap->m_samples[j] = block[icapchan*num_samples + j];
bool sample = block[base + j];

//Deduplicate consecutive samples with same value
if(last == sample)
cap->m_durations[k] ++;

//Nope, it toggled - store the new value
else
{
k++;
cap->m_offsets[k] = j;
cap->m_durations[k] = 1;
cap->m_samples[k] = sample;
last = sample;
}

}

//Done, shrink any unused space
cap->Resize(k);
cap->m_offsets.shrink_to_fit();
cap->m_durations.shrink_to_fit();
cap->m_samples.shrink_to_fit();

//See how much space we saved
/*
LogDebug("%s: %zu samples deduplicated to %zu (%.1f %%)\n",
m_digitalChannels[i]->m_displayname.c_str(),
num_samples,
k,
(k * 100.0f) / num_samples);
*/

//Done, save data and go on to next
ret[m_digitalChannels[i]->GetIndex()] = cap;
icapchan ++;
80 changes: 61 additions & 19 deletions scopeprotocols/SPIDecoder.cpp
Original file line number Diff line number Diff line change
@@ -113,11 +113,9 @@ void SPIDecoder::Refresh()

//TODO: different cpha/cpol modes

//TODO: packets based on CS# pulses
//TODO: packets based on CS# pulses?

//Loop over the data and look for transactions
//For now, assume equal sample rate

enum
{
STATE_DESELECTED,
@@ -130,14 +128,22 @@ void SPIDecoder::Refresh()
int64_t bytestart = 0;
bool first = false;

size_t len = clk->m_samples.size();
len = min(len, csn->m_samples.size());
len = min(len, data->m_samples.size());
for(size_t i=0; i<len; i++)
size_t ics = 0;
size_t iclk = 0;
size_t idata = 0;

int64_t timestamp = 0;

size_t clklen = clk->m_samples.size();
size_t cslen = csn->m_samples.size();
size_t datalen = data->m_samples.size();

while(true)
{
bool cur_cs = csn->m_samples[i];
bool cur_clk = clk->m_samples[i];
bool cur_data = data->m_samples[i];
//Get the current samples
bool cur_cs = csn->m_samples[ics];
bool cur_clk = clk->m_samples[iclk];
bool cur_data = data->m_samples[idata];

switch(state)
{
@@ -148,7 +154,7 @@ void SPIDecoder::Refresh()
state = STATE_SELECTED_CLKLO;
current_byte = 0;
bitcount = 0;
bytestart = clk->m_offsets[i];
bytestart = timestamp;
first = true;
}
break;
@@ -163,11 +169,20 @@ void SPIDecoder::Refresh()
if(first)
{
cap->m_offsets.push_back(bytestart);
cap->m_durations.push_back(clk->m_offsets[i] - bytestart);
cap->m_durations.push_back(timestamp - bytestart);
cap->m_samples.push_back(SPISymbol(SPISymbol::TYPE_SELECT, 0));
first = false;
}
bytestart = clk->m_offsets[i];

//Extend the last byte until this edge
else if(!cap->m_samples.empty())
{
size_t ilast = cap->m_samples.size()-1;
if(cap->m_samples[ilast].m_stype == SPISymbol::TYPE_DATA)
cap->m_durations[ilast] = timestamp - cap->m_offsets[ilast];
}

bytestart = timestamp;
}

state = STATE_SELECTED_CLKHI;
@@ -182,12 +197,12 @@ void SPIDecoder::Refresh()
if(bitcount == 8)
{
cap->m_offsets.push_back(bytestart);
cap->m_durations.push_back(clk->m_offsets[i] - bytestart);
cap->m_durations.push_back(timestamp - bytestart);
cap->m_samples.push_back(SPISymbol(SPISymbol::TYPE_DATA, current_byte));

bitcount = 0;
current_byte = 0;
bytestart = clk->m_offsets[i];
bytestart = timestamp;
}
}

@@ -196,10 +211,10 @@ void SPIDecoder::Refresh()
else if(cur_cs)
{
cap->m_offsets.push_back(bytestart);
cap->m_durations.push_back(clk->m_offsets[i] - bytestart);
cap->m_durations.push_back(timestamp - bytestart);
cap->m_samples.push_back(SPISymbol(SPISymbol::TYPE_DESELECT, 0));

bytestart = clk->m_offsets[i];
bytestart = timestamp;
state = STATE_DESELECTED;
}
break;
@@ -214,17 +229,44 @@ void SPIDecoder::Refresh()
else if(cur_cs)
{
cap->m_offsets.push_back(bytestart);
cap->m_durations.push_back(clk->m_offsets[i] - bytestart);
cap->m_durations.push_back(timestamp - bytestart);
cap->m_samples.push_back(SPISymbol(SPISymbol::TYPE_DESELECT, 0));

bytestart = clk->m_offsets[i];
bytestart = timestamp;
state = STATE_DESELECTED;
}

break;
}

//Get timestamps of next event on each channel
int64_t next_cs = timestamp;
if( (ics + 1) < cslen)
next_cs = csn->m_offsets[ics + 1];
int64_t next_clk = timestamp;
if( (iclk + 1) < clklen)
next_clk = clk->m_offsets[iclk + 1];
int64_t next_data = timestamp;
if( (idata + 1) < datalen)
next_data = data->m_offsets[idata + 1];
int64_t next_timestamp = min(next_cs, min(next_clk, next_data));

//If we can't move forward, stop
if(next_timestamp == timestamp)
break;

timestamp = next_timestamp;

while( ((ics + 1) <= cslen) && (csn->m_offsets[ics + 1] <= timestamp) )
ics ++;
while( ((iclk + 1) < clklen) && (clk->m_offsets[iclk + 1] <= timestamp) )
iclk ++;
while( ((idata + 1) < datalen) && (data->m_offsets[idata + 1] <= timestamp) )
idata ++;
}

LogDebug("%zu events\n", cap->m_samples.size());

SetData(cap, 0);
}