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: 585ac7de61de
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: 83e8a0e5c299
Choose a head ref
  • 3 commits
  • 6 files changed
  • 1 contributor

Commits on May 12, 2020

  1. Copy the full SHA
    6ccc407 View commit details
  2. Copy the full SHA
    6528cf5 View commit details
  3. Protocol decoder dialog no longer blocks background waveform processi…

    …ng and rendering while displayed. Fixes #91.
    azonenberg committed May 12, 2020
    Copy the full SHA
    83e8a0e View commit details
7 changes: 6 additions & 1 deletion glscopeclient/OscilloscopeWindow.cpp
Original file line number Diff line number Diff line change
@@ -1489,6 +1489,11 @@ void OscilloscopeWindow::GarbageCollectGroups()
g->m_measurementFrame.hide();
else
g->m_measurementFrame.show_all();

if(g->m_columnToIndexMap.empty())
g->m_newMeasurementFrame.hide();
else
g->m_newMeasurementFrame.show_all();
}
}

@@ -1704,8 +1709,8 @@ void OscilloscopeWindow::OnWaveformDataReady(Oscilloscope* scope)
a->OnWaveformDataReady();

//Update the history window
start = GetTime();
m_historyWindows[scope]->OnWaveformDataReady();

m_tHistory += GetTime() - start;
}

