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: 0e0252d4d85d
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: e28a7493bd00
Choose a head ref
  • 1 commit
  • 7 files changed
  • 1 contributor

Commits on Aug 17, 2020

  1. Lots of fixes to cursor handling. Normalized cursors so X1 is always …

    …before X2. Added value display to cursors.
    azonenberg committed Aug 17, 2020
    Copy the full SHA
    e28a749 View commit details
2 changes: 1 addition & 1 deletion lib
Submodule lib updated from 6dca06 to 402579
5 changes: 3 additions & 2 deletions src/glscopeclient/ScopeSyncWizard.cpp
Original file line number Diff line number Diff line change
@@ -336,9 +336,9 @@ void ScopeSyncWizard::OnWaveformDataReady()
At 10 Gsps this is a whopping 1000 ns, typical values are in the low tens of ns.
*/
m_maxSkewSamples = static_cast<int64_t>(pw->m_offsets.size() / 2);

m_maxSkewSamples = min(m_maxSkewSamples, static_cast<int64_t>(10000LL));

m_delta = - m_maxSkewSamples;

//Set the timer
@@ -372,6 +372,7 @@ bool ScopeSyncWizard::OnTimer()
int64_t deltaPs = m_primaryWaveform->m_timescale * d;

//Loop over samples in the primary waveform
//TODO: AVX
ssize_t samplesProcessed = 0;
size_t isecondary = 0;
double correlation = 0;
8 changes: 6 additions & 2 deletions src/glscopeclient/WaveformArea.h
Original file line number Diff line number Diff line change
@@ -353,6 +353,8 @@ class WaveformArea : public Gtk::GLArea
void RenderCairoOverlays();
void DoRenderCairoOverlays(Cairo::RefPtr< Cairo::Context > cr);
void RenderCursors(Cairo::RefPtr< Cairo::Context > cr);
void RenderInsertionBar(Cairo::RefPtr< Cairo::Context > cr);
void RenderCursor(Cairo::RefPtr< Cairo::Context > cr, int64_t pos, Gdk::Color color, bool label_to_left);
void RenderChannelLabel(Cairo::RefPtr< Cairo::Context > cr);
void RenderEyeMask(Cairo::RefPtr< Cairo::Context > cr);
void RenderDecodeOverlays(Cairo::RefPtr< Cairo::Context > cr);
@@ -394,7 +396,8 @@ class WaveformArea : public Gtk::GLArea
float XAxisUnitsToPixels(int64_t t);
float XAxisUnitsToXPosition(int64_t t);
float PickStepSize(float volts_per_half_span, int min_steps = 2, int max_steps = 5);
size_t BinarySearchForGequal(float* buf, size_t len, float value);
template<class T> size_t BinarySearchForGequal(T* buf, size_t len, T value);
float GetValueAtTime(int64_t time_ps);
void Int64ToFloat(float* dst, int64_t* src, size_t len);
void Int64ToFloatAVX512(float* dst, int64_t* src, size_t len);

@@ -441,7 +444,8 @@ class WaveformArea : public Gtk::GLArea
{
DRAG_NONE,
DRAG_TRIGGER,
DRAG_CURSOR,
DRAG_CURSOR_0,
DRAG_CURSOR_1,
DRAG_OFFSET,
DRAG_WAVEFORM_AREA,
DRAG_OVERLAY
104 changes: 93 additions & 11 deletions src/glscopeclient/WaveformArea_cairo.cpp
Original file line number Diff line number Diff line change
@@ -244,6 +244,7 @@ void WaveformArea::DoRenderCairoOverlays(Cairo::RefPtr< Cairo::Context > cr)

RenderDecodeOverlays(cr);
RenderCursors(cr);
RenderInsertionBar(cr);
RenderChannelLabel(cr);
}

@@ -600,6 +601,88 @@ void WaveformArea::RenderChannelInfoBox(
cr->restore();
}

