Commit 45479282876370e5670dd5ebff24cd8e6dba0e43

Authored by oliverhaag
1 parent fba5d6e4

Roll-mode support

openhantek/ChangeLog
@@ -203,3 +203,8 @@ @@ -203,3 +203,8 @@
203 2012-12-04 Oliver Haag <oliver.haag@gmail.com> 203 2012-12-04 Oliver Haag <oliver.haag@gmail.com>
204 * Workaround for stacked QGLWidget on Mac OS X 204 * Workaround for stacked QGLWidget on Mac OS X
205 * Bugfix: Check for connected scope on setSamplerate/setRecordTime 205 * Bugfix: Check for connected scope on setSamplerate/setRecordTime
  206 +
  207 +2013-03-12 Oliver Haag <oliver.haag@gmail.com>
  208 +* Use std::vector instead of QList
  209 +* Experimental Roll-mode support
  210 +* QThread::msleep is too unprecise, causing problems in Roll-mode
openhantek/src/dataanalyzer.cpp
@@ -38,7 +38,22 @@ @@ -38,7 +38,22 @@
38 38
39 39
40 //////////////////////////////////////////////////////////////////////////////// 40 ////////////////////////////////////////////////////////////////////////////////
41 -// class HorizontalDock 41 +// struct SampleValues
  42 +/// \brief Initializes the members to their default values.
  43 +SampleValues::SampleValues() {
  44 + this->interval = 0.0;
  45 +}
  46 +
  47 +////////////////////////////////////////////////////////////////////////////////
  48 +// struct AnalyzedData
  49 +/// \brief Initializes the members to their default values.
  50 +AnalyzedData::AnalyzedData() {
  51 + this->amplitude = 0.0;
  52 + this->frequency = 0.0;
  53 +}
  54 +
  55 +////////////////////////////////////////////////////////////////////////////////
  56 +// class DataAnalyzer
