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

Commits on Dec 13, 2019

  1. Copy the full SHA
    f56e4f8 View commit details
  2. Copy the full SHA
    4d1ac6f View commit details
26 changes: 24 additions & 2 deletions scopehal/ProtocolDecoder.cpp
Original file line number Diff line number Diff line change
@@ -54,6 +54,14 @@ void ProtocolDecoderParameter::ParseString(string str)
{
switch(m_type)
{
case TYPE_BOOL:
m_filename = "";
if( (str == "1") || (str == "true") )
m_intval = 1;
else
m_intval = 0;
m_floatval = m_intval;
break;
case TYPE_FLOAT:
sscanf(str.c_str(), "%20f", &m_floatval);
m_intval = m_floatval;
@@ -80,6 +88,7 @@ string ProtocolDecoderParameter::ToString()
case TYPE_FLOAT:
snprintf(str_out, sizeof(str_out), "%f", m_floatval);
break;
case TYPE_BOOL:
case TYPE_INT:
snprintf(str_out, sizeof(str_out), "%d", m_intval);
break;
@@ -328,7 +337,14 @@ void ProtocolDecoder::SampleOnRisingEdges(DigitalCapture* data, DigitalCapture*
if(ndata >= data->m_samples.size())
break;

//TODO: should we specify duration here?
//Extend the previous sample's duration (if any) to our start
if(samples.size())
{
auto& s = samples[samples.size() - 1];
s.m_duration = clkstart - s.m_offset;
}

//Add the new sample
samples.push_back(DigitalSample(clkstart, 1, data->m_samples[ndata].m_sample));
}
}
@@ -364,7 +380,13 @@ void ProtocolDecoder::SampleOnFallingEdges(DigitalCapture* data, DigitalCapture*
if(ndata >= data->m_samples.size())
break;

//TODO: should we specify duration here?
//Extend the previous sample's duration (if any) to our start
if(samples.size())
{
auto& s = samples[samples.size() - 1];
s.m_duration = clkstart - s.m_offset;
}

samples.push_back(DigitalSample(clkstart, 1, data->m_samples[ndata].m_sample));
}
}
2 changes: 2 additions & 0 deletions scopeprotocols/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -22,6 +22,8 @@ set(SCOPEPROTOCOLS_SOURCES
IBM8b10bRenderer.cpp
JtagDecoder.cpp
JtagRenderer.cpp
MDIODecoder.cpp
MDIORenderer.cpp
SincInterpolationDecoder.cpp
ThresholdDecoder.cpp
UARTDecoder.cpp
2 changes: 1 addition & 1 deletion scopeprotocols/FFTDecoder.cpp
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@
#include "../scopehal/scopehal.h"
#include "FFTDecoder.h"
#include "../scopehal/AnalogRenderer.h"
#include <ffts.h>
#include <ffts/ffts.h>

using namespace std;

280 changes: 280 additions & 0 deletions scopeprotocols/MDIODecoder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
/***********************************************************************************************************************
* *
* 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 MDIODecoder
*/

#include "../scopehal/scopehal.h"
#include "../scopehal/ChannelRenderer.h"
#include "../scopehal/TextRenderer.h"
#include "MDIORenderer.h"
#include "MDIODecoder.h"

using namespace std;

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

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

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

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

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

ChannelRenderer* MDIODecoder::CreateRenderer()
{
return new MDIORenderer(this);
}

bool MDIODecoder::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 MDIODecoder::GetProtocolName()
{
return "MDIO";
}

void MDIODecoder::SetDefaultName()
{
char hwname[256];
snprintf(hwname, sizeof(hwname), "MDIO(%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 MDIODecoder::Refresh()
{
//Get the input data
if( (m_channels[0] == NULL) || (m_channels[1] == NULL) )
{
SetData(NULL);
return;
}
DigitalCapture* mdio = dynamic_cast<DigitalCapture*>(m_channels[0]->GetData());
DigitalCapture* mdc = dynamic_cast<DigitalCapture*>(m_channels[1]->GetData());
if( (mdio == NULL) || (mdc == NULL) )
{
SetData(NULL);
return;
}

//Create the capture
MDIOCapture* cap = new MDIOCapture;
cap->m_timescale = 1; //SampleOnRisingEdges() gives us ps level timestamps
cap->m_startTimestamp = mdc->m_startTimestamp;
cap->m_startPicoseconds = mdc->m_startPicoseconds;

//Sample the data stream at each clock edge
vector<DigitalSample> dmdio;
SampleOnRisingEdges(mdio, mdc, dmdio);
for(size_t i=0; i<dmdio.size(); i++)
{
//Start by looking for a preamble
size_t start = dmdio[i].m_offset;
bool err = false;
size_t len = 0;
for(size_t j=0; j<32; j++)
{
len = (dmdio[i+j].m_offset - start) + dmdio[i+j].m_duration;

//Abort if we don't have space for a whole frame
if(i+j+1 == dmdio.size())
{
err = true;
break;
}

//Expect 32 "1" bits in a row. If we see any non-1 bits, declare an error
if(dmdio[i+j].m_sample != true)
{
err = true;
break;
}
}
i += 32;

//If we don't have a valid preamble, stop
if(err)
{
cap->m_samples.push_back(MDIOSample(
start,
len,
MDIOSymbol(MDIOSymbol::TYPE_ERROR, 0)));
continue;
}

//Good preamble
cap->m_samples.push_back(MDIOSample(
start,
len,
MDIOSymbol(MDIOSymbol::TYPE_PREAMBLE, 0)));

//TODO: safely ignore extra preamble bits

//Next 2 bits are start delimiter
if(i+2 >= dmdio.size())
break;
uint16_t sof = 0;
if(dmdio[i].m_sample)
sof |= 2;
if(dmdio[i+1].m_sample)
sof |= 1;

//MDIO Clause 22 frame
if(sof == 0x01)
{
//Add the start symbol
cap->m_samples.push_back(MDIOSample(
dmdio[i].m_offset,
(dmdio[i+1].m_offset - dmdio[i].m_offset) + dmdio[i+1].m_duration,
MDIOSymbol(MDIOSymbol::TYPE_START, sof)));
i += 2;

//Next 2 bits are opcode
if(i+2 >= dmdio.size())
break;
uint16_t op = 0;
if(dmdio[i].m_sample)
op |= 2;
if(dmdio[i+1].m_sample)
op |= 1;

cap->m_samples.push_back(MDIOSample(
dmdio[i].m_offset,
(dmdio[i+1].m_offset - dmdio[i].m_offset) + dmdio[i+1].m_duration,
MDIOSymbol(MDIOSymbol::TYPE_OP, op)));
i += 2;

//Next 5 bits are PHY address
if(i+5 >= dmdio.size())
break;
uint16_t addr = 0;
start = dmdio[i].m_offset;
for(size_t j=0; j<5; j++)
{
len = (dmdio[i+j].m_offset - start) + dmdio[i+j].m_duration;
addr <<= 1;
if(dmdio[i+j].m_sample)
addr |= 1;
}
cap->m_samples.push_back(MDIOSample(
start,
len,
MDIOSymbol(MDIOSymbol::TYPE_PHYADDR, addr)));
i += 5;

//Next 5 bits are reg address
if(i+5 >= dmdio.size())
break;
addr = 0;
start = dmdio[i].m_offset;
for(size_t j=0; j<5; j++)
{
len = (dmdio[i+j].m_offset - start) + dmdio[i+j].m_duration;
addr <<= 1;
if(dmdio[i+j].m_sample)
addr |= 1;
}
cap->m_samples.push_back(MDIOSample(
start,
len,
MDIOSymbol(MDIOSymbol::TYPE_REGADDR, addr)));
i += 5;

//Next 2 bits are bus turnaround
if(i+2 >= dmdio.size())
break;
cap->m_samples.push_back(MDIOSample(
dmdio[i].m_offset,
(dmdio[i+1].m_offset - dmdio[i].m_offset) + dmdio[i+1].m_duration,
MDIOSymbol(MDIOSymbol::TYPE_TURN, 0)));
i += 2;

//Next 16 bits are frame data
if(i+16 >= dmdio.size())
break;
uint16_t value = 0;
start = dmdio[i].m_offset;
for(size_t j=0; j<16; j++)
{
len = (dmdio[i+j].m_offset - start) + dmdio[i+j].m_duration;
value <<= 1;
if(dmdio[i+j].m_sample)
value |= 1;
}
cap->m_samples.push_back(MDIOSample(
start,
len,
MDIOSymbol(MDIOSymbol::TYPE_DATA, value)));
i += 16;
}

//MDIO Clause 45 frame
else if(sof == 0x00)
{
LogWarning("MDIO Clause 45 not yet supported");
}

//Invalid frame format
else
{
cap->m_samples.push_back(MDIOSample(
dmdio[i].m_offset,
(dmdio[i+1].m_offset - dmdio[i].m_offset) + dmdio[i+1].m_duration,
MDIOSymbol(MDIOSymbol::TYPE_ERROR, 0)));
}
}

SetData(cap);
}
Loading