void WaveformArea::RenderCursor(Cairo::RefPtr< Cairo::Context > cr, int64_t pos, Gdk::Color color, bool label_to_left)
{
//Draw the actual cursor
double x = XAxisUnitsToXPosition(pos);
cr->set_source_rgb(color.get_red_p(), color.get_green_p(), color.get_blue_p());
cr->move_to(x, 0);
cr->line_to(x, m_height);
cr->stroke();

//For now, only display labels on analog channels
if(!IsAnalog())
return;

//Draw the value label at the bottom
string text = m_channel->GetYAxisUnits().PrettyPrint(GetValueAtTime(pos));

//Figure out text size
int twidth;
int theight;
Glib::RefPtr<Pango::Layout> tlayout = Pango::Layout::create (cr);
Pango::FontDescription font("sans normal 10");
font.set_weight(Pango::WEIGHT_NORMAL);
tlayout->set_font_description(font);
tlayout->set_text(text);
tlayout->get_pixel_size(twidth, theight);

//Draw background
int labelmargin = 2;
int left;
int right;
if(label_to_left)
{
right = x - labelmargin;
left = x - (twidth + 2*labelmargin);
}
else
{
left = x + labelmargin;
right = x + (twidth + 2*labelmargin);
}
int bottom = m_height;
int top = m_height - (theight + 2*labelmargin);
cr->set_source_rgba(0, 0, 0, 0.75);
cr->move_to(left, bottom);
cr->line_to(right, bottom);
cr->line_to(right, top);
cr->line_to(left, top);
cr->fill();

//Draw text
cr->set_source_rgb(color.get_red_p(), color.get_green_p(), color.get_blue_p());
cr->save();
cr->move_to(labelmargin + left, top + labelmargin);
tlayout->update_from_cairo_context(cr);
tlayout->show_in_cairo_context(cr);
cr->restore();
}

/**
@brief Gets the value of our channel at the specified timestamp (absolute, not waveform ticks)
*/
float WaveformArea::GetValueAtTime(int64_t time_ps)
{
AnalogWaveform* waveform = dynamic_cast<AnalogWaveform*>(m_channel->GetData());
if(!waveform)
return 0;

//Find the index of the sample of interest
double ticks = 1.0f * (time_ps - waveform->m_triggerPhase) / waveform->m_timescale;
size_t index = BinarySearchForGequal(
(int64_t*)&waveform->m_offsets[0],
waveform->m_offsets.size(),
(int64_t)ceil(ticks));

//Stop if start of waveform (no lerping possible)
if(index == 0)
return waveform->m_samples[index];

//Linear interpolate to find the value better
return ProtocolDecoder::InterpolateValue(waveform, index-1, ticks - waveform->m_offsets[index-1]);
}

void WaveformArea::RenderCursors(Cairo::RefPtr< Cairo::Context > cr)
{
int ytop = 0;
@@ -614,20 +697,14 @@ void WaveformArea::RenderCursors(Cairo::RefPtr< Cairo::Context > cr)
{
//Draw first vertical cursor
double x = XAxisUnitsToXPosition(m_group->m_xCursorPos[0]);
cr->move_to(x, ytop);
cr->line_to(x, ybot);
cr->set_source_rgb(yellow.get_red_p(), yellow.get_green_p(), yellow.get_blue_p());
cr->stroke();
RenderCursor(cr, m_group->m_xCursorPos[0], yellow, true);

//Dual cursors
if(m_group->m_cursorConfig == WaveformGroup::CURSOR_X_DUAL)
{
//Draw second vertical cursor
double x2 = XAxisUnitsToXPosition(m_group->m_xCursorPos[1]);
cr->move_to(x2, ytop);
cr->line_to(x2, ybot);
cr->set_source_rgb(orange.get_red_p(), orange.get_green_p(), orange.get_blue_p());
cr->stroke();
RenderCursor(cr, m_group->m_xCursorPos[1], orange, false);

//Draw filled area between them
cr->set_source_rgba(yellow.get_red_p(), yellow.get_green_p(), yellow.get_blue_p(), 0.2);
@@ -638,9 +715,15 @@ void WaveformArea::RenderCursors(Cairo::RefPtr< Cairo::Context > cr)
cr->fill();
}
}
}