3 changes: 3 additions & 0 deletions glscopeclient/ProtocolDecoderDialog.cpp
Original file line number Diff line number Diff line change
@@ -49,6 +49,9 @@ ProtocolDecoderDialog::ProtocolDecoderDialog(
add_button("OK", Gtk::RESPONSE_OK);
add_button("Cancel", Gtk::RESPONSE_CANCEL);

//hide close button to force user to pick OK or cancel
set_deletable(false);

get_vbox()->pack_start(m_channelDisplayNameBox, Gtk::PACK_SHRINK);
m_channelDisplayNameBox.pack_start(m_channelDisplayNameLabel, Gtk::PACK_SHRINK);
m_channelDisplayNameLabel.set_text("Display name");
15 changes: 15 additions & 0 deletions glscopeclient/WaveformArea.cpp
Original file line number Diff line number Diff line change
@@ -90,6 +90,9 @@ void WaveformArea::SharedCtorInit()
m_firstFrame = false;
m_waveformRenderData = NULL;

m_decodeDialog = NULL;
m_pendingDecode = NULL;

//Configure the OpenGL context we want
//TODO: it looks like OpenGL ES 3.1 can do everything we need
//Do we want to support this for running on embedded ARM GPUs etc eventually?
@@ -148,6 +151,11 @@ WaveformArea::~WaveformArea()
OnRemoveOverlay(d);
m_overlays.clear();

if(m_decodeDialog)
delete m_decodeDialog;
if(m_pendingDecode)
delete m_pendingDecode;

for(auto m : m_moveExistingGroupItems)
{
m_moveMenu.remove(*m);
@@ -704,6 +712,13 @@ bool WaveformArea::IsEye()
return (eye != NULL);
}

bool WaveformArea::IsEyeOrBathtub()
{
//TODO: this should really be "is fixed two UI wide plot"
auto bath = dynamic_cast<HorizontalBathtubDecoder*>(m_channel);
return IsEye() || (bath != NULL);
}

bool WaveformArea::IsFFT()
{
return (m_channel->GetYAxisUnits().GetType() == Unit::UNIT_DB);
12 changes: 11 additions & 1 deletion glscopeclient/WaveformArea.h
Original file line number Diff line number Diff line change
@@ -36,6 +36,7 @@
#define WaveformArea_h

#include "WaveformGroup.h"
#include "ProtocolDecoderDialog.h"

/**
@brief Slightly more capable rectangle class
@@ -133,6 +134,7 @@ class WaveformArea : public Gtk::GLArea
bool IsAnalog();
bool IsDigital();
bool IsEye();
bool IsEyeOrBathtub();
bool IsWaterfall();
bool IsFFT();
bool IsTime();
@@ -247,7 +249,7 @@ class WaveformArea : public Gtk::GLArea
bool m_updatingContextMenu;
void OnHide();
void OnTogglePersistence();
void OnProtocolDecode(std::string name);

void OnMeasure(std::string name);
void OnTriggerMode(Oscilloscope::TriggerType type, Gtk::RadioMenuItem* item);
void OnBandwidthLimit(int mhz, Gtk::RadioMenuItem* item);
@@ -262,6 +264,14 @@ class WaveformArea : public Gtk::GLArea

void RefreshMeasurements();

//Pending protocol decodes
void OnProtocolDecode(std::string name);
ProtocolDecoderDialog* m_decodeDialog;
ProtocolDecoder* m_pendingDecode;
void OnDecodeDialogResponse(int response);
void OnDecodeReconfigureDialogResponse(int response);
void OnDecodeSetupComplete();

int m_width;
int m_height;

4 changes: 1 addition & 3 deletions glscopeclient/WaveformArea_cairo.cpp
Original file line number Diff line number Diff line change
@@ -39,8 +39,6 @@
#include <random>
#include <map>
#include "ProfileBlock.h"
#include "../../lib/scopeprotocols/EyeDecoder2.h"
#include "../../lib/scopeprotocols/WaterfallDecoder.h"

using namespace std;
using namespace glm;
@@ -93,7 +91,7 @@ void WaveformArea::RenderGrid(Cairo::RefPtr< Cairo::Context > cr)
Pango::FontDescription font("monospace normal 10");
font.set_weight(Pango::WEIGHT_NORMAL);
tlayout->set_font_description(font);
tlayout->set_text("500 mV_xxx");
tlayout->set_text("500.000 mV_xx");
tlayout->get_pixel_size(twidth, theight);
m_plotRight = m_width - twidth;

113 changes: 78 additions & 35 deletions glscopeclient/WaveformArea_events.cpp
Original file line number Diff line number Diff line change
@@ -38,7 +38,6 @@
#include "OscilloscopeWindow.h"
#include <random>
#include "ProfileBlock.h"
#include "ProtocolDecoderDialog.h"
#include "ChannelPropertiesDialog.h"
#include "../../lib/scopeprotocols/EyeDecoder2.h"
#include "../../lib/scopeprotocols/WaterfallDecoder.h"
@@ -120,11 +119,11 @@ bool WaveformArea::on_scroll_event (GdkEventScroll* ev)
switch(ev->direction)
{
case GDK_SCROLL_UP:
if(!IsEye())
if(!IsEyeOrBathtub())
m_parent->OnZoomInHorizontal(m_group);
break;
case GDK_SCROLL_DOWN:
if(!IsEye())
if(!IsEyeOrBathtub())
m_parent->OnZoomOutHorizontal(m_group);
break;
case GDK_SCROLL_LEFT:
@@ -320,12 +319,10 @@ void WaveformArea::OnDoubleClick(GdkEventButton* /*event*/, int64_t /*timestamp*
auto decode = dynamic_cast<ProtocolDecoder*>(m_selectedChannel);
if(decode)
{
ProtocolDecoderDialog dialog(m_parent, decode, NULL);
if(dialog.run() == Gtk::RESPONSE_OK)
{
dialog.ConfigureDecoder();
queue_draw();
}
m_decodeDialog = new ProtocolDecoderDialog(m_parent, decode, NULL);
m_decodeDialog->show();
m_decodeDialog->signal_response().connect(
sigc::mem_fun(*this, &WaveformArea::OnDecodeReconfigureDialogResponse));
}
else
{
@@ -497,39 +494,78 @@ void WaveformArea::OnProtocolDecode(string name)
{
//Create a new decoder for the incoming signal
string color = GetDefaultChannelColor(g_numDecodes);
auto decode = ProtocolDecoder::CreateDecoder(name, color);
if(m_pendingDecode)
delete m_pendingDecode;
m_pendingDecode = ProtocolDecoder::CreateDecoder(name, color);

//Only one input with no config required? Do default configuration
if( (decode->GetInputCount() == 1) && !decode->NeedsConfig())
if( (m_pendingDecode->GetInputCount() == 1) && !m_pendingDecode->NeedsConfig())
{
decode->SetInput(0, m_selectedChannel);
decode->SetDefaultName();
m_pendingDecode->SetInput(0, m_selectedChannel);
m_pendingDecode->SetDefaultName();
OnDecodeSetupComplete();
}

//Multiple inputs or config needed? Show the dialog
else
{
ProtocolDecoderDialog dialog(m_parent, decode, m_selectedChannel);
if(dialog.run() != Gtk::RESPONSE_OK)
{
delete decode;
return;
}
dialog.ConfigureDecoder();
if(m_decodeDialog)
delete m_decodeDialog;
m_decodeDialog = new ProtocolDecoderDialog(m_parent, m_pendingDecode, m_selectedChannel);
m_decodeDialog->show();
m_decodeDialog->signal_response().connect(sigc::mem_fun(*this, &WaveformArea::OnDecodeDialogResponse));
}
}

void WaveformArea::OnDecodeDialogResponse(int response)
{
//Clean up decoder if canceled
if(response != Gtk::RESPONSE_OK)
{
delete m_pendingDecode;
m_pendingDecode = NULL;
}

//All good, set it up
else
{
m_decodeDialog->ConfigureDecoder();
OnDecodeSetupComplete();
}

//Clean up the dialog
delete m_decodeDialog;
m_decodeDialog = NULL;
}

void WaveformArea::OnDecodeReconfigureDialogResponse(int response)
{
//Apply the changes
if(response == Gtk::RESPONSE_OK)
{
m_decodeDialog->ConfigureDecoder();
queue_draw();
}

//Clean up the dialog
delete m_decodeDialog;
m_decodeDialog = NULL;
}

void WaveformArea::OnDecodeSetupComplete()
{
//Increment the color chooser only after we've decided to add the decode.
//If the dialog is canceled, don't do anything.
g_numDecodes ++;

//If it's an eye pattern or waterfall, set the initial size
auto eye = dynamic_cast<EyeDecoder2*>(decode);
auto eye = dynamic_cast<EyeDecoder2*>(m_pendingDecode);
if(eye != NULL)
{
eye->SetWidth(m_width / 4);
eye->SetHeight(m_height);
}
auto fall = dynamic_cast<WaterfallDecoder*>(decode);
auto fall = dynamic_cast<WaterfallDecoder*>(m_pendingDecode);
if(fall != NULL)
{
fall->SetWidth(m_width);
@@ -538,36 +574,39 @@ void WaveformArea::OnProtocolDecode(string name)
}

//Run the decoder for the first time, so we get valid output even if there's not a trigger pending.
decode->Refresh();
m_pendingDecode->Refresh();

//Create a new waveform view for the generated signal
if(!decode->IsOverlay())
m_parent->DoAddChannel(decode, m_group, this);
if(!m_pendingDecode->IsOverlay())
m_parent->DoAddChannel(m_pendingDecode, m_group, this);

//It's an overlay. Reference it and add to our overlay list
else
{
decode->AddRef();
m_overlays.push_back(decode);
m_parent->AddDecoder(decode);
m_pendingDecode->AddRef();
m_overlays.push_back(m_pendingDecode);
m_parent->AddDecoder(m_pendingDecode);
queue_draw();
}

//If the decoder is a packet-oriented protocol, pop up a protocol analyzer
//TODO: UI for re-opening the analyzer if we close it?
//TODO: allow protocol decoder dialogs to reconfigure decoder in the future
auto pdecode = dynamic_cast<PacketDecoder*>(decode);
auto pdecode = dynamic_cast<PacketDecoder*>(m_pendingDecode);
if(pdecode != NULL)
{
char title[256];
snprintf(title, sizeof(title), "Protocol Analyzer: %s", decode->m_displayname.c_str());
snprintf(title, sizeof(title), "Protocol Analyzer: %s", m_pendingDecode->m_displayname.c_str());

auto analyzer = new ProtocolAnalyzerWindow(title, m_parent, pdecode, this);
m_parent->m_analyzers.emplace(analyzer);

analyzer->OnWaveformDataReady();
analyzer->show();
}

//This decode is no longer pending
m_pendingDecode = NULL;
}

void WaveformArea::OnMeasure(string name)
@@ -598,19 +637,23 @@ void WaveformArea::OnTriggerMode(Oscilloscope::TriggerType type, Gtk::RadioMenuI

void WaveformArea::OnWaveformDataReady()
{
//If we're an eye, refresh the parent's time scale
auto eye = dynamic_cast<EyeDecoder2*>(m_channel);
if(eye != NULL)
//If we're a fixed width curve, refresh the parent's time scale
if(IsEyeOrBathtub())
{
auto eye = dynamic_cast<EyeDecoder2*>(m_channel);
if(eye == NULL)
eye = dynamic_cast<EyeDecoder2*>(dynamic_cast<ProtocolDecoder*>(m_channel)->GetInput(0));
int64_t width = eye->GetUIWidth();

//eye is two UIs wide
int64_t eye_width_ps = 2 * eye->GetUIWidth();
int64_t eye_width_ps = 2 * width;

//If decode fails for some reason, don't have an invalid timeline
if(eye_width_ps == 0)
eye_width_ps = 5;

m_group->m_pixelsPerXUnit = m_width * 1.0f / eye_width_ps;
m_group->m_xAxisOffset = -eye->GetUIWidth();
m_group->m_xAxisOffset = -width;
}

//Update our measurements and redraw the waveform