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

Commits on Nov 22, 2019

  1. Copy the full SHA
    91bb927 View commit details
2 changes: 2 additions & 0 deletions scopeprotocols/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -16,6 +16,8 @@ set(SCOPEPROTOCOLS_SOURCES
EyeDecoder2.cpp
EyeRenderer.cpp
FFTDecoder.cpp
I2CDecoder.cpp
I2CRenderer.cpp
IBM8b10bDecoder.cpp
IBM8b10bRenderer.cpp
JtagDecoder.cpp
237 changes: 237 additions & 0 deletions scopeprotocols/I2CDecoder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
/***********************************************************************************************************************
* *
* ANTIKERNEL v0.1 *
* *
* Copyright (c) 2012-2019 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 I2CDecoder
*/

#include "../scopehal/scopehal.h"
#include "../scopehal/ChannelRenderer.h"
#include "../scopehal/TextRenderer.h"
#include "I2CRenderer.h"
#include "I2CDecoder.h"

using namespace std;

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

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

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

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

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

ChannelRenderer* I2CDecoder::CreateRenderer()
{
return new I2CRenderer(this);
}

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

string I2CDecoder::GetProtocolName()
{
return "I2C";
}

void I2CDecoder::SetDefaultName()
{
char hwname[256];
snprintf(hwname, sizeof(hwname), "I2C(%s, %s)", m_channels[0]->m_displayname.c_str(), m_channels[1]->m_displayname.c_str());
m_hwname = hwname;
m_displayname = m_hwname;
}

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

void I2CDecoder::Refresh()
{
//Get the input data
if( (m_channels[0] == NULL) || (m_channels[1] == NULL) )
{
SetData(NULL);
return;
}
DigitalCapture* sda = dynamic_cast<DigitalCapture*>(m_channels[0]->GetData());
DigitalCapture* scl = dynamic_cast<DigitalCapture*>(m_channels[1]->GetData());
if( (sda == NULL) || (scl == NULL) )
{
SetData(NULL);
return;
}

//Create the capture
I2CCapture* cap = new I2CCapture;
cap->m_timescale = sda->m_timescale;
cap->m_startTimestamp = sda->m_startTimestamp;
cap->m_startPicoseconds = sda->m_startPicoseconds;

//Loop over the data and look for transactions
//For now, assume equal sample rate
bool last_scl = true;
bool last_sda = true;
size_t symbol_start = 0;
I2CSymbol::stype current_type = I2CSymbol::TYPE_ERROR;
uint8_t current_byte = 0;
uint8_t bitcount = 0;
bool last_was_start = 0;
for(size_t i=0; i<sda->m_samples.size(); i++)
{
bool cur_sda = sda->m_samples[i].m_sample;
bool cur_scl = scl->m_samples[i].m_sample;

//SDA falling with SCL high is beginning of a start condition
if(!cur_sda && last_sda && cur_scl)
{
LogDebug("found i2c start at time %zu\n", sda->m_samples[i].m_offset);

//If we're following an ACK, this is a restart
if(current_type == I2CSymbol::TYPE_DATA)
current_type = I2CSymbol::TYPE_RESTART;
else
{
symbol_start = i;
current_type = I2CSymbol::TYPE_START;
}
}

//End a start bit when SDA goes high if the first data bit is a 1
//Otherwise end on a falling clock edge
else if( ((current_type == I2CSymbol::TYPE_START) || (current_type == I2CSymbol::TYPE_RESTART)) &&
(cur_sda || !cur_scl) )
{
cap->m_samples.push_back(I2CSample(
sda->m_samples[symbol_start].m_offset,
sda->m_samples[i].m_offset - symbol_start,
I2CSymbol(current_type, 0)));

last_was_start = true;
current_type = I2CSymbol::TYPE_DATA;
symbol_start = i;
bitcount = 0;
current_byte = 0;
}


//SDA rising with SCL high is a stop condition
else if(cur_sda && !last_sda && cur_scl)
{
LogDebug("found i2c stop at time %zu\n", sda->m_samples[i].m_offset);

cap->m_samples.push_back(I2CSample(
sda->m_samples[symbol_start].m_offset,
sda->m_samples[i].m_offset - symbol_start,
I2CSymbol(I2CSymbol::TYPE_STOP, 0)));
last_was_start = false;

symbol_start = i;
}

//On a rising SCL edge, end the current bit
else if(cur_scl && !last_scl)
{
if(current_type == I2CSymbol::TYPE_DATA)
{
//Save the current data bit
bitcount ++;
current_byte = (current_byte << 1);
if(cur_sda)
current_byte |= 1;

//Add a sample if the byte is over
if(bitcount == 8)
{
if(last_was_start)
{
cap->m_samples.push_back(I2CSample(
sda->m_samples[symbol_start].m_offset,
sda->m_samples[i].m_offset - symbol_start,
I2CSymbol(I2CSymbol::TYPE_ADDRESS, current_byte)));
}
else
{
cap->m_samples.push_back(I2CSample(
sda->m_samples[symbol_start].m_offset,
sda->m_samples[i].m_offset - symbol_start,
I2CSymbol(I2CSymbol::TYPE_DATA, current_byte)));
}
last_was_start = false;

bitcount = 0;
current_byte = 0;
symbol_start = i;

current_type = I2CSymbol::TYPE_ACK;
}
}

//ACK/NAK
else if(current_type == I2CSymbol::TYPE_ACK)
{
cap->m_samples.push_back(I2CSample(
sda->m_samples[symbol_start].m_offset,
sda->m_samples[i].m_offset - symbol_start,
I2CSymbol(I2CSymbol::TYPE_ACK, cur_sda)));
last_was_start = false;

symbol_start = i;
current_type = I2CSymbol::TYPE_DATA;
}
}

//Save old state of both pins
last_sda = cur_sda;
last_scl = cur_scl;
}

SetData(cap);
}
92 changes: 92 additions & 0 deletions scopeprotocols/I2CDecoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/***********************************************************************************************************************
* *
* ANTIKERNEL v0.1 *
* *
* Copyright (c) 2012-2019 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 I2CDecoder
*/

#ifndef I2CDecoder_h
#define I2CDecoder_h

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

class I2CSymbol
{
public:
enum stype
{
TYPE_START,
TYPE_RESTART,
TYPE_STOP,
TYPE_DATA,
TYPE_ACK,
TYPE_ERROR,
TYPE_ADDRESS,
TYPE_NONE
};

I2CSymbol(stype t,uint8_t d)
: m_stype(t)
, m_data(d)
{}

stype m_stype;
uint8_t m_data;

bool operator== (const I2CSymbol& s) const
{
return (m_stype == s.m_stype) && (m_data == s.m_data);
}
};

typedef OscilloscopeSample<I2CSymbol> I2CSample;
typedef CaptureChannel<I2CSymbol> I2CCapture;

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

virtual void Refresh();
virtual ChannelRenderer* CreateRenderer();
virtual bool NeedsConfig();

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

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

PROTOCOL_DECODER_INITPROC(I2CDecoder)

protected:
};

