Commit db4f8ba0b7b2bcc9ee7f41c96b597cdda56acacc

Authored by David Graeff
Committed by David Gräff
1 parent 4a1617f4

Fix digital phosphor effect

openhantek/src/glgenerator.cpp
@@ -11,8 +11,8 @@ GlGenerator::GlGenerator(DsoSettingsScope *scope, DsoSettingsView *view) : setti @@ -11,8 +11,8 @@ GlGenerator::GlGenerator(DsoSettingsScope *scope, DsoSettingsView *view) : setti
11 const int DIVS_TIME_S2 = (int)DIVS_TIME - 2; 11 const int DIVS_TIME_S2 = (int)DIVS_TIME - 2;
12 const int DIVS_VOLTAGE_S2 = (int)DIVS_VOLTAGE - 2; 12 const int DIVS_VOLTAGE_S2 = (int)DIVS_VOLTAGE - 2;
13 const int vaGrid0Size = (int) ((DIVS_TIME * DIVS_SUB - 2) * DIVS_VOLTAGE_S2 + 13 const int vaGrid0Size = (int) ((DIVS_TIME * DIVS_SUB - 2) * DIVS_VOLTAGE_S2 +
14 - (DIVS_VOLTAGE * DIVS_SUB - 2) * DIVS_TIME_S2 -  
15 - (DIVS_TIME_S2 * DIVS_VOLTAGE_S2)) * 2; 14 + (DIVS_VOLTAGE * DIVS_SUB - 2) * DIVS_TIME_S2 -
  15 + (DIVS_TIME_S2 * DIVS_VOLTAGE_S2)) * 2;
16 16
17 vaGrid[0].resize(vaGrid0Size); 17 vaGrid[0].resize(vaGrid0Size);
18 std::vector<GLfloat>::iterator glIterator = vaGrid[0].begin(); 18 std::vector<GLfloat>::iterator glIterator = vaGrid[0].begin();
@@ -105,106 +105,116 @@ const std::vector&lt;GLfloat&gt; &amp;GlGenerator::grid(int a) const { return vaGrid[a]; } @@ -105,106 +105,116 @@ const std::vector&lt;GLfloat&gt; &amp;GlGenerator::grid(int a) const { return vaGrid[a]; }
105 105
106 bool GlGenerator::isReady() const { return ready; } 106 bool GlGenerator::isReady() const { return ready; }
107 107
  108 +GlGenerator::PrePostStartTriggerSamples GlGenerator::computeSoftwareTriggerTY(const DataAnalyzerResult *result)
  109 +{
  110 + unsigned int preTrigSamples = 0;
  111 + unsigned int postTrigSamples = 0;
  112 + unsigned int swTriggerStart = 0;
  113 + unsigned int channel = settings->trigger.source;
  114 +
  115 + // check trigger point for software trigger
  116 + if (settings->trigger.mode != Dso::TRIGGERMODE_SOFTWARE || channel >= settings->physicalChannels)
  117 + return PrePostStartTriggerSamples(preTrigSamples, postTrigSamples, swTriggerStart);
  118 +
  119 + // Trigger channel not in use
  120 + if (!settings->voltage[channel].used || !result->data(channel) ||
  121 + result->data(channel)->voltage.sample.empty())
  122 + return PrePostStartTriggerSamples(preTrigSamples, postTrigSamples, swTriggerStart);
  123 +
  124 + double value;
  125 + double level = settings->voltage[channel].trigger;
  126 + unsigned int sampleCount = result->data(channel)->voltage.sample.size();
  127 + double timeDisplay = settings->horizontal.timebase * 10;
  128 + double samplesDisplay = timeDisplay * settings->horizontal.samplerate;
  129 + if (samplesDisplay >= sampleCount) {
  130 + // For sure not enough samples to adjust for jitter.
  131 + // Following options exist:
  132 + // 1: Decrease sample rate
  133 + // 2: Change trigger mode to auto
  134 + // 3: Ignore samples
  135 + // For now #3 is chosen
  136 + timestampDebug(QString("Too few samples to make a steady "
  137 + "picture. Decrease sample rate"));
  138 + return PrePostStartTriggerSamples(preTrigSamples, postTrigSamples, swTriggerStart);
  139 + }
  140 + preTrigSamples = (settings->trigger.position * samplesDisplay);
  141 + postTrigSamples = sampleCount - (samplesDisplay - preTrigSamples);
  142 +
  143 + const int threshold = 7;
  144 + double prev;
  145 + bool (*opcmp)(int,int,int);
  146 + bool (*smplcmp)(int,int);
  147 + if (settings->trigger.slope == Dso::SLOPE_POSITIVE) {
  148 + prev = INT_MAX;
  149 + opcmp = [](int value, int level, int prev) { return value > level && prev <= level;};
  150 + smplcmp = [](int sampleK, int value) { return sampleK >= value;};
  151 + } else {
  152 + prev = INT_MIN;
  153 + opcmp = [](int value, int level, int prev) { return value > level && prev <= level;};
  154 + smplcmp = [](int sampleK, int value) { return sampleK < value;};
  155 + }
  156 +
  157 + for (unsigned int i = preTrigSamples; i < postTrigSamples; i++) {
  158 + value = result->data(channel)->voltage.sample[i];
  159 + if (opcmp(value, level, prev)) {
  160 + int rising = 0;
  161 + for (unsigned int k = i + 1; k < i + 11 && k < sampleCount; k++) {
  162 + if (smplcmp(result->data(channel)->voltage.sample[k], value)) { rising++; }
  163 + }
  164 + if (rising > threshold) {
  165 + swTriggerStart = i;
  166 + break;
  167 + }
  168 + }
  169 + prev = value;
  170 + }
  171 + if (swTriggerStart == 0) {
  172 + timestampDebug(QString("Trigger not asserted. Data ignored"));
  173 + }
  174 + return PrePostStartTriggerSamples(preTrigSamples, postTrigSamples, swTriggerStart);
  175 +}
  176 +
