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

Commits on May 13, 2020

  1. Copy the full SHA
    d6f0879 View commit details
  2. Copy the full SHA
    7ce4742 View commit details
1 change: 1 addition & 0 deletions scopeprotocols/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@ set(SCOPEPROTOCOLS_SOURCES
PeriodMeasurementDecoder.cpp
RiseMeasurementDecoder.cpp
SincInterpolationDecoder.cpp
SPIDecoder.cpp
ThresholdDecoder.cpp
TMDSDecoder.cpp
TopMeasurementDecoder.cpp
38 changes: 15 additions & 23 deletions scopeprotocols/HorizontalBathtubDecoder.cpp
Original file line number Diff line number Diff line change
@@ -141,41 +141,33 @@ void HorizontalBathtubDecoder::Refresh()
//Extract the single scanline we're interested in
//TODO: support a range of voltages
int64_t* row = din->GetAccumData() + ybin*din->GetWidth();
float nmax = 0;
for(size_t i=0; i<din->GetWidth(); i++)
{
int64_t sample = row[i];
if(sample > nmax)
nmax = sample;

cap->m_samples.push_back(AnalogSample(i*ps_per_pixel - din->m_uiWidth, ps_per_pixel, sample));
}

//Normalize to max amplitude
for(size_t i=0; i<cap->m_samples.size(); i++)
cap->m_samples[i].m_sample /= nmax;
cap->m_samples.push_back(AnalogSample(i*ps_per_pixel - din->m_uiWidth, ps_per_pixel, row[i]));

//Move from the center out and persist the max BER
float maxleft = 0;
float maxright = 0;
//Move from the center out and integrate BER
float sumleft = 0;
float sumright = 0;
ssize_t mid = cap->m_samples.size()/2;
for(ssize_t i=mid; i>=0; i--)
{
float& samp = cap->m_samples[i].m_sample;
if(samp > maxleft)
maxleft = samp;
else
samp = maxleft;
sumleft += samp;
samp = sumleft;
}
for(size_t i=mid; i<cap->m_samples.size(); i++)
{
float& samp = cap->m_samples[i].m_sample;
if(samp > maxright)
maxright = samp;
else
samp = maxright;
sumright += samp;
samp = sumright;
}

//Normalize to max amplitude
float nmax = sumleft;
if(sumright > sumleft)
nmax = sumright;
for(size_t i=0; i<cap->m_samples.size(); i++)
cap->m_samples[i].m_sample /= nmax;

//Log post-scaling
for(size_t i=0; i<cap->m_samples.size(); i++)
{
218 changes: 218 additions & 0 deletions scopeprotocols/SPIDecoder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
/***********************************************************************************************************************
* *
* ANTIKERNEL v0.1 *
* *
* Copyright (c) 2012-2020 Andrew D. Zonenberg *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the *
* following conditions are met: *
* *
* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other materials provided with the distribution. *
* *
* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products *
* derived from this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
* POSSIBILITY OF SUCH DAMAGE. *
* *
***********************************************************************************************************************/

/**
@file
@author Andrew D. Zonenberg
@brief Implementation of SPIDecoder
*/

#include "../scopehal/scopehal.h"
#include "SPIDecoder.h"

using namespace std;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction / destruction

SPIDecoder::SPIDecoder(string color)
: ProtocolDecoder(OscilloscopeChannel::CHANNEL_TYPE_COMPLEX, color, CAT_SERIAL)
{
//Set up channels
m_signalNames.push_back("clk");
m_channels.push_back(NULL);

m_signalNames.push_back("cs#");
m_channels.push_back(NULL);

m_signalNames.push_back("data");
m_channels.push_back(NULL);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Factory methods

bool SPIDecoder::NeedsConfig()
{
return true;
}

bool SPIDecoder::ValidateChannel(size_t i, OscilloscopeChannel* channel)
{
if( (i < 3) && (channel->GetType() == OscilloscopeChannel::CHANNEL_TYPE_DIGITAL) && (channel->GetWidth() == 1) )
return true;
return false;
}

string SPIDecoder::GetProtocolName()
{
return "SPI";
}

void SPIDecoder::SetDefaultName()
{
char hwname[256];
snprintf(hwname, sizeof(hwname), "SPI(%s)", m_channels[2]->m_displayname.c_str());
m_hwname = hwname;
m_displayname = m_hwname;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Actual decoder logic

void SPIDecoder::Refresh()
{
//Get the input data
for(int i=0; i<2; i++)
{
if(m_channels[i] == NULL)
{
SetData(NULL);
return;
}
}
DigitalCapture* clk = dynamic_cast<DigitalCapture*>(m_channels[0]->GetData());
DigitalCapture* csn = dynamic_cast<DigitalCapture*>(m_channels[1]->GetData());
DigitalCapture* data = dynamic_cast<DigitalCapture*>(m_channels[2]->GetData());
if( (clk == NULL) || (csn == NULL) || (data == NULL) )
{
SetData(NULL);
return;
}

//Create the capture
SPICapture* cap = new SPICapture;
cap->m_timescale = clk->m_timescale;
cap->m_startTimestamp = clk->m_startTimestamp;
cap->m_startPicoseconds = clk->m_startPicoseconds;

//TODO: different cpha/cpol modes

//TODO: packets based on CS# pulses

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

enum
{
STATE_DESELECTED,
STATE_SELECTED_CLKLO,
STATE_SELECTED_CLKHI
} state = STATE_DESELECTED;

uint8_t current_byte = 0;
uint8_t bitcount = 0;
int64_t bytestart = 0;

for(size_t i=0; i<clk->m_samples.size(); i++)
{
if( (i >= csn->m_samples.size()) || (i >= data->m_samples.size()) )
break;

bool cur_cs = csn->m_samples[i].m_sample;
bool cur_clk = clk->m_samples[i].m_sample;
bool cur_data = data->m_samples[i].m_sample;

switch(state)
{
//wait for falling edge of CS#
case STATE_DESELECTED:
if(!cur_cs)
{
state = STATE_SELECTED_CLKLO;
current_byte = 0;
bitcount = 0;
}
break;

//wait for rising edge of clk
case STATE_SELECTED_CLKLO:
if(cur_clk)
{
if(bitcount == 0)
bytestart = clk->m_samples[i].m_offset;

state = STATE_SELECTED_CLKHI;
bitcount ++;
if(cur_data)
current_byte = 0x80 | (current_byte >> 1);
else
current_byte = (current_byte >> 1);

if(bitcount == 8)
{
cap->m_samples.push_back(SPISample(
bytestart,
clk->m_samples[i].m_offset - bytestart,
current_byte));

bitcount = 0;
current_byte = 0;
}
}

//end of packet
//TODO: error if a byte is truncated
else if(cur_cs)
state = STATE_DESELECTED;
break;

//wait for falling edge of clk
case STATE_SELECTED_CLKHI:
if(!cur_clk)
state = STATE_SELECTED_CLKLO;

//end of packet
//TODO: error if a byte is truncated
else if(cur_cs)
state = STATE_DESELECTED;

break;
}
}

SetData(cap);
}

Gdk::Color SPIDecoder::GetColor(int /*i*/)
{
return m_standardColors[COLOR_DATA];
}

string SPIDecoder::GetText(int i)
{
SPICapture* capture = dynamic_cast<SPICapture*>(GetData());
if(capture != NULL)
{
char tmp[16];
snprintf(tmp, sizeof(tmp), "%02x", capture->m_samples[i].m_sample);
return string(tmp);
}
return "";
}
65 changes: 65 additions & 0 deletions scopeprotocols/SPIDecoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/***********************************************************************************************************************
* *
* ANTIKERNEL v0.1 *
* *
* Copyright (c) 2012-2020 Andrew D. Zonenberg *
* All rights reserved. *
* *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the *
* following conditions are met: *
* *
* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other materials provided with the distribution. *
* *
* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products *
* derived from this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
* POSSIBILITY OF SUCH DAMAGE. *
* *
***********************************************************************************************************************/

/**
@file
@author Andrew D. Zonenberg
@brief Declaration of SPIDecoder
*/

#ifndef SPIDecoder_h
#define SPIDecoder_h

#include "../scopehal/ProtocolDecoder.h"

typedef OscilloscopeSample<uint8_t> SPISample;
typedef CaptureChannel<uint8_t> SPICapture;

class SPIDecoder : public ProtocolDecoder
{
public:
SPIDecoder(std::string color);

virtual std::string GetText(int i);
virtual Gdk::Color GetColor(int i);

virtual void Refresh();
virtual bool NeedsConfig();

static std::string GetProtocolName();
virtual void SetDefaultName();

virtual bool ValidateChannel(size_t i, OscilloscopeChannel* channel);

PROTOCOL_DECODER_INITPROC(SPIDecoder)

protected:
};

#endif
1 change: 1 addition & 0 deletions scopeprotocols/scopeprotocols.cpp
Original file line number Diff line number Diff line change
@@ -70,6 +70,7 @@ void ScopeProtocolStaticInit()
AddDecoderClass(PeriodMeasurementDecoder);
AddDecoderClass(RiseMeasurementDecoder);
AddDecoderClass(SincInterpolationDecoder);
AddDecoderClass(SPIDecoder);
AddDecoderClass(ThresholdDecoder);
AddDecoderClass(TMDSDecoder);
AddDecoderClass(TopMeasurementDecoder);
2 changes: 1 addition & 1 deletion scopeprotocols/scopeprotocols.h
Original file line number Diff line number Diff line change
@@ -71,6 +71,7 @@
#include "PeriodMeasurementDecoder.h"
#include "RiseMeasurementDecoder.h"
#include "SincInterpolationDecoder.h"
#include "SPIDecoder.h"
#include "ThresholdDecoder.h"
#include "TMDSDecoder.h"
#include "TopMeasurementDecoder.h"
@@ -87,7 +88,6 @@
#include "RPCDecoder.h"
#include "RPCNameserverDecoder.h"
#include "SchmittTriggerDecoder.h"
#include "SPIDecoder.h"
*/

#include "AverageStatistic.h"