SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
glscope.cpp
Go to the documentation of this file.
1 // Copyright (C) 2017 F4EXB //
3 // written by Edouard Griffiths //
4 // //
5 // This program is free software; you can redistribute it and/or modify //
6 // it under the terms of the GNU General Public License as published by //
7 // the Free Software Foundation as version 3 of the License, or //
8 // (at your option) any later version. //
9 // //
10 // This program is distributed in the hope that it will be useful, //
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
13 // GNU General Public License V3 for more details. //
14 // //
15 // You should have received a copy of the GNU General Public License //
16 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
18 
19 #include <QPainter>
20 #include <QMouseEvent>
21 #include <QOpenGLContext>
22 #include <QOpenGLFunctions>
23 #include <QSurface>
24 #include <QFontDatabase>
25 #include <QDebug>
26 #include <algorithm>
27 
28 #include "glscope.h"
29 
30 GLScope::GLScope(QWidget* parent) :
31  QGLWidget(parent),
32  m_tracesData(0),
33  m_traces(0),
34  m_processingTraceIndex(-1),
35  m_bufferIndex(0),
36  m_displayMode(DisplayX),
37  m_dataChanged(0),
38  m_configChanged(false),
39  m_sampleRate(0),
40  m_timeOfsProMill(0),
41  m_triggerPre(0),
42  m_traceSize(0),
43  m_timeBase(1),
44  m_timeOffset(0),
45  m_focusedTraceIndex(0),
46  m_displayGridIntensity(10),
47  m_displayTraceIntensity(50),
48  m_displayXYPoints(false)
49 {
50  setAttribute(Qt::WA_OpaquePaintEvent);
51  connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick()));
52  m_timer.start(50);
53 
54  m_y1Scale.setFont(font());
55  m_y1Scale.setOrientation(Qt::Vertical);
56  m_y2Scale.setFont(font());
57  m_y2Scale.setOrientation(Qt::Vertical);
58  m_x1Scale.setFont(font());
59  m_x1Scale.setOrientation(Qt::Horizontal);
60  m_x2Scale.setFont(font());
61  m_x2Scale.setOrientation(Qt::Horizontal);
62 
63  m_channelOverlayFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
64  m_channelOverlayFont.setBold(true);
65  m_channelOverlayFont.setPointSize(font().pointSize()+1);
66 
67  //m_traceCounter = 0;
68 }
69 
71 {
72  cleanup();
73 }
74 
76 {
77  m_displayGridIntensity = intensity;
78  if (m_displayGridIntensity > 100) {
80  } else if (m_displayGridIntensity < 0) {
82  }
83  update();
84 }
85 
87 {
88  m_displayTraceIntensity = intensity;
89  if (m_displayTraceIntensity > 100) {
91  } else if (m_displayTraceIntensity < 0) {
93  }
94  update();
95 }
96 
97 void GLScope::setTraces(std::vector<ScopeVis::TraceData>* tracesData, std::vector<float *>* traces)
98 {
99  m_tracesData = tracesData;
100  m_traces = traces;
101 }
102 
103 void GLScope::newTraces(std::vector<float *>* traces)
104 {
105  if (traces->size() > 0)
106  {
107  if (!m_mutex.tryLock(0)) {
108  return;
109  }
110 
111  if (m_dataChanged.testAndSetOrdered(0, 1)) {
112  m_traces = traces;
113  }
114 
115  m_mutex.unlock();
116  }
117 }
118 
119 void GLScope::newTraces(std::vector<float *>* traces, int traceIndex)
120 {
121  if (traces->size() > 0)
122  {
123  if(!m_mutex.tryLock(0)) {
124  return;
125  }
126 
127  if (m_dataChanged.testAndSetOrdered(0, 1))
128  {
129  m_processingTraceIndex.store(traceIndex);
130  m_traces = &traces[traceIndex];
131  }
132 
133  m_mutex.unlock();
134  }
135 }
136 
138 {
139  QOpenGLContext *glCurrentContext = QOpenGLContext::currentContext();
140 
141  if (glCurrentContext) {
142  if (QOpenGLContext::currentContext()->isValid()) {
143  qDebug() << "GLScope::initializeGL: context:"
144  << " major: " << (QOpenGLContext::currentContext()->format()).majorVersion()
145  << " minor: " << (QOpenGLContext::currentContext()->format()).minorVersion()
146  << " ES: " << (QOpenGLContext::currentContext()->isOpenGLES() ? "yes" : "no");
147  }
148  else {
149  qDebug() << "GLScope::initializeGL: current context is invalid";
150  }
151  } else {
152  qCritical() << "GLScope::initializeGL: no current context";
153  return;
154  }
155 
156  QSurface *surface = glCurrentContext->surface();
157 
158  if (surface == 0)
159  {
160  qCritical() << "GLScope::initializeGL: no surface attached";
161  return;
162  }
163  else
164  {
165  if (surface->surfaceType() != QSurface::OpenGLSurface)
166  {
167  qCritical() << "GLScope::initializeGL: surface is not an OpenGLSurface: " << surface->surfaceType()
168  << " cannot use an OpenGL context";
169  return;
170  }
171  else
172  {
173  qDebug() << "GLScope::initializeGL: OpenGL surface:"
174  << " class: " << (surface->surfaceClass() == QSurface::Window ? "Window" : "Offscreen");
175  }
176  }
177 
178  connect(glCurrentContext, &QOpenGLContext::aboutToBeDestroyed, this, &GLScope::cleanup); // TODO: when migrating to QOpenGLWidget
179 
180  QOpenGLFunctions *glFunctions = QOpenGLContext::currentContext()->functions();
181  glFunctions->initializeOpenGLFunctions();
182 
183  //glDisable(GL_DEPTH_TEST);
190 }
191 
192 void GLScope::resizeGL(int width, int height)
193 {
194  QOpenGLFunctions *glFunctions = QOpenGLContext::currentContext()->functions();
195  glFunctions->glViewport(0, 0, width, height);
196  m_configChanged = true;
197 }
198 
200 {
201  if (!m_mutex.tryLock(0)) {
202  return;
203  }
204 
205  if (m_configChanged) {
206  applyConfig();
207  }
208 
209 // qDebug("GLScope::paintGL: m_traceCounter: %d", m_traceCounter);
210 // m_traceCounter = 0;
211 
212  QOpenGLFunctions *glFunctions = QOpenGLContext::currentContext()->functions();
213  glFunctions->glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
214  glFunctions->glClear(GL_COLOR_BUFFER_BIT);
215 
216  if ((m_displayMode == DisplayX) || (m_displayMode == DisplayXYV) || (m_displayMode == DisplayXYH)) // display trace #0
217  {
218  // draw rect around
219  {
220  GLfloat q3[] {
221  1, 1,
222  0, 1,
223  0, 0,
224  1, 0
225  };
226 
227  QVector4D color(1.0f, 1.0f, 1.0f, 0.5f);
229  }
230 
231  // paint grid
232  const ScaleEngine::TickList* tickList;
233  const ScaleEngine::Tick* tick;
234 
235  // Y1 (X trace or trace #0)
236  {
237  tickList = &m_y1Scale.getTickList();
238 
239  //GLfloat q3[4*tickList->count()];
240  GLfloat *q3 = m_q3TickY1.m_array;
241  int effectiveTicks = 0;
242 
243  for (int i= 0; i < tickList->count(); i++)
244  {
245  tick = &(*tickList)[i];
246 
247  if (tick->major)
248  {
249  if (tick->textSize > 0)
250  {
251  float y = 1 - (tick->pos / m_y1Scale.getSize());
252  q3[4*effectiveTicks] = 0;
253  q3[4*effectiveTicks+1] = y;
254  q3[4*effectiveTicks+2] = 1;
255  q3[4*effectiveTicks+3] = y;
256  effectiveTicks++;
257  }
258  }
259  }
260 
261  float blue = 1.0f;
262  QVector4D color(1.0f, 1.0f, blue, (float) m_displayGridIntensity / 100.0f);
263  m_glShaderSimple.drawSegments(m_glScopeMatrix1, color, q3, 2*effectiveTicks);
264  }
265 
266  // X1 (time)
267  {
268  tickList = &m_x1Scale.getTickList();
269 
270  //GLfloat q3[4*tickList->count()];
271  GLfloat *q3 = m_q3TickX1.m_array;
272  int effectiveTicks = 0;
273  for(int i= 0; i < tickList->count(); i++) {
274  tick = &(*tickList)[i];
275  if(tick->major) {
276  if(tick->textSize > 0) {
277  float x = tick->pos / m_x1Scale.getSize();
278  q3[4*effectiveTicks] = x;
279  q3[4*effectiveTicks+1] = 0;
280  q3[4*effectiveTicks+2] = x;
281  q3[4*effectiveTicks+3] = 1;
282  effectiveTicks++;
283  }
284  }
285  }
286 
287  QVector4D color(1.0f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f);
288  m_glShaderSimple.drawSegments(m_glScopeMatrix1, color, q3, 2*effectiveTicks);
289  }
290 
291  // paint left #1 scale
292  {
293  GLfloat vtx1[] = {
294  0, 1,
295  1, 1,
296  1, 0,
297  0, 0
298  };
299  GLfloat tex1[] = {
300  0, 1,
301  1, 1,
302  1, 0,
303  0, 0
304  };
306  }
307 
308  // paint bottom #1 scale
309  {
310  GLfloat vtx1[] = {
311  0, 1,
312  1, 1,
313  1, 0,
314  0, 0
315  };
316  GLfloat tex1[] = {
317  0, 1,
318  1, 1,
319  1, 0,
320  0, 0
321  };
323  }
324 
325  // paint trace #1
326  if (m_traceSize > 0)
327  {
328  const float *trace = (*m_traces)[0];
329  const ScopeVis::TraceData& traceData = (*m_tracesData)[0];
330 
331  if (traceData.m_viewTrace)
332  {
333  int start = (m_timeOfsProMill/1000.0) * m_traceSize;
334  int end = std::min(start + m_traceSize/m_timeBase, m_traceSize);
335 
336  if(end - start < 2)
337  start--;
338 
339  float rectX = m_glScopeRect1.x();
340  float rectY = m_glScopeRect1.y() + m_glScopeRect1.height() / 2.0f;
341  float rectW = m_glScopeRect1.width() * (float)m_timeBase / (float)(m_traceSize - 1);
342  //float rectH = -(m_glScopeRect1.height() / 2.0f) * traceData.m_amp;
343  float rectH = -m_glScopeRect1.height() / 2.0f;
344 
345  //QVector4D color(1.0f, 1.0f, 0.25f, m_displayTraceIntensity / 100.0f);
346  QVector4D color(traceData.m_traceColorR, traceData.m_traceColorG, traceData.m_traceColorB, m_displayTraceIntensity / 100.0f);
347  QMatrix4x4 mat;
348  mat.setToIdentity();
349  mat.translate(-1.0f + 2.0f * rectX, 1.0f - 2.0f * rectY);
350  mat.scale(2.0f * rectW, -2.0f * rectH);
351  m_glShaderSimple.drawPolyline(mat, color, (GLfloat *) &trace[2*start], end - start);
352 
353  // Paint trigger level if any
354  if ((traceData.m_triggerDisplayLevel > -1.0f) && (traceData.m_triggerDisplayLevel < 1.0f))
355  {
356  GLfloat q3[] {
357  0, traceData.m_triggerDisplayLevel,
358  1, traceData.m_triggerDisplayLevel
359  };
360 
361  float rectX = m_glScopeRect1.x();
362  float rectY = m_glScopeRect1.y() + m_glScopeRect1.height() / 2.0f;
363  float rectW = m_glScopeRect1.width();
364  float rectH = -m_glScopeRect1.height() / 2.0f;
365 
366  QVector4D color(
370  0.4f);
371  QMatrix4x4 mat;
372  mat.setToIdentity();
373  mat.translate(-1.0f + 2.0f * rectX, 1.0f - 2.0f * rectY);
374  mat.scale(2.0f * rectW, -2.0f * rectH);
375  m_glShaderSimple.drawSegments(mat, color, q3, 2);
376  } // display trigger
377 
378  // Paint overlay if any
379  if ((m_focusedTraceIndex == 0) && (traceData.m_hasTextOverlay))
380  {
382  traceData.m_textOverlay,
383  traceData.m_traceColor,
386  } // display overlay
387  } // displayable trace
388  } // trace length > 0
389  } // Display X
390 
391  if ((m_displayMode == DisplayY) || (m_displayMode == DisplayXYV) || (m_displayMode == DisplayXYH)) // display traces #1..n
392  {
393  // draw rect around
394  {
395  GLfloat q3[] {
396  1, 1,
397  0, 1,
398  0, 0,
399  1, 0
400  };
401 
402  QVector4D color(1.0f, 1.0f, 1.0f, 0.5f);
404  }
405 
406  // paint grid
407  const ScaleEngine::TickList* tickList;
408  const ScaleEngine::Tick* tick;
409 
410  // Y2 (Focused Y trace)
411  {
412  tickList = &m_y2Scale.getTickList();
413 
414  //GLfloat q3[4*tickList->count()];
415  GLfloat *q3 = m_q3TickY2.m_array;
416  int effectiveTicks = 0;
417 
418  for (int i= 0; i < tickList->count(); i++)
419  {
420  tick = &(*tickList)[i];
421 
422  if (tick->major)
423  {
424  if (tick->textSize > 0)
425  {
426  float y = 1 - (tick->pos / m_y2Scale.getSize());
427  q3[4*effectiveTicks] = 0;
428  q3[4*effectiveTicks+1] = y;
429  q3[4*effectiveTicks+2] = 1;
430  q3[4*effectiveTicks+3] = y;
431  effectiveTicks++;
432  }
433  }
434  }
435 
436  float blue = 1.0f;
437  QVector4D color(1.0f, 1.0f, blue, (float) m_displayGridIntensity / 100.0f);
438  m_glShaderSimple.drawSegments(m_glScopeMatrix2, color, q3, 2*effectiveTicks);
439  }
440 
441  // X2 (time)
442  {
443  tickList = &m_x2Scale.getTickList();
444 
445  //GLfloat q3[4*tickList->count()];
446  GLfloat *q3 = m_q3TickX2.m_array;
447  int effectiveTicks = 0;
448  for(int i= 0; i < tickList->count(); i++) {
449  tick = &(*tickList)[i];
450  if(tick->major) {
451  if(tick->textSize > 0) {
452  float x = tick->pos / m_x2Scale.getSize();
453  q3[4*effectiveTicks] = x;
454  q3[4*effectiveTicks+1] = 0;
455  q3[4*effectiveTicks+2] = x;
456  q3[4*effectiveTicks+3] = 1;
457  effectiveTicks++;
458  }
459  }
460  }
461 
462  QVector4D color(1.0f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f);
463  m_glShaderSimple.drawSegments(m_glScopeMatrix2, color, q3, 2*effectiveTicks);
464  }
465 
466  // paint left #2 scale
467  {
468  GLfloat vtx1[] = {
469  0, 1,
470  1, 1,
471  1, 0,
472  0, 0
473  };
474  GLfloat tex1[] = {
475  0, 1,
476  1, 1,
477  1, 0,
478  0, 0
479  };
481  }
482 
483  // paint bottom #2 scale
484  {
485  GLfloat vtx1[] = {
486  0, 1,
487  1, 1,
488  1, 0,
489  0, 0
490  };
491  GLfloat tex1[] = {
492  0, 1,
493  1, 1,
494  1, 0,
495  0, 0
496  };
498  }
499 
500  // paint traces #1..n
501  if (m_traceSize > 0)
502  {
503  int start = (m_timeOfsProMill/1000.0) * m_traceSize;
504  int end = std::min(start + m_traceSize/m_timeBase, m_traceSize);
505 
506  if(end - start < 2)
507  start--;
508 
509  for (unsigned int i = 1; i < m_traces->size(); i++)
510  {
511  const float *trace = (*m_traces)[i];
512  const ScopeVis::TraceData& traceData = (*m_tracesData)[i];
513 
514  if (!traceData.m_viewTrace) {
515  continue;
516  }
517 
518  float rectX = m_glScopeRect2.x();
519  float rectY = m_glScopeRect2.y() + m_glScopeRect2.height() / 2.0f;
520  float rectW = m_glScopeRect2.width() * (float)m_timeBase / (float)(m_traceSize - 1);
521  //float rectH = -(m_glScopeRect1.height() / 2.0f) * traceData.m_amp;
522  float rectH = -m_glScopeRect2.height() / 2.0f;
523 
524  //QVector4D color(1.0f, 1.0f, 0.25f, m_displayTraceIntensity / 100.0f);
525  QVector4D color(traceData.m_traceColorR, traceData.m_traceColorG, traceData.m_traceColorB, m_displayTraceIntensity / 100.0f);
526  QMatrix4x4 mat;
527  mat.setToIdentity();
528  mat.translate(-1.0f + 2.0f * rectX, 1.0f - 2.0f * rectY);
529  mat.scale(2.0f * rectW, -2.0f * rectH);
530  m_glShaderSimple.drawPolyline(mat, color, (GLfloat *) &trace[2*start], end - start);
531 
532  // Paint trigger level if any
533  if ((traceData.m_triggerDisplayLevel > -1.0f) && (traceData.m_triggerDisplayLevel < 1.0f))
534  {
535  GLfloat q3[] {
536  0, traceData.m_triggerDisplayLevel,
537  1, traceData.m_triggerDisplayLevel
538  };
539 
540  float rectX = m_glScopeRect2.x();
541  float rectY = m_glScopeRect2.y() + m_glScopeRect2.height() / 2.0f;
542  float rectW = m_glScopeRect2.width();
543  float rectH = -m_glScopeRect2.height() / 2.0f;
544 
545  QVector4D color(
549  0.4f);
550  QMatrix4x4 mat;
551  mat.setToIdentity();
552  mat.translate(-1.0f + 2.0f * rectX, 1.0f - 2.0f * rectY);
553  mat.scale(2.0f * rectW, -2.0f * rectH);
554  m_glShaderSimple.drawSegments(mat, color, q3, 2);
555  }
556 
557  // Paint overlay if any
558  if ((i == m_focusedTraceIndex) && (traceData.m_hasTextOverlay))
559  {
561  traceData.m_textOverlay,
562  traceData.m_traceColor,
565  }
566 
567  } // one trace display
568  } // trace length > 0
569  } // Display Y
570 
571  if (m_displayMode == DisplayPol)
572  {
573  // paint left display: mixed XY
574 
575  // draw rect around
576  {
577  GLfloat q3[] {
578  1, 1,
579  0, 1,
580  0, 0,
581  1, 0
582  };
583 
584  QVector4D color(1.0f, 1.0f, 1.0f, 0.5f);
586 
587  }
588 
589  // paint grid
590  const ScaleEngine::TickList* tickList;
591  const ScaleEngine::Tick* tick;
592 
593  // Horizontal Y1
594  tickList = &m_y1Scale.getTickList();
595  {
596  //GLfloat q3[4*tickList->count()];
597  GLfloat *q3 = m_q3TickY1.m_array;
598  int effectiveTicks = 0;
599 
600  for (int i= 0; i < tickList->count(); i++)
601  {
602  tick = &(*tickList)[i];
603 
604  if (tick->major)
605  {
606  if (tick->textSize > 0)
607  {
608  float y = 1 - (tick->pos / m_y1Scale.getSize());
609  q3[4*effectiveTicks] = 0;
610  q3[4*effectiveTicks+1] = y;
611  q3[4*effectiveTicks+2] = 1;
612  q3[4*effectiveTicks+3] = y;
613  effectiveTicks++;
614  }
615  }
616  }
617 
618  QVector4D color(1.0f, 1.0f, 0.25f, (float) m_displayGridIntensity / 100.0f);
619  m_glShaderSimple.drawSegments(m_glScopeMatrix1, color, q3, 2*effectiveTicks);
620  }
621 
622  // Vertical X1
623  tickList = &m_x1Scale.getTickList();
624  {
625  //GLfloat q3[4*tickList->count()];
626  GLfloat *q3 = m_q3TickX1.m_array;
627  int effectiveTicks = 0;
628  for(int i= 0; i < tickList->count(); i++) {
629  tick = &(*tickList)[i];
630  if(tick->major) {
631  if(tick->textSize > 0) {
632  float x = tick->pos / m_x1Scale.getSize();
633  q3[4*effectiveTicks] = x;
634  q3[4*effectiveTicks+1] = 0;
635  q3[4*effectiveTicks+2] = x;
636  q3[4*effectiveTicks+3] = 1;
637  effectiveTicks++;
638  }
639  }
640  }
641 
642  QVector4D color(1.0f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f);
643  m_glShaderSimple.drawSegments(m_glScopeMatrix1, color, q3, 2*effectiveTicks);
644  }
645 
646  // paint left #1 scale
647  {
648  GLfloat vtx1[] = {
649  0, 1,
650  1, 1,
651  1, 0,
652  0, 0
653  };
654  GLfloat tex1[] = {
655  0, 1,
656  1, 1,
657  1, 0,
658  0, 0
659  };
660 
662  }
663 
664  // paint bottom #1 scale
665  {
666  GLfloat vtx1[] = {
667  0, 1,
668  1, 1,
669  1, 0,
670  0, 0
671  };
672  GLfloat tex1[] = {
673  0, 1,
674  1, 1,
675  1, 0,
676  0, 0
677  };
678 
680  }
681 
682  // Paint secondary grid
683 
684  // Horizontal Y2
685  tickList = &m_y2Scale.getTickList();
686  {
687  //GLfloat q3[4*tickList->count()];
688  GLfloat *q3 = m_q3TickY2.m_array;
689  int effectiveTicks = 0;
690  for(int i= 0; i < tickList->count(); i++) {
691  tick = &(*tickList)[i];
692  if(tick->major) {
693  if(tick->textSize > 0) {
694  float y = 1 - (tick->pos / m_y2Scale.getSize());
695  q3[4*effectiveTicks] = 0;
696  q3[4*effectiveTicks+1] = y;
697  q3[4*effectiveTicks+2] = 1;
698  q3[4*effectiveTicks+3] = y;
699  effectiveTicks++;
700  }
701  }
702  }
703 
704  QVector4D color(0.25f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f);
705  m_glShaderSimple.drawSegments(m_glScopeMatrix1, color, q3, 2*effectiveTicks);
706  }
707 
708  // Paint secondary scale
709  {
710  GLfloat vtx1[] = {
711  0, 1,
712  1, 1,
713  1, 0,
714  0, 0
715  };
716  GLfloat tex1[] = {
717  0, 1,
718  1, 1,
719  1, 0,
720  0, 0
721  };
722 
724  }
725 
726  // paint all traces
727  if (m_traceSize > 0)
728  {
729  int start = (m_timeOfsProMill/1000.0) * m_traceSize;
730  int end = std::min(start + m_traceSize/m_timeBase, m_traceSize);
731 
732  if(end - start < 2)
733  start--;
734 
735  for (unsigned int i = 0; i < m_traces->size(); i++)
736  {
737  const float *trace = (*m_traces)[i];
738  const ScopeVis::TraceData& traceData = (*m_tracesData)[i];
739 
740  if (!traceData.m_viewTrace) {
741  continue;
742  }
743 
744  float rectX = m_glScopeRect1.x();
745  float rectY = m_glScopeRect1.y() + m_glScopeRect1.height() / 2.0f;
746  float rectW = m_glScopeRect1.width() * (float)m_timeBase / (float)(m_traceSize - 1);
747  //float rectH = -(m_glScopeRect1.height() / 2.0f) * traceData.m_amp;
748  float rectH = -m_glScopeRect1.height() / 2.0f;
749 
750  //QVector4D color(1.0f, 1.0f, 0.25f, m_displayTraceIntensity / 100.0f);
751  QVector4D color(traceData.m_traceColorR, traceData.m_traceColorG, traceData.m_traceColorB, m_displayTraceIntensity / 100.0f);
752  QMatrix4x4 mat;
753  mat.setToIdentity();
754  mat.translate(-1.0f + 2.0f * rectX, 1.0f - 2.0f * rectY);
755  mat.scale(2.0f * rectW, -2.0f * rectH);
756  m_glShaderSimple.drawPolyline(mat, color, (GLfloat *) &trace[2*start], end - start);
757 
758  // Paint trigger level if any
759  if ((traceData.m_triggerDisplayLevel > -1.0f) && (traceData.m_triggerDisplayLevel < 1.0f))
760  {
761  GLfloat q3[] {
762  0, traceData.m_triggerDisplayLevel,
763  1, traceData.m_triggerDisplayLevel
764  };
765 
766  float rectX = m_glScopeRect1.x();
767  float rectY = m_glScopeRect1.y() + m_glScopeRect1.height() / 2.0f;
768  float rectW = m_glScopeRect1.width();
769  float rectH = -m_glScopeRect1.height() / 2.0f;
770 
771  QVector4D color(
775  0.4f);
776  QMatrix4x4 mat;
777  mat.setToIdentity();
778  mat.translate(-1.0f + 2.0f * rectX, 1.0f - 2.0f * rectY);
779  mat.scale(2.0f * rectW, -2.0f * rectH);
780  m_glShaderSimple.drawSegments(mat, color, q3, 2);
781  }
782 
783  // Paint overlay if any
784  if ((i == m_focusedTraceIndex) && (traceData.m_hasTextOverlay))
785  {
787  traceData.m_textOverlay,
788  traceData.m_traceColor,
791  }
792  } // all traces display
793  } // trace length > 0
794 
795  // paint right display: polar XY
796 
797  // draw rect around
798  {
799  GLfloat q3[] {
800  1, 1,
801  0, 1,
802  0, 0,
803  1, 0
804  };
805 
806  QVector4D color(1.0f, 1.0f, 1.0f, 0.5f);
808  }
809 
810  // paint grid
811 
812  // Horizontal Y2
813  tickList = &m_y2Scale.getTickList();
814  {
815  //GLfloat q3[4*tickList->count()];
816  GLfloat *q3 = m_q3TickY2.m_array;
817  int effectiveTicks = 0;
818  for(int i= 0; i < tickList->count(); i++) {
819  tick = &(*tickList)[i];
820  if(tick->major) {
821  if(tick->textSize > 0) {
822  float y = 1 - (tick->pos / m_y2Scale.getSize());
823  q3[4*effectiveTicks] = 0;
824  q3[4*effectiveTicks+1] = y;
825  q3[4*effectiveTicks+2] = 1;
826  q3[4*effectiveTicks+3] = y;
827  effectiveTicks++;
828  }
829  }
830  }
831 
832  QVector4D color(1.0f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f);
833  m_glShaderSimple.drawSegments(m_glScopeMatrix2, color, q3, 2*effectiveTicks);
834  }
835 
836  // Vertical X2
837  tickList = &m_x2Scale.getTickList();
838  {
839  //GLfloat q3[4*tickList->count()];
840  GLfloat *q3 = m_q3TickX2.m_array;
841  int effectiveTicks = 0;
842  for(int i= 0; i < tickList->count(); i++) {
843  tick = &(*tickList)[i];
844  if(tick->major) {
845  if(tick->textSize > 0) {
846  float x = tick->pos / m_x2Scale.getSize();
847  q3[4*effectiveTicks] = x;
848  q3[4*effectiveTicks+1] = 0;
849  q3[4*effectiveTicks+2] = x;
850  q3[4*effectiveTicks+3] = 1;
851  effectiveTicks++;
852  }
853  }
854  }
855 
856  QVector4D color(1.0f, 1.0f, 1.0f, (float) m_displayGridIntensity / 100.0f);
857  m_glShaderSimple.drawSegments(m_glScopeMatrix2, color, q3, 2*effectiveTicks);
858  }
859 
860  // paint left #2 scale
861  {
862  GLfloat vtx1[] = {
863  0, 1,
864  1, 1,
865  1, 0,
866  0, 0
867  };
868  GLfloat tex1[] = {
869  0, 1,
870  1, 1,
871  1, 0,
872  0, 0
873  };
874 
876  }
877 
878  // paint bottom #2 scale
879  {
880  GLfloat vtx1[] = {
881  0, 1,
882  1, 1,
883  1, 0,
884  0, 0
885  };
886  GLfloat tex1[] = {
887  0, 1,
888  1, 1,
889  1, 0,
890  0, 0
891  };
892 
894  }
895 
896  // paint polar traces
897 
898  if (m_traceSize > 0)
899  {
900  int start = (m_timeOfsProMill/1000.0) * m_traceSize;
901  int end = std::min(start + m_traceSize/m_timeBase, m_traceSize);
902 
903  if(end - start < 2)
904  start--;
905 
906  //GLfloat q3[2*(end - start)];
907  GLfloat *q3 = m_q3Polar.m_array;
908  const float *trace0 = (*m_traces)[0];
909  memcpy(q3, &(trace0[2*start+1]), (2*(end - start) - 1)*sizeof(float)); // copy X values
910 
911  for (unsigned int i = 1; i < m_traces->size(); i++)
912  {
913  const float *trace = (*m_traces)[i];
914  const ScopeVis::TraceData& traceData = (*m_tracesData)[i];
915 
916  if (!traceData.m_viewTrace) {
917  continue;
918  }
919 
920  for(int i = start; i < end; i++)
921  {
922  float y = trace[2*i+1];
923  q3[2*(i-start)+1] = y;
924  }
925 
926  float rectX = m_glScopeRect2.x() + m_glScopeRect2.width() / 2.0f;
927  float rectY = m_glScopeRect2.y() + m_glScopeRect2.height() / 2.0f;
928  float rectW = m_glScopeRect2.width() / 2.0f;
929  float rectH = -(m_glScopeRect2.height() / 2.0f);
930 
931  QVector4D color(traceData.m_traceColorR, traceData.m_traceColorG, traceData.m_traceColorB, m_displayTraceIntensity / 100.0f);
932  QMatrix4x4 mat;
933  mat.setToIdentity();
934  mat.translate(-1.0f + 2.0f * rectX, 1.0f - 2.0f * rectY);
935  mat.scale(2.0f * rectW, -2.0f * rectH);
936  if (m_displayXYPoints) {
937  m_glShaderSimple.drawPoints(mat, color, q3, end -start);
938  } else {
939  m_glShaderSimple.drawPolyline(mat, color, q3, end -start);
940  }
941  } // XY polar display
942  } // trace length > 0
943  } // XY mixed + polar display
944 
945  m_dataChanged.store(0);
946  m_processingTraceIndex.store(-1);
947  m_mutex.unlock();
948 }
949 
950 void GLScope::setSampleRate(int sampleRate)
951 {
952  m_sampleRate = sampleRate;
953  m_configChanged = true;
954  update();
956 }
957 
958 void GLScope::setTimeBase(int timeBase)
959 {
960  m_timeBase = timeBase;
961  m_configChanged = true;
962  update();
963 }
964 
965 void GLScope::setTriggerPre(uint32_t triggerPre, bool emitSignal)
966 {
967  m_triggerPre = triggerPre;
968  m_configChanged = true;
969  update();
970 
971  if (emitSignal) {
973  }
974 }
975 
976 void GLScope::setTimeOfsProMill(int timeOfsProMill)
977 {
978  m_timeOfsProMill = timeOfsProMill;
979  m_configChanged = true;
980  update();
981 }
982 
984 {
985  m_focusedTraceIndex = traceIndex;
986  m_configChanged = true;
987  update();
988 }
989 
991 {
992  m_displayMode = displayMode;
993  m_configChanged = true;
994  update();
995 }
996 
997 void GLScope::setTraceSize(int traceSize, bool emitSignal)
998 {
999  m_traceSize = traceSize;
1000  m_configChanged = true;
1001  update();
1002 
1003  if (emitSignal) {
1005  }
1006 }
1007 
1009 {
1010  m_configChanged = true;
1011  update();
1012 }
1013 
1015 {
1016  m_configChanged = false;
1017 
1018  QFontMetrics fm(font());
1019  //float t_start = ((m_timeOfsProMill / 1000.0) * ((float) m_traceSize / m_sampleRate)) - ((float) m_triggerPre / m_sampleRate);
1020  float t_start = (((m_timeOfsProMill / 1000.0f) * (float) m_traceSize) / m_sampleRate) - ((float) m_triggerPre / m_sampleRate);
1021  float t_len = ((float) m_traceSize / m_sampleRate) / (float) m_timeBase;
1022 
1023  // scales
1024 
1025  m_x1Scale.setRange(Unit::Time, t_start, t_start + t_len); // time scale
1026 
1027  if (m_displayMode == DisplayPol)
1028  {
1029  setYScale(m_x2Scale, 0); // polar scale (X)
1030  }
1031  else
1032  {
1033  m_x2Scale.setRange(Unit::Time, t_start, t_start + t_len); // time scale
1034  }
1035 
1036  if (m_traces->size() > 0)
1037  {
1038  setYScale(m_y1Scale, 0); // This is always the X trace (trace #0)
1039  }
1040 
1041  if ((m_traces->size() > 1) && (m_focusedTraceIndex < m_traces->size()))
1042  {
1043  setYScale(m_y2Scale, m_focusedTraceIndex > 0 ? m_focusedTraceIndex : 1); // if Highlighted trace is #0 (X trace) set it to first Y trace (trace #1)
1044  }
1045  else
1046  {
1047  setYScale(m_y2Scale, 0); // Default to the X trace (trace #0) - If there is only one trace it should not get there (Y displays disabled in the UI)
1048  }
1049 
1050  // display arrangements
1051 
1052  if ((m_displayMode == DisplayX) || (m_displayMode == DisplayY)) // unique displays
1053  {
1055  }
1056  else if (m_displayMode == DisplayXYV) // both displays vertically arranged
1057  {
1059  }
1060  else if (m_displayMode == DisplayXYH) // both displays horizontally arranged
1061  {
1063  }
1064  else if (m_displayMode == DisplayPol) // horizontal arrangement: XY stacked on left and polar on right
1065  {
1066  setPolarDisplays();
1067  }
1068 
1073 
1074  int start = (m_timeOfsProMill/1000.0) * m_traceSize;
1075  int end = std::min(start + m_traceSize/m_timeBase, m_traceSize);
1076 
1077  if(end - start < 2)
1078  start--;
1079 
1080  m_q3Polar.allocate(2*(end - start));
1081 }
1082 
1084 {
1085  QFontMetrics fm(font());
1086  int M = fm.width("-");
1087  int scopeHeight = height() - m_topMargin - m_botMargin;
1088  int scopeWidth = width() - m_leftMargin - m_rightMargin;
1089 
1090  // X display
1091 
1092  m_glScopeRect1 = QRectF(
1093  (float) m_leftMargin / (float) width(),
1094  (float) m_topMargin / (float) height(),
1095  (float) scopeWidth / (float) width(),
1096  (float) scopeHeight / (float) height()
1097  );
1098 
1099  m_glScopeMatrix1.setToIdentity();
1100  m_glScopeMatrix1.translate (
1101  -1.0f + ((float) 2*m_leftMargin / (float) width()),
1102  1.0f - ((float) 2*m_topMargin / (float) height())
1103  );
1104  m_glScopeMatrix1.scale (
1105  (float) 2*scopeWidth / (float) width(),
1106  (float) -2*scopeHeight / (float) height()
1107  );
1108 
1109  m_glBot1ScaleMatrix.setToIdentity();
1110  m_glBot1ScaleMatrix.translate (
1111  -1.0f + ((float) 2*m_leftMargin / (float) width()),
1112  1.0f - ((float) 2*(scopeHeight + m_topMargin + 1) / (float) height())
1113  );
1114  m_glBot1ScaleMatrix.scale (
1115  (float) 2*scopeWidth / (float) width(),
1116  (float) -2*(m_botMargin - 1) / (float) height()
1117  );
1118 
1119  m_glLeft1ScaleMatrix.setToIdentity();
1120  m_glLeft1ScaleMatrix.translate (
1121  -1.0f,
1122  1.0f - ((float) 2*m_topMargin / (float) height())
1123  );
1124  m_glLeft1ScaleMatrix.scale (
1125  (float) 2*(m_leftMargin-1) / (float) width(),
1126  (float) -2*scopeHeight / (float) height()
1127  );
1128 
1129  // Y displays
1130 
1131  m_glScopeRect2 = QRectF(
1132  (float) m_leftMargin / (float) width(),
1133  (float) m_topMargin / (float) height(),
1134  (float) scopeWidth / (float) width(),
1135  (float) scopeHeight / (float) height()
1136  );
1137 
1138  m_glScopeMatrix2.setToIdentity();
1139  m_glScopeMatrix2.translate (
1140  -1.0f + ((float) 2*m_leftMargin / (float) width()),
1141  1.0f - ((float) 2*m_topMargin / (float) height())
1142  );
1143  m_glScopeMatrix2.scale (
1144  (float) 2*scopeWidth / (float) width(),
1145  (float) -2*scopeHeight / (float) height()
1146  );
1147 
1148  m_glBot2ScaleMatrix.setToIdentity();
1149  m_glBot2ScaleMatrix.translate (
1150  -1.0f + ((float) 2*m_leftMargin / (float) width()),
1151  1.0f - ((float) 2*(scopeHeight + m_topMargin + 1) / (float) height())
1152  );
1153  m_glBot2ScaleMatrix.scale (
1154  (float) 2*scopeWidth / (float) width(),
1155  (float) -2*(m_botMargin - 1) / (float) height()
1156  );
1157 
1158  m_glLeft2ScaleMatrix.setToIdentity();
1159  m_glLeft2ScaleMatrix.translate (
1160  -1.0f,
1161  1.0f - ((float) 2*m_topMargin / (float) height())
1162  );
1163  m_glLeft2ScaleMatrix.scale (
1164  (float) 2*(m_leftMargin-1) / (float) width(),
1165  (float) -2*scopeHeight / (float) height()
1166  );
1167 
1168  { // X horizontal scale (X1)
1169  m_x1Scale.setSize(scopeWidth);
1170 
1171  m_bot1ScalePixmap = QPixmap(
1172  scopeWidth,
1173  m_botMargin - 1
1174  );
1175 
1176  const ScaleEngine::TickList* tickList;
1177  const ScaleEngine::Tick* tick;
1178 
1179  m_bot1ScalePixmap.fill(Qt::black);
1180  QPainter painter(&m_bot1ScalePixmap);
1181  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1182  painter.setFont(font());
1183  tickList = &m_x1Scale.getTickList();
1184 
1185  for(int i = 0; i < tickList->count(); i++) {
1186  tick = &(*tickList)[i];
1187  if(tick->major) {
1188  if(tick->textSize > 0) {
1189  painter.drawText(QPointF(tick->textPos, fm.height() - 1), tick->text);
1190  }
1191  }
1192  }
1193 
1195  } // X horizontal scale
1196 
1197  { // Y horizontal scale (X2)
1198  m_x2Scale.setSize(scopeWidth);
1199 
1200  m_bot2ScalePixmap = QPixmap(
1201  scopeWidth,
1202  m_botMargin - 1
1203  );
1204 
1205  const ScaleEngine::TickList* tickList;
1206  const ScaleEngine::Tick* tick;
1207 
1208  m_bot2ScalePixmap.fill(Qt::black);
1209  QPainter painter(&m_bot2ScalePixmap);
1210  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1211  painter.setFont(font());
1212  tickList = &m_x2Scale.getTickList();
1213 
1214  for(int i = 0; i < tickList->count(); i++) {
1215  tick = &(*tickList)[i];
1216  if(tick->major) {
1217  if(tick->textSize > 0) {
1218  painter.drawText(QPointF(tick->textPos, fm.height() - 1), tick->text);
1219  }
1220  }
1221  }
1222 
1224  } // Y horizontal scale
1225 
1226  { // X vertical scale (Y1)
1227  m_y1Scale.setSize(scopeHeight);
1228 
1229  m_left1ScalePixmap = QPixmap(
1230  m_leftMargin - 1,
1231  scopeHeight
1232  );
1233 
1234  const ScaleEngine::TickList* tickList;
1235  const ScaleEngine::Tick* tick;
1236 
1237  m_left1ScalePixmap.fill(Qt::black);
1238  QPainter painter(&m_left1ScalePixmap);
1239  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1240  painter.setFont(font());
1241  tickList = &m_y1Scale.getTickList();
1242 
1243  for(int i = 0; i < tickList->count(); i++) {
1244  tick = &(*tickList)[i];
1245  if(tick->major) {
1246  if(tick->textSize > 0) {
1247  painter.drawText(QPointF(m_leftMargin - M - tick->textSize, m_topMargin + scopeHeight - tick->textPos - fm.ascent()/2), tick->text);
1248  }
1249  }
1250  }
1251 
1253  } // X vertical scale
1254 
1255  { // Y vertical scale (Y2)
1256  m_y2Scale.setSize(scopeHeight);
1257 
1258  m_left2ScalePixmap = QPixmap(
1259  m_leftMargin - 1,
1260  scopeHeight
1261  );
1262 
1263  const ScaleEngine::TickList* tickList;
1264  const ScaleEngine::Tick* tick;
1265 
1266  m_left2ScalePixmap.fill(Qt::black);
1267  QPainter painter(&m_left2ScalePixmap);
1268  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1269  painter.setFont(font());
1270  tickList = &m_y2Scale.getTickList();
1271 
1272  for(int i = 0; i < tickList->count(); i++) {
1273  tick = &(*tickList)[i];
1274  if(tick->major) {
1275  if(tick->textSize > 0) {
1276  painter.drawText(QPointF(m_leftMargin - M - tick->textSize, m_topMargin + scopeHeight - tick->textPos - fm.ascent()/2), tick->text);
1277  }
1278  }
1279  }
1280 
1282  } // Y vertical scale
1283 }
1284 
1286 {
1287  QFontMetrics fm(font());
1288  int M = fm.width("-");
1289  int scopeHeight = (height() - m_topMargin) / 2 - m_botMargin;
1290  int scopeWidth = width() - m_leftMargin - m_rightMargin;
1291 
1292  // X display
1293 
1294  m_glScopeRect1 = QRectF(
1295  (float) m_leftMargin / (float) width(),
1296  (float) m_topMargin / (float) height(),
1297  (float) scopeWidth / (float) width(),
1298  (float) scopeHeight / (float) height()
1299  );
1300 
1301  m_glScopeMatrix1.setToIdentity();
1302  m_glScopeMatrix1.translate (
1303  -1.0f + ((float) 2*m_leftMargin / (float) width()),
1304  1.0f - ((float) 2*m_topMargin / (float) height())
1305  );
1306  m_glScopeMatrix1.scale (
1307  (float) 2*scopeWidth / (float) width(),
1308  (float) -2*scopeHeight / (float) height()
1309  );
1310 
1311  m_glBot1ScaleMatrix.setToIdentity();
1312  m_glBot1ScaleMatrix.translate (
1313  -1.0f + ((float) 2*m_leftMargin / (float) width()),
1314  1.0f - ((float) 2*(scopeHeight + m_topMargin + 1) / (float) height())
1315  );
1316  m_glBot1ScaleMatrix.scale (
1317  (float) 2*scopeWidth / (float) width(),
1318  (float) -2*(m_botMargin - 1) / (float) height()
1319  );
1320 
1321  m_glLeft1ScaleMatrix.setToIdentity();
1322  m_glLeft1ScaleMatrix.translate (
1323  -1.0f,
1324  1.0f - ((float) 2*m_topMargin / (float) height())
1325  );
1326  m_glLeft1ScaleMatrix.scale (
1327  (float) 2*(m_leftMargin-1) / (float) width(),
1328  (float) -2*scopeHeight / (float) height()
1329  );
1330 
1331  // Y display
1332 
1333  m_glScopeRect2 = QRectF(
1334  (float) m_leftMargin / (float)width(),
1335  (float) (m_botMargin + m_topMargin + scopeHeight) / (float)height(),
1336  (float) scopeWidth / (float)width(),
1337  (float) scopeHeight / (float)height()
1338  );
1339 
1340  m_glScopeMatrix2.setToIdentity();
1341  m_glScopeMatrix2.translate (
1342  -1.0f + ((float) 2*m_leftMargin / (float) width()),
1343  1.0f - ((float) 2*(m_botMargin + m_topMargin + scopeHeight) / (float) height())
1344  );
1345  m_glScopeMatrix2.scale (
1346  (float) 2*scopeWidth / (float) width(),
1347  (float) -2*scopeHeight / (float) height()
1348  );
1349 
1350  m_glBot2ScaleMatrix.setToIdentity();
1351  m_glBot2ScaleMatrix.translate (
1352  -1.0f + ((float) 2*m_leftMargin / (float) width()),
1353  1.0f - ((float) 2*(scopeHeight + m_topMargin + scopeHeight + m_botMargin + 1) / (float) height())
1354  );
1355  m_glBot2ScaleMatrix.scale (
1356  (float) 2*scopeWidth / (float) width(),
1357  (float) -2*(m_botMargin - 1) / (float) height()
1358  );
1359 
1360  m_glLeft2ScaleMatrix.setToIdentity();
1361  m_glLeft2ScaleMatrix.translate (
1362  -1.0f,
1363  1.0f - ((float) 2*(m_topMargin + scopeHeight + m_botMargin) / (float) height())
1364  );
1365  m_glLeft2ScaleMatrix.scale (
1366  (float) 2*(m_leftMargin-1) / (float) width(),
1367  (float) -2*scopeHeight / (float) height()
1368  );
1369 
1370  { // X horizontal scale (X1)
1371  m_x1Scale.setSize(scopeWidth);
1372 
1373  m_bot1ScalePixmap = QPixmap(
1374  scopeWidth,
1375  m_botMargin - 1
1376  );
1377 
1378  const ScaleEngine::TickList* tickList;
1379  const ScaleEngine::Tick* tick;
1380 
1381  m_bot1ScalePixmap.fill(Qt::black);
1382  QPainter painter(&m_bot1ScalePixmap);
1383  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1384  painter.setFont(font());
1385  tickList = &m_x1Scale.getTickList();
1386 
1387  for(int i = 0; i < tickList->count(); i++) {
1388  tick = &(*tickList)[i];
1389  if(tick->major) {
1390  if(tick->textSize > 0) {
1391  painter.drawText(QPointF(tick->textPos, fm.height() - 1), tick->text);
1392  }
1393  }
1394  }
1395 
1397  } // X horizontal scale (X1)
1398 
1399  { // Y horizontal scale (X2)
1400  m_x2Scale.setSize(scopeWidth);
1401  m_bot2ScalePixmap = QPixmap(
1402  scopeWidth,
1403  m_botMargin - 1
1404  );
1405 
1406  const ScaleEngine::TickList* tickList;
1407  const ScaleEngine::Tick* tick;
1408 
1409  m_bot2ScalePixmap.fill(Qt::black);
1410  QPainter painter(&m_bot2ScalePixmap);
1411  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1412  painter.setFont(font());
1413  tickList = &m_x2Scale.getTickList();
1414 
1415  for(int i = 0; i < tickList->count(); i++) {
1416  tick = &(*tickList)[i];
1417  if(tick->major) {
1418  if(tick->textSize > 0) {
1419  painter.drawText(QPointF(tick->textPos, fm.height() - 1), tick->text);
1420  }
1421  }
1422  }
1423 
1425  } // Y horizontal scale (X2)
1426 
1427  { // X vertical scale (Y1)
1428  m_y1Scale.setSize(scopeHeight);
1429 
1430  m_left1ScalePixmap = QPixmap(
1431  m_leftMargin - 1,
1432  scopeHeight
1433  );
1434 
1435  const ScaleEngine::TickList* tickList;
1436  const ScaleEngine::Tick* tick;
1437 
1438  m_left1ScalePixmap.fill(Qt::black);
1439  QPainter painter(&m_left1ScalePixmap);
1440  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1441  painter.setFont(font());
1442  tickList = &m_y1Scale.getTickList();
1443 
1444  for(int i = 0; i < tickList->count(); i++) {
1445  tick = &(*tickList)[i];
1446  if(tick->major) {
1447  if(tick->textSize > 0) {
1448  painter.drawText(QPointF(m_leftMargin - M - tick->textSize, m_topMargin + scopeHeight - tick->textPos - fm.ascent()/2), tick->text);
1449  }
1450  }
1451  }
1452 
1454  } // X vertical scale (Y1)
1455 
1456  { // Y vertical scale (Y2)
1457  m_y2Scale.setSize(scopeHeight);
1458 
1459  m_left2ScalePixmap = QPixmap(
1460  m_leftMargin - 1,
1461  scopeHeight
1462  );
1463 
1464  const ScaleEngine::TickList* tickList;
1465  const ScaleEngine::Tick* tick;
1466 
1467  m_left2ScalePixmap.fill(Qt::black);
1468  QPainter painter(&m_left2ScalePixmap);
1469  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1470  painter.setFont(font());
1471  tickList = &m_y2Scale.getTickList();
1472 
1473  for(int i = 0; i < tickList->count(); i++) {
1474  tick = &(*tickList)[i];
1475  if(tick->major) {
1476  if(tick->textSize > 0) {
1477  painter.drawText(QPointF(m_leftMargin - M - tick->textSize, m_topMargin + scopeHeight - tick->textPos - fm.ascent()/2), tick->text);
1478  }
1479  }
1480  }
1481 
1483  } // Y vertical scale (Y2)
1484 }
1485 
1487 {
1488  QFontMetrics fm(font());
1489  int M = fm.width("-");
1490  int scopeHeight = height() - m_topMargin - m_botMargin;
1491  int scopeWidth = (width() - m_rightMargin)/2 - m_leftMargin;
1492 
1493  // X display
1494 
1495  m_glScopeRect1 = QRectF(
1496  (float) m_leftMargin / (float) width(),
1497  (float) m_topMargin / (float) height(),
1498  (float) scopeWidth / (float) width(),
1499  (float) scopeHeight / (float) height()
1500  );
1501  m_glScopeMatrix1.setToIdentity();
1502  m_glScopeMatrix1.translate (
1503  -1.0f + ((float) 2*m_leftMargin / (float) width()),
1504  1.0f - ((float) 2*m_topMargin / (float) height())
1505  );
1506  m_glScopeMatrix1.scale (
1507  (float) 2*scopeWidth / (float) width(),
1508  (float) -2*scopeHeight / (float) height()
1509  );
1510 
1511  m_glBot1ScaleMatrix.setToIdentity();
1512  m_glBot1ScaleMatrix.translate (
1513  -1.0f + ((float) 2*m_leftMargin / (float) width()),
1514  1.0f - ((float) 2*(scopeHeight + m_topMargin + 1) / (float) height())
1515  );
1516  m_glBot1ScaleMatrix.scale (
1517  (float) 2*scopeWidth / (float) width(),
1518  (float) -2*(m_botMargin - 1) / (float) height()
1519  );
1520 
1521  m_glLeft1ScaleMatrix.setToIdentity();
1522  m_glLeft1ScaleMatrix.translate (
1523  -1.0f,
1524  1.0f - ((float) 2*m_topMargin / (float) height())
1525  );
1526  m_glLeft1ScaleMatrix.scale (
1527  (float) 2*(m_leftMargin-1) / (float) width(),
1528  (float) -2*scopeHeight / (float) height()
1529  );
1530 
1531  // Y display
1532 
1533  m_glScopeRect2 = QRectF(
1534  (float)(m_leftMargin + m_leftMargin + ((width() - m_leftMargin - m_leftMargin - m_rightMargin) / 2)) / (float)width(),
1535  (float)m_topMargin / (float)height(),
1536  (float)((width() - m_leftMargin - m_leftMargin - m_rightMargin) / 2) / (float)width(),
1537  (float)(height() - m_topMargin - m_botMargin) / (float)height()
1538  );
1539  m_glScopeMatrix2.setToIdentity();
1540  m_glScopeMatrix2.translate (
1541  -1.0f + ((float) 2*(m_leftMargin + m_leftMargin + ((width() - m_leftMargin - m_leftMargin - m_rightMargin) / 2)) / (float) width()),
1542  1.0f - ((float) 2*m_topMargin / (float) height())
1543  );
1544  m_glScopeMatrix2.scale (
1545  (float) 2*((width() - m_leftMargin - m_leftMargin - m_rightMargin) / 2) / (float) width(),
1546  (float) -2*(height() - m_topMargin - m_botMargin) / (float) height()
1547  );
1548 
1549  m_glBot2ScaleMatrix.setToIdentity();
1550  m_glBot2ScaleMatrix.translate (
1551  -1.0f + ((float) 2*(m_leftMargin + m_leftMargin + scopeWidth) / (float) width()),
1552  1.0f - ((float) 2*(scopeHeight + m_topMargin + 1) / (float) height())
1553  );
1554  m_glBot2ScaleMatrix.scale (
1555  (float) 2*scopeWidth / (float) width(),
1556  (float) -2*(m_botMargin - 1) / (float) height()
1557  );
1558 
1559  m_glLeft2ScaleMatrix.setToIdentity();
1560  m_glLeft2ScaleMatrix.translate (
1561  -1.0f + (float) 2*(m_leftMargin + scopeWidth) / (float) width(),
1562  1.0f - ((float) 2*m_topMargin / (float) height())
1563  );
1564  m_glLeft2ScaleMatrix.scale (
1565  (float) 2*(m_leftMargin-1) / (float) width(),
1566  (float) -2*scopeHeight / (float) height()
1567  );
1568 
1569  { // X horizontal scale (X1)
1570  m_x1Scale.setSize(scopeWidth);
1571 
1572  m_bot1ScalePixmap = QPixmap(
1573  scopeWidth,
1574  m_botMargin - 1
1575  );
1576 
1577  const ScaleEngine::TickList* tickList;
1578  const ScaleEngine::Tick* tick;
1579 
1580  m_bot1ScalePixmap.fill(Qt::black);
1581  QPainter painter(&m_bot1ScalePixmap);
1582  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1583  painter.setFont(font());
1584  tickList = &m_x1Scale.getTickList();
1585 
1586  for(int i = 0; i < tickList->count(); i++) {
1587  tick = &(*tickList)[i];
1588  if(tick->major) {
1589  if(tick->textSize > 0) {
1590  painter.drawText(QPointF(tick->textPos, fm.height() - 1), tick->text);
1591  }
1592  }
1593  }
1594 
1596 
1597  } // X horizontal scale (X1)
1598 
1599  { // Y horizontal scale (X2)
1600  m_x2Scale.setSize(scopeWidth);
1601  m_bot2ScalePixmap = QPixmap(
1602  scopeWidth,
1603  m_botMargin - 1
1604  );
1605 
1606  const ScaleEngine::TickList* tickList;
1607  const ScaleEngine::Tick* tick;
1608 
1609  m_bot2ScalePixmap.fill(Qt::black);
1610  QPainter painter(&m_bot2ScalePixmap);
1611  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1612  painter.setFont(font());
1613  tickList = &m_x2Scale.getTickList();
1614 
1615  for(int i = 0; i < tickList->count(); i++) {
1616  tick = &(*tickList)[i];
1617  if(tick->major) {
1618  if(tick->textSize > 0) {
1619  painter.drawText(QPointF(tick->textPos, fm.height() - 1), tick->text);
1620  }
1621  }
1622  }
1623 
1625  } // Y horizontal scale (X2)
1626 
1627  { // X vertical scale (Y1)
1628  m_y1Scale.setSize(scopeHeight);
1629 
1630  m_left1ScalePixmap = QPixmap(
1631  m_leftMargin - 1,
1632  scopeHeight
1633  );
1634 
1635  const ScaleEngine::TickList* tickList;
1636  const ScaleEngine::Tick* tick;
1637 
1638  m_left1ScalePixmap.fill(Qt::black);
1639  QPainter painter(&m_left1ScalePixmap);
1640  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1641  painter.setFont(font());
1642  tickList = &m_y1Scale.getTickList();
1643 
1644  for(int i = 0; i < tickList->count(); i++) {
1645  tick = &(*tickList)[i];
1646  if(tick->major) {
1647  if(tick->textSize > 0) {
1648  painter.drawText(QPointF(m_leftMargin - M - tick->textSize, m_topMargin + scopeHeight - tick->textPos - fm.ascent()/2), tick->text);
1649  }
1650  }
1651  }
1652 
1654  } // X vertical scale (Y1)
1655 
1656  { // Y vertical scale (Y2)
1657  m_y2Scale.setSize(scopeHeight);
1658 
1659  m_left2ScalePixmap = QPixmap(
1660  m_leftMargin - 1,
1661  scopeHeight
1662  );
1663 
1664  const ScaleEngine::TickList* tickList;
1665  const ScaleEngine::Tick* tick;
1666 
1667  m_left2ScalePixmap.fill(Qt::black);
1668  QPainter painter(&m_left2ScalePixmap);
1669  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1670  painter.setFont(font());
1671  tickList = &m_y2Scale.getTickList();
1672 
1673  for(int i = 0; i < tickList->count(); i++) {
1674  tick = &(*tickList)[i];
1675  if(tick->major) {
1676  if(tick->textSize > 0) {
1677  painter.drawText(QPointF(m_leftMargin - M - tick->textSize, m_topMargin + scopeHeight - tick->textPos - fm.ascent()/2), tick->text);
1678  }
1679  }
1680  }
1681 
1683  } // Y vertical scale (Y2)
1684 }
1685 
1687 {
1688  QFontMetrics fm(font());
1689  int M = fm.width("-");
1690  int scopeHeight = height() - m_topMargin - m_botMargin;
1691  int scopeWidth = (width() - m_rightMargin)/2 - m_leftMargin;
1692  int scopeDim = std::min(scopeWidth, scopeHeight);
1693  scopeWidth += scopeWidth - scopeDim;
1694 
1695  // Mixed XY display (left)
1696 
1697  m_glScopeRect1 = QRectF(
1698  (float) m_leftMargin / (float) width(),
1699  (float) m_topMargin / (float) height(),
1700  (float) (scopeWidth-m_leftMargin) / (float) width(),
1701  (float) scopeHeight / (float) height()
1702  );
1703  m_glScopeMatrix1.setToIdentity();
1704  m_glScopeMatrix1.translate (
1705  -1.0f + ((float) 2*m_leftMargin / (float) width()),
1706  1.0f - ((float) 2*m_topMargin / (float) height())
1707  );
1708  m_glScopeMatrix1.scale (
1709  (float) 2*(scopeWidth-m_leftMargin) / (float) width(),
1710  (float) -2*scopeHeight / (float) height()
1711  );
1712 
1713  m_glBot1ScaleMatrix.setToIdentity();
1714  m_glBot1ScaleMatrix.translate (
1715  -1.0f + ((float) 2*m_leftMargin / (float) width()),
1716  1.0f - ((float) 2*(scopeHeight + m_topMargin + 1) / (float) height())
1717  );
1718  m_glBot1ScaleMatrix.scale (
1719  (float) 2*(scopeWidth-m_leftMargin) / (float) width(),
1720  (float) -2*(m_botMargin - 1) / (float) height()
1721  );
1722 
1723  m_glLeft1ScaleMatrix.setToIdentity();
1724  m_glLeft1ScaleMatrix.translate (
1725  -1.0f,
1726  1.0f - ((float) 2*m_topMargin / (float) height())
1727  );
1728  m_glLeft1ScaleMatrix.scale (
1729  (float) 2*(m_leftMargin-1) / (float) width(),
1730  (float) -2*scopeHeight / (float) height()
1731  );
1732 
1733  m_glRight1ScaleMatrix.setToIdentity();
1734  m_glRight1ScaleMatrix.translate (
1735  -1.0f + ((float) 2*scopeWidth / (float) width()),
1736  1.0f - ((float) 2*m_topMargin / (float) height())
1737  );
1738  m_glRight1ScaleMatrix.scale (
1739  (float) 2*(m_leftMargin-1) / (float) width(),
1740  (float) -2*scopeHeight / (float) height()
1741  );
1742 
1743  // Polar XY display (right)
1744 
1745  m_glScopeRect2 = QRectF(
1746  (float)(m_leftMargin + scopeWidth + m_leftMargin) / (float)width(),
1747  (float)m_topMargin / (float)height(),
1748  (float) scopeDim / (float)width(),
1749  (float)(height() - m_topMargin - m_botMargin) / (float)height()
1750  );
1751  m_glScopeMatrix2.setToIdentity();
1752  m_glScopeMatrix2.translate (
1753  -1.0f + ((float) 2*(m_leftMargin + scopeWidth + m_leftMargin) / (float) width()),
1754  1.0f - ((float) 2*m_topMargin / (float) height())
1755  );
1756  m_glScopeMatrix2.scale (
1757  (float) 2*scopeDim / (float) width(),
1758  (float) -2*(height() - m_topMargin - m_botMargin) / (float) height()
1759  );
1760 
1761  m_glBot2ScaleMatrix.setToIdentity();
1762  m_glBot2ScaleMatrix.translate (
1763  -1.0f + ((float) 2*(m_leftMargin + m_leftMargin + scopeWidth) / (float) width()),
1764  1.0f - ((float) 2*(scopeHeight + m_topMargin + 1) / (float) height())
1765  );
1766  m_glBot2ScaleMatrix.scale (
1767  (float) 2*scopeDim / (float) width(),
1768  (float) -2*(m_botMargin - 1) / (float) height()
1769  );
1770 
1771  m_glLeft2ScaleMatrix.setToIdentity();
1772  m_glLeft2ScaleMatrix.translate (
1773  -1.0f + (float) 2*(m_leftMargin + scopeWidth) / (float) width(),
1774  1.0f - ((float) 2*m_topMargin / (float) height())
1775  );
1776  m_glLeft2ScaleMatrix.scale (
1777  (float) 2*(m_leftMargin-1) / (float) width(),
1778  (float) -2*scopeHeight / (float) height()
1779  );
1780 
1781  { // Mixed XY horizontal scale (X1)
1782  m_x1Scale.setSize(scopeWidth);
1783 
1784  m_bot1ScalePixmap = QPixmap(
1785  scopeWidth,
1786  m_botMargin - 1
1787  );
1788 
1789  const ScaleEngine::TickList* tickList;
1790  const ScaleEngine::Tick* tick;
1791 
1792  m_bot1ScalePixmap.fill(Qt::black);
1793  QPainter painter(&m_bot1ScalePixmap);
1794  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1795  painter.setFont(font());
1796  tickList = &m_x1Scale.getTickList();
1797 
1798  for(int i = 0; i < tickList->count(); i++) {
1799  tick = &(*tickList)[i];
1800  if(tick->major) {
1801  if(tick->textSize > 0) {
1802  painter.drawText(QPointF(tick->textPos, fm.height() - 1), tick->text);
1803  }
1804  }
1805  }
1806 
1808  } // Mixed XY horizontal scale (X1)
1809 
1810  { // Polar XY horizontal scale (X2)
1811  m_x2Scale.setSize(scopeDim);
1812  m_bot2ScalePixmap = QPixmap(
1813  scopeDim,
1814  m_botMargin - 1
1815  );
1816 
1817  const ScaleEngine::TickList* tickList;
1818  const ScaleEngine::Tick* tick;
1819 
1820  m_bot2ScalePixmap.fill(Qt::black);
1821  QPainter painter(&m_bot2ScalePixmap);
1822  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1823  painter.setFont(font());
1824  tickList = &m_x2Scale.getTickList();
1825 
1826  for(int i = 0; i < tickList->count(); i++) {
1827  tick = &(*tickList)[i];
1828  if(tick->major) {
1829  if(tick->textSize > 0) {
1830  painter.drawText(QPointF(tick->textPos, fm.height() - 1), tick->text);
1831  }
1832  }
1833  }
1834 
1836  } // Polar XY horizontal scale (X2)
1837 
1838  { // Mixed XY vertical scale (Y1)
1839  m_y1Scale.setSize(scopeHeight);
1840 
1841  m_left1ScalePixmap = QPixmap(
1842  m_leftMargin - 1,
1843  scopeHeight
1844  );
1845 
1846  const ScaleEngine::TickList* tickList;
1847  const ScaleEngine::Tick* tick;
1848 
1849  m_left1ScalePixmap.fill(Qt::black);
1850  QPainter painter(&m_left1ScalePixmap);
1851  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1852  painter.setFont(font());
1853  tickList = &m_y1Scale.getTickList();
1854 
1855  for(int i = 0; i < tickList->count(); i++) {
1856  tick = &(*tickList)[i];
1857  if(tick->major) {
1858  if(tick->textSize > 0) {
1859  painter.drawText(QPointF(m_leftMargin - M - tick->textSize, m_topMargin + scopeHeight - tick->textPos - fm.ascent()/2), tick->text);
1860  }
1861  }
1862  }
1863 
1865 
1866  } // Mixed XY vertical scale (Y1)
1867 
1868  { // Polar XY vertical scale (Y2)
1869  m_y2Scale.setSize(scopeHeight);
1870 
1871  m_left2ScalePixmap = QPixmap(
1872  m_leftMargin - 1,
1873  scopeHeight
1874  );
1875 
1876  const ScaleEngine::TickList* tickList;
1877  const ScaleEngine::Tick* tick;
1878 
1879  m_left2ScalePixmap.fill(Qt::black);
1880  QPainter painter(&m_left2ScalePixmap);
1881  painter.setPen(QColor(0xf0, 0xf0, 0xff));
1882  painter.setFont(font());
1883  tickList = &m_y2Scale.getTickList();
1884 
1885  for(int i = 0; i < tickList->count(); i++) {
1886  tick = &(*tickList)[i];
1887  if(tick->major) {
1888  if(tick->textSize > 0) {
1889  painter.drawText(QPointF(m_leftMargin - M - tick->textSize, m_topMargin + scopeHeight - tick->textPos - fm.ascent()/2), tick->text);
1890  }
1891  }
1892  }
1893 
1895  } // Polar XY vertical scale (Y2)
1896 }
1897 
1898 void GLScope::setYScale(ScaleEngine& scale, uint32_t highlightedTraceIndex)
1899 {
1900  ScopeVis::TraceData& traceData = (*m_tracesData)[highlightedTraceIndex];
1901  double amp_range = 2.0 / traceData.m_amp;
1902  double amp_ofs = traceData.m_ofs;
1903  double pow_floor = -100.0 + traceData.m_ofs * 100.0;
1904  double pow_range = 100.0 / traceData.m_amp;
1905 
1906  switch (traceData.m_projectionType)
1907  {
1908  case Projector::ProjectionMagDB: // dB scale
1909  scale.setRange(Unit::Decibel, pow_floor, pow_floor + pow_range);
1910  break;
1913  if (amp_range < 1e-6) {
1914  scale.setRange(Unit::None, amp_ofs * 1e9, amp_range * 1e9 + amp_ofs * 1e9);
1915  } else if (amp_range < 1e-3) {
1916  scale.setRange(Unit::None, amp_ofs * 1e6, amp_range * 1e6 + amp_ofs * 1e6);
1917  } else if (amp_range < 1.0) {
1918  scale.setRange(Unit::None, amp_ofs * 1e3, amp_range * 1e3 + amp_ofs * 1e3);
1919  } else {
1920  scale.setRange(Unit::None, amp_ofs, amp_range + amp_ofs);
1921  }
1922  break;
1923  case Projector::ProjectionPhase: // Phase or frequency
1925  scale.setRange(Unit::None, -1.0/traceData.m_amp + amp_ofs, 1.0/traceData.m_amp + amp_ofs);
1926  break;
1927  case Projector::ProjectionReal: // Linear generic
1929  default:
1930  if (amp_range < 1e-6) {
1931  scale.setRange(Unit::None, - amp_range * 5e8 + amp_ofs * 1e9, amp_range * 5e8 + amp_ofs * 1e9);
1932  } else if (amp_range < 1e-3) {
1933  scale.setRange(Unit::None, - amp_range * 5e5 + amp_ofs * 1e6, amp_range * 5e5 + amp_ofs * 1e6);
1934  } else if (amp_range < 1.0) {
1935  scale.setRange(Unit::None, - amp_range * 5e2 + amp_ofs * 1e3, amp_range * 5e2 + amp_ofs * 1e3);
1936  } else {
1937  scale.setRange(Unit::None, - amp_range * 0.5 + amp_ofs, amp_range * 0.5 + amp_ofs);
1938  }
1939  break;
1940  }
1941 }
1942 
1944  const QString& text,
1945  const QColor& color,
1946  QPixmap& channelOverlayPixmap,
1947  const QRectF& glScopeRect)
1948 {
1949  if (text.isEmpty()) {
1950  return;
1951  }
1952 
1953  QFontMetricsF metrics(m_channelOverlayFont);
1954  QRectF textRect = metrics.boundingRect(text);
1955  QRectF overlayRect(0, 0, textRect.width()*1.05f + 4.0f, textRect.height());
1956  channelOverlayPixmap = QPixmap(overlayRect.width(), overlayRect.height());
1957  channelOverlayPixmap.fill(Qt::transparent);
1958  QPainter painter(&channelOverlayPixmap);
1959  painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing, false);
1960  painter.fillRect(overlayRect, QColor(0, 0, 0, 0x80));
1961  QColor textColor(color);
1962  textColor.setAlpha(0xC0);
1963  painter.setPen(textColor);
1964  painter.setFont(m_channelOverlayFont);
1965  painter.drawText(QPointF(2.0f, overlayRect.height() - 4.0f), text);
1966  painter.end();
1967 
1968  m_glShaderPowerOverlay.initTexture(channelOverlayPixmap.toImage());
1969 
1970  {
1971  GLfloat vtx1[] = {
1972  0, 1,
1973  1, 1,
1974  1, 0,
1975  0, 0
1976  };
1977  GLfloat tex1[] = {
1978  0, 1,
1979  1, 1,
1980  1, 0,
1981  0, 0
1982  };
1983 
1984  float shiftX = glScopeRect.width() - ((overlayRect.width() + 4.0f) / width());
1985  float shiftY = 4.0f / height();
1986  float rectX = glScopeRect.x() + shiftX;
1987  float rectY = glScopeRect.y() + shiftY;
1988  float rectW = overlayRect.width() / (float) width();
1989  float rectH = overlayRect.height() / (float) height();
1990 
1991  QMatrix4x4 mat;
1992  mat.setToIdentity();
1993  mat.translate(-1.0f + 2.0f * rectX, 1.0f - 2.0f * rectY);
1994  mat.scale(2.0f * rectW, -2.0f * rectH);
1995  m_glShaderPowerOverlay.drawSurface(mat, tex1, vtx1, 4);
1996  }
1997 }
1998 
2000 {
2001  if (m_dataChanged.load()) {
2002  update();
2003  }
2004 }
2005 
2006 void GLScope::connectTimer(const QTimer& timer)
2007 {
2008  qDebug() << "GLScope::connectTimer";
2009  disconnect(&m_timer, SIGNAL(timeout()), this, SLOT(tick()));
2010  connect(&timer, SIGNAL(timeout()), this, SLOT(tick()));
2011  m_timer.stop();
2012 }
2013 
2015 {
2016  //makeCurrent();
2022  //doneCurrent();
2023 }
2024 
void newTraces(std::vector< float *> *traces)
Definition: glscope.cpp:103
bool m_viewTrace
Trace visibility.
Definition: scopevis.h:67
void applyConfig()
Definition: glscope.cpp:1014
void setSize(float size)
QAtomicInt m_dataChanged
Definition: glscope.h:99
QTimer m_timer
Definition: glscope.h:97
void initializeGL()
Definition: glscope.cpp:137
void setTraceSize(int trceSize, bool emitSignal=false)
Definition: glscope.cpp:997
QPixmap m_left1ScalePixmap
Definition: glscope.h:120
QPixmap m_bot2ScalePixmap
Definition: glscope.h:123
void drawChannelOverlay(const QString &text, const QColor &color, QPixmap &channelOverlayPixmap, const QRectF &glScopeRect)
Definition: glscope.cpp:1943
void cleanup()
Definition: glscope.cpp:2014
QMatrix4x4 m_glBot2ScaleMatrix
Definition: glscope.h:118
void setTraces(std::vector< ScopeVis::TraceData > *tracesData, std::vector< float *> *traces)
Definition: glscope.cpp:97
ScaleEngine m_x2Scale
Display #2 X scale. Time scale.
Definition: glscope.h:132
static const int m_leftMargin
Definition: glscope.h:153
uint32_t m_focusedTraceIndex
Definition: glscope.h:107
QPixmap m_channelOverlayPixmap1
Definition: glscope.h:124
Calculate logarithmic (dB) of squared magnitude.
Definition: projector.h:31
void drawSegments(const QMatrix4x4 &transformMatrix, const QVector4D &color, GLfloat *vertices, int nbVertices)
ScaleEngine m_y1Scale
Display #1 Y scale. Always connected to trace #0 (X trace)
Definition: glscope.h:133
void preTriggerChanged(uint32_t)
number of samples
GLShaderSimple m_glShaderSimple
Definition: glscope.h:138
void setVerticalDisplays()
Arrange displays when X and Y are stacked vertically.
Definition: glscope.cpp:1285
std::vector< float * > * m_traces
Definition: glscope.h:91
IncrementalArray< GLfloat > m_q3TickY1
Definition: glscope.h:146
int m_traceSize
Definition: glscope.h:104
GLShaderTextured m_glShaderBottom1Scale
Definition: glscope.h:140
int m_displayGridIntensity
Definition: glscope.h:127
DisplayMode m_displayMode
Definition: glscope.h:96
QColor m_traceColor
Trace display color.
Definition: scopevis.h:61
float m_traceColorR
Trace display color - red shortcut.
Definition: scopevis.h:62
uint32_t m_triggerPre
Definition: glscope.h:103
void setTriggerPre(uint32_t triggerPre, bool emitSignal=false)
number of samples
Definition: glscope.cpp:965
float m_triggerDisplayLevel
Displayable trigger display level in -1:+1 scale. Off scale if not displayable.
Definition: scopevis.h:60
float m_traceColorG
Trace display color - green shortcut.
Definition: scopevis.h:63
QString m_textOverlay
Text overlay to display.
Definition: scopevis.h:66
void initTexture(const QImage &image, QOpenGLTexture::WrapMode wrapMode=QOpenGLTexture::Repeat)
QMatrix4x4 m_glScopeMatrix1
Definition: glscope.h:112
unsigned int uint32_t
Definition: rtptypes_win.h:46
IncrementalArray< GLfloat > m_q3TickY2
Definition: glscope.h:147
void traceSizeChanged(uint32_t)
bool m_displayXYPoints
Definition: glscope.h:129
QPixmap m_left2ScalePixmap
Definition: glscope.h:121
float m_triggerColorR
Trigger line display color - red shortcut.
Definition: scopevis.h:116
void setHorizontalDisplays()
Arrange displays when X and Y are stacked horizontally.
Definition: glscope.cpp:1486
float getSize()
Definition: scaleengine.h:80
void updateDisplay()
Definition: glscope.cpp:1008
void drawSurface(const QMatrix4x4 &transformMatrix, GLfloat *textureCoords, GLfloat *vertices, int nbVertices)
ScopeVis::TriggerData m_focusedTriggerData
Definition: glscope.h:93
GLShaderTextured m_glShaderLeft1Scale
Definition: glscope.h:139
int m_displayTraceIntensity
Definition: glscope.h:128
QFont m_channelOverlayFont
Definition: glscope.h:136
Calculate phase.
Definition: projector.h:32
float m_traceColorB
Trace display color - blue shortcut.
Definition: scopevis.h:64
void setUniqueDisplays()
Arrange displays when X and Y are unique on screen.
Definition: glscope.cpp:1083
QMatrix4x4 m_glBot1ScaleMatrix
Definition: glscope.h:117
void setPolarDisplays()
Arrange displays when X and Y are stacked over on the left and polar display is on the right...
Definition: glscope.cpp:1686
int32_t i
Definition: decimators.h:244
void paintGL()
Definition: glscope.cpp:199
GLShaderTextured m_glShaderLeft2Scale
Definition: glscope.h:141
IncrementalArray< GLfloat > m_q3TickX2
Definition: glscope.h:149
void drawContour(const QMatrix4x4 &transformMatrix, const QVector4D &color, GLfloat *vertices, int nbVertices)
void setFocusedTraceIndex(uint32_t traceIndex)
Definition: glscope.cpp:983
IncrementalArray< GLfloat > m_q3TickX1
Definition: glscope.h:148
Calculate linear magnitude or modulus.
Definition: projector.h:29
GLShaderTextured m_glShaderPowerOverlay
Definition: glscope.h:143
bool m_hasTextOverlay
True if a text overlay has to be displayed.
Definition: scopevis.h:65
QMatrix4x4 m_glRight1ScaleMatrix
Definition: glscope.h:115
void tick()
Definition: glscope.cpp:1999
void setFont(const QFont &font)
QAtomicInt m_processingTraceIndex
Definition: glscope.h:92
Calculate linear squared magnitude or power.
Definition: projector.h:30
void setTimeBase(int timeBase)
Definition: glscope.cpp:958
QPixmap m_channelOverlayPixmap2
Definition: glscope.h:125
float m_amp
Amplification factor.
Definition: scopevis.h:52
QMutex m_mutex
Definition: glscope.h:98
Calculate phase derivative i.e. instantaneous frequency scaled to sample rate.
Definition: projector.h:33
GLScope(QWidget *parent=0)
Definition: glscope.cpp:30
int m_sampleRate
Definition: glscope.h:101
GLShaderTextured m_glShaderBottom2Scale
Definition: glscope.h:142
int m_timeBase
Definition: glscope.h:105
bool m_configChanged
Definition: glscope.h:100
void setYScale(ScaleEngine &scale, uint32_t highlightedTraceIndex)
Definition: glscope.cpp:1898
void connectTimer(const QTimer &timer)
Definition: glscope.cpp:2006
void allocate(uint32_t size)
void sampleRateChanged(int)
void setDisplayGridIntensity(int intensity)
Definition: glscope.cpp:75
const TickList & getTickList()
QList< Tick > TickList
Definition: scaleengine.h:37
void resizeGL(int width, int height)
Definition: glscope.cpp:192
QRectF m_glScopeRect1
Definition: glscope.h:110
void setTimeOfsProMill(int timeOfsProMill)
Definition: glscope.cpp:976
void setRange(Unit::Physical physicalUnit, float rangeMin, float rangeMax)
void drawPolyline(const QMatrix4x4 &transformMatrix, const QVector4D &color, GLfloat *vertices, int nbVertices)
void setDisplayTraceIntensity(int intensity)
Definition: glscope.cpp:86
QPixmap m_bot1ScalePixmap
Definition: glscope.h:122
int m_timeOfsProMill
Definition: glscope.h:102
std::vector< ScopeVis::TraceData > * m_tracesData
Definition: glscope.h:90
Projector::ProjectionType m_projectionType
Complex to real projection type.
Definition: scopevis.h:50
Extract imaginary part.
Definition: projector.h:28
static const int m_topMargin
Definition: glscope.h:151
void drawPoints(const QMatrix4x4 &transformMatrix, const QVector4D &color, GLfloat *vertices, int nbVertices)
static const int m_botMargin
Definition: glscope.h:152
ScaleEngine m_y2Scale
Display #2 Y scale. Connected to highlighted Y trace (#1..n)
Definition: glscope.h:134
QMatrix4x4 m_glScopeMatrix2
Definition: glscope.h:113
void setDisplayMode(DisplayMode displayMode)
Definition: glscope.cpp:990
virtual ~GLScope()
Definition: glscope.cpp:70
QRectF m_glScopeRect2
Definition: glscope.h:111
void setOrientation(Qt::Orientation orientation)
ScaleEngine m_x1Scale
Display #1 X scale. Time scale.
Definition: glscope.h:131
float m_triggerColorB
Trigger line display color - blue shortcut.
Definition: scopevis.h:118
float m_triggerColorG
Trigger line display color - green shortcut.
Definition: scopevis.h:117
QMatrix4x4 m_glLeft2ScaleMatrix
Definition: glscope.h:116
float m_ofs
Offset factor.
Definition: scopevis.h:54
static const int m_rightMargin
Definition: glscope.h:154
void setSampleRate(int sampleRate)
Definition: glscope.cpp:950
QMatrix4x4 m_glLeft1ScaleMatrix
Definition: glscope.h:114
DisplayMode
Definition: glscope.h:45
IncrementalArray< GLfloat > m_q3Polar
Definition: glscope.h:145
Extract real part.
Definition: projector.h:27
T min(const T &x, const T &y)
Definition: framework.h:440