108 void GlGenerator::generateGraphs(const DataAnalyzerResult *result) { 177 void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {
109 178
110 - int digitalPhosphorDepth = view->digitalPhosphorDepth; 179 + int digitalPhosphorDepth = view->digitalPhosphor ? view->digitalPhosphorDepth : 1;
111 180
112 // Handle all digital phosphor related list manipulations 181 // Handle all digital phosphor related list manipulations
113 for (int mode = Dso::CHANNELMODE_VOLTAGE; mode < Dso::CHANNELMODE_COUNT; ++mode) { 182 for (int mode = Dso::CHANNELMODE_VOLTAGE; mode < Dso::CHANNELMODE_COUNT; ++mode) {
114 - // Adapt the number of graphs  
115 - vaChannel[mode].resize(settings->voltage.size()); 183 + DrawLinesWithHistoryPerChannel& d = vaChannel[mode];
  184 + // Resize to the number of channels
  185 + d.resize(settings->voltage.size());
116 186
117 for (unsigned int channel = 0; channel < vaChannel[mode].size(); ++channel) { 187 for (unsigned int channel = 0; channel < vaChannel[mode].size(); ++channel) {
  188 + DrawLinesWithHistory& drawLinesHistory = d[channel];
118 // Move the last list element to the front 189 // Move the last list element to the front
119 - vaChannel[mode][channel].push_front(std::vector<GLfloat>()); 190 + if (digitalPhosphorDepth > 1 && drawLinesHistory.size())
  191 + drawLinesHistory.push_front(drawLinesHistory.back());
120 192
121 // Resize lists for vector array to fit the digital phosphor depth 193 // Resize lists for vector array to fit the digital phosphor depth
122 - vaChannel[mode][channel].resize(digitalPhosphorDepth); 194 + drawLinesHistory.resize(digitalPhosphorDepth);
123 } 195 }
124 } 196 }
125 197
126 ready = true; 198 ready = true;
127 199
128 - unsigned int preTrigSamples = 0;  
129 - unsigned int postTrigSamples = 0; 200 + unsigned preTrigSamples;
  201 + unsigned postTrigSamples;
  202 + unsigned swTriggerStart;
130 switch (settings->horizontal.format) { 203 switch (settings->horizontal.format) {
131 - case Dso::GRAPHFORMAT_TY: {  
132 - unsigned int swTriggerStart = 0;  
133 - // check trigger point for software trigger  
134 - if (settings->trigger.mode == Dso::TRIGGERMODE_SOFTWARE && settings->trigger.source <= 1) {  
135 - unsigned int channel = settings->trigger.source;  
136 - if (settings->voltage[channel].used && result->data(channel) &&  
137 - !result->data(channel)->voltage.sample.empty()) {  
138 - double value;  
139 - double level = settings->voltage[channel].trigger;  
140 - unsigned int sampleCount = result->data(channel)->voltage.sample.size();  
141 - double timeDisplay = settings->horizontal.timebase * 10;  
142 - double samplesDisplay = timeDisplay * settings->horizontal.samplerate;  
143 - if (samplesDisplay >= sampleCount) {  
144 - // For sure not enough samples to adjust for jitter.  
145 - // Following options exist:  
146 - // 1: Decrease sample rate  
147 - // 2: Change trigger mode to auto  
148 - // 3: Ignore samples  
149 - // For now #3 is chosen  
150 - timestampDebug(QString("Too few samples to make a steady "  
151 - "picture. Decrease sample rate"));  
152 - return;  
153 - }  
154 - preTrigSamples = (settings->trigger.position * samplesDisplay);  
155 - postTrigSamples = sampleCount - (samplesDisplay - preTrigSamples);  
156 -  
157 - if (settings->trigger.slope == Dso::SLOPE_POSITIVE) {  
158 - double prev = INT_MAX;  
159 - for (unsigned int i = preTrigSamples; i < postTrigSamples; i++) {  
160 - value = result->data(channel)->voltage.sample[i];  
161 - if (value > level && prev <= level) {  
162 - int rising = 0;  
163 - for (unsigned int k = i + 1; k < i + 11 && k < sampleCount; k++) {  
164 - if (result->data(channel)->voltage.sample[k] >= value) { rising++; }  
165 - }  
166 - if (rising > 7) {  
167 - swTriggerStart = i;  
168 - break;  
169 - }  
170 - }  
171 - prev = value;  
172 - }  
173 - } else if (settings->trigger.slope == Dso::SLOPE_NEGATIVE) {  
174 - double prev = INT_MIN;  
175 - for (unsigned int i = preTrigSamples; i < postTrigSamples; i++) {  
176 - value = result->data(channel)->voltage.sample[i];  
177 - if (value < level && prev >= level) {  
178 - int falling = 0;  
179 - for (unsigned int k = i + 1; k < i + 11 && k < sampleCount; k++) {  
180 - if (result->data(channel)->voltage.sample[k] < value) { falling++; }  
181 - }  
182 - if (falling > 7) {  
183 - swTriggerStart = i;  
184 - break;  
185 - }  
186 - }  
187 - prev = value;  
188 - }  
189 - }  
190 - }  
191 - if (swTriggerStart == 0) {  
192 - timestampDebug(QString("Trigger not asserted. Data ignored"));  
193 - return;  
194 - }  
195 - } 204 + case Dso::GRAPHFORMAT_TY:
  205 + std::tie(preTrigSamples, postTrigSamples, swTriggerStart) = computeSoftwareTriggerTY(result);
196 206
197 // Add graphs for channels 207 // Add graphs for channels
198 for (int mode = Dso::CHANNELMODE_VOLTAGE; mode < Dso::CHANNELMODE_COUNT; ++mode) { 208 for (int mode = Dso::CHANNELMODE_VOLTAGE; mode < Dso::CHANNELMODE_COUNT; ++mode) {
199 for (int channel = 0; channel < (int)settings->voltage.size(); ++channel) { 209 for (int channel = 0; channel < (int)settings->voltage.size(); ++channel) {
200 // Check if this channel is used and available at the data analyzer 210 // Check if this channel is used and available at the data analyzer
201 if (((mode == Dso::CHANNELMODE_VOLTAGE) ? settings->voltage[channel].used 211 if (((mode == Dso::CHANNELMODE_VOLTAGE) ? settings->voltage[channel].used
202 - : settings->spectrum[channel].used) &&  
203 - result->data(channel) && !result->data(channel)->voltage.sample.empty()) { 212 + : settings->spectrum[channel].used) &&
  213 + result->data(channel) && !result->data(channel)->voltage.sample.empty()) {
204 // Check if the sample count has changed 214 // Check if the sample count has changed
205 size_t sampleCount = (mode == Dso::CHANNELMODE_VOLTAGE) 215 size_t sampleCount = (mode == Dso::CHANNELMODE_VOLTAGE)
206 - ? result->data(channel)->voltage.sample.size()  
207 - : result->data(channel)->spectrum.sample.size(); 216 + ? result->data(channel)->voltage.sample.size()
  217 + : result->data(channel)->spectrum.sample.size();
208 if (mode == Dso::CHANNELMODE_VOLTAGE) sampleCount -= (swTriggerStart - preTrigSamples); 218 if (mode == Dso::CHANNELMODE_VOLTAGE) sampleCount -= (swTriggerStart - preTrigSamples);
209 size_t neededSize = sampleCount * 2; 219 size_t neededSize = sampleCount * 2;
210 220
@@ -227,12 +237,12 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) { @@ -227,12 +237,12 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {
227 horizontalFactor = result->data(channel)->voltage.interval / settings->horizontal.timebase; 237 horizontalFactor = result->data(channel)->voltage.interval / settings->horizontal.timebase;
228 else 238 else
229 horizontalFactor = 239 horizontalFactor =
230 - result->data(channel)->spectrum.interval / settings->horizontal.frequencybase; 240 + result->data(channel)->spectrum.interval / settings->horizontal.frequencybase;
231 241
232 // Fill vector array 242 // Fill vector array
233 if (mode == Dso::CHANNELMODE_VOLTAGE) { 243 if (mode == Dso::CHANNELMODE_VOLTAGE) {
234 std::vector<double>::const_iterator dataIterator = 244 std::vector<double>::const_iterator dataIterator =
235 - result->data(channel)->voltage.sample.begin(); 245 + result->data(channel)->voltage.sample.begin();
236 const double gain = settings->voltage[channel].gain; 246 const double gain = settings->voltage[channel].gain;
237 const double offset = settings->voltage[channel].offset; 247 const double offset = settings->voltage[channel].offset;
238 const double invert = settings->voltage[channel].inverted ? -1.0 : 1.0; 248 const double invert = settings->voltage[channel].inverted ? -1.0 : 1.0;
@@ -245,7 +255,7 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) { @@ -245,7 +255,7 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {
245 } 255 }
246 } else { 256 } else {
247 std::vector<double>::const_iterator dataIterator = 257 std::vector<double>::const_iterator dataIterator =
248 - result->data(channel)->spectrum.sample.begin(); 258 + result->data(channel)->spectrum.sample.begin();
249 const double magnitude = settings->spectrum[channel].magnitude; 259 const double magnitude = settings->spectrum[channel].magnitude;
250 const double offset = settings->spectrum[channel].offset; 260 const double offset = settings->spectrum[channel].offset;
251 261
@@ -261,15 +271,15 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) { @@ -261,15 +271,15 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {
261 } 271 }
262 } 272 }
263 } 273 }
264 - } break; 274 + break;
265 275
266 case Dso::GRAPHFORMAT_XY: 276 case Dso::GRAPHFORMAT_XY:
267 for (int channel = 0; channel < settings->voltage.size(); ++channel) { 277 for (int channel = 0; channel < settings->voltage.size(); ++channel) {
268 // For even channel numbers check if this channel is used and this and the 278 // For even channel numbers check if this channel is used and this and the
269 // following channel are available at the data analyzer 279 // following channel are available at the data analyzer
270 if (channel % 2 == 0 && channel + 1 < settings->voltage.size() && settings->voltage[channel].used && 280 if (channel % 2 == 0 && channel + 1 < settings->voltage.size() && settings->voltage[channel].used &&
271 - result->data(channel) && !result->data(channel)->voltage.sample.empty() && result->data(channel + 1) &&  
272 - !result->data(channel + 1)->voltage.sample.empty()) { 281 + result->data(channel) && !result->data(channel)->voltage.sample.empty() && result->data(channel + 1) &&
  282 + !result->data(channel + 1)->voltage.sample.empty()) {
273 // Check if the sample count has changed 283 // Check if the sample count has changed
274 const unsigned sampleCount = qMin(result->data(channel)->voltage.sample.size(), 284 const unsigned sampleCount = qMin(result->data(channel)->voltage.sample.size(),
275 result->data(channel + 1)->voltage.sample.size()); 285 result->data(channel + 1)->voltage.sample.size());
@@ -277,7 +287,7 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) { @@ -277,7 +287,7 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {
277 for (unsigned index = 0; index < (unsigned)digitalPhosphorDepth; ++index) { 287 for (unsigned index = 0; index < (unsigned)digitalPhosphorDepth; ++index) {
278 if (vaChannel[Dso::CHANNELMODE_VOLTAGE][(size_t)channel][index].size() != neededSize) 288 if (vaChannel[Dso::CHANNELMODE_VOLTAGE][(size_t)channel][index].size() != neededSize)
279 vaChannel[Dso::CHANNELMODE_VOLTAGE][(size_t)channel][index] 289 vaChannel[Dso::CHANNELMODE_VOLTAGE][(size_t)channel][index]
280 - .clear(); // Something was changed, drop old traces 290 + .clear(); // Something was changed, drop old traces
281 } 291 }
282 292
283 // Set size directly to avoid reallocations 293 // Set size directly to avoid reallocations
@@ -285,7 +295,7 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) { @@ -285,7 +295,7 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {
285 295
286 // Iterator to data for direct access 296 // Iterator to data for direct access
287 std::vector<GLfloat>::iterator glIterator = 297 std::vector<GLfloat>::iterator glIterator =
288 - vaChannel[Dso::CHANNELMODE_VOLTAGE][channel].front().begin(); 298 + vaChannel[Dso::CHANNELMODE_VOLTAGE][channel].front().begin();
289 299
290 // Fill vector array 300 // Fill vector array
291 unsigned int xChannel = channel; 301 unsigned int xChannel = channel;
openhantek/src/glgenerator.h
@@ -30,9 +30,15 @@ class GlGenerator : public QObject { @@ -30,9 +30,15 @@ class GlGenerator : public QObject {
30 bool isReady() const; 30 bool isReady() const;
31 31
32 private: 32 private:
  33 + typedef std::tuple<unsigned,unsigned,unsigned> PrePostStartTriggerSamples;
  34 + typedef std::vector<GLfloat> DrawLines;
  35 + typedef std::deque<DrawLines> DrawLinesWithHistory;
  36 + typedef std::vector<DrawLinesWithHistory> DrawLinesWithHistoryPerChannel;
  37 + DrawLinesWithHistoryPerChannel vaChannel[Dso::CHANNELMODE_COUNT];
  38 +
  39 + PrePostStartTriggerSamples computeSoftwareTriggerTY(const DataAnalyzerResult *result);
33 DsoSettingsScope *settings; 40 DsoSettingsScope *settings;
34 DsoSettingsView *view; 41 DsoSettingsView *view;
35 - std::vector<std::deque<std::vector<GLfloat>>> vaChannel[Dso::CHANNELMODE_COUNT];  
36 std::vector<GLfloat> vaGrid[3]; 42 std::vector<GLfloat> vaGrid[3];
37 bool ready = false; 43 bool ready = false;
38 signals: 44 signals:
openhantek/src/glscope.cpp
@@ -37,7 +37,8 @@ void GlScope::paintGL() { @@ -37,7 +37,8 @@ void GlScope::paintGL() {
37 glClear(GL_COLOR_BUFFER_BIT); 37 glClear(GL_COLOR_BUFFER_BIT);
38 glLineWidth(1); 38 glLineWidth(1);
39 39
40 - if (settings->view.digitalPhosphorDepth > 0 && generator->isReady()) { drawGraph(); } 40 + int digitalPhosphorDepth = settings->view.digitalPhosphor ? settings->view.digitalPhosphorDepth : 1;
  41 + if (generator->isReady()) { drawGraph(digitalPhosphorDepth); }
41 42
42 if (!this->zoomed) { 43 if (!this->zoomed) {
43 // Draw vertical lines at marker positions 44 // Draw vertical lines at marker positions
@@ -126,7 +127,7 @@ void GlScope::drawGraphDepth(int mode, int channel, int index) { @@ -126,7 +127,7 @@ void GlScope::drawGraphDepth(int mode, int channel, int index) {
126 generator->channel(mode, channel, index).size() / 2); 127 generator->channel(mode, channel, index).size() / 2);
127 } 128 }
128 129
129 -void GlScope::drawGraph() { 130 +void GlScope::drawGraph(int digitalPhosphorDepth) {
130 if (settings->view.antialiasing) { 131 if (settings->view.antialiasing) {
131 glEnable(GL_POINT_SMOOTH); 132 glEnable(GL_POINT_SMOOTH);
132 glEnable(GL_LINE_SMOOTH); 133 glEnable(GL_LINE_SMOOTH);
@@ -142,11 +143,11 @@ void GlScope::drawGraph() { @@ -142,11 +143,11 @@ void GlScope::drawGraph() {
142 } 143 }
143 144
144 // Values we need for the fading of the digital phosphor 145 // Values we need for the fading of the digital phosphor
145 - if ((int)fadingFactor.size() != settings->view.digitalPhosphorDepth) {  
146 - fadingFactor.resize((size_t)settings->view.digitalPhosphorDepth); 146 + if ((int)fadingFactor.size() != digitalPhosphorDepth) {
  147 + fadingFactor.resize((size_t)digitalPhosphorDepth);
147 fadingFactor[0] = 100; 148 fadingFactor[0] = 100;
148 - double fadingRatio = pow(10.0, 2.0 / settings->view.digitalPhosphorDepth);  
149 - for (size_t index = 1; index < (size_t)settings->view.digitalPhosphorDepth; ++index) 149 + double fadingRatio = pow(10.0, 2.0 / digitalPhosphorDepth);
  150 + for (size_t index = 1; index < (size_t)digitalPhosphorDepth; ++index)
150 fadingFactor[index] = fadingFactor[index - 1] * fadingRatio; 151 fadingFactor[index] = fadingFactor[index - 1] * fadingRatio;
151 } 152 }
152 153
@@ -158,7 +159,7 @@ void GlScope::drawGraph() { @@ -158,7 +159,7 @@ void GlScope::drawGraph() {
158 if (!channelUsed(mode, channel)) continue; 159 if (!channelUsed(mode, channel)) continue;
159 160
160 // Draw graph for all available depths 161 // Draw graph for all available depths
161 - for (int index = settings->view.digitalPhosphorDepth - 1; index >= 0; index--) { 162 + for (int index = digitalPhosphorDepth - 1; index >= 0; index--) {
162 drawGraphDepth(mode, channel, index); 163 drawGraphDepth(mode, channel, index);
163 } 164 }
164 } 165 }
@@ -169,7 +170,7 @@ void GlScope::drawGraph() { @@ -169,7 +170,7 @@ void GlScope::drawGraph() {
169 // Real and virtual channels 170 // Real and virtual channels
170 for (int channel = 0; channel < settings->scope.voltage.size() - 1; channel += 2) { 171 for (int channel = 0; channel < settings->scope.voltage.size() - 1; channel += 2) {
171 if (settings->scope.voltage[channel].used) { 172 if (settings->scope.voltage[channel].used) {
172 - for (int index = settings->view.digitalPhosphorDepth - 1; index >= 0; index--) { 173 + for (int index = digitalPhosphorDepth - 1; index >= 0; index--) {
173 drawGraphDepth(Dso::CHANNELMODE_VOLTAGE, channel, index); 174 drawGraphDepth(Dso::CHANNELMODE_VOLTAGE, channel, index);
174 } 175 }
175 } 176 }
openhantek/src/glscope.h
@@ -39,7 +39,7 @@ class GlScope : public GL_WIDGET_CLASS { @@ -39,7 +39,7 @@ class GlScope : public GL_WIDGET_CLASS {
39 39
40 void drawGrid(); 40 void drawGrid();
41 void drawGraphDepth(int mode, int channel, int index); 41 void drawGraphDepth(int mode, int channel, int index);
42 - void drawGraph(); 42 + void drawGraph(int digitalPhosphorDepth);
43 bool channelUsed(int mode, int channel); 43 bool channelUsed(int mode, int channel);
44 44
45 private: 45 private: