1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2009 Michael Gernoth <michael at gernoth.net>
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
9 //-----------------------------------------------------------------------------
12 #include <QPainterPath>
16 #include <QCloseEvent>
17 #include <QMouseEvent>
23 #include <QHBoxLayout>
25 #include "proxguiqt.h"
34 void ProxGuiQT::ShowGraphWindow(void)
36 emit
ShowGraphWindowSignal();
39 void ProxGuiQT::RepaintGraphWindow(void)
41 emit
RepaintGraphWindowSignal();
44 void ProxGuiQT::HideGraphWindow(void)
46 emit
HideGraphWindowSignal();
49 void ProxGuiQT::_ShowGraphWindow(void)
55 plotwidget
= new ProxWidget();
60 void ProxGuiQT::_RepaintGraphWindow(void)
62 if (!plotapp
|| !plotwidget
)
68 void ProxGuiQT::_HideGraphWindow(void)
70 if (!plotapp
|| !plotwidget
)
76 void ProxGuiQT::MainLoop()
78 plotapp
= new QApplication(argc
, argv
);
80 connect(this, SIGNAL(ShowGraphWindowSignal()), this, SLOT(_ShowGraphWindow()));
81 connect(this, SIGNAL(RepaintGraphWindowSignal()), this, SLOT(_RepaintGraphWindow()));
82 connect(this, SIGNAL(HideGraphWindowSignal()), this, SLOT(_HideGraphWindow()));
87 ProxGuiQT::ProxGuiQT(int argc
, char **argv
) : plotapp(NULL
), plotwidget(NULL
),
88 argc(argc
), argv(argv
)
92 ProxGuiQT::~ProxGuiQT(void)
95 //plotwidget->close();
107 //--------------------
108 void ProxWidget::applyOperation()
110 printf("ApplyOperation()");
112 memcpy(GraphBuffer
,s_Buff
, sizeof(int) * GraphTraceLen
);
113 RepaintGraphWindow();
116 void ProxWidget::stickOperation()
119 printf("stickOperation()");
121 void ProxWidget::vchange_autocorr(int v
)
123 autoCorr(GraphBuffer
,s_Buff
, GraphTraceLen
, v
);
124 printf("vchange_autocorr(%d)\n", v
);
125 RepaintGraphWindow();
127 void ProxWidget::vchange_dthr_up(int v
)
129 int down
= opsController
->horizontalSlider_dirthr_down
->value();
130 directionalThreshold(GraphBuffer
,s_Buff
, GraphTraceLen
, v
, down
);
131 printf("vchange_dthr_up(%d)", v
);
132 RepaintGraphWindow();
135 void ProxWidget::vchange_dthr_down(int v
)
137 printf("vchange_dthr_down(%d)", v
);
138 int up
= opsController
->horizontalSlider_dirthr_up
->value();
139 directionalThreshold(GraphBuffer
,s_Buff
, GraphTraceLen
, v
, up
);
140 RepaintGraphWindow();
143 ProxWidget::ProxWidget(QWidget
*parent
, ProxGuiQT
*master
) : QWidget(parent
)
145 this->master
= master
;
148 /** Setup the controller widget **/
150 QWidget
* controlWidget
= new QWidget();
151 opsController
= new Ui::Form();
152 opsController
->setupUi(controlWidget
);
153 //Due to quirks in QT Designer, we need to fiddle a bit
154 opsController
->horizontalSlider_dirthr_down
->setMinimum(-128);
155 opsController
->horizontalSlider_dirthr_down
->setMaximum(0);
156 opsController
->horizontalSlider_dirthr_down
->setValue(-20);
159 QObject::connect(opsController
->pushButton_apply
, SIGNAL(clicked()), this, SLOT(applyOperation()));
160 QObject::connect(opsController
->pushButton_sticky
, SIGNAL(clicked()), this, SLOT(stickOperation()));
161 QObject::connect(opsController
->horizontalSlider_window
, SIGNAL(valueChanged(int)), this, SLOT(vchange_autocorr(int)));
162 QObject::connect(opsController
->horizontalSlider_dirthr_up
, SIGNAL(valueChanged(int)), this, SLOT(vchange_dthr_up(int)));
163 QObject::connect(opsController
->horizontalSlider_dirthr_down
, SIGNAL(valueChanged(int)), this, SLOT(vchange_dthr_down(int)));
165 controlWidget
->show();
167 // Set up the plot widget, which does the actual plotting
169 plot
= new Plot(this);
171 QSlider* slider = new QSlider(Qt::Horizontal);
172 slider->setFocusPolicy(Qt::StrongFocus);
173 slider->setTickPosition(QSlider::TicksBothSides);
174 slider->setTickInterval(10);
175 slider->setSingleStep(1);
177 QVBoxLayout
*layout
= new QVBoxLayout
;
178 //layout->addWidget(slider);
179 layout
->addWidget(plot
);
181 //printf("Proxwidget Constructor just set layout\r\n");
185 //----------- Plotting
187 int Plot::xCoordOf(int i
, QRect r
)
189 return r
.left() + (int)((i
- GraphStart
)*GraphPixelsPerPoint
);
192 int Plot::yCoordOf(int v
, QRect r
, int maxVal
)
194 int z
= (r
.bottom() - r
.top())/2;
195 return -(z
* v
) / maxVal
+ z
;
198 int Plot::valueOf_yCoord(int y
, QRect r
, int maxVal
)
200 int z
= (r
.bottom() - r
.top())/2;
201 return (y
-z
) * maxVal
/ z
;
203 static const QColor GREEN
= QColor(100,255,100);
204 static const QColor RED
= QColor(255,100,100);
205 static const QColor BLUE
= QColor(100,100,255);
206 static const QColor GRAY
= QColor(240,240,240);
208 QColor
Plot::getColor(int graphNum
)
211 case 0: return GREEN
; //Green
212 case 1: return RED
; //Red
213 case 2: return BLUE
; //Blue
214 default: return GRAY
; //Gray
218 void Plot::PlotDemod(uint8_t *buffer
, size_t len
, QRect plotRect
, QRect annotationRect
, QPainter
*painter
, int graphNum
, int plotOffset
)
220 if (len
== 0 || PlotGridX
<= 0) return;
221 //clock_t begin = clock();
222 QPainterPath penPath
;
224 int grid_delta_x
= PlotGridX
;
225 int first_delta_x
= grid_delta_x
; //(plotOffset > 0) ? PlotGridX : (PlotGridX +);
226 if (GraphStart
> plotOffset
) first_delta_x
-= (GraphStart
-plotOffset
);
227 int DemodStart
= GraphStart
;
228 if (plotOffset
> GraphStart
) DemodStart
= plotOffset
;
232 if (DemodStart
-plotOffset
> 0) BitStart
= (int)(((DemodStart
-plotOffset
)+(PlotGridX
-1))/PlotGridX
)-1;
233 first_delta_x
+= BitStart
* PlotGridX
;
234 if (BitStart
> len
) return;
237 //printf("first_delta_x %i, grid_delta_x %i, DemodStart %i, BitStart %i\n",first_delta_x,grid_delta_x,DemodStart, BitStart);
239 painter
->setPen(getColor(graphNum
));
241 int absVMax
= (int)(100*1.05+1);
242 int x
= xCoordOf(DemodStart
, plotRect
);
243 int y
= yCoordOf((buffer
[BitStart
]*200-100)*-1,plotRect
,absVMax
);
244 penPath
.moveTo(x
, y
);
246 int clk
= first_delta_x
;
247 for(int i
= BitStart
; i
< len
&& xCoordOf(delta_x
+DemodStart
, plotRect
) < plotRect
.right(); i
++) {
248 for (int ii
= 0; ii
< (clk
) && i
< len
&& xCoordOf(DemodStart
+delta_x
+ii
, plotRect
) < plotRect
.right() ; ii
++ ) {
249 x
= xCoordOf(DemodStart
+delta_x
+ii
, plotRect
);
250 v
= buffer
[i
]*200-100;
252 y
= yCoordOf( v
, plotRect
, absVMax
);
254 penPath
.lineTo(x
, y
);
256 if(GraphPixelsPerPoint
> 10) {
257 QRect
f(QPoint(x
- 3, y
- 3),QPoint(x
+ 3, y
+ 3));
258 painter
->fillRect(f
, QColor(100, 255, 100));
260 if (ii
== (int)clk
/2) {
262 sprintf(str
, "%u",buffer
[i
]);
263 painter
->drawText(x
-8, y
+ ((buffer
[i
] > 0) ? 18 : -6), str
);
271 painter
->drawPath(penPath
);
274 void Plot::PlotGraph(int *buffer
, int len
, QRect plotRect
, QRect annotationRect
, QPainter
*painter
, int graphNum
)
276 if (len
== 0) return;
277 //clock_t begin = clock();
278 QPainterPath penPath
;
280 startMax
= (len
- (int)((plotRect
.right() - plotRect
.left() - 40) / GraphPixelsPerPoint
));
284 if(GraphStart
> startMax
) {
285 GraphStart
= startMax
;
287 if (GraphStart
> len
) return;
288 int vMin
= INT_MAX
, vMax
= INT_MIN
, vMean
= 0, v
= 0, absVMax
= 0;
289 int sample_index
= GraphStart
;
290 for( ; sample_index
< len
&& xCoordOf(sample_index
,plotRect
) < plotRect
.right() ; sample_index
++) {
292 v
= buffer
[sample_index
];
293 if(v
< vMin
) vMin
= v
;
294 if(v
> vMax
) vMax
= v
;
298 vMean
/= (sample_index
- GraphStart
);
300 if(fabs( (double) vMin
) > absVMax
) absVMax
= (int)fabs( (double) vMin
);
301 if(fabs( (double) vMax
) > absVMax
) absVMax
= (int)fabs( (double) vMax
);
302 absVMax
= (int)(absVMax
*1.25 + 1);
303 // number of points that will be plotted
304 int span
= (int)((plotRect
.right() - plotRect
.left()) / GraphPixelsPerPoint
);
305 // one label every 100 pixels, let us say
306 int labels
= (plotRect
.right() - plotRect
.left() - 40) / 100;
307 if(labels
<= 0) labels
= 1;
308 int pointsPerLabel
= span
/ labels
;
309 if(pointsPerLabel
<= 0) pointsPerLabel
= 1;
311 int x
= xCoordOf(GraphStart
, plotRect
);
312 int y
= yCoordOf(buffer
[GraphStart
],plotRect
,absVMax
);
313 penPath
.moveTo(x
, y
);
314 for(int i
= GraphStart
; i
< len
&& xCoordOf(i
, plotRect
) < plotRect
.right(); i
++) {
316 x
= xCoordOf(i
, plotRect
);
319 y
= yCoordOf( v
, plotRect
, absVMax
);//(y * (r.top() - r.bottom()) / (2*absYMax)) + zeroHeight;
321 penPath
.lineTo(x
, y
);
323 if(GraphPixelsPerPoint
> 10) {
324 QRect
f(QPoint(x
- 3, y
- 3),QPoint(x
+ 3, y
+ 3));
325 painter
->fillRect(f
, QColor(100, 255, 100));
329 painter
->setPen(getColor(graphNum
));
332 int xo
= 5+(graphNum
*40);
333 painter
->drawLine(xo
, plotRect
.top(),xo
, plotRect
.bottom());
335 int vMarkers
= (absVMax
- (absVMax
% 10)) / 5;
336 int minYDist
= 40; //Minimum pixel-distance between markers
343 for(int v
= vMarkers
; yCoordOf(v
,plotRect
,absVMax
) > plotRect
.top() && n
< 20; v
+= vMarkers
,n
++)
345 int y0
= yCoordOf(v
,plotRect
,absVMax
);
346 int y1
= yCoordOf(-v
,plotRect
,absVMax
);
348 if(lasty0
- y0
< minYDist
) continue;
350 painter
->drawLine(xo
-5,y0
, xo
+5, y0
);
352 sprintf(yLbl
, "%d", v
);
353 painter
->drawText(xo
+8,y0
+7,yLbl
);
355 painter
->drawLine(xo
-5, y1
, xo
+5, y1
);
356 sprintf(yLbl
, "%d",-v
);
357 painter
->drawText(xo
+8, y1
+5 , yLbl
);
362 painter
->drawPath(penPath
);
364 sprintf(str
, "max=%d min=%d mean=%d n=%d/%d CursorAVal=[%d] CursorBVal=[%d]",
365 vMax
, vMin
, vMean
, sample_index
, len
, buffer
[CursorAPos
], buffer
[CursorBPos
]);
366 painter
->drawText(20, annotationRect
.bottom() - 23 - 20 * graphNum
, str
);
368 //clock_t end = clock();
369 //double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
370 //printf("Plot time %f\n", elapsed_secs);
373 void Plot::plotGridLines(QPainter
* painter
,QRect r
)
375 int zeroHeight
= r
.top() + (r
.bottom() - r
.top()) / 2;
378 int grid_delta_x
= (int) (PlotGridX
* GraphPixelsPerPoint
);
379 int grid_delta_y
= (int) (PlotGridY
* GraphPixelsPerPoint
);
380 if ((PlotGridX
> 0) && ((PlotGridX
* GraphPixelsPerPoint
) > 1)) {
381 for(i
= (GridOffset
* GraphPixelsPerPoint
); i
< r
.right(); i
+= grid_delta_x
) {
382 painter
->drawLine(r
.left()+i
, r
.top(), r
.left()+i
, r
.bottom());
385 if ((PlotGridY
> 0) && ((PlotGridY
* GraphPixelsPerPoint
) > 1)){
386 for(i
= 0; i
< ((r
.top() + r
.bottom())>>1); i
+= grid_delta_y
) {
387 painter
->drawLine(r
.left(),zeroHeight
+ i
,r
.right(),zeroHeight
+ i
);
388 painter
->drawLine(r
.left(),zeroHeight
- i
,r
.right(),zeroHeight
- i
);
393 #define HEIGHT_INFO 60
394 #define WIDTH_AXES 80
396 void Plot::paintEvent(QPaintEvent
*event
)
398 QPainter
painter(this);
399 //QPainterPath penPath, whitePath, greyPath, lightgreyPath, cursorAPath, cursorBPath, cursorCPath, cursorDPath;
401 QBrush
brush(QColor(100, 255, 100));
402 QPen
pen(QColor(100, 255, 100));
404 painter
.setFont(QFont("Courier New", 10));
410 if (CursorAPos
> GraphTraceLen
)
412 if(CursorBPos
> GraphTraceLen
)
414 if(CursorCPos
> GraphTraceLen
)
416 if(CursorDPos
> GraphTraceLen
)
419 QRect
plotRect(WIDTH_AXES
, 0, width()-WIDTH_AXES
, height()-HEIGHT_INFO
);
420 QRect
infoRect(0, height()-HEIGHT_INFO
, width(), HEIGHT_INFO
);
423 painter
.fillRect(rect(), QColor(60, 60, 60));
425 painter
.fillRect(plotRect
, QColor(0, 0, 0));
428 int zeroHeight
= plotRect
.top() + (plotRect
.bottom() - plotRect
.top()) / 2;
429 painter
.setPen(QColor(100, 100, 100));
430 painter
.drawLine(plotRect
.left(), zeroHeight
, plotRect
.right(), zeroHeight
);
431 // plot X and Y grid lines
432 plotGridLines(&painter
, plotRect
);
434 //Start painting graph
435 if (showDemod
&& DemodBufferLen
> 8) {
436 PlotDemod(DemodBuffer
, DemodBufferLen
,plotRect
,infoRect
,&painter
,2,g_DemodStartIdx
);
438 PlotGraph(s_Buff
, GraphTraceLen
,plotRect
,infoRect
,&painter
,1);
439 PlotGraph(GraphBuffer
, GraphTraceLen
,plotRect
,infoRect
,&painter
,0);
443 if(CursorAPos
> GraphStart
&& xCoordOf(CursorAPos
, plotRect
) < plotRect
.right())
445 painter
.setPen(QColor(255, 255, 0));
446 painter
.drawLine(xCoordOf(CursorAPos
, plotRect
),plotRect
.top(),xCoordOf(CursorAPos
, plotRect
),plotRect
.bottom());
448 if(CursorBPos
> GraphStart
&& xCoordOf(CursorBPos
, plotRect
) < plotRect
.right())
450 painter
.setPen(QColor(255, 0, 255));
451 painter
.drawLine(xCoordOf(CursorBPos
, plotRect
),plotRect
.top(),xCoordOf(CursorBPos
, plotRect
),plotRect
.bottom());
453 if(CursorCPos
> GraphStart
&& xCoordOf(CursorCPos
, plotRect
) < plotRect
.right())
455 painter
.setPen(QColor(255, 153, 0)); //orange
456 painter
.drawLine(xCoordOf(CursorCPos
, plotRect
),plotRect
.top(),xCoordOf(CursorCPos
, plotRect
),plotRect
.bottom());
458 if(CursorDPos
> GraphStart
&& xCoordOf(CursorDPos
, plotRect
) < plotRect
.right())
460 painter
.setPen(QColor(0, 0, 205)); //light blue
461 painter
.drawLine(xCoordOf(CursorDPos
, plotRect
),plotRect
.top(),xCoordOf(CursorDPos
, plotRect
),plotRect
.bottom());
466 sprintf(str
, "@%d dt=%d [%2.2f] zoom=%2.2f CursorAPos=%d CursorBPos=%d GridX=%d GridY=%d (%s) GridXoffset=%d",
467 GraphStart
, CursorBPos
- CursorAPos
, (CursorBPos
- CursorAPos
)/CursorScaleFactor
,
468 GraphPixelsPerPoint
,CursorAPos
,CursorBPos
,PlotGridXdefault
,PlotGridYdefault
,GridLocked
?"Locked":"Unlocked",GridOffset
);
469 painter
.setPen(QColor(255, 255, 255));
470 painter
.drawText(20, infoRect
.bottom() - 3, str
);
474 Plot::Plot(QWidget
*parent
) : QWidget(parent
), GraphStart(0), GraphPixelsPerPoint(1)
476 //Need to set this, otherwise we don't receive keypress events
477 setFocusPolicy( Qt::StrongFocus
);
480 QPalette
palette(QColor(0,0,0,0));
481 palette
.setColor(QPalette::WindowText
, QColor(255,255,255));
482 palette
.setColor(QPalette::Text
, QColor(255,255,255));
483 palette
.setColor(QPalette::Button
, QColor(100, 100, 100));
485 setAutoFillBackground(true);
489 setWindowTitle(tr("Sliders"));
492 void Plot::closeEvent(QCloseEvent
*event
)
498 void Plot::mouseMoveEvent(QMouseEvent
*event
)
502 x
= (int)(x
/ GraphPixelsPerPoint
);
504 if((event
->buttons() & Qt::LeftButton
)) {
506 } else if (event
->buttons() & Qt::RightButton
) {
514 void Plot::keyPressEvent(QKeyEvent
*event
)
521 if(event
->modifiers() & Qt::ShiftModifier
) {
523 offset
= PageWidth
- (PageWidth
% PlotGridX
);
527 if(event
->modifiers() & Qt::ControlModifier
)
530 offset
= (int)(20 / GraphPixelsPerPoint
);
532 switch(event
->key()) {
534 if(GraphPixelsPerPoint
<= 50) {
535 GraphPixelsPerPoint
*= 2;
540 if(GraphPixelsPerPoint
>= 0.02) {
541 GraphPixelsPerPoint
/= 2;
546 if(GraphPixelsPerPoint
< 20) {
547 if (PlotGridX
&& GridLocked
&& GraphStart
< startMax
){
548 GridOffset
-= offset
;
549 GridOffset
%= PlotGridX
;
552 GraphStart
+= offset
;
554 if (PlotGridX
&& GridLocked
&& GraphStart
< startMax
){
556 GridOffset
%= PlotGridX
;
562 GridOffset
+= PlotGridX
;
565 if (GraphStart
> startMax
) {
566 GridOffset
+= (GraphStart
- startMax
);
567 GridOffset
%= PlotGridX
;
572 if(GraphPixelsPerPoint
< 20) {
573 if (PlotGridX
&& GridLocked
&& GraphStart
> 0){
574 GridOffset
+= offset
;
575 GridOffset
%= PlotGridX
;
578 GraphStart
-= offset
;
580 if (PlotGridX
&& GridLocked
&& GraphStart
> 0){
582 GridOffset
%= PlotGridX
;
589 GridOffset
+= GraphStart
;
591 GridOffset
+= PlotGridX
;
592 GridOffset
%= PlotGridX
;
597 if(PlotGridX
|| PlotGridY
) {
601 PlotGridX
= PlotGridXdefault
;
602 PlotGridY
= PlotGridYdefault
;
607 puts("Plot Window Keystrokes:\n");
608 puts(" Key Action\n");
609 puts(" DOWN Zoom in");
610 puts(" G Toggle grid display");
611 puts(" H Show help");
612 puts(" L Toggle lock grid relative to samples");
613 puts(" LEFT Move left");
614 puts(" <CTL>LEFT Move left 1 sample");
615 puts(" <SHIFT>LEFT Page left");
616 puts(" LEFT-MOUSE-CLICK Set yellow cursor");
617 puts(" Q Hide window");
618 puts(" RIGHT Move right");
619 puts(" <CTL>RIGHT Move right 1 sample");
620 puts(" <SHIFT>RIGHT Page right");
621 puts(" RIGHT-MOUSE-CLICK Set purple cursor");
622 puts(" UP Zoom out");
624 puts("Use client window 'data help' for more plot commands\n");
628 GridLocked
= !GridLocked
;
636 QWidget::keyPressEvent(event
);