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

Commits on Aug 5, 2020

  1. Initial work on eye mask testing. Can load eye mask files and display…

    … them, but not check for collisions. See #56.
    azonenberg committed Aug 5, 2020
    Copy the full SHA
    f3be005 View commit details
Showing with 340 additions and 3 deletions.
  1. +21 −1 scopehal/ProtocolDecoder.cpp
  2. +1 −0 scopeprotocols/CMakeLists.txt
  3. +11 −0 scopeprotocols/EyeDecoder2.cpp
  4. +9 −2 scopeprotocols/EyeDecoder2.h
  5. +184 −0 scopeprotocols/EyeMask.cpp
  6. +114 −0 scopeprotocols/EyeMask.h
22 changes: 21 additions & 1 deletion scopehal/ProtocolDecoder.cpp
Original file line number Diff line number Diff line change
@@ -791,7 +791,27 @@ string ProtocolDecoder::SerializeConfiguration(IDTable& table)
config += tmp;
for(auto it : m_parameters)
{
snprintf(tmp, sizeof(tmp), " %-20s %s\n", (it.first+":").c_str(), it.second.ToString().c_str());
switch(it.second.GetType())
{
case ProtocolDecoderParameter::TYPE_FLOAT:
case ProtocolDecoderParameter::TYPE_INT:
case ProtocolDecoderParameter::TYPE_BOOL:
snprintf(
tmp,
sizeof(tmp),
" %-20s %s\n", (it.first+":").c_str(), it.second.ToString().c_str());
break;

case ProtocolDecoderParameter::TYPE_FILENAME:
case ProtocolDecoderParameter::TYPE_FILENAMES:
default:
snprintf(
tmp,
sizeof(tmp),
" %-20s \"%s\"\n", (it.first+":").c_str(), it.second.ToString().c_str());
break;
}

config += tmp;
}

1 change: 1 addition & 0 deletions scopeprotocols/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -30,6 +30,7 @@ set(SCOPEPROTOCOLS_SOURCES
EthernetProtocolDecoder.cpp
EyeBitRateMeasurementDecoder.cpp
EyeDecoder2.cpp
EyeMask.cpp
EyeHeightMeasurementDecoder.cpp
EyeJitterMeasurementDecoder.cpp
EyePeriodMeasurementDecoder.cpp
11 changes: 11 additions & 0 deletions scopeprotocols/EyeDecoder2.cpp
Original file line number Diff line number Diff line change
@@ -108,6 +108,12 @@ EyeDecoder2::EyeDecoder2(string color)
m_centerName = "Center Voltage";
m_parameters[m_centerName] = ProtocolDecoderParameter(ProtocolDecoderParameter::TYPE_FLOAT);
m_parameters[m_centerName].SetFloatVal(0);

m_maskName = "Mask";
m_parameters[m_maskName] = ProtocolDecoderParameter(ProtocolDecoderParameter::TYPE_FILENAME);
m_parameters[m_maskName].SetFileName("");
m_parameters[m_maskName].m_fileFilterMask = "*.yml";
m_parameters[m_maskName].m_fileFilterName = "YAML files (*.yml)";
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -364,6 +370,11 @@ void EyeDecoder2::Refresh()
}
}

//Load the mask, if needed
string maskpath = m_parameters[m_maskName].GetFileName();
if(maskpath != m_mask.GetFileName())
m_mask.Load(maskpath);

//Initialize the capture
//TODO: timestamps? do we need those?
if(cap == NULL)
11 changes: 9 additions & 2 deletions scopeprotocols/EyeDecoder2.h
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@
#define EyeDecoder2_h

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

class EyeWaveform : public WaveformBase
{
@@ -117,12 +118,15 @@ class EyeDecoder2 : public ProtocolDecoder
SetData(NULL);
}

size_t GetWidth()
size_t GetWidth() const
{ return m_width; }

size_t GetHeight()
size_t GetHeight() const
{ return m_height; }

const EyeMask& GetMask() const
{ return m_mask; }

PROTOCOL_DECODER_INITPROC(EyeDecoder2)

protected:
@@ -132,6 +136,9 @@ class EyeDecoder2 : public ProtocolDecoder

std::string m_saturationName;
std::string m_centerName;
std::string m_maskName;

EyeMask m_mask;
};

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

#include "scopeprotocols.h"
#include "EyeMask.h"

using namespace std;

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

EyeMask::EyeMask()
: m_hitrate(0)
, m_timebaseIsRelative(false)
{
}

