js8call/plotter.cpp

860 lines
22 KiB
C++
Raw Normal View History

2018-02-08 21:28:33 -05:00
#include "plotter.h"
#include <QDebug>
2024-09-01 20:03:35 -07:00
#include <QMouseEvent>
#include <QPainter>
#include <QPen>
2024-09-01 08:01:23 -07:00
#include <QToolTip>
2024-09-01 20:03:35 -07:00
#include <QWheelEvent>
2018-02-08 21:28:33 -05:00
#include "commons.h"
#include "moc_plotter.cpp"
2024-09-08 09:00:09 -07:00
#include <algorithm>
2018-02-08 21:28:33 -05:00
#include <fstream>
#include <iostream>
#include "DriftingDateTime.h"
Squashed commit of the following: commit 0d6833b23da2519155ee93b98b4144240b356730 Author: Jordan Sherer <jordan@widefido.com> Date: Thu Sep 5 14:06:47 2019 -0400 Bump version commit 17705fcff6a22529f3dec45aa95cad90feb78c63 Author: Jordan Sherer <jordan@widefido.com> Date: Thu Sep 5 10:36:03 2019 -0400 Updated configration labeling for idle timeout commit a9f8aa9549c1c6b62201a6c102d91649ee17b9a5 Author: Jordan Sherer <jordan@widefido.com> Date: Thu Sep 5 10:07:11 2019 -0400 Decoder params tests commit 94e524741020fd8b3925233a189cedf0a8a282cc Author: Jordan Sherer <jordan@widefido.com> Date: Wed Sep 4 21:24:23 2019 -0400 Fixed decoder bug that crashed the software commit 4fdbfc8d9082e0f52513a5c215489b13558972f9 Author: Jordan Sherer <jordan@widefido.com> Date: Wed Sep 4 21:02:52 2019 -0400 Decoder params tweak commit 1e25ac41d442372f09b254d957e0d9e31773254e Merge: 97a0fb5 552cd7f Author: Jordan Sherer <jordan@widefido.com> Date: Wed Sep 4 18:17:40 2019 -0400 Merge branch 'fortran-cleanup' of bitbucket.org:widefido/js8call-private into fortran-cleanup commit 97a0fb51b37c24e2638400dc5694fc4e988ae4f2 Author: Jordan Sherer <jordan@widefido.com> Date: Wed Sep 4 18:15:25 2019 -0400 Heartbeat as a mode does not work if slow mode does not work. Tabling this idea for now. commit 552cd7fe5fc81c712b57b5f3ea79599177e53f69 Author: Jordan Sherer <jordan@widefido.com> Date: Tue Sep 3 23:35:14 2019 +0000 js8_params.f90 edited online with Bitbucket commit 7c9e960b863148a4ecbca4f61584536471623ea2 Author: Jordan Sherer <jordan@widefido.com> Date: Tue Sep 3 16:28:52 2019 -0400 Do not randomize offset at startup commit cff7b90dbb9aada2944e668a9bcf078470af4608 Author: Jordan Sherer <jordan@widefido.com> Date: Tue Sep 3 16:20:19 2019 -0400 Slow label for button commit 977145dee89ccd7da4d43ce0bc2f9b79243aa200 Author: Jordan Sherer <jordan@widefido.com> Date: Tue Sep 3 16:17:36 2019 -0400 Experimental slow mode commit 27c128e0b327e1c077a9b49e11750bef2f3c26eb Author: Jordan Sherer <jordan@widefido.com> Date: Tue Sep 3 15:26:01 2019 -0400 HBs are Normal commit 89792f91abf22dcd7c512bf7362f5e2e1cb36374 Author: Jordan Sherer <jordan@widefido.com> Date: Tue Sep 3 14:16:27 2019 -0400 Update heartbeat UI for more clarity commit f5cebbcdabe37d90b75ca7e8d1675a553e107c83 Author: Jordan Sherer <jordan@widefido.com> Date: Tue Sep 3 11:58:53 2019 -0400 Optimize decode params commit b14003bb34d93f9e93d7d4ad4241d619963c3a65 Author: Jordan Sherer <jordan@widefido.com> Date: Tue Sep 3 11:30:00 2019 -0400 Shrink speed column for Joe ;) commit 35f4446146efc9fd7044af3b56b0b93664238b24 Author: Jordan Sherer <jordan@widefido.com> Date: Tue Sep 3 10:54:28 2019 -0400 Fixed fast mode decoder for directed messages commit 64212acc30dd360348a72b354899a5b0de28aa83 Author: Jordan Sherer <jordan@widefido.com> Date: Tue Sep 3 10:05:11 2019 -0400 Simplified decoder callbacks commit a026766517d282a3fda0258356f6f22fee2a916f Author: Jordan Sherer <jordan@widefido.com> Date: Tue Sep 3 09:50:33 2019 -0400 Commentary commit 9d28b1ff5bd5cda7a04028218a01639e3902bf7b Author: Jordan Sherer <jordan@widefido.com> Date: Mon Sep 2 23:33:22 2019 -0400 Let's experiment with a new UI for HB commit a013d66d8b8d16cc941a14eb76af2ce23b7bb6d5 Author: Jordan Sherer <jordan@widefido.com> Date: Mon Sep 2 21:44:26 2019 -0400 31.25 baud experiment commit 0671458bf588dd94710c5ba34f20695e13a28d31 Author: Jordan Sherer <jordan@widefido.com> Date: Mon Sep 2 15:31:43 2019 -0400 Added basic foundation for slow mode, coming soon. commit 8b9aed6e29b093e8fb736ebdbdf0fbe12a820e8e Author: Jordan Sherer <jordan@widefido.com> Date: Mon Sep 2 09:59:08 2019 -0400 Display SPEED+AUTO commit 5f5af250c1c5b610e8969b32c01654d3467f0973 Author: Jordan Sherer <jordan@widefido.com> Date: Sun Sep 1 09:45:39 2019 -0400 Added mode speed option to the activity tables commit 82fa0335fdd41f0a578149e0211d6307293c739d Author: Jordan Sherer <jordan@widefido.com> Date: Sat Aug 31 23:14:07 2019 -0400 Remember mode speed setting commit 79ec805b223099bb4d552dc612a6c97a8982525e Author: Jordan Sherer <jordan@widefido.com> Date: Sat Aug 31 21:14:04 2019 -0400 Remove unused sync vars commit fc52dfcc320e59f6c7ca58ba277cb70469419587 Author: Jordan Sherer <jordan@widefido.com> Date: Sat Aug 31 21:12:11 2019 -0400 Timing delta max commit 62b8fc5054d3611d40d7441d57d695df594b8446 Author: Jordan Sherer <jordan@widefido.com> Date: Sat Aug 31 17:14:08 2019 -0400 Fast modes optionally can use huff encoding for data... we'll see which is best commit 44c357aff3e1c6687e93fb843917bd420888b397 Author: Jordan Sherer <jordan@widefido.com> Date: Sat Aug 31 17:03:21 2019 -0400 Added ability to use a different message packing algorithm for fast modes commit e075a078eb75509ef690e6c78c0e797ada569b94 Author: Jordan Sherer <jordan@widefido.com> Date: Sat Aug 31 16:18:14 2019 -0400 Fixed symbol offset in sync code for turbo mode commit a130b5d4a594e9bceece003be0ba72abb05a9f90 Author: Jordan Sherer <jordan@widefido.com> Date: Sat Aug 31 16:09:27 2019 -0400 Added WPM to menu commit 98cacab7bfc243492b6dec703d216d378cc3d34d Author: Jordan Sherer <jordan@widefido.com> Date: Fri Aug 30 23:18:58 2019 -0400 Key eater commit eef58e2c88d010c7f3917a111243eae744a425c3 Author: Jordan Sherer <jordan@widefido.com> Date: Fri Aug 30 16:07:31 2019 -0400 Reorganizing js8dec for better understanding and less confusion between it and JS8b commit 08c14f966e1cda836ca90a8bd1ccd5ae68ec8dd7 Author: Jordan Sherer <jordan@widefido.com> Date: Fri Aug 30 14:20:52 2019 -0400 Do no expose relay and messaging to fast and turbo modes commit c605a31c266866f78eb043812af837ead6442ede Author: Jordan Sherer <jordan@widefido.com> Date: Fri Aug 30 12:02:41 2019 -0400 Do not allow mode speed changes if transmitting commit add062e657a5215f9a4a1ae3ee82063aa85cf0e4 Author: Jordan Sherer <jordan@widefido.com> Date: Thu Aug 29 23:02:31 2019 -0400 Fixed bug where tones were not generated with the correct costas arrays...causing really poor synchronization and failed decodes. I'm surprised it worked at all :P commit cd492b5dd9fd62b5518a5711a1ef8ec522ea08fe Author: Jordan Sherer <jordan@widefido.com> Date: Thu Aug 29 21:56:45 2019 -0400 Back to 20 baud. It has the best decodability, imho commit a2266cd00b8bd14c77bdbc8fc18818689e969858 Author: Jordan Sherer <jordan@widefido.com> Date: Thu Aug 29 14:27:29 2019 -0400 Back to 20 baud with some decoder optimizations commit 86413042e75873585bcb40236da67f2d64870859 Author: Jordan Sherer <jordan@widefido.com> Date: Wed Aug 28 23:04:47 2019 -0400 Try 24 baud commit a6704162b37d1c0704f43a64ab6b8a0a6e3c1cba Author: Jordan Sherer <jordan@widefido.com> Date: Wed Aug 28 17:09:12 2019 -0400 Fixed legacy compiler issue with mode text commit 2fdbcc12e5f0c8cc8062c745af0930db4472cd9c Author: Jordan Sherer <jordan@widefido.com> Date: Wed Aug 28 10:17:23 2019 -0400 Function for determining current mode commit 82e70345baa665418a51307f0309f2b7dcb3d3b7 Author: Jordan Sherer <jordan@widefido.com> Date: Wed Aug 28 09:59:26 2019 -0400 Don't write the log commit d3380e01676537f4bab9a05932cb5a59de3cf45f Author: Jordan Sherer <jordan@widefido.com> Date: Wed Aug 28 09:59:03 2019 -0400 Fixed issues with turbo decode with partial sync code commit c2a8ebb8f305e67fcb2597d25e062663722a0d73 Author: Jordan Sherer <jordan@widefido.com> Date: Wed Aug 28 03:30:02 2019 -0400 Working through better decoding of fast modes commit 7ca93f8c6a7970559577c9dfd833eb92a1b91a0c Author: Jordan Sherer <jordan@widefido.com> Date: Tue Aug 27 23:23:34 2019 -0400 Trying for better TX/RX delays commit b99271b4feaa7e41c7b88219cb3c7d43dbe7b48d Author: Jordan Sherer <jordan@widefido.com> Date: Tue Aug 27 22:57:02 2019 -0400 Added flags to easily enable/disable the faster modes commit 32d913a7f7d3deb6a8d66651d51673ec451d2500 Author: Jordan Sherer <jordan@widefido.com> Date: Tue Aug 27 22:43:20 2019 -0400 Added mode button commit c7cc90548591638bfc5a4a8895036dd67b155aaa Author: Jordan Sherer <jordan@widefido.com> Date: Tue Aug 27 22:17:42 2019 -0400 Updated start delay for the modes commit b91dc63f92101cd8b6adbf9de588c4ffd10bfc10 Author: Jordan Sherer <jordan@widefido.com> Date: Tue Aug 27 21:55:57 2019 -0400 Late threshold for turbo mode is 1/2 the delay commit 09ec95fab1307e65aa9bd462d60525afd2a770fe Author: Jordan Sherer <jordan@widefido.com> Date: Tue Aug 27 21:52:55 2019 -0400 Renamed mode menu items commit a4e5a9ed9bce66c625e4df1182cd3c91a6ba44dd Author: Jordan Sherer <jordan@widefido.com> Date: Tue Aug 27 21:50:45 2019 -0400 Only enable networking and autoreply for normal JS8 commit fc558d5823c46fc5d3dc651610b7af43e7519165 Author: Jordan Sherer <jordan@widefido.com> Date: Tue Aug 27 21:14:12 2019 -0400 Fixed spot button tooltip commit 9a9965d543540a2d215bcbfff34934846afe507a Author: Jordan Sherer <jordan@widefido.com> Date: Tue Aug 27 10:04:31 2019 -0400 Working selectable decoder commit 4a9cdbc52dae1d857c102d8777f1aded4fac87bb Author: Jordan Sherer <jordan@widefido.com> Date: Mon Aug 26 20:53:30 2019 -0400 Mode menu selection of the submodes. Turbo decoder disabled right now. Naming to be determined commit a3acbf7c243f7aa740c229ae178fffa528e68933 Merge: 8ea554d daa8cc2 Author: Jordan Sherer <jordan@widefido.com> Date: Mon Aug 26 13:29:14 2019 -0400 Merge branch 'ft8call-develop' into fortran-cleanup commit 8ea554d79904c9b2f3ccf1027bf4d41fb25e6fe3 Author: Jordan Sherer <jordan@widefido.com> Date: Mon Aug 26 09:53:21 2019 -0400 Use indx variable instead of computed commit 067e65500328133f921b172e515babbcc0df831b Author: Jordan Sherer <jordan@widefido.com> Date: Sun Aug 25 22:41:00 2019 -0400 Make it easier to flip between modes commit a544a7635201072f3ea20483353edf2e79dc813d Author: Jordan Sherer <jordan@widefido.com> Date: Sun Aug 25 21:18:46 2019 -0400 Fixed sync issues with multi costas. Added log statements for future debugging commit a8f3ead932017ae7d98fdb9a779bf3bb44bd395d Author: Jordan Sherer <jordan@widefido.com> Date: Sun Aug 25 15:54:59 2019 -0400 Playing around with different costas arrays commit fa89fe11a15d26abadd5102c8980620cfeffccd9 Author: Jordan Sherer <jordan@widefido.com> Date: Sun Aug 25 15:51:45 2019 -0400 Added reference to 7x7 costas arrays commit 2417ebed6139534214f76ce94bdf1f54a966760a Merge: 6011f1e 32fcabd Author: Jordan Sherer <jordan@widefido.com> Date: Sat Aug 24 23:41:39 2019 -0400 Merge branch 'ft8call-develop' into fortran-cleanup commit 6011f1e807b1814399477d3c172db46831a090c6 Author: Jordan Sherer <jordan@widefido.com> Date: Sat Aug 24 23:35:42 2019 -0400 Back to 10 baud. Update late threshold to be computed to 3/4 dead air time. commit 41d3995861226f7208b2773430010a48abc125c1 Author: Jordan Sherer <jordan@widefido.com> Date: Sat Aug 24 15:36:12 2019 -0400 Trying out 20 baud commit a8d77e9e5b98f3f0bf19f68b53199b5952e8aaad Author: Jordan Sherer <jordan@widefido.com> Date: Sat Aug 24 15:23:36 2019 -0400 Fixed up sync quarter symbol constant commit 7050722436b9c629ea00649e6b3c81d7af7be82a Author: Jordan Sherer <jordan@widefido.com> Date: Sat Aug 24 14:43:48 2019 -0400 Computed symbol stop commit f130fe87abdccbabd2e71f2771b789c7f46d57ca Author: Jordan Sherer <jordan@widefido.com> Date: Fri Aug 23 20:56:59 2019 -0400 Added reference to 7x7 costas arrays commit 53e91858f5a4e9ce78c38ef65c77e87f1903c058 Author: Jordan Sherer <jordan@widefido.com> Date: Fri Aug 23 16:34:51 2019 -0400 Back to 10 baud commit 1ae79d566ebd9a40ad3cf4a07977ef0e09615d91 Author: Jordan Sherer <jordan@widefido.com> Date: Fri Aug 23 15:14:41 2019 -0400 Testing 31.25 baud commit 7e033c28ae090d6c3f5a63fa651ee51c3243d61c Author: Jordan Sherer <jordan@widefido.com> Date: Fri Aug 23 15:14:17 2019 -0400 Experimenting with a few different baudrates commit 050e24ad3a040924ded6d641004ae63da47e4251 Author: Jordan Sherer <jordan@widefido.com> Date: Fri Aug 23 12:25:50 2019 -0400 Added ldpcsim for js8 commit d309a75d860e39737dec732560432a191290b258 Author: Jordan Sherer <jordan@widefido.com> Date: Thu Aug 22 22:42:11 2019 -0400 Experimental submode switching commit 74f72bb24a22631b8b69942ea0633bb0564b8aa3 Author: Jordan Sherer <jordan@widefido.com> Date: Thu Aug 22 22:41:53 2019 -0400 Allow switching decoders based on submode commit f8740a23b27e80fa53350e140d4638a27cd6e975 Author: Jordan Sherer <jordan@widefido.com> Date: Wed Aug 21 23:43:18 2019 -0400 Initial spike of js8 fortran code commit 31625316639f79246b4a2e3d0cea4507bf0547f9 Author: Jordan Sherer <jordan@widefido.com> Date: Wed Aug 21 23:09:00 2019 -0400 Remove fix contest message commit c0e0862afa8ae2d47e9577562399b8c9bc929c6a Author: Jordan Sherer <jordan@widefido.com> Date: Wed Aug 21 21:05:05 2019 -0400 Cleanup unused text files and batch files commit 1b3aa55869f0c310e6c911a7cbb3fe269bc7421a Author: Jordan Sherer <jordan@widefido.com> Date: Wed Aug 21 21:00:38 2019 -0400 Removed fast_decode and dx commit 49e5cabff25c13620a9d2c6fc6ddd4988f1be217 Author: Jordan Sherer <jordan@widefido.com> Date: Wed Aug 21 20:54:39 2019 -0400 Cleaning up msk stuff commit 8bde6f391f4b23d2a2e9d55685d96bc647a462f6 Author: Jordan Sherer <jordan@widefido.com> Date: Wed Aug 21 20:44:39 2019 -0400 Initial cleanup pass of qra, ftrsd, and wsprd
2019-09-05 14:07:24 -04:00
#include "varicode.h"
2018-03-05 14:49:51 -05:00
extern "C" {
void flat4_(float swide[], int* iz, int* nflatten);
void plotsave_(float swide[], int* m_w , int* m_h1, int* irow);
}
namespace
{
constexpr std::size_t VERT_DIVS = 7;
qint32
freqPerDiv(float const fSpan)
{
2024-09-08 20:13:33 -07:00
if (fSpan > 2500) { return 500; }
if (fSpan > 1000) { return 200; }
if (fSpan > 500) { return 100; }
if (fSpan > 250) { return 50; }
if (fSpan > 100) { return 20; }
return 10;
}
double
fftBinWidth(qint32 const nsps)
{
2024-09-09 05:34:41 -07:00
switch (nsps)
{
case 252000: return 1500.0 / 32768.0;
case 82944: return 1500.0 / 12288.0;
case 40960: return 1500.0 / 6144.0;
default: return 1500.0 / 2048.0;
}
}
2024-09-08 21:28:23 -07:00
float
bw(qint32 const nSubMode)
{
2024-09-09 05:34:41 -07:00
switch (nSubMode)
{
case Varicode::JS8CallNormal: return 8.0 * (double)RX_SAMPLE_RATE / (double)JS8A_SYMBOL_SAMPLES;
case Varicode::JS8CallFast: return 8.0 * (double)RX_SAMPLE_RATE / (double)JS8B_SYMBOL_SAMPLES;
case Varicode::JS8CallTurbo: return 8.0 * (double)RX_SAMPLE_RATE / (double)JS8C_SYMBOL_SAMPLES;
case Varicode::JS8CallSlow: return 8.0 * (double)RX_SAMPLE_RATE / (double)JS8E_SYMBOL_SAMPLES;
case Varicode::JS8CallUltra: return 8.0 * (double)RX_SAMPLE_RATE / (double)JS8I_SYMBOL_SAMPLES;
default: return 0;
}
2024-09-08 21:28:23 -07:00
}
}
2018-02-08 21:28:33 -05:00
CPlotter::CPlotter(QWidget *parent) : //CPlotter Constructor
QFrame {parent},
m_set_freq_action {new QAction {tr ("&Set Rx && Tx Offset"), this}},
m_bScaleOK {false},
m_fSpan {2000.0},
m_plotZero {0},
m_plotGain {0},
m_plot2dGain {0},
m_plot2dZero {0},
m_nSubMode {0},
m_filterEnabled{false},
m_filterCenter {0},
m_filterWidth {0},
2018-11-04 22:37:14 -05:00
m_turbo {false},
2018-02-08 21:28:33 -05:00
m_Running {false},
m_paintEventBusy {false},
m_fftBinWidth {1500.0/2048.0},
m_dialFreq {0.},
m_sum {},
2024-09-13 08:30:52 -07:00
m_points {},
2018-02-08 21:28:33 -05:00
m_line {0},
m_nsps {6912},
m_Percent2DScreen {0}, //percent of screen used for 2D display
2018-02-08 21:28:33 -05:00
m_Percent2DScreen0 {0},
m_rxFreq {1020},
m_txFreq {0},
m_startFreq {0},
m_lastMouseX {-1}
2018-02-08 21:28:33 -05:00
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setFocusPolicy(Qt::StrongFocus);
setAttribute(Qt::WA_PaintOnScreen,false);
setAutoFillBackground(false);
setAttribute(Qt::WA_OpaquePaintEvent, false);
setAttribute(Qt::WA_NoSystemBackground, true);
2018-03-05 14:49:51 -05:00
m_bReplot=false;
2018-02-08 21:28:33 -05:00
setMouseTracking(true);
2018-02-08 21:28:33 -05:00
}
2024-09-08 12:43:10 -07:00
CPlotter::~CPlotter() = default;
2018-02-08 21:28:33 -05:00
QSize CPlotter::minimumSizeHint() const
{
return QSize(50, 50);
}
QSize CPlotter::sizeHint() const
{
return QSize(180, 180);
}
2024-09-08 10:00:57 -07:00
void CPlotter::resizeEvent(QResizeEvent *) //resizeEvent()
2018-02-08 21:28:33 -05:00
{
2024-09-08 10:00:57 -07:00
if (!size().isValid()) return;
if ((m_Size != size()) ||
// XXX (m_bReference != m_bReference0) ||
2024-09-08 10:00:57 -07:00
(m_Percent2DScreen != m_Percent2DScreen0))
{
2018-02-08 21:28:33 -05:00
m_Size = size();
2024-09-08 10:00:57 -07:00
m_w = m_Size.width();
m_h = m_Size.height();
m_h2 = m_Percent2DScreen * m_h / 100.0;
if (m_h2 > m_h - 30) m_h2 = m_h - 30;
// XXX if (m_bReference ) m_h2 = m_h - 30;
2024-09-08 10:00:57 -07:00
if (m_h2 < 1) m_h2 = 1;
m_h1 = m_h - m_h2;
2018-03-05 14:49:51 -05:00
// m_line=0;
2024-09-08 14:17:32 -07:00
m_FilterOverlayPixmap = QPixmap(m_Size);
m_FilterOverlayPixmap.fill(Qt::transparent);
2024-09-08 14:17:32 -07:00
m_DialOverlayPixmap = QPixmap(m_Size);
m_DialOverlayPixmap.fill(Qt::transparent);
2024-09-08 14:17:32 -07:00
m_HoverOverlayPixmap = QPixmap(m_Size);
m_HoverOverlayPixmap.fill(Qt::transparent);
2024-09-08 14:17:32 -07:00
m_2DPixmap = QPixmap(m_w, m_h2);
2018-02-08 21:28:33 -05:00
m_2DPixmap.fill(Qt::black);
2024-09-08 14:17:32 -07:00
m_WaterfallPixmap = QPixmap(m_w, m_h1);
m_WaterfallPixmap.fill(Qt::black);
2024-09-08 14:17:32 -07:00
m_OverlayPixmap = QPixmap(m_w, m_h2);
2018-02-08 21:28:33 -05:00
m_OverlayPixmap.fill(Qt::black);
2024-08-31 22:19:32 -07:00
// Address scale font looking terrible, since it's drawn into this
// intermediate pixmap, so if we don't scale it to match the device,
// the text will look pixelated.
//
// Same is true of the decode lines in the waterfall; they look
// pixelated, but the fix doesn't appear to be straightforward, and
// it's arguably an effect there, a bit like a Tektronix display.
m_ScalePixmap = QPixmap(QSize(m_w, 30) * devicePixelRatio());
m_ScalePixmap.setDevicePixelRatio(devicePixelRatio());
2018-02-08 21:28:33 -05:00
m_ScalePixmap.fill(Qt::white);
2024-08-31 22:19:32 -07:00
2018-02-08 21:28:33 -05:00
m_Percent2DScreen0 = m_Percent2DScreen;
}
DrawOverlay();
}
void CPlotter::paintEvent(QPaintEvent *) // paintEvent()
{
if (m_paintEventBusy) return;
m_paintEventBusy = true;
2018-02-08 21:28:33 -05:00
QPainter painter(this);
painter.drawPixmap(0,0,m_ScalePixmap);
painter.drawPixmap(0,30,m_WaterfallPixmap);
painter.drawPixmap(0,m_h1,m_2DPixmap);
int const x = XfromFreq(m_rxFreq);
painter.drawPixmap(x,0,m_DialOverlayPixmap);
if (m_lastMouseX >= 0 && m_lastMouseX != x)
{
painter.drawPixmap(m_lastMouseX, 0, m_HoverOverlayPixmap);
}
if (m_filterEnabled && m_filterWidth > 0)
{
painter.drawPixmap(0, 0, m_FilterOverlayPixmap);
}
m_paintEventBusy = false;
2018-02-08 21:28:33 -05:00
}
2024-09-13 14:08:06 -07:00
void
CPlotter::draw(float swide[],
bool const bScroll,
bool const)
2018-02-08 21:28:33 -05:00
{
// XXX if(m_bReference != m_bReference0) resizeEvent(nullptr);
// XXX m_bReference0 = m_bReference;
2018-02-08 21:28:33 -05:00
// Move current data down one line (must do this before attaching a QPainter object)
if(bScroll && !m_bReplot)
{
m_WaterfallPixmap.scroll(0, 1, m_WaterfallPixmap.rect());
}
2024-09-08 09:00:09 -07:00
2018-02-08 21:28:33 -05:00
QPainter painter1(&m_WaterfallPixmap);
m_2DPixmap = m_OverlayPixmap.copy();
2018-02-08 21:28:33 -05:00
QPainter painter2D(&m_2DPixmap);
if(!painter2D.isActive()) return;
2024-09-08 20:09:29 -07:00
int iz = XfromFreq(5000.0);
m_fMax = FreqfromX(iz);
if(bScroll && swide[0] < 1.e29)
{
flat4_(swide, &iz, &m_Flatten);
2018-02-08 21:28:33 -05:00
}
2024-09-08 20:09:29 -07:00
if(swide[0] > 1.e29 && swide[0] < 1.5e30) painter1.setPen(Qt::green); // horizontal line
if(swide[0] > 1.4e30 ) painter1.setPen(Qt::yellow);
if(!m_bReplot)
{
m_j = 0;
int irow = -1;
plotsave_(swide, &m_w, &m_h1, &irow);
2018-03-05 14:49:51 -05:00
}
2024-09-08 20:09:29 -07:00
double const fac = sqrt(m_binsPerPixel * m_waterfallAvg / 15.0);
double const gain = fac * pow(10.0, 0.015 * m_plotGain);
double const gain2d = pow(10.0, 0.02 * m_plot2dGain);
2024-09-13 14:08:06 -07:00
auto const base = static_cast<int>(m_startFreq / m_fftBinWidth + 0.5);
auto ymin = 1.e30f;
// First loop; draws points into the waterfall and determines the
// minimum y extent.
2024-09-08 20:01:56 -07:00
for(int i = 0; i < iz; i++)
{
float const y = swide[i];
2024-09-13 10:49:58 -07:00
if (y < ymin ) ymin = y;
if (y < 1.e29) painter1.setPen(g_ColorTbl[std::clamp(static_cast<int>(10.0 * gain * y + m_plotZero), 0, 254)]);
painter1.drawPoint(i, m_j);
2018-02-08 21:28:33 -05:00
}
2018-03-05 14:49:51 -05:00
m_line++;
2024-09-13 14:08:06 -07:00
// Summarization method, used when scrolling and during computation of
// linear average.
auto const sum = [base,
bins = m_binsPerPixel](float const * const data,
auto const index)
{
float sum = 0.0f;
int k = base + bins * index;
for (int l = 0; l < bins; l++)
{
sum += data[k++];
}
return sum;
};
// Second loop, determines how we're going to draw the spectrum.
// Updates the sums if we're scrolling, updates the points to
2024-09-08 20:01:56 -07:00
for (int i = 0; i < iz; i++)
{
2024-09-13 13:03:50 -07:00
if (bScroll)
2024-09-08 20:09:29 -07:00
{
2024-09-13 14:08:06 -07:00
m_sum[i] = sum(dec_data.savg, i);
2018-02-08 21:28:33 -05:00
}
2024-09-14 22:26:48 -07:00
float y = 0;
2024-09-13 13:03:50 -07:00
switch (m_spectrum)
2024-09-08 20:09:29 -07:00
{
case Spectrum::Current:
y = gain2d * (swide[i] - ymin) + m_plot2dZero + (m_Flatten == 0 ? 15 : 0);
break;
case Spectrum::Cumulative:
y = gain2d * (m_sum[i] / m_binsPerPixel + m_plot2dZero) + (m_Flatten == 0 ? 15 : 0);
break;
case Spectrum::LinearAvg:
y = gain2d * sum(spectra_.syellow, i) / m_binsPerPixel + m_plot2dZero;
break;
case Spectrum::Reference:
y = spectra_.ref[static_cast<int>(FreqfromX(i) / (12000.0f / 6912.0f) + 0.5f)] + m_plot2dZero;
break;
2018-02-08 21:28:33 -05:00
}
m_points[i].setX(i);
2024-09-13 13:03:50 -07:00
m_points[i].setY(int(0.9 * m_h2 - y * m_h2 / 70.0));
2018-02-08 21:28:33 -05:00
}
2024-09-08 20:01:56 -07:00
// Line color based on what we're about here. Typically green, sometimes
// yellow or blue.
2024-09-13 14:08:06 -07:00
if (m_spectrum == Spectrum::LinearAvg) { painter2D.setPen(Qt::yellow); }
else if(m_spectrum == Spectrum::Reference) { painter2D.setPen(Qt::blue); }
else { painter2D.setPen(Qt::green); }
2024-09-13 14:08:06 -07:00
// Draw the computed spectrum line.
painter2D.drawPolyline(m_points, iz - 1);
2024-09-13 14:08:06 -07:00
if (m_bReplot) return;
2018-02-08 21:28:33 -05:00
2024-09-08 12:08:52 -07:00
if (swide[0] > 1.0e29) m_line = 0;
2024-09-08 17:53:35 -07:00
if (m_line == painter1.fontMetrics().height())
{
2024-09-08 06:18:53 -07:00
qint64 const ms = DriftingDateTime::currentMSecsSinceEpoch() % 86400000;
int const n = (ms/1000) % m_TRperiod;
auto const t1 = DriftingDateTime::currentDateTimeUtc().addSecs(-n);
auto const ts = t1.toString(m_TRperiod < 60 ? "hh:mm:ss" : "hh:mm");
2018-02-08 21:28:33 -05:00
painter1.setPen(Qt::white);
2024-09-08 06:18:53 -07:00
painter1.drawText(5,
painter1.fontMetrics().ascent(),
QString("%1 %2").arg(ts).arg(m_rxBand));
2018-02-08 21:28:33 -05:00
}
update(); //trigger a new paintEvent
2024-09-08 20:01:56 -07:00
m_bScaleOK = true;
2018-02-08 21:28:33 -05:00
}
void CPlotter::drawDecodeLine(const QColor &color, int ia, int ib)
2018-02-08 21:28:33 -05:00
{
2024-09-08 17:53:35 -07:00
int const x1 = XfromFreq(ia);
int const x2 = XfromFreq(ib);
2020-05-06 11:15:41 -04:00
QPainter painter1(&m_WaterfallPixmap);
2024-09-08 17:53:35 -07:00
painter1.setPen(color);
painter1.drawLine(qMin(x1, x2), 4, qMax(x1, x2), 4);
painter1.drawLine(qMin(x1, x2), 0, qMin(x1, x2), 9);
painter1.drawLine(qMax(x1, x2), 0, qMax(x1, x2), 9);
2018-02-08 21:28:33 -05:00
}
void CPlotter::drawHorizontalLine(const QColor &color, int x, int width)
{
QPainter painter1(&m_WaterfallPixmap);
2024-09-08 19:54:14 -07:00
2024-09-08 17:53:35 -07:00
painter1.setPen(color);
painter1.drawLine(x, 0, width <= 0 ? m_w : x + width, 0);
}
2018-03-05 14:49:51 -05:00
void CPlotter::replot()
{
float swide[m_w];
2024-09-08 19:54:14 -07:00
m_bReplot = true;
for (int irow = 0; irow < m_h1; irow++)
{
m_j = irow;
plotsave_(swide, &m_w, &m_h1, &irow);
draw(swide, false, false);
2018-03-05 14:49:51 -05:00
}
2024-09-08 19:54:14 -07:00
2018-03-05 14:49:51 -05:00
update(); //trigger a new paintEvent
2024-09-08 19:54:14 -07:00
m_bReplot = false;
2018-03-05 14:49:51 -05:00
}
void CPlotter::DrawOverlay()
2018-02-08 21:28:33 -05:00
{
2024-09-08 14:37:43 -07:00
if (m_OverlayPixmap.isNull() ||
m_WaterfallPixmap.isNull()) return;
2018-02-08 21:28:33 -05:00
2024-09-08 14:37:43 -07:00
QLinearGradient gradient(0, 0, 0, m_h2); //fill background with gradient
2018-02-08 21:28:33 -05:00
gradient.setColorAt(1, Qt::black);
gradient.setColorAt(0, Qt::darkBlue);
QPainter p(&m_OverlayPixmap);
p.setBrush(gradient);
p.drawRect(0, 0, m_w, m_h2);
p.setBrush(Qt::SolidPattern);
double const df = m_binsPerPixel * m_fftBinWidth;
2024-09-08 14:37:43 -07:00
m_fSpan = m_w * df;
m_freqPerDiv = freqPerDiv(m_fSpan);
2024-09-08 10:00:57 -07:00
float const ppdV = m_freqPerDiv / df;
float const ppdH = (float)m_h2 / (float)VERT_DIVS;
std::size_t const hdivs = m_fSpan / m_freqPerDiv + 1.9999;
2024-09-08 10:00:57 -07:00
float xx0 = float(m_startFreq) /float(m_freqPerDiv);
xx0 = xx0 - int(xx0);
int x0 = xx0 * ppdV + 0.5;
2024-09-09 11:40:50 -07:00
p.setPen(QPen(Qt::white, 1, Qt::DotLine));
for (std::size_t i = 1; i < hdivs; i++) //draw vertical grids
{
if (int const x = (int)((float)i * ppdV) - x0;
x >= 0 &&
x <= m_w)
{
p.drawLine(x, 0, x , m_h2);
2018-02-08 21:28:33 -05:00
}
}
for (std::size_t i = 1; i < VERT_DIVS; i++) //draw horizontal grids
{
int const y = (int)( (float)i * ppdH );
p.drawLine(0, y, m_w, y);
2018-02-08 21:28:33 -05:00
}
DrawOverlayScale(df, ppdV);
2018-02-08 21:28:33 -05:00
2024-09-09 07:50:19 -07:00
// paint dials and filter overlays
if (m_mode == "FT8")
{
int const fwidth = XfromFreq(m_rxFreq + bw(m_nSubMode)) - XfromFreq(m_rxFreq);
DrawOverlayDial(fwidth);
DrawOverlayHover(fwidth);
DrawOverlayFilter();
}
}
void
CPlotter::DrawOverlayScale(double const df,
2024-09-12 19:00:35 -07:00
float const ppdV)
2024-09-09 07:50:19 -07:00
{
QPen const penOrange (QColor(230, 126, 34), 3);
QPen const penGray (QColor(149, 165, 166), 3);
QPen const penLightGreen (QColor( 46, 204, 113), 3);
QPen const penLightYellow(QColor(241, 196, 15), 3);
m_ScalePixmap.fill(Qt::white);
2024-09-09 07:50:19 -07:00
QPainter p(&m_ScalePixmap);
p.setFont({"Arial"});
p.setPen(Qt::black);
2024-09-12 13:04:50 -07:00
p.drawRect(0, 0, m_w, 30);
2024-09-09 07:50:19 -07:00
2024-09-12 14:09:43 -07:00
int const fOffset = ((m_startFreq + m_freqPerDiv - 1) / m_freqPerDiv) * m_freqPerDiv;
double const xOffset = double(fOffset - m_startFreq) / m_freqPerDiv;
2024-09-12 19:00:35 -07:00
std::size_t const nMinor = m_freqPerDiv == 200 ? 4: 5;
std::size_t const nHDivs = m_w * df / m_freqPerDiv + 0.9999;
float const ppdVM = ppdV / nMinor;
float const ppdVL = ppdV / 2;
2024-09-12 19:00:35 -07:00
// Draw ticks and labels.
2024-09-09 07:50:19 -07:00
2024-09-12 19:00:35 -07:00
for (std::size_t iMajor = 0; iMajor < nHDivs; iMajor++)
{
2024-09-12 19:00:35 -07:00
auto const rMajor = (xOffset + iMajor) * ppdV;
auto const xMajor = static_cast<int>(rMajor);
p.drawLine(xMajor, 18, xMajor, 30);
2024-09-12 19:00:35 -07:00
for (std::size_t iMinor = 1; iMinor < nMinor; iMinor++)
{
2024-09-12 19:00:35 -07:00
auto const xMinor = static_cast<int>(rMajor + iMinor * ppdVM);
p.drawLine(xMinor, 22, xMinor, 30);
}
2024-09-12 19:00:35 -07:00
if (xMajor > 70)
{
p.drawText(QRect(xMajor - static_cast<int>(ppdVL), 0, static_cast<int>(ppdV), 20),
Qt::AlignCenter,
QString::number(fOffset + iMajor * m_freqPerDiv));
}
2018-02-08 21:28:33 -05:00
}
// If our scale incldues the WSPR range, display it.
2018-02-08 21:28:33 -05:00
if (m_dialFreq > 10.13 &&
2024-09-08 21:37:27 -07:00
m_dialFreq < 10.15 && !m_mode.startsWith(QLatin1StringView("WSPR")))
{
2024-09-10 06:26:15 -07:00
float const wspr = 1.0e6f * (10.1401 - m_dialFreq);
int const x1 = XfromFreq(wspr);
int const x2 = XfromFreq(wspr + 200.0f);
2024-09-10 06:36:41 -07:00
2024-09-10 06:26:15 -07:00
if (x1 <= m_w && x2 >= 0)
{
2024-09-09 07:50:19 -07:00
p.setPen(penOrange); //Mark WSPR sub-band orange
p.drawLine(x1, 9, x2, 9);
2018-02-08 21:28:33 -05:00
}
}
// Colorize the JS8 sub-bands.
2024-09-10 06:36:41 -07:00
for (std::size_t i = 0; i <= 3500; i += 500)
{
2024-09-10 06:36:41 -07:00
int const x1 = XfromFreq(static_cast<float>(i));
int const x2 = XfromFreq(static_cast<float>(i + 500));
2024-09-10 06:26:15 -07:00
if (x1 <= m_w && x2 > 0)
2024-09-08 21:28:23 -07:00
{
2024-09-10 06:26:15 -07:00
switch (i) {
2024-09-08 21:28:23 -07:00
case 500:
2024-09-09 21:40:04 -07:00
case 2500:
p.setPen(penLightYellow);
break;
2024-09-08 21:28:23 -07:00
case 1000:
case 1500:
case 2000:
2024-09-09 21:40:04 -07:00
p.setPen(penLightGreen);
break;
2024-09-10 06:26:15 -07:00
default:
p.setPen(penGray);
break;
2019-12-30 14:37:11 -05:00
}
2024-09-09 07:50:19 -07:00
p.drawLine(x1 + 1, 26, x2 - 2, 26);
p.drawLine(x1 + 1, 28, x2 - 2, 28);
2024-09-08 21:28:23 -07:00
}
2019-12-30 14:37:11 -05:00
}
2024-09-09 07:50:19 -07:00
p.setPen(Qt::black);
p.drawLine(0, 29, m_w, 29);
}
// Paint the dial overlay, showing the chunk of the frequency spectrum
// presently in use.
void
CPlotter::DrawOverlayDial(int const fwidth)
{
QPainter p(&m_DialOverlayPixmap);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(rect(), Qt::transparent);
p.setPen(Qt::red);
2024-09-09 11:34:32 -07:00
p.fillRect(0, 26, fwidth + 2, 4, Qt::red);
2024-09-09 14:29:22 -07:00
p.fillRect(0, m_h - 4, fwidth + 2, 4, Qt::red);
p.drawLine(0, 30, 0, m_h); // first slot, left line
p.drawLine(fwidth + 1, 30, fwidth + 1, m_h); // first slot, right line
#if TEST_FOX_WAVE_GEN
if (m_turbo)
{
2024-09-09 11:58:06 -07:00
auto const bwValue = bw(m_nSubMode);
int const offset = XfromFreq(m_rxFreq + bwValue + TEST_FOX_WAVE_GEN_OFFSET) -
XfromFreq(m_rxFreq + bwValue + 4; // + 4 for the line padding
for (int i = 1; i < TEST_FOX_WAVE_GEN_SLOTS; i++)
2024-09-08 21:28:23 -07:00
{
2024-09-09 11:34:32 -07:00
p.fillRect(i*(fwidth + offset), 26, i*(fwidth + offset) + fwidth + 3, 4, Qt::Red);
p.drawLine(i*(fwidth + offset), 30, i*(fwidth + offset), m_h); // n slot, left line
p.drawLine(i*(fwidth + offset) + fwidth + 2, 30, i*(fwidth + offset) + fwidth + 2, m_h); // n slot, right line
2024-09-08 21:28:23 -07:00
}
}
#endif
}
// Paint the hover overlay, showing the prospective chunk of frequency
// spectrum under the mouse.
void
CPlotter::DrawOverlayHover(int const fwidth)
{
QPainter p(&m_HoverOverlayPixmap);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(rect(), Qt::transparent);
p.setPen(Qt::white);
p.drawLine(0, 30, 0, m_h); // first slot, left line hover
p.drawLine(fwidth, 30, fwidth, m_h); // first slot, right line hover
#if TEST_FOX_WAVE_GEN
if (m_turbo)
{
for(int i = 1; i < TEST_FOX_WAVE_GEN_SLOTS; i++)
2024-09-08 21:28:23 -07:00
{
hoverPainter.drawLine(i*(fwidth + offset), 30, i*(fwidth + offset), m_h); // n slot, left line
hoverPainter.drawLine(i*(fwidth + offset) + fwidth + 2, 30, i*(fwidth + offset) + fwidth + 2, m_h); // n slot, right line
2024-09-08 21:28:23 -07:00
}
}
#endif
#if DRAW_FREQ_OVERLAY
hoverPainter.setFont({"Arial"});
hoverPainter.drawText(fwidth + 5, m_h, QString("%1").arg(FreqfromX(m_lastMouseX)));
#endif
}
// Paint the filter overlay pixmap, if the filter is enabled and has a width
// greater than zero. Note that we could be more clever here and ensure the
// filter is actually visible prior to painting, but what we're doing here
// is reasonably trivial, so probably not worth the effort.
void
CPlotter::DrawOverlayFilter()
{
if (m_filterEnabled && m_filterWidth > 0)
{
QPainter p(&m_FilterOverlayPixmap);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.fillRect(rect(), Qt::transparent);
2024-09-10 06:36:41 -07:00
int const start = XfromFreq(static_cast<float>(m_filterCenter - m_filterWidth / 2));
int const end = XfromFreq(static_cast<float>(m_filterCenter + m_filterWidth / 2));
// Yellow vertical line, showing the filter location.
p.setPen(Qt::yellow);
p.drawLine(start, 30, start, m_h);
p.drawLine(end, 30, end, m_h);
// Put a mask over everything outside the bandpass.
QColor const blackMask(0, 0, 0, std::clamp(m_filterOpacity, 0, 255));
p.fillRect(0, 30, start, m_h, blackMask);
p.fillRect(end + 1, 30, m_w, m_h, blackMask);
}
2018-02-08 21:28:33 -05:00
}
2024-09-08 09:00:09 -07:00
int CPlotter::XfromFreq(float const f) const //XfromFreq()
2018-02-08 21:28:33 -05:00
{
2024-09-08 19:54:14 -07:00
return std::clamp(static_cast<int>(m_w * (f - m_startFreq) / m_fSpan + 0.5), 0, m_w);
2018-02-08 21:28:33 -05:00
}
2024-09-08 09:00:09 -07:00
float CPlotter::FreqfromX(int const x) const //FreqfromX()
2018-02-08 21:28:33 -05:00
{
2024-09-08 09:00:09 -07:00
return float(m_startFreq + x * m_binsPerPixel * m_fftBinWidth);
2018-02-08 21:28:33 -05:00
}
2024-09-08 09:00:09 -07:00
void CPlotter::setPlot2dGain(int const n) //setPlot2dGain
2018-02-08 21:28:33 -05:00
{
2024-09-08 09:00:09 -07:00
m_plot2dGain = n;
2018-02-08 21:28:33 -05:00
update();
}
2024-09-08 09:00:09 -07:00
void CPlotter::setStartFreq(int const f) //SetStartFreq()
2018-02-08 21:28:33 -05:00
{
2024-09-08 09:00:09 -07:00
m_startFreq = f;
resizeEvent(nullptr);
2018-02-08 21:28:33 -05:00
update();
}
2024-09-08 09:00:09 -07:00
void CPlotter::UpdateOverlay() //UpdateOverlay
{
DrawOverlay();
}
2018-02-08 21:28:33 -05:00
2024-09-08 09:00:09 -07:00
void CPlotter::setBinsPerPixel(int const n) //setBinsPerPixel
2018-02-08 21:28:33 -05:00
{
m_binsPerPixel = n < 1 ? 1 : n;
2018-02-08 21:28:33 -05:00
DrawOverlay(); //Redraw scales and ticks
update(); //trigger a new paintEvent}
}
2024-09-08 09:00:09 -07:00
void CPlotter::setRxFreq(int const x) //setRxFreq
2018-02-08 21:28:33 -05:00
{
m_rxFreq = x; // x is freq in Hz
DrawOverlay();
update();
}
void CPlotter::leaveEvent(QEvent *)
{
m_lastMouseX = -1;
}
2024-09-08 19:54:14 -07:00
void CPlotter::wheelEvent(QWheelEvent * event)
{
auto const delta = event->angleDelta();
if (delta.isNull())
{
event->ignore();
return;
}
2024-09-08 09:00:09 -07:00
int const dir = delta.y() > 0 ? 1 : -1;
int newFreq = rxFreq();
2024-09-08 19:54:14 -07:00
if(event->modifiers() & Qt::ControlModifier)
2024-09-08 09:00:09 -07:00
{
newFreq += dir;
2024-09-08 19:54:14 -07:00
}
else
{
2024-09-08 09:00:09 -07:00
newFreq = newFreq / 10 * 10 + dir * 10;
}
2024-09-08 09:00:09 -07:00
emit setFreq1(newFreq, newFreq);
}
2024-09-08 09:00:09 -07:00
void CPlotter::mouseMoveEvent(QMouseEvent * event)
{
2024-09-08 09:00:09 -07:00
auto const x = std::clamp(static_cast<int>(event->position().x()), 0, m_Size.width());
2024-09-08 09:00:09 -07:00
m_lastMouseX = x;
#if DRAW_FREQ_OVERLAY
2024-09-08 09:00:09 -07:00
DrawOverlay();
#endif
2024-09-08 09:00:09 -07:00
update();
event->ignore();
2018-02-08 21:28:33 -05:00
2024-09-08 09:00:09 -07:00
QToolTip::showText(event->globalPosition().toPoint(),
QString::number(int(FreqfromX(x))));
}
void CPlotter::mouseReleaseEvent(QMouseEvent * event)
{
if (Qt::LeftButton == event->button())
{
auto const x = std::clamp(static_cast<int>(event->position().x()), 0, m_Size.width());
bool const ctrl = event->modifiers() & Qt::ControlModifier;
bool const shift = event->modifiers() & Qt::ShiftModifier;
auto const newFreq = int(FreqfromX(x)+0.5);
int const oldTxFreq = m_txFreq;
int const oldRxFreq = m_rxFreq;
if (ctrl) { emit setFreq1(newFreq, newFreq ); }
else if (shift) { emit setFreq1(oldRxFreq, newFreq ); }
else { emit setFreq1(newFreq, oldTxFreq); }
emit freezeDecode1(ctrl ? 101 : 1);
}
else
{
event->ignore(); // let parent handle
2018-02-08 21:28:33 -05:00
}
}
2024-09-08 09:00:09 -07:00
void CPlotter::mouseDoubleClickEvent(QMouseEvent * event)
2018-02-08 21:28:33 -05:00
{
2024-09-08 09:00:09 -07:00
if (Qt::LeftButton == event->button())
{
emit freezeDecode1(event->modifiers() & Qt::ControlModifier ? 102 : 2);
2018-02-08 21:28:33 -05:00
}
2024-09-08 09:00:09 -07:00
else
{
event->ignore(); // let parent handle
2018-02-08 21:28:33 -05:00
}
}
2024-09-08 09:00:09 -07:00
void CPlotter::setNsps(int const ntrperiod, int const nsps) //setNsps
2018-02-08 21:28:33 -05:00
{
2024-09-08 09:00:09 -07:00
m_TRperiod = ntrperiod;
m_nsps = nsps;
m_fftBinWidth = fftBinWidth(nsps);
2024-09-08 09:00:09 -07:00
DrawOverlay(); //Redraw scales and ticks
update(); //trigger a new paintEvent}
2018-02-08 21:28:33 -05:00
}
2024-09-08 09:00:09 -07:00
void CPlotter::setTxFreq(int const n) //setTxFreq
2018-02-08 21:28:33 -05:00
{
2024-09-08 09:00:09 -07:00
m_txFreq = n;
2018-02-08 21:28:33 -05:00
DrawOverlay();
update();
}
2024-09-08 09:00:09 -07:00
void CPlotter::setDialFreq(double const d)
2018-02-08 21:28:33 -05:00
{
2024-09-08 09:00:09 -07:00
m_dialFreq = d;
2018-02-08 21:28:33 -05:00
DrawOverlay();
update();
}
2024-09-08 10:00:57 -07:00
void CPlotter::setRxBand(QString const & band)
2018-02-08 21:28:33 -05:00
{
2024-09-08 09:00:09 -07:00
m_rxBand = band;
2018-11-04 22:37:14 -05:00
DrawOverlay();
update();
}
2024-09-08 09:00:09 -07:00
void CPlotter::setTurbo(bool const turbo)
2018-11-04 22:37:14 -05:00
{
2024-09-08 09:00:09 -07:00
m_turbo = turbo;
2018-11-04 22:37:14 -05:00
DrawOverlay();
update();
2018-02-08 21:28:33 -05:00
}
2024-09-08 09:00:09 -07:00
void CPlotter::setFilterCenter(int const center)
{
m_filterCenter = center;
DrawOverlay();
update();
}
2024-09-08 09:00:09 -07:00
void CPlotter::setFilterWidth(int const width)
{
2024-09-08 09:00:09 -07:00
m_filterWidth = width;
DrawOverlay();
update();
}
2024-09-08 09:00:09 -07:00
void CPlotter::setFilterEnabled(bool const enabled)
{
m_filterEnabled = enabled;
DrawOverlay();
update();
}
2024-09-08 09:00:09 -07:00
void CPlotter::setFilterOpacity(int const alpha)
{
2024-09-09 05:43:55 -07:00
m_filterOpacity = alpha;
DrawOverlay();
update();
}
void
CPlotter::setRxRange(int const fMin)
2018-02-08 21:28:33 -05:00
{
m_fMin = fMin;
DrawOverlay();
update();
2018-02-08 21:28:33 -05:00
}
void
CPlotter::setMode(QString const & mode)
{
m_mode = mode;
DrawOverlay();
update();
}
void
CPlotter::setSubMode(int const nSubMode)
{
m_nSubMode = nSubMode;
DrawOverlay();
update();
}
void
CPlotter::setTol(int const n)
2018-02-08 21:28:33 -05:00
{
2024-09-09 05:43:55 -07:00
m_tol = n; // XXX this is never referenced
2018-02-08 21:28:33 -05:00
DrawOverlay();
update();
}
void CPlotter::setFlatten(bool const b1, bool const b2)
{
m_Flatten = 0;
if (b1) m_Flatten = 1;
if (b2) m_Flatten = 2;
2018-02-08 21:28:33 -05:00
}
void CPlotter::SetPercent2DScreen(int percent)
{
m_Percent2DScreen=percent;
2024-09-08 09:00:09 -07:00
resizeEvent(nullptr);
2018-02-08 21:28:33 -05:00
update();
}