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

Commits on Jun 29, 2020

  1. Initial implementation of conditional halting. Right now only support…

    …s string matching on protocol decodes, but easily extensible. Fixes #123.
    azonenberg committed Jun 29, 2020
    Copy the full SHA
    5801996 View commit details
Showing with 246 additions and 7 deletions.
  1. +3 −2 glscopeclient/CMakeLists.txt
  2. +149 −0 glscopeclient/HaltConditionsDialog.cpp
  3. +64 −0 glscopeclient/HaltConditionsDialog.h
  4. +24 −5 glscopeclient/OscilloscopeWindow.cpp
  5. +6 −0 glscopeclient/OscilloscopeWindow.h
5 changes: 3 additions & 2 deletions glscopeclient/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -5,9 +5,9 @@ find_package(OpenGL REQUIRED)
# Additional libraries on Windows
if(WIN32)
set(WIN_LIBS shlwapi)

# For some reason, find_package does not manage to find glew32 on Windows. Hardcoding for now.
set(GLEW_LIBRARIES "glew32")
set(GLEW_LIBRARIES "glew32")
endif()

#Set up include paths
@@ -19,6 +19,7 @@ link_directories(${GTKMM_LIBRARY_DIRS} ${SIGCXX_LIBRARY_DIRS})
add_executable(glscopeclient
ChannelPropertiesDialog.cpp
Framebuffer.cpp
HaltConditionsDialog.cpp
HistoryWindow.cpp
InstrumentConnectionDialog.cpp
OscilloscopeWindow.cpp
149 changes: 149 additions & 0 deletions glscopeclient/HaltConditionsDialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/***********************************************************************************************************************
* *
* 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 HaltConditionsDialog
*/
#include "glscopeclient.h"
#include "OscilloscopeWindow.h"
#include "HaltConditionsDialog.h"

using namespace std;

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

HaltConditionsDialog::HaltConditionsDialog(
OscilloscopeWindow* parent)
: Gtk::Dialog("Halt Conditions", *parent)
, m_parent(parent)
{
char buf[128];

get_vbox()->pack_start(m_grid, Gtk::PACK_EXPAND_WIDGET);
m_grid.attach(m_haltEnabledButton, 0, 0, 1, 1);
m_haltEnabledButton.set_label("Halt Enabled");

m_grid.attach_next_to(m_channelNameLabel, m_haltEnabledButton, Gtk::POS_BOTTOM, 1, 1);
m_channelNameLabel.set_label("Halt when");
m_grid.attach_next_to(m_channelNameBox, m_channelNameLabel, Gtk::POS_RIGHT, 1, 1);
m_grid.attach_next_to(m_operatorBox, m_channelNameBox, Gtk::POS_RIGHT, 1, 1);
m_operatorBox.append("==");
m_operatorBox.append("!=");
m_grid.attach_next_to(m_targetEntry, m_operatorBox, Gtk::POS_RIGHT, 1, 1);

show_all();
}

HaltConditionsDialog::~HaltConditionsDialog()
{

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Event handlers

void HaltConditionsDialog::RefreshChannels()
{
//TODO: save previous state

m_channelNameBox.remove_all();
m_chanptrs.clear();

//Populate channel list
/*
for(size_t j=0; j<m_parent->GetScopeCount(); j++)
{
auto scope = m_parent->GetScope(j);
for(size_t k=0; k<scope->GetChannelCount(); k++)
{
auto c = scope->GetChannel(k);
m_channelNameBox.append(c->m_displayname);
m_chanptrs[c->m_displayname] = c;
}
}
*/

//For now, only allow conditional triggering on complex decodes
auto decodes = ProtocolDecoder::EnumDecodes();
for(auto d : decodes)
{
if(d->GetType() != OscilloscopeChannel::CHANNEL_TYPE_COMPLEX)
continue;
m_channelNameBox.append(d->m_displayname);
m_chanptrs[d->m_displayname] = d;
}
}

/**
@brief Check if we should halt the trigger
*/
bool HaltConditionsDialog::ShouldHalt()
{
//If conditional halt is not enabled, no sense checking conditions
if(!m_haltEnabledButton.get_active())
return false;

//Get the channel we're looking at
auto chan = m_chanptrs[m_channelNameBox.get_active_text()];
auto decode = dynamic_cast<ProtocolDecoder*>(chan);
if(decode == NULL)
return false;

//Don't check if no data to look at
auto data = decode->GetData();
if(data->m_offsets.empty())
return false;

//TODO: support more than just == / !=
bool match_equal = (m_operatorBox.get_active_text() == "==");

//Loop over the decode and see if anything matches
size_t len = data->m_offsets.size();
auto text = m_targetEntry.get_text();
for(size_t i=0; i<len; i++)
{
auto target = decode->GetText(i);
if(match_equal)
{
if(target == text)
return true;
}
else
{
if(target != text)
return true;
}
}

return false;
}
64 changes: 64 additions & 0 deletions glscopeclient/HaltConditionsDialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/***********************************************************************************************************************
* *
* 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 Dialog for configuring channel properties
*/

#ifndef HaltConditionsDialog_h
#define HaltConditionsDialog_h

/**
@brief Dialog for configuring halt conditions
*/
class HaltConditionsDialog : public Gtk::Dialog
{
public:
HaltConditionsDialog(OscilloscopeWindow* parent);
virtual ~HaltConditionsDialog();

void RefreshChannels();

bool ShouldHalt();

protected:
Gtk::Grid m_grid;
Gtk::CheckButton m_haltEnabledButton;
Gtk::Label m_channelNameLabel;
Gtk::ComboBoxText m_channelNameBox;
Gtk::ComboBoxText m_operatorBox;
Gtk::Entry m_targetEntry;

OscilloscopeWindow* m_parent;
std::map<std::string, OscilloscopeChannel*> m_chanptrs;
};

#endif
29 changes: 24 additions & 5 deletions glscopeclient/OscilloscopeWindow.cpp
Original file line number Diff line number Diff line change
@@ -61,6 +61,7 @@ OscilloscopeWindow::OscilloscopeWindow(vector<Oscilloscope*> scopes, bool nodigi
, m_fullscreen(false)
, m_multiScopeFreeRun(false)
, m_scopeSyncWizard(NULL)
, m_haltConditionsDialog(this)
{
SetTitle();

@@ -189,6 +190,10 @@ void OscilloscopeWindow::CreateWidgets(bool nodigital)
m_setupMenu.append(m_setupTriggerMenuItem);
m_setupTriggerMenuItem.set_label("Trigger");
m_setupTriggerMenuItem.set_submenu(m_setupTriggerMenu);
m_setupMenu.append(m_setupHaltMenuItem);
m_setupHaltMenuItem.set_label("Halt Conditions...");
m_setupHaltMenuItem.signal_activate().connect(
sigc::mem_fun(*this, &OscilloscopeWindow::OnHaltConditions));
m_menu.append(m_viewMenuItem);
m_viewMenuItem.set_label("View");
m_viewMenuItem.set_submenu(m_viewMenu);
@@ -366,6 +371,7 @@ void OscilloscopeWindow::CreateWidgets(bool nodigital)

//Don't show measurements or wizards by default
group->m_measurementView.hide();
m_haltConditionsDialog.hide();

//Initialize the style sheets
m_css = Gtk::CssProvider::create();
@@ -1106,7 +1112,7 @@ void OscilloscopeWindow::OnFileSave(bool saveToCurrentFile, bool saveLayout, boo

//See if the directory exists
bool dir_exists = false;

#ifndef _WIN32
int hfile = open(m_currentDataDirName.c_str(), O_RDONLY);
if(hfile >= 0)
@@ -1134,7 +1140,7 @@ void OscilloscopeWindow::OnFileSave(bool saveToCurrentFile, bool saveLayout, boo
}
#else
auto fileType = GetFileAttributes(m_currentDataDirName.c_str());

// Check if any file exists at this path
if(fileType != INVALID_FILE_ATTRIBUTES)
{
@@ -1157,7 +1163,7 @@ void OscilloscopeWindow::OnFileSave(bool saveToCurrentFile, bool saveLayout, boo

//See if the file exists
bool file_exists = false;

#ifndef _WIN32
hfile = open(m_currentFileName.c_str(), O_RDONLY);
if(hfile >= 0)
@@ -1172,7 +1178,7 @@ void OscilloscopeWindow::OnFileSave(bool saveToCurrentFile, bool saveLayout, boo
&& !(fileAttr & FILE_ATTRIBUTE_DIRECTORY));

#endif


//If we are trying to create a new file, warn if the directory exists but the file does not
//If the file exists GTK will warn, and we don't want to prompt the user twice if both exist!
@@ -1194,7 +1200,7 @@ void OscilloscopeWindow::OnFileSave(bool saveToCurrentFile, bool saveLayout, boo
#else
auto result = mkdir(m_currentDataDirName.c_str(), 0755);
#endif

if(0 != result)
{
string msg = string("The data directory ") + m_currentDataDirName + " could not be created!";
@@ -1988,6 +1994,10 @@ void OscilloscopeWindow::OnAllWaveformsUpdated()
//Update the trigger sync wizard, if it's active
if(m_scopeSyncWizard && m_scopeSyncWizard->is_visible())
m_scopeSyncWizard->OnWaveformDataReady();

//Check if a conditional halt applies
if(m_haltConditionsDialog.ShouldHalt())
OnStop();
}

void OscilloscopeWindow::RefreshAllDecoders()
@@ -2206,3 +2216,12 @@ void OscilloscopeWindow::OnSyncComplete()
{
m_syncComplete = true;
}

/**
@brief Shows the halt conditions dialog
*/
void OscilloscopeWindow::OnHaltConditions()
{
m_haltConditionsDialog.show();
m_haltConditionsDialog.RefreshChannels();
}
6 changes: 6 additions & 0 deletions glscopeclient/OscilloscopeWindow.h
Original file line number Diff line number Diff line change
@@ -42,6 +42,7 @@
#include "ProtocolAnalyzerWindow.h"
#include "HistoryWindow.h"
#include "ScopeSyncWizard.h"
#include "HaltConditionsDialog.h"

/**
@brief Main application window class for an oscilloscope
@@ -143,6 +144,7 @@ class OscilloscopeWindow : public Gtk::Window
Gtk::MenuItem m_setupSyncMenuItem;
Gtk::MenuItem m_setupTriggerMenuItem;
Gtk::Menu m_setupTriggerMenu;
Gtk::MenuItem m_setupHaltMenuItem;
Gtk::MenuItem m_channelsMenuItem;
Gtk::Menu m_channelsMenu;
Gtk::MenuItem m_viewMenuItem;
@@ -206,6 +208,7 @@ class OscilloscopeWindow : public Gtk::Window
void OnClearSweeps();
void OnTimebaseSettings();
void OnScopeSync();
void OnHaltConditions();

//Protocol decoding etc
void RefreshAllDecoders();
@@ -262,6 +265,9 @@ class OscilloscopeWindow : public Gtk::Window
//Instrument sync wizard
ScopeSyncWizard* m_scopeSyncWizard;
bool m_syncComplete;

//Conditional halting
HaltConditionsDialog m_haltConditionsDialog;
};

#endif