42 /// \brief Initializes the buffers and other variables. 57 /// \brief Initializes the buffers and other variables.
43 /// \param settings The settings that should be used. 58 /// \param settings The settings that should be used.
44 /// \param parent The parent widget. 59 /// \param parent The parent widget.
@@ -59,24 +74,16 @@ DataAnalyzer::DataAnalyzer(DsoSettings *settings, QObject *parent) : QThread(par @@ -59,24 +74,16 @@ DataAnalyzer::DataAnalyzer(DsoSettings *settings, QObject *parent) : QThread(par
59 74
60 /// \brief Deallocates the buffers. 75 /// \brief Deallocates the buffers.
61 DataAnalyzer::~DataAnalyzer() { 76 DataAnalyzer::~DataAnalyzer() {
62 - for(int channel = 0; channel < this->analyzedData.count(); ++channel) {  
63 - AnalyzedData *channelData = this->analyzedData[channel];  
64 -  
65 - if(channelData->samples.voltage.sample)  
66 - delete[] channelData->samples.voltage.sample;  
67 - if(channelData->samples.spectrum.sample)  
68 - delete[] channelData->samples.spectrum.sample;  
69 - }  
70 } 77 }
71 78
72 /// \brief Returns the analyzed data. 79 /// \brief Returns the analyzed data.
73 /// \param channel Channel, whose data should be returned. 80 /// \param channel Channel, whose data should be returned.
74 /// \return Analyzed data as AnalyzedData struct. 81 /// \return Analyzed data as AnalyzedData struct.
75 -const AnalyzedData *DataAnalyzer::data(int channel) const {  
76 - if(channel < 0 || channel >= this->analyzedData.count()) 82 +AnalyzedData const *DataAnalyzer::data(unsigned int channel) const {
  83 + if(channel >= this->analyzedData.size())
77 return 0; 84 return 0;
78 85
79 - return this->analyzedData[channel]; 86 + return &this->analyzedData[channel];
80 } 87 }
81 88
82 /// \brief Returns the sample count of the analyzed data. 89 /// \brief Returns the sample count of the analyzed data.
@@ -96,96 +103,79 @@ void DataAnalyzer::run() { @@ -96,96 +103,79 @@ void DataAnalyzer::run() {
96 this->analyzedDataMutex->lock(); 103 this->analyzedDataMutex->lock();
97 104
98 unsigned int maxSamples = 0; 105 unsigned int maxSamples = 0;
99 - unsigned int channelCount = (unsigned int) this->settings->scope.voltage.count(); 106 + unsigned int channelCount = (unsigned int) this->settings->scope.voltage.size();
100 107
101 // Adapt the number of channels for analyzed data 108 // Adapt the number of channels for analyzed data
102 - for(unsigned int channel = this->analyzedData.count(); channel < channelCount; ++channel) {  
103 - AnalyzedData *channelData = new AnalyzedData;  
104 - channelData->samples.voltage.count = 0;  
105 - channelData->samples.voltage.interval = 0;  
106 - channelData->samples.voltage.sample = 0;  
107 - channelData->samples.spectrum.count = 0;  
108 - channelData->samples.spectrum.interval = 0;  
109 - channelData->samples.spectrum.sample = 0;  
110 - channelData->amplitude = 0;  
111 - channelData->frequency = 0;  
112 - this->analyzedData.append(channelData);  
113 - }  
114 - for(unsigned int channel = this->analyzedData.count(); channel > channelCount; --channel) {  
115 - AnalyzedData *channelData = this->analyzedData.last();  
116 - if(channelData->samples.voltage.sample)  
117 - delete[] channelData->samples.voltage.sample;  
118 - if(channelData->samples.spectrum.sample)  
119 - delete[] channelData->samples.spectrum.sample;  
120 - this->analyzedData.removeLast();  
121 - } 109 + this->analyzedData.resize(channelCount);
122 110
123 for(unsigned int channel = 0; channel < channelCount; ++channel) { 111 for(unsigned int channel = 0; channel < channelCount; ++channel) {
124 - AnalyzedData *channelData = this->analyzedData[channel]; 112 + AnalyzedData *const channelData = &this->analyzedData[channel];
125 113
126 if( // Check... 114 if( // Check...
127 ( // ...if we got data for this channel... 115 ( // ...if we got data for this channel...
128 channel < this->settings->scope.physicalChannels && 116 channel < this->settings->scope.physicalChannels &&
129 - channel < (unsigned int) this->waitingData.count() &&  
130 - this->waitingData[channel]) || 117 + channel < (unsigned int) this->waitingData->size() &&
  118 + !this->waitingData->at(channel).empty()) ||
131 ( // ...or if it's a math channel that can be calculated 119 ( // ...or if it's a math channel that can be calculated
132 channel >= this->settings->scope.physicalChannels && 120 channel >= this->settings->scope.physicalChannels &&
133 (this->settings->scope.voltage[channel].used || this->settings->scope.spectrum[channel].used) && 121 (this->settings->scope.voltage[channel].used || this->settings->scope.spectrum[channel].used) &&
134 - this->analyzedData.count() >= 2 &&  
135 - this->analyzedData[0]->samples.voltage.sample &&  
136 - this->analyzedData[1]->samples.voltage.sample 122 + this->analyzedData.size() >= 2 &&
  123 + !this->analyzedData[0].samples.voltage.sample.empty() &&
  124 + !this->analyzedData[1].samples.voltage.sample.empty()
137 ) 125 )
138 ) { 126 ) {
139 // Set sampling interval 127 // Set sampling interval
140 - channelData->samples.voltage.interval = 1.0 / this->waitingDataSamplerate; 128 + const double interval = 1.0 / this->waitingDataSamplerate;
  129 + if(interval != channelData->samples.voltage.interval) {
  130 + channelData->samples.voltage.interval = interval;
  131 + if(this->waitingDataAppend) // Clear roll buffer if the samplerate changed
  132 + channelData->samples.voltage.sample.clear();
  133 + }
  134 +
141 135
142 unsigned int size; 136 unsigned int size;
143 if(channel < this->settings->scope.physicalChannels) { 137 if(channel < this->settings->scope.physicalChannels) {
144 - size = this->waitingDataSize[channel]; 138 + size = this->waitingData->at(channel).size();
  139 + if(this->waitingDataAppend)
  140 + size += channelData->samples.voltage.sample.size();
145 if(size > maxSamples) 141 if(size > maxSamples)
146 maxSamples = size; 142 maxSamples = size;
147 } 143 }
148 else 144 else
149 size = maxSamples; 145 size = maxSamples;
150 - // Reallocate memory for samples if the sample count has changed  
151 - if(channelData->samples.voltage.count != size) {  
152 - channelData->samples.voltage.count = size;  
153 - if(channelData->samples.voltage.sample)  
154 - delete[] channelData->samples.voltage.sample;  
155 - channelData->samples.voltage.sample = new double[size];  
156 - }  
157 146
158 // Physical channels 147 // Physical channels
159 if(channel < this->settings->scope.physicalChannels) { 148 if(channel < this->settings->scope.physicalChannels) {
160 // Copy the buffer of the oscilloscope into the sample buffer 149 // Copy the buffer of the oscilloscope into the sample buffer
161 - if(channel < (unsigned int) this->waitingData.count())  
162 - for(unsigned int position = 0; position < this->waitingDataSize[channel]; ++position)  
163 - channelData->samples.voltage.sample[position] = this->waitingData[channel][position]; 150 + if(this->waitingDataAppend)
  151 + channelData->samples.voltage.sample.insert(channelData->samples.voltage.sample.end(), this->waitingData->at(channel).begin(), this->waitingData->at(channel).end());
  152 + else
  153 + channelData->samples.voltage.sample = this->waitingData->at(channel);
164 } 154 }
165 // Math channel 155 // Math channel
166 else { 156 else {
  157 + // Resize the sample vector
  158 + channelData->samples.voltage.sample.resize(size);
167 // Set sampling interval 159 // Set sampling interval
168 - this->analyzedData[this->settings->scope.physicalChannels]->samples.voltage.interval = this->analyzedData[0]->samples.voltage.interval; 160 + this->analyzedData[this->settings->scope.physicalChannels].samples.voltage.interval = this->analyzedData[0].samples.voltage.interval;
169 161
170 - // Reallocate memory for samples if the sample count has changed  
171 - if(this->analyzedData[this->settings->scope.physicalChannels]->samples.voltage.count != this->analyzedData[0]->samples.voltage.count) {  
172 - this->analyzedData[this->settings->scope.physicalChannels]->samples.voltage.count = this->analyzedData[0]->samples.voltage.count;  
173 - if(this->analyzedData[this->settings->scope.physicalChannels]->samples.voltage.sample)  
174 - delete[] this->analyzedData[this->settings->scope.physicalChannels]->samples.voltage.sample;  
175 - this->analyzedData[this->settings->scope.physicalChannels]->samples.voltage.sample = new double[this->analyzedData[this->settings->scope.physicalChannels]->samples.voltage.count];  
176 - } 162 + // Resize the sample vector
  163 + this->analyzedData[this->settings->scope.physicalChannels].samples.voltage.sample.resize(qMin(this->analyzedData[0].samples.voltage.sample.size(), this->analyzedData[1].samples.voltage.sample.size()));
177 164
178 // Calculate values and write them into the sample buffer 165 // Calculate values and write them into the sample buffer
179 - for(unsigned int realPosition = 0; realPosition < this->analyzedData[this->settings->scope.physicalChannels]->samples.voltage.count; ++realPosition) { 166 + std::vector<double>::const_iterator ch1Iterator = this->analyzedData[0].samples.voltage.sample.begin();
  167 + std::vector<double>::const_iterator ch2Iterator = this->analyzedData[1].samples.voltage.sample.begin();
  168 + std::vector<double> &resultData = this->analyzedData[this->settings->scope.physicalChannels].samples.voltage.sample;
  169 + for(std::vector<double>::iterator resultIterator = resultData.begin(); resultIterator != resultData.end(); ++resultIterator) {
180 switch(this->settings->scope.voltage[this->settings->scope.physicalChannels].misc) { 170 switch(this->settings->scope.voltage[this->settings->scope.physicalChannels].misc) {
181 case Dso::MATHMODE_1ADD2: 171 case Dso::MATHMODE_1ADD2:
182 - this->analyzedData[this->settings->scope.physicalChannels]->samples.voltage.sample[realPosition] = this->analyzedData[0]->samples.voltage.sample[realPosition] + this->analyzedData[1]->samples.voltage.sample[realPosition]; 172 + *(resultIterator++) = *(ch1Iterator++) + *(ch2Iterator++);
183 break; 173 break;
184 case Dso::MATHMODE_1SUB2: 174 case Dso::MATHMODE_1SUB2:
185 - this->analyzedData[this->settings->scope.physicalChannels]->samples.voltage.sample[realPosition] = this->analyzedData[0]->samples.voltage.sample[realPosition] - this->analyzedData[1]->samples.voltage.sample[realPosition]; 175 + *(resultIterator++) = *(ch1Iterator++) - *(ch2Iterator++);
186 break; 176 break;
187 case Dso::MATHMODE_2SUB1: 177 case Dso::MATHMODE_2SUB1:
188 - this->analyzedData[this->settings->scope.physicalChannels]->samples.voltage.sample[realPosition] = this->analyzedData[1]->samples.voltage.sample[realPosition] - this->analyzedData[0]->samples.voltage.sample[realPosition]; 178 + *(resultIterator++) = *(ch2Iterator++) - *(ch1Iterator++);
189 break; 179 break;
190 } 180 }
191 } 181 }
@@ -193,12 +183,8 @@ void DataAnalyzer::run() { @@ -193,12 +183,8 @@ void DataAnalyzer::run() {
193 } 183 }
194 else { 184 else {
195 // Clear unused channels 185 // Clear unused channels
196 - channelData->samples.voltage.count = 0;  
197 - this->analyzedData[this->settings->scope.physicalChannels]->samples.voltage.interval = 0;  
198 - if(channelData->samples.voltage.sample) {  
199 - delete[] channelData->samples.voltage.sample;  
200 - channelData->samples.voltage.sample = 0;  
201 - } 186 + channelData->samples.voltage.sample.clear();
  187 + this->analyzedData[this->settings->scope.physicalChannels].samples.voltage.interval = 0;
202 } 188 }
203 } 189 }
204 190
@@ -209,14 +195,15 @@ void DataAnalyzer::run() { @@ -209,14 +195,15 @@ void DataAnalyzer::run() {
209 195
210 196
211 // Calculate frequencies, peak-to-peak voltages and spectrums 197 // Calculate frequencies, peak-to-peak voltages and spectrums
212 - for(int channel = 0; channel < this->analyzedData.count(); ++channel) {  
213 - AnalyzedData *channelData = this->analyzedData[channel]; 198 + for(unsigned int channel = 0; channel < this->analyzedData.size(); ++channel) {
  199 + AnalyzedData *const channelData = &this->analyzedData[channel];
214 200
215 - if(channelData->samples.voltage.sample) { 201 + if(!channelData->samples.voltage.sample.empty()) {
216 // Calculate new window 202 // Calculate new window
217 - if(this->lastWindow != this->settings->scope.spectrumWindow || this->lastRecordLength != channelData->samples.voltage.count) {  
218 - if(this->lastRecordLength != channelData->samples.voltage.count) {  
219 - this->lastRecordLength = channelData->samples.voltage.count; 203 + unsigned int sampleCount = channelData->samples.voltage.sample.size();
  204 + if(this->lastWindow != this->settings->scope.spectrumWindow || this->lastRecordLength != sampleCount) {
  205 + if(this->lastRecordLength != sampleCount) {
  206 + this->lastRecordLength = sampleCount;
220 207
221 if(this->window) 208 if(this->window)
222 fftw_free(this->window); 209 fftw_free(this->window);
@@ -303,28 +290,23 @@ void DataAnalyzer::run() { @@ -303,28 +290,23 @@ void DataAnalyzer::run() {
303 } 290 }
304 291
305 // Set sampling interval 292 // Set sampling interval
306 - channelData->samples.spectrum.interval = 1.0 / channelData->samples.voltage.interval / channelData->samples.voltage.count; 293 + channelData->samples.spectrum.interval = 1.0 / channelData->samples.voltage.interval / sampleCount;
307 294
308 // Number of real/complex samples 295 // Number of real/complex samples
309 - unsigned int dftLength = channelData->samples.voltage.count / 2; 296 + unsigned int dftLength = sampleCount / 2;
310 297
311 // Reallocate memory for samples if the sample count has changed 298 // Reallocate memory for samples if the sample count has changed
312 - if(channelData->samples.spectrum.count != dftLength) {  
313 - channelData->samples.spectrum.count = dftLength;  
314 - if(channelData->samples.spectrum.sample)  
315 - delete[] channelData->samples.spectrum.sample;  
316 - channelData->samples.spectrum.sample = new double[channelData->samples.voltage.count];  
317 - } 299 + channelData->samples.spectrum.sample.resize(sampleCount);
318 300
319 // Create sample buffer and apply window 301 // Create sample buffer and apply window
320 - double *windowedValues = new double[channelData->samples.voltage.count];  
321 - for(unsigned int position = 0; position < channelData->samples.voltage.count; ++position) 302 + double *windowedValues = new double[sampleCount];
  303 + for(unsigned int position = 0; position < sampleCount; ++position)
322 windowedValues[position] = this->window[position] * channelData->samples.voltage.sample[position]; 304 windowedValues[position] = this->window[position] * channelData->samples.voltage.sample[position];
323 305
324 // Do discrete real to half-complex transformation 306 // Do discrete real to half-complex transformation
325 /// \todo Check if record length is multiple of 2 307 /// \todo Check if record length is multiple of 2
326 /// \todo Reuse plan and use FFTW_MEASURE to get fastest algorithm 308 /// \todo Reuse plan and use FFTW_MEASURE to get fastest algorithm
327 - fftw_plan fftPlan = fftw_plan_r2r_1d(channelData->samples.voltage.count, windowedValues, channelData->samples.spectrum.sample, FFTW_R2HC, FFTW_ESTIMATE); 309 + fftw_plan fftPlan = fftw_plan_r2r_1d(sampleCount, windowedValues, &channelData->samples.spectrum.sample.front(), FFTW_R2HC, FFTW_ESTIMATE);
328 fftw_execute(fftPlan); 310 fftw_execute(fftPlan);
329 fftw_destroy_plan(fftPlan); 311 fftw_destroy_plan(fftPlan);
330 312
@@ -336,15 +318,15 @@ void DataAnalyzer::run() { @@ -336,15 +318,15 @@ void DataAnalyzer::run() {
336 double correctionFactor = 1.0 / dftLength / dftLength; 318 double correctionFactor = 1.0 / dftLength / dftLength;
337 conjugateComplex[0] = (channelData->samples.spectrum.sample[0] * channelData->samples.spectrum.sample[0]) * correctionFactor; 319 conjugateComplex[0] = (channelData->samples.spectrum.sample[0] * channelData->samples.spectrum.sample[0]) * correctionFactor;
338 for(position = 1; position < dftLength; ++position) 320 for(position = 1; position < dftLength; ++position)
339 - conjugateComplex[position] = (channelData->samples.spectrum.sample[position] * channelData->samples.spectrum.sample[position] + channelData->samples.spectrum.sample[channelData->samples.voltage.count - position] * channelData->samples.spectrum.sample[channelData->samples.voltage.count - position]) * correctionFactor; 321 + conjugateComplex[position] = (channelData->samples.spectrum.sample[position] * channelData->samples.spectrum.sample[position] + channelData->samples.spectrum.sample[sampleCount - position] * channelData->samples.spectrum.sample[sampleCount - position]) * correctionFactor;
340 // Complex values, all zero for autocorrelation 322 // Complex values, all zero for autocorrelation
341 conjugateComplex[dftLength] = (channelData->samples.spectrum.sample[dftLength] * channelData->samples.spectrum.sample[dftLength]) * correctionFactor; 323 conjugateComplex[dftLength] = (channelData->samples.spectrum.sample[dftLength] * channelData->samples.spectrum.sample[dftLength]) * correctionFactor;
342 - for(++position; position < channelData->samples.voltage.count; ++position) 324 + for(++position; position < sampleCount; ++position)
343 conjugateComplex[position] = 0; 325 conjugateComplex[position] = 0;
344 326
345 // Do half-complex to real inverse transformation 327 // Do half-complex to real inverse transformation
346 - double *correlation = new double[channelData->samples.voltage.count];  
347 - fftPlan = fftw_plan_r2r_1d(channelData->samples.voltage.count, conjugateComplex, correlation, FFTW_HC2R, FFTW_ESTIMATE); 328 + double *correlation = new double[sampleCount];
  329 + fftPlan = fftw_plan_r2r_1d(sampleCount, conjugateComplex, correlation, FFTW_HC2R, FFTW_ESTIMATE);
348 fftw_execute(fftPlan); 330 fftw_execute(fftPlan);
349 fftw_destroy_plan(fftPlan); 331 fftw_destroy_plan(fftPlan);
350 delete[] conjugateComplex; 332 delete[] conjugateComplex;
@@ -353,7 +335,7 @@ void DataAnalyzer::run() { @@ -353,7 +335,7 @@ void DataAnalyzer::run() {
353 double minimalVoltage, maximalVoltage; 335 double minimalVoltage, maximalVoltage;
354 minimalVoltage = maximalVoltage = channelData->samples.voltage.sample[0]; 336 minimalVoltage = maximalVoltage = channelData->samples.voltage.sample[0];
355 337
356 - for(unsigned int position = 1; position < channelData->samples.voltage.count; ++position) { 338 + for(unsigned int position = 1; position < sampleCount; ++position) {
357 if(channelData->samples.voltage.sample[position] < minimalVoltage) 339 if(channelData->samples.voltage.sample[position] < minimalVoltage)
358 minimalVoltage = channelData->samples.voltage.sample[position]; 340 minimalVoltage = channelData->samples.voltage.sample[position];
359 else if(channelData->samples.voltage.sample[position] > maximalVoltage) 341 else if(channelData->samples.voltage.sample[position] > maximalVoltage)
@@ -367,7 +349,7 @@ void DataAnalyzer::run() { @@ -367,7 +349,7 @@ void DataAnalyzer::run() {
367 double peakCorrelation = 0; 349 double peakCorrelation = 0;
368 unsigned int peakPosition = 0; 350 unsigned int peakPosition = 0;
369 351
370 - for(unsigned int position = 1; position < channelData->samples.voltage.count / 2; ++position) { 352 + for(unsigned int position = 1; position < sampleCount / 2; ++position) {
371 if(correlation[position] > peakCorrelation && correlation[position] > minimumCorrelation * 2) { 353 if(correlation[position] > peakCorrelation && correlation[position] > minimumCorrelation * 2) {
372 peakCorrelation = correlation[position]; 354 peakCorrelation = correlation[position];
373 peakPosition = position; 355 peakPosition = position;
@@ -388,21 +370,21 @@ void DataAnalyzer::run() { @@ -388,21 +370,21 @@ void DataAnalyzer::run() {
388 // Convert values into dB (Relative to the reference level) 370 // Convert values into dB (Relative to the reference level)
389 double offset = 60 - this->settings->scope.spectrumReference - 20 * log10(dftLength); 371 double offset = 60 - this->settings->scope.spectrumReference - 20 * log10(dftLength);
390 double offsetLimit = this->settings->scope.spectrumLimit - this->settings->scope.spectrumReference; 372 double offsetLimit = this->settings->scope.spectrumLimit - this->settings->scope.spectrumReference;
391 - for(unsigned int position = 0; position < channelData->samples.spectrum.count; ++position) {  
392 - channelData->samples.spectrum.sample[position] = 20 * log10(fabs(channelData->samples.spectrum.sample[position])) + offset; 373 + for(std::vector<double>::iterator spectrumIterator = channelData->samples.spectrum.sample.begin(); spectrumIterator != channelData->samples.spectrum.sample.end(); ++spectrumIterator) {
  374 + double value = 20 * log10(fabs(channelData->samples.spectrum.sample[position])) + offset;
393 375
394 // Check if this value has to be limited 376 // Check if this value has to be limited
395 - if(offsetLimit > channelData->samples.spectrum.sample[position])  
396 - channelData->samples.spectrum.sample[position] = offsetLimit; 377 + if(offsetLimit > value)
  378 + value = offsetLimit;
  379 +
  380 + *spectrumIterator = value;
397 } 381 }
398 } 382 }
399 } 383 }
400 - else if(channelData->samples.spectrum.sample) { 384 + else if(!channelData->samples.spectrum.sample.empty()) {
401 // Clear unused channels 385 // Clear unused channels
402 - channelData->samples.spectrum.count = 0;  
403 channelData->samples.spectrum.interval = 0; 386 channelData->samples.spectrum.interval = 0;
404 - delete[] channelData->samples.spectrum.sample;  
405 - channelData->samples.spectrum.sample = 0; 387 + channelData->samples.spectrum.sample.clear();
406 } 388 }
407 } 389 }
408 390
@@ -416,19 +398,27 @@ void DataAnalyzer::run() { @@ -416,19 +398,27 @@ void DataAnalyzer::run() {
416 /// \param data The data arrays with the input data. 398 /// \param data The data arrays with the input data.
417 /// \param size The sizes of the data arrays. 399 /// \param size The sizes of the data arrays.
418 /// \param samplerate The samplerate for all input data. 400 /// \param samplerate The samplerate for all input data.
  401 +/// \param append The data will be appended to the previously analyzed data (Roll mode).
419 /// \param mutex The mutex for all input data. 402 /// \param mutex The mutex for all input data.
420 -void DataAnalyzer::analyze(const QList<double *> *data, const QList<unsigned int> *size, double samplerate, QMutex *mutex) { 403 +void DataAnalyzer::analyze(const std::vector<std::vector<double> > *data, double samplerate, bool append, QMutex *mutex) {
421 // Previous analysis still running, drop the new data 404 // Previous analysis still running, drop the new data
422 - if(this->isRunning()) 405 + if(this->isRunning()) {
  406 +#ifdef DEBUG
  407 + Helper::timestampDebug("Analyzer overload, dropping packets!");
  408 +#endif
423 return; 409 return;
  410 + }
424 411
425 // The thread will analyze it, just save the pointers 412 // The thread will analyze it, just save the pointers
426 mutex->lock(); 413 mutex->lock();
427 - this->waitingData.clear();  
428 - this->waitingData.append(*data);  
429 - this->waitingDataSize.clear();  
430 - this->waitingDataSize.append(*size); 414 + this->waitingData = data;
  415 + this->waitingDataAppend = append;
431 this->waitingDataMutex = mutex; 416 this->waitingDataMutex = mutex;
432 this->waitingDataSamplerate = samplerate; 417 this->waitingDataSamplerate = samplerate;
433 this->start(); 418 this->start();
  419 +#ifdef DEBUG
  420 + static unsigned long id = 0;
  421 + ++id;
  422 + Helper::timestampDebug(QString("Analyzed packet %1").arg(id));
  423 +#endif
434 } 424 }
openhantek/src/dataanalyzer.h
@@ -27,6 +27,8 @@ @@ -27,6 +27,8 @@
27 #define DATAANALYZER_H 27 #define DATAANALYZER_H
28 28
29 29
  30 +#include <vector>
  31 +
30 #include <QThread> 32 #include <QThread>
31 33
32 34
@@ -43,9 +45,10 @@ class QMutex; @@ -43,9 +45,10 @@ class QMutex;
43 /// \struct SampleValues dataanalyzer.h 45 /// \struct SampleValues dataanalyzer.h
44 /// \brief Struct for a array of sample values. 46 /// \brief Struct for a array of sample values.
45 struct SampleValues { 47 struct SampleValues {
46 - double *sample; ///< Pointer to the array holding the sampling data  
47 - unsigned int count; ///< Number of sample values 48 + std::vector<double> sample; ///< Vector holding the sampling data
48 double interval; ///< The interval between two sample values 49 double interval; ///< The interval between two sample values
  50 +
  51 + SampleValues();
49 }; 52 };
50 53
51 //////////////////////////////////////////////////////////////////////////////// 54 ////////////////////////////////////////////////////////////////////////////////
@@ -61,8 +64,10 @@ struct SampleData { @@ -61,8 +64,10 @@ struct SampleData {
61 /// \brief Struct for the analyzed data. 64 /// \brief Struct for the analyzed data.
62 struct AnalyzedData { 65 struct AnalyzedData {
63 SampleData samples; ///< Voltage and spectrum values 66 SampleData samples; ///< Voltage and spectrum values
64 - double frequency; ///< The frequency of the signal  
65 double amplitude; ///< The amplitude of the signal 67 double amplitude; ///< The amplitude of the signal
  68 + double frequency; ///< The frequency of the signal
  69 +
  70 + AnalyzedData();
66 }; 71 };
67 72
68 //////////////////////////////////////////////////////////////////////////////// 73 ////////////////////////////////////////////////////////////////////////////////
@@ -77,7 +82,7 @@ class DataAnalyzer : public QThread { @@ -77,7 +82,7 @@ class DataAnalyzer : public QThread {
77 DataAnalyzer(DsoSettings *settings, QObject *parent = 0); 82 DataAnalyzer(DsoSettings *settings, QObject *parent = 0);
78 ~DataAnalyzer(); 83 ~DataAnalyzer();
79 84
80 - const AnalyzedData *data(int channel) const; 85 + const AnalyzedData *data(unsigned int channel) const;
81 unsigned int sampleCount(); 86 unsigned int sampleCount();
82 QMutex *mutex() const; 87 QMutex *mutex() const;
83 88
@@ -86,7 +91,7 @@ class DataAnalyzer : public QThread { @@ -86,7 +91,7 @@ class DataAnalyzer : public QThread {
86 91
87 DsoSettings *settings; ///< The settings provided by the parent class 92 DsoSettings *settings; ///< The settings provided by the parent class
88 93
89 - QList<AnalyzedData *> analyzedData; ///< The analyzed data for each channel 94 + std::vector<AnalyzedData> analyzedData; ///< The analyzed data for each channel
90 QMutex *analyzedDataMutex; ///< A mutex for the analyzed data of all channels 95 QMutex *analyzedDataMutex; ///< A mutex for the analyzed data of all channels
91 96
92 unsigned int lastRecordLength; ///< The record length of the previously analyzed data 97 unsigned int lastRecordLength; ///< The record length of the previously analyzed data
@@ -94,13 +99,13 @@ class DataAnalyzer : public QThread { @@ -94,13 +99,13 @@ class DataAnalyzer : public QThread {
94 Dso::WindowFunction lastWindow; ///< The previously used dft window function 99 Dso::WindowFunction lastWindow; ///< The previously used dft window function
95 double *window; ///< The array for the dft window factors 100 double *window; ///< The array for the dft window factors
96 101
97 - QList<double *> waitingData; ///< Pointer to input data from device  
98 - QList<unsigned int> waitingDataSize; ///< Number of input data samples 102 + const std::vector<std::vector<double> > *waitingData; ///< Pointer to input data from device
99 double waitingDataSamplerate; ///< The samplerate of the input data 103 double waitingDataSamplerate; ///< The samplerate of the input data
  104 + bool waitingDataAppend; ///< true, if waiting data should be appended
100 QMutex *waitingDataMutex; ///< A mutex for the input data 105 QMutex *waitingDataMutex; ///< A mutex for the input data
101 106
102 public slots: 107 public slots:
103 - void analyze(const QList<double *> *data, const QList<unsigned int> *size, double samplerate, QMutex *mutex); 108 + void analyze(const std::vector<std::vector<double> > *data, double samplerate, bool append, QMutex *mutex);
104 109
105 signals: 110 signals:
106 void analyzed(unsigned long samples); ///< The data with that much samples has been analyzed 111 void analyzed(unsigned long samples); ///< The data with that much samples has been analyzed
openhantek/src/dsocontrol.h
@@ -27,6 +27,8 @@ @@ -27,6 +27,8 @@
27 #define DSOCONTROL_H 27 #define DSOCONTROL_H
28 28
29 29
  30 +#include <vector>
  31 +
30 #include <QStringList> 32 #include <QStringList>
31 #include <QThread> 33 #include <QThread>
32 34
@@ -65,7 +67,7 @@ class DsoControl : public QThread { @@ -65,7 +67,7 @@ class DsoControl : public QThread {
65 void samplingStarted(); ///< The oscilloscope started sampling/waiting for trigger 67 void samplingStarted(); ///< The oscilloscope started sampling/waiting for trigger
66 void samplingStopped(); ///< The oscilloscope stopped sampling/waiting for trigger 68 void samplingStopped(); ///< The oscilloscope stopped sampling/waiting for trigger
67 void statusMessage(const QString &message, int timeout); ///< Status message about the oscilloscope 69 void statusMessage(const QString &message, int timeout); ///< Status message about the oscilloscope
68 - void samplesAvailable(const QList<double *> *data, const QList<unsigned int> *size, double samplerate, QMutex *mutex); ///< New sample data is available 70 + void samplesAvailable(const std::vector<std::vector<double> > *data, double samplerate, bool append, QMutex *mutex); ///< New sample data is available
69 71
70 void recordLengthChanged(unsigned long duration); ///< The record length has changed 72 void recordLengthChanged(unsigned long duration); ///< The record length has changed
71 void recordTimeChanged(double duration); ///< The record time duration has changed 73 void recordTimeChanged(double duration); ///< The record time duration has changed
openhantek/src/exporter.cpp
@@ -231,7 +231,7 @@ bool Exporter::doExport() { @@ -231,7 +231,7 @@ bool Exporter::doExport() {
231 centerOffset = DIVS_TIME / horizontalFactor / 2; 231 centerOffset = DIVS_TIME / horizontalFactor / 2;
232 } 232 }
233 unsigned int firstPosition = qMax((int) (centerPosition - centerOffset), 0); 233 unsigned int firstPosition = qMax((int) (centerPosition - centerOffset), 0);
234 - unsigned int lastPosition = qMin((int) (centerPosition + centerOffset), (int) this->dataAnalyzer->data(channel)->samples.voltage.count - 1); 234 + unsigned int lastPosition = qMin((int) (centerPosition + centerOffset), (int) this->dataAnalyzer->data(channel)->samples.voltage.sample.size() - 1);
235 235
236 // Draw graph 236 // Draw graph
237 QPointF *graph = new QPointF[lastPosition - firstPosition + 1]; 237 QPointF *graph = new QPointF[lastPosition - firstPosition + 1];
@@ -262,7 +262,7 @@ bool Exporter::doExport() { @@ -262,7 +262,7 @@ bool Exporter::doExport() {
262 centerOffset = DIVS_TIME / horizontalFactor / 2; 262 centerOffset = DIVS_TIME / horizontalFactor / 2;
263 } 263 }
264 unsigned int firstPosition = qMax((int) (centerPosition - centerOffset), 0); 264 unsigned int firstPosition = qMax((int) (centerPosition - centerOffset), 0);
265 - unsigned int lastPosition = qMin((int) (centerPosition + centerOffset), (int) this->dataAnalyzer->data(channel)->samples.spectrum.count - 1); 265 + unsigned int lastPosition = qMin((int) (centerPosition + centerOffset), (int) this->dataAnalyzer->data(channel)->samples.spectrum.sample.size() - 1);
266 266
267 // Draw graph 267 // Draw graph
268 QPointF *graph = new QPointF[lastPosition - firstPosition + 1]; 268 QPointF *graph = new QPointF[lastPosition - firstPosition + 1];
@@ -382,7 +382,7 @@ bool Exporter::doExport() { @@ -382,7 +382,7 @@ bool Exporter::doExport() {
382 csvStream << "\"" << this->settings->scope.voltage[channel].name << "\"," << this->dataAnalyzer->data(channel)->samples.voltage.interval; 382 csvStream << "\"" << this->settings->scope.voltage[channel].name << "\"," << this->dataAnalyzer->data(channel)->samples.voltage.interval;
383 383
384 // And now all sample values in volts 384 // And now all sample values in volts
385 - for(unsigned int position = 0; position < this->dataAnalyzer->data(channel)->samples.voltage.count; ++position) 385 + for(unsigned int position = 0; position < this->dataAnalyzer->data(channel)->samples.voltage.sample.size(); ++position)
386 csvStream << "," << this->dataAnalyzer->data(channel)->samples.voltage.sample[position]; 386 csvStream << "," << this->dataAnalyzer->data(channel)->samples.voltage.sample[position];
387 387
388 // Finally a newline 388 // Finally a newline
@@ -394,7 +394,7 @@ bool Exporter::doExport() { @@ -394,7 +394,7 @@ bool Exporter::doExport() {
394 csvStream << "\"" << this->settings->scope.spectrum[channel].name << "\"," << this->dataAnalyzer->data(channel)->samples.spectrum.interval; 394 csvStream << "\"" << this->settings->scope.spectrum[channel].name << "\"," << this->dataAnalyzer->data(channel)->samples.spectrum.interval;
395 395
396 // And now all magnitudes in dB 396 // And now all magnitudes in dB
397 - for(unsigned int position = 0; position < this->dataAnalyzer->data(channel)->samples.spectrum.count; ++position) 397 + for(unsigned int position = 0; position < this->dataAnalyzer->data(channel)->samples.spectrum.sample.size(); ++position)
398 csvStream << "," << this->dataAnalyzer->data(channel)->samples.spectrum.sample[position]; 398 csvStream << "," << this->dataAnalyzer->data(channel)->samples.spectrum.sample[position];
399 399
400 // Finally a newline 400 // Finally a newline
openhantek/src/glgenerator.cpp
@@ -33,44 +33,6 @@ @@ -33,44 +33,6 @@
33 33
34 34
35 //////////////////////////////////////////////////////////////////////////////// 35 ////////////////////////////////////////////////////////////////////////////////
36 -// class GlArray  
37 -/// \brief Initializes the array.  
38 -GlArray::GlArray() {  
39 - this->data = 0;  
40 - this->size = 0;  
41 -}  
42 -  
43 -/// \brief Deletes the array.  
44 -GlArray::~GlArray() {  
45 - if(this->data)  
46 - delete this->data;  
47 -}  
48 -  
49 -/// \brief Get the size of the array.  
50 -/// \return Number of array elements.  
51 -unsigned int GlArray::getSize() {  
52 - return this->size;  
53 -}  
54 -  
55 -/// \brief Set the size of the array.  
56 -/// Previous array contents are lost.  
57 -/// \param size New number of array elements.  
58 -void GlArray::setSize(unsigned int size) {  
59 - if(this->size == size)  
60 - return;  
61 -  
62 - if(this->data)  
63 - delete[] this->data;  
64 - if(size)  
65 - this->data = new GLfloat[size];  
66 - else  
67 - this->data = 0;  
68 -  
69 - this->size = size;  
70 -}  
71 -  
72 -  
73 -////////////////////////////////////////////////////////////////////////////////  
74 // class GlGenerator 36 // class GlGenerator
75 /// \brief Initializes the scope widget. 37 /// \brief Initializes the scope widget.
76 /// \param settings The target settings object. 38 /// \param settings The target settings object.
@@ -104,12 +66,8 @@ void GlGenerator::generateGraphs() { @@ -104,12 +66,8 @@ void GlGenerator::generateGraphs() {
104 return; 66 return;
105 67
106 // Adapt the number of graphs 68 // Adapt the number of graphs
107 - for(int mode = Dso::CHANNELMODE_VOLTAGE; mode < Dso::CHANNELMODE_COUNT; ++mode) {  
108 - for(int channel = this->vaChannel[mode].count(); channel < this->settings->scope.voltage.count(); ++channel)  
109 - this->vaChannel[mode].append(QList<GlArray *>());  
110 - for(int channel = this->settings->scope.voltage.count(); channel < this->vaChannel[mode].count(); ++channel)  
111 - this->vaChannel[mode].removeLast();  
112 - } 69 + for(int mode = Dso::CHANNELMODE_VOLTAGE; mode < Dso::CHANNELMODE_COUNT; ++mode)
  70 + this->vaChannel[mode].resize(this->settings->scope.voltage.count());
113 71
114 // Set digital phosphor depth to one if we don't use it 72 // Set digital phosphor depth to one if we don't use it
115 if(this->settings->view.digitalPhosphor) 73 if(this->settings->view.digitalPhosphor)
@@ -119,18 +77,12 @@ void GlGenerator::generateGraphs() { @@ -119,18 +77,12 @@ void GlGenerator::generateGraphs() {
119 77
120 // Handle all digital phosphor related list manipulations 78 // Handle all digital phosphor related list manipulations
121 for(int mode = Dso::CHANNELMODE_VOLTAGE; mode < Dso::CHANNELMODE_COUNT; ++mode) { 79 for(int mode = Dso::CHANNELMODE_VOLTAGE; mode < Dso::CHANNELMODE_COUNT; ++mode) {
122 - for(int channel = 0; channel < this->vaChannel[mode].count(); ++channel) {  
123 - // Resize lists for vector array if the digital phosphor depth has changed  
124 - if(this->vaChannel[mode][channel].count() != this->digitalPhosphorDepth)  
125 - for(int index = this->vaChannel[mode][channel].count(); index < this->digitalPhosphorDepth; ++index)  
126 - this->vaChannel[mode][channel].append(new GlArray());  
127 - for(int index = this->digitalPhosphorDepth; index < this->vaChannel[mode][channel].count(); ++index) {  
128 - delete this->vaChannel[mode][channel].last();  
129 - this->vaChannel[mode][channel].removeLast();  
130 - }  
131 - 80 + for(unsigned int channel = 0; channel < this->vaChannel[mode].size(); ++channel) {
132 // Move the last list element to the front 81 // Move the last list element to the front
133 - this->vaChannel[mode][channel].move(this->digitalPhosphorDepth -1, 0); 82 + this->vaChannel[mode][channel].push_front(std::vector<GLfloat>());
  83 +
  84 + // Resize lists for vector array to fit the digital phosphor depth
  85 + this->vaChannel[mode][channel].resize(this->digitalPhosphorDepth);
134 } 86 }
135 } 87 }
136 88
@@ -140,21 +92,22 @@ void GlGenerator::generateGraphs() { @@ -140,21 +92,22 @@ void GlGenerator::generateGraphs() {
140 case Dso::GRAPHFORMAT_TY: 92 case Dso::GRAPHFORMAT_TY:
141 // Add graphs for channels 93 // Add graphs for channels
142 for(int mode = Dso::CHANNELMODE_VOLTAGE; mode < Dso::CHANNELMODE_COUNT; ++mode) { 94 for(int mode = Dso::CHANNELMODE_VOLTAGE; mode < Dso::CHANNELMODE_COUNT; ++mode) {
143 - for(int channel = 0; channel < this->settings->scope.voltage.count(); ++channel) { 95 + for(int channel = 0; channel < this->settings->scope.voltage.size(); ++channel) {
144 // Check if this channel is used and available at the data analyzer 96 // Check if this channel is used and available at the data analyzer
145 - if(((mode == Dso::CHANNELMODE_VOLTAGE) ? this->settings->scope.voltage[channel].used : this->settings->scope.spectrum[channel].used) && this->dataAnalyzer->data(channel) && this->dataAnalyzer->data(channel)->samples.voltage.sample) { 97 + if(((mode == Dso::CHANNELMODE_VOLTAGE) ? this->settings->scope.voltage[channel].used : this->settings->scope.spectrum[channel].used) && this->dataAnalyzer->data(channel) && !this->dataAnalyzer->data(channel)->samples.voltage.sample.empty()) {
146 // Check if the sample count has changed 98 // Check if the sample count has changed
147 - unsigned int neededSize = ((mode == Dso::CHANNELMODE_VOLTAGE) ? this->dataAnalyzer->data(channel)->samples.voltage.count : this->dataAnalyzer->data(channel)->samples.spectrum.count) * 2;  
148 - for(int index = 0; index < this->digitalPhosphorDepth; ++index) {  
149 - if(this->vaChannel[mode][channel][index]->getSize() != neededSize)  
150 - this->vaChannel[mode][channel][index]->setSize(0); 99 + unsigned int sampleCount = (mode == Dso::CHANNELMODE_VOLTAGE) ? this->dataAnalyzer->data(channel)->samples.voltage.sample.size() : this->dataAnalyzer->data(channel)->samples.spectrum.sample.size();
  100 + unsigned int neededSize = sampleCount * 2;
  101 + for(unsigned int index = 0; index < this->digitalPhosphorDepth; ++index) {
  102 + if(this->vaChannel[mode][channel][index].size() != neededSize)
  103 + this->vaChannel[mode][channel][index].clear(); // Something was changed, drop old traces
151 } 104 }
152 105
153 - // Check if the array is allocated  
154 - if(!this->vaChannel[mode][channel].first()->data)  
155 - this->vaChannel[mode][channel].first()->setSize(neededSize); 106 + // Set size directly to avoid reallocations
  107 + this->vaChannel[mode][channel].front().resize(neededSize);
156 108
157 - GLfloat *vaNewChannel = this->vaChannel[mode][channel].first()->data; 109 + // Iterator to data for direct access
  110 + std::vector<GLfloat>::iterator glIterator = this->vaChannel[mode][channel].front().begin();
158 111
159 // What's the horizontal distance between sampling points? 112 // What's the horizontal distance between sampling points?
160 double horizontalFactor; 113 double horizontalFactor;
@@ -164,64 +117,78 @@ void GlGenerator::generateGraphs() { @@ -164,64 +117,78 @@ void GlGenerator::generateGraphs() {
164 horizontalFactor = this->dataAnalyzer->data(channel)->samples.spectrum.interval / this->settings->scope.horizontal.frequencybase; 117 horizontalFactor = this->dataAnalyzer->data(channel)->samples.spectrum.interval / this->settings->scope.horizontal.frequencybase;
165 118
166 // Fill vector array 119 // Fill vector array
167 - unsigned int arrayPosition = 0;  
168 if(mode == Dso::CHANNELMODE_VOLTAGE) { 120 if(mode == Dso::CHANNELMODE_VOLTAGE) {
169 - for(unsigned int position = 0; position < this->dataAnalyzer->data(channel)->samples.voltage.count; ++position) {  
170 - vaNewChannel[arrayPosition++] = position * horizontalFactor - DIVS_TIME / 2;  
171 - vaNewChannel[arrayPosition++] = this->dataAnalyzer->data(channel)->samples.voltage.sample[position] / this->settings->scope.voltage[channel].gain + this->settings->scope.voltage[channel].offset; 121 + std::vector<double>::const_iterator dataIterator = this->dataAnalyzer->data(channel)->samples.voltage.sample.begin();
  122 + const double gain = this->settings->scope.voltage[channel].gain;
  123 + const double offset = this->settings->scope.voltage[channel].offset;
  124 +
  125 + for(unsigned int position = 0; position < sampleCount; ++position) {
  126 + *(glIterator++) = position * horizontalFactor - DIVS_TIME / 2;
  127 + *(glIterator++) = *(dataIterator++) / gain + offset;
172 } 128 }
173 } 129 }
174 else { 130 else {
175 - for(unsigned int position = 0; position < this->dataAnalyzer->data(channel)->samples.spectrum.count; ++position) {  
176 - vaNewChannel[arrayPosition++] = position * horizontalFactor - DIVS_TIME / 2;  
177 - vaNewChannel[arrayPosition++] = this->dataAnalyzer->data(channel)->samples.spectrum.sample[position] / this->settings->scope.spectrum[channel].magnitude + this->settings->scope.spectrum[channel].offset; 131 + std::vector<double>::const_iterator dataIterator = this->dataAnalyzer->data(channel)->samples.spectrum.sample.begin();
  132 + const double magnitude = this->settings->scope.spectrum[channel].magnitude;
  133 + const double offset = this->settings->scope.spectrum[channel].offset;
  134 +
  135 + for(unsigned int position = 0; position < sampleCount; ++position) {
  136 + *(glIterator++) = position * horizontalFactor - DIVS_TIME / 2;
  137 + *(glIterator++) = *(dataIterator++) / magnitude + offset;
178 } 138 }
179 } 139 }
180 } 140 }
181 else { 141 else {
182 // Delete all vector arrays 142 // Delete all vector arrays
183 - for(int index = 0; index < this->digitalPhosphorDepth; ++index)  
184 - this->vaChannel[mode][channel][index]->setSize(0); 143 + for(unsigned int index = 0; index < this->digitalPhosphorDepth; ++index)
  144 + this->vaChannel[mode][channel][index].clear();
185 } 145 }
186 } 146 }
187 } 147 }
188 break; 148 break;
189 149
190 case Dso::GRAPHFORMAT_XY: 150 case Dso::GRAPHFORMAT_XY:
191 - for(int channel = 0; channel < this->settings->scope.voltage.count(); ++channel) { 151 + for(int channel = 0; channel < this->settings->scope.voltage.size(); ++channel) {
192 // For even channel numbers check if this channel is used and this and the following channel are available at the data analyzer 152 // For even channel numbers check if this channel is used and this and the following channel are available at the data analyzer
193 - if(channel % 2 == 0 && channel + 1 < this->settings->scope.voltage.count() && this->settings->scope.voltage[channel].used && this->dataAnalyzer->data(channel) && this->dataAnalyzer->data(channel)->samples.voltage.sample && this->dataAnalyzer->data(channel + 1) && this->dataAnalyzer->data(channel + 1)->samples.voltage.sample) { 153 + if(channel % 2 == 0 && channel + 1 < this->settings->scope.voltage.size() && this->settings->scope.voltage[channel].used && this->dataAnalyzer->data(channel) && !this->dataAnalyzer->data(channel)->samples.voltage.sample.empty() && this->dataAnalyzer->data(channel + 1) && !this->dataAnalyzer->data(channel + 1)->samples.voltage.sample.empty()) {
194 // Check if the sample count has changed 154 // Check if the sample count has changed
195 - unsigned int neededSize = qMin(this->dataAnalyzer->data(channel)->samples.voltage.count, this->dataAnalyzer->data(channel + 1)->samples.voltage.count) * 2;  
196 - for(int index = 0; index < this->digitalPhosphorDepth; ++index) {  
197 - if(this->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel][index]->getSize() != neededSize)  
198 - this->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel][index]->setSize(0); 155 + const unsigned int sampleCount = qMin(this->dataAnalyzer->data(channel)->samples.voltage.sample.size(), this->dataAnalyzer->data(channel + 1)->samples.voltage.sample.size());
  156 + const unsigned int neededSize = sampleCount * 2;
  157 + for(unsigned int index = 0; index < this->digitalPhosphorDepth; ++index) {
  158 + if(this->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel][index].size() != neededSize)
  159 + this->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel][index].clear(); // Something was changed, drop old traces
199 } 160 }
200 161
201 - // Check if the array is allocated  
202 - if(!this->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel].first()->data)  
203 - this->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel].first()->setSize(neededSize); 162 + // Set size directly to avoid reallocations
  163 + this->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel].front().resize(neededSize);
204 164
205 - GLfloat *vaNewChannel = this->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel].first()->data; 165 + // Iterator to data for direct access
  166 + std::vector<GLfloat>::iterator glIterator = this->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel].front().begin();
206 167
207 // Fill vector array 168 // Fill vector array
208 - unsigned int arrayPosition = 0;  
209 unsigned int xChannel = channel; 169 unsigned int xChannel = channel;
210 unsigned int yChannel = channel + 1; 170 unsigned int yChannel = channel + 1;
211 - for(unsigned int position = 0; position < this->dataAnalyzer->data(channel)->samples.voltage.count; ++position) {  
212 - vaNewChannel[arrayPosition++] = this->dataAnalyzer->data(xChannel)->samples.voltage.sample[position] / this->settings->scope.voltage[xChannel].gain + this->settings->scope.voltage[xChannel].offset;  
213 - vaNewChannel[arrayPosition++] = this->dataAnalyzer->data(yChannel)->samples.voltage.sample[position] / this->settings->scope.voltage[yChannel].gain + this->settings->scope.voltage[yChannel].offset; 171 + std::vector<double>::const_iterator xIterator = this->dataAnalyzer->data(xChannel)->samples.voltage.sample.begin();
  172 + std::vector<double>::const_iterator yIterator = this->dataAnalyzer->data(yChannel)->samples.voltage.sample.begin();
  173 + const double xGain = this->settings->scope.voltage[xChannel].gain;
  174 + const double yGain = this->settings->scope.voltage[yChannel].gain;
  175 + const double xOffset = this->settings->scope.voltage[xChannel].offset;
  176 + const double yOffset = this->settings->scope.voltage[yChannel].offset;
  177 +
  178 + for(unsigned int position = 0; position < sampleCount; ++position) {
  179 + *(glIterator++) = *(xIterator++) / xGain + xOffset;
  180 + *(glIterator++) = *(yIterator++) / yGain + yOffset;
214 } 181 }
215 } 182 }
216 else { 183 else {
217 // Delete all vector arrays 184 // Delete all vector arrays
218 - for(int index = 0; index < this->digitalPhosphorDepth; ++index)  
219 - this->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel][index]->setSize(0); 185 + for(unsigned int index = 0; index < this->digitalPhosphorDepth; ++index)
  186 + this->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel][index].clear();
220 } 187 }
221 188
222 // Delete all spectrum graphs 189 // Delete all spectrum graphs
223 - for(int index = 0; index < this->digitalPhosphorDepth; ++index)  
224 - this->vaChannel[Dso::CHANNELMODE_SPECTRUM][channel][index]->setSize(0); 190 + for(unsigned int index = 0; index < this->digitalPhosphorDepth; ++index)
  191 + this->vaChannel[Dso::CHANNELMODE_SPECTRUM][channel][index].clear();
225 } 192 }
226 break; 193 break;
227 194
@@ -237,20 +204,20 @@ void GlGenerator::generateGraphs() { @@ -237,20 +204,20 @@ void GlGenerator::generateGraphs() {
237 /// \brief Create the needed OpenGL vertex arrays for the grid. 204 /// \brief Create the needed OpenGL vertex arrays for the grid.
238 void GlGenerator::generateGrid() { 205 void GlGenerator::generateGrid() {
239 // Grid 206 // Grid
240 - this->vaGrid[0].setSize(((DIVS_TIME * DIVS_SUB - 2) * (DIVS_VOLTAGE - 2) + (DIVS_VOLTAGE * DIVS_SUB - 2) * (DIVS_TIME - 2) - ((DIVS_TIME - 2) * (DIVS_VOLTAGE - 2))) * 2);  
241 - int pointIndex = 0; 207 + this->vaGrid[0].resize(((DIVS_TIME * DIVS_SUB - 2) * (DIVS_VOLTAGE - 2) + (DIVS_VOLTAGE * DIVS_SUB - 2) * (DIVS_TIME - 2) - ((DIVS_TIME - 2) * (DIVS_VOLTAGE - 2))) * 2);
  208 + std::vector<GLfloat>::iterator glIterator = this->vaGrid[0].begin();
242 // Draw vertical lines 209 // Draw vertical lines
243 for(int div = 1; div < DIVS_TIME / 2; ++div) { 210 for(int div = 1; div < DIVS_TIME / 2; ++div) {
244 for(int dot = 1; dot < DIVS_VOLTAGE / 2 * DIVS_SUB; ++dot) { 211 for(int dot = 1; dot < DIVS_VOLTAGE / 2 * DIVS_SUB; ++dot) {
245 float dotPosition = (float) dot / DIVS_SUB; 212 float dotPosition = (float) dot / DIVS_SUB;
246 - this->vaGrid[0].data[pointIndex++] = -div;  
247 - this->vaGrid[0].data[pointIndex++] = -dotPosition;  
248 - this->vaGrid[0].data[pointIndex++] = -div;  
249 - this->vaGrid[0].data[pointIndex++] = dotPosition;  
250 - this->vaGrid[0].data[pointIndex++] = div;  
251 - this->vaGrid[0].data[pointIndex++] = -dotPosition;  
252 - this->vaGrid[0].data[pointIndex++] = div;  
253 - this->vaGrid[0].data[pointIndex++] = dotPosition; 213 + *(glIterator++) = -div;
  214 + *(glIterator++) = -dotPosition;
  215 + *(glIterator++) = -div;
  216 + *(glIterator++) = dotPosition;
  217 + *(glIterator++) = div;
  218 + *(glIterator++) = -dotPosition;
  219 + *(glIterator++) = div;
  220 + *(glIterator++) = dotPosition;
254 } 221 }
255 } 222 }
256 // Draw horizontal lines 223 // Draw horizontal lines
@@ -259,63 +226,64 @@ void GlGenerator::generateGrid() { @@ -259,63 +226,64 @@ void GlGenerator::generateGrid() {
259 if(dot % DIVS_SUB == 0) 226 if(dot % DIVS_SUB == 0)
260 continue; // Already done by vertical lines 227 continue; // Already done by vertical lines
261 float dotPosition = (float) dot / DIVS_SUB; 228 float dotPosition = (float) dot / DIVS_SUB;
262 - this->vaGrid[0].data[pointIndex++] = -dotPosition;  
263 - this->vaGrid[0].data[pointIndex++] = -div;  
264 - this->vaGrid[0].data[pointIndex++] = dotPosition;  
265 - this->vaGrid[0].data[pointIndex++] = -div;  
266 - this->vaGrid[0].data[pointIndex++] = -dotPosition;  
267 - this->vaGrid[0].data[pointIndex++] = div;  
268 - this->vaGrid[0].data[pointIndex++] = dotPosition;  
269 - this->vaGrid[0].data[pointIndex++] = div; 229 + *(glIterator++) = -dotPosition;
  230 + *(glIterator++) = -div;
  231 + *(glIterator++) = dotPosition;
  232 + *(glIterator++) = -div;
  233 + *(glIterator++) = -dotPosition;
  234 + *(glIterator++) = div;
  235 + *(glIterator++) = dotPosition;
  236 + *(glIterator++) = div;
270 } 237 }
271 } 238 }
272 239
273 // Axes 240 // Axes
274 - this->vaGrid[1].setSize((2 + (DIVS_TIME * DIVS_SUB - 2) + (DIVS_VOLTAGE * DIVS_SUB - 2)) * 4);  
275 - pointIndex = 0; 241 + this->vaGrid[1].resize((2 + (DIVS_TIME * DIVS_SUB - 2) + (DIVS_VOLTAGE * DIVS_SUB - 2)) * 4);
  242 + glIterator = this->vaGrid[1].begin();
276 // Horizontal axis 243 // Horizontal axis
277 - this->vaGrid[1].data[pointIndex++] = -DIVS_TIME / 2;  
278 - this->vaGrid[1].data[pointIndex++] = 0;  
279 - this->vaGrid[1].data[pointIndex++] = DIVS_TIME / 2;  
280 - this->vaGrid[1].data[pointIndex++] = 0; 244 + *(glIterator++) = -DIVS_TIME / 2;
  245 + *(glIterator++) = 0;
  246 + *(glIterator++) = DIVS_TIME / 2;
  247 + *(glIterator++) = 0;
281 // Vertical axis 248 // Vertical axis
282 - this->vaGrid[1].data[pointIndex++] = 0;  
283 - this->vaGrid[1].data[pointIndex++] = -DIVS_VOLTAGE / 2;  
284 - this->vaGrid[1].data[pointIndex++] = 0;  
285 - this->vaGrid[1].data[pointIndex++] = DIVS_VOLTAGE / 2; 249 + *(glIterator++) = 0;
  250 + *(glIterator++) = -DIVS_VOLTAGE / 2;
  251 + *(glIterator++) = 0;
  252 + *(glIterator++) = DIVS_VOLTAGE / 2;
286 // Subdiv lines on horizontal axis 253 // Subdiv lines on horizontal axis
287 for(int line = 1; line < DIVS_TIME / 2 * DIVS_SUB; ++line) { 254 for(int line = 1; line < DIVS_TIME / 2 * DIVS_SUB; ++line) {
288 float linePosition = (float) line / DIVS_SUB; 255 float linePosition = (float) line / DIVS_SUB;
289 - this->vaGrid[1].data[pointIndex++] = linePosition;  
290 - this->vaGrid[1].data[pointIndex++] = -0.05;  
291 - this->vaGrid[1].data[pointIndex++] = linePosition;  
292 - this->vaGrid[1].data[pointIndex++] = 0.05;  
293 - this->vaGrid[1].data[pointIndex++] = -linePosition;  
294 - this->vaGrid[1].data[pointIndex++] = -0.05;  
295 - this->vaGrid[1].data[pointIndex++] = -linePosition;  
296 - this->vaGrid[1].data[pointIndex++] = 0.05; 256 + *(glIterator++) = linePosition;
  257 + *(glIterator++) = -0.05;
  258 + *(glIterator++) = linePosition;
  259 + *(glIterator++) = 0.05;
  260 + *(glIterator++) = -linePosition;
  261 + *(glIterator++) = -0.05;
  262 + *(glIterator++) = -linePosition;
  263 + *(glIterator++) = 0.05;
297 } 264 }
298 // Subdiv lines on vertical axis 265 // Subdiv lines on vertical axis
299 for(int line = 1; line < DIVS_VOLTAGE / 2 * DIVS_SUB; ++line) { 266 for(int line = 1; line < DIVS_VOLTAGE / 2 * DIVS_SUB; ++line) {
300 float linePosition = (float) line / DIVS_SUB; 267 float linePosition = (float) line / DIVS_SUB;
301 - this->vaGrid[1].data[pointIndex++] = -0.05;  
302 - this->vaGrid[1].data[pointIndex++] = linePosition;  
303 - this->vaGrid[1].data[pointIndex++] = 0.05;  
304 - this->vaGrid[1].data[pointIndex++] = linePosition;  
305 - this->vaGrid[1].data[pointIndex++] = -0.05;  
306 - this->vaGrid[1].data[pointIndex++] = -linePosition;  
307 - this->vaGrid[1].data[pointIndex++] = 0.05;  
308 - this->vaGrid[1].data[pointIndex++] = -linePosition; 268 + *(glIterator++) = -0.05;
  269 + *(glIterator++) = linePosition;
  270 + *(glIterator++) = 0.05;
  271 + *(glIterator++) = linePosition;
  272 + *(glIterator++) = -0.05;
  273 + *(glIterator++) = -linePosition;
  274 + *(glIterator++) = 0.05;
  275 + *(glIterator++) = -linePosition;
309 } 276 }
310 277
311 // Border 278 // Border
312 - this->vaGrid[2].setSize(4 * 2);  
313 - this->vaGrid[2].data[0] = -DIVS_TIME / 2;  
314 - this->vaGrid[2].data[1] = -DIVS_VOLTAGE / 2;  
315 - this->vaGrid[2].data[2] = DIVS_TIME / 2;  
316 - this->vaGrid[2].data[3] = -DIVS_VOLTAGE / 2;  
317 - this->vaGrid[2].data[4] = DIVS_TIME / 2;  
318 - this->vaGrid[2].data[5] = DIVS_VOLTAGE / 2;  
319 - this->vaGrid[2].data[6] = -DIVS_TIME / 2;  
320 - this->vaGrid[2].data[7] = DIVS_VOLTAGE / 2; 279 + this->vaGrid[2].resize(4 * 2);
  280 + glIterator = this->vaGrid[2].begin();
  281 + *(glIterator++) = -DIVS_TIME / 2;
  282 + *(glIterator++) = -DIVS_VOLTAGE / 2;
  283 + *(glIterator++) = DIVS_TIME / 2;
  284 + *(glIterator++) = -DIVS_VOLTAGE / 2;
  285 + *(glIterator++) = DIVS_TIME / 2;
  286 + *(glIterator++) = DIVS_VOLTAGE / 2;
  287 + *(glIterator++) = -DIVS_TIME / 2;
  288 + *(glIterator++) = DIVS_VOLTAGE / 2;
321 } 289 }
openhantek/src/glgenerator.h
@@ -29,8 +29,9 @@ @@ -29,8 +29,9 @@
29 #define GLGENERATOR_H 29 #define GLGENERATOR_H
30 30
31 31
  32 +#include <deque>
  33 +
32 #include <QGLWidget> 34 #include <QGLWidget>
33 -#include <QList>  
34 #include <QObject> 35 #include <QObject>
35 36
36 37
@@ -48,23 +49,6 @@ class GlScope; @@ -48,23 +49,6 @@ class GlScope;
48 49
49 50
50 //////////////////////////////////////////////////////////////////////////////// 51 ////////////////////////////////////////////////////////////////////////////////
51 -/// \class GlArray glgenerator.h  
52 -/// \brief An array of GLfloat values and it's size.  
53 -class GlArray {  
54 - public:  
55 - GlArray();  
56 - ~GlArray();  
57 -  
58 - unsigned int getSize();  
59 - void setSize(unsigned int size);  
60 -  
61 - GLfloat *data; ///< Pointer to the array  
62 -  
63 - protected:  
64 - unsigned int size; ///< The array size (Number of GLfloat values)  
65 -};  
66 -  
67 -////////////////////////////////////////////////////////////////////////////////  
68 /// \class GlGenerator glgenerator.h 52 /// \class GlGenerator glgenerator.h
69 /// \brief Generates the vertex arrays for the GlScope classes. 53 /// \brief Generates the vertex arrays for the GlScope classes.
70 class GlGenerator : public QObject { 54 class GlGenerator : public QObject {
@@ -85,10 +69,10 @@ class GlGenerator : public QObject { @@ -85,10 +69,10 @@ class GlGenerator : public QObject {
85 DataAnalyzer *dataAnalyzer; 69 DataAnalyzer *dataAnalyzer;
86 DsoSettings *settings; 70 DsoSettings *settings;
87 71
88 - QList<QList<GlArray *> > vaChannel[Dso::CHANNELMODE_COUNT];  
89 - GlArray vaGrid[3]; 72 + std::vector<std::deque<std::vector<GLfloat> > > vaChannel[Dso::CHANNELMODE_COUNT];
  73 + std::vector<GLfloat> vaGrid[3];
90 74
91 - int digitalPhosphorDepth; 75 + unsigned int digitalPhosphorDepth;
92 76
93 public slots: 77 public slots:
94 void generateGraphs(); 78 void generateGraphs();
openhantek/src/glscope.cpp
@@ -96,7 +96,7 @@ void GlScope::paintGL() { @@ -96,7 +96,7 @@ void GlScope::paintGL() {
96 double *fadingFactor = new double[this->generator->digitalPhosphorDepth]; 96 double *fadingFactor = new double[this->generator->digitalPhosphorDepth];
97 fadingFactor[0] = 100; 97 fadingFactor[0] = 100;
98 double fadingRatio = pow(10.0, 2.0 / this->generator->digitalPhosphorDepth); 98 double fadingRatio = pow(10.0, 2.0 / this->generator->digitalPhosphorDepth);
99 - for(int index = 1; index < this->generator->digitalPhosphorDepth; ++index) 99 + for(unsigned int index = 1; index < this->generator->digitalPhosphorDepth; ++index)
100 fadingFactor[index] = fadingFactor[index - 1] * fadingRatio; 100 fadingFactor[index] = fadingFactor[index - 1] * fadingRatio;
101 101
102 switch(this->settings->scope.horizontal.format) { 102 switch(this->settings->scope.horizontal.format) {
@@ -107,13 +107,13 @@ void GlScope::paintGL() { @@ -107,13 +107,13 @@ void GlScope::paintGL() {
107 if((mode == Dso::CHANNELMODE_VOLTAGE) ? this->settings->scope.voltage[channel].used : this->settings->scope.spectrum[channel].used) { 107 if((mode == Dso::CHANNELMODE_VOLTAGE) ? this->settings->scope.voltage[channel].used : this->settings->scope.spectrum[channel].used) {
108 // Draw graph for all available depths 108 // Draw graph for all available depths
109 for(int index = this->generator->digitalPhosphorDepth - 1; index >= 0; index--) { 109 for(int index = this->generator->digitalPhosphorDepth - 1; index >= 0; index--) {
110 - if(this->generator->vaChannel[mode][channel][index]->data) { 110 + if(!this->generator->vaChannel[mode][channel][index].empty()) {
111 if(mode == Dso::CHANNELMODE_VOLTAGE) 111 if(mode == Dso::CHANNELMODE_VOLTAGE)
112 this->qglColor(this->settings->view.color.screen.voltage[channel].darker(fadingFactor[index])); 112 this->qglColor(this->settings->view.color.screen.voltage[channel].darker(fadingFactor[index]));
113 else 113 else
114 this->qglColor(this->settings->view.color.screen.spectrum[channel].darker(fadingFactor[index])); 114 this->qglColor(this->settings->view.color.screen.spectrum[channel].darker(fadingFactor[index]));
115 - glVertexPointer(2, GL_FLOAT, 0, this->generator->vaChannel[mode][channel][index]->data);  
116 - glDrawArrays((this->settings->view.interpolation == Dso::INTERPOLATION_OFF) ? GL_POINTS : GL_LINE_STRIP, 0, this->generator->vaChannel[mode][channel][index]->getSize() / 2); 115 + glVertexPointer(2, GL_FLOAT, 0, &this->generator->vaChannel[mode][channel][index].front());
  116 + glDrawArrays((this->settings->view.interpolation == Dso::INTERPOLATION_OFF) ? GL_POINTS : GL_LINE_STRIP, 0, this->generator->vaChannel[mode][channel][index].size() / 2);
117 } 117 }
118 } 118 }
119 } 119 }
@@ -127,10 +127,10 @@ void GlScope::paintGL() { @@ -127,10 +127,10 @@ void GlScope::paintGL() {
127 if(this->settings->scope.voltage[channel].used) { 127 if(this->settings->scope.voltage[channel].used) {
128 // Draw graph for all available depths 128 // Draw graph for all available depths
129 for(int index = this->generator->digitalPhosphorDepth - 1; index >= 0; index--) { 129 for(int index = this->generator->digitalPhosphorDepth - 1; index >= 0; index--) {
130 - if(this->generator->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel][index]->data) { 130 + if(!this->generator->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel][index].empty()) {
131 this->qglColor(this->settings->view.color.screen.voltage[channel].darker(fadingFactor[index])); 131 this->qglColor(this->settings->view.color.screen.voltage[channel].darker(fadingFactor[index]));
132 - glVertexPointer(2, GL_FLOAT, 0, this->generator->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel][index]->data);  
133 - glDrawArrays((this->settings->view.interpolation == Dso::INTERPOLATION_OFF) ? GL_POINTS : GL_LINE_STRIP, 0, this->generator->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel][index]->getSize() / 2); 132 + glVertexPointer(2, GL_FLOAT, 0, &this->generator->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel][index].front());
  133 + glDrawArrays((this->settings->view.interpolation == Dso::INTERPOLATION_OFF) ? GL_POINTS : GL_LINE_STRIP, 0, this->generator->vaChannel[Dso::CHANNELMODE_VOLTAGE][channel][index].size() / 2);
134 } 134 }
135 } 135 }
136 } 136 }
@@ -156,17 +156,17 @@ void GlScope::paintGL() { @@ -156,17 +156,17 @@ void GlScope::paintGL() {
156 this->qglColor(this->settings->view.color.screen.markers); 156 this->qglColor(this->settings->view.color.screen.markers);
157 157
158 for(int marker = 0; marker < MARKER_COUNT; ++marker) { 158 for(int marker = 0; marker < MARKER_COUNT; ++marker) {
159 - if(!this->vaMarker[marker].data) {  
160 - this->vaMarker[marker].setSize(2 * 2);  
161 - this->vaMarker[marker].data[1] = - DIVS_VOLTAGE;  
162 - this->vaMarker[marker].data[3] = DIVS_VOLTAGE; 159 + if(this->vaMarker[marker].size() != 4) {
  160 + this->vaMarker[marker].resize(2 * 2);
  161 + this->vaMarker[marker][1] = -DIVS_VOLTAGE;
  162 + this->vaMarker[marker][3] = DIVS_VOLTAGE;
163 } 163 }
164 164
165 - this->vaMarker[marker].data[0] = this->settings->scope.horizontal.marker[marker];  
166 - this->vaMarker[marker].data[2] = this->settings->scope.horizontal.marker[marker]; 165 + this->vaMarker[marker][0] = this->settings->scope.horizontal.marker[marker];
  166 + this->vaMarker[marker][2] = this->settings->scope.horizontal.marker[marker];
167 167
168 - glVertexPointer(2, GL_FLOAT, 0, this->vaMarker[marker].data);  
169 - glDrawArrays(GL_LINES, 0, this->vaMarker[marker].getSize() / 2); 168 + glVertexPointer(2, GL_FLOAT, 0, &this->vaMarker[marker].front());
  169 + glDrawArrays(GL_LINES, 0, this->vaMarker[marker].size() / 2);
170 } 170 }
171 171
172 glDisable(GL_LINE_STIPPLE); 172 glDisable(GL_LINE_STIPPLE);
@@ -215,14 +215,14 @@ void GlScope::drawGrid() { @@ -215,14 +215,14 @@ void GlScope::drawGrid() {
215 215
216 // Grid 216 // Grid
217 this->qglColor(this->settings->view.color.screen.grid); 217 this->qglColor(this->settings->view.color.screen.grid);
218 - glVertexPointer(2, GL_FLOAT, 0, this->generator->vaGrid[0].data);  
219 - glDrawArrays(GL_POINTS, 0, this->generator->vaGrid[0].getSize() / 2); 218 + glVertexPointer(2, GL_FLOAT, 0, &this->generator->vaGrid[0].front());
  219 + glDrawArrays(GL_POINTS, 0, this->generator->vaGrid[0].size() / 2);
220 // Axes 220 // Axes
221 this->qglColor(this->settings->view.color.screen.axes); 221 this->qglColor(this->settings->view.color.screen.axes);
222 - glVertexPointer(2, GL_FLOAT, 0, this->generator->vaGrid[1].data);  
223 - glDrawArrays(GL_LINES, 0, this->generator->vaGrid[1].getSize() / 2); 222 + glVertexPointer(2, GL_FLOAT, 0, &this->generator->vaGrid[1].front());
  223 + glDrawArrays(GL_LINES, 0, this->generator->vaGrid[1].size() / 2);
224 // Border 224 // Border
225 this->qglColor(this->settings->view.color.screen.border); 225 this->qglColor(this->settings->view.color.screen.border);
226 - glVertexPointer(2, GL_FLOAT, 0, this->generator->vaGrid[2].data);  
227 - glDrawArrays(GL_LINE_LOOP, 0, this->generator->vaGrid[2].getSize() / 2); 226 + glVertexPointer(2, GL_FLOAT, 0, &this->generator->vaGrid[2].front());
  227 + glDrawArrays(GL_LINE_LOOP, 0, this->generator->vaGrid[2].size() / 2);
228 } 228 }
openhantek/src/glscope.h
@@ -64,7 +64,7 @@ class GlScope : public QGLWidget { @@ -64,7 +64,7 @@ class GlScope : public QGLWidget {
64 GlGenerator *generator; 64 GlGenerator *generator;
65 DsoSettings *settings; 65 DsoSettings *settings;
66 66
67 - GlArray vaMarker[2]; 67 + std::vector<GLfloat> vaMarker[2];
68 bool zoomed; 68 bool zoomed;
69 }; 69 };
70 70
openhantek/src/hantek/control.cpp
@@ -29,6 +29,7 @@ @@ -29,6 +29,7 @@
29 29
30 #include <QList> 30 #include <QList>
31 #include <QMutex> 31 #include <QMutex>
  32 +#include <QTime>
32 33
33 34
34 #include "hantek/control.h" 35 #include "hantek/control.h"
@@ -110,10 +111,7 @@ namespace Hantek { @@ -110,10 +111,7 @@ namespace Hantek {
110 this->device = new Device(this); 111 this->device = new Device(this);
111 112
112 // Sample buffers 113 // Sample buffers
113 - for(unsigned int channel = 0; channel < HANTEK_CHANNELS; ++channel) {  
114 - this->samples.append(0);  
115 - this->samplesSize.append(0);  
116 - } 114 + this->samples.resize(HANTEK_CHANNELS);
117 115
118 this->previousSampleCount = 0; 116 this->previousSampleCount = 0;
119 117
@@ -162,6 +160,7 @@ namespace Hantek { @@ -162,6 +160,7 @@ namespace Hantek {
162 160
163 // The control loop is running until the device is disconnected 161 // The control loop is running until the device is disconnected
164 int captureState = CAPTURE_WAITING; 162 int captureState = CAPTURE_WAITING;
  163 + int rollState = 0;
165 bool samplingStarted = false; 164 bool samplingStarted = false;
166 Dso::TriggerMode lastTriggerMode = (Dso::TriggerMode) -1; 165 Dso::TriggerMode lastTriggerMode = (Dso::TriggerMode) -1;
167 166
@@ -172,7 +171,7 @@ namespace Hantek { @@ -172,7 +171,7 @@ namespace Hantek {
172 continue; 171 continue;
173 172
174 #ifdef DEBUG 173 #ifdef DEBUG
175 - qDebug("Sending bulk command:%s", Helper::hexDump(this->command[command]->data(), this->command[command]->getSize()).toLocal8Bit().data()); 174 + Helper::timestampDebug(QString("Sending bulk command:%1").arg(Helper::hexDump(this->command[command]->data(), this->command[command]->getSize())));
176 #endif 175 #endif
177 176
178 errorCode = this->device->bulkCommand(this->command[command]); 177 errorCode = this->device->bulkCommand(this->command[command]);
@@ -196,7 +195,7 @@ namespace Hantek { @@ -196,7 +195,7 @@ namespace Hantek {
196 continue; 195 continue;
197 196
198 #ifdef DEBUG 197 #ifdef DEBUG
199 - qDebug("Sending control command %02x:%s", this->controlCode[control], Helper::hexDump(this->control[control]->data(), this->control[control]->getSize()).toLocal8Bit().data()); 198 + Helper::timestampDebug(QString("Sending control command %1:%2").arg(QString::number(this->controlCode[control], 16), Helper::hexDump(this->control[control]->data(), this->control[control]->getSize())));
200 #endif 199 #endif
201 200
202 errorCode = this->device->controlWrite(this->controlCode[control], this->control[control]->data(), this->control[control]->getSize()); 201 errorCode = this->device->controlWrite(this->controlCode[control], this->control[control]->data(), this->control[control]->getSize());
@@ -218,9 +217,9 @@ namespace Hantek { @@ -218,9 +217,9 @@ namespace Hantek {
218 // Not more often than every 10 ms though 217 // Not more often than every 10 ms though
219 int cycleTime; 218 int cycleTime;
220 if(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] == UINT_MAX) 219 if(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] == UINT_MAX)
221 - cycleTime = qMax((int) ((double) this->device->getPacketSize() / this->settings.samplerate.current * 250), 1); 220 + cycleTime = qMax((int) ((double) this->device->getPacketSize() / ((this->settings.samplerate.limits == &this->specification.samplerate.multi) ? 1 : HANTEK_CHANNELS) / this->settings.samplerate.current * 250), 1);
222 else 221 else
223 - cycleTime = qMax((unsigned int) ((double) this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] / this->settings.samplerate.current * 250), 10u); 222 + cycleTime = qMax((int) ((double) this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] / this->settings.samplerate.current * 250), 10);
224 this->msleep(cycleTime); 223 this->msleep(cycleTime);
225 224
226 if(!this->sampling) { 225 if(!this->sampling) {
@@ -228,94 +227,184 @@ namespace Hantek { @@ -228,94 +227,184 @@ namespace Hantek {
228 continue; 227 continue;
229 } 228 }
230 229
  230 + if(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] == UINT_MAX) {
  231 + // Roll mode
  232 + captureState = CAPTURE_WAITING;
  233 +
  234 + switch(rollState) {
  235 + case ROLL_STARTSAMPLING:
  236 + // Don't iterate through roll mode steps when stopped
  237 + if(!this->sampling)
  238 + continue;
  239 +
  240 + // Sampling hasn't started, update the expected sample count
  241 + this->previousSampleCount = this->getSampleCount();
  242 +
  243 + errorCode = this->device->bulkCommand(this->command[BULK_STARTSAMPLING]);
  244 + if(errorCode < 0) {
  245 + if(errorCode == LIBUSB_ERROR_NO_DEVICE)
  246 + captureState = LIBUSB_ERROR_NO_DEVICE;
  247 + break;
  248 + }
231 #ifdef DEBUG 249 #ifdef DEBUG
232 - int lastCaptureState = captureState; 250 + Helper::timestampDebug("Starting to capture");
233 #endif 251 #endif
234 - captureState = this->getCaptureState();  
235 - if(captureState < 0)  
236 - qWarning("Getting capture state failed: %s", Helper::libUsbErrorString(captureState).toLocal8Bit().data()); 252 +
  253 + samplingStarted = true;
  254 +
  255 + break;
  256 +
  257 + case ROLL_ENABLETRIGGER:
  258 + errorCode = this->device->bulkCommand(this->command[BULK_ENABLETRIGGER]);
  259 + if(errorCode < 0) {
  260 + if(errorCode == LIBUSB_ERROR_NO_DEVICE)
  261 + captureState = LIBUSB_ERROR_NO_DEVICE;
  262 + break;
  263 + }
237 #ifdef DEBUG 264 #ifdef DEBUG
238 - else if(captureState != lastCaptureState)  
239 - qDebug("Capture state changed to %d", captureState); 265 + Helper::timestampDebug("Enabling trigger");
240 #endif 266 #endif
241 - switch(captureState) {  
242 - case CAPTURE_READY:  
243 - case CAPTURE_READY2250:  
244 - case CAPTURE_READY5200:  
245 - // Get data and process it, if we're still sampling  
246 - errorCode = this->getSamples(samplingStarted);  
247 - if(errorCode < 0)  
248 - qWarning("Getting sample data failed: %s", Helper::libUsbErrorString(errorCode).toLocal8Bit().data()); 267 +
  268 + break;
  269 +
  270 + case ROLL_FORCETRIGGER:
  271 + errorCode = this->device->bulkCommand(this->command[BULK_FORCETRIGGER]);
  272 + if(errorCode < 0) {
  273 + if(errorCode == LIBUSB_ERROR_NO_DEVICE)
  274 + captureState = LIBUSB_ERROR_NO_DEVICE;
  275 + break;
  276 + }
249 #ifdef DEBUG 277 #ifdef DEBUG
250 - else  
251 - qDebug("Received %d B of sampling data", errorCode); 278 + Helper::timestampDebug("Forcing trigger");
252 #endif 279 #endif
  280 +
  281 + break;
253 282
254 - // Check if we're in single trigger mode  
255 - if(this->settings.trigger.mode == Dso::TRIGGERMODE_SINGLE && samplingStarted)  
256 - this->stopSampling();  
257 -  
258 - // Sampling completed, restart it when necessary  
259 - samplingStarted = false; 283 + case ROLL_GETDATA:
  284 + // Get data and process it, if we're still sampling
  285 + errorCode = this->getSamples(samplingStarted);
  286 + if(errorCode < 0)
  287 + qWarning("Getting sample data failed: %s", Helper::libUsbErrorString(errorCode).toLocal8Bit().data());
  288 + #ifdef DEBUG
  289 + else
  290 + Helper::timestampDebug(QString("Received %1 B of sampling data").arg(errorCode));
  291 + #endif
  292 +
  293 + // Check if we're in single trigger mode
  294 + if(this->settings.trigger.mode == Dso::TRIGGERMODE_SINGLE && samplingStarted)
  295 + this->stopSampling();
  296 +
  297 + // Sampling completed, restart it when necessary
  298 + samplingStarted = false;
  299 +
  300 + break;
260 301
261 - // Start next capture if necessary by leaving out the break statement  
262 - if(!this->sampling) 302 + default:
  303 +#ifdef DEBUG
  304 + Helper::timestampDebug("Roll mode state unknown");
  305 +#endif
263 break; 306 break;
  307 + }
264 308
265 - case CAPTURE_WAITING:  
266 - // Sampling hasn't started, update the expected sample count  
267 - this->previousSampleCount = this->getSampleCount(); 309 + // Go to next state, or restart if last state was reached
  310 + rollState = (rollState + 1) % ROLL_COUNT;
  311 + }
  312 + else {
  313 + // Standard mode
  314 + rollState = ROLL_STARTSAMPLING;
  315 +
  316 +#ifdef DEBUG
  317 + int lastCaptureState = captureState;
  318 +#endif
  319 + captureState = this->getCaptureState();
  320 + if(captureState < 0)
  321 + qWarning("Getting capture state failed: %s", Helper::libUsbErrorString(captureState).toLocal8Bit().data());
  322 +#ifdef DEBUG
  323 + else if(captureState != lastCaptureState)
  324 + Helper::timestampDebug(QString("Capture state changed to %1").arg(captureState));
  325 +#endif
  326 + switch(captureState) {
  327 + case CAPTURE_READY:
  328 + case CAPTURE_READY2250:
  329 + case CAPTURE_READY5200:
  330 + // Get data and process it, if we're still sampling
  331 + errorCode = this->getSamples(samplingStarted);
  332 + if(errorCode < 0)
  333 + qWarning("Getting sample data failed: %s", Helper::libUsbErrorString(errorCode).toLocal8Bit().data());
  334 +#ifdef DEBUG
  335 + else
  336 + Helper::timestampDebug(QString("Received %1 B of sampling data").arg(errorCode));
  337 +#endif
  338 +
  339 + // Check if we're in single trigger mode
  340 + if(this->settings.trigger.mode == Dso::TRIGGERMODE_SINGLE && samplingStarted)
  341 + this->stopSampling();
  342 +
  343 + // Sampling completed, restart it when necessary
  344 + samplingStarted = false;
  345 +
  346 + // Start next capture if necessary by leaving out the break statement
  347 + if(!this->sampling)
  348 + break;
268 349
269 - if(samplingStarted && lastTriggerMode == this->settings.trigger.mode) {  
270 - ++cycleCounter; 350 + case CAPTURE_WAITING:
  351 + // Sampling hasn't started, update the expected sample count
  352 + this->previousSampleCount = this->getSampleCount();
271 353
272 - if(cycleCounter == startCycle) {  
273 - // Buffer refilled completely since start of sampling, enable the trigger now  
274 - errorCode = this->device->bulkCommand(this->command[BULK_ENABLETRIGGER]);  
275 - if(errorCode < 0) {  
276 - if(errorCode == LIBUSB_ERROR_NO_DEVICE)  
277 - captureState = LIBUSB_ERROR_NO_DEVICE;  
278 - break; 354 + if(samplingStarted && lastTriggerMode == this->settings.trigger.mode) {
  355 + ++cycleCounter;
  356 +
  357 + if(cycleCounter == startCycle && this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] != UINT_MAX) {
  358 + // Buffer refilled completely since start of sampling, enable the trigger now
  359 + errorCode = this->device->bulkCommand(this->command[BULK_ENABLETRIGGER]);
  360 + if(errorCode < 0) {
  361 + if(errorCode == LIBUSB_ERROR_NO_DEVICE)
  362 + captureState = LIBUSB_ERROR_NO_DEVICE;
  363 + break;
  364 + }
  365 +#ifdef DEBUG
  366 + Helper::timestampDebug("Enabling trigger");
  367 +#endif
279 } 368 }
  369 + else if(cycleCounter >= 8 + startCycle && this->settings.trigger.mode == Dso::TRIGGERMODE_AUTO) {
  370 + // Force triggering
  371 + errorCode = this->device->bulkCommand(this->command[BULK_FORCETRIGGER]);
  372 + if(errorCode < 0) {
  373 + if(errorCode == LIBUSB_ERROR_NO_DEVICE)
  374 + captureState = LIBUSB_ERROR_NO_DEVICE;
  375 + break;
  376 + }
280 #ifdef DEBUG 377 #ifdef DEBUG
281 - qDebug("Enabling trigger"); 378 + Helper::timestampDebug("Forcing trigger");
282 #endif 379 #endif
  380 + }
  381 +
  382 + if(cycleCounter < 20 || cycleCounter < 4000 / cycleTime)
  383 + break;
283 } 384 }
284 - else if(cycleCounter >= 8 + startCycle && this->settings.trigger.mode == Dso::TRIGGERMODE_AUTO) {  
285 - // Force triggering  
286 - errorCode = this->device->bulkCommand(this->command[BULK_FORCETRIGGER]); 385 +
  386 + // Start capturing
  387 + errorCode = this->device->bulkCommand(this->command[BULK_STARTSAMPLING]);
  388 + if(errorCode < 0) {
287 if(errorCode == LIBUSB_ERROR_NO_DEVICE) 389 if(errorCode == LIBUSB_ERROR_NO_DEVICE)
288 captureState = LIBUSB_ERROR_NO_DEVICE; 390 captureState = LIBUSB_ERROR_NO_DEVICE;
  391 + break;
  392 + }
289 #ifdef DEBUG 393 #ifdef DEBUG
290 - qDebug("Forcing trigger"); 394 + Helper::timestampDebug("Starting to capture");
291 #endif 395 #endif
292 - }  
293 396
294 - if(cycleCounter < 20 || cycleCounter < 4000 / cycleTime)  
295 - break;  
296 - }  
297 -  
298 - // Start capturing  
299 - errorCode = this->device->bulkCommand(this->command[BULK_STARTSAMPLING]);  
300 - if(errorCode < 0) {  
301 - if(errorCode == LIBUSB_ERROR_NO_DEVICE)  
302 - captureState = LIBUSB_ERROR_NO_DEVICE; 397 + samplingStarted = true;
  398 + cycleCounter = 0;
  399 + startCycle = this->settings.trigger.position * 1000 / cycleTime + 1;
  400 + lastTriggerMode = this->settings.trigger.mode;
303 break; 401 break;
304 - }  
305 -#ifdef DEBUG  
306 - qDebug("Starting to capture");  
307 -#endif  
308 402
309 - samplingStarted = true;  
310 - cycleCounter = 0;  
311 - startCycle = this->settings.trigger.position * 1000 / cycleTime + 1;  
312 - lastTriggerMode = this->settings.trigger.mode;  
313 - break;  
314 -  
315 - case CAPTURE_SAMPLING:  
316 - break;  
317 - default:  
318 - break; 403 + case CAPTURE_SAMPLING:
  404 + break;
  405 + default:
  406 + break;
  407 + }
319 } 408 }
320 } 409 }
321 410
@@ -417,20 +506,14 @@ namespace Hantek { @@ -417,20 +506,14 @@ namespace Hantek {
417 506
418 // Clear unused channels 507 // Clear unused channels
419 for(int channelCounter = 0; channelCounter < HANTEK_CHANNELS; ++channelCounter) 508 for(int channelCounter = 0; channelCounter < HANTEK_CHANNELS; ++channelCounter)
420 - if(channelCounter != channel && this->samples[channelCounter]) { 509 + if(channelCounter != channel) {
421 510
422 - delete this->samples[channelCounter];  
423 - this->samples[channelCounter] = 0; 511 + this->samples[channelCounter].clear();
424 } 512 }
425 513
426 if(channel < HANTEK_CHANNELS) { 514 if(channel < HANTEK_CHANNELS) {
427 - // Reallocate memory for samples if the sample count has changed  
428 - if(!this->samples[channel] || this->samplesSize[channel] != sampleCount) {  
429 - if(this->samples[channel])  
430 - delete this->samples[channel];  
431 - this->samples[channel] = new double[sampleCount];  
432 - this->samplesSize[channel] = sampleCount;  
433 - } 515 + // Resize sample vector
  516 + this->samples[channel].resize(sampleCount);
434 517
435 // Convert data from the oscilloscope and write it into the sample buffer 518 // Convert data from the oscilloscope and write it into the sample buffer
436 unsigned int bufferPosition = this->settings.trigger.point * 2; 519 unsigned int bufferPosition = this->settings.trigger.point * 2;
@@ -464,13 +547,8 @@ namespace Hantek { @@ -464,13 +547,8 @@ namespace Hantek {
464 sampleCount = totalSampleCount / HANTEK_CHANNELS; 547 sampleCount = totalSampleCount / HANTEK_CHANNELS;
465 for(int channel = 0; channel < HANTEK_CHANNELS; ++channel) { 548 for(int channel = 0; channel < HANTEK_CHANNELS; ++channel) {
466 if(this->settings.voltage[channel].used) { 549 if(this->settings.voltage[channel].used) {
467 - // Reallocate memory for samples if the sample count has changed  
468 - if(!this->samples[channel] || this->samplesSize[channel] != sampleCount) {  
469 - if(this->samples[channel])  
470 - delete this->samples[channel];  
471 - this->samples[channel] = new double[sampleCount];  
472 - this->samplesSize[channel] = sampleCount;  
473 - } 550 + // Resize sample vector
  551 + this->samples[channel].resize(sampleCount);
474 552
475 // Convert data from the oscilloscope and write it into the sample buffer 553 // Convert data from the oscilloscope and write it into the sample buffer
476 unsigned int bufferPosition = this->settings.trigger.point * 2; 554 unsigned int bufferPosition = this->settings.trigger.point * 2;
@@ -497,17 +575,20 @@ namespace Hantek { @@ -497,17 +575,20 @@ namespace Hantek {
497 } 575 }
498 } 576 }
499 } 577 }
500 - else if(this->samples[channel]) { 578 + else {
501 // Clear unused channels 579 // Clear unused channels
502 - delete this->samples[channel];  
503 - this->samples[channel] = 0;  
504 - this->samplesSize[channel] = 0; 580 + this->samples[channel].clear();
505 } 581 }
506 } 582 }
507 } 583 }
508 584
509 this->samplesMutex.unlock(); 585 this->samplesMutex.unlock();
510 - emit samplesAvailable(&(this->samples), &(this->samplesSize), this->settings.samplerate.current, &(this->samplesMutex)); 586 +#ifdef DEBUG
  587 + static unsigned int id = 0;
  588 + ++id;
  589 + Helper::timestampDebug(QString("Received packet %1").arg(id));
  590 +#endif
  591 + emit samplesAvailable(&(this->samples), this->settings.samplerate.current, this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] == UINT_MAX, &(this->samplesMutex));
511 } 592 }
512 593
513 return errorCode; 594 return errorCode;
@@ -671,6 +752,14 @@ namespace Hantek { @@ -671,6 +752,14 @@ namespace Hantek {
671 return 0; 752 return 0;
672 } 753 }
673 754
  755 + // Check if the divider has changed and adapt samplerate limits accordingly
  756 + if(this->specification.bufferDividers[index] != this->specification.bufferDividers[this->settings.recordLengthId]) {
  757 + this->updateSamplerateLimits();
  758 +
  759 + // Samplerate dividers changed, recalculate it
  760 + this->restoreTargets();
  761 + }
  762 +
674 this->settings.recordLengthId = index; 763 this->settings.recordLengthId = index;
675 764
676 return this->settings.samplerate.limits->recordLengths[index]; 765 return this->settings.samplerate.limits->recordLengths[index];
@@ -777,9 +866,9 @@ namespace Hantek { @@ -777,9 +866,9 @@ namespace Hantek {
777 866
778 this->settings.samplerate.downsampler = downsampler; 867 this->settings.samplerate.downsampler = downsampler;
779 if(downsampler) 868 if(downsampler)
780 - this->settings.samplerate.current = this->settings.samplerate.limits->base / downsampler; 869 + this->settings.samplerate.current = this->settings.samplerate.limits->base / this->specification.bufferDividers[this->settings.recordLengthId] / downsampler;
781 else 870 else
782 - this->settings.samplerate.current = this->settings.samplerate.limits->max; 871 + this->settings.samplerate.current = this->settings.samplerate.limits->max / this->specification.bufferDividers[this->settings.recordLengthId];
783 872
784 // Update dependencies 873 // Update dependencies
785 this->setPretriggerPosition(this->settings.trigger.position); 874 this->setPretriggerPosition(this->settings.trigger.position);
@@ -791,15 +880,14 @@ namespace Hantek { @@ -791,15 +880,14 @@ namespace Hantek {
791 } 880 }
792 881
793 // Check for Roll mode 882 // Check for Roll mode
794 - if(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] != UINT_MAX) { 883 + if(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] != UINT_MAX)
795 emit recordTimeChanged((double) this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] / this->settings.samplerate.current); 884 emit recordTimeChanged((double) this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] / this->settings.samplerate.current);
796 - emit samplerateChanged(this->settings.samplerate.current);  
797 - } 885 + emit samplerateChanged(this->settings.samplerate.current);
798 886
799 return downsampler; 887 return downsampler;
800 } 888 }
801 889
802 - /// \brief Try to connect to the oscilloscope. 890 + /// \brief Restore the samplerate/timebase targets after divider updates.
803 void Control::restoreTargets() { 891 void Control::restoreTargets() {
804 if(this->settings.samplerate.target.samplerateSet) 892 if(this->settings.samplerate.target.samplerateSet)
805 this->setSamplerate(); 893 this->setSamplerate();
@@ -807,6 +895,13 @@ namespace Hantek { @@ -807,6 +895,13 @@ namespace Hantek {
807 this->setRecordTime(); 895 this->setRecordTime();
808 } 896 }
809 897
  898 + /// \brief Update the minimum and maximum supported samplerate.
  899 + void Control::updateSamplerateLimits() {
  900 + // Works only if the minimum samplerate for normal mode is lower than for fast rate mode, which is the case for all models
  901 + ControlSamplerateLimits *limits = (this->settings.usedChannels <= 1) ? &this->specification.samplerate.multi : &this->specification.samplerate.single;
  902 + emit samplerateLimitsChanged((double) this->specification.samplerate.single.base / this->specification.samplerate.single.maxDownsampler / this->specification.bufferDividers[this->settings.recordLengthId], limits->max / this->specification.bufferDividers[this->settings.recordLengthId]);
  903 + }
  904 +
810 /// \brief Try to connect to the oscilloscope. 905 /// \brief Try to connect to the oscilloscope.
811 void Control::connectDevice() { 906 void Control::connectDevice() {
812 int errorCode; 907 int errorCode;
@@ -1023,7 +1118,7 @@ namespace Hantek { @@ -1023,7 +1118,7 @@ namespace Hantek {
1023 /// \param index The record length index that should be set. 1118 /// \param index The record length index that should be set.
1024 /// \return The record length that has been set, 0 on error. 1119 /// \return The record length that has been set, 0 on error.
1025 unsigned int Control::setRecordLength(unsigned int index) { 1120 unsigned int Control::setRecordLength(unsigned int index) {
1026 - if(!this->device->isConnected()) 1121 + if(!this->device->isConnected())
1027 return 0; 1122 return 0;
1028 1123
1029 if(!this->updateRecordLength(index)) 1124 if(!this->updateRecordLength(index))
@@ -1052,7 +1147,7 @@ namespace Hantek { @@ -1052,7 +1147,7 @@ namespace Hantek {
1052 } 1147 }
1053 1148
1054 // When possible, enable fast rate if it is required to reach the requested samplerate 1149 // When possible, enable fast rate if it is required to reach the requested samplerate
1055 - bool fastRate = (this->settings.usedChannels <= 1) && (samplerate > this->specification.samplerate.single.max); 1150 + bool fastRate = (this->settings.usedChannels <= 1) && (samplerate > this->specification.samplerate.single.max / this->specification.bufferDividers[this->settings.recordLengthId]);
1056 1151
1057 // What is the nearest, at least as high samplerate the scope can provide? 1152 // What is the nearest, at least as high samplerate the scope can provide?
1058 unsigned int downsampler = 0; 1153 unsigned int downsampler = 0;
@@ -1085,7 +1180,7 @@ namespace Hantek { @@ -1085,7 +1180,7 @@ namespace Hantek {
1085 double maxSamplerate = (double) this->specification.samplerate.single.recordLengths[this->settings.recordLengthId] / duration; 1180 double maxSamplerate = (double) this->specification.samplerate.single.recordLengths[this->settings.recordLengthId] / duration;
1086 1181
1087 // When possible, enable fast rate if the record time can't be set that low to improve resolution 1182 // When possible, enable fast rate if the record time can't be set that low to improve resolution
1088 - bool fastRate = (this->settings.usedChannels <= 1) && (maxSamplerate >= this->specification.samplerate.multi.base); 1183 + bool fastRate = (this->settings.usedChannels <= 1) && (maxSamplerate >= this->specification.samplerate.multi.base / this->specification.bufferDividers[this->settings.recordLengthId]);
1089 1184
1090 // What is the nearest, at most as high samplerate the scope can provide? 1185 // What is the nearest, at most as high samplerate the scope can provide?
1091 unsigned int downsampler = 0; 1186 unsigned int downsampler = 0;
@@ -1162,14 +1257,8 @@ namespace Hantek { @@ -1162,14 +1257,8 @@ namespace Hantek {
1162 bool fastRateChanged = (this->settings.usedChannels <= 1) != (channelCount <= 1); 1257 bool fastRateChanged = (this->settings.usedChannels <= 1) != (channelCount <= 1);
1163 this->settings.usedChannels = channelCount; 1258 this->settings.usedChannels = channelCount;
1164 1259
1165 - if(fastRateChanged) {  
1166 - // Works only if the minimum samplerate for normal mode is lower than for fast rate mode, which is the case for all models  
1167 - ControlSamplerateLimits *limits = (channelCount <= 1) ? &this->specification.samplerate.multi : &this->specification.samplerate.single;  
1168 - emit samplerateLimitsChanged((double) this->specification.samplerate.single.base / this->specification.samplerate.single.maxDownsampler, limits->max);  
1169 -  
1170 - // Samplerate differs for fast rate mode, recalculate it  
1171 - this->restoreTargets();  
1172 - } 1260 + if(fastRateChanged)
  1261 + this->updateSamplerateLimits();
1173 1262
1174 return Dso::ERROR_NONE; 1263 return Dso::ERROR_NONE;
1175 } 1264 }
@@ -1412,6 +1501,8 @@ namespace Hantek { @@ -1412,6 +1501,8 @@ namespace Hantek {
1412 1501
1413 // All trigger positions are measured in samples 1502 // All trigger positions are measured in samples
1414 unsigned int positionSamples = position * this->settings.samplerate.current; 1503 unsigned int positionSamples = position * this->settings.samplerate.current;
  1504 + unsigned int recordLength = this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId];
  1505 + bool rollMode = recordLength == UINT_MAX;
1415 // Fast rate mode uses both channels 1506 // Fast rate mode uses both channels
1416 if(this->settings.samplerate.limits == &this->specification.samplerate.multi) 1507 if(this->settings.samplerate.limits == &this->specification.samplerate.multi)
1417 positionSamples /= HANTEK_CHANNELS; 1508 positionSamples /= HANTEK_CHANNELS;
@@ -1419,7 +1510,7 @@ namespace Hantek { @@ -1419,7 +1510,7 @@ namespace Hantek {
1419 switch(this->specification.command.bulk.setPretrigger) { 1510 switch(this->specification.command.bulk.setPretrigger) {
1420 case BULK_SETTRIGGERANDSAMPLERATE: { 1511 case BULK_SETTRIGGERANDSAMPLERATE: {
1421 // Calculate the position value (Start point depending on record length) 1512 // Calculate the position value (Start point depending on record length)
1422 - unsigned int position = 0x7ffff - this->specification.samplerate.single.recordLengths[this->settings.recordLengthId] + positionSamples; 1513 + unsigned int position = rollMode ? 0x1 : 0x7ffff - recordLength + positionSamples;
1423 1514
1424 // SetTriggerAndSamplerate bulk command for trigger position 1515 // SetTriggerAndSamplerate bulk command for trigger position
1425 static_cast<BulkSetTriggerAndSamplerate *>(this->command[BULK_SETTRIGGERANDSAMPLERATE])->setTriggerPosition(position); 1516 static_cast<BulkSetTriggerAndSamplerate *>(this->command[BULK_SETTRIGGERANDSAMPLERATE])->setTriggerPosition(position);
@@ -1429,8 +1520,8 @@ namespace Hantek { @@ -1429,8 +1520,8 @@ namespace Hantek {
1429 } 1520 }
1430 case BULK_FSETBUFFER: { 1521 case BULK_FSETBUFFER: {
1431 // Calculate the position values (Inverse, maximum is 0x7ffff) 1522 // Calculate the position values (Inverse, maximum is 0x7ffff)
1432 - unsigned int positionPre = 0x7fffful - this->specification.samplerate.single.recordLengths[this->settings.recordLengthId] + positionSamples;  
1433 - unsigned int positionPost = 0x7fffful - positionSamples; 1523 + unsigned int positionPre = 0x7ffff - recordLength + positionSamples;
  1524 + unsigned int positionPost = 0x7ffff - positionSamples;
1434 1525
1435 // SetBuffer2250 bulk command for trigger position 1526 // SetBuffer2250 bulk command for trigger position
1436 BulkSetBuffer2250 *commandSetBuffer2250 = static_cast<BulkSetBuffer2250 *>(this->command[BULK_FSETBUFFER]); 1527 BulkSetBuffer2250 *commandSetBuffer2250 = static_cast<BulkSetBuffer2250 *>(this->command[BULK_FSETBUFFER]);
@@ -1442,7 +1533,7 @@ namespace Hantek { @@ -1442,7 +1533,7 @@ namespace Hantek {
1442 } 1533 }
1443 case BULK_ESETTRIGGERORSAMPLERATE: { 1534 case BULK_ESETTRIGGERORSAMPLERATE: {
1444 // Calculate the position values (Inverse, maximum is 0xffff) 1535 // Calculate the position values (Inverse, maximum is 0xffff)
1445 - unsigned short int positionPre = 0xffff - this->specification.samplerate.single.recordLengths[this->settings.recordLengthId] + positionSamples; 1536 + unsigned short int positionPre = 0xffff - recordLength + positionSamples;
1446 unsigned short int positionPost = 0xffff - positionSamples; 1537 unsigned short int positionPost = 0xffff - positionSamples;
1447 1538
1448 // SetBuffer5200 bulk command for trigger position 1539 // SetBuffer5200 bulk command for trigger position
openhantek/src/hantek/control.h
@@ -53,6 +53,17 @@ namespace Hantek { @@ -53,6 +53,17 @@ namespace Hantek {
53 }; 53 };
54 54
55 ////////////////////////////////////////////////////////////////////////////// 55 //////////////////////////////////////////////////////////////////////////////
  56 + /// \enum RollState hantek/types.h
  57 + /// \brief The states of the roll cycle (Since capture state isn't valid).
  58 + enum RollState {
  59 + ROLL_STARTSAMPLING = 0, ///< Start sampling
  60 + ROLL_ENABLETRIGGER = 1, ///< Enable triggering
  61 + ROLL_FORCETRIGGER = 2, ///< Force triggering
  62 + ROLL_GETDATA = 3, ///< Request sample data
  63 + ROLL_COUNT
  64 + };
  65 +
  66 + //////////////////////////////////////////////////////////////////////////////
56 /// \struct ControlSpecificationCommandsBulk hantek/control.h 67 /// \struct ControlSpecificationCommandsBulk hantek/control.h
57 /// \brief Stores the bulk command codes used for this device. 68 /// \brief Stores the bulk command codes used for this device.
58 struct ControlSpecificationCommandsBulk { 69 struct ControlSpecificationCommandsBulk {
@@ -208,6 +219,7 @@ namespace Hantek { @@ -208,6 +219,7 @@ namespace Hantek {
208 unsigned int updateRecordLength(unsigned int size); 219 unsigned int updateRecordLength(unsigned int size);
209 unsigned int updateSamplerate(unsigned int downsampler, bool fastRate); 220 unsigned int updateSamplerate(unsigned int downsampler, bool fastRate);
210 void restoreTargets(); 221 void restoreTargets();
  222 + void updateSamplerateLimits();
211 223
212 // Communication with device 224 // Communication with device
213 Device *device; ///< The USB device for the oscilloscope 225 Device *device; ///< The USB device for the oscilloscope
@@ -223,8 +235,7 @@ namespace Hantek { @@ -223,8 +235,7 @@ namespace Hantek {
223 ControlSettings settings; ///< The current settings of the device 235 ControlSettings settings; ///< The current settings of the device
224 236
225 // Results 237 // Results
226 - QList<double *> samples; ///< Sample data arrays  
227 - QList<unsigned int> samplesSize; ///< Number of samples data array 238 + std::vector<std::vector<double> > samples; ///< Sample data vectors sent to the data analyzer
228 unsigned int previousSampleCount; ///< The expected total number of samples at the last check before sampling started 239 unsigned int previousSampleCount; ///< The expected total number of samples at the last check before sampling started
229 QMutex samplesMutex; ///< Mutex for the sample data 240 QMutex samplesMutex; ///< Mutex for the sample data
230 241
openhantek/src/helper.h
@@ -30,6 +30,7 @@ @@ -30,6 +30,7 @@
30 #include <cerrno> 30 #include <cerrno>
31 31
32 #include <QString> 32 #include <QString>
  33 +#include <QTime>
33 34
34 35
35 #if LIBUSB_VERSION == 0 36 #if LIBUSB_VERSION == 0
@@ -71,6 +72,13 @@ namespace Helper { @@ -71,6 +72,13 @@ namespace Helper {
71 #ifdef DEBUG 72 #ifdef DEBUG
72 QString hexDump(unsigned char *data, unsigned int length); 73 QString hexDump(unsigned char *data, unsigned int length);
73 unsigned int hexParse(const QString dump, unsigned char *data, unsigned int length); 74 unsigned int hexParse(const QString dump, unsigned char *data, unsigned int length);
  75 + inline void timestampDebug(QString text);
  76 +
  77 + /// \brief Print debug information with timestamp.
  78 + /// \param text Text that will be output via qDebug.
  79 + inline void timestampDebug(QString text) {
  80 + qDebug("%s: %s", QTime::currentTime().toString("hh:mm:ss.zzz").toAscii().constData(), text.toAscii().constData());
  81 + }
74 #endif 82 #endif
75 83
76 ////////////////////////////////////////////////////////////////////////////// 84 //////////////////////////////////////////////////////////////////////////////
openhantek/src/openhantek.cpp
@@ -276,7 +276,7 @@ void OpenHantekMainWindow::connectSignals() { @@ -276,7 +276,7 @@ void OpenHantekMainWindow::connectSignals() {
276 connect(this, SIGNAL(settingsChanged()), this, SLOT(applySettings())); 276 connect(this, SIGNAL(settingsChanged()), this, SLOT(applySettings()));
277 //connect(this->dsoWidget, SIGNAL(stopped()), this, SLOT(stopped())); 277 //connect(this->dsoWidget, SIGNAL(stopped()), this, SLOT(stopped()));
278 connect(this->dsoControl, SIGNAL(statusMessage(QString, int)), this->statusBar(), SLOT(showMessage(QString, int))); 278 connect(this->dsoControl, SIGNAL(statusMessage(QString, int)), this->statusBar(), SLOT(showMessage(QString, int)));
279 - connect(this->dsoControl, SIGNAL(samplesAvailable(const QList<double *> *, const QList<unsigned int> *, double, QMutex *)), this->dataAnalyzer, SLOT(analyze(const QList<double *> *, const QList<unsigned int> *, double, QMutex *))); 279 + connect(this->dsoControl, SIGNAL(samplesAvailable(const std::vector<std::vector<double> > *, double, bool, QMutex *)), this->dataAnalyzer, SLOT(analyze(const std::vector<std::vector<double> > *, double, bool, QMutex *)));
280 280
281 // Connect signals to DSO controller and widget 281 // Connect signals to DSO controller and widget
282 connect(this->horizontalDock, SIGNAL(samplerateChanged(double)), this, SLOT(samplerateSelected())); 282 connect(this->horizontalDock, SIGNAL(samplerateChanged(double)), this, SLOT(samplerateSelected()));
@@ -334,8 +334,10 @@ void OpenHantekMainWindow::initializeDevice() { @@ -334,8 +334,10 @@ void OpenHantekMainWindow::initializeDevice() {
334 this->timebaseSelected(); 334 this->timebaseSelected();
335 if(this->dsoControl->getAvailableRecordLengths()->isEmpty()) 335 if(this->dsoControl->getAvailableRecordLengths()->isEmpty())
336 this->dsoControl->setRecordLength(this->settings->scope.horizontal.recordLength); 336 this->dsoControl->setRecordLength(this->settings->scope.horizontal.recordLength);
337 - else  
338 - this->dsoControl->setRecordLength(this->dsoControl->getAvailableRecordLengths()->indexOf(this->settings->scope.horizontal.recordLength)); 337 + else {
  338 + int index = this->dsoControl->getAvailableRecordLengths()->indexOf(this->settings->scope.horizontal.recordLength);
  339 + this->dsoControl->setRecordLength(index < 0 ? 1 : index);
  340 + }
339 this->dsoControl->setTriggerMode(this->settings->scope.trigger.mode); 341 this->dsoControl->setTriggerMode(this->settings->scope.trigger.mode);
340 this->dsoControl->setPretriggerPosition(this->settings->scope.trigger.position * this->settings->scope.horizontal.timebase * DIVS_TIME); 342 this->dsoControl->setPretriggerPosition(this->settings->scope.trigger.position * this->settings->scope.horizontal.timebase * DIVS_TIME);
341 this->dsoControl->setTriggerSlope(this->settings->scope.trigger.slope); 343 this->dsoControl->setTriggerSlope(this->settings->scope.trigger.slope);
@@ -610,7 +612,7 @@ void OpenHantekMainWindow::updateSettings() { @@ -610,7 +612,7 @@ void OpenHantekMainWindow::updateSettings() {
610 /// \brief The oscilloscope changed the record time. 612 /// \brief The oscilloscope changed the record time.
611 /// \param duration The new record time duration in seconds. 613 /// \param duration The new record time duration in seconds.
612 void OpenHantekMainWindow::recordTimeChanged(double duration) { 614 void OpenHantekMainWindow::recordTimeChanged(double duration) {
613 - if(this->settings->scope.horizontal.samplerateSet) { 615 + if(this->settings->scope.horizontal.samplerateSet && this->settings->scope.horizontal.recordLength != UINT_MAX) {
614 // The samplerate was set, let's adapt the timebase accordingly 616 // The samplerate was set, let's adapt the timebase accordingly
615 this->settings->scope.horizontal.timebase = duration / DIVS_TIME; 617 this->settings->scope.horizontal.timebase = duration / DIVS_TIME;
616 this->horizontalDock->setTimebase(this->settings->scope.horizontal.timebase); 618 this->horizontalDock->setTimebase(this->settings->scope.horizontal.timebase);
@@ -625,7 +627,7 @@ void OpenHantekMainWindow::recordTimeChanged(double duration) { @@ -625,7 +627,7 @@ void OpenHantekMainWindow::recordTimeChanged(double duration) {
625 /// \brief The oscilloscope changed the samplerate. 627 /// \brief The oscilloscope changed the samplerate.
626 /// \param samplerate The new samplerate in samples per second. 628 /// \param samplerate The new samplerate in samples per second.
627 void OpenHantekMainWindow::samplerateChanged(double samplerate) { 629 void OpenHantekMainWindow::samplerateChanged(double samplerate) {
628 - if(!this->settings->scope.horizontal.samplerateSet) { 630 + if(!this->settings->scope.horizontal.samplerateSet && this->settings->scope.horizontal.recordLength != UINT_MAX) {
629 // The timebase was set, let's adapt the samplerate accordingly 631 // The timebase was set, let's adapt the samplerate accordingly
630 this->settings->scope.horizontal.samplerate = samplerate; 632 this->settings->scope.horizontal.samplerate = samplerate;
631 this->horizontalDock->setSamplerate(samplerate); 633 this->horizontalDock->setSamplerate(samplerate);