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 11 const int DIVS_TIME_S2 = (int)DIVS_TIME - 2;
12 12 const int DIVS_VOLTAGE_S2 = (int)DIVS_VOLTAGE - 2;
13 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 17 vaGrid[0].resize(vaGrid0Size);
18 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 105  
106 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 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 181 // Handle all digital phosphor related list manipulations
113 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 187 for (unsigned int channel = 0; channel < vaChannel[mode].size(); ++channel) {
  188 + DrawLinesWithHistory& drawLinesHistory = d[channel];
118 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 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 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 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 207 // Add graphs for channels
198 208 for (int mode = Dso::CHANNELMODE_VOLTAGE; mode < Dso::CHANNELMODE_COUNT; ++mode) {
199 209 for (int channel = 0; channel < (int)settings->voltage.size(); ++channel) {
200 210 // Check if this channel is used and available at the data analyzer
201 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 214 // Check if the sample count has changed
205 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 218 if (mode == Dso::CHANNELMODE_VOLTAGE) sampleCount -= (swTriggerStart - preTrigSamples);
209 219 size_t neededSize = sampleCount * 2;
210 220  
... ... @@ -227,12 +237,12 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {
227 237 horizontalFactor = result->data(channel)->voltage.interval / settings->horizontal.timebase;
228 238 else
229 239 horizontalFactor =
230   - result->data(channel)->spectrum.interval / settings->horizontal.frequencybase;
  240 + result->data(channel)->spectrum.interval / settings->horizontal.frequencybase;
231 241  
232 242 // Fill vector array
233 243 if (mode == Dso::CHANNELMODE_VOLTAGE) {
234 244 std::vector<double>::const_iterator dataIterator =
235   - result->data(channel)->voltage.sample.begin();
  245 + result->data(channel)->voltage.sample.begin();
236 246 const double gain = settings->voltage[channel].gain;
237 247 const double offset = settings->voltage[channel].offset;
238 248 const double invert = settings->voltage[channel].inverted ? -1.0 : 1.0;
... ... @@ -245,7 +255,7 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {
245 255 }
246 256 } else {
247 257 std::vector<double>::const_iterator dataIterator =
248   - result->data(channel)->spectrum.sample.begin();
  258 + result->data(channel)->spectrum.sample.begin();
249 259 const double magnitude = settings->spectrum[channel].magnitude;
250 260 const double offset = settings->spectrum[channel].offset;
251 261  
... ... @@ -261,15 +271,15 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {
261 271 }
262 272 }
263 273 }
264   - } break;
  274 + break;
265 275  
266 276 case Dso::GRAPHFORMAT_XY:
267 277 for (int channel = 0; channel < settings->voltage.size(); ++channel) {
268 278 // For even channel numbers check if this channel is used and this and the
269 279 // following channel are available at the data analyzer
270 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 283 // Check if the sample count has changed
274 284 const unsigned sampleCount = qMin(result->data(channel)->voltage.sample.size(),
275 285 result->data(channel + 1)->voltage.sample.size());
... ... @@ -277,7 +287,7 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {
277 287 for (unsigned index = 0; index < (unsigned)digitalPhosphorDepth; ++index) {
278 288 if (vaChannel[Dso::CHANNELMODE_VOLTAGE][(size_t)channel][index].size() != neededSize)
279 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 293 // Set size directly to avoid reallocations
... ... @@ -285,7 +295,7 @@ void GlGenerator::generateGraphs(const DataAnalyzerResult *result) {
285 295  
286 296 // Iterator to data for direct access
287 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 300 // Fill vector array
291 301 unsigned int xChannel = channel;
... ...
openhantek/src/glgenerator.h
... ... @@ -30,9 +30,15 @@ class GlGenerator : public QObject {
30 30 bool isReady() const;
31 31  
32 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 40 DsoSettingsScope *settings;
34 41 DsoSettingsView *view;
35   - std::vector<std::deque<std::vector<GLfloat>>> vaChannel[Dso::CHANNELMODE_COUNT];
36 42 std::vector<GLfloat> vaGrid[3];
37 43 bool ready = false;
38 44 signals:
... ...
openhantek/src/glscope.cpp
... ... @@ -37,7 +37,8 @@ void GlScope::paintGL() {
37 37 glClear(GL_COLOR_BUFFER_BIT);
38 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 43 if (!this->zoomed) {
43 44 // Draw vertical lines at marker positions
... ... @@ -126,7 +127,7 @@ void GlScope::drawGraphDepth(int mode, int channel, int index) {
126 127 generator->channel(mode, channel, index).size() / 2);
127 128 }
128 129  
129   -void GlScope::drawGraph() {
  130 +void GlScope::drawGraph(int digitalPhosphorDepth) {
130 131 if (settings->view.antialiasing) {
131 132 glEnable(GL_POINT_SMOOTH);
132 133 glEnable(GL_LINE_SMOOTH);
... ... @@ -142,11 +143,11 @@ void GlScope::drawGraph() {
142 143 }
143 144  
144 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 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 151 fadingFactor[index] = fadingFactor[index - 1] * fadingRatio;
151 152 }
152 153  
... ... @@ -158,7 +159,7 @@ void GlScope::drawGraph() {
158 159 if (!channelUsed(mode, channel)) continue;
159 160  
160 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 163 drawGraphDepth(mode, channel, index);
163 164 }
164 165 }
... ... @@ -169,7 +170,7 @@ void GlScope::drawGraph() {
169 170 // Real and virtual channels
170 171 for (int channel = 0; channel < settings->scope.voltage.size() - 1; channel += 2) {
171 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 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 39  
40 40 void drawGrid();
41 41 void drawGraphDepth(int mode, int channel, int index);
42   - void drawGraph();
  42 + void drawGraph(int digitalPhosphorDepth);
43 43 bool channelUsed(int mode, int channel);
44 44  
45 45 private:
... ...