void WaveformArea::RenderInsertionBar(Cairo::RefPtr< Cairo::Context > cr)
{
int barsize = 5;

Gdk::Color yellow("yellow");
Gdk::Color orange("orange");

if(m_insertionBarLocation != INSERT_NONE)
{
int barpos = 0;
@@ -650,12 +733,12 @@ void WaveformArea::RenderCursors(Cairo::RefPtr< Cairo::Context > cr)
{
case INSERT_BOTTOM:
cr->set_source_rgba(yellow.get_red_p(), yellow.get_green_p(), yellow.get_blue_p(), alpha);
barpos = ybot - barsize;
barpos = m_height - barsize;
break;

case INSERT_BOTTOM_SPLIT:
cr->set_source_rgba(orange.get_red_p(), orange.get_green_p(), orange.get_blue_p(), alpha);
barpos = ybot - barsize;
barpos = m_height - barsize;
break;

case INSERT_TOP:
@@ -702,7 +785,6 @@ void WaveformArea::RenderCursors(Cairo::RefPtr< Cairo::Context > cr)
}
}


void WaveformArea::MakePathSignalBody(
const Cairo::RefPtr<Cairo::Context>& cr,
float xstart, float /*xoff*/, float xend, float ybot, float /*ymid*/, float ytop)
44 changes: 41 additions & 3 deletions src/glscopeclient/WaveformArea_events.cpp
Original file line number Diff line number Diff line change
@@ -120,6 +120,10 @@ bool WaveformArea::on_scroll_event (GdkEventScroll* ev)
switch(ev->direction)
{
case GDK_SCROLL_UP:
{
//TODO: zoom to center
}

if(!IsEyeOrBathtub())
m_parent->OnZoomInHorizontal(m_group);
break;
@@ -210,7 +214,7 @@ void WaveformArea::OnSingleClick(GdkEventButton* event, int64_t timestamp)
//Start dragging the second cursor
if(m_group->m_cursorConfig == WaveformGroup::CURSOR_X_DUAL)
{
m_dragState = DRAG_CURSOR;
m_dragState = DRAG_CURSOR_1;
m_group->m_xCursorPos[1] = timestamp;
}

@@ -384,7 +388,11 @@ bool WaveformArea::on_button_release_event(GdkEventButton* event)
break;

//Move the cursor
case DRAG_CURSOR:
case DRAG_CURSOR_0:
m_group->m_xCursorPos[0] = timestamp;
break;

case DRAG_CURSOR_1:
if(m_group->m_cursorConfig == WaveformGroup::CURSOR_X_DUAL)
m_group->m_xCursorPos[1] = timestamp;
break;
@@ -499,10 +507,40 @@ bool WaveformArea::on_motion_notify_event(GdkEventMotion* event)
queue_draw();
break;

case DRAG_CURSOR:
case DRAG_CURSOR_0:
m_group->m_xCursorPos[0] = timestamp;

if(m_group->m_cursorConfig == WaveformGroup::CURSOR_X_DUAL)
{
//Cursor 0 should always be left of 1.
//If they cross, flip them
if(m_group->m_xCursorPos[0] > m_group->m_xCursorPos[1])
{
m_dragState = DRAG_CURSOR_1;
int64_t tmp = m_group->m_xCursorPos[1];
m_group->m_xCursorPos[1] = m_group->m_xCursorPos[0];
m_group->m_xCursorPos[0] = tmp;
}
}

m_group->m_vbox.queue_draw();
break;

case DRAG_CURSOR_1:
if(m_group->m_cursorConfig == WaveformGroup::CURSOR_X_DUAL)
{
m_group->m_xCursorPos[1] = timestamp;

//Cursor 0 should always be left of 1
//If they cross, flip them
if(m_group->m_xCursorPos[0] > m_group->m_xCursorPos[1])
{
m_dragState = DRAG_CURSOR_0;
int64_t tmp = m_group->m_xCursorPos[1];
m_group->m_xCursorPos[1] = m_group->m_xCursorPos[0];
m_group->m_xCursorPos[0] = tmp;
}

m_group->m_vbox.queue_draw();
}
break;
8 changes: 5 additions & 3 deletions src/glscopeclient/WaveformArea_rendering.cpp
Original file line number Diff line number Diff line change
@@ -44,6 +44,9 @@

using namespace std;

template size_t WaveformArea::BinarySearchForGequal<float>(float* buf, size_t len, float value);
template size_t WaveformArea::BinarySearchForGequal<int64_t>(int64_t* buf, size_t len, int64_t value);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// WaveformRenderData

@@ -147,7 +150,6 @@ void WaveformArea::PrepareGeometry(WaveformRenderData* wdata)
else
digheight = 20;

//#pragma omp parallel for
//TODO: AVX
yscale = digheight;
for(size_t j=0; j<realcount; j++)
@@ -227,7 +229,6 @@ void WaveformArea::Int64ToFloatAVX512(float* dst, int64_t* src, size_t len)
size_t len_rounded = len - (len % 8);

//Main unrolled loop
//#pragma omp parallel for
for(size_t j=0; j<len_rounded; j+= 8)
{
__m512i i64x8 = _mm512_load_epi64(src + j);
@@ -243,7 +244,8 @@ void WaveformArea::Int64ToFloatAVX512(float* dst, int64_t* src, size_t len)
/**
@brief Look for a value greater than or equal to "value" in buf and return the index
*/
size_t WaveformArea::BinarySearchForGequal(float* buf, size_t len, float value)
template<class T>
size_t WaveformArea::BinarySearchForGequal(T* buf, size_t len, T value)
{
size_t pos = len/2;
size_t last_lo = 0;
4 changes: 4 additions & 0 deletions src/glscopeclient/main.cpp
Original file line number Diff line number Diff line change
@@ -219,6 +219,10 @@ int main(int argc, char* argv[])
}
#endif

//Complain if the OpenMP wait policy isn't set right
if(strcmp(getenv("OMP_WAIT_POLICY"), "PASSIVE") != 0)
LogWarning("glscopeclient works best with the OMP_WAIT_POLICY environment variable set to PASSIVE\n");

g_app = new ScopeApp;

//Initialize object creation tables for predefined libraries