EyeMask::~EyeMask()
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Mask file parsing

bool EyeMask::Load(string path)
{
try
{
m_fname = path;
auto docs = YAML::LoadAllFromFile(path);
if(!Load(docs[0]))
return false;
}
catch(const YAML::BadFile& ex)
{
return false;
}

return true;
}

/**
@brief Loads the YAML file
*/
bool EyeMask::Load(const YAML::Node& node)
{
//Clear out any previous state
m_polygons.clear();
m_hitrate = 0;
m_timebaseIsRelative = false;
m_maskname = "";

//Load protocol section
auto proto = node["protocol"];
for(auto it : proto)
{
auto name = it.first.as<string>();
if(name == "name")
m_maskname = it.second.as<string>();
}

//For now, ignore display limits

//Load units
auto units = node["units"];
float yscale = 1;
for(auto it : units)
{
auto name = it.first.as<string>();
if(name == "xscale")
{
auto scale = it.second.as<string>();
if(scale == "ui")
m_timebaseIsRelative = true;
else if(scale == "ps")
m_timebaseIsRelative = false;
else
LogError("Unrecognized xscale \"%s\"\n", scale.c_str());
}
if(name == "yscale")
{
auto scale = it.second.as<string>();
if(scale == "mv")
yscale = 0.001f;
else if(scale == "v")
yscale = 0.001f;
else
LogError("Unrecognized yscale \"%s\"\n", scale.c_str());
}
}

//Load pass conditions
auto conditions = node["conditions"];
for(auto it : conditions)
{
auto name = it.first.as<string>();
if(name == "hitrate")
m_hitrate = it.second.as<float>();
}

//Load actual mask polygons
auto mask = node["mask"];
for(auto p : mask)
{
EyeMaskPolygon poly;

auto points = p["points"];
for(auto v : points)
poly.m_points.push_back(EyeMaskPoint(v["x"].as<float>(), v["y"].as<float>() * yscale));

m_polygons.push_back(poly);
}

return true;
}

void EyeMask::RenderForDisplay(
Cairo::RefPtr<Cairo::Context> cr,
EyeWaveform* waveform,
float xscale,
float xoff,
float yscale,
float yoff,
float height) const
{
//Color is hard coded for now
cr->set_source_rgba(0, 0, 1, 0.75);

//Draw each polygon
for(auto poly : m_polygons)
{
for(size_t i=0; i<poly.m_points.size(); i++)
{
auto point = poly.m_points[i];

//Convert from ps to UI if needed
float time = point.m_time;
if(m_timebaseIsRelative)
time *= waveform->GetUIWidth();

float x = (time - xoff) * xscale;

float y = height/2 - ( (point.m_voltage + yoff) * yscale );

if(i == 0)
cr->move_to(x, y);
else
cr->line_to(x, y);
}
cr->fill();
}
}
114 changes: 114 additions & 0 deletions scopeprotocols/EyeMask.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/***********************************************************************************************************************
* *
* 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 EyeMask, EyeMaskPoint, and EyeMaskPolygon
*/
#ifndef EyeMask_h
#define EyeMask_h

class EyeDecoder2;
class EyeWaveform;

/**
@brief A single point within an EyeMaskPolygon
*/
class EyeMaskPoint
{
public:
EyeMaskPoint()
{}

EyeMaskPoint(float t, float v)
: m_time(t)
, m_voltage(v)
{}

float m_time; //either ps or UIs, depending on EyeMask units
float m_voltage; //volts
};

/**
@brief A single polygon within an EyeMask
*/
class EyeMaskPolygon
{
public:
std::vector<EyeMaskPoint> m_points;
};

/**
@brief A mask used for checking eye patterns
*/
class EyeMask
{
public:
EyeMask();
virtual ~EyeMask();

bool Load(std::string path);
bool Load(const YAML::Node& node);

std::string GetFileName() const
{ return m_fname; }

std::string GetMaskName() const
{ return m_maskname; }

float GetAllowedHitRate() const
{ return m_hitrate; }

void RenderForDisplay(
Cairo::RefPtr<Cairo::Context> cr,
EyeWaveform* waveform,
float xscale,
float xoff,
float yscale,
float yoff,
float height) const;

//TODO: function to render to boolean bitmap
//TODO: function to render to nice pretty cairo bitmap

protected:
std::string m_fname;
std::vector<EyeMaskPolygon> m_polygons;

float m_hitrate;

//true = time measured in UIs
//false = time measured in ps
bool m_timebaseIsRelative;

std::string m_maskname;
};

#endif