#endif
125 changes: 125 additions & 0 deletions scopeprotocols/I2CRenderer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/***********************************************************************************************************************
* *
* ANTIKERNEL v0.1 *
* *
* Copyright (c) 2012-2019 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 I2CRenderer
*/

#include "scopeprotocols.h"
#include "../scopehal/scopehal.h"
#include "../scopehal/ChannelRenderer.h"
#include "../scopehal/TextRenderer.h"
#include "I2CRenderer.h"

using namespace std;

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

I2CRenderer::I2CRenderer(OscilloscopeChannel* channel)
: TextRenderer(channel)
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Rendering

Gdk::Color I2CRenderer::GetColor(int i)
{
I2CCapture* capture = dynamic_cast<I2CCapture*>(m_channel->GetData());
if(capture != NULL)
{
const I2CSymbol& s = capture->m_samples[i].m_sample;

//errors are red
if(s.m_stype == I2CSymbol::TYPE_ERROR)
return Gdk::Color("#ff0000");

//addresses are yellow
else if(s.m_stype == I2CSymbol::TYPE_ADDRESS)
return Gdk::Color("#ffff00");

//control characters are purple
else if(s.m_stype != I2CSymbol::TYPE_DATA)
return Gdk::Color("#c000a0");

//Data characters are green
else
return Gdk::Color("#008000");
}

//error
return Gdk::Color("red");
}

string I2CRenderer::GetText(int i)
{
I2CCapture* capture = dynamic_cast<I2CCapture*>(m_channel->GetData());
if(capture != NULL)
{
const I2CSymbol& s = capture->m_samples[i].m_sample;

char tmp[32];
switch(s.m_stype)
{
case I2CSymbol::TYPE_NONE:
case I2CSymbol::TYPE_ERROR:
snprintf(tmp, sizeof(tmp), "ERR");
break;
case I2CSymbol::TYPE_START:
snprintf(tmp, sizeof(tmp), "START");
break;
case I2CSymbol::TYPE_RESTART:
snprintf(tmp, sizeof(tmp), "RESTART");
break;
case I2CSymbol::TYPE_STOP:
snprintf(tmp, sizeof(tmp), "STOP");
break;
case I2CSymbol::TYPE_ACK:
if(s.m_data)
snprintf(tmp, sizeof(tmp), "NAK");
else
snprintf(tmp, sizeof(tmp), "ACK");
break;
case I2CSymbol::TYPE_ADDRESS:
if(s.m_data & 1)
snprintf(tmp, sizeof(tmp), "R:%02x", s.m_data & 0xfe);
else
snprintf(tmp, sizeof(tmp), "W:%02x", s.m_data & 0xfe);
break;
case I2CSymbol::TYPE_DATA:
snprintf(tmp, sizeof(tmp), "%02x", s.m_data);
break;
}
return string(tmp);
}
return "";
}
54 changes: 54 additions & 0 deletions scopeprotocols/I2CRenderer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/***********************************************************************************************************************
* *
* ANTIKERNEL v0.1 *
* *
* Copyright (c) 2012-2019 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 I2CRenderer
*/

#ifndef I2CRenderer_h
#define I2CRenderer_h

#include "../scopehal/TextRenderer.h"

/**
@brief Renderer for an I2C channel
*/
class I2CRenderer : public TextRenderer
{
public:
I2CRenderer(OscilloscopeChannel* channel);

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

#endif
1 change: 1 addition & 0 deletions scopeprotocols/scopeprotocols.cpp
Original file line number Diff line number Diff line change
@@ -52,6 +52,7 @@ void ScopeProtocolStaticInit()
AddDecoderClass(EyeDecoder2);
AddDecoderClass(FFTDecoder);
AddDecoderClass(IBM8b10bDecoder);
AddDecoderClass(I2CDecoder);
AddDecoderClass(JtagDecoder);
AddDecoderClass(SincInterpolationDecoder);
AddDecoderClass(ThresholdDecoder);
1 change: 1 addition & 0 deletions scopeprotocols/scopeprotocols.h
Original file line number Diff line number Diff line change
@@ -52,6 +52,7 @@
#include "EyeDecoder2.h"
#include "FFTDecoder.h"
#include "IBM8b10bDecoder.h"
#include "I2CDecoder.h"
#include "JtagDecoder.h"
#include "SincInterpolationDecoder.h"
#include "ThresholdDecoder.h"