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

Commits on Feb 14, 2020

  1. Copy the full SHA
    ca00081 View commit details
  2. Copy the full SHA
    3ca0fd0 View commit details
2 changes: 2 additions & 0 deletions scopeprotocols/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@ set(SCOPEPROTOCOLS_SOURCES
ClockRecoveryDecoder.cpp
DCOffsetDecoder.cpp
DifferenceDecoder.cpp
DVIDecoder.cpp
DVIRenderer.cpp
Ethernet10BaseTDecoder.cpp
Ethernet100BaseTDecoder.cpp
EthernetAutonegotiationDecoder.cpp
241 changes: 241 additions & 0 deletions scopeprotocols/DVIDecoder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
/***********************************************************************************************************************
* *
* 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 DVIDecoder
*/

#include "../scopehal/scopehal.h"
#include "TMDSDecoder.h"
#include "../scopehal/ChannelRenderer.h"
#include "../scopehal/TextRenderer.h"
#include "DVIRenderer.h"
#include "DVIDecoder.h"

using namespace std;

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

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

m_signalNames.push_back("D1 (green)");
m_channels.push_back(NULL);

m_signalNames.push_back("D2 (red)");
m_channels.push_back(NULL);
}

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

bool DVIDecoder::NeedsConfig()
{
//channels have to be selected
return true;
}

ChannelRenderer* DVIDecoder::CreateRenderer()
{
return new DVIRenderer(this);
}

bool DVIDecoder::ValidateChannel(size_t i, OscilloscopeChannel* channel)
{
if( (i <= 2) && (dynamic_cast<TMDSDecoder*>(channel) != NULL ) )
return true;
return false;
}

string DVIDecoder::GetProtocolName()
{
return "DVI";
}

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

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

void DVIDecoder::Refresh()
{
//Get the input data
if( (m_channels[0] == NULL) || (m_channels[1] == NULL) || (m_channels[2] == NULL) )
{
SetData(NULL);
return;
}

TMDSCapture* dblue = dynamic_cast<TMDSCapture*>(m_channels[0]->GetData());
TMDSCapture* dgreen = dynamic_cast<TMDSCapture*>(m_channels[1]->GetData());
TMDSCapture* dred = dynamic_cast<TMDSCapture*>(m_channels[2]->GetData());
if( (dblue == NULL) || (dgreen == NULL) || (dred == NULL) )
{
SetData(NULL);
return;
}

//Create the capture
DVICapture* cap = new DVICapture;
cap->m_timescale = 1;
cap->m_startTimestamp = dblue->m_startTimestamp;
cap->m_startPicoseconds = dblue->m_startPicoseconds;

size_t iblue = 0;
size_t igreen = 0;
size_t ired = 0;

TMDSSymbol::TMDSType last_type = TMDSSymbol::TMDS_TYPE_ERROR;

//Decode the actual data
for(iblue = 0; (iblue < dblue->size()) && (igreen < dgreen->size()) && (ired < dred->size()); )
{
auto sblue = dblue->m_samples[iblue];

//Control code in master channel? Decode it
if(sblue.m_sample.m_type == TMDSSymbol::TMDS_TYPE_CONTROL)
{
//Extract synchronization signals from blue channel
//Red/green have status signals that aren't used in DVI.
bool hsync = (sblue.m_sample.m_data & 1) ? true : false;
bool vsync = (sblue.m_sample.m_data & 2) ? true : false;

//If this symbol matches the previous one, just extend it
//rather than creating a new symbol
if( (cap->m_samples.size() > 0) && (dblue->m_samples[iblue-1].m_sample == sblue.m_sample) )
{
auto& last_sample = cap->m_samples[cap->m_samples.size()-1];
last_sample.m_duration = sblue.m_offset + sblue.m_duration - last_sample.m_offset;
}

else if(vsync)
{
cap->m_samples.push_back(DVISample(
sblue.m_offset, sblue.m_duration,
DVISymbol(DVISymbol::DVI_TYPE_VSYNC)));
}

else if(hsync)
{
cap->m_samples.push_back(DVISample(
sblue.m_offset, sblue.m_duration,
DVISymbol(DVISymbol::DVI_TYPE_HSYNC)));
}

else
{
cap->m_samples.push_back(DVISample(
sblue.m_offset, sblue.m_duration,
DVISymbol(DVISymbol::DVI_TYPE_PREAMBLE)));
}
}

//Data? Decode it
else if(sblue.m_sample.m_type == TMDSSymbol::TMDS_TYPE_DATA)
{
//If the LAST sample was a control symbol, re-synchronize the three lanes
//to compensate for lane-to-lane clock skew.
//Should only be needed at the start of the capture, but can't hurt to re-do it in case of some
//weird clock domain crossing issues in the transmitter causing idle insertion/removal.
if(last_type == TMDSSymbol::TMDS_TYPE_CONTROL)
{
//Align green
for(ssize_t delta=-50; delta <= 50; delta ++)
{
size_t ngreen = delta + igreen;
if(ngreen < 1)
continue;
if(ngreen >= dgreen->size())
continue;
if(dgreen->m_samples[ngreen-1].m_sample.m_type != TMDSSymbol::TMDS_TYPE_CONTROL)
continue;
if(dgreen->m_samples[ngreen].m_sample.m_type != TMDSSymbol::TMDS_TYPE_DATA)
continue;

igreen += delta;
break;
}

//Align red
for(ssize_t delta= -50; delta <= 50; delta ++)
{
size_t nred = delta + ired;
if(nred < 1)
continue;
if(nred >= dred->size())
continue;
if(dred->m_samples[nred-1].m_sample.m_type != TMDSSymbol::TMDS_TYPE_CONTROL)
continue;
if(dred->m_samples[nred].m_sample.m_type != TMDSSymbol::TMDS_TYPE_DATA)
continue;

ired += delta;
break;
}
}

auto sgreen = dgreen->m_samples[igreen];
auto sred = dred->m_samples[ired];

cap->m_samples.push_back(DVISample(
sblue.m_offset, sblue.m_duration,
DVISymbol(DVISymbol::DVI_TYPE_VIDEO,
sred.m_sample.m_data,
sgreen.m_sample.m_data,
sblue.m_sample.m_data)));
}

//Save the previous type of sample
last_type = sblue.m_sample.m_type;

//Default to incrementing all channels
iblue ++;
igreen ++;
ired ++;
}

SetData(cap);
}
93 changes: 93 additions & 0 deletions scopeprotocols/DVIDecoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/***********************************************************************************************************************
* *
* 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 DVIDecoder
*/

#ifndef DVIDecoder_h
#define DVIDecoder_h

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

class DVISymbol
{
public:
enum DVIType
{
DVI_TYPE_PREAMBLE,
DVI_TYPE_HSYNC,
DVI_TYPE_VSYNC,
DVI_TYPE_VIDEO,
DVI_TYPE_ERROR
};

DVISymbol(DVIType type, uint8_t r = 0, uint8_t g = 0, uint8_t b = 0)
: m_type(type)
, m_red(r)
, m_green(g)
, m_blue(b)
{}

DVIType m_type;
uint8_t m_red;
uint8_t m_green;
uint8_t m_blue;

bool operator== (const DVISymbol& s) const
{
return (m_type == s.m_type) && (m_red == s.m_red) && (m_green == s.m_green) && (m_blue == s.m_blue);
}
};

typedef OscilloscopeSample<DVISymbol> DVISample;
typedef CaptureChannel<DVISymbol> DVICapture;

class DVIDecoder : public ProtocolDecoder
{
public:
DVIDecoder(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(DVIDecoder)

protected:
};

#endif
Loading