JS8Call-Improved master
Loading...
Searching...
No Matches
CPlotter.h
1// -*- Mode: C++ -*-
3// Some code in this file and accompanying files is based on work by
4// Moe Wheatley, AE4Y, released under the "Simplified BSD License".
5// For more details see the accompanying file LICENSE_WHEATLEY.TXT
7
8#ifndef PLOTTER_H
9#define PLOTTER_H
10
11#include "JS8_Main/Flatten.h"
12#include "RDP.h"
13#include "WF.h"
14
15#include <QColor>
16#include <QPixmap>
17#include <QPolygonF>
18#include <QSize>
19#include <QString>
20#include <QTimer>
21#include <QVector>
22#include <QWidget>
23
24#include <algorithm>
25#include <array>
26#include <boost/circular_buffer.hpp>
27#include <cmath>
28#include <limits>
29#include <variant>
30
31class CPlotter final : public QWidget {
32 Q_OBJECT
33
34 // Scaler for the waterfall portion of the display; given a
35 // y value, returns an index [0, 255) into the colors array.
36
37 class Scaler1D {
38 int const &m_avg;
39 int const &m_bpp;
40 int m_gain = 0;
41 int m_zero = 0;
42 float m_scale;
43
44 public:
45 Scaler1D(int const &avg, int const &bpp) : m_avg(avg), m_bpp(bpp) {
46 rescale();
47 }
48
49 void rescale() {
50 m_scale = 10.0f * std::sqrt(m_bpp * m_avg / 15.0f) *
51 std::pow(10.0f, 0.015f * m_gain);
52 }
53
54 int gain() const { return m_gain; }
55 int zero() const { return m_zero; }
56
57 void setGain(int const gain) {
58 m_gain = gain;
59 rescale();
60 }
61 void setZero(int const zero) { m_zero = zero; }
62
63 inline auto operator()(float const value) const {
64 return std::isnan(value)
65 ? 0
66 : std::clamp(m_zero + static_cast<int>(m_scale * value),
67 0, 254);
68 }
69 };
70
71 // Scaler for the spectrum portion of the display; given a
72 // y value, returns a pixel offset into the spectrum view.
73
74 class Scaler2D {
75 int const &m_h2;
76 int m_gain = 0;
77 int m_zero = 0;
78 float m_scaledGain;
79 float m_scaledZero;
80
81 public:
82 Scaler2D(int const &h2) : m_h2(h2) { rescale(); }
83
84 void rescale() {
85 m_scaledGain = m_h2 / 70.0f * std::pow(10.0f, 0.02f * m_gain);
86 m_scaledZero = m_h2 * 0.9f - m_h2 / 70.0f * m_zero;
87 }
88
89 int gain() const { return m_gain; }
90 int zero() const { return m_zero; }
91
92 void setGain(int const gain) {
93 m_gain = gain;
94 rescale();
95 }
96 void setZero(int const zero) {
97 m_zero = zero;
98 rescale();
99 }
100
101 inline auto operator()(float const value) const {
102 return m_scaledZero - m_scaledGain * value;
103 }
104 };
105
106 public:
107 using Colors = QVector<QColor>;
108 using Spectrum = WF::Spectrum;
109
110 explicit CPlotter(QWidget *parent = nullptr);
111
112 ~CPlotter();
113
114 // Sizing
115
116 QSize minimumSizeHint() const override;
117 QSize sizeHint() const override;
118
119 // Inline accessors
120
121 int binsPerPixel() const { return m_binsPerPixel; }
122 int flatten() const { return m_flatten.live(); }
123 int freq() const { return m_freq; }
124 int percent2D() const { return m_percent2D; }
125 int plot2dGain() const { return m_scaler2D.gain(); }
126 int plot2dZero() const { return m_scaler2D.zero(); }
127 int plotGain() const { return m_scaler1D.gain(); }
128 int plotZero() const { return m_scaler1D.zero(); }
129 Spectrum spectrum() const { return m_spectrum; }
130 int startFreq() const { return m_startFreq; }
131
132 int frequencyAt(int const x) const {
133 return static_cast<int>(freqFromX(x));
134 }
135
136 // Inline manipulators
137
138 void setFlatten(bool const flatten) { m_flatten(flatten); }
139 void setPlot2dGain(int const plot2dGain) { m_scaler2D.setGain(plot2dGain); }
140 void setPlot2dZero(int const plot2dZero) { m_scaler2D.setZero(plot2dZero); }
141 void setSpectrum(Spectrum const spectrum) { m_spectrum = spectrum; }
142
143 // Manipulators
144
145 void drawLine(QString const &);
146 void drawData(WF::SWide, WF::State);
147 void drawDecodeLine(const QColor &, int, int);
148 void drawHorizontalLine(const QColor &, int, int);
149 void setBinsPerPixel(int);
150 void setColors(Colors const &);
151 void setDialFreq(float);
152 void setFilter(int, int);
153 void setFilterEnabled(bool);
154 void setFilterOpacity(int);
155 void setFreq(int);
156 void setPercent2D(int);
157 void setPlotGain(int);
158 void setPlotZero(int);
159 void setStartFreq(int);
160 void setSubMode(int);
161 void setWaterfallAvg(int);
162
163 signals:
164
165 void changeFreq(int);
166
167 protected:
168 // Event Handlers
169
170 void paintEvent(QPaintEvent *) override;
171 void resizeEvent(QResizeEvent *) override;
172 void leaveEvent(QEvent *) override;
173 void wheelEvent(QWheelEvent *) override;
174 void mouseMoveEvent(QMouseEvent *) override;
175 void mouseReleaseEvent(QMouseEvent *) override;
176
177 private:
178 // Replot data storage; alternatives of nothing at all, a
179 // string denoting the label of a transmit period interval
180 // start, and waterfall display data, flattened. Important
181 // that the monostate alternative is first in the list.
182
183 using Replot = boost::circular_buffer<
184 std::variant<std::monostate, QString, WF::SWide>>;
185
186 // Accessors
187
188 bool shouldDrawSpectrum(WF::State) const;
189 bool in30MBand() const;
190 int xFromFreq(float f) const;
191 float freqFromX(int x) const;
192
193 // Manipulators
194
195 void drawMetrics();
196 void drawFilter();
197 void drawDials();
198 void replot();
199 void resize();
200
201 // Data members ** ORDER DEPENDENCY **
202
203 float m_dialFreq = 0.0f;
204 int m_nSubMode = 0;
205 int m_filterCenter = 0;
206 int m_filterWidth = 0;
207 int m_filterOpacity = 127;
208 int m_percent2D = 0;
209 int m_binsPerPixel = 2;
210 int m_waterfallAvg = 1;
211 int m_lastMouseX = -1;
212 int m_line = std::numeric_limits<int>::max();
213 int m_startFreq = 0;
214 int m_freq = 0;
215 int m_w = 0;
216 int m_h1 = 0;
217 int m_h2 = 0;
218 bool m_filterEnabled = false;
219 float m_freqPerPixel;
220
221 RDP m_rdp;
222 Scaler1D m_scaler1D;
223 Scaler2D m_scaler2D;
224 Colors m_colors;
225 Replot m_replot;
226 QPolygonF m_points;
227 Flatten m_flatten;
228 Spectrum m_spectrum = Spectrum::Current;
229 QTimer *m_replotTimer;
230 QTimer *m_resizeTimer;
231
232 QPixmap m_ScalePixmap;
233 QPixmap m_WaterfallPixmap;
234 QPixmap m_OverlayPixmap;
235 QPixmap m_SpectrumPixmap;
236
237 std::array<QPixmap, 2> m_FilterPixmap = {};
238 std::array<QPixmap, 2> m_DialPixmap = {};
239
240 QString m_text;
241};
242
243#endif // PLOTTER_H
Definition Flatten.h:9
Definition RDP.h:9