Commit d52c9b8280c05d6b0add84dd2005024eb25db356

Authored by oliverhaag
1 parent 8ee5d2fc

Record length and samplerate can be set

openhantek/ChangeLog
@@ -183,3 +183,12 @@ @@ -183,3 +183,12 @@
183 183
184 2012-11-21 Oliver Haag <oliver.haag@gmail.com> 184 2012-11-21 Oliver Haag <oliver.haag@gmail.com>
185 * Bugfix: DSO-2250 detection failed 185 * Bugfix: DSO-2250 detection failed
  186 +
  187 +2012-11-25 Oliver Haag <oliver.haag@gmail.com>
  188 +* Added samplerate spinbox to horizontal dock
  189 +* Moved record length selection from menu into horizontal dock
  190 +* Large rework to allow setting either samplerate or timebase
  191 +* Calculate the samplerate depending on the set parameter and the record length
  192 +* Added signals to DsoControl to update horizontal dock automatically
  193 +* Reworks in signal connections to make this work properly
  194 +* Bugfix: DSO-2250 used channels wasn't set
openhantek/roadmap.dox
@@ -17,11 +17,18 @@ Released February 9, 2011 @@ -17,11 +17,18 @@ Released February 9, 2011
17 </ul> 17 </ul>
18 18
19 \section sec_0_3 OpenHantek 0.3.0 19 \section sec_0_3 OpenHantek 0.3.0
20 -Planned Q2/Q3, 2011 20 +Planned Q1, 2013
21 <ul> 21 <ul>
22 <li>%Hantek DSO-2250 support</li> 22 <li>%Hantek DSO-2250 support</li>
23 - <li>USB hotplugging</li> 23 + <li>Proper support for different record lengths</li>
  24 + <li>Arbitrary samplerate support</li>
  25 +</ul>
  26 +
  27 +\section sec_0_4 OpenHantek 0.4.0
  28 +<ul>
24 <li>Improved zoom functionality</li> 29 <li>Improved zoom functionality</li>
  30 + <li>Self alignment routines</li>
  31 + <li>USB hotplugging</li>
25 </ul> 32 </ul>
26 33
27 **/ 34 **/
openhantek/src/dataanalyzer.cpp
@@ -139,7 +139,7 @@ void DataAnalyzer::run() { @@ -139,7 +139,7 @@ void DataAnalyzer::run() {
139 // Set sampling interval 139 // Set sampling interval
140 channelData->samples.voltage.interval = 1.0 / this->waitingDataSamplerate; 140 channelData->samples.voltage.interval = 1.0 / this->waitingDataSamplerate;
141 141
142 - unsigned int size; 142 + unsigned long int size;
143 if(channel < this->settings->scope.physicalChannels) { 143 if(channel < this->settings->scope.physicalChannels) {
144 size = this->waitingDataSize[channel]; 144 size = this->waitingDataSize[channel];
145 if(size > maxSamples) 145 if(size > maxSamples)
@@ -159,7 +159,7 @@ void DataAnalyzer::run() { @@ -159,7 +159,7 @@ void DataAnalyzer::run() {
159 if(channel < this->settings->scope.physicalChannels) { 159 if(channel < this->settings->scope.physicalChannels) {
160 // Copy the buffer of the oscilloscope into the sample buffer 160 // Copy the buffer of the oscilloscope into the sample buffer
161 if(channel < (unsigned int) this->waitingData.count()) 161 if(channel < (unsigned int) this->waitingData.count())
162 - for(unsigned int position = 0; position < this->waitingDataSize[channel]; ++position) 162 + for(unsigned long int position = 0; position < this->waitingDataSize[channel]; ++position)
163 channelData->samples.voltage.sample[position] = this->waitingData[channel][position]; 163 channelData->samples.voltage.sample[position] = this->waitingData[channel][position];
164 } 164 }
165 // Math channel 165 // Math channel
@@ -176,7 +176,7 @@ void DataAnalyzer::run() { @@ -176,7 +176,7 @@ void DataAnalyzer::run() {
176 } 176 }
177 177
178 // Calculate values and write them into the sample buffer 178 // 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) { 179 + for(unsigned long int realPosition = 0; realPosition < this->analyzedData[this->settings->scope.physicalChannels]->samples.voltage.count; ++realPosition) {
180 switch(this->settings->scope.voltage[this->settings->scope.physicalChannels].misc) { 180 switch(this->settings->scope.voltage[this->settings->scope.physicalChannels].misc) {
181 case Dso::MATHMODE_1ADD2: 181 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]; 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];
@@ -223,24 +223,24 @@ void DataAnalyzer::run() { @@ -223,24 +223,24 @@ void DataAnalyzer::run() {
223 this->window = (double *) fftw_malloc(sizeof(double) * this->lastRecordLength); 223 this->window = (double *) fftw_malloc(sizeof(double) * this->lastRecordLength);
224 } 224 }
225 225
226 - unsigned int windowEnd = this->lastRecordLength - 1; 226 + unsigned long int windowEnd = this->lastRecordLength - 1;
227 this->lastWindow = this->settings->scope.spectrumWindow; 227 this->lastWindow = this->settings->scope.spectrumWindow;
228 228
229 switch(this->settings->scope.spectrumWindow) { 229 switch(this->settings->scope.spectrumWindow) {
230 case Dso::WINDOW_HAMMING: 230 case Dso::WINDOW_HAMMING:
231 - for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) 231 + for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition)
232 *(this->window + windowPosition) = 0.54 - 0.46 * cos(2.0 * M_PI * windowPosition / windowEnd); 232 *(this->window + windowPosition) = 0.54 - 0.46 * cos(2.0 * M_PI * windowPosition / windowEnd);
233 break; 233 break;
234 case Dso::WINDOW_HANN: 234 case Dso::WINDOW_HANN:
235 - for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) 235 + for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition)
236 *(this->window + windowPosition) = 0.5 * (1.0 - cos(2.0 * M_PI * windowPosition / windowEnd)); 236 *(this->window + windowPosition) = 0.5 * (1.0 - cos(2.0 * M_PI * windowPosition / windowEnd));
237 break; 237 break;
238 case Dso::WINDOW_COSINE: 238 case Dso::WINDOW_COSINE:
239 - for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) 239 + for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition)
240 *(this->window + windowPosition) = sin(M_PI * windowPosition / windowEnd); 240 *(this->window + windowPosition) = sin(M_PI * windowPosition / windowEnd);
241 break; 241 break;
242 case Dso::WINDOW_LANCZOS: 242 case Dso::WINDOW_LANCZOS:
243 - for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) { 243 + for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) {
244 double sincParameter = (2.0 * windowPosition / windowEnd - 1.0) * M_PI; 244 double sincParameter = (2.0 * windowPosition / windowEnd - 1.0) * M_PI;
245 if(sincParameter == 0) 245 if(sincParameter == 0)
246 *(this->window + windowPosition) = 1; 246 *(this->window + windowPosition) = 1;
@@ -249,55 +249,55 @@ void DataAnalyzer::run() { @@ -249,55 +249,55 @@ void DataAnalyzer::run() {
249 } 249 }
250 break; 250 break;
251 case Dso::WINDOW_BARTLETT: 251 case Dso::WINDOW_BARTLETT:
252 - for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) 252 + for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition)
253 *(this->window + windowPosition) = 2.0 / windowEnd * (windowEnd / 2 - abs(windowPosition - windowEnd / 2)); 253 *(this->window + windowPosition) = 2.0 / windowEnd * (windowEnd / 2 - abs(windowPosition - windowEnd / 2));
254 break; 254 break;
255 case Dso::WINDOW_TRIANGULAR: 255 case Dso::WINDOW_TRIANGULAR:
256 - for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) 256 + for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition)
257 *(this->window + windowPosition) = 2.0 / this->lastRecordLength * (this->lastRecordLength / 2 - abs(windowPosition - windowEnd / 2)); 257 *(this->window + windowPosition) = 2.0 / this->lastRecordLength * (this->lastRecordLength / 2 - abs(windowPosition - windowEnd / 2));
258 break; 258 break;
259 case Dso::WINDOW_GAUSS: 259 case Dso::WINDOW_GAUSS:
260 { 260 {
261 double sigma = 0.4; 261 double sigma = 0.4;
262 - for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) 262 + for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition)
263 *(this->window + windowPosition) = exp(-0.5 * pow(((windowPosition - windowEnd / 2) / (sigma * windowEnd / 2)), 2)); 263 *(this->window + windowPosition) = exp(-0.5 * pow(((windowPosition - windowEnd / 2) / (sigma * windowEnd / 2)), 2));
264 } 264 }
265 break; 265 break;
266 case Dso::WINDOW_BARTLETTHANN: 266 case Dso::WINDOW_BARTLETTHANN:
267 - for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) 267 + for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition)
268 *(this->window + windowPosition) = 0.62 - 0.48 * abs(windowPosition / windowEnd - 0.5) - 0.38 * cos(2.0 * M_PI * windowPosition / windowEnd); 268 *(this->window + windowPosition) = 0.62 - 0.48 * abs(windowPosition / windowEnd - 0.5) - 0.38 * cos(2.0 * M_PI * windowPosition / windowEnd);
269 break; 269 break;
270 case Dso::WINDOW_BLACKMAN: 270 case Dso::WINDOW_BLACKMAN:
271 { 271 {
272 double alpha = 0.16; 272 double alpha = 0.16;
273 - for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) 273 + for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition)
274 *(this->window + windowPosition) = (1 - alpha) / 2 - 0.5 * cos(2.0 * M_PI * windowPosition / windowEnd) + alpha / 2 * cos(4.0 * M_PI * windowPosition / windowEnd); 274 *(this->window + windowPosition) = (1 - alpha) / 2 - 0.5 * cos(2.0 * M_PI * windowPosition / windowEnd) + alpha / 2 * cos(4.0 * M_PI * windowPosition / windowEnd);
275 } 275 }
276 break; 276 break;
277 //case WINDOW_KAISER: 277 //case WINDOW_KAISER:
278 // TODO 278 // TODO
279 //double alpha = 3.0; 279 //double alpha = 3.0;
280 - //for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) 280 + //for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition)
281 //*(this->window + windowPosition) = ; 281 //*(this->window + windowPosition) = ;
282 //break; 282 //break;
283 case Dso::WINDOW_NUTTALL: 283 case Dso::WINDOW_NUTTALL:
284 - for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) 284 + for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition)
285 *(this->window + windowPosition) = 0.355768 - 0.487396 * cos(2 * M_PI * windowPosition / windowEnd) + 0.144232 * cos(4 * M_PI * windowPosition / windowEnd) - 0.012604 * cos(6 * M_PI * windowPosition / windowEnd); 285 *(this->window + windowPosition) = 0.355768 - 0.487396 * cos(2 * M_PI * windowPosition / windowEnd) + 0.144232 * cos(4 * M_PI * windowPosition / windowEnd) - 0.012604 * cos(6 * M_PI * windowPosition / windowEnd);
286 break; 286 break;
287 case Dso::WINDOW_BLACKMANHARRIS: 287 case Dso::WINDOW_BLACKMANHARRIS:
288 - for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) 288 + for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition)
289 *(this->window + windowPosition) = 0.35875 - 0.48829 * cos(2 * M_PI * windowPosition / windowEnd) + 0.14128 * cos(4 * M_PI * windowPosition / windowEnd) - 0.01168 * cos(6 * M_PI * windowPosition / windowEnd); 289 *(this->window + windowPosition) = 0.35875 - 0.48829 * cos(2 * M_PI * windowPosition / windowEnd) + 0.14128 * cos(4 * M_PI * windowPosition / windowEnd) - 0.01168 * cos(6 * M_PI * windowPosition / windowEnd);
290 break; 290 break;
291 case Dso::WINDOW_BLACKMANNUTTALL: 291 case Dso::WINDOW_BLACKMANNUTTALL:
292 - for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) 292 + for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition)
293 *(this->window + windowPosition) = 0.3635819 - 0.4891775 * cos(2 * M_PI * windowPosition / windowEnd) + 0.1365995 * cos(4 * M_PI * windowPosition / windowEnd) - 0.0106411 * cos(6 * M_PI * windowPosition / windowEnd); 293 *(this->window + windowPosition) = 0.3635819 - 0.4891775 * cos(2 * M_PI * windowPosition / windowEnd) + 0.1365995 * cos(4 * M_PI * windowPosition / windowEnd) - 0.0106411 * cos(6 * M_PI * windowPosition / windowEnd);
294 break; 294 break;
295 case Dso::WINDOW_FLATTOP: 295 case Dso::WINDOW_FLATTOP:
296 - for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) 296 + for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition)
297 *(this->window + windowPosition) = 1.0 - 1.93 * cos(2 * M_PI * windowPosition / windowEnd) + 1.29 * cos(4 * M_PI * windowPosition / windowEnd) - 0.388 * cos(6 * M_PI * windowPosition / windowEnd) + 0.032 * cos(8 * M_PI * windowPosition / windowEnd); 297 *(this->window + windowPosition) = 1.0 - 1.93 * cos(2 * M_PI * windowPosition / windowEnd) + 1.29 * cos(4 * M_PI * windowPosition / windowEnd) - 0.388 * cos(6 * M_PI * windowPosition / windowEnd) + 0.032 * cos(8 * M_PI * windowPosition / windowEnd);
298 break; 298 break;
299 default: // Dso::WINDOW_RECTANGULAR 299 default: // Dso::WINDOW_RECTANGULAR
300 - for(unsigned int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition) 300 + for(unsigned long int windowPosition = 0; windowPosition < this->lastRecordLength; ++windowPosition)
301 *(this->window + windowPosition) = 1.0; 301 *(this->window + windowPosition) = 1.0;
302 } 302 }
303 } 303 }
@@ -306,7 +306,7 @@ void DataAnalyzer::run() { @@ -306,7 +306,7 @@ void DataAnalyzer::run() {
306 channelData->samples.spectrum.interval = 1.0 / channelData->samples.voltage.interval / channelData->samples.voltage.count; 306 channelData->samples.spectrum.interval = 1.0 / channelData->samples.voltage.interval / channelData->samples.voltage.count;
307 307
308 // Number of real/complex samples 308 // Number of real/complex samples
309 - unsigned int dftLength = channelData->samples.voltage.count / 2; 309 + unsigned long int dftLength = channelData->samples.voltage.count / 2;
310 310
311 // Reallocate memory for samples if the sample count has changed 311 // Reallocate memory for samples if the sample count has changed
312 if(channelData->samples.spectrum.count != dftLength) { 312 if(channelData->samples.spectrum.count != dftLength) {
@@ -318,7 +318,7 @@ void DataAnalyzer::run() { @@ -318,7 +318,7 @@ void DataAnalyzer::run() {
318 318
319 // Create sample buffer and apply window 319 // Create sample buffer and apply window
320 double *windowedValues = new double[channelData->samples.voltage.count]; 320 double *windowedValues = new double[channelData->samples.voltage.count];
321 - for(unsigned int position = 0; position < channelData->samples.voltage.count; ++position) 321 + for(unsigned long int position = 0; position < channelData->samples.voltage.count; ++position)
322 windowedValues[position] = this->window[position] * channelData->samples.voltage.sample[position]; 322 windowedValues[position] = this->window[position] * channelData->samples.voltage.sample[position];
323 323
324 // Do discrete real to half-complex transformation 324 // Do discrete real to half-complex transformation
@@ -332,7 +332,7 @@ void DataAnalyzer::run() { @@ -332,7 +332,7 @@ void DataAnalyzer::run() {
332 double *conjugateComplex = windowedValues; // Reuse the windowedValues buffer 332 double *conjugateComplex = windowedValues; // Reuse the windowedValues buffer
333 333
334 // Real values 334 // Real values
335 - unsigned int position; 335 + unsigned long int position;
336 double correctionFactor = 1.0 / dftLength / dftLength; 336 double correctionFactor = 1.0 / dftLength / dftLength;
337 conjugateComplex[0] = (channelData->samples.spectrum.sample[0] * channelData->samples.spectrum.sample[0]) * correctionFactor; 337 conjugateComplex[0] = (channelData->samples.spectrum.sample[0] * channelData->samples.spectrum.sample[0]) * correctionFactor;
338 for(position = 1; position < dftLength; ++position) 338 for(position = 1; position < dftLength; ++position)
@@ -353,7 +353,7 @@ void DataAnalyzer::run() { @@ -353,7 +353,7 @@ void DataAnalyzer::run() {
353 double minimalVoltage, maximalVoltage; 353 double minimalVoltage, maximalVoltage;
354 minimalVoltage = maximalVoltage = channelData->samples.voltage.sample[0]; 354 minimalVoltage = maximalVoltage = channelData->samples.voltage.sample[0];
355 355
356 - for(unsigned int position = 1; position < channelData->samples.voltage.count; ++position) { 356 + for(unsigned long int position = 1; position < channelData->samples.voltage.count; ++position) {
357 if(channelData->samples.voltage.sample[position] < minimalVoltage) 357 if(channelData->samples.voltage.sample[position] < minimalVoltage)
358 minimalVoltage = channelData->samples.voltage.sample[position]; 358 minimalVoltage = channelData->samples.voltage.sample[position];
359 else if(channelData->samples.voltage.sample[position] > maximalVoltage) 359 else if(channelData->samples.voltage.sample[position] > maximalVoltage)
@@ -365,9 +365,9 @@ void DataAnalyzer::run() { @@ -365,9 +365,9 @@ void DataAnalyzer::run() {
365 // Get the frequency from the correlation results 365 // Get the frequency from the correlation results
366 double minimumCorrelation = correlation[0]; 366 double minimumCorrelation = correlation[0];
367 double peakCorrelation = 0; 367 double peakCorrelation = 0;
368 - unsigned int peakPosition = 0; 368 + unsigned long int peakPosition = 0;
369 369
370 - for(unsigned int position = 1; position < channelData->samples.voltage.count / 2; ++position) { 370 + for(unsigned long int position = 1; position < channelData->samples.voltage.count / 2; ++position) {
371 if(correlation[position] > peakCorrelation && correlation[position] > minimumCorrelation * 2) { 371 if(correlation[position] > peakCorrelation && correlation[position] > minimumCorrelation * 2) {
372 peakCorrelation = correlation[position]; 372 peakCorrelation = correlation[position];
373 peakPosition = position; 373 peakPosition = position;
@@ -388,7 +388,7 @@ void DataAnalyzer::run() { @@ -388,7 +388,7 @@ void DataAnalyzer::run() {
388 // Convert values into dB (Relative to the reference level) 388 // Convert values into dB (Relative to the reference level)
389 double offset = 60 - this->settings->scope.spectrumReference - 20 * log10(dftLength); 389 double offset = 60 - this->settings->scope.spectrumReference - 20 * log10(dftLength);
390 double offsetLimit = this->settings->scope.spectrumLimit - this->settings->scope.spectrumReference; 390 double offsetLimit = this->settings->scope.spectrumLimit - this->settings->scope.spectrumReference;
391 - for(unsigned int position = 0; position < channelData->samples.spectrum.count; ++position) { 391 + for(unsigned long int position = 0; position < channelData->samples.spectrum.count; ++position) {
392 channelData->samples.spectrum.sample[position] = 20 * log10(fabs(channelData->samples.spectrum.sample[position])) + offset; 392 channelData->samples.spectrum.sample[position] = 20 * log10(fabs(channelData->samples.spectrum.sample[position])) + offset;
393 393
394 // Check if this value has to be limited 394 // Check if this value has to be limited
@@ -417,7 +417,7 @@ void DataAnalyzer::run() { @@ -417,7 +417,7 @@ void DataAnalyzer::run() {
417 /// \param size The sizes of the data arrays. 417 /// \param size The sizes of the data arrays.
418 /// \param samplerate The samplerate for all input data. 418 /// \param samplerate The samplerate for all input data.
419 /// \param mutex The mutex for all input data. 419 /// \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) { 420 +void DataAnalyzer::analyze(const QList<double *> *data, const QList<unsigned long int> *size, double samplerate, QMutex *mutex) {
421 // Previous analysis still running, drop the new data 421 // Previous analysis still running, drop the new data
422 if(this->isRunning()) 422 if(this->isRunning())
423 return; 423 return;
openhantek/src/dataanalyzer.h
@@ -95,15 +95,15 @@ class DataAnalyzer : public QThread { @@ -95,15 +95,15 @@ class DataAnalyzer : public QThread {
95 double *window; ///< The array for the dft window factors 95 double *window; ///< The array for the dft window factors
96 96
97 QList<double *> waitingData; ///< Pointer to input data from device 97 QList<double *> waitingData; ///< Pointer to input data from device
98 - QList<unsigned int> waitingDataSize; ///< Number of input data samples 98 + QList<unsigned long int> waitingDataSize; ///< Number of input data samples
99 double waitingDataSamplerate; ///< The samplerate of the input data 99 double waitingDataSamplerate; ///< The samplerate of the input data
100 QMutex *waitingDataMutex; ///< A mutex for the input data 100 QMutex *waitingDataMutex; ///< A mutex for the input data
101 101
102 public slots: 102 public slots:
103 - void analyze(const QList<double *> *data, const QList<unsigned int> *size, double samplerate, QMutex *mutex); 103 + void analyze(const QList<double *> *data, const QList<unsigned long int> *size, double samplerate, QMutex *mutex);
104 104
105 signals: 105 signals:
106 - void analyzed(unsigned int samples); ///< The data with that much samples has been analyzed 106 + void analyzed(unsigned long samples); ///< The data with that much samples has been analyzed
107 }; 107 };
108 108
109 #endif 109 #endif
openhantek/src/dockwindows.cpp
@@ -46,20 +46,29 @@ HorizontalDock::HorizontalDock(DsoSettings *settings, QWidget *parent, Qt::Windo @@ -46,20 +46,29 @@ HorizontalDock::HorizontalDock(DsoSettings *settings, QWidget *parent, Qt::Windo
46 this->settings = settings; 46 this->settings = settings;
47 47
48 // Initialize elements 48 // Initialize elements
  49 + this->samplerateLabel = new QLabel(tr("Samplerate"));
  50 + this->samplerateSiSpinBox = new SiSpinBox(Helper::UNIT_SAMPLES);
  51 + this->samplerateSiSpinBox->setMinimum(1);
  52 + this->samplerateSiSpinBox->setMaximum(1e8);
  53 + this->samplerateSiSpinBox->setUnitPostfix("/s");
  54 +
  55 + QList<double> timebaseSteps;
  56 + timebaseSteps << 1.0 << 2.0 << 4.0 << 10.0;
  57 +
49 this->timebaseLabel = new QLabel(tr("Timebase")); 58 this->timebaseLabel = new QLabel(tr("Timebase"));
50 this->timebaseSiSpinBox = new SiSpinBox(Helper::UNIT_SECONDS); 59 this->timebaseSiSpinBox = new SiSpinBox(Helper::UNIT_SECONDS);
  60 + this->timebaseSiSpinBox->setSteps(timebaseSteps);
51 this->timebaseSiSpinBox->setMinimum(1e-9); 61 this->timebaseSiSpinBox->setMinimum(1e-9);
52 this->timebaseSiSpinBox->setMaximum(3.6e3); 62 this->timebaseSiSpinBox->setMaximum(3.6e3);
53 63
54 - QList<double> frequencybaseSteps;  
55 - frequencybaseSteps << 1.0 << 2.0 << 5.0 << 10.0;  
56 -  
57 this->frequencybaseLabel = new QLabel(tr("Frequencybase")); 64 this->frequencybaseLabel = new QLabel(tr("Frequencybase"));
58 this->frequencybaseSiSpinBox = new SiSpinBox(Helper::UNIT_HERTZ); 65 this->frequencybaseSiSpinBox = new SiSpinBox(Helper::UNIT_HERTZ);
59 - this->frequencybaseSiSpinBox->setSteps(frequencybaseSteps);  
60 this->frequencybaseSiSpinBox->setMinimum(1.0); 66 this->frequencybaseSiSpinBox->setMinimum(1.0);
61 this->frequencybaseSiSpinBox->setMaximum(100e6); 67 this->frequencybaseSiSpinBox->setMaximum(100e6);
62 68
  69 + this->recordLengthLabel = new QLabel(tr("Record length"));
  70 + this->recordLengthComboBox = new QComboBox();
  71 +
63 this->formatLabel = new QLabel(tr("Format")); 72 this->formatLabel = new QLabel(tr("Format"));
64 this->formatComboBox = new QComboBox(); 73 this->formatComboBox = new QComboBox();
65 for(int format = Dso::GRAPHFORMAT_TY; format < Dso::GRAPHFORMAT_COUNT; ++format) 74 for(int format = Dso::GRAPHFORMAT_TY; format < Dso::GRAPHFORMAT_COUNT; ++format)
@@ -68,12 +77,16 @@ HorizontalDock::HorizontalDock(DsoSettings *settings, QWidget *parent, Qt::Windo @@ -68,12 +77,16 @@ HorizontalDock::HorizontalDock(DsoSettings *settings, QWidget *parent, Qt::Windo
68 this->dockLayout = new QGridLayout(); 77 this->dockLayout = new QGridLayout();
69 this->dockLayout->setColumnMinimumWidth(0, 64); 78 this->dockLayout->setColumnMinimumWidth(0, 64);
70 this->dockLayout->setColumnStretch(1, 1); 79 this->dockLayout->setColumnStretch(1, 1);
71 - this->dockLayout->addWidget(this->timebaseLabel, 0, 0);  
72 - this->dockLayout->addWidget(this->timebaseSiSpinBox, 0, 1);  
73 - this->dockLayout->addWidget(this->frequencybaseLabel, 1, 0);  
74 - this->dockLayout->addWidget(this->frequencybaseSiSpinBox, 1, 1);  
75 - this->dockLayout->addWidget(this->formatLabel, 2, 0);  
76 - this->dockLayout->addWidget(this->formatComboBox, 2, 1); 80 + this->dockLayout->addWidget(this->samplerateLabel, 0, 0);
  81 + this->dockLayout->addWidget(this->samplerateSiSpinBox, 0, 1);
  82 + this->dockLayout->addWidget(this->timebaseLabel, 1, 0);
  83 + this->dockLayout->addWidget(this->timebaseSiSpinBox, 1, 1);
  84 + this->dockLayout->addWidget(this->frequencybaseLabel, 2, 0);
  85 + this->dockLayout->addWidget(this->frequencybaseSiSpinBox, 2, 1);
  86 + this->dockLayout->addWidget(this->recordLengthLabel, 3, 0);
  87 + this->dockLayout->addWidget(this->recordLengthComboBox, 3, 1);
  88 + this->dockLayout->addWidget(this->formatLabel, 4, 0);
  89 + this->dockLayout->addWidget(this->formatComboBox, 4, 1);
77 90
78 this->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); 91 this->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
79 92
@@ -82,13 +95,17 @@ HorizontalDock::HorizontalDock(DsoSettings *settings, QWidget *parent, Qt::Windo @@ -82,13 +95,17 @@ HorizontalDock::HorizontalDock(DsoSettings *settings, QWidget *parent, Qt::Windo
82 this->setWidget(this->dockWidget); 95 this->setWidget(this->dockWidget);
83 96
84 // Connect signals and slots 97 // Connect signals and slots
85 - connect(this->frequencybaseSiSpinBox, SIGNAL(valueChanged(double)), this, SLOT(frequencybaseSelected(double))); 98 + connect(this->samplerateSiSpinBox, SIGNAL(valueChanged(double)), this, SLOT(samplerateSelected(double)));
86 connect(this->timebaseSiSpinBox, SIGNAL(valueChanged(double)), this, SLOT(timebaseSelected(double))); 99 connect(this->timebaseSiSpinBox, SIGNAL(valueChanged(double)), this, SLOT(timebaseSelected(double)));
  100 + connect(this->frequencybaseSiSpinBox, SIGNAL(valueChanged(double)), this, SLOT(frequencybaseSelected(double)));
  101 + connect(this->recordLengthComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(recordLengthSelected(int)));
87 connect(this->formatComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(formatSelected(int))); 102 connect(this->formatComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(formatSelected(int)));
88 103
89 // Set values 104 // Set values
  105 + this->setSamplerate(this->settings->scope.horizontal.samplerate);
90 this->setTimebase(this->settings->scope.horizontal.timebase); 106 this->setTimebase(this->settings->scope.horizontal.timebase);
91 this->setFrequencybase(this->settings->scope.horizontal.frequencybase); 107 this->setFrequencybase(this->settings->scope.horizontal.frequencybase);
  108 + this->setRecordLength(this->settings->scope.horizontal.recordLength);
92 this->setFormat(this->settings->scope.horizontal.format); 109 this->setFormat(this->settings->scope.horizontal.format);
93 } 110 }
94 111
@@ -104,16 +121,40 @@ void HorizontalDock::closeEvent(QCloseEvent *event) { @@ -104,16 +121,40 @@ void HorizontalDock::closeEvent(QCloseEvent *event) {
104 event->accept(); 121 event->accept();
105 } 122 }
106 123
107 -/// \brief Changes the frequencybase if the new value is supported. 124 +/// \brief Changes the frequencybase.
108 /// \param frequencybase The frequencybase in hertz. 125 /// \param frequencybase The frequencybase in hertz.
109 void HorizontalDock::setFrequencybase(double frequencybase) { 126 void HorizontalDock::setFrequencybase(double frequencybase) {
  127 + this->suppressSignals = true;
110 this->frequencybaseSiSpinBox->setValue(frequencybase); 128 this->frequencybaseSiSpinBox->setValue(frequencybase);
  129 + this->suppressSignals = false;
111 } 130 }
112 131
113 -/// \brief Changes the timebase if the new value is supported. 132 +/// \brief Changes the samplerate.
  133 +/// \param samplerate The samplerate in seconds.
  134 +void HorizontalDock::setSamplerate(double samplerate) {
  135 + this->suppressSignals = true;
  136 + this->samplerateSiSpinBox->setValue(samplerate);
  137 + this->suppressSignals = false;
  138 +}
  139 +
  140 +/// \brief Changes the timebase.
114 /// \param timebase The timebase in seconds. 141 /// \param timebase The timebase in seconds.
115 void HorizontalDock::setTimebase(double timebase) { 142 void HorizontalDock::setTimebase(double timebase) {
  143 + this->suppressSignals = true;
116 this->timebaseSiSpinBox->setValue(timebase); 144 this->timebaseSiSpinBox->setValue(timebase);
  145 + this->suppressSignals = false;
  146 +}
  147 +
  148 +/// \brief Changes the record length if the new value is supported.
  149 +/// \param recordLength The record length in samples.
  150 +void HorizontalDock::setRecordLength(unsigned long int recordLength) {
  151 + int index = this->recordLengthComboBox->findData((uint) recordLength); // QVariant doesn't take unsigned long int, doesn't matter for 32 bit platforms at least
  152 +
  153 + if(index != -1) {
  154 + this->suppressSignals = true;
  155 + this->recordLengthComboBox->setCurrentIndex(index);
  156 + this->suppressSignals = false;
  157 + }
117 } 158 }
118 159
119 /// \brief Changes the format if the new value is supported. 160 /// \brief Changes the format if the new value is supported.
@@ -121,32 +162,96 @@ void HorizontalDock::setTimebase(double timebase) { @@ -121,32 +162,96 @@ void HorizontalDock::setTimebase(double timebase) {
121 /// \return Index of format-value, -1 on error. 162 /// \return Index of format-value, -1 on error.
122 int HorizontalDock::setFormat(Dso::GraphFormat format) { 163 int HorizontalDock::setFormat(Dso::GraphFormat format) {
123 if(format >= Dso::GRAPHFORMAT_TY && format <= Dso::GRAPHFORMAT_XY) { 164 if(format >= Dso::GRAPHFORMAT_TY && format <= Dso::GRAPHFORMAT_XY) {
  165 + this->suppressSignals = true;
124 this->formatComboBox->setCurrentIndex(format); 166 this->formatComboBox->setCurrentIndex(format);
  167 + this->suppressSignals = false;
125 return format; 168 return format;
126 } 169 }
127 170
128 return -1; 171 return -1;
129 } 172 }
130 173
131 -/// \brief Called when the frequencybase combo box changes it's value. 174 +/// \brief Updates the available record lengths in the combo box.
  175 +/// \param recordLengths The available record lengths for the combo box.
  176 +void HorizontalDock::availableRecordLengthsChanged(const QList<unsigned long int> &recordLengths) {
  177 + /// \todo Empty lists should be interpreted as scope supporting continuous record length values.
  178 + this->recordLengthComboBox->blockSignals(true); // Avoid messing up the settings
  179 + this->recordLengthComboBox->setUpdatesEnabled(false);
  180 +
  181 + // Update existing elements to avoid unnecessary index updates
  182 + int index = 0;
  183 + for(; index < recordLengths.size(); ++index) {
  184 + unsigned long int recordLengthItem = recordLengths[index];
  185 + if(index < this->recordLengthComboBox->count()) {
  186 + this->recordLengthComboBox->setItemData(index, (unsigned int) recordLengthItem);
  187 + this->recordLengthComboBox->setItemText(index, recordLengthItem == ULONG_MAX ? tr("Roll") : Helper::valueToString(recordLengthItem, Helper::UNIT_SAMPLES, 3));
  188 + }
  189 + else {
  190 + this->recordLengthComboBox->addItem(recordLengthItem == ULONG_MAX ? tr("Roll") : Helper::valueToString(recordLengthItem, Helper::UNIT_SAMPLES, 3), (uint) recordLengthItem);
  191 + }
  192 + }
  193 + // Remove extra elements
  194 + for(int extraIndex = this->recordLengthComboBox->count() - 1; extraIndex > index; --extraIndex) {
  195 + this->recordLengthComboBox->removeItem(extraIndex);
  196 + }
  197 +
  198 + this->setRecordLength(this->settings->scope.horizontal.recordLength);
  199 + this->recordLengthComboBox->setUpdatesEnabled(true);
  200 + this->recordLengthComboBox->blockSignals(false);
  201 +}
  202 +
  203 +/// \brief Updates the minimum and maximum of the samplerate spin box.
  204 +/// \param minimum The minimum value the spin box should accept.
  205 +/// \param maximum The minimum value the spin box should accept.
  206 +void HorizontalDock::samplerateLimitsChanged(double minimum, double maximum) {
  207 + this->suppressSignals = true;
  208 + this->samplerateSiSpinBox->setMinimum(minimum);
  209 + this->samplerateSiSpinBox->setMaximum(maximum);
  210 + this->suppressSignals = false;
  211 +}
  212 +
  213 +/// \brief Called when the frequencybase spinbox changes its value.
132 /// \param frequencybase The frequencybase in hertz. 214 /// \param frequencybase The frequencybase in hertz.
133 void HorizontalDock::frequencybaseSelected(double frequencybase) { 215 void HorizontalDock::frequencybaseSelected(double frequencybase) {
134 this->settings->scope.horizontal.frequencybase = frequencybase; 216 this->settings->scope.horizontal.frequencybase = frequencybase;
135 - emit frequencybaseChanged(frequencybase); 217 + if(!this->suppressSignals)
  218 + emit frequencybaseChanged(frequencybase);
136 } 219 }
137 220
138 -/// \brief Called when the timebase combo box changes it's value. 221 +/// \brief Called when the samplerate spinbox changes its value.
  222 +/// \param samplerate The samplerate in samples/second.
  223 +void HorizontalDock::samplerateSelected(double samplerate) {
  224 + this->settings->scope.horizontal.samplerate = samplerate;
  225 + if(!this->suppressSignals) {
  226 + this->settings->scope.horizontal.samplerateSet = true;
  227 + emit samplerateChanged(samplerate);
  228 + }
  229 +}
  230 +
  231 +/// \brief Called when the timebase spinbox changes its value.
139 /// \param timebase The timebase in seconds. 232 /// \param timebase The timebase in seconds.
140 void HorizontalDock::timebaseSelected(double timebase) { 233 void HorizontalDock::timebaseSelected(double timebase) {
141 this->settings->scope.horizontal.timebase = timebase; 234 this->settings->scope.horizontal.timebase = timebase;
142 - emit timebaseChanged(timebase); 235 + if(!this->suppressSignals) {
  236 + this->settings->scope.horizontal.samplerateSet = false;
  237 + emit timebaseChanged(timebase);
  238 + }
  239 +}
  240 +
  241 +/// \brief Called when the record length combo box changes its value.
  242 +/// \param index The index of the combo box item.
  243 +void HorizontalDock::recordLengthSelected(int index) {
  244 + this->settings->scope.horizontal.recordLength = this->recordLengthComboBox->itemData(index).toUInt();
  245 + if(!this->suppressSignals)
  246 + emit recordLengthChanged(index);
143 } 247 }
144 248
145 -/// \brief Called when the format combo box changes it's value. 249 +/// \brief Called when the format combo box changes its value.
146 /// \param index The index of the combo box item. 250 /// \param index The index of the combo box item.
147 void HorizontalDock::formatSelected(int index) { 251 void HorizontalDock::formatSelected(int index) {
148 this->settings->scope.horizontal.format = (Dso::GraphFormat) index; 252 this->settings->scope.horizontal.format = (Dso::GraphFormat) index;
149 - emit formatChanged(this->settings->scope.horizontal.format); 253 + if(!this->suppressSignals)
  254 + emit formatChanged(this->settings->scope.horizontal.format);
150 } 255 }
151 256
152 257
openhantek/src/dockwindows.h
@@ -54,7 +54,9 @@ class HorizontalDock : public QDockWidget { @@ -54,7 +54,9 @@ class HorizontalDock : public QDockWidget {
54 ~HorizontalDock(); 54 ~HorizontalDock();
55 55
56 void setFrequencybase(double timebase); 56 void setFrequencybase(double timebase);
  57 + void setSamplerate(double samplerate);
57 void setTimebase(double timebase); 58 void setTimebase(double timebase);
  59 + void setRecordLength(unsigned long int recordLength);
58 int setFormat(Dso::GraphFormat format); 60 int setFormat(Dso::GraphFormat format);
59 61
60 protected: 62 protected:
@@ -62,25 +64,39 @@ class HorizontalDock : public QDockWidget { @@ -62,25 +64,39 @@ class HorizontalDock : public QDockWidget {
62 64
63 QGridLayout *dockLayout; ///< The main layout for the dock window 65 QGridLayout *dockLayout; ///< The main layout for the dock window
64 QWidget *dockWidget; ///< The main widget for the dock window 66 QWidget *dockWidget; ///< The main widget for the dock window
65 - QLabel *timebaseLabel; ///< The label for the timebase combobox  
66 - QLabel *frequencybaseLabel; ///< The label for the frequencybase combobox 67 + QLabel *samplerateLabel; ///< The label for the samplerate spinbox
  68 + QLabel *timebaseLabel; ///< The label for the timebase spinbox
  69 + QLabel *frequencybaseLabel; ///< The label for the frequencybase spinbox
  70 + QLabel *recordLengthLabel; ///< The label for the record length combobox
67 QLabel *formatLabel; ///< The label for the format combobox 71 QLabel *formatLabel; ///< The label for the format combobox
  72 + SiSpinBox *samplerateSiSpinBox; ///< Selects the samplerate for aquisitions
68 SiSpinBox *timebaseSiSpinBox; ///< Selects the timebase for voltage graphs 73 SiSpinBox *timebaseSiSpinBox; ///< Selects the timebase for voltage graphs
69 SiSpinBox *frequencybaseSiSpinBox; ///< Selects the frequencybase for spectrum graphs 74 SiSpinBox *frequencybaseSiSpinBox; ///< Selects the frequencybase for spectrum graphs
  75 + QComboBox *recordLengthComboBox; ///< Selects the record length for aquisitions
70 QComboBox *formatComboBox; ///< Selects the way the sampled data is interpreted and shown 76 QComboBox *formatComboBox; ///< Selects the way the sampled data is interpreted and shown
71 77
72 DsoSettings *settings; ///< The settings provided by the parent class 78 DsoSettings *settings; ///< The settings provided by the parent class
73 79
74 QStringList formatStrings; ///< Strings for the formats 80 QStringList formatStrings; ///< Strings for the formats
  81 +
  82 + bool suppressSignals; ///< Disable changed-signals temporarily
75 83
  84 + public slots:
  85 + void availableRecordLengthsChanged(const QList<unsigned long int> &recordLengths);
  86 + void samplerateLimitsChanged(double minimum, double maximum);
  87 +
76 protected slots: 88 protected slots:
77 void frequencybaseSelected(double frequencybase); 89 void frequencybaseSelected(double frequencybase);
  90 + void samplerateSelected(double samplerate);
78 void timebaseSelected(double timebase); 91 void timebaseSelected(double timebase);
  92 + void recordLengthSelected(int index);
79 void formatSelected(int index); 93 void formatSelected(int index);
80 94
81 signals: 95 signals:
82 void frequencybaseChanged(double frequencybase); ///< The frequencybase has been changed 96 void frequencybaseChanged(double frequencybase); ///< The frequencybase has been changed
  97 + void samplerateChanged(double samplerate); ///< The samplerate has been changed
83 void timebaseChanged(double timebase); ///< The timebase has been changed 98 void timebaseChanged(double timebase); ///< The timebase has been changed
  99 + void recordLengthChanged(unsigned long recordLength); ///< The recordd length has been changed
84 void formatChanged(Dso::GraphFormat format); ///< The viewing format has been changed 100 void formatChanged(Dso::GraphFormat format); ///< The viewing format has been changed
85 }; 101 };
86 102
openhantek/src/dsocontrol.h
@@ -47,6 +47,9 @@ class DsoControl : public QThread { @@ -47,6 +47,9 @@ class DsoControl : public QThread {
47 DsoControl(QObject *parent = 0); 47 DsoControl(QObject *parent = 0);
48 48
49 virtual unsigned int getChannelCount() = 0; ///< Get the number of channels for this oscilloscope 49 virtual unsigned int getChannelCount() = 0; ///< Get the number of channels for this oscilloscope
  50 + virtual QList<unsigned long int> *getAvailableRecordLengths() = 0; ///< Get available record lengths, empty list for continuous
  51 + virtual double getMinSamplerate() = 0; ///< The minimum samplerate supported
  52 + virtual double getMaxSamplerate() = 0; ///< The maximum samplerate supported
50 53
51 const QStringList *getSpecialTriggerSources(); 54 const QStringList *getSpecialTriggerSources();
52 55
@@ -62,7 +65,13 @@ class DsoControl : public QThread { @@ -62,7 +65,13 @@ class DsoControl : public QThread {
62 void samplingStarted(); ///< The oscilloscope started sampling/waiting for trigger 65 void samplingStarted(); ///< The oscilloscope started sampling/waiting for trigger
63 void samplingStopped(); ///< The oscilloscope stopped sampling/waiting for trigger 66 void samplingStopped(); ///< The oscilloscope stopped sampling/waiting for trigger
64 void statusMessage(const QString &message, int timeout); ///< Status message about the oscilloscope 67 void statusMessage(const QString &message, int timeout); ///< Status message about the oscilloscope
65 - void samplesAvailable(const QList<double *> *data, const QList<unsigned int> *size, double samplerate, QMutex *mutex); ///< New sample data is available 68 + void samplesAvailable(const QList<double *> *data, const QList<unsigned long int> *size, double samplerate, QMutex *mutex); ///< New sample data is available
  69 +
  70 + void recordLengthChanged(unsigned long duration); ///< The record length has changed
  71 + void recordTimeChanged(double duration); ///< The record time duration has changed
  72 + void samplerateChanged(double samplerate); ///< The samplerate has changed
  73 + void availableRecordLengthsChanged(const QList<unsigned long int> &recordLengths); ///< The available record lengths, empty list for continuous
  74 + void samplerateLimitsChanged(double minimum, double maximum); ///< The minimum or maximum samplerate has changed
66 75
67 public slots: 76 public slots:
68 virtual void connectDevice(); 77 virtual void connectDevice();
@@ -71,8 +80,9 @@ class DsoControl : public QThread { @@ -71,8 +80,9 @@ class DsoControl : public QThread {
71 virtual void startSampling(); 80 virtual void startSampling();
72 virtual void stopSampling(); 81 virtual void stopSampling();
73 82
74 - virtual unsigned long int setSamplerate(unsigned long int samplerate) = 0; ///< Set the samplerate that should be met  
75 - virtual unsigned long int setRecordLength(unsigned long int size) = 0; ///< Set the required record length 83 + virtual unsigned long int setRecordLength(unsigned long int size) = 0; ///< Set record length id, minimum for continuous
  84 + virtual double setSamplerate(double samplerate) = 0; ///< Set the samplerate that should be met
  85 + virtual double setRecordTime(double duration) = 0; ///< Set the record time duration that should be met
76 86
77 virtual int setTriggerMode(Dso::TriggerMode mode) = 0; ///< Set the trigger mode 87 virtual int setTriggerMode(Dso::TriggerMode mode) = 0; ///< Set the trigger mode
78 virtual int setTriggerSource(bool special, unsigned int id) = 0; ///< Set the trigger source 88 virtual int setTriggerSource(bool special, unsigned int id) = 0; ///< Set the trigger source
openhantek/src/dsowidget.cpp
@@ -225,9 +225,10 @@ DsoWidget::DsoWidget(DsoSettings *settings, DataAnalyzer *dataAnalyzer, QWidget @@ -225,9 +225,10 @@ DsoWidget::DsoWidget(DsoSettings *settings, DataAnalyzer *dataAnalyzer, QWidget
225 225
226 // Apply settings and update measured values 226 // Apply settings and update measured values
227 this->updateTriggerDetails(); 227 this->updateTriggerDetails();
228 - this->updateRecordLength(this->settings->scope.horizontal.samples);  
229 - this->updateFrequencybase();  
230 - this->updateTimebase(); 228 + this->updateRecordLength(this->settings->scope.horizontal.recordLength);
  229 + this->updateFrequencybase(this->settings->scope.horizontal.frequencybase);
  230 + this->updateSamplerate(this->settings->scope.horizontal.samplerate);
  231 + this->updateTimebase(this->settings->scope.horizontal.timebase);
231 this->updateZoom(this->settings->view.zoom); 232 this->updateZoom(this->settings->view.zoom);
232 233
233 // The widget itself 234 // The widget itself
@@ -245,8 +246,8 @@ DsoWidget::DsoWidget(DsoSettings *settings, DataAnalyzer *dataAnalyzer, QWidget @@ -245,8 +246,8 @@ DsoWidget::DsoWidget(DsoSettings *settings, DataAnalyzer *dataAnalyzer, QWidget
245 this->connect(this->markerSlider, SIGNAL(valueChanged(int, double)), this->zoomScope, SLOT(updateGL())); 246 this->connect(this->markerSlider, SIGNAL(valueChanged(int, double)), this->zoomScope, SLOT(updateGL()));
246 247
247 // Connect other signals 248 // Connect other signals
248 - this->connect(this->dataAnalyzer, SIGNAL(analyzed(unsigned int)), this, SLOT(dataAnalyzed()));  
249 - this->connect(this->dataAnalyzer, SIGNAL(analyzed(unsigned int)), this, SLOT(updateRecordLength(unsigned int))); 249 + this->connect(this->dataAnalyzer, SIGNAL(analyzed(unsigned long)), this, SLOT(dataAnalyzed()));
  250 + this->connect(this->dataAnalyzer, SIGNAL(analyzed(unsigned long)), this, SLOT(updateRecordLength(unsigned long)));
250 } 251 }
251 252
252 /// \brief Stops the oscilloscope thread and the timer. 253 /// \brief Stops the oscilloscope thread and the timer.
@@ -283,7 +284,7 @@ void DsoWidget::updateMarkerDetails() { @@ -283,7 +284,7 @@ void DsoWidget::updateMarkerDetails() {
283 if(this->settings->view.zoom) { 284 if(this->settings->view.zoom) {
284 this->markerInfoLabel->setText(tr("Zoom x%L1").arg(DIVS_TIME / divs, -1, 'g', 3)); 285 this->markerInfoLabel->setText(tr("Zoom x%L1").arg(DIVS_TIME / divs, -1, 'g', 3));
285 this->markerTimebaseLabel->setText(Helper::valueToString(time / DIVS_TIME, Helper::UNIT_SECONDS, 3) + tr("/div")); 286 this->markerTimebaseLabel->setText(Helper::valueToString(time / DIVS_TIME, Helper::UNIT_SECONDS, 3) + tr("/div"));
286 - this->markerFrequencybaseLabel->setText(Helper::valueToString(divs * this->settings->scope.horizontal.frequencybase / DIVS_TIME, Helper::UNIT_HERTZ, 3) + tr("/div")); 287 + this->markerFrequencybaseLabel->setText(Helper::valueToString(divs * this->settings->scope.horizontal.frequencybase / DIVS_TIME, Helper::UNIT_HERTZ, 4) + tr("/div"));
287 } 288 }
288 this->markerTimeLabel->setText(Helper::valueToString(time, Helper::UNIT_SECONDS, 4)); 289 this->markerTimeLabel->setText(Helper::valueToString(time, Helper::UNIT_SECONDS, 4));
289 this->markerFrequencyLabel->setText(Helper::valueToString(1.0 / time, Helper::UNIT_HERTZ, 4)); 290 this->markerFrequencyLabel->setText(Helper::valueToString(1.0 / time, Helper::UNIT_HERTZ, 4));
@@ -294,7 +295,7 @@ void DsoWidget::updateSpectrumDetails(unsigned int channel) { @@ -294,7 +295,7 @@ void DsoWidget::updateSpectrumDetails(unsigned int channel) {
294 this->setMeasurementVisible(channel, this->settings->scope.voltage[channel].used || this->settings->scope.spectrum[channel].used); 295 this->setMeasurementVisible(channel, this->settings->scope.voltage[channel].used || this->settings->scope.spectrum[channel].used);
295 296
296 if(this->settings->scope.spectrum[channel].used) 297 if(this->settings->scope.spectrum[channel].used)
297 - this->measurementMagnitudeLabel[channel]->setText(Helper::valueToString(this->settings->scope.spectrum[channel].magnitude, Helper::UNIT_DECIBEL, 0) + tr("/div")); 298 + this->measurementMagnitudeLabel[channel]->setText(Helper::valueToString(this->settings->scope.spectrum[channel].magnitude, Helper::UNIT_DECIBEL, 3) + tr("/div"));
298 else 299 else
299 this->measurementMagnitudeLabel[channel]->setText(QString()); 300 this->measurementMagnitudeLabel[channel]->setText(QString());
300 } 301 }
@@ -320,24 +321,27 @@ void DsoWidget::updateVoltageDetails(unsigned int channel) { @@ -320,24 +321,27 @@ void DsoWidget::updateVoltageDetails(unsigned int channel) {
320 this->setMeasurementVisible(channel, this->settings->scope.voltage[channel].used || this->settings->scope.spectrum[channel].used); 321 this->setMeasurementVisible(channel, this->settings->scope.voltage[channel].used || this->settings->scope.spectrum[channel].used);
321 322
322 if(this->settings->scope.voltage[channel].used) 323 if(this->settings->scope.voltage[channel].used)
323 - this->measurementGainLabel[channel]->setText(Helper::valueToString(this->settings->scope.voltage[channel].gain, Helper::UNIT_VOLTS, 0) + tr("/div")); 324 + this->measurementGainLabel[channel]->setText(Helper::valueToString(this->settings->scope.voltage[channel].gain, Helper::UNIT_VOLTS, 3) + tr("/div"));
324 else 325 else
325 this->measurementGainLabel[channel]->setText(QString()); 326 this->measurementGainLabel[channel]->setText(QString());
326 } 327 }
327 328
328 /// \brief Handles frequencybaseChanged signal from the horizontal dock. 329 /// \brief Handles frequencybaseChanged signal from the horizontal dock.
329 -void DsoWidget::updateFrequencybase() {  
330 - this->settingsFrequencybaseLabel->setText(Helper::valueToString(this->settings->scope.horizontal.frequencybase, Helper::UNIT_HERTZ, 0) + tr("/div")); 330 +/// \param frequencybase The frequencybase used for displaying the trace.
  331 +void DsoWidget::updateFrequencybase(double frequencybase) {
  332 + this->settingsFrequencybaseLabel->setText(Helper::valueToString(frequencybase, Helper::UNIT_HERTZ, 4) + tr("/div"));
331 } 333 }
332 334
333 /// \brief Updates the samplerate field after changing the samplerate. 335 /// \brief Updates the samplerate field after changing the samplerate.
334 -void DsoWidget::updateSamplerate() {  
335 - this->settingsSamplerateLabel->setText(Helper::valueToString(this->settings->scope.horizontal.samplerate, Helper::UNIT_SAMPLES) + tr("/s")); 336 +/// \param samplerate The samplerate set in the oscilloscope.
  337 +void DsoWidget::updateSamplerate(double samplerate) {
  338 + this->settingsSamplerateLabel->setText(Helper::valueToString(samplerate, Helper::UNIT_SAMPLES, 4) + tr("/s"));
336 } 339 }
337 340
338 /// \brief Handles timebaseChanged signal from the horizontal dock. 341 /// \brief Handles timebaseChanged signal from the horizontal dock.
339 -void DsoWidget::updateTimebase() {  
340 - this->settingsTimebaseLabel->setText(Helper::valueToString(this->settings->scope.horizontal.timebase, Helper::UNIT_SECONDS, 0) + tr("/div")); 342 +/// \param timebase The timebase used for displaying the trace.
  343 +void DsoWidget::updateTimebase(double timebase) {
  344 + this->settingsTimebaseLabel->setText(Helper::valueToString(timebase, Helper::UNIT_SECONDS, 4) + tr("/div"));
341 345
342 this->updateMarkerDetails(); 346 this->updateMarkerDetails();
343 } 347 }
@@ -425,8 +429,8 @@ void DsoWidget::updateVoltageUsed(unsigned int channel, bool used) { @@ -425,8 +429,8 @@ void DsoWidget::updateVoltageUsed(unsigned int channel, bool used) {
425 } 429 }
426 430
427 /// \brief Change the record length. 431 /// \brief Change the record length.
428 -void DsoWidget::updateRecordLength(unsigned int size) {  
429 - this->settingsRecordLengthLabel->setText(tr("%1 S").arg(size)); 432 +void DsoWidget::updateRecordLength(unsigned long size) {
  433 + this->settingsRecordLengthLabel->setText(Helper::valueToString(size, Helper::UNIT_SAMPLES, 4));
430 } 434 }
431 435
432 /// \brief Export the oscilloscope screen to a file. 436 /// \brief Export the oscilloscope screen to a file.
openhantek/src/dsowidget.h
@@ -96,9 +96,9 @@ class DsoWidget : public QWidget { @@ -96,9 +96,9 @@ class DsoWidget : public QWidget {
96 public slots: 96 public slots:
97 // Horizontal axis 97 // Horizontal axis
98 //void horizontalFormatChanged(HorizontalFormat format); 98 //void horizontalFormatChanged(HorizontalFormat format);
99 - void updateFrequencybase();  
100 - void updateSamplerate();  
101 - void updateTimebase(); 99 + void updateFrequencybase(double frequencybase);
  100 + void updateSamplerate(double samplerate);
  101 + void updateTimebase(double timebase);
102 102
103 // Trigger 103 // Trigger
104 void updateTriggerMode(); 104 void updateTriggerMode();
@@ -116,7 +116,7 @@ class DsoWidget : public QWidget { @@ -116,7 +116,7 @@ class DsoWidget : public QWidget {
116 void updateVoltageUsed(unsigned int channel, bool used); 116 void updateVoltageUsed(unsigned int channel, bool used);
117 117
118 // Menus 118 // Menus
119 - void updateRecordLength(unsigned int size); 119 + void updateRecordLength(unsigned long size);
120 120
121 // Export 121 // Export
122 bool exportAs(); 122 bool exportAs();
openhantek/src/glgenerator.cpp
@@ -86,7 +86,7 @@ GlGenerator::GlGenerator(DsoSettings *settings, QObject *parent) : QObject(paren @@ -86,7 +86,7 @@ GlGenerator::GlGenerator(DsoSettings *settings, QObject *parent) : QObject(paren
86 86
87 /// \brief Deletes OpenGL objects. 87 /// \brief Deletes OpenGL objects.
88 GlGenerator::~GlGenerator() { 88 GlGenerator::~GlGenerator() {
89 - // todo: Clean up vaChannel 89 + /// \todo Clean up vaChannel
90 } 90 }
91 91
92 /// \brief Set the data analyzer whose data will be drawn. 92 /// \brief Set the data analyzer whose data will be drawn.
openhantek/src/hantek/control.cpp
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 // 5 //
6 // Copyright (C) 2008, 2009 Oleg Khudyakov 6 // Copyright (C) 2008, 2009 Oleg Khudyakov
7 // prcoder@potrebitel.ru 7 // prcoder@potrebitel.ru
8 -// Copyright (C) 2010, 2011 Oliver Haag 8 +// Copyright (C) 2010 - 2012 Oliver Haag
9 // oliver.haag@gmail.com 9 // oliver.haag@gmail.com
10 // 10 //
11 // This program is free software: you can redistribute it and/or modify it 11 // This program is free software: you can redistribute it and/or modify it
@@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
24 //////////////////////////////////////////////////////////////////////////////// 24 ////////////////////////////////////////////////////////////////////////////////
25 25
26 26
  27 +#include <cmath>
27 #include <limits> 28 #include <limits>
28 29
29 #include <QList> 30 #include <QList>
@@ -43,7 +44,7 @@ namespace Hantek { @@ -43,7 +44,7 @@ namespace Hantek {
43 Control::Control(QObject *parent) : DsoControl(parent) { 44 Control::Control(QObject *parent) : DsoControl(parent) {
44 // Use DSO-2090 specification as default 45 // Use DSO-2090 specification as default
45 this->specification.command.bulk.setRecordLength = (BulkCode) -1; 46 this->specification.command.bulk.setRecordLength = (BulkCode) -1;
46 - this->specification.command.bulk.setFilter = (BulkCode) -1; 47 + this->specification.command.bulk.setChannels = (BulkCode) -1;
47 this->specification.command.bulk.setGain = (BulkCode) -1; 48 this->specification.command.bulk.setGain = (BulkCode) -1;
48 this->specification.command.bulk.setSamplerate = (BulkCode) -1; 49 this->specification.command.bulk.setSamplerate = (BulkCode) -1;
49 this->specification.command.bulk.setTrigger = (BulkCode) -1; 50 this->specification.command.bulk.setTrigger = (BulkCode) -1;
@@ -53,12 +54,12 @@ namespace Hantek { @@ -53,12 +54,12 @@ namespace Hantek {
53 this->specification.command.values.offsetLimits = (ControlValue) -1; 54 this->specification.command.values.offsetLimits = (ControlValue) -1;
54 this->specification.command.values.voltageLimits = (ControlValue) -1; 55 this->specification.command.values.voltageLimits = (ControlValue) -1;
55 56
56 - this->specification.recordLengths << 0;  
57 -  
58 this->specification.samplerate.single.base = 50e6; 57 this->specification.samplerate.single.base = 50e6;
59 this->specification.samplerate.single.max = 50e6; 58 this->specification.samplerate.single.max = 50e6;
  59 + this->specification.samplerate.single.recordLengths << 0;
60 this->specification.samplerate.multi.base = 100e6; 60 this->specification.samplerate.multi.base = 100e6;
61 this->specification.samplerate.multi.max = 100e6; 61 this->specification.samplerate.multi.max = 100e6;
  62 + this->specification.samplerate.multi.recordLengths << 0;
62 63
63 for(unsigned int channel = 0; channel < HANTEK_CHANNELS; ++channel) { 64 for(unsigned int channel = 0; channel < HANTEK_CHANNELS; ++channel) {
64 for(unsigned int gainId = 0; gainId < 9; ++gainId) { 65 for(unsigned int gainId = 0; gainId < 9; ++gainId) {
@@ -69,8 +70,8 @@ namespace Hantek { @@ -69,8 +70,8 @@ namespace Hantek {
69 70
70 // Set settings to default values 71 // Set settings to default values
71 this->settings.samplerate.limits = &(this->specification.samplerate.single); 72 this->settings.samplerate.limits = &(this->specification.samplerate.single);
72 - this->settings.samplerate.downsampling = 1;  
73 - this->settings.samplerate.current = 0.0; 73 + this->settings.samplerate.downsampler = 1;
  74 + this->settings.samplerate.current = 1e8;
74 this->settings.trigger.position = 0; 75 this->settings.trigger.position = 0;
75 this->settings.trigger.point = 0; 76 this->settings.trigger.point = 0;
76 this->settings.trigger.mode = Dso::TRIGGERMODE_NORMAL; 77 this->settings.trigger.mode = Dso::TRIGGERMODE_NORMAL;
@@ -114,6 +115,8 @@ namespace Hantek { @@ -114,6 +115,8 @@ namespace Hantek {
114 this->samplesSize.append(0); 115 this->samplesSize.append(0);
115 } 116 }
116 117
  118 + this->previousSampleCount = 0;
  119 +
117 connect(this->device, SIGNAL(disconnected()), this, SLOT(disconnectDevice())); 120 connect(this->device, SIGNAL(disconnected()), this, SLOT(disconnectDevice()));
118 } 121 }
119 122
@@ -134,6 +137,25 @@ namespace Hantek { @@ -134,6 +137,25 @@ namespace Hantek {
134 return HANTEK_CHANNELS; 137 return HANTEK_CHANNELS;
135 } 138 }
136 139
  140 + /// \brief Get available record lengths for this oscilloscope.
  141 + /// \return The number of physical channels, empty list for continuous.
  142 + QList<unsigned long int> *Control::getAvailableRecordLengths() {
  143 + return &this->settings.samplerate.limits->recordLengths;
  144 + }
  145 +
  146 + /// \brief Get minimum samplerate for this oscilloscope.
  147 + /// \return The minimum samplerate for the current configuration in S/s.
  148 + double Control::getMinSamplerate() {
  149 + return (double) this->specification.samplerate.single.base / this->specification.samplerate.single.maxDownsampler;
  150 + }
  151 +
  152 + /// \brief Get maximum samplerate for this oscilloscope.
  153 + /// \return The maximum samplerate for the current configuration in S/s.
  154 + double Control::getMaxSamplerate() {
  155 + ControlSamplerateLimits *limits = (this->settings.usedChannels <= 1) ? &this->specification.samplerate.multi : &this->specification.samplerate.single;
  156 + return limits->max;
  157 + }
  158 +
137 /// \brief Handles all USB things until the device gets disconnected. 159 /// \brief Handles all USB things until the device gets disconnected.
138 void Control::run() { 160 void Control::run() {
139 int errorCode, cycleCounter = 0, startCycle = 0; 161 int errorCode, cycleCounter = 0, startCycle = 0;
@@ -194,7 +216,7 @@ namespace Hantek { @@ -194,7 +216,7 @@ namespace Hantek {
194 216
195 // Check the current oscilloscope state everytime 25% of the time the buffer should be refilled 217 // Check the current oscilloscope state everytime 25% of the time the buffer should be refilled
196 // Not more often than every 10 ms though 218 // Not more often than every 10 ms though
197 - int cycleTime = qMax((unsigned long int) (this->specification.recordLengths[this->settings.recordLengthId] / this->settings.samplerate.current * 250), 10lu); 219 + int cycleTime = qMax((unsigned long int) (this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] / this->settings.samplerate.current * 250), 10lu);
198 this->msleep(cycleTime); 220 this->msleep(cycleTime);
199 221
200 if(!this->sampling) { 222 if(!this->sampling) {
@@ -237,6 +259,12 @@ namespace Hantek { @@ -237,6 +259,12 @@ namespace Hantek {
237 break; 259 break;
238 260
239 case CAPTURE_WAITING: 261 case CAPTURE_WAITING:
  262 + // Sampling hasn't started, update the expected sample count
  263 + if(this->settings.samplerate.limits == &this->specification.samplerate.multi)
  264 + this->previousSampleCount = this->specification.samplerate.multi.recordLengths[this->settings.recordLengthId];
  265 + else
  266 + this->previousSampleCount = this->specification.samplerate.single.recordLengths[this->settings.recordLengthId] * HANTEK_CHANNELS;
  267 +
240 if(samplingStarted && lastTriggerMode == this->settings.trigger.mode) { 268 if(samplingStarted && lastTriggerMode == this->settings.trigger.mode) {
241 ++cycleCounter; 269 ++cycleCounter;
242 270
@@ -338,8 +366,24 @@ namespace Hantek { @@ -338,8 +366,24 @@ namespace Hantek {
338 return errorCode; 366 return errorCode;
339 367
340 // Save raw data to temporary buffer 368 // Save raw data to temporary buffer
341 - unsigned int dataCount = this->specification.recordLengths[this->settings.recordLengthId] * HANTEK_CHANNELS;  
342 - unsigned int dataLength = dataCount; 369 + bool fastRate = this->settings.samplerate.limits == &this->specification.samplerate.multi;
  370 +
  371 + unsigned long int totalSampleCount = fastRate ? this->specification.samplerate.multi.recordLengths[this->settings.recordLengthId] : this->specification.samplerate.single.recordLengths[this->settings.recordLengthId] * HANTEK_CHANNELS;
  372 +
  373 + // To make sure no samples will remain in the scope buffer, also check the sample count before the last sampling started
  374 + if(totalSampleCount < this->previousSampleCount) {
  375 + unsigned long int currentSampleCount = totalSampleCount;
  376 + totalSampleCount = this->previousSampleCount;
  377 + this->previousSampleCount = currentSampleCount; // Using sampleCount as temporary buffer since it was set to totalSampleCount
  378 + }
  379 + else {
  380 + this->previousSampleCount = totalSampleCount;
  381 + }
  382 +
  383 + unsigned long int sampleCount = totalSampleCount;
  384 + if(!fastRate)
  385 + sampleCount /= HANTEK_CHANNELS;
  386 + unsigned long int dataLength = totalSampleCount;
343 if(this->specification.sampleSize > 8) 387 if(this->specification.sampleSize > 8)
344 dataLength *= 2; 388 dataLength *= 2;
345 389
@@ -353,18 +397,19 @@ namespace Hantek { @@ -353,18 +397,19 @@ namespace Hantek {
353 // How much data did we really receive? 397 // How much data did we really receive?
354 dataLength = errorCode; 398 dataLength = errorCode;
355 if(this->specification.sampleSize > 8) 399 if(this->specification.sampleSize > 8)
356 - dataCount = dataLength / 2; 400 + totalSampleCount = dataLength / 2;
357 else 401 else
358 - dataCount = dataLength; 402 + totalSampleCount = dataLength;
359 403
360 this->samplesMutex.lock(); 404 this->samplesMutex.lock();
361 405
362 // Convert channel data 406 // Convert channel data
363 - if(this->settings.samplerate.limits == &this->specification.samplerate.multi) { 407 + if(fastRate) {
364 // Fast rate mode, one channel is using all buffers 408 // Fast rate mode, one channel is using all buffers
  409 + sampleCount = totalSampleCount;
365 int channel = 0; 410 int channel = 0;
366 for(; channel < HANTEK_CHANNELS; ++channel) { 411 for(; channel < HANTEK_CHANNELS; ++channel) {
367 - if(this->settings.voltage[0].used) 412 + if(this->settings.voltage[channel].used)
368 break; 413 break;
369 } 414 }
370 415
@@ -378,34 +423,34 @@ namespace Hantek { @@ -378,34 +423,34 @@ namespace Hantek {
378 423
379 if(channel < HANTEK_CHANNELS) { 424 if(channel < HANTEK_CHANNELS) {
380 // Reallocate memory for samples if the sample count has changed 425 // Reallocate memory for samples if the sample count has changed
381 - if(!this->samples[channel] || this->samplesSize[channel] != dataCount) { 426 + if(!this->samples[channel] || this->samplesSize[channel] != sampleCount) {
382 if(this->samples[channel]) 427 if(this->samples[channel])
383 delete this->samples[channel]; 428 delete this->samples[channel];
384 - this->samples[channel] = new double[dataCount];  
385 - this->samplesSize[channel] = dataCount; 429 + this->samples[channel] = new double[sampleCount];
  430 + this->samplesSize[channel] = sampleCount;
386 } 431 }
387 432
388 // Convert data from the oscilloscope and write it into the sample buffer 433 // Convert data from the oscilloscope and write it into the sample buffer
389 - unsigned int bufferPosition = (this->settings.trigger.point + 1) * 2; 434 + unsigned long int bufferPosition = this->settings.trigger.point * 2;
390 if(this->specification.sampleSize > 8) { 435 if(this->specification.sampleSize > 8) {
391 // Additional most significant bits after the normal data 436 // Additional most significant bits after the normal data
392 unsigned int extraBitsPosition; // Track the position of the extra bits in the additional byte 437 unsigned int extraBitsPosition; // Track the position of the extra bits in the additional byte
393 unsigned int extraBitsSize = this->specification.sampleSize - 8; // Number of extra bits 438 unsigned int extraBitsSize = this->specification.sampleSize - 8; // Number of extra bits
394 unsigned short int extraBitsMask = (0x00ff << extraBitsSize) & 0xff00; // Mask for extra bits extraction 439 unsigned short int extraBitsMask = (0x00ff << extraBitsSize) & 0xff00; // Mask for extra bits extraction
395 440
396 - for(unsigned int realPosition = 0; realPosition < dataCount; ++realPosition, ++bufferPosition) {  
397 - if(bufferPosition >= dataCount)  
398 - bufferPosition %= dataCount; 441 + for(unsigned long int realPosition = 0; realPosition < sampleCount; ++realPosition, ++bufferPosition) {
  442 + if(bufferPosition >= sampleCount)
  443 + bufferPosition %= sampleCount;
399 444
400 extraBitsPosition = bufferPosition % HANTEK_CHANNELS; 445 extraBitsPosition = bufferPosition % HANTEK_CHANNELS;
401 446
402 - this->samples[channel][realPosition] = ((double) ((unsigned short int) data[bufferPosition] + (((unsigned short int) data[dataCount + bufferPosition - extraBitsPosition] << (8 - (HANTEK_CHANNELS - 1 - extraBitsPosition) * extraBitsSize)) & extraBitsMask)) / this->specification.voltageLimit[channel][this->settings.voltage[channel].gain] - this->settings.voltage[channel].offsetReal) * this->specification.gainSteps[this->settings.voltage[channel].gain]; 447 + this->samples[channel][realPosition] = ((double) ((unsigned short int) data[bufferPosition] + (((unsigned short int) data[sampleCount + bufferPosition - extraBitsPosition] << (8 - (HANTEK_CHANNELS - 1 - extraBitsPosition) * extraBitsSize)) & extraBitsMask)) / this->specification.voltageLimit[channel][this->settings.voltage[channel].gain] - this->settings.voltage[channel].offsetReal) * this->specification.gainSteps[this->settings.voltage[channel].gain];
403 } 448 }
404 } 449 }
405 else { 450 else {
406 - for(unsigned int realPosition = 0; realPosition < dataCount; ++realPosition, ++bufferPosition) {  
407 - if(bufferPosition >= dataCount)  
408 - bufferPosition %= dataCount; 451 + for(unsigned long int realPosition = 0; realPosition < sampleCount; ++realPosition, ++bufferPosition) {
  452 + if(bufferPosition >= sampleCount)
  453 + bufferPosition %= sampleCount;
409 454
410 this->samples[channel][realPosition] = ((double) data[bufferPosition] / this->specification.voltageLimit[channel][this->settings.voltage[channel].gain] - this->settings.voltage[channel].offsetReal) * this->specification.gainSteps[this->settings.voltage[channel].gain]; 455 this->samples[channel][realPosition] = ((double) data[bufferPosition] / this->specification.voltageLimit[channel][this->settings.voltage[channel].gain] - this->settings.voltage[channel].offsetReal) * this->specification.gainSteps[this->settings.voltage[channel].gain];
411 } 456 }
@@ -414,39 +459,39 @@ namespace Hantek { @@ -414,39 +459,39 @@ namespace Hantek {
414 } 459 }
415 else { 460 else {
416 // Normal mode, channels are using their separate buffers 461 // Normal mode, channels are using their separate buffers
417 - unsigned int channelDataCount = dataCount / HANTEK_CHANNELS;  
418 - 462 + sampleCount = totalSampleCount / HANTEK_CHANNELS;
419 for(int channel = 0; channel < HANTEK_CHANNELS; ++channel) { 463 for(int channel = 0; channel < HANTEK_CHANNELS; ++channel) {
420 if(this->settings.voltage[channel].used) { 464 if(this->settings.voltage[channel].used) {
421 // Reallocate memory for samples if the sample count has changed 465 // Reallocate memory for samples if the sample count has changed
422 - if(!this->samples[channel] || this->samplesSize[channel] != channelDataCount) { 466 + if(!this->samples[channel] || this->samplesSize[channel] != sampleCount) {
423 if(this->samples[channel]) 467 if(this->samples[channel])
424 delete this->samples[channel]; 468 delete this->samples[channel];
425 - this->samples[channel] = new double[channelDataCount];  
426 - this->samplesSize[channel] = channelDataCount; 469 + this->samples[channel] = new double[sampleCount];
  470 + this->samplesSize[channel] = sampleCount;
427 } 471 }
428 472
429 // Convert data from the oscilloscope and write it into the sample buffer 473 // Convert data from the oscilloscope and write it into the sample buffer
430 - unsigned int bufferPosition = (this->settings.trigger.point + 1) * 2; 474 + unsigned long int bufferPosition = this->settings.trigger.point * 2;
431 if(this->specification.sampleSize > 8) { 475 if(this->specification.sampleSize > 8) {
432 // Additional most significant bits after the normal data 476 // Additional most significant bits after the normal data
433 unsigned int extraBitsSize = this->specification.sampleSize - 8; // Number of extra bits 477 unsigned int extraBitsSize = this->specification.sampleSize - 8; // Number of extra bits
434 unsigned short int extraBitsMask = (0x00ff << extraBitsSize) & 0xff00; // Mask for extra bits extraction 478 unsigned short int extraBitsMask = (0x00ff << extraBitsSize) & 0xff00; // Mask for extra bits extraction
435 unsigned int extraBitsIndex = 8 - channel * 2; // Bit position offset for extra bits extraction 479 unsigned int extraBitsIndex = 8 - channel * 2; // Bit position offset for extra bits extraction
436 480
437 - for(unsigned int realPosition = 0; realPosition < channelDataCount; ++realPosition, bufferPosition += 2) {  
438 - if(bufferPosition >= dataCount)  
439 - bufferPosition %= dataCount; 481 + for(unsigned long int realPosition = 0; realPosition < sampleCount; ++realPosition, bufferPosition += HANTEK_CHANNELS) {
  482 + if(bufferPosition >= totalSampleCount)
  483 + bufferPosition %= totalSampleCount;
440 484
441 - this->samples[channel][realPosition] = ((double) ((unsigned short int) data[bufferPosition + HANTEK_CHANNELS - 1 - channel] + (((unsigned short int) data[dataCount + bufferPosition] << extraBitsIndex) & extraBitsMask)) / this->specification.voltageLimit[channel][this->settings.voltage[channel].gain] - this->settings.voltage[channel].offsetReal) * this->specification.gainSteps[this->settings.voltage[channel].gain]; 485 + this->samples[channel][realPosition] = ((double) ((unsigned short int) data[bufferPosition + HANTEK_CHANNELS - 1 - channel] + (((unsigned short int) data[totalSampleCount + bufferPosition] << extraBitsIndex) & extraBitsMask)) / this->specification.voltageLimit[channel][this->settings.voltage[channel].gain] - this->settings.voltage[channel].offsetReal) * this->specification.gainSteps[this->settings.voltage[channel].gain];
442 } 486 }
443 } 487 }
444 else { 488 else {
445 - for(unsigned int realPosition = 0; realPosition < channelDataCount; ++realPosition, bufferPosition += 2) {  
446 - if(bufferPosition >= dataCount)  
447 - bufferPosition %= dataCount; 489 + bufferPosition += HANTEK_CHANNELS - 1 - channel;
  490 + for(unsigned long int realPosition = 0; realPosition < sampleCount; ++realPosition, bufferPosition += HANTEK_CHANNELS) {
  491 + if(bufferPosition >= totalSampleCount)
  492 + bufferPosition %= totalSampleCount;
448 493
449 - this->samples[channel][realPosition] = ((double) data[bufferPosition + HANTEK_CHANNELS - 1 - channel] / this->specification.voltageLimit[channel][this->settings.voltage[channel].gain] - this->settings.voltage[channel].offsetReal) * this->specification.gainSteps[this->settings.voltage[channel].gain]; 494 + this->samples[channel][realPosition] = ((double) data[bufferPosition] / this->specification.voltageLimit[channel][this->settings.voltage[channel].gain] - this->settings.voltage[channel].offsetReal) * this->specification.gainSteps[this->settings.voltage[channel].gain];
450 } 495 }
451 } 496 }
452 } 497 }
@@ -466,29 +511,112 @@ namespace Hantek { @@ -466,29 +511,112 @@ namespace Hantek {
466 return errorCode; 511 return errorCode;
467 } 512 }
468 513
469 - /// \brief Sets the size of the sample buffer without updating dependencies.  
470 - /// \param size The record length that should be met (S).  
471 - /// \return The record length that has been set, 0 on error.  
472 - unsigned long int Control::updateRecordLength(unsigned long int size) {  
473 - // Get the record length supporting the highest samplerate while meeting the requirement  
474 - int bestSizeId = -1;  
475 - for(int sizeId = 0; sizeId < this->specification.recordLengths.count(); ++sizeId) {  
476 - if(this->specification.recordLengths[sizeId] >= size) {  
477 - // We meet the size-requirement, check if we provide the highest possible samplerate  
478 - if(bestSizeId == -1 || this->specification.recordLengths[bestSizeId] < size || this->specification.bufferDividers[sizeId] < this->specification.bufferDividers[bestSizeId])  
479 - bestSizeId = sizeId;  
480 - }  
481 - else {  
482 - // We don't meet the size-requirement, but maybe we're still the one coming closest  
483 - if(bestSizeId == -1 || this->specification.recordLengths[sizeId] > this->specification.recordLengths[bestSizeId])  
484 - bestSizeId = sizeId; 514 + /// \brief Calculated the nearest samplerate supported by the oscilloscope.
  515 + /// \param samplerate The target samplerate, that should be met as good as possible.
  516 + /// \param fastRate true, if the fast rate mode is enabled.
  517 + /// \param maximum The target samplerate is the maximum allowed when true, the minimum otherwise.
  518 + /// \param downsampler Pointer to where the selected downsampling factor should be written.
  519 + /// \return The nearest samplerate supported, 0.0 on error.
  520 + double Control::getBestSamplerate(double samplerate, bool fastRate, bool maximum, unsigned long int *downsampler) {
  521 + // Abort if the input value is invalid
  522 + if(samplerate <= 0.0)
  523 + return 0.0;
  524 +
  525 + double bestSamplerate = 0.0;
  526 +
  527 + // Get samplerate specifications for this mode and model
  528 + ControlSamplerateLimits *limits;
  529 + if(fastRate)
  530 + limits = &(this->specification.samplerate.multi);
  531 + else
  532 + limits = &(this->specification.samplerate.single);
  533 +
  534 + // Get downsampling factor that would provide the requested rate
  535 + double bestDownsampler = (double) limits->base / this->specification.bufferDividers[this->settings.recordLengthId] / samplerate;
  536 + // Base samplerate sufficient, or is the maximum better?
  537 + if(bestDownsampler < 1.0 && (samplerate <= limits->max / this->specification.bufferDividers[this->settings.recordLengthId] || !maximum)) {
  538 + bestDownsampler = 0.0;
  539 + bestSamplerate = limits->max / this->specification.bufferDividers[this->settings.recordLengthId];
  540 + }
  541 + else {
  542 + switch(this->specification.command.bulk.setSamplerate) {
  543 + case BULK_SETTRIGGERANDSAMPLERATE:
  544 + // DSO-2090 supports the downsampling factors 1, 2, 4 and 5 using valueFast or all even values above using valueSlow
  545 + if((maximum && bestDownsampler <= 5.0) || (!maximum && bestDownsampler < 6.0)) {
  546 + // valueFast is used
  547 + if(maximum) {
  548 + // The samplerate shall not be higher, so we round up
  549 + bestDownsampler = ceil(bestDownsampler);
  550 + if(bestDownsampler > 2.0) // 3 and 4 not possible with the DSO-2090
  551 + bestDownsampler = 5.0;
  552 + }
  553 + else {
  554 + // The samplerate shall not be lower, so we round down
  555 + bestDownsampler = floor(bestDownsampler);
  556 + if(bestDownsampler > 2.0 && bestDownsampler < 5.0) // 3 and 4 not possible with the DSO-2090
  557 + bestDownsampler = 2.0;
  558 + }
  559 + }
  560 + else {
  561 + // valueSlow is used
  562 + if(maximum) {
  563 + bestDownsampler = ceil(bestDownsampler / 2.0) * 2.0; // Round up to next even value
  564 + }
  565 + else {
  566 + bestDownsampler = floor(bestDownsampler / 2.0) * 2.0; // Round down to next even value
  567 + }
  568 + if(bestDownsampler > 2.0 * 0x10001) // Check for overflow
  569 + bestDownsampler = 2.0 * 0x10001;
  570 + }
  571 + break;
  572 +
  573 + case BULK_CSETTRIGGERORSAMPLERATE:
  574 + // DSO-5200 may not supports all downsampling factors, requires testing
  575 + if(maximum) {
  576 + bestDownsampler = ceil(bestDownsampler); // Round up to next integer value
  577 + }
  578 + else {
  579 + bestDownsampler = floor(bestDownsampler); // Round down to next integer value
  580 + }
  581 + break;
  582 +
  583 + case BULK_ESETTRIGGERORSAMPLERATE:
  584 + // DSO-2250 doesn't have a fast value, so it supports all downsampling factors
  585 + if(maximum) {
  586 + bestDownsampler = ceil(bestDownsampler); // Round up to next integer value
  587 + }
  588 + else {
  589 + bestDownsampler = floor(bestDownsampler); // Round down to next integer value
  590 + }
  591 + break;
  592 +
  593 + default:
  594 + return 0.0;
485 } 595 }
  596 +
  597 + // Limit maximum downsampler value to avoid overflows in the sent commands
  598 + if(bestDownsampler > limits->maxDownsampler)
  599 + bestDownsampler = limits->maxDownsampler;
  600 +
  601 + bestSamplerate = limits->base / bestDownsampler / this->specification.bufferDividers[this->settings.recordLengthId];
486 } 602 }
487 603
  604 + if(downsampler)
  605 + *downsampler = (unsigned long int) bestDownsampler;
  606 + return bestSamplerate;
  607 + }
  608 +
  609 + /// \brief Sets the size of the sample buffer without updating dependencies.
  610 + /// \param index The record length index that should be set.
  611 + /// \return The record length that has been set, 0 on error.
  612 + unsigned long int Control::updateRecordLength(unsigned long int index) {
  613 + if(index >= (unsigned long int) this->settings.samplerate.limits->recordLengths.size())
  614 + return 0;
  615 +
488 switch(this->specification.command.bulk.setRecordLength) { 616 switch(this->specification.command.bulk.setRecordLength) {
489 case BULK_SETTRIGGERANDSAMPLERATE: 617 case BULK_SETTRIGGERANDSAMPLERATE:
490 // SetTriggerAndSamplerate bulk command for record length 618 // SetTriggerAndSamplerate bulk command for record length
491 - static_cast<BulkSetTriggerAndSamplerate *>(this->command[BULK_SETTRIGGERANDSAMPLERATE])->setRecordLength(bestSizeId); 619 + static_cast<BulkSetTriggerAndSamplerate *>(this->command[BULK_SETTRIGGERANDSAMPLERATE])->setRecordLength(index);
492 this->commandPending[BULK_SETTRIGGERANDSAMPLERATE] = true; 620 this->commandPending[BULK_SETTRIGGERANDSAMPLERATE] = true;
493 621
494 break; 622 break;
@@ -498,7 +626,7 @@ namespace Hantek { @@ -498,7 +626,7 @@ namespace Hantek {
498 // Pointers to needed commands 626 // Pointers to needed commands
499 BulkSetRecordLength2250 *commandSetRecordLength2250 = static_cast<BulkSetRecordLength2250 *>(this->command[BULK_DSETBUFFER]); 627 BulkSetRecordLength2250 *commandSetRecordLength2250 = static_cast<BulkSetRecordLength2250 *>(this->command[BULK_DSETBUFFER]);
500 628
501 - commandSetRecordLength2250->setRecordLength(bestSizeId); 629 + commandSetRecordLength2250->setRecordLength(index);
502 } 630 }
503 else { 631 else {
504 // SetBuffer5200 bulk command for record length 632 // SetBuffer5200 bulk command for record length
@@ -506,7 +634,7 @@ namespace Hantek { @@ -506,7 +634,7 @@ namespace Hantek {
506 634
507 commandSetBuffer5200->setUsedPre(DTRIGGERPOSITION_ON); 635 commandSetBuffer5200->setUsedPre(DTRIGGERPOSITION_ON);
508 commandSetBuffer5200->setUsedPost(DTRIGGERPOSITION_ON); 636 commandSetBuffer5200->setUsedPost(DTRIGGERPOSITION_ON);
509 - commandSetBuffer5200->setRecordLength(bestSizeId); 637 + commandSetBuffer5200->setRecordLength(index);
510 } 638 }
511 639
512 this->commandPending[BULK_DSETBUFFER] = true; 640 this->commandPending[BULK_DSETBUFFER] = true;
@@ -517,9 +645,136 @@ namespace Hantek { @@ -517,9 +645,136 @@ namespace Hantek {
517 return 0; 645 return 0;
518 } 646 }
519 647
520 - this->settings.recordLengthId = bestSizeId; 648 + this->settings.recordLengthId = index;
  649 +
  650 + return this->settings.samplerate.limits->recordLengths[index];
  651 + }
  652 +
  653 + /// \brief Sets the samplerate based on the parameters calculated by Control::getBestSamplerate.
  654 + /// \param downsampler The downsampling factor.
  655 + /// \param fastRate true, if one channel uses all buffers.
  656 + /// \return The downsampling factor that has been set.
  657 + unsigned long int Control::updateSamplerate(unsigned long int downsampler, bool fastRate) {
  658 + // Set the calculated samplerate
  659 + switch(this->specification.command.bulk.setSamplerate) {
  660 + case BULK_SETTRIGGERANDSAMPLERATE: {
  661 + short int downsamplerValue = 0;
  662 + unsigned char samplerateId = 0;
  663 + bool downsampling = false;
  664 +
  665 + if(downsampler <= 5) {
  666 + // All dividers up to 5 are done using the special samplerate IDs
  667 + if(downsampler == 0)
  668 + samplerateId = 1;
  669 + else if(downsampler <= 2)
  670 + samplerateId = downsampler;
  671 + else { // Downsampling factors 3 and 4 are not supported
  672 + samplerateId = 3;
  673 + downsampler = 5;
  674 + downsamplerValue = 0xffff;
  675 + }
  676 + }
  677 + else {
  678 + // For any dividers above the downsampling factor can be set directly
  679 + downsampler &= ~0x0001; // Only even values possible
  680 + downsamplerValue = (short int) (0x10001 - (downsampler >> 1));
  681 +
  682 + downsampling = true;
  683 + }
  684 +
  685 + // Pointers to needed commands
  686 + BulkSetTriggerAndSamplerate *commandSetTriggerAndSamplerate = static_cast<BulkSetTriggerAndSamplerate *>(this->command[BULK_SETTRIGGERANDSAMPLERATE]);
  687 +
  688 + // Store if samplerate ID or downsampling factor is used
  689 + commandSetTriggerAndSamplerate->setDownsamplingMode(downsampling);
  690 + // Store samplerate ID
  691 + commandSetTriggerAndSamplerate->setSamplerateId(samplerateId);
  692 + // Store downsampling factor
  693 + commandSetTriggerAndSamplerate->setDownsampler(downsamplerValue);
  694 + // Set fast rate when used
  695 + commandSetTriggerAndSamplerate->setFastRate(false /*fastRate*/);
  696 +
  697 + this->commandPending[BULK_SETTRIGGERANDSAMPLERATE] = true;
  698 +
  699 + break;
  700 + }
  701 + case BULK_CSETTRIGGERORSAMPLERATE: {
  702 + // Split the resulting divider into the values understood by the device
  703 + // The fast value is kept at 4 (or 3) for slow sample rates
  704 + long int valueSlow = qMax(((long int) downsampler - 3) / 2, (long int) 0);
  705 + unsigned char valueFast = downsampler - valueSlow * 2;
  706 +
  707 + // Pointers to needed commands
  708 + BulkSetSamplerate5200 *commandSetSamplerate5200 = static_cast<BulkSetSamplerate5200 *>(this->command[BULK_CSETTRIGGERORSAMPLERATE]);
  709 + BulkSetTrigger5200 *commandSetTrigger5200 = static_cast<BulkSetTrigger5200 *>(this->command[BULK_ESETTRIGGERORSAMPLERATE]);
  710 +
  711 + // Store samplerate fast value
  712 + commandSetSamplerate5200->setSamplerateFast(4 - valueFast);
  713 + // Store samplerate slow value (two's complement)
  714 + commandSetSamplerate5200->setSamplerateSlow(valueSlow == 0 ? 0 : 0xffff - valueSlow);
  715 + // Set fast rate when used
  716 + commandSetTrigger5200->setFastRate(fastRate);
  717 +
  718 + this->commandPending[BULK_CSETTRIGGERORSAMPLERATE] = true;
  719 + this->commandPending[BULK_ESETTRIGGERORSAMPLERATE] = true;
  720 +
  721 + break;
  722 + }
  723 + case BULK_ESETTRIGGERORSAMPLERATE: {
  724 + // Pointers to needed commands
  725 + BulkSetSamplerate2250 *commandSetSamplerate2250 = static_cast<BulkSetSamplerate2250 *>(this->command[BULK_ESETTRIGGERORSAMPLERATE]);
  726 +
  727 + bool downsampling = downsampler >= 1;
  728 + // Store downsampler state value
  729 + commandSetSamplerate2250->setDownsampling(downsampling);
  730 + // Store samplerate value
  731 + commandSetSamplerate2250->setSamplerate(downsampler > 1 ? 0x10001 - downsampler : 0);
  732 + // Set fast rate when used
  733 + commandSetSamplerate2250->setFastRate(fastRate);
  734 +
  735 + this->commandPending[BULK_ESETTRIGGERORSAMPLERATE] = true;
  736 +
  737 + break;
  738 + }
  739 + default:
  740 + return ULONG_MAX;
  741 + }
  742 +
  743 + // Update settings
  744 + bool fastRateChanged = fastRate != (this->settings.samplerate.limits == &this->specification.samplerate.multi);
  745 + if(fastRateChanged) {
  746 + if(fastRate)
  747 + this->settings.samplerate.limits = &this->specification.samplerate.multi;
  748 + else
  749 + this->settings.samplerate.limits = &this->specification.samplerate.single;
  750 + }
521 751
522 - return this->specification.recordLengths[this->settings.recordLengthId]; 752 + this->settings.samplerate.downsampler = downsampler;
  753 + if(downsampler)
  754 + this->settings.samplerate.current = this->settings.samplerate.limits->base / downsampler;
  755 + else
  756 + this->settings.samplerate.current = this->settings.samplerate.limits->max;
  757 +
  758 + // Update dependencies
  759 + this->setPretriggerPosition(this->settings.trigger.position);
  760 +
  761 + // Emit signals for changed settings
  762 + if(fastRateChanged) {
  763 + emit availableRecordLengthsChanged(this->settings.samplerate.limits->recordLengths);
  764 + emit recordLengthChanged(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId]);
  765 + }
  766 + emit recordTimeChanged((double) this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] / this->settings.samplerate.current);
  767 + emit samplerateChanged(this->settings.samplerate.current);
  768 +
  769 + return downsampler;
  770 + }
  771 +
  772 + /// \brief Try to connect to the oscilloscope.
  773 + void Control::restoreTargets() {
  774 + if(this->settings.samplerate.target.samplerateSet)
  775 + this->setSamplerate();
  776 + else
  777 + this->setRecordTime();
523 } 778 }
524 779
525 /// \brief Try to connect to the oscilloscope. 780 /// \brief Try to connect to the oscilloscope.
@@ -545,7 +800,7 @@ namespace Hantek { @@ -545,7 +800,7 @@ namespace Hantek {
545 this->command[BULK_SETGAIN] = new BulkSetGain(); 800 this->command[BULK_SETGAIN] = new BulkSetGain();
546 // Initialize the command versions to the ones used on the DSO-2090 801 // Initialize the command versions to the ones used on the DSO-2090
547 this->specification.command.bulk.setRecordLength = (BulkCode) -1; 802 this->specification.command.bulk.setRecordLength = (BulkCode) -1;
548 - this->specification.command.bulk.setFilter = (BulkCode) -1; 803 + this->specification.command.bulk.setChannels = (BulkCode) -1;
549 this->specification.command.bulk.setGain = BULK_SETGAIN; 804 this->specification.command.bulk.setGain = BULK_SETGAIN;
550 this->specification.command.bulk.setSamplerate = (BulkCode) -1; 805 this->specification.command.bulk.setSamplerate = (BulkCode) -1;
551 this->specification.command.bulk.setTrigger = (BulkCode) -1; 806 this->specification.command.bulk.setTrigger = (BulkCode) -1;
@@ -563,32 +818,30 @@ namespace Hantek { @@ -563,32 +818,30 @@ namespace Hantek {
563 818
564 case MODEL_DSO2090: 819 case MODEL_DSO2090:
565 // Instantiate additional commands for the DSO-2090 820 // Instantiate additional commands for the DSO-2090
566 - this->command[BULK_SETFILTER] = new BulkSetFilter();  
567 this->command[BULK_SETTRIGGERANDSAMPLERATE] = new BulkSetTriggerAndSamplerate(); 821 this->command[BULK_SETTRIGGERANDSAMPLERATE] = new BulkSetTriggerAndSamplerate();
568 this->specification.command.bulk.setRecordLength = BULK_SETTRIGGERANDSAMPLERATE; 822 this->specification.command.bulk.setRecordLength = BULK_SETTRIGGERANDSAMPLERATE;
569 - this->specification.command.bulk.setFilter = BULK_SETFILTER; 823 + this->specification.command.bulk.setChannels = BULK_SETTRIGGERANDSAMPLERATE;
570 this->specification.command.bulk.setSamplerate = BULK_SETTRIGGERANDSAMPLERATE; 824 this->specification.command.bulk.setSamplerate = BULK_SETTRIGGERANDSAMPLERATE;
571 this->specification.command.bulk.setTrigger = BULK_SETTRIGGERANDSAMPLERATE; 825 this->specification.command.bulk.setTrigger = BULK_SETTRIGGERANDSAMPLERATE;
572 this->specification.command.bulk.setPretrigger = BULK_SETTRIGGERANDSAMPLERATE; 826 this->specification.command.bulk.setPretrigger = BULK_SETTRIGGERANDSAMPLERATE;
573 // Initialize those as pending 827 // Initialize those as pending
574 - this->commandPending[BULK_SETFILTER] = true;  
575 this->commandPending[BULK_SETTRIGGERANDSAMPLERATE] = true; 828 this->commandPending[BULK_SETTRIGGERANDSAMPLERATE] = true;
576 break; 829 break;
577 830
578 case MODEL_DSO2250: 831 case MODEL_DSO2250:
579 // Instantiate additional commands for the DSO-2250 832 // Instantiate additional commands for the DSO-2250
580 - this->command[BULK_BSETFILTER] = new BulkSetFilter2250(); 833 + this->command[BULK_BSETCHANNELS] = new BulkSetChannels2250();
581 this->command[BULK_CSETTRIGGERORSAMPLERATE] = new BulkSetTrigger2250(); 834 this->command[BULK_CSETTRIGGERORSAMPLERATE] = new BulkSetTrigger2250();
582 this->command[BULK_DSETBUFFER] = new BulkSetRecordLength2250(); 835 this->command[BULK_DSETBUFFER] = new BulkSetRecordLength2250();
583 this->command[BULK_ESETTRIGGERORSAMPLERATE] = new BulkSetSamplerate2250(); 836 this->command[BULK_ESETTRIGGERORSAMPLERATE] = new BulkSetSamplerate2250();
584 this->command[BULK_FSETBUFFER] = new BulkSetBuffer2250(); 837 this->command[BULK_FSETBUFFER] = new BulkSetBuffer2250();
585 this->specification.command.bulk.setRecordLength = BULK_DSETBUFFER; 838 this->specification.command.bulk.setRecordLength = BULK_DSETBUFFER;
586 - this->specification.command.bulk.setFilter = BULK_BSETFILTER; 839 + this->specification.command.bulk.setChannels = BULK_BSETCHANNELS;
587 this->specification.command.bulk.setSamplerate = BULK_ESETTRIGGERORSAMPLERATE; 840 this->specification.command.bulk.setSamplerate = BULK_ESETTRIGGERORSAMPLERATE;
588 this->specification.command.bulk.setTrigger = BULK_CSETTRIGGERORSAMPLERATE; 841 this->specification.command.bulk.setTrigger = BULK_CSETTRIGGERORSAMPLERATE;
589 this->specification.command.bulk.setPretrigger = BULK_FSETBUFFER; 842 this->specification.command.bulk.setPretrigger = BULK_FSETBUFFER;
590 843
591 - this->commandPending[BULK_BSETFILTER] = true; 844 + this->commandPending[BULK_BSETCHANNELS] = true;
592 this->commandPending[BULK_CSETTRIGGERORSAMPLERATE] = true; 845 this->commandPending[BULK_CSETTRIGGERORSAMPLERATE] = true;
593 this->commandPending[BULK_DSETBUFFER] = true; 846 this->commandPending[BULK_DSETBUFFER] = true;
594 this->commandPending[BULK_ESETTRIGGERORSAMPLERATE] = true; 847 this->commandPending[BULK_ESETTRIGGERORSAMPLERATE] = true;
@@ -605,6 +858,7 @@ namespace Hantek { @@ -605,6 +858,7 @@ namespace Hantek {
605 this->command[BULK_DSETBUFFER] = new BulkSetBuffer5200(); 858 this->command[BULK_DSETBUFFER] = new BulkSetBuffer5200();
606 this->command[BULK_ESETTRIGGERORSAMPLERATE] = new BulkSetTrigger5200(); 859 this->command[BULK_ESETTRIGGERORSAMPLERATE] = new BulkSetTrigger5200();
607 this->specification.command.bulk.setRecordLength = BULK_DSETBUFFER; 860 this->specification.command.bulk.setRecordLength = BULK_DSETBUFFER;
  861 + this->specification.command.bulk.setChannels = BULK_ESETTRIGGERORSAMPLERATE;
608 this->specification.command.bulk.setSamplerate = BULK_CSETTRIGGERORSAMPLERATE; 862 this->specification.command.bulk.setSamplerate = BULK_CSETTRIGGERORSAMPLERATE;
609 this->specification.command.bulk.setTrigger = BULK_ESETTRIGGERORSAMPLERATE; 863 this->specification.command.bulk.setTrigger = BULK_ESETTRIGGERORSAMPLERATE;
610 this->specification.command.bulk.setPretrigger = BULK_ESETTRIGGERORSAMPLERATE; 864 this->specification.command.bulk.setPretrigger = BULK_ESETTRIGGERORSAMPLERATE;
@@ -630,7 +884,8 @@ namespace Hantek { @@ -630,7 +884,8 @@ namespace Hantek {
630 884
631 // Maximum possible samplerate for a single channel and dividers for record lengths 885 // Maximum possible samplerate for a single channel and dividers for record lengths
632 this->specification.bufferDividers.clear(); 886 this->specification.bufferDividers.clear();
633 - this->specification.recordLengths.clear(); 887 + this->specification.samplerate.single.recordLengths.clear();
  888 + this->specification.samplerate.multi.recordLengths.clear();
634 this->specification.gainSteps.clear(); 889 this->specification.gainSteps.clear();
635 for(int channel = 0; channel < HANTEK_CHANNELS; ++channel) 890 for(int channel = 0; channel < HANTEK_CHANNELS; ++channel)
636 this->specification.voltageLimit[channel].clear(); 891 this->specification.voltageLimit[channel].clear();
@@ -640,10 +895,13 @@ namespace Hantek { @@ -640,10 +895,13 @@ namespace Hantek {
640 case MODEL_DSO5200A: 895 case MODEL_DSO5200A:
641 this->specification.samplerate.single.base = 100e6; 896 this->specification.samplerate.single.base = 100e6;
642 this->specification.samplerate.single.max = 125e6; 897 this->specification.samplerate.single.max = 125e6;
  898 + this->specification.samplerate.single.maxDownsampler = 131072;
  899 + this->specification.samplerate.single.recordLengths << ULONG_MAX << 10240 << 14336;
643 this->specification.samplerate.multi.base = 200e6; 900 this->specification.samplerate.multi.base = 200e6;
644 this->specification.samplerate.multi.max = 250e6; 901 this->specification.samplerate.multi.max = 250e6;
  902 + this->specification.samplerate.multi.maxDownsampler = 131072;
  903 + this->specification.samplerate.multi.recordLengths << ULONG_MAX << 20480 << 28672;
645 this->specification.bufferDividers << 1000 << 1 << 1; 904 this->specification.bufferDividers << 1000 << 1 << 1;
646 - this->specification.recordLengths << ULONG_MAX << 10240 << 14336;  
647 this->specification.gainSteps 905 this->specification.gainSteps
648 << 0.16 << 0.40 << 0.80 << 1.60 << 4.00 << 8.0 << 16.0 << 40.0 << 80.0; 906 << 0.16 << 0.40 << 0.80 << 1.60 << 4.00 << 8.0 << 16.0 << 40.0 << 80.0;
649 /// \todo Use calibration data to get the DSO-5200(A) sample ranges 907 /// \todo Use calibration data to get the DSO-5200(A) sample ranges
@@ -658,10 +916,13 @@ namespace Hantek { @@ -658,10 +916,13 @@ namespace Hantek {
658 case MODEL_DSO2250: 916 case MODEL_DSO2250:
659 this->specification.samplerate.single.base = 100e6; 917 this->specification.samplerate.single.base = 100e6;
660 this->specification.samplerate.single.max = 100e6; 918 this->specification.samplerate.single.max = 100e6;
  919 + this->specification.samplerate.single.maxDownsampler = 65536;
  920 + this->specification.samplerate.single.recordLengths << ULONG_MAX << 10240 << 524288;
661 this->specification.samplerate.multi.base = 200e6; 921 this->specification.samplerate.multi.base = 200e6;
662 this->specification.samplerate.multi.max = 250e6; 922 this->specification.samplerate.multi.max = 250e6;
  923 + this->specification.samplerate.multi.maxDownsampler = 65536;
  924 + this->specification.samplerate.multi.recordLengths << ULONG_MAX << 20480 << 1048576;
663 this->specification.bufferDividers << 1000 << 1 << 1; 925 this->specification.bufferDividers << 1000 << 1 << 1;
664 - this->specification.recordLengths << ULONG_MAX << 10240 << 524288;  
665 this->specification.gainSteps 926 this->specification.gainSteps
666 << 0.08 << 0.16 << 0.40 << 0.80 << 1.60 << 4.00 << 8.0 << 16.0 << 40.0; 927 << 0.08 << 0.16 << 0.40 << 0.80 << 1.60 << 4.00 << 8.0 << 16.0 << 40.0;
667 for(int channel = 0; channel < HANTEK_CHANNELS; ++channel) 928 for(int channel = 0; channel < HANTEK_CHANNELS; ++channel)
@@ -675,10 +936,13 @@ namespace Hantek { @@ -675,10 +936,13 @@ namespace Hantek {
675 case MODEL_DSO2150: 936 case MODEL_DSO2150:
676 this->specification.samplerate.single.base = 50e6; 937 this->specification.samplerate.single.base = 50e6;
677 this->specification.samplerate.single.max = 75e6; 938 this->specification.samplerate.single.max = 75e6;
  939 + this->specification.samplerate.single.maxDownsampler = 131072;
  940 + this->specification.samplerate.single.recordLengths << ULONG_MAX << 10240 << 32768;
678 this->specification.samplerate.multi.base = 100e6; 941 this->specification.samplerate.multi.base = 100e6;
679 this->specification.samplerate.multi.max = 150e6; 942 this->specification.samplerate.multi.max = 150e6;
  943 + this->specification.samplerate.multi.maxDownsampler = 131072;
  944 + this->specification.samplerate.multi.recordLengths << ULONG_MAX << 20480 << 65536;
680 this->specification.bufferDividers << 1000 << 1 << 1; 945 this->specification.bufferDividers << 1000 << 1 << 1;
681 - this->specification.recordLengths << ULONG_MAX << 10240 << 32768;  
682 this->specification.gainSteps 946 this->specification.gainSteps
683 << 0.08 << 0.16 << 0.40 << 0.80 << 1.60 << 4.00 << 8.0 << 16.0 << 40.0; 947 << 0.08 << 0.16 << 0.40 << 0.80 << 1.60 << 4.00 << 8.0 << 16.0 << 40.0;
684 for(int channel = 0; channel < HANTEK_CHANNELS; ++channel) 948 for(int channel = 0; channel < HANTEK_CHANNELS; ++channel)
@@ -692,10 +956,13 @@ namespace Hantek { @@ -692,10 +956,13 @@ namespace Hantek {
692 default: 956 default:
693 this->specification.samplerate.single.base = 50e6; 957 this->specification.samplerate.single.base = 50e6;
694 this->specification.samplerate.single.max = 50e6; 958 this->specification.samplerate.single.max = 50e6;
  959 + this->specification.samplerate.single.maxDownsampler = 131072;
  960 + this->specification.samplerate.single.recordLengths << ULONG_MAX << 10240 << 32768;
695 this->specification.samplerate.multi.base = 100e6; 961 this->specification.samplerate.multi.base = 100e6;
696 this->specification.samplerate.multi.max = 100e6; 962 this->specification.samplerate.multi.max = 100e6;
  963 + this->specification.samplerate.multi.maxDownsampler = 131072;
  964 + this->specification.samplerate.multi.recordLengths << ULONG_MAX << 20480 << 65536;
697 this->specification.bufferDividers << 1000 << 1 << 1; 965 this->specification.bufferDividers << 1000 << 1 << 1;
698 - this->specification.recordLengths << ULONG_MAX << 10240 << 32768;  
699 this->specification.gainSteps 966 this->specification.gainSteps
700 << 0.08 << 0.16 << 0.40 << 0.80 << 1.60 << 4.00 << 8.0 << 16.0 << 40.0; 967 << 0.08 << 0.16 << 0.40 << 0.80 << 1.60 << 4.00 << 8.0 << 16.0 << 40.0;
701 for(int channel = 0; channel < HANTEK_CHANNELS; ++channel) 968 for(int channel = 0; channel < HANTEK_CHANNELS; ++channel)
@@ -706,8 +973,10 @@ namespace Hantek { @@ -706,8 +973,10 @@ namespace Hantek {
706 this->specification.sampleSize = 8; 973 this->specification.sampleSize = 8;
707 break; 974 break;
708 } 975 }
  976 + this->settings.recordLengthId = 1;
709 this->settings.samplerate.limits = &(this->specification.samplerate.single); 977 this->settings.samplerate.limits = &(this->specification.samplerate.single);
710 - this->settings.samplerate.downsampling = 1; 978 + this->settings.samplerate.downsampler = 1;
  979 + this->previousSampleCount = 0;
711 980
712 // Get channel level data 981 // Get channel level data
713 errorCode = this->device->controlRead(CONTROL_VALUE, (unsigned char *) &(this->specification.offsetLimit), sizeof(this->specification.offsetLimit), (int) VALUE_OFFSETLIMITS); 982 errorCode = this->device->controlRead(CONTROL_VALUE, (unsigned char *) &(this->specification.offsetLimit), sizeof(this->specification.offsetLimit), (int) VALUE_OFFSETLIMITS);
@@ -721,131 +990,78 @@ namespace Hantek { @@ -721,131 +990,78 @@ namespace Hantek {
721 } 990 }
722 991
723 /// \brief Sets the size of the oscilloscopes sample buffer. 992 /// \brief Sets the size of the oscilloscopes sample buffer.
724 - /// \param size The record length that should be met (S). 993 + /// \param index The record length index that should be set.
725 /// \return The record length that has been set, 0 on error. 994 /// \return The record length that has been set, 0 on error.
726 - unsigned long int Control::setRecordLength(unsigned long int size) {  
727 - if(!this->device->isConnected()) 995 + unsigned long int Control::setRecordLength(unsigned long int index) {
  996 + if(!this->device->isConnected())
728 return 0; 997 return 0;
729 998
730 - this->updateRecordLength(size); 999 + if(!this->updateRecordLength(index))
  1000 + return 0;
731 1001
732 - this->setSamplerate(); 1002 + this->restoreTargets();
733 this->setPretriggerPosition(this->settings.trigger.position); 1003 this->setPretriggerPosition(this->settings.trigger.position);
734 1004
735 - return this->specification.recordLengths[this->settings.recordLengthId]; 1005 + emit recordLengthChanged(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId]);
  1006 + return this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId];
736 } 1007 }
737 1008
738 /// \brief Sets the samplerate of the oscilloscope. 1009 /// \brief Sets the samplerate of the oscilloscope.
739 - /// \param samplerate The samplerate that should be met (S/s).  
740 - /// \return The samplerate that has been set, 0 on error.  
741 - unsigned long int Control::setSamplerate(unsigned long int samplerate) {  
742 - if(!this->device->isConnected())  
743 - return 0; 1010 + /// \param samplerate The samplerate that should be met (S/s), 0.0 to restore current samplerate.
  1011 + /// \return The samplerate that has been set, 0.0 on error.
  1012 + double Control::setSamplerate(double samplerate) {
  1013 + if(samplerate == 0.0) {
  1014 + samplerate = this->settings.samplerate.target.samplerate;
  1015 + }
  1016 + else {
  1017 + this->settings.samplerate.target.samplerate = samplerate;
  1018 + this->settings.samplerate.target.samplerateSet = true;
  1019 + }
744 1020
745 - // Keep samplerate if no parameter was given  
746 - if(!samplerate)  
747 - samplerate = this->settings.samplerate.current;  
748 - // Abort samplerate calculation if we didn't get a valid value yet  
749 - if(!samplerate)  
750 - return samplerate; 1021 + // When possible, enable fast rate if it is required to reach the requested samplerate
  1022 + bool fastRate = (this->settings.usedChannels <= 1) && (samplerate > this->specification.samplerate.single.max);
751 1023
752 - // Calculate with fast rate first if only one channel is used  
753 - bool fastRate = false;  
754 - this->settings.samplerate.limits = &(this->specification.samplerate.single);  
755 - if(this->settings.usedChannels <= 1) {  
756 - fastRate = true;  
757 - this->settings.samplerate.limits = &(this->specification.samplerate.multi); 1024 + // What is the nearest, at least as high samplerate the scope can provide?
  1025 + unsigned long int downsampler = 0;
  1026 + double bestSamplerate = getBestSamplerate(samplerate, fastRate, false, &(downsampler));
  1027 +
  1028 + // Set the calculated samplerate
  1029 + if(this->updateSamplerate(downsampler, fastRate) == ULONG_MAX)
  1030 + return 0.0;
  1031 + else {
  1032 + return bestSamplerate;
  1033 + }
  1034 + }
  1035 +
  1036 + /// \brief Sets the time duration of one aquisition by adapting the samplerate.
  1037 + /// \param duration The record time duration that should be met (s), 0.0 to restore current record time.
  1038 + /// \return The record time duration that has been set, 0.0 on error.
  1039 + double Control::setRecordTime(double duration) {
  1040 + if(duration == 0.0) {
  1041 + duration = this->settings.samplerate.target.duration;
  1042 + }
  1043 + else {
  1044 + this->settings.samplerate.target.duration = duration;
  1045 + this->settings.samplerate.target.samplerateSet = false;
758 } 1046 }
759 1047
760 - // Get downsampling factor that would provide the requested rate  
761 - this->settings.samplerate.downsampling = this->settings.samplerate.limits->base / this->specification.bufferDividers[this->settings.recordLengthId] / samplerate;  
762 - // A downsampling factor of zero will result in the maximum rate  
763 - if(this->settings.samplerate.downsampling)  
764 - this->settings.samplerate.current = this->settings.samplerate.limits->base / this->specification.bufferDividers[this->settings.recordLengthId] / this->settings.samplerate.downsampling;  
765 - else  
766 - this->settings.samplerate.current = this->settings.samplerate.limits->max / this->specification.bufferDividers[this->settings.recordLengthId]; 1048 + // Calculate the maximum samplerate that would still provide the requested duration
  1049 + double maxSamplerate = (double) this->specification.samplerate.single.recordLengths[this->settings.recordLengthId] / duration;
767 1050
768 - // Maybe normal mode would be sufficient or even better than fast rate mode  
769 - if(fastRate) {  
770 - // Don't set the downsampling factor to zero (maximum rate) if we could use fast rate mode anyway  
771 - unsigned long int slowDownsampling = qMax(this->specification.samplerate.single.base / this->specification.bufferDividers[this->settings.recordLengthId] / samplerate, (long unsigned int) 1);  
772 -  
773 - // Use normal mode if we need valueSlow or it would meet the rate at least as exactly as fast rate mode  
774 - if(this->settings.samplerate.downsampling > 4 || (qAbs((double) this->specification.samplerate.single.base / this->specification.bufferDividers[this->settings.recordLengthId] / slowDownsampling - samplerate) <= qAbs((double) this->settings.samplerate.current - samplerate))) {  
775 - fastRate = false;  
776 - this->settings.samplerate.limits = &(this->specification.samplerate.single);  
777 - this->settings.samplerate.downsampling = slowDownsampling;  
778 - this->settings.samplerate.current = this->specification.samplerate.single.base / this->specification.bufferDividers[this->settings.recordLengthId] / this->settings.samplerate.downsampling;  
779 - }  
780 - } 1051 + // When possible, enable fast rate if the record time can't be set that low to improve resolution
  1052 + bool fastRate = (this->settings.usedChannels <= 1) && (maxSamplerate >= this->specification.samplerate.multi.base);
781 1053
782 - switch(this->specification.command.bulk.setSamplerate) {  
783 - case BULK_SETTRIGGERANDSAMPLERATE: {  
784 - // Split the resulting divider into the values understood by the device  
785 - // The fast value is kept at 4 (or 3) for slow sample rates  
786 - long int valueSlow = qMax(((long int) this->settings.samplerate.downsampling - 3) / 2, (long int) 0);  
787 - unsigned char valueFast = this->settings.samplerate.downsampling - valueSlow * 2;  
788 -  
789 - // Pointers to needed commands  
790 - BulkSetTriggerAndSamplerate *commandSetTriggerAndSamplerate = static_cast<BulkSetTriggerAndSamplerate *>(this->command[BULK_SETTRIGGERANDSAMPLERATE]);  
791 -  
792 - // Store samplerate fast value  
793 - commandSetTriggerAndSamplerate->setSamplerateFast(valueFast);  
794 - // Store samplerate slow value (two's complement)  
795 - commandSetTriggerAndSamplerate->setSamplerateSlow(valueSlow == 0 ? 0 : 0xffff - valueSlow);  
796 - // Set fast rate when used  
797 - commandSetTriggerAndSamplerate->setFastRate(fastRate);  
798 -  
799 - this->commandPending[BULK_SETTRIGGERANDSAMPLERATE] = true;  
800 -  
801 - break;  
802 - }  
803 - case BULK_CSETTRIGGERORSAMPLERATE: {  
804 - // Split the resulting divider into the values understood by the device  
805 - // The fast value is kept at 4 (or 3) for slow sample rates  
806 - long int valueSlow = qMax(((long int) this->settings.samplerate.downsampling - 3) / 2, (long int) 0);  
807 - unsigned char valueFast = this->settings.samplerate.downsampling - valueSlow * 2;  
808 -  
809 - // Pointers to needed commands  
810 - BulkSetSamplerate5200 *commandSetSamplerate5200 = static_cast<BulkSetSamplerate5200 *>(this->command[BULK_CSETTRIGGERORSAMPLERATE]);  
811 - BulkSetTrigger5200 *commandSetTrigger5200 = static_cast<BulkSetTrigger5200 *>(this->command[BULK_ESETTRIGGERORSAMPLERATE]);  
812 -  
813 - // Store samplerate fast value  
814 - commandSetSamplerate5200->setSamplerateFast(4 - valueFast);  
815 - // Store samplerate slow value (two's complement)  
816 - commandSetSamplerate5200->setSamplerateSlow(valueSlow == 0 ? 0 : 0xffff - valueSlow);  
817 - // Set fast rate when used  
818 - commandSetTrigger5200->setFastRate(fastRate);  
819 -  
820 - this->commandPending[BULK_CSETTRIGGERORSAMPLERATE] = true;  
821 - this->commandPending[BULK_ESETTRIGGERORSAMPLERATE] = true;  
822 -  
823 - break;  
824 - }  
825 - case BULK_ESETTRIGGERORSAMPLERATE: {  
826 - // Pointers to needed commands  
827 - BulkSetSamplerate2250 *commandSetSamplerate2250 = static_cast<BulkSetSamplerate2250 *>(this->command[BULK_ESETTRIGGERORSAMPLERATE]);  
828 -  
829 - bool downsampling = this->settings.samplerate.downsampling > 1;  
830 - // Store downsampler state value  
831 - commandSetSamplerate2250->setDownsampling(downsampling);  
832 - // Store samplerate value  
833 - commandSetSamplerate2250->setSamplerate(downsampling ? 0x10001 - this->settings.samplerate.downsampling : 0);  
834 - // Set fast rate when used  
835 - commandSetSamplerate2250->setFastRate(fastRate);  
836 -  
837 - this->commandPending[BULK_ESETTRIGGERORSAMPLERATE] = true;  
838 -  
839 - break;  
840 - }  
841 - default:  
842 - return 0;  
843 - } 1054 + // What is the nearest, at most as high samplerate the scope can provide?
  1055 + unsigned long int downsampler = 0;
  1056 + double bestSamplerate = getBestSamplerate(maxSamplerate, fastRate, true, &(downsampler));
844 1057
845 - this->updateRecordLength(this->specification.recordLengths[this->settings.recordLengthId]);  
846 - this->setPretriggerPosition(this->settings.trigger.position);  
847 - return this->settings.samplerate.current;  
848 - } 1058 + // Set the calculated samplerate
  1059 + if(this->updateSamplerate(downsampler, fastRate) == ULONG_MAX)
  1060 + return 0.0;
  1061 + else {
  1062 + return (double) this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] / bestSamplerate;
  1063 + }
  1064 + }
849 1065
850 /// \brief Enables/disables filtering of the given channel. 1066 /// \brief Enables/disables filtering of the given channel.
851 /// \param channel The channel that should be set. 1067 /// \param channel The channel that should be set.
@@ -858,28 +1074,6 @@ namespace Hantek { @@ -858,28 +1074,6 @@ namespace Hantek {
858 if(channel >= HANTEK_CHANNELS) 1074 if(channel >= HANTEK_CHANNELS)
859 return Dso::ERROR_PARAMETER; 1075 return Dso::ERROR_PARAMETER;
860 1076
861 - // Channel filtering commands  
862 - switch(this->specification.command.bulk.setFilter) {  
863 - case BULK_SETFILTER: {  
864 - // SetFilter bulk command for channel filter (used has to be inverted!)  
865 - BulkSetFilter *commandSetFilter = static_cast<BulkSetFilter *>(this->command[BULK_SETFILTER]);  
866 - commandSetFilter->setChannel(channel, !used);  
867 - this->commandPending[BULK_SETFILTER] = true;  
868 -  
869 - break;  
870 - }  
871 - case BULK_BSETFILTER: {  
872 - // SetFilter2250 bulk command for channel filter (used has to be inverted!)  
873 - BulkSetFilter2250 *commandSetFilter2250 = static_cast<BulkSetFilter2250 *>(this->command[BULK_BSETFILTER]);  
874 - commandSetFilter2250->setChannel(channel, !used);  
875 - this->commandPending[BULK_BSETFILTER] = true;  
876 -  
877 - break;  
878 - }  
879 - default:  
880 - return Dso::ERROR_UNSUPPORTED;  
881 - }  
882 -  
883 // Update settings 1077 // Update settings
884 this->settings.voltage[channel].used = used; 1078 this->settings.voltage[channel].used = used;
885 unsigned int channelCount = 0; 1079 unsigned int channelCount = 0;
@@ -887,35 +1081,58 @@ namespace Hantek { @@ -887,35 +1081,58 @@ namespace Hantek {
887 if(this->settings.voltage[channelCounter].used) 1081 if(this->settings.voltage[channelCounter].used)
888 ++channelCount; 1082 ++channelCount;
889 } 1083 }
890 - this->settings.usedChannels = channelCount;  
891 1084
892 - // Additional UsedChannels field for all models except DSO-2250  
893 - if(this->specification.command.bulk.setTrigger == BULK_SETTRIGGERANDSAMPLERATE || this->specification.command.bulk.setTrigger == BULK_ESETTRIGGERORSAMPLERATE) {  
894 - unsigned char usedChannels = USED_CH1;  
895 -  
896 - if(this->settings.voltage[1].used) {  
897 - if(this->settings.voltage[0].used)  
898 - usedChannels = USED_CH1CH2; 1085 + // Calculate the UsedChannels field for the command
  1086 + unsigned char usedChannels = USED_CH1;
  1087 +
  1088 + if(this->settings.voltage[1].used) {
  1089 + if(this->settings.voltage[0].used) {
  1090 + usedChannels = USED_CH1CH2;
  1091 + }
  1092 + else {
  1093 + // DSO-2250 uses a different value for channel 2
  1094 + if(this->specification.command.bulk.setTrigger == BULK_BSETCHANNELS)
  1095 + usedChannels = BUSED_CH2;
899 else 1096 else
900 usedChannels = USED_CH2; 1097 usedChannels = USED_CH2;
901 } 1098 }
902 -  
903 - switch(this->specification.command.bulk.setTrigger) {  
904 - case BULK_SETTRIGGERANDSAMPLERATE: {  
905 - // SetTriggerAndSamplerate bulk command for trigger source  
906 - static_cast<BulkSetTriggerAndSamplerate *>(this->command[BULK_SETTRIGGERANDSAMPLERATE])->setUsedChannels(usedChannels);  
907 - this->commandPending[BULK_SETTRIGGERANDSAMPLERATE] = true;  
908 - break;  
909 - }  
910 - case BULK_ESETTRIGGERORSAMPLERATE: {  
911 - // SetTrigger5200s bulk command for trigger source  
912 - static_cast<BulkSetTrigger5200 *>(this->command[BULK_ESETTRIGGERORSAMPLERATE])->setUsedChannels(usedChannels);  
913 - this->commandPending[BULK_ESETTRIGGERORSAMPLERATE] = true;  
914 - break;  
915 - }  
916 - default:  
917 - break; 1099 + }
  1100 +
  1101 + switch(this->specification.command.bulk.setTrigger) {
  1102 + case BULK_SETTRIGGERANDSAMPLERATE: {
  1103 + // SetTriggerAndSamplerate bulk command for trigger source
  1104 + static_cast<BulkSetTriggerAndSamplerate *>(this->command[BULK_SETTRIGGERANDSAMPLERATE])->setUsedChannels(usedChannels);
  1105 + this->commandPending[BULK_SETTRIGGERANDSAMPLERATE] = true;
  1106 + break;
  1107 + }
  1108 + case BULK_BSETCHANNELS: {
  1109 + // SetChannels2250 bulk command for active channels
  1110 + static_cast<BulkSetChannels2250 *>(this->command[BULK_BSETCHANNELS])->setUsedChannels(usedChannels);
  1111 + this->commandPending[BULK_BSETCHANNELS] = true;
  1112 +
  1113 + break;
  1114 + }
  1115 + case BULK_ESETTRIGGERORSAMPLERATE: {
  1116 + // SetTrigger5200s bulk command for trigger source
  1117 + static_cast<BulkSetTrigger5200 *>(this->command[BULK_ESETTRIGGERORSAMPLERATE])->setUsedChannels(usedChannels);
  1118 + this->commandPending[BULK_ESETTRIGGERORSAMPLERATE] = true;
  1119 + break;
918 } 1120 }
  1121 + default:
  1122 + break;
  1123 + }
  1124 +
  1125 + // Check if fast rate mode availability changed
  1126 + bool fastRateChanged = (this->settings.usedChannels <= 1) != (channelCount <= 1);
  1127 + this->settings.usedChannels = channelCount;
  1128 +
  1129 + if(fastRateChanged) {
  1130 + // Works only if the minimum samplerate for normal mode is lower than for fast rate mode, which is the case for all models
  1131 + ControlSamplerateLimits *limits = (channelCount <= 1) ? &this->specification.samplerate.multi : &this->specification.samplerate.single;
  1132 + emit samplerateLimitsChanged((double) this->specification.samplerate.single.base / this->specification.samplerate.single.maxDownsampler, limits->max);
  1133 +
  1134 + // Samplerate differs for fast rate mode, recalculate it
  1135 + this->restoreTargets();
919 } 1136 }
920 1137
921 return Dso::ERROR_NONE; 1138 return Dso::ERROR_NONE;
@@ -1166,7 +1383,7 @@ namespace Hantek { @@ -1166,7 +1383,7 @@ namespace Hantek {
1166 switch(this->specification.command.bulk.setPretrigger) { 1383 switch(this->specification.command.bulk.setPretrigger) {
1167 case BULK_SETTRIGGERANDSAMPLERATE: { 1384 case BULK_SETTRIGGERANDSAMPLERATE: {
1168 // Calculate the position value (Start point depending on record length) 1385 // Calculate the position value (Start point depending on record length)
1169 - unsigned long int position = 0x7ffff - this->specification.recordLengths[this->settings.recordLengthId] + positionSamples; 1386 + unsigned long int position = 0x7ffff - this->specification.samplerate.single.recordLengths[this->settings.recordLengthId] + positionSamples;
1170 1387
1171 // SetTriggerAndSamplerate bulk command for trigger position 1388 // SetTriggerAndSamplerate bulk command for trigger position
1172 static_cast<BulkSetTriggerAndSamplerate *>(this->command[BULK_SETTRIGGERANDSAMPLERATE])->setTriggerPosition(position); 1389 static_cast<BulkSetTriggerAndSamplerate *>(this->command[BULK_SETTRIGGERANDSAMPLERATE])->setTriggerPosition(position);
@@ -1176,7 +1393,7 @@ namespace Hantek { @@ -1176,7 +1393,7 @@ namespace Hantek {
1176 } 1393 }
1177 case BULK_FSETBUFFER: { 1394 case BULK_FSETBUFFER: {
1178 // Calculate the position values (Inverse, maximum is 0x7ffff) 1395 // Calculate the position values (Inverse, maximum is 0x7ffff)
1179 - unsigned long int positionPre = 0x7fffful - this->specification.recordLengths[this->settings.recordLengthId] + positionSamples; 1396 + unsigned long int positionPre = 0x7fffful - this->specification.samplerate.single.recordLengths[this->settings.recordLengthId] + positionSamples;
1180 unsigned long int positionPost = 0x7fffful - positionSamples; 1397 unsigned long int positionPost = 0x7fffful - positionSamples;
1181 1398
1182 // SetBuffer2250 bulk command for trigger position 1399 // SetBuffer2250 bulk command for trigger position
@@ -1189,7 +1406,7 @@ namespace Hantek { @@ -1189,7 +1406,7 @@ namespace Hantek {
1189 } 1406 }
1190 case BULK_ESETTRIGGERORSAMPLERATE: { 1407 case BULK_ESETTRIGGERORSAMPLERATE: {
1191 // Calculate the position values (Inverse, maximum is 0xffff) 1408 // Calculate the position values (Inverse, maximum is 0xffff)
1192 - unsigned short int positionPre = 0xffff - this->specification.recordLengths[this->settings.recordLengthId] + positionSamples; 1409 + unsigned short int positionPre = 0xffff - this->specification.samplerate.single.recordLengths[this->settings.recordLengthId] + positionSamples;
1193 unsigned short int positionPost = 0xffff - positionSamples; 1410 unsigned short int positionPost = 0xffff - positionSamples;
1194 1411
1195 // SetBuffer5200 bulk command for trigger position 1412 // SetBuffer5200 bulk command for trigger position
openhantek/src/hantek/control.h
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 // 6 //
7 // Copyright (C) 2008, 2009 Oleg Khudyakov 7 // Copyright (C) 2008, 2009 Oleg Khudyakov
8 // prcoder@potrebitel.ru 8 // prcoder@potrebitel.ru
9 -// Copyright (C) 2010, 2011 Oliver Haag 9 +// Copyright (C) 2010 - 2012 Oliver Haag
10 // oliver.haag@gmail.com 10 // oliver.haag@gmail.com
11 // 11 //
12 // This program is free software: you can redistribute it and/or modify it 12 // This program is free software: you can redistribute it and/or modify it
@@ -56,7 +56,7 @@ namespace Hantek { @@ -56,7 +56,7 @@ namespace Hantek {
56 /// \struct ControlSpecificationCommandsBulk hantek/control.h 56 /// \struct ControlSpecificationCommandsBulk hantek/control.h
57 /// \brief Stores the bulk command codes used for this device. 57 /// \brief Stores the bulk command codes used for this device.
58 struct ControlSpecificationCommandsBulk { 58 struct ControlSpecificationCommandsBulk {
59 - BulkCode setFilter; ///< Command for setting used channels 59 + BulkCode setChannels; ///< Command for setting used channels
60 BulkCode setSamplerate; ///< Command for samplerate settings 60 BulkCode setSamplerate; ///< Command for samplerate settings
61 BulkCode setGain; ///< Command for gain settings (Usually in combination with CONTROL_SETRELAYS) 61 BulkCode setGain; ///< Command for gain settings (Usually in combination with CONTROL_SETRELAYS)
62 BulkCode setRecordLength; ///< Command for buffer settings 62 BulkCode setRecordLength; ///< Command for buffer settings
@@ -95,6 +95,8 @@ namespace Hantek { @@ -95,6 +95,8 @@ namespace Hantek {
95 struct ControlSamplerateLimits { 95 struct ControlSamplerateLimits {
96 unsigned long int base; ///< The base for sample rate calculations 96 unsigned long int base; ///< The base for sample rate calculations
97 unsigned long int max; ///< The maximum sample rate 97 unsigned long int max; ///< The maximum sample rate
  98 + unsigned long int maxDownsampler; ///< The maximum downsampling ratio
  99 + QList<unsigned long int> recordLengths; ///< Available record lengths, ULONG_MAX means rolling
98 }; 100 };
99 101
100 ////////////////////////////////////////////////////////////////////////////// 102 //////////////////////////////////////////////////////////////////////////////
@@ -114,7 +116,6 @@ namespace Hantek { @@ -114,7 +116,6 @@ namespace Hantek {
114 116
115 // Limits 117 // Limits
116 ControlSpecificationSamplerate samplerate; ///< The samplerate specifications 118 ControlSpecificationSamplerate samplerate; ///< The samplerate specifications
117 - QList<unsigned long int> recordLengths; ///< Available record lengths, ULONG_MAX means rolling  
118 QList<unsigned long int> bufferDividers; ///< Samplerate dividers for record lengths 119 QList<unsigned long int> bufferDividers; ///< Samplerate dividers for record lengths
119 QList<double> gainSteps; ///< Available voltage steps in V/screenheight 120 QList<double> gainSteps; ///< Available voltage steps in V/screenheight
120 unsigned char sampleSize; ///< Number of bits per sample 121 unsigned char sampleSize; ///< Number of bits per sample
@@ -129,12 +130,22 @@ namespace Hantek { @@ -129,12 +130,22 @@ namespace Hantek {
129 }; 130 };
130 131
131 ////////////////////////////////////////////////////////////////////////////// 132 //////////////////////////////////////////////////////////////////////////////
  133 + /// \struct ControlSettingsSamplerateTarget hantek/control.h
  134 + /// \brief Stores the target samplerate settings of the device.
  135 + struct ControlSettingsSamplerateTarget {
  136 + double samplerate; ///< The target samplerate set via setSamplerate
  137 + double duration; ///< The target record time set via setRecordTime
  138 + bool samplerateSet; ///< true means samplerate was set last, false duration
  139 + };
  140 +
  141 + //////////////////////////////////////////////////////////////////////////////
132 /// \struct ControlSettingsSamplerate hantek/control.h 142 /// \struct ControlSettingsSamplerate hantek/control.h
133 /// \brief Stores the current samplerate settings of the device. 143 /// \brief Stores the current samplerate settings of the device.
134 struct ControlSettingsSamplerate { 144 struct ControlSettingsSamplerate {
  145 + ControlSettingsSamplerateTarget target; ///< The target samplerate values
135 ControlSamplerateLimits *limits; ///< The samplerate limits 146 ControlSamplerateLimits *limits; ///< The samplerate limits
136 - unsigned long int downsampling; ///< The variable downsampling factor  
137 - unsigned long int current; ///< The current samplerate 147 + unsigned long int downsampler; ///< The variable downsampling factor
  148 + double current; ///< The current samplerate
138 }; 149 };
139 150
140 ////////////////////////////////////////////////////////////////////////////// 151 //////////////////////////////////////////////////////////////////////////////
@@ -182,6 +193,9 @@ namespace Hantek { @@ -182,6 +193,9 @@ namespace Hantek {
182 ~Control(); 193 ~Control();
183 194
184 unsigned int getChannelCount(); 195 unsigned int getChannelCount();
  196 + QList<unsigned long int> *getAvailableRecordLengths();
  197 + double getMinSamplerate();
  198 + double getMaxSamplerate();
185 199
186 protected: 200 protected:
187 void run(); 201 void run();
@@ -189,7 +203,10 @@ namespace Hantek { @@ -189,7 +203,10 @@ namespace Hantek {
189 unsigned long int calculateTriggerPoint(unsigned long int value); 203 unsigned long int calculateTriggerPoint(unsigned long int value);
190 int getCaptureState(); 204 int getCaptureState();
191 int getSamples(bool process); 205 int getSamples(bool process);
  206 + double getBestSamplerate(double samplerate, bool fastRate = false, bool maximum = false, unsigned long int *downsampler = 0);
192 unsigned long int updateRecordLength(unsigned long int size); 207 unsigned long int updateRecordLength(unsigned long int size);
  208 + unsigned long int updateSamplerate(unsigned long int downsampler, bool fastRate);
  209 + void restoreTargets();
193 210
194 // Communication with device 211 // Communication with device
195 Device *device; ///< The USB device for the oscilloscope 212 Device *device; ///< The USB device for the oscilloscope
@@ -206,14 +223,16 @@ namespace Hantek { @@ -206,14 +223,16 @@ namespace Hantek {
206 223
207 // Results 224 // Results
208 QList<double *> samples; ///< Sample data arrays 225 QList<double *> samples; ///< Sample data arrays
209 - QList<unsigned int> samplesSize; ///< Number of samples data array 226 + QList<unsigned long int> samplesSize; ///< Number of samples data array
  227 + unsigned long int previousSampleCount; ///< The expected total number of samples at the last check before sampling started
210 QMutex samplesMutex; ///< Mutex for the sample data 228 QMutex samplesMutex; ///< Mutex for the sample data
211 229
212 public slots: 230 public slots:
213 virtual void connectDevice(); 231 virtual void connectDevice();
214 232
215 - unsigned long int setSamplerate(unsigned long int samplerate = 0);  
216 unsigned long int setRecordLength(unsigned long int size); 233 unsigned long int setRecordLength(unsigned long int size);
  234 + double setSamplerate(double samplerate = 0.0);
  235 + double setRecordTime(double duration = 0.0);
217 236
218 int setChannelUsed(unsigned int channel, bool used); 237 int setChannelUsed(unsigned int channel, bool used);
219 int setCoupling(unsigned int channel, Dso::Coupling coupling); 238 int setCoupling(unsigned int channel, Dso::Coupling coupling);
openhantek/src/hantek/device.cpp
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 // 5 //
6 // Copyright (C) 2008, 2009 Oleg Khudyakov 6 // Copyright (C) 2008, 2009 Oleg Khudyakov
7 // prcoder@potrebitel.ru 7 // prcoder@potrebitel.ru
8 -// Copyright (C) 2010 Oliver Haag 8 +// Copyright (C) 2010 - 2012 Oliver Haag
9 // oliver.haag@gmail.com 9 // oliver.haag@gmail.com
10 // 10 //
11 // This program is free software: you can redistribute it and/or modify it 11 // This program is free software: you can redistribute it and/or modify it
@@ -274,20 +274,21 @@ namespace Hantek { @@ -274,20 +274,21 @@ namespace Hantek {
274 } 274 }
275 275
276 #if LIBUSB_VERSION != 0 276 #if LIBUSB_VERSION != 0
277 - /// \brief Bulk transfer to the oscilloscope. 277 + /// \brief Bulk transfer to/from the oscilloscope.
278 /// \param endpoint Endpoint number, also sets the direction of the transfer. 278 /// \param endpoint Endpoint number, also sets the direction of the transfer.
279 /// \param data Buffer for the sent/recieved data. 279 /// \param data Buffer for the sent/recieved data.
280 /// \param length The length of the packet. 280 /// \param length The length of the packet.
281 /// \param attempts The number of attempts, that are done on timeouts. 281 /// \param attempts The number of attempts, that are done on timeouts.
  282 + /// \param timeout The timeout in ms.
282 /// \return Number of transferred bytes on success, libusb error code on error. 283 /// \return Number of transferred bytes on success, libusb error code on error.
283 - int Device::bulkTransfer(unsigned char endpoint, unsigned char *data, unsigned int length, int attempts) { 284 + int Device::bulkTransfer(unsigned char endpoint, unsigned char *data, unsigned long int length, int attempts, unsigned int timeout) {
284 if(!this->handle) 285 if(!this->handle)
285 return LIBUSB_ERROR_NO_DEVICE; 286 return LIBUSB_ERROR_NO_DEVICE;
286 287
287 int errorCode = LIBUSB_ERROR_TIMEOUT; 288 int errorCode = LIBUSB_ERROR_TIMEOUT;
288 int transferred; 289 int transferred;
289 for(int attempt = 0; (attempt < attempts || attempts == -1) && errorCode == LIBUSB_ERROR_TIMEOUT; ++attempt) 290 for(int attempt = 0; (attempt < attempts || attempts == -1) && errorCode == LIBUSB_ERROR_TIMEOUT; ++attempt)
290 - errorCode = libusb_bulk_transfer(this->handle, endpoint, data, length, &transferred, HANTEK_TIMEOUT); 291 + errorCode = libusb_bulk_transfer(this->handle, endpoint, data, length, &transferred, timeout);
291 292
292 if(errorCode == LIBUSB_ERROR_NO_DEVICE) 293 if(errorCode == LIBUSB_ERROR_NO_DEVICE)
293 this->disconnect(); 294 this->disconnect();
@@ -303,7 +304,7 @@ namespace Hantek { @@ -303,7 +304,7 @@ namespace Hantek {
303 /// \param length The length of the packet. 304 /// \param length The length of the packet.
304 /// \param attempts The number of attempts, that are done on timeouts. 305 /// \param attempts The number of attempts, that are done on timeouts.
305 /// \return Number of sent bytes on success, libusb error code on error. 306 /// \return Number of sent bytes on success, libusb error code on error.
306 - int Device::bulkWrite(unsigned char *data, unsigned int length, int attempts) { 307 + int Device::bulkWrite(unsigned char *data, unsigned long int length, int attempts) {
307 if(!this->handle) 308 if(!this->handle)
308 return LIBUSB_ERROR_NO_DEVICE; 309 return LIBUSB_ERROR_NO_DEVICE;
309 310
@@ -330,7 +331,7 @@ namespace Hantek { @@ -330,7 +331,7 @@ namespace Hantek {
330 /// \param length The length of the packet. 331 /// \param length The length of the packet.
331 /// \param attempts The number of attempts, that are done on timeouts. 332 /// \param attempts The number of attempts, that are done on timeouts.
332 /// \return Number of received bytes on success, libusb error code on error. 333 /// \return Number of received bytes on success, libusb error code on error.
333 - int Device::bulkRead(unsigned char *data, unsigned int length, int attempts) { 334 + int Device::bulkRead(unsigned char *data, unsigned long int length, int attempts) {
334 if(!this->handle) 335 if(!this->handle)
335 return LIBUSB_ERROR_NO_DEVICE; 336 return LIBUSB_ERROR_NO_DEVICE;
336 337
@@ -374,7 +375,7 @@ namespace Hantek { @@ -374,7 +375,7 @@ namespace Hantek {
374 /// \param length The length of data contained in the packets. 375 /// \param length The length of data contained in the packets.
375 /// \param attempts The number of attempts, that are done on timeouts. 376 /// \param attempts The number of attempts, that are done on timeouts.
376 /// \return Number of received bytes on success, libusb error code on error. 377 /// \return Number of received bytes on success, libusb error code on error.
377 - int Device::bulkReadMulti(unsigned char *data, unsigned int length, int attempts) { 378 + int Device::bulkReadMulti(unsigned char *data, unsigned long int length, int attempts) {
378 if(!this->handle) 379 if(!this->handle)
379 return LIBUSB_ERROR_NO_DEVICE; 380 return LIBUSB_ERROR_NO_DEVICE;
380 381
@@ -385,14 +386,14 @@ namespace Hantek { @@ -385,14 +386,14 @@ namespace Hantek {
385 return errorCode; 386 return errorCode;
386 387
387 errorCode = this->inPacketLength; 388 errorCode = this->inPacketLength;
388 - unsigned int packet, received = 0; 389 + unsigned long int packet, received = 0;
389 for(packet = 0; received < length && errorCode == this->inPacketLength; ++packet) { 390 for(packet = 0; received < length && errorCode == this->inPacketLength; ++packet) {
390 #if LIBUSB_VERSION == 0 391 #if LIBUSB_VERSION == 0
391 errorCode = LIBUSB_ERROR_TIMEOUT; 392 errorCode = LIBUSB_ERROR_TIMEOUT;
392 for(int attempt = 0; (attempt < attempts || attempts == -1) && errorCode == LIBUSB_ERROR_TIMEOUT; ++attempt) 393 for(int attempt = 0; (attempt < attempts || attempts == -1) && errorCode == LIBUSB_ERROR_TIMEOUT; ++attempt)
393 - errorCode = usb_bulk_read(this->handle, HANTEK_EP_IN, (char *) data + packet * this->inPacketLength, qMin(length - received, (unsigned int) this->inPacketLength), HANTEK_TIMEOUT); 394 + errorCode = usb_bulk_read(this->handle, HANTEK_EP_IN, (char *) data + packet * this->inPacketLength, qMin(length - received, (unsigned long int) this->inPacketLength), HANTEK_TIMEOUT);
394 #else 395 #else
395 - errorCode = this->bulkTransfer(HANTEK_EP_IN, data + packet * this->inPacketLength, qMin(length - received, (unsigned int) this->inPacketLength), attempts); 396 + errorCode = this->bulkTransfer(HANTEK_EP_IN, data + packet * this->inPacketLength, qMin(length - received, (unsigned long int) this->inPacketLength), attempts, HANTEK_TIMEOUT_MULTI);
396 #endif 397 #endif
397 if(errorCode > 0) 398 if(errorCode > 0)
398 received += errorCode; 399 received += errorCode;
@@ -413,7 +414,7 @@ namespace Hantek { @@ -413,7 +414,7 @@ namespace Hantek {
413 /// \param index The index field of the packet. 414 /// \param index The index field of the packet.
414 /// \param attempts The number of attempts, that are done on timeouts. 415 /// \param attempts The number of attempts, that are done on timeouts.
415 /// \return Number of transferred bytes on success, libusb error code on error. 416 /// \return Number of transferred bytes on success, libusb error code on error.
416 - int Device::controlTransfer(unsigned char type, unsigned char request, unsigned char *data, unsigned int length, int value, int index, int attempts) { 417 + int Device::controlTransfer(unsigned char type, unsigned char request, unsigned char *data, unsigned long int length, int value, int index, int attempts) {
417 if(!this->handle) 418 if(!this->handle)
418 return LIBUSB_ERROR_NO_DEVICE; 419 return LIBUSB_ERROR_NO_DEVICE;
419 420
@@ -438,7 +439,7 @@ namespace Hantek { @@ -438,7 +439,7 @@ namespace Hantek {
438 /// \param index The index field of the packet. 439 /// \param index The index field of the packet.
439 /// \param attempts The number of attempts, that are done on timeouts. 440 /// \param attempts The number of attempts, that are done on timeouts.
440 /// \return Number of sent bytes on success, libusb error code on error. 441 /// \return Number of sent bytes on success, libusb error code on error.
441 - int Device::controlWrite(unsigned char request, unsigned char *data, unsigned int length, int value, int index, int attempts) { 442 + int Device::controlWrite(unsigned char request, unsigned char *data, unsigned long int length, int value, int index, int attempts) {
442 if(!this->handle) 443 if(!this->handle)
443 return LIBUSB_ERROR_NO_DEVICE; 444 return LIBUSB_ERROR_NO_DEVICE;
444 445
@@ -453,7 +454,7 @@ namespace Hantek { @@ -453,7 +454,7 @@ namespace Hantek {
453 /// \param index The index field of the packet. 454 /// \param index The index field of the packet.
454 /// \param attempts The number of attempts, that are done on timeouts. 455 /// \param attempts The number of attempts, that are done on timeouts.
455 /// \return Number of received bytes on success, libusb error code on error. 456 /// \return Number of received bytes on success, libusb error code on error.
456 - int Device::controlRead(unsigned char request, unsigned char *data, unsigned int length, int value, int index, int attempts) { 457 + int Device::controlRead(unsigned char request, unsigned char *data, unsigned long int length, int value, int index, int attempts) {
457 if(!this->handle) 458 if(!this->handle)
458 return LIBUSB_ERROR_NO_DEVICE; 459 return LIBUSB_ERROR_NO_DEVICE;
459 460
openhantek/src/hantek/device.h
@@ -4,10 +4,8 @@ @@ -4,10 +4,8 @@
4 /// \file hantek/device.h 4 /// \file hantek/device.h
5 /// \brief Declares the Hantek::Device class. 5 /// \brief Declares the Hantek::Device class.
6 // 6 //
7 -// Copyright (C) 2008, 2009 Oleg Khudyakov  
8 -// prcoder@potrebitel.ru  
9 -// Copyright (C) 2010 Oliver Haag  
10 -// oliver.haag@gmail.com 7 +/// \copyright (c) 2008, 2009 Oleg Khudyakov <prcoder@potrebitel.ru>
  8 +/// \copyright (c) 2010 - 2012 Oliver Haag <oliver.haag@gmail.com>
11 // 9 //
12 // This program is free software: you can redistribute it and/or modify it 10 // This program is free software: you can redistribute it and/or modify it
13 // under the terms of the GNU General Public License as published by the Free 11 // under the terms of the GNU General Public License as published by the Free
@@ -62,17 +60,17 @@ namespace Hantek { @@ -62,17 +60,17 @@ namespace Hantek {
62 60
63 // Various methods to handle USB transfers 61 // Various methods to handle USB transfers
64 #if LIBUSB_VERSION != 0 62 #if LIBUSB_VERSION != 0
65 - int bulkTransfer(unsigned char endpoint, unsigned char *data, unsigned int length, int attempts = HANTEK_ATTEMPTS_DEFAULT); 63 + int bulkTransfer(unsigned char endpoint, unsigned char *data, unsigned long int length, int attempts = HANTEK_ATTEMPTS, unsigned int timeout = HANTEK_TIMEOUT);
66 #endif 64 #endif
67 - int bulkWrite(unsigned char *data, unsigned int length, int attempts = HANTEK_ATTEMPTS_DEFAULT);  
68 - int bulkRead(unsigned char *data, unsigned int length, int attempts = HANTEK_ATTEMPTS_DEFAULT); 65 + int bulkWrite(unsigned char *data, unsigned long int length, int attempts = HANTEK_ATTEMPTS);
  66 + int bulkRead(unsigned char *data, unsigned long int length, int attempts = HANTEK_ATTEMPTS);
69 67
70 - int bulkCommand(Helper::DataArray<unsigned char> *command, int attempts = HANTEK_ATTEMPTS_DEFAULT);  
71 - int bulkReadMulti(unsigned char *data, unsigned int length, int attempts = HANTEK_ATTEMPTS_DEFAULT); 68 + int bulkCommand(Helper::DataArray<unsigned char> *command, int attempts = HANTEK_ATTEMPTS);
  69 + int bulkReadMulti(unsigned char *data, unsigned long int length, int attempts = HANTEK_ATTEMPTS_MULTI);
72 70
73 - int controlTransfer(unsigned char type, unsigned char request, unsigned char *data, unsigned int length, int value, int index, int attempts = HANTEK_ATTEMPTS_DEFAULT);  
74 - int controlWrite(unsigned char request, unsigned char *data, unsigned int length, int value = 0, int index = 0, int attempts = HANTEK_ATTEMPTS_DEFAULT);  
75 - int controlRead(unsigned char request, unsigned char *data, unsigned int length, int value = 0, int index = 0, int attempts = HANTEK_ATTEMPTS_DEFAULT); 71 + int controlTransfer(unsigned char type, unsigned char request, unsigned char *data, unsigned long int length, int value, int index, int attempts = HANTEK_ATTEMPTS);
  72 + int controlWrite(unsigned char request, unsigned char *data, unsigned long int length, int value = 0, int index = 0, int attempts = HANTEK_ATTEMPTS);
  73 + int controlRead(unsigned char request, unsigned char *data, unsigned long int length, int value = 0, int index = 0, int attempts = HANTEK_ATTEMPTS);
76 74
77 int getConnectionSpeed(); 75 int getConnectionSpeed();
78 Model getModel(); 76 Model getModel();
openhantek/src/hantek/types.cpp
@@ -101,24 +101,26 @@ namespace Hantek { @@ -101,24 +101,26 @@ namespace Hantek {
101 } 101 }
102 102
103 /// \brief Sets the data bytes to the specified values. 103 /// \brief Sets the data bytes to the specified values.
104 - /// \param samplerateSlow The SamplerateSlow value. 104 + /// \param downsampler The Downsampler value.
105 /// \param triggerPosition The trigger position value. 105 /// \param triggerPosition The trigger position value.
106 /// \param triggerSource The trigger source id (Tsr1). 106 /// \param triggerSource The trigger source id (Tsr1).
107 /// \param recordLength The record length id (Tsr1). 107 /// \param recordLength The record length id (Tsr1).
108 - /// \param samplerateFast The samplerateFast value (Tsr1). 108 + /// \param samplerateId The samplerateId value (Tsr1).
  109 + /// \param downsamplingMode The downsamplingMode value (Tsr1).
109 /// \param usedChannels The enabled channels (Tsr2). 110 /// \param usedChannels The enabled channels (Tsr2).
110 /// \param fastRate The fastRate state (Tsr2). 111 /// \param fastRate The fastRate state (Tsr2).
111 /// \param triggerSlope The triggerSlope value (Tsr2). 112 /// \param triggerSlope The triggerSlope value (Tsr2).
112 - BulkSetTriggerAndSamplerate::BulkSetTriggerAndSamplerate(unsigned short int samplerateSlow, unsigned long int triggerPosition, unsigned char triggerSource, unsigned char recordLength, unsigned char samplerateFast, unsigned char usedChannels, bool fastRate, unsigned char triggerSlope) : Helper::DataArray<unsigned char>(12) { 113 + BulkSetTriggerAndSamplerate::BulkSetTriggerAndSamplerate(unsigned short int downsampler, unsigned long int triggerPosition, unsigned char triggerSource, unsigned char recordLength, unsigned char samplerateId, bool downsamplingMode, unsigned char usedChannels, bool fastRate, unsigned char triggerSlope) : Helper::DataArray<unsigned char>(12) {
113 this->init(); 114 this->init();
114 115
115 this->setTriggerSource(triggerSource); 116 this->setTriggerSource(triggerSource);
116 this->setRecordLength(recordLength); 117 this->setRecordLength(recordLength);
117 - this->setSamplerateFast(samplerateFast); 118 + this->setSamplerateId(samplerateId);
  119 + this->setDownsamplingMode(downsamplingMode);
118 this->setUsedChannels(usedChannels); 120 this->setUsedChannels(usedChannels);
119 this->setFastRate(fastRate); 121 this->setFastRate(fastRate);
120 this->setTriggerSlope(triggerSlope); 122 this->setTriggerSlope(triggerSlope);
121 - this->setSamplerateSlow(samplerateSlow); 123 + this->setDownsampler(downsampler);
122 this->setTriggerPosition(triggerPosition); 124 this->setTriggerPosition(triggerPosition);
123 } 125 }
124 126
@@ -146,16 +148,28 @@ namespace Hantek { @@ -146,16 +148,28 @@ namespace Hantek {
146 ((Tsr1Bits *) &(this->array[2]))->recordLength = value; 148 ((Tsr1Bits *) &(this->array[2]))->recordLength = value;
147 } 149 }
148 150
149 - /// \brief Get the samplerateFast value in Tsr1Bits.  
150 - /// \return The samplerateFast value.  
151 - unsigned char BulkSetTriggerAndSamplerate::getSamplerateFast() {  
152 - return ((Tsr1Bits *) &(this->array[2]))->samplerateFast; 151 + /// \brief Get the samplerateId value in Tsr1Bits.
  152 + /// \return The samplerateId value.
  153 + unsigned char BulkSetTriggerAndSamplerate::getSamplerateId() {
  154 + return ((Tsr1Bits *) &(this->array[2]))->samplerateId;
  155 + }
  156 +
  157 + /// \brief Set the samplerateId in Tsr1Bits to the given value.
  158 + /// \param value The new samplerateId value.
  159 + void BulkSetTriggerAndSamplerate::setSamplerateId(unsigned char value) {
  160 + ((Tsr1Bits *) &(this->array[2]))->samplerateId = value;
153 } 161 }
154 162
155 - /// \brief Set the samplerateFast in Tsr1Bits to the given value.  
156 - /// \param value The new samplerateFast value.  
157 - void BulkSetTriggerAndSamplerate::setSamplerateFast(unsigned char value) {  
158 - ((Tsr1Bits *) &(this->array[2]))->samplerateFast = value; 163 + /// \brief Get the downsamplerMode value in Tsr1Bits.
  164 + /// \return The downsamplerMode value.
  165 + bool BulkSetTriggerAndSamplerate::getDownsamplingMode() {
  166 + return ((Tsr1Bits *) &(this->array[2]))->downsamplingMode == 1;
  167 + }
  168 +
  169 + /// \brief Set the downsamplerMode in Tsr1Bits to the given value.
  170 + /// \param downsampling The new downsamplerMode value.
  171 + void BulkSetTriggerAndSamplerate::setDownsamplingMode(bool downsampling) {
  172 + ((Tsr1Bits *) &(this->array[2]))->downsamplingMode = downsampling ? 1 : 0;
159 } 173 }
160 174
161 /// \brief Get the usedChannels value in Tsr2Bits. 175 /// \brief Get the usedChannels value in Tsr2Bits.
@@ -194,17 +208,17 @@ namespace Hantek { @@ -194,17 +208,17 @@ namespace Hantek {
194 ((Tsr2Bits *) &(this->array[3]))->triggerSlope = slope; 208 ((Tsr2Bits *) &(this->array[3]))->triggerSlope = slope;
195 } 209 }
196 210
197 - /// \brief Get the SamplerateSlow value.  
198 - /// \return The SamplerateSlow value.  
199 - unsigned short int BulkSetTriggerAndSamplerate::getSamplerateSlow() { 211 + /// \brief Get the Downsampler value.
  212 + /// \return The Downsampler value.
  213 + unsigned short int BulkSetTriggerAndSamplerate::getDownsampler() {
200 return (unsigned short int) this->array[4] | ((unsigned short int) this->array[5] << 8); 214 return (unsigned short int) this->array[4] | ((unsigned short int) this->array[5] << 8);
201 } 215 }
202 216
203 - /// \brief Set the SamplerateSlow to the given value.  
204 - /// \param samplerate The new SamplerateSlow value.  
205 - void BulkSetTriggerAndSamplerate::setSamplerateSlow(unsigned short int samplerate) {  
206 - this->array[4] = (unsigned char) samplerate;  
207 - this->array[5] = (unsigned char) (samplerate >> 8); 217 + /// \brief Set the Downsampler to the given value.
  218 + /// \param downsampler The new Downsampler value.
  219 + void BulkSetTriggerAndSamplerate::setDownsampler(unsigned short int downsampler) {
  220 + this->array[4] = (unsigned char) downsampler;
  221 + this->array[5] = (unsigned char) (downsampler >> 8);
208 } 222 }
209 223
210 /// \brief Get the TriggerPosition value. 224 /// \brief Get the TriggerPosition value.
@@ -328,8 +342,6 @@ namespace Hantek { @@ -328,8 +342,6 @@ namespace Hantek {
328 /// \brief Initialize the array to the needed values. 342 /// \brief Initialize the array to the needed values.
329 void BulkSetGain::init() { 343 void BulkSetGain::init() {
330 this->array[0] = BULK_SETGAIN; 344 this->array[0] = BULK_SETGAIN;
331 - this->array[1] = 0x0f;  
332 - ((GainBits *) &(this->array[2]))->reserved = 3;  
333 } 345 }
334 346
335 347
@@ -363,7 +375,6 @@ namespace Hantek { @@ -363,7 +375,6 @@ namespace Hantek {
363 /// \brief Initialize the array to the needed values. 375 /// \brief Initialize the array to the needed values.
364 void BulkSetLogicalData::init() { 376 void BulkSetLogicalData::init() {
365 this->array[0] = BULK_SETLOGICALDATA; 377 this->array[0] = BULK_SETLOGICALDATA;
366 - this->array[1] = 0x0f;  
367 } 378 }
368 379
369 380
@@ -378,45 +389,33 @@ namespace Hantek { @@ -378,45 +389,33 @@ namespace Hantek {
378 ////////////////////////////////////////////////////////////////////////////// 389 //////////////////////////////////////////////////////////////////////////////
379 // class BulkSetFilter2250 390 // class BulkSetFilter2250
380 /// \brief Sets the data array to needed values. 391 /// \brief Sets the data array to needed values.
381 - BulkSetFilter2250::BulkSetFilter2250() : Helper::DataArray<unsigned char>(4) { 392 + BulkSetChannels2250::BulkSetChannels2250() : Helper::DataArray<unsigned char>(4) {
382 this->init(); 393 this->init();
383 } 394 }
384 395
385 /// \brief Sets the used channels. 396 /// \brief Sets the used channels.
386 - /// \param channel1 true if channel 1 is filtered.  
387 - /// \param channel2 true if channel 2 is filtered.  
388 - BulkSetFilter2250::BulkSetFilter2250(bool channel1, bool channel2) : Helper::DataArray<unsigned char>(4) { 397 + /// \param usedChannels The UsedChannels value.
  398 + BulkSetChannels2250::BulkSetChannels2250(unsigned char usedChannels) : Helper::DataArray<unsigned char>(4) {
389 this->init(); 399 this->init();
390 400
391 - this->setChannel(0, channel1);  
392 - this->setChannel(1, channel2); 401 + this->setUsedChannels(usedChannels);
393 } 402 }
394 403
395 - /// \brief Gets the filtering state of one channel.  
396 - /// \param channel The channel whose filtering state should be returned.  
397 - /// \return The filtering state of the channel.  
398 - bool BulkSetFilter2250::getChannel(unsigned int channel) {  
399 - FilterBits *filterBits = (FilterBits *) &(this->array[2]);  
400 - if(channel == 0)  
401 - return filterBits->channel1 == 1;  
402 - else  
403 - return filterBits->channel2 == 1; 404 + /// \brief Get the UsedChannels value
  405 + /// \return The UsedChannels value.
  406 + unsigned char BulkSetChannels2250::getUsedChannels() {
  407 + return this->array[2];
404 } 408 }
405 409
406 - /// \brief Enables/disables filtering of one channel.  
407 - /// \param channel The channel that should be set.  
408 - /// \param filtered true if the channel should be filtered.  
409 - void BulkSetFilter2250::setChannel(unsigned int channel, bool filtered) {  
410 - FilterBits *filterBits = (FilterBits *) &(this->array[2]);  
411 - if(channel == 0)  
412 - filterBits->channel1 = filtered ? 1 : 0;  
413 - else  
414 - filterBits->channel2 = filtered ? 1 : 0; 410 + /// \brief Set the UsedChannels to the given value.
  411 + /// \param value The new UsedChannels value.
  412 + void BulkSetChannels2250::setUsedChannels(unsigned char value) {
  413 + this->array[2] = value;
415 } 414 }
416 415
417 /// \brief Initialize the array to the needed values. 416 /// \brief Initialize the array to the needed values.
418 - void BulkSetFilter2250::init() {  
419 - this->array[0] = BULK_BSETFILTER; 417 + void BulkSetChannels2250::init() {
  418 + this->array[0] = BULK_BSETCHANNELS;
420 } 419 }
421 420
422 421
openhantek/src/hantek/types.h
@@ -36,7 +36,9 @@ @@ -36,7 +36,9 @@
36 #define HANTEK_EP_OUT 0x02 ///< OUT Endpoint for bulk transfers 36 #define HANTEK_EP_OUT 0x02 ///< OUT Endpoint for bulk transfers
37 #define HANTEK_EP_IN 0x86 ///< IN Endpoint for bulk transfers 37 #define HANTEK_EP_IN 0x86 ///< IN Endpoint for bulk transfers
38 #define HANTEK_TIMEOUT 500 ///< Timeout for USB transfers in ms 38 #define HANTEK_TIMEOUT 500 ///< Timeout for USB transfers in ms
39 -#define HANTEK_ATTEMPTS_DEFAULT 3 ///< The number of transfer attempts 39 +#define HANTEK_TIMEOUT_MULTI 10 ///< Timeout for multi packet USB transfers in ms
  40 +#define HANTEK_ATTEMPTS 3 ///< The number of transfer attempts
  41 +#define HANTEK_ATTEMPTS_MULTI 1 ///< The number of multi packet transfer attempts
40 42
41 #define HANTEK_CHANNELS 2 ///< Number of physical channels 43 #define HANTEK_CHANNELS 2 ///< Number of physical channels
42 #define HANTEK_SPECIAL_CHANNELS 2 ///< Number of special channels 44 #define HANTEK_SPECIAL_CHANNELS 2 ///< Number of special channels
@@ -57,7 +59,7 @@ namespace Hantek { @@ -57,7 +59,7 @@ namespace Hantek {
57 /// <table> 59 /// <table>
58 /// <tr> 60 /// <tr>
59 /// <td>0x00</td> 61 /// <td>0x00</td>
60 - /// <td>0x0f</td> 62 + /// <td>0x00</td>
61 /// <td>FilterBits</td> 63 /// <td>FilterBits</td>
62 /// <td>0x00</td> 64 /// <td>0x00</td>
63 /// <td>0x00</td> 65 /// <td>0x00</td>
@@ -67,6 +69,8 @@ namespace Hantek { @@ -67,6 +69,8 @@ namespace Hantek {
67 /// </tr> 69 /// </tr>
68 /// </table> 70 /// </table>
69 /// </p> 71 /// </p>
  72 + /// <p>
  73 + /// This command is used by the official %Hantek software, but doesn't seem to be used by the device.
70 /// <p><br /></p> 74 /// <p><br /></p>
71 BULK_SETFILTER, 75 BULK_SETFILTER,
72 76
@@ -79,8 +83,8 @@ namespace Hantek { @@ -79,8 +83,8 @@ namespace Hantek {
79 /// <td>0x00</td> 83 /// <td>0x00</td>
80 /// <td>Tsr1Bits</td> 84 /// <td>Tsr1Bits</td>
81 /// <td>Tsr2Bits</td> 85 /// <td>Tsr2Bits</td>
82 - /// <td>SamplerateSlow[0]</td>  
83 - /// <td>SamplerateSlow[1]</td> 86 + /// <td>Downsampler[0]</td>
  87 + /// <td>Downsampler[1]</td>
84 /// </tr> 88 /// </tr>
85 /// </table> 89 /// </table>
86 /// <table> 90 /// <table>
@@ -95,11 +99,20 @@ namespace Hantek { @@ -95,11 +99,20 @@ namespace Hantek {
95 /// </table> 99 /// </table>
96 /// </p> 100 /// </p>
97 /// <p> 101 /// <p>
98 - /// The samplerate is set relative to the maximum sample rate by a divider that is set in Tsr1Bits.samplerateFast and the 16-bit value in the two SamplerateSlow bytes.<br />  
99 - /// Without using fast rate mode, the samplerate is:<br />  
100 - /// <i>Samplerate = SamplerateMax / (1comp(SamplerateSlow) * 2 + Tsr1Bits.samplerateFast)</i><br />  
101 - /// SamplerateMax is 50 MHz for the DSO-2090.<br />  
102 - /// When using fast rate mode the resulting samplerate is twice (For DSO-2150 three times) as fast, when using the large buffer it is half as fast. When Tsr1Bits.recordLength is 0 (Roll mode) the sampling rate is divided by 1000. Setting Tsr1Bits.samplerateFast to 0 doesn't work, the result will be the same as Tsr1Bits.samplerateFast = 1. SamplerateSlow can't be used together with fast rate mode, the result is always the the same as SlowValue = 0. 102 + /// The samplerate is set relative to the base samplerate by a divider or to a maximum samplerate.<br />
  103 + /// This divider is set by Tsr1Bits.samplerateId for values up to 5 with to the following values:
  104 + /// <table>
  105 + /// <tr>
  106 + /// <td><b>Tsr1Bits.samplerateId</b></td><td>0</td><td>1</td><td>2</td><td>3</td>
  107 + /// </tr>
  108 + /// <tr>
  109 + /// <td><b>Samplerate</b></td><td>Max</td><td>Base</td><td>Base / 2</td><td>Base / 5</td>
  110 + /// </tr>
  111 + /// </table>
  112 + /// For higher divider values, the value can be set using the 16-bit value in the two Downsampler bytes. The value of Downsampler is given by:<br />
  113 + /// <i>Downsampler = 1comp((Base / Samplerate / 2) - 2)</i><br />
  114 + /// The Base samplerate is 50 MS/s for the DSO-2090 and DSO-2150. The Max samplerate is also 50 MS/s for the DSO-2090 and 75 MS/s for the DSO-2150.<br />
  115 + /// When using fast rate mode the Base and Max samplerate is twice as fast. When Tsr1Bits.recordLength is 0 (Roll mode) the sampling rate is divided by 1000.
103 /// </p> 116 /// </p>
104 /// <p> 117 /// <p>
105 /// The TriggerPosition sets the position of the pretrigger in samples. The left side (0 %) is 0x77660 when using the small buffer and 0x78000 when using the large buffer. 118 /// The TriggerPosition sets the position of the pretrigger in samples. The left side (0 %) is 0x77660 when using the small buffer and 0x78000 when using the large buffer.
@@ -225,7 +238,7 @@ namespace Hantek { @@ -225,7 +238,7 @@ namespace Hantek {
225 /// <table> 238 /// <table>
226 /// <tr> 239 /// <tr>
227 /// <td>0x07</td> 240 /// <td>0x07</td>
228 - /// <td>0x0f</td> 241 + /// <td>0x00</td>
229 /// <td>GainBits</td> 242 /// <td>GainBits</td>
230 /// <td>0x00</td> 243 /// <td>0x00</td>
231 /// <td>0x00</td> 244 /// <td>0x00</td>
@@ -245,7 +258,7 @@ namespace Hantek { @@ -245,7 +258,7 @@ namespace Hantek {
245 /// <table> 258 /// <table>
246 /// <tr> 259 /// <tr>
247 /// <td>0x08</td> 260 /// <td>0x08</td>
248 - /// <td>0x0f</td> 261 + /// <td>0x00</td>
249 /// <td>Data | 0x01</td> 262 /// <td>Data | 0x01</td>
250 /// <td>0x00</td> 263 /// <td>0x00</td>
251 /// <td>0x00</td> 264 /// <td>0x00</td>
@@ -293,20 +306,20 @@ namespace Hantek { @@ -293,20 +306,20 @@ namespace Hantek {
293 /// <p><br /></p> 306 /// <p><br /></p>
294 BULK_AUNKNOWN, 307 BULK_AUNKNOWN,
295 308
296 - /// BulkSetFilter2250 [<em>::MODEL_DSO2250</em>] 309 + /// BulkSetChannels2250 [<em>::MODEL_DSO2250</em>]
297 /// <p> 310 /// <p>
298 /// This command sets the activated channels for the DSO-2250: 311 /// This command sets the activated channels for the DSO-2250:
299 /// <table> 312 /// <table>
300 /// <tr> 313 /// <tr>
301 /// <td>0x0b</td> 314 /// <td>0x0b</td>
302 /// <td>0x00</td> 315 /// <td>0x00</td>
303 - /// <td>FilterBits</td> 316 + /// <td>BUsedChannels</td>
304 /// <td>0x00</td> 317 /// <td>0x00</td>
305 /// </tr> 318 /// </tr>
306 /// </table> 319 /// </table>
307 /// </p> 320 /// </p>
308 /// <p><br /></p> 321 /// <p><br /></p>
309 - BULK_BSETFILTER, 322 + BULK_BSETCHANNELS,
310 323
311 /// BulkSetTrigger2250 [<em>::MODEL_DSO2250</em>] 324 /// BulkSetTrigger2250 [<em>::MODEL_DSO2250</em>]
312 /// <p> 325 /// <p>
@@ -314,10 +327,10 @@ namespace Hantek { @@ -314,10 +327,10 @@ namespace Hantek {
314 /// <table> 327 /// <table>
315 /// <tr> 328 /// <tr>
316 /// <td>0x0c</td> 329 /// <td>0x0c</td>
317 - /// <td>0x0f</td> 330 + /// <td>0x00</td>
318 /// <td>CTriggerBits</td> 331 /// <td>CTriggerBits</td>
319 /// <td>0x00</td> 332 /// <td>0x00</td>
320 - /// <td>0x02</td> 333 + /// <td>0x00</td>
321 /// <td>0x00</td> 334 /// <td>0x00</td>
322 /// <td>0x00</td> 335 /// <td>0x00</td>
323 /// <td>0x00</td> 336 /// <td>0x00</td>
@@ -340,9 +353,10 @@ namespace Hantek { @@ -340,9 +353,10 @@ namespace Hantek {
340 /// </table> 353 /// </table>
341 /// </p> 354 /// </p>
342 /// <p> 355 /// <p>
343 - /// The values are similar to the ones used with ::BULK_SETTRIGGERANDSAMPLERATE. The formula is a bit different here:<br /> 356 + /// The samplerate is set relative to the maximum sample rate by a divider that is set in SamplerateFast and the 16-bit value in the two SamplerateSlow bytes.<br />
  357 + /// Without using fast rate mode, the samplerate is:<br />
344 /// <i>Samplerate = SamplerateMax / (2comp(SamplerateSlow) * 2 + 4 - SamplerateFast)</i><br /> 358 /// <i>Samplerate = SamplerateMax / (2comp(SamplerateSlow) * 2 + 4 - SamplerateFast)</i><br />
345 - /// SamplerateMax is 100 MS/s for the DSO-5200 in default configuration and 250 MS/s in fast rate mode though, the modifications regarding record length are the the same that apply for the DSO-2090. 359 + /// SamplerateBase is 100 MS/s for the DSO-5200 in normal mode and 200 MS/s in fast rate mode, the modifications regarding record length are the the same that apply for the DSO-2090. The maximum samplerate is 125 MS/s in normal mode and 250 MS/s in fast rate mode, and is reached by setting SamplerateSlow = 0 and SamplerateFast = 4.
346 /// </p> 360 /// </p>
347 /// <p><br /></p> 361 /// <p><br /></p>
348 BULK_CSETTRIGGERORSAMPLERATE, 362 BULK_CSETTRIGGERORSAMPLERATE,
@@ -397,17 +411,17 @@ namespace Hantek { @@ -397,17 +411,17 @@ namespace Hantek {
397 /// <td>0x00</td> 411 /// <td>0x00</td>
398 /// <td>ESamplerateBits</td> 412 /// <td>ESamplerateBits</td>
399 /// <td>0x00</td> 413 /// <td>0x00</td>
400 - /// <td>SamplerateSlow[0]</td>  
401 - /// <td>SamplerateSlow[1]</td> 414 + /// <td>Samplerate[0]</td>
  415 + /// <td>Samplerate[1]</td>
402 /// <td>0x00</td> 416 /// <td>0x00</td>
403 /// <td>0x00</td> 417 /// <td>0x00</td>
404 /// </tr> 418 /// </tr>
405 /// </table> 419 /// </table>
406 /// </p> 420 /// </p>
407 /// <p> 421 /// <p>
408 - /// The values are similar to the ones used with ::BULK_SETTRIGGERANDSAMPLERATE. The formula is a bit different here:<br />  
409 - /// <i>Samplerate = SamplerateMax / (2comp(SamplerateSlow) * 2 + ESamplerateBits.samplerateFast)</i><br />  
410 - /// SamplerateMax is 100 MS/s for the DSO-2250 in default configuration and 250 MS/s in fast rate mode though, the modifications regarding record length are the the same that apply for the DSO-2090. 422 + /// The downsampler can be activated by setting ESamplerateBits.downsampling = 1. If this is the case, the value of Downsampler is given by:<br />
  423 + /// <i>Downsampler = 1comp((Base / Samplerate) - 2)</i><br />
  424 + /// Base is 100 MS/s for the DSO-2250 in standard mode and 200 MS/s in fast rate mode, the modifications regarding record length are the the same that apply for the DSO-2090. The maximum samplerate is 125 MS/s in standard mode and 250 MS/s in fast rate mode and is achieved by setting ESamplerateBits.downsampling = 0.
411 /// </p> 425 /// </p>
412 /// <p><br /></p> 426 /// <p><br /></p>
413 /// BulkSetTrigger5200 [<em>::MODEL_DSO5200, ::MODEL_DSO5200A</em>] 427 /// BulkSetTrigger5200 [<em>::MODEL_DSO5200, ::MODEL_DSO5200A</em>]
@@ -436,25 +450,25 @@ namespace Hantek { @@ -436,25 +450,25 @@ namespace Hantek {
436 /// <tr> 450 /// <tr>
437 /// <td>0x0f</td> 451 /// <td>0x0f</td>
438 /// <td>0x00</td> 452 /// <td>0x00</td>
439 - /// <td>TriggerPositionPre[0]</td>  
440 - /// <td>TriggerPositionPre[1]</td>  
441 - /// <td>FBuffer1Bits</td> 453 + /// <td>TriggerPositionPost[0]</td>
  454 + /// <td>TriggerPositionPost[1]</td>
  455 + /// <td>TriggerPositionPost[2]</td>
442 /// <td>0x00</td> 456 /// <td>0x00</td>
443 /// </tr> 457 /// </tr>
444 /// </table> 458 /// </table>
445 /// <table> 459 /// <table>
446 /// <tr> 460 /// <tr>
447 - /// <td>TriggerPositionPost[0]</td>  
448 - /// <td>TriggerPositionPost[1]</td>  
449 - /// <td>FBuffer1Bits</td> 461 + /// <td>TriggerPositionPre[0]</td>
  462 + /// <td>TriggerPositionPre[1]</td>
  463 + /// <td>TriggerPositionPre[2]</td>
  464 + /// <td>0x00</td>
450 /// <td>0x00</td> 465 /// <td>0x00</td>
451 - /// <td>FBuffer2Bits</td>  
452 /// <td>0x00</td> 466 /// <td>0x00</td>
453 /// </tr> 467 /// </tr>
454 /// </table> 468 /// </table>
455 /// </p> 469 /// </p>
456 /// <p> 470 /// <p>
457 - /// The TriggerPositionPre and TriggerPositionPost values set the pretrigger position. Both values have a range from 0xd7ff (0xc7ff for 14 kiS buffer) to 0xfffe. On the left side (0 %) the TriggerPositionPre value is minimal, on the right side (100 %) it is maximal. The TriggerPositionPost value is maximal for 0 % and minimal for 100%. 471 + /// The TriggerPositionPre and TriggerPositionPost values set the pretrigger position. Both values have a range from 0x7d800 (0x00000 for 512 kiS buffer) to 0x7ffff. On the left side (0 %) the TriggerPositionPre value is minimal, on the right side (100 %) it is maximal. The TriggerPositionPost value is maximal for 0 % and minimal for 100%.
458 /// </p> 472 /// </p>
459 /// <p><br /></p> 473 /// <p><br /></p>
460 BULK_FSETBUFFER, 474 BULK_FSETBUFFER,
@@ -703,6 +717,16 @@ namespace Hantek { @@ -703,6 +717,16 @@ namespace Hantek {
703 }; 717 };
704 718
705 ////////////////////////////////////////////////////////////////////////////// 719 //////////////////////////////////////////////////////////////////////////////
  720 + /// \enum BUsedChannels hantek/types.h
  721 + /// \brief The enabled channels for the DSO-2250.
  722 + enum BUsedChannels {
  723 + BUSED_CH1, ///< Only channel 1 is activated
  724 + BUSED_NONE, ///< No channels are activated
  725 + BUSED_CH1CH2, ///< Channel 1 and 2 are both activated
  726 + BUSED_CH2 ///< Only channel 2 is activated
  727 + };
  728 +
  729 + //////////////////////////////////////////////////////////////////////////////
706 /// \enum DTriggerPositionUsed hantek/types.h 730 /// \enum DTriggerPositionUsed hantek/types.h
707 /// \brief The trigger position states for the 0x0d command. 731 /// \brief The trigger position states for the 0x0d command.
708 enum DTriggerPositionUsed { 732 enum DTriggerPositionUsed {
@@ -711,14 +735,6 @@ namespace Hantek { @@ -711,14 +735,6 @@ namespace Hantek {
711 }; 735 };
712 736
713 ////////////////////////////////////////////////////////////////////////////// 737 //////////////////////////////////////////////////////////////////////////////
714 - /// \enum FTriggerPositionUsed hantek/types.h  
715 - /// \brief The trigger position states for the 0x0f command.  
716 - enum FTriggerPositionUsed {  
717 - FTRIGGERPOSITION_OFF = 0, ///< Used for Roll mode  
718 - FTRIGGERPOSITION_ON = 3 ///< Used for normal operation  
719 - };  
720 -  
721 - //////////////////////////////////////////////////////////////////////////////  
722 /// \struct FilterBits hantek/types.h 738 /// \struct FilterBits hantek/types.h
723 /// \brief The bits for BULK_SETFILTER. 739 /// \brief The bits for BULK_SETFILTER.
724 struct FilterBits { 740 struct FilterBits {
@@ -743,7 +759,8 @@ namespace Hantek { @@ -743,7 +759,8 @@ namespace Hantek {
743 struct Tsr1Bits { 759 struct Tsr1Bits {
744 unsigned char triggerSource:2; ///< The trigger source, see Hantek::TriggerSource 760 unsigned char triggerSource:2; ///< The trigger source, see Hantek::TriggerSource
745 unsigned char recordLength:3; ///< See ::RecordLengthId 761 unsigned char recordLength:3; ///< See ::RecordLengthId
746 - unsigned char samplerateFast:3; ///< samplerate value for fast sampling rates 762 + unsigned char samplerateId:2; ///< Samplerate ID when downsampler is disabled
  763 + unsigned char downsamplingMode:1; ///< true, if Downsampler is used
747 }; 764 };
748 765
749 ////////////////////////////////////////////////////////////////////////////// 766 //////////////////////////////////////////////////////////////////////////////
@@ -795,23 +812,6 @@ namespace Hantek { @@ -795,23 +812,6 @@ namespace Hantek {
795 }; 812 };
796 813
797 ////////////////////////////////////////////////////////////////////////////// 814 //////////////////////////////////////////////////////////////////////////////
798 - /// \struct FBuffer1Bits hantek/types.h  
799 - /// \brief Buffer mode bits for 0x0f command (Byte 1).  
800 - struct FBuffer1Bits {  
801 - unsigned char triggerPositionUsed:2; ///< See ::DTriggerPositionUsed  
802 - unsigned char largeBuffer:1; ///< false, if ::RecordLengthId is ::RECORDLENGTHID_LARGE  
803 - unsigned char reserved:5; ///< Unused bits  
804 - };  
805 -  
806 - //////////////////////////////////////////////////////////////////////////////  
807 - /// \struct FBuffer2Bits hantek/types.h  
808 - /// \brief Buffer mode bits for 0x0f command (Byte 2).  
809 - struct FBuffer2Bits {  
810 - unsigned char reserved:7; ///< Unused bits  
811 - unsigned char slowBuffer:1; ///< false, if ::RecordLengthId is ::RECORDLENGTHID_SMALL  
812 - };  
813 -  
814 - //////////////////////////////////////////////////////////////////////////////  
815 /// \class BulkSetFilter hantek/types.h 815 /// \class BulkSetFilter hantek/types.h
816 /// \brief The BULK_SETFILTER builder. 816 /// \brief The BULK_SETFILTER builder.
817 class BulkSetFilter : public Helper::DataArray<unsigned char> { 817 class BulkSetFilter : public Helper::DataArray<unsigned char> {
@@ -834,22 +834,24 @@ namespace Hantek { @@ -834,22 +834,24 @@ namespace Hantek {
834 class BulkSetTriggerAndSamplerate : public Helper::DataArray<unsigned char> { 834 class BulkSetTriggerAndSamplerate : public Helper::DataArray<unsigned char> {
835 public: 835 public:
836 BulkSetTriggerAndSamplerate(); 836 BulkSetTriggerAndSamplerate();
837 - BulkSetTriggerAndSamplerate(unsigned short int samplerateSlow, unsigned long int triggerPosition, unsigned char triggerSource = 0, unsigned char recordLength = 0, unsigned char samplerateFast = 0, unsigned char usedChannels = 0, bool fastRate = false, unsigned char triggerSlope = 0); 837 + BulkSetTriggerAndSamplerate(unsigned short int downsampler, unsigned long int triggerPosition, unsigned char triggerSource = 0, unsigned char recordLength = 0, unsigned char samplerateId = 0, bool downsamplingMode = true, unsigned char usedChannels = 0, bool fastRate = false, unsigned char triggerSlope = 0);
838 838
839 unsigned char getTriggerSource(); 839 unsigned char getTriggerSource();
840 void setTriggerSource(unsigned char value); 840 void setTriggerSource(unsigned char value);
841 unsigned char getRecordLength(); 841 unsigned char getRecordLength();
842 void setRecordLength(unsigned char value); 842 void setRecordLength(unsigned char value);
843 - unsigned char getSamplerateFast();  
844 - void setSamplerateFast(unsigned char value); 843 + unsigned char getSamplerateId();
  844 + void setSamplerateId(unsigned char value);
  845 + bool getDownsamplingMode();
  846 + void setDownsamplingMode(bool downsampling);
845 unsigned char getUsedChannels(); 847 unsigned char getUsedChannels();
846 void setUsedChannels(unsigned char value); 848 void setUsedChannels(unsigned char value);
847 bool getFastRate(); 849 bool getFastRate();
848 void setFastRate(bool fastRate); 850 void setFastRate(bool fastRate);
849 unsigned char getTriggerSlope(); 851 unsigned char getTriggerSlope();
850 void setTriggerSlope(unsigned char slope); 852 void setTriggerSlope(unsigned char slope);
851 - unsigned short int getSamplerateSlow();  
852 - void setSamplerateSlow(unsigned short int samplerate); 853 + unsigned short int getDownsampler();
  854 + void setDownsampler(unsigned short int downsampler);
853 unsigned long int getTriggerPosition(); 855 unsigned long int getTriggerPosition();
854 void setTriggerPosition(unsigned long int position); 856 void setTriggerPosition(unsigned long int position);
855 857
@@ -947,15 +949,15 @@ namespace Hantek { @@ -947,15 +949,15 @@ namespace Hantek {
947 }; 949 };
948 950
949 ////////////////////////////////////////////////////////////////////////////// 951 //////////////////////////////////////////////////////////////////////////////
950 - /// \class BulkSetFilter2250 hantek/types.h 952 + /// \class BulkSetChannels2250 hantek/types.h
951 /// \brief The DSO-2250 BULK_BSETFILTER builder. 953 /// \brief The DSO-2250 BULK_BSETFILTER builder.
952 - class BulkSetFilter2250 : public Helper::DataArray<unsigned char> { 954 + class BulkSetChannels2250 : public Helper::DataArray<unsigned char> {
953 public: 955 public:
954 - BulkSetFilter2250();  
955 - BulkSetFilter2250(bool channel1, bool channel2); 956 + BulkSetChannels2250();
  957 + BulkSetChannels2250(unsigned char usedChannels);
956 958
957 - bool getChannel(unsigned int channel);  
958 - void setChannel(unsigned int channel, bool filtered); 959 + unsigned char getUsedChannels();
  960 + void setUsedChannels(unsigned char value);
959 961
960 private: 962 private:
961 void init(); 963 void init();
openhantek/src/openhantek.cpp
@@ -92,61 +92,12 @@ OpenHantekMainWindow::OpenHantekMainWindow(QWidget *parent, Qt::WindowFlags flag @@ -92,61 +92,12 @@ OpenHantekMainWindow::OpenHantekMainWindow(QWidget *parent, Qt::WindowFlags flag
92 this->settings->options.window.position = this->pos(); 92 this->settings->options.window.position = this->pos();
93 this->settings->options.window.size = this->size(); 93 this->settings->options.window.size = this->size();
94 94
95 - // Connect general signals  
96 - connect(this, SIGNAL(settingsChanged()), this, SLOT(applySettings()));  
97 - //connect(this->dsoWidget, SIGNAL(stopped()), this, SLOT(stopped()));  
98 - connect(this->dsoControl, SIGNAL(statusMessage(QString, int)), this->statusBar(), SLOT(showMessage(QString, int)));  
99 - 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 *)));  
100 -  
101 - // Connect signals to DSO controller and widget  
102 - //connect(this->horizontalDock, SIGNAL(formatChanged(HorizontalFormat)), this->dsoWidget, SLOT(horizontalFormatChanged(HorizontalFormat)));  
103 - connect(this->horizontalDock, SIGNAL(timebaseChanged(double)), this, SLOT(updateTimebase()));  
104 - connect(this->horizontalDock, SIGNAL(timebaseChanged(double)), this->dsoWidget, SLOT(updateTimebase()));  
105 - connect(this->horizontalDock, SIGNAL(frequencybaseChanged(double)), this->dsoWidget, SLOT(updateFrequencybase()));  
106 -  
107 - connect(this->triggerDock, SIGNAL(modeChanged(Dso::TriggerMode)), this->dsoControl, SLOT(setTriggerMode(Dso::TriggerMode)));  
108 - connect(this->triggerDock, SIGNAL(modeChanged(Dso::TriggerMode)), this->dsoWidget, SLOT(updateTriggerMode()));  
109 - connect(this->triggerDock, SIGNAL(sourceChanged(bool, unsigned int)), this->dsoControl, SLOT(setTriggerSource(bool, unsigned int)));  
110 - connect(this->triggerDock, SIGNAL(sourceChanged(bool, unsigned int)), this->dsoWidget, SLOT(updateTriggerSource()));  
111 - connect(this->triggerDock, SIGNAL(slopeChanged(Dso::Slope)), this->dsoControl, SLOT(setTriggerSlope(Dso::Slope)));  
112 - connect(this->triggerDock, SIGNAL(slopeChanged(Dso::Slope)), this->dsoWidget, SLOT(updateTriggerSlope()));  
113 - connect(this->dsoWidget, SIGNAL(triggerPositionChanged(double)), this->dsoControl, SLOT(setPretriggerPosition(double)));  
114 - connect(this->dsoWidget, SIGNAL(triggerLevelChanged(unsigned int, double)), this->dsoControl, SLOT(setTriggerLevel(unsigned int, double)));  
115 -  
116 - connect(this->voltageDock, SIGNAL(usedChanged(unsigned int, bool)), this, SLOT(updateUsed(unsigned int)));  
117 - connect(this->voltageDock, SIGNAL(usedChanged(unsigned int, bool)), this->dsoWidget, SLOT(updateVoltageUsed(unsigned int, bool)));  
118 - connect(this->voltageDock, SIGNAL(couplingChanged(unsigned int, Dso::Coupling)), this->dsoControl, SLOT(setCoupling(unsigned int, Dso::Coupling)));  
119 - connect(this->voltageDock, SIGNAL(couplingChanged(unsigned int, Dso::Coupling)), this->dsoWidget, SLOT(updateVoltageCoupling(unsigned int)));  
120 - connect(this->voltageDock, SIGNAL(modeChanged(Dso::MathMode)), this->dsoWidget, SLOT(updateMathMode()));  
121 - connect(this->voltageDock, SIGNAL(gainChanged(unsigned int, double)), this, SLOT(updateVoltageGain(unsigned int)));  
122 - connect(this->voltageDock, SIGNAL(gainChanged(unsigned int, double)), this->dsoWidget, SLOT(updateVoltageGain(unsigned int)));  
123 - connect(this->dsoWidget, SIGNAL(offsetChanged(unsigned int, double)), this, SLOT(updateOffset(unsigned int)));  
124 -  
125 - connect(this->spectrumDock, SIGNAL(usedChanged(unsigned int, bool)), this, SLOT(updateUsed(unsigned int)));  
126 - connect(this->spectrumDock, SIGNAL(usedChanged(unsigned int, bool)), this->dsoWidget, SLOT(updateSpectrumUsed(unsigned int, bool)));  
127 - connect(this->spectrumDock, SIGNAL(magnitudeChanged(unsigned int, double)), this->dsoWidget, SLOT(updateSpectrumMagnitude(unsigned int)));  
128 -  
129 - // Started/stopped signals from oscilloscope  
130 - connect(this->dsoControl, SIGNAL(samplingStarted()), this, SLOT(started()));  
131 - connect(this->dsoControl, SIGNAL(samplingStopped()), this, SLOT(stopped())); 95 + // Connect all signals
  96 + this->connectSignals();
132 97
133 // Set up the oscilloscope 98 // Set up the oscilloscope
134 this->dsoControl->connectDevice(); 99 this->dsoControl->connectDevice();
135 -  
136 - for(unsigned int channel = 0; channel < this->settings->scope.physicalChannels; ++channel) {  
137 - this->dsoControl->setCoupling(channel, (Dso::Coupling) this->settings->scope.voltage[channel].misc);  
138 - this->updateVoltageGain(channel);  
139 - this->updateOffset(channel);  
140 - this->dsoControl->setTriggerLevel(channel, this->settings->scope.voltage[channel].trigger);  
141 - }  
142 - this->updateUsed(this->settings->scope.physicalChannels);  
143 - this->dsoControl->setRecordLength(this->settings->scope.horizontal.samples);  
144 - this->updateTimebase();  
145 - this->dsoControl->setTriggerMode(this->settings->scope.trigger.mode);  
146 - this->dsoControl->setPretriggerPosition(this->settings->scope.trigger.position * this->settings->scope.horizontal.timebase * DIVS_TIME);  
147 - this->dsoControl->setTriggerSlope(this->settings->scope.trigger.slope);  
148 - this->dsoControl->setTriggerSource(this->settings->scope.trigger.special, this->settings->scope.trigger.source);  
149 - 100 + this->initializeDevice();
150 this->dsoControl->startSampling(); 101 this->dsoControl->startSampling();
151 } 102 }
152 103
@@ -202,21 +153,6 @@ void OpenHantekMainWindow::createActions() { @@ -202,21 +153,6 @@ void OpenHantekMainWindow::createActions() {
202 this->startStopAction = new QAction(this); 153 this->startStopAction = new QAction(this);
203 this->startStopAction->setShortcut(tr("Space")); 154 this->startStopAction->setShortcut(tr("Space"));
204 this->stopped(); 155 this->stopped();
205 -  
206 - this->recordLengthActionGroup = new QActionGroup(this);  
207 - connect(this->recordLengthActionGroup, SIGNAL(selected(QAction *)), this, SLOT(recordLengthSelected(QAction *)));  
208 -  
209 - this->recordLengthSmallAction = new QAction(tr("&Small"), this);  
210 - this->recordLengthSmallAction->setActionGroup(this->recordLengthActionGroup);  
211 - this->recordLengthSmallAction->setCheckable(true);  
212 - this->recordLengthSmallAction->setChecked(this->settings->scope.horizontal.samples == 10240);  
213 - this->recordLengthSmallAction->setStatusTip(tr("10240 Samples"));  
214 -  
215 - this->recordLengthLargeAction = new QAction(tr("&Large"), this);  
216 - this->recordLengthLargeAction->setActionGroup(this->recordLengthActionGroup);  
217 - this->recordLengthLargeAction->setCheckable(true);  
218 - this->recordLengthLargeAction->setChecked(this->settings->scope.horizontal.samples != 10240);  
219 - this->recordLengthLargeAction->setStatusTip(tr("32768 Samples"));  
220 156
221 this->digitalPhosphorAction = new QAction(QIcon(":actions/digitalphosphor.png"), tr("Digital &phosphor"), this); 157 this->digitalPhosphorAction = new QAction(QIcon(":actions/digitalphosphor.png"), tr("Digital &phosphor"), this);
222 this->digitalPhosphorAction->setCheckable(true); 158 this->digitalPhosphorAction->setCheckable(true);
@@ -276,12 +212,9 @@ void OpenHantekMainWindow::createMenus() { @@ -276,12 +212,9 @@ void OpenHantekMainWindow::createMenus() {
276 this->oscilloscopeMenu->addSeparator(); 212 this->oscilloscopeMenu->addSeparator();
277 this->oscilloscopeMenu->addAction(this->startStopAction); 213 this->oscilloscopeMenu->addAction(this->startStopAction);
278 #ifdef DEBUG 214 #ifdef DEBUG
  215 + this->oscilloscopeMenu->addSeparator();
279 this->oscilloscopeMenu->addAction(this->commandAction); 216 this->oscilloscopeMenu->addAction(this->commandAction);
280 #endif 217 #endif
281 - this->oscilloscopeMenu->addSeparator();  
282 - this->recordLengthMenu = this->oscilloscopeMenu->addMenu(tr("&Record length"));  
283 - this->recordLengthMenu->addAction(this->recordLengthSmallAction);  
284 - this->recordLengthMenu->addAction(this->recordLengthLargeAction);  
285 218
286 this->menuBar()->addSeparator(); 219 this->menuBar()->addSeparator();
287 220
@@ -337,6 +270,82 @@ void OpenHantekMainWindow::createDockWindows() @@ -337,6 +270,82 @@ void OpenHantekMainWindow::createDockWindows()
337 this->voltageDock = new VoltageDock(this->settings); 270 this->voltageDock = new VoltageDock(this->settings);
338 } 271 }
339 272
  273 +/// \brief Connect general signals and device management signals.
  274 +void OpenHantekMainWindow::connectSignals() {
  275 + // Connect general signals
  276 + connect(this, SIGNAL(settingsChanged()), this, SLOT(applySettings()));
  277 + //connect(this->dsoWidget, SIGNAL(stopped()), this, SLOT(stopped()));
  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 long int> *, double, QMutex *)), this->dataAnalyzer, SLOT(analyze(const QList<double *> *, const QList<unsigned long int> *, double, QMutex *)));
  280 +
  281 + // Connect signals to DSO controller and widget
  282 + connect(this->horizontalDock, SIGNAL(samplerateChanged(double)), this, SLOT(samplerateSelected()));
  283 + connect(this->horizontalDock, SIGNAL(timebaseChanged(double)), this, SLOT(timebaseSelected()));
  284 + connect(this->horizontalDock, SIGNAL(frequencybaseChanged(double)), this->dsoWidget, SLOT(updateFrequencybase(double)));
  285 + connect(this->horizontalDock, SIGNAL(recordLengthChanged(unsigned long)), this, SLOT(recordLengthSelected(unsigned long)));
  286 + //connect(this->horizontalDock, SIGNAL(formatChanged(HorizontalFormat)), this->dsoWidget, SLOT(horizontalFormatChanged(HorizontalFormat)));
  287 +
  288 + connect(this->triggerDock, SIGNAL(modeChanged(Dso::TriggerMode)), this->dsoControl, SLOT(setTriggerMode(Dso::TriggerMode)));
  289 + connect(this->triggerDock, SIGNAL(modeChanged(Dso::TriggerMode)), this->dsoWidget, SLOT(updateTriggerMode()));
  290 + connect(this->triggerDock, SIGNAL(sourceChanged(bool, unsigned int)), this->dsoControl, SLOT(setTriggerSource(bool, unsigned int)));
  291 + connect(this->triggerDock, SIGNAL(sourceChanged(bool, unsigned int)), this->dsoWidget, SLOT(updateTriggerSource()));
  292 + connect(this->triggerDock, SIGNAL(slopeChanged(Dso::Slope)), this->dsoControl, SLOT(setTriggerSlope(Dso::Slope)));
  293 + connect(this->triggerDock, SIGNAL(slopeChanged(Dso::Slope)), this->dsoWidget, SLOT(updateTriggerSlope()));
  294 + connect(this->dsoWidget, SIGNAL(triggerPositionChanged(double)), this->dsoControl, SLOT(setPretriggerPosition(double)));
  295 + connect(this->dsoWidget, SIGNAL(triggerLevelChanged(unsigned int, double)), this->dsoControl, SLOT(setTriggerLevel(unsigned int, double)));
  296 +
  297 + connect(this->voltageDock, SIGNAL(usedChanged(unsigned int, bool)), this, SLOT(updateUsed(unsigned int)));
  298 + connect(this->voltageDock, SIGNAL(usedChanged(unsigned int, bool)), this->dsoWidget, SLOT(updateVoltageUsed(unsigned int, bool)));
  299 + connect(this->voltageDock, SIGNAL(couplingChanged(unsigned int, Dso::Coupling)), this->dsoControl, SLOT(setCoupling(unsigned int, Dso::Coupling)));
  300 + connect(this->voltageDock, SIGNAL(couplingChanged(unsigned int, Dso::Coupling)), this->dsoWidget, SLOT(updateVoltageCoupling(unsigned int)));
  301 + connect(this->voltageDock, SIGNAL(modeChanged(Dso::MathMode)), this->dsoWidget, SLOT(updateMathMode()));
  302 + connect(this->voltageDock, SIGNAL(gainChanged(unsigned int, double)), this, SLOT(updateVoltageGain(unsigned int)));
  303 + connect(this->voltageDock, SIGNAL(gainChanged(unsigned int, double)), this->dsoWidget, SLOT(updateVoltageGain(unsigned int)));
  304 + connect(this->dsoWidget, SIGNAL(offsetChanged(unsigned int, double)), this, SLOT(updateOffset(unsigned int)));
  305 +
  306 + connect(this->spectrumDock, SIGNAL(usedChanged(unsigned int, bool)), this, SLOT(updateUsed(unsigned int)));
  307 + connect(this->spectrumDock, SIGNAL(usedChanged(unsigned int, bool)), this->dsoWidget, SLOT(updateSpectrumUsed(unsigned int, bool)));
  308 + connect(this->spectrumDock, SIGNAL(magnitudeChanged(unsigned int, double)), this->dsoWidget, SLOT(updateSpectrumMagnitude(unsigned int)));
  309 +
  310 + // Started/stopped signals from oscilloscope
  311 + connect(this->dsoControl, SIGNAL(samplingStarted()), this, SLOT(started()));
  312 + connect(this->dsoControl, SIGNAL(samplingStopped()), this, SLOT(stopped()));
  313 +
  314 + //connect(this->dsoControl, SIGNAL(recordLengthChanged(unsigned long)), this, SLOT(recordLengthChanged()));
  315 + connect(this->dsoControl, SIGNAL(recordTimeChanged(double)), this, SLOT(recordTimeChanged(double)));
  316 + connect(this->dsoControl, SIGNAL(samplerateChanged(double)), this, SLOT(samplerateChanged(double)));
  317 +
  318 + connect(this->dsoControl, SIGNAL(availableRecordLengthsChanged(QList<unsigned long int>)), this->horizontalDock, SLOT(availableRecordLengthsChanged(QList<unsigned long int>)));
  319 + connect(this->dsoControl, SIGNAL(samplerateLimitsChanged(double, double)), this->horizontalDock, SLOT(samplerateLimitsChanged(double, double)));
  320 +}
  321 +
  322 +/// \brief Initialize the device with the current settings.
  323 +void OpenHantekMainWindow::initializeDevice() {
  324 + for(unsigned int channel = 0; channel < this->settings->scope.physicalChannels; ++channel) {
  325 + this->dsoControl->setCoupling(channel, (Dso::Coupling) this->settings->scope.voltage[channel].misc);
  326 + this->updateVoltageGain(channel);
  327 + this->updateOffset(channel);
  328 + this->dsoControl->setTriggerLevel(channel, this->settings->scope.voltage[channel].trigger);
  329 + }
  330 + this->updateUsed(this->settings->scope.physicalChannels);
  331 + if(this->dsoControl->getAvailableRecordLengths()->isEmpty())
  332 + this->dsoControl->setRecordLength(this->settings->scope.horizontal.recordLength);
  333 + else
  334 + this->dsoControl->setRecordLength(this->dsoControl->getAvailableRecordLengths()->indexOf(this->settings->scope.horizontal.recordLength));
  335 + if(this->settings->scope.horizontal.samplerateSet)
  336 + this->samplerateSelected();
  337 + else
  338 + this->timebaseSelected();
  339 + this->dsoControl->setTriggerMode(this->settings->scope.trigger.mode);
  340 + this->dsoControl->setPretriggerPosition(this->settings->scope.trigger.position * this->settings->scope.horizontal.timebase * DIVS_TIME);
  341 + this->dsoControl->setTriggerSlope(this->settings->scope.trigger.slope);
  342 + this->dsoControl->setTriggerSource(this->settings->scope.trigger.special, this->settings->scope.trigger.source);
  343 +
  344 + // Apply the limits to the dock widgets
  345 + this->horizontalDock->availableRecordLengthsChanged(*this->dsoControl->getAvailableRecordLengths());
  346 + this->horizontalDock->samplerateLimitsChanged(this->dsoControl->getMinSamplerate(), this->dsoControl->getMaxSamplerate());
  347 +}
  348 +
340 /// \brief Read the settings from an ini file. 349 /// \brief Read the settings from an ini file.
341 /// \param fileName Optional filename to export the settings to a specific file. 350 /// \param fileName Optional filename to export the settings to a specific file.
342 /// \return 0 on success, negative on error. 351 /// \return 0 on success, negative on error.
@@ -598,11 +607,47 @@ void OpenHantekMainWindow::updateSettings() { @@ -598,11 +607,47 @@ void OpenHantekMainWindow::updateSettings() {
598 } 607 }
599 } 608 }
600 609
  610 +/// \brief The oscilloscope changed the record time.
  611 +/// \param duration The new record time duration in seconds.
  612 +void OpenHantekMainWindow::recordTimeChanged(double duration) {
  613 + if(this->settings->scope.horizontal.samplerateSet) {
  614 + // The samplerate was set, let's adapt the timebase accordingly
  615 + this->settings->scope.horizontal.timebase = duration / DIVS_TIME;
  616 + this->horizontalDock->setTimebase(this->settings->scope.horizontal.timebase);
  617 + }
  618 +
  619 + // The trigger position should be kept at the same place but the timebase has changed
  620 + this->dsoControl->setPretriggerPosition(this->settings->scope.trigger.position * this->settings->scope.horizontal.timebase * DIVS_TIME);
  621 +
  622 + this->dsoWidget->updateTimebase(this->settings->scope.horizontal.timebase);
  623 +}
  624 +
  625 +/// \brief The oscilloscope changed the samplerate.
  626 +/// \param samplerate The new samplerate in samples per second.
  627 +void OpenHantekMainWindow::samplerateChanged(double samplerate) {
  628 + if(!this->settings->scope.horizontal.samplerateSet) {
  629 + // The timebase was set, let's adapt the samplerate accordingly
  630 + this->settings->scope.horizontal.samplerate = samplerate;
  631 + this->horizontalDock->setSamplerate(samplerate);
  632 + }
  633 +
  634 + this->dsoWidget->updateSamplerate(samplerate);
  635 +}
  636 +
601 /// \brief Apply new record length to settings. 637 /// \brief Apply new record length to settings.
602 -/// \param action The selected record length menu item.  
603 -void OpenHantekMainWindow::recordLengthSelected(QAction *action) {  
604 - this->settings->scope.horizontal.samples = (action == this->recordLengthSmallAction) ? 10240 : 32768;  
605 - this->dsoControl->setRecordLength(this->settings->scope.horizontal.samples); 638 +/// \param recordLength The selected record length in samples.
  639 +void OpenHantekMainWindow::recordLengthSelected(unsigned long recordLength) {
  640 + this->dsoControl->setRecordLength(recordLength);
  641 +}
  642 +
  643 +/// \brief Sets the samplerate of the oscilloscope.
  644 +void OpenHantekMainWindow::samplerateSelected() {
  645 + this->dsoControl->setSamplerate(this->settings->scope.horizontal.samplerate);
  646 +}
  647 +
  648 +/// \brief Sets the record time of the oscilloscope.
  649 +void OpenHantekMainWindow::timebaseSelected() {
  650 + this->dsoControl->setRecordTime(this->settings->scope.horizontal.timebase * DIVS_TIME);
606 } 651 }
607 652
608 /// \brief Sets the offset of the oscilloscope for the given channel. 653 /// \brief Sets the offset of the oscilloscope for the given channel.
@@ -614,15 +659,6 @@ void OpenHantekMainWindow::updateOffset(unsigned int channel) { @@ -614,15 +659,6 @@ void OpenHantekMainWindow::updateOffset(unsigned int channel) {
614 this->dsoControl->setOffset(channel, (this->settings->scope.voltage[channel].offset / DIVS_VOLTAGE) + 0.5); 659 this->dsoControl->setOffset(channel, (this->settings->scope.voltage[channel].offset / DIVS_VOLTAGE) + 0.5);
615 } 660 }
616 661
617 -/// \brief Sets the samplerate of the oscilloscope.  
618 -void OpenHantekMainWindow::updateTimebase() {  
619 - this->settings->scope.horizontal.samplerate = this->dsoControl->setSamplerate(1e3 / this->settings->scope.horizontal.timebase);  
620 - this->dsoWidget->updateSamplerate();  
621 -  
622 - // The trigger position should be kept at the same place but the timebase has changed  
623 - this->dsoControl->setPretriggerPosition(this->settings->scope.trigger.position * this->settings->scope.horizontal.timebase * DIVS_TIME);  
624 -}  
625 -  
626 /// \brief Sets the state of the given oscilloscope channel. 662 /// \brief Sets the state of the given oscilloscope channel.
627 /// \param channel The channel whose state has changed. 663 /// \param channel The channel whose state has changed.
628 void OpenHantekMainWindow::updateUsed(unsigned int channel) { 664 void OpenHantekMainWindow::updateUsed(unsigned int channel) {
openhantek/src/openhantek.h
@@ -65,6 +65,10 @@ class OpenHantekMainWindow : public QMainWindow { @@ -65,6 +65,10 @@ class OpenHantekMainWindow : public QMainWindow {
65 void createToolBars(); 65 void createToolBars();
66 void createStatusBar(); 66 void createStatusBar();
67 void createDockWindows(); 67 void createDockWindows();
  68 +
  69 + // Device management
  70 + void connectSignals();
  71 + void initializeDevice();
68 72
69 // Settings 73 // Settings
70 int readSettings(const QString &fileName = QString()); 74 int readSettings(const QString &fileName = QString());
@@ -81,8 +85,6 @@ class OpenHantekMainWindow : public QMainWindow { @@ -81,8 +85,6 @@ class OpenHantekMainWindow : public QMainWindow {
81 85
82 QAction *configAction; 86 QAction *configAction;
83 QAction *startStopAction; 87 QAction *startStopAction;
84 - QActionGroup *recordLengthActionGroup;  
85 - QAction *recordLengthSmallAction, *recordLengthLargeAction;  
86 QAction *digitalPhosphorAction, *zoomAction; 88 QAction *digitalPhosphorAction, *zoomAction;
87 89
88 QAction *aboutAction, *aboutQtAction; 90 QAction *aboutAction, *aboutQtAction;
@@ -94,7 +96,7 @@ class OpenHantekMainWindow : public QMainWindow { @@ -94,7 +96,7 @@ class OpenHantekMainWindow : public QMainWindow {
94 // Menus 96 // Menus
95 QMenu *fileMenu; 97 QMenu *fileMenu;
96 QMenu *viewMenu, *dockMenu, *toolbarMenu; 98 QMenu *viewMenu, *dockMenu, *toolbarMenu;
97 - QMenu *oscilloscopeMenu, *recordLengthMenu; 99 + QMenu *oscilloscopeMenu;
98 QMenu *helpMenu; 100 QMenu *helpMenu;
99 101
100 // Toolbars 102 // Toolbars
@@ -143,9 +145,12 @@ class OpenHantekMainWindow : public QMainWindow { @@ -143,9 +145,12 @@ class OpenHantekMainWindow : public QMainWindow {
143 void applySettings(); 145 void applySettings();
144 void updateSettings(); 146 void updateSettings();
145 147
146 - void recordLengthSelected(QAction *action); 148 + void recordTimeChanged(double duration);
  149 + void samplerateChanged(double samplerate);
  150 + void recordLengthSelected(unsigned long recordLength);
  151 + void samplerateSelected();
  152 + void timebaseSelected();
147 void updateOffset(unsigned int channel); 153 void updateOffset(unsigned int channel);
148 - void updateTimebase();  
149 void updateUsed(unsigned int channel); 154 void updateUsed(unsigned int channel);
150 void updateVoltageGain(unsigned int channel); 155 void updateVoltageGain(unsigned int channel);
151 156
openhantek/src/settings.cpp
@@ -64,8 +64,9 @@ DsoSettings::DsoSettings(QWidget *parent) : QObject(parent) { @@ -64,8 +64,9 @@ DsoSettings::DsoSettings(QWidget *parent) : QObject(parent) {
64 this->scope.horizontal.marker[0] = -1.0; 64 this->scope.horizontal.marker[0] = -1.0;
65 this->scope.horizontal.marker[1] = 1.0; 65 this->scope.horizontal.marker[1] = 1.0;
66 this->scope.horizontal.timebase = 1e-3; 66 this->scope.horizontal.timebase = 1e-3;
67 - this->scope.horizontal.samples = 10240; 67 + this->scope.horizontal.recordLength = 0;
68 this->scope.horizontal.samplerate = 1e6; 68 this->scope.horizontal.samplerate = 1e6;
  69 + this->scope.horizontal.samplerateSet = false;
69 // Trigger 70 // Trigger
70 this->scope.trigger.filter = true; 71 this->scope.trigger.filter = true;
71 this->scope.trigger.mode = Dso::TRIGGERMODE_NORMAL; 72 this->scope.trigger.mode = Dso::TRIGGERMODE_NORMAL;
@@ -276,6 +277,12 @@ int DsoSettings::load(const QString &amp;fileName) { @@ -276,6 +277,12 @@ int DsoSettings::load(const QString &amp;fileName) {
276 } 277 }
277 if(settingsLoader->contains("timebase")) 278 if(settingsLoader->contains("timebase"))
278 this->scope.horizontal.timebase = settingsLoader->value("timebase").toDouble(); 279 this->scope.horizontal.timebase = settingsLoader->value("timebase").toDouble();
  280 + if(settingsLoader->contains("recordLength"))
  281 + this->scope.horizontal.recordLength = settingsLoader->value("recordLength").toUInt();
  282 + if(settingsLoader->contains("samplerate"))
  283 + this->scope.horizontal.samplerate = settingsLoader->value("samplerate").toDouble();
  284 + if(settingsLoader->contains("samplerateSet"))
  285 + this->scope.horizontal.samplerateSet = settingsLoader->value("samplerateSet").toBool();
279 settingsLoader->endGroup(); 286 settingsLoader->endGroup();
280 // Trigger 287 // Trigger
281 settingsLoader->beginGroup("trigger"); 288 settingsLoader->beginGroup("trigger");
@@ -449,6 +456,9 @@ int DsoSettings::save(const QString &amp;fileName) { @@ -449,6 +456,9 @@ int DsoSettings::save(const QString &amp;fileName) {
449 for(int marker = 0; marker < 2; ++marker) 456 for(int marker = 0; marker < 2; ++marker)
450 settingsSaver->setValue(QString("marker%1").arg(marker), this->scope.horizontal.marker[marker]); 457 settingsSaver->setValue(QString("marker%1").arg(marker), this->scope.horizontal.marker[marker]);
451 settingsSaver->setValue("timebase", this->scope.horizontal.timebase); 458 settingsSaver->setValue("timebase", this->scope.horizontal.timebase);
  459 + settingsSaver->setValue("recordLength", (unsigned int) this->scope.horizontal.recordLength);
  460 + settingsSaver->setValue("samplerate", this->scope.horizontal.samplerate);
  461 + settingsSaver->setValue("samplerateSet", this->scope.horizontal.samplerateSet);
452 settingsSaver->endGroup(); 462 settingsSaver->endGroup();
453 // Trigger 463 // Trigger
454 settingsSaver->beginGroup("trigger"); 464 settingsSaver->beginGroup("trigger");
@@ -457,6 +467,7 @@ int DsoSettings::save(const QString &amp;fileName) { @@ -457,6 +467,7 @@ int DsoSettings::save(const QString &amp;fileName) {
457 settingsSaver->setValue("position", this->scope.trigger.position); 467 settingsSaver->setValue("position", this->scope.trigger.position);
458 settingsSaver->setValue("slope", this->scope.trigger.slope); 468 settingsSaver->setValue("slope", this->scope.trigger.slope);
459 settingsSaver->setValue("source", this->scope.trigger.source); 469 settingsSaver->setValue("source", this->scope.trigger.source);
  470 + settingsSaver->setValue("special", this->scope.trigger.special);
460 settingsSaver->endGroup(); 471 settingsSaver->endGroup();
461 // Spectrum 472 // Spectrum
462 for(int channel = 0; channel < this->scope.spectrum.count(); ++channel) { 473 for(int channel = 0; channel < this->scope.spectrum.count(); ++channel) {
openhantek/src/settings.h
@@ -93,8 +93,9 @@ struct DsoSettingsScopeHorizontal { @@ -93,8 +93,9 @@ struct DsoSettingsScopeHorizontal {
93 double frequencybase; ///< Frequencybase in Hz/div 93 double frequencybase; ///< Frequencybase in Hz/div
94 double marker[2]; ///< Marker positions in div 94 double marker[2]; ///< Marker positions in div
95 double timebase; ///< Timebase in s/div 95 double timebase; ///< Timebase in s/div
96 - unsigned long int samples; ///< Sample count  
97 - unsigned long int samplerate; ///< The samplerate of the oscilloscope in S 96 + unsigned long int recordLength; ///< Sample count
  97 + double samplerate; ///< The samplerate of the oscilloscope in S
  98 + bool samplerateSet; ///< The samplerate was set by the user, not the timebase
98 }; 99 };
99 100
100 //////////////////////////////////////////////////////////////////////////////// 101 ////////////////////////////////////////////////////////////////////////////////
@@ -105,8 +106,8 @@ struct DsoSettingsScopeTrigger { @@ -105,8 +106,8 @@ struct DsoSettingsScopeTrigger {
105 Dso::TriggerMode mode; ///< Automatic, normal or single trigger 106 Dso::TriggerMode mode; ///< Automatic, normal or single trigger
106 double position; ///< Horizontal position for pretrigger 107 double position; ///< Horizontal position for pretrigger
107 Dso::Slope slope; ///< Rising or falling edge causes trigger 108 Dso::Slope slope; ///< Rising or falling edge causes trigger
108 - bool special; ///< true if the trigger source is not a standard channel  
109 unsigned int source; ///< Channel that is used as trigger source 109 unsigned int source; ///< Channel that is used as trigger source
  110 + bool special; ///< true if the trigger source is not a standard channel
110 }; 111 };
111 112
112 //////////////////////////////////////////////////////////////////////////////// 113 ////////////////////////////////////////////////////////////////////////////////
openhantek/translations/openhantek_de.ts
@@ -270,67 +270,62 @@ @@ -270,67 +270,62 @@
270 <context> 270 <context>
271 <name>DsoWidget</name> 271 <name>DsoWidget</name>
272 <message> 272 <message>
273 - <location filename="../src/dsowidget.cpp" line="284"/> 273 + <location filename="../src/dsowidget.cpp" line="285"/>
274 <source>Zoom x%L1</source> 274 <source>Zoom x%L1</source>
275 <translation>Zoom x%L1</translation> 275 <translation>Zoom x%L1</translation>
276 </message> 276 </message>
277 <message> 277 <message>
278 - <location filename="../src/dsowidget.cpp" line="285"/>  
279 <location filename="../src/dsowidget.cpp" line="286"/> 278 <location filename="../src/dsowidget.cpp" line="286"/>
280 - <location filename="../src/dsowidget.cpp" line="297"/>  
281 - <location filename="../src/dsowidget.cpp" line="323"/>  
282 - <location filename="../src/dsowidget.cpp" line="330"/>  
283 - <location filename="../src/dsowidget.cpp" line="340"/> 279 + <location filename="../src/dsowidget.cpp" line="287"/>
  280 + <location filename="../src/dsowidget.cpp" line="298"/>
  281 + <location filename="../src/dsowidget.cpp" line="324"/>
  282 + <location filename="../src/dsowidget.cpp" line="332"/>
  283 + <location filename="../src/dsowidget.cpp" line="344"/>
284 <source>/div</source> 284 <source>/div</source>
285 <translation>/div</translation> 285 <translation>/div</translation>
286 </message> 286 </message>
287 <message> 287 <message>
288 - <location filename="../src/dsowidget.cpp" line="437"/> 288 + <location filename="../src/dsowidget.cpp" line="441"/>
289 <source>Portable Document Format (*.pdf)</source> 289 <source>Portable Document Format (*.pdf)</source>
290 <translation>Portables Dokumentenformat (*.pdf)</translation> 290 <translation>Portables Dokumentenformat (*.pdf)</translation>
291 </message> 291 </message>
292 <message> 292 <message>
293 - <location filename="../src/dsowidget.cpp" line="438"/> 293 + <location filename="../src/dsowidget.cpp" line="442"/>
294 <source>PostScript (*.ps)</source> 294 <source>PostScript (*.ps)</source>
295 <translation>PostScript (*.ps)</translation> 295 <translation>PostScript (*.ps)</translation>
296 </message> 296 </message>
297 <message> 297 <message>
298 - <location filename="../src/dsowidget.cpp" line="442"/> 298 + <location filename="../src/dsowidget.cpp" line="446"/>
299 <source>Export file...</source> 299 <source>Export file...</source>
300 <translation>Datei exportieren...</translation> 300 <translation>Datei exportieren...</translation>
301 </message> 301 </message>
302 <message> 302 <message>
303 - <location filename="../src/dsowidget.cpp" line="477"/> 303 + <location filename="../src/dsowidget.cpp" line="481"/>
304 <source>Marker 1/2</source> 304 <source>Marker 1/2</source>
305 <translation>Marker 1/2</translation> 305 <translation>Marker 1/2</translation>
306 </message> 306 </message>
307 <message> 307 <message>
308 - <location filename="../src/dsowidget.cpp" line="309"/> 308 + <location filename="../src/dsowidget.cpp" line="310"/>
309 <source>%L1%</source> 309 <source>%L1%</source>
310 <translation>%L1%</translation> 310 <translation>%L1%</translation>
311 </message> 311 </message>
312 <message> 312 <message>
313 - <location filename="../src/dsowidget.cpp" line="310"/> 313 + <location filename="../src/dsowidget.cpp" line="311"/>
314 <source>%1 %2 %3 %4</source> 314 <source>%1 %2 %3 %4</source>
315 <translation>%1 %2 %3 %4</translation> 315 <translation>%1 %2 %3 %4</translation>
316 </message> 316 </message>
317 <message> 317 <message>
318 - <location filename="../src/dsowidget.cpp" line="335"/> 318 + <location filename="../src/dsowidget.cpp" line="338"/>
319 <source>/s</source> 319 <source>/s</source>
320 <translation>/s</translation> 320 <translation>/s</translation>
321 </message> 321 </message>
322 <message> 322 <message>
323 - <location filename="../src/dsowidget.cpp" line="429"/>  
324 - <source>%1 S</source>  
325 - <translation>%1 S</translation>  
326 - </message>  
327 - <message>  
328 - <location filename="../src/dsowidget.cpp" line="439"/> 323 + <location filename="../src/dsowidget.cpp" line="443"/>
329 <source>Image (*.png *.xpm *.jpg)</source> 324 <source>Image (*.png *.xpm *.jpg)</source>
330 <translation>Bild (*.png *.xpm *.jpg)</translation> 325 <translation>Bild (*.png *.xpm *.jpg)</translation>
331 </message> 326 </message>
332 <message> 327 <message>
333 - <location filename="../src/dsowidget.cpp" line="440"/> 328 + <location filename="../src/dsowidget.cpp" line="444"/>
334 <source>Comma-Separated Values (*.csv)</source> 329 <source>Comma-Separated Values (*.csv)</source>
335 <translation>Kommagetrennte Werte (*.csv)</translation> 330 <translation>Kommagetrennte Werte (*.csv)</translation>
336 </message> 331 </message>
@@ -343,42 +338,42 @@ @@ -343,42 +338,42 @@
343 <translation>Oszillograph drucken</translation> 338 <translation>Oszillograph drucken</translation>
344 </message> 339 </message>
345 <message> 340 <message>
346 - <location filename="../src/exporter.cpp" line="127"/> 341 + <location filename="../src/exporter.cpp" line="129"/>
347 <source>%L1%</source> 342 <source>%L1%</source>
348 <translation>%L1%</translation> 343 <translation>%L1%</translation>
349 </message> 344 </message>
350 <message> 345 <message>
351 - <location filename="../src/exporter.cpp" line="128"/> 346 + <location filename="../src/exporter.cpp" line="130"/>
352 <source>%1 %2 %3 %4</source> 347 <source>%1 %2 %3 %4</source>
353 <translation>%1 %2 %3 %4</translation> 348 <translation>%1 %2 %3 %4</translation>
354 </message> 349 </message>
355 <message> 350 <message>
356 - <location filename="../src/exporter.cpp" line="132"/> 351 + <location filename="../src/exporter.cpp" line="134"/>
357 <source>%1 S</source> 352 <source>%1 S</source>
358 <translation>%1 S</translation> 353 <translation>%1 S</translation>
359 </message> 354 </message>
360 <message> 355 <message>
361 - <location filename="../src/exporter.cpp" line="134"/> 356 + <location filename="../src/exporter.cpp" line="136"/>
362 <source>/s</source> 357 <source>/s</source>
363 <translation>/s</translation> 358 <translation>/s</translation>
364 </message> 359 </message>
365 <message> 360 <message>
366 - <location filename="../src/exporter.cpp" line="136"/>  
367 <location filename="../src/exporter.cpp" line="138"/> 361 <location filename="../src/exporter.cpp" line="138"/>
368 - <location filename="../src/exporter.cpp" line="158"/>  
369 - <location filename="../src/exporter.cpp" line="161"/>  
370 - <location filename="../src/exporter.cpp" line="191"/>  
371 - <location filename="../src/exporter.cpp" line="192"/> 362 + <location filename="../src/exporter.cpp" line="140"/>
  363 + <location filename="../src/exporter.cpp" line="160"/>
  364 + <location filename="../src/exporter.cpp" line="163"/>
  365 + <location filename="../src/exporter.cpp" line="193"/>
  366 + <location filename="../src/exporter.cpp" line="194"/>
372 <source>/div</source> 367 <source>/div</source>
373 <translation>/div</translation> 368 <translation>/div</translation>
374 </message> 369 </message>
375 <message> 370 <message>
376 - <location filename="../src/exporter.cpp" line="186"/> 371 + <location filename="../src/exporter.cpp" line="188"/>
377 <source>Zoom x%L1</source> 372 <source>Zoom x%L1</source>
378 <translation>Zoom x%L1</translation> 373 <translation>Zoom x%L1</translation>
379 </message> 374 </message>
380 <message> 375 <message>
381 - <location filename="../src/exporter.cpp" line="198"/> 376 + <location filename="../src/exporter.cpp" line="200"/>
382 <source>Marker 1/2</source> 377 <source>Marker 1/2</source>
383 <translation>Marker 1/2</translation> 378 <translation>Marker 1/2</translation>
384 </message> 379 </message>
@@ -386,27 +381,27 @@ @@ -386,27 +381,27 @@
386 <context> 381 <context>
387 <name>Hantek::Control</name> 382 <name>Hantek::Control</name>
388 <message> 383 <message>
389 - <location filename="../src/hantek/control.cpp" line="56"/> 384 + <location filename="../src/hantek/control.cpp" line="92"/>
390 <source>EXT</source> 385 <source>EXT</source>
391 <translation>EXT</translation> 386 <translation>EXT</translation>
392 </message> 387 </message>
393 <message> 388 <message>
394 - <location filename="../src/hantek/control.cpp" line="56"/> 389 + <location filename="../src/hantek/control.cpp" line="92"/>
395 <source>EXT/10</source> 390 <source>EXT/10</source>
396 <translation>EXT/10</translation> 391 <translation>EXT/10</translation>
397 </message> 392 </message>
398 <message> 393 <message>
399 - <location filename="../src/hantek/control.cpp" line="268"/> 394 + <location filename="../src/hantek/control.cpp" line="322"/>
400 <source>The device has been disconnected</source> 395 <source>The device has been disconnected</source>
401 <translation>Die Verbindung zum Gerรคt wurde getrennt</translation> 396 <translation>Die Verbindung zum Gerรคt wurde getrennt</translation>
402 </message> 397 </message>
403 <message> 398 <message>
404 - <location filename="../src/hantek/control.cpp" line="527"/> 399 + <location filename="../src/hantek/control.cpp" line="875"/>
405 <source>Unknown model</source> 400 <source>Unknown model</source>
406 <translation>Unbekanntes Modell</translation> 401 <translation>Unbekanntes Modell</translation>
407 </message> 402 </message>
408 <message> 403 <message>
409 - <location filename="../src/hantek/control.cpp" line="562"/> 404 + <location filename="../src/hantek/control.cpp" line="985"/>
410 <source>Couldn&apos;t get channel level data from oscilloscope</source> 405 <source>Couldn&apos;t get channel level data from oscilloscope</source>
411 <translation>Konnte Kanalpegeldaten des Oszilloskops nicht lesen</translation> 406 <translation>Konnte Kanalpegeldaten des Oszilloskops nicht lesen</translation>
412 </message> 407 </message>
@@ -414,41 +409,41 @@ @@ -414,41 +409,41 @@
414 <context> 409 <context>
415 <name>Hantek::Device</name> 410 <name>Hantek::Device</name>
416 <message> 411 <message>
417 - <location filename="../src/hantek/device.cpp" line="71"/> 412 + <location filename="../src/hantek/device.cpp" line="72"/>
418 <source>Can&apos;t search for Hantek oscilloscopes: %1</source> 413 <source>Can&apos;t search for Hantek oscilloscopes: %1</source>
419 <translation>Suche nach Hantek Oszilloskopen fehlgeschlagen: %1</translation> 414 <translation>Suche nach Hantek Oszilloskopen fehlgeschlagen: %1</translation>
420 </message> 415 </message>
421 <message> 416 <message>
422 - <location filename="../src/hantek/device.cpp" line="129"/>  
423 - <location filename="../src/hantek/device.cpp" line="210"/> 417 + <location filename="../src/hantek/device.cpp" line="123"/>
  418 + <location filename="../src/hantek/device.cpp" line="204"/>
424 <source>Failed to claim interface %1 of device %2: %3</source> 419 <source>Failed to claim interface %1 of device %2: %3</source>
425 <translation>Anforderung der Schnittstelle %1 des Gerรคtes %2 fehlgeschlagen: %3</translation> 420 <translation>Anforderung der Schnittstelle %1 des Gerรคtes %2 fehlgeschlagen: %3</translation>
426 </message> 421 </message>
427 <message> 422 <message>
428 - <location filename="../src/hantek/device.cpp" line="149"/>  
429 - <location filename="../src/hantek/device.cpp" line="230"/> 423 + <location filename="../src/hantek/device.cpp" line="143"/>
  424 + <location filename="../src/hantek/device.cpp" line="224"/>
430 <source>Device found: Hantek %1 (%2)</source> 425 <source>Device found: Hantek %1 (%2)</source>
431 <translation>Gerรคt gefunden: Hantek %1 (%2)</translation> 426 <translation>Gerรคt gefunden: Hantek %1 (%2)</translation>
432 </message> 427 </message>
433 <message> 428 <message>
434 - <location filename="../src/hantek/device.cpp" line="156"/> 429 + <location filename="../src/hantek/device.cpp" line="150"/>
435 <source>Couldn&apos;t open device %1</source> 430 <source>Couldn&apos;t open device %1</source>
436 <translation>Konnte Gerรคt %1 nicht รถffnen</translation> 431 <translation>Konnte Gerรคt %1 nicht รถffnen</translation>
437 </message> 432 </message>
438 <message> 433 <message>
439 - <location filename="../src/hantek/device.cpp" line="159"/>  
440 - <location filename="../src/hantek/device.cpp" line="244"/> 434 + <location filename="../src/hantek/device.cpp" line="153"/>
  435 + <location filename="../src/hantek/device.cpp" line="238"/>
441 <source>No Hantek oscilloscope found</source> 436 <source>No Hantek oscilloscope found</source>
442 <translation>Keine Hantek Oszilloskope gefunden</translation> 437 <translation>Keine Hantek Oszilloskope gefunden</translation>
443 </message> 438 </message>
444 <message> 439 <message>
445 - <location filename="../src/hantek/device.cpp" line="82"/>  
446 - <location filename="../src/hantek/device.cpp" line="169"/> 440 + <location filename="../src/hantek/device.cpp" line="83"/>
  441 + <location filename="../src/hantek/device.cpp" line="163"/>
447 <source>Failed to get device list: %1</source> 442 <source>Failed to get device list: %1</source>
448 <translation>Abrufen der Gerรคteliste fehlgeschlagen: %1</translation> 443 <translation>Abrufen der Gerรคteliste fehlgeschlagen: %1</translation>
449 </message> 444 </message>
450 <message> 445 <message>
451 - <location filename="../src/hantek/device.cpp" line="240"/> 446 + <location filename="../src/hantek/device.cpp" line="234"/>
452 <source>Couldn&apos;t open device %1: %2</source> 447 <source>Couldn&apos;t open device %1: %2</source>
453 <translation>Konnte Gerรคt %1 nicht รถffnen: %2</translation> 448 <translation>Konnte Gerรคt %1 nicht รถffnen: %2</translation>
454 </message> 449 </message>
@@ -456,25 +451,41 @@ @@ -456,25 +451,41 @@
456 <context> 451 <context>
457 <name>HorizontalDock</name> 452 <name>HorizontalDock</name>
458 <message> 453 <message>
459 - <location filename="../src/dockwindows.cpp" line="44"/> 454 + <location filename="../src/dockwindows.cpp" line="45"/>
460 <source>Horizontal</source> 455 <source>Horizontal</source>
461 <translation>Horizontal</translation> 456 <translation>Horizontal</translation>
462 </message> 457 </message>
463 <message> 458 <message>
464 - <location filename="../src/dockwindows.cpp" line="63"/> 459 + <location filename="../src/dockwindows.cpp" line="49"/>
  460 + <source>Samplerate</source>
  461 + <translation>Samplerate</translation>
  462 + </message>
  463 + <message>
  464 + <location filename="../src/dockwindows.cpp" line="58"/>
465 <source>Timebase</source> 465 <source>Timebase</source>
466 <translation>Zeitbasis</translation> 466 <translation>Zeitbasis</translation>
467 </message> 467 </message>
468 <message> 468 <message>
469 - <location filename="../src/dockwindows.cpp" line="67"/> 469 + <location filename="../src/dockwindows.cpp" line="64"/>
470 <source>Frequencybase</source> 470 <source>Frequencybase</source>
471 <translation>Frequenzbasis</translation> 471 <translation>Frequenzbasis</translation>
472 </message> 472 </message>
473 <message> 473 <message>
474 - <location filename="../src/dockwindows.cpp" line="71"/> 474 + <location filename="../src/dockwindows.cpp" line="69"/>
  475 + <source>Record length</source>
  476 + <translation>Satzlรคnge</translation>
  477 + </message>
  478 + <message>
  479 + <location filename="../src/dockwindows.cpp" line="72"/>
475 <source>Format</source> 480 <source>Format</source>
476 <translation>Format</translation> 481 <translation>Format</translation>
477 </message> 482 </message>
  483 + <message>
  484 + <location filename="../src/dockwindows.cpp" line="187"/>
  485 + <location filename="../src/dockwindows.cpp" line="190"/>
  486 + <source>Roll</source>
  487 + <translation>Rollen</translation>
  488 + </message>
478 </context> 489 </context>
479 <context> 490 <context>
480 <name>OpenHantekMainWindow</name> 491 <name>OpenHantekMainWindow</name>
@@ -484,289 +495,264 @@ @@ -484,289 +495,264 @@
484 <translation>OpenHantek</translation> 495 <translation>OpenHantek</translation>
485 </message> 496 </message>
486 <message> 497 <message>
487 - <location filename="../src/openhantek.cpp" line="168"/> 498 + <location filename="../src/openhantek.cpp" line="119"/>
488 <source>&amp;Open...</source> 499 <source>&amp;Open...</source>
489 <translation>&amp;ร–ffnen...</translation> 500 <translation>&amp;ร–ffnen...</translation>
490 </message> 501 </message>
491 <message> 502 <message>
492 - <location filename="../src/openhantek.cpp" line="169"/> 503 + <location filename="../src/openhantek.cpp" line="120"/>
493 <source>Ctrl+O</source> 504 <source>Ctrl+O</source>
494 <translation>Strg+O</translation> 505 <translation>Strg+O</translation>
495 </message> 506 </message>
496 <message> 507 <message>
497 - <location filename="../src/openhantek.cpp" line="170"/> 508 + <location filename="../src/openhantek.cpp" line="121"/>
498 <source>Open saved settings</source> 509 <source>Open saved settings</source>
499 <translation>Gespeicherte Einstellungen รถffnen</translation> 510 <translation>Gespeicherte Einstellungen รถffnen</translation>
500 </message> 511 </message>
501 <message> 512 <message>
502 - <location filename="../src/openhantek.cpp" line="173"/> 513 + <location filename="../src/openhantek.cpp" line="124"/>
503 <source>&amp;Save</source> 514 <source>&amp;Save</source>
504 <translation>&amp;Speichern</translation> 515 <translation>&amp;Speichern</translation>
505 </message> 516 </message>
506 <message> 517 <message>
507 - <location filename="../src/openhantek.cpp" line="174"/>  
508 - <location filename="../src/openhantek.cpp" line="198"/> 518 + <location filename="../src/openhantek.cpp" line="125"/>
  519 + <location filename="../src/openhantek.cpp" line="149"/>
509 <source>Ctrl+S</source> 520 <source>Ctrl+S</source>
510 <translation>Strg+S</translation> 521 <translation>Strg+S</translation>
511 </message> 522 </message>
512 <message> 523 <message>
513 - <location filename="../src/openhantek.cpp" line="175"/> 524 + <location filename="../src/openhantek.cpp" line="126"/>
514 <source>Save the current settings</source> 525 <source>Save the current settings</source>
515 <translation>Aktuelle Einstellungen speichern</translation> 526 <translation>Aktuelle Einstellungen speichern</translation>
516 </message> 527 </message>
517 <message> 528 <message>
518 - <location filename="../src/openhantek.cpp" line="178"/> 529 + <location filename="../src/openhantek.cpp" line="129"/>
519 <source>Save &amp;as...</source> 530 <source>Save &amp;as...</source>
520 <translation>Speichern &amp;unter...</translation> 531 <translation>Speichern &amp;unter...</translation>
521 </message> 532 </message>
522 <message> 533 <message>
523 - <location filename="../src/openhantek.cpp" line="179"/> 534 + <location filename="../src/openhantek.cpp" line="130"/>
524 <source>Save the current settings to another file</source> 535 <source>Save the current settings to another file</source>
525 <translation>Aktuelle Einstellungen in anderer Datei speichern</translation> 536 <translation>Aktuelle Einstellungen in anderer Datei speichern</translation>
526 </message> 537 </message>
527 <message> 538 <message>
528 - <location filename="../src/openhantek.cpp" line="182"/> 539 + <location filename="../src/openhantek.cpp" line="133"/>
529 <source>&amp;Print...</source> 540 <source>&amp;Print...</source>
530 <translation>&amp;Drucken...</translation> 541 <translation>&amp;Drucken...</translation>
531 </message> 542 </message>
532 <message> 543 <message>
533 - <location filename="../src/openhantek.cpp" line="183"/> 544 + <location filename="../src/openhantek.cpp" line="134"/>
534 <source>Ctrl+P</source> 545 <source>Ctrl+P</source>
535 <translation>Strg+P</translation> 546 <translation>Strg+P</translation>
536 </message> 547 </message>
537 <message> 548 <message>
538 - <location filename="../src/openhantek.cpp" line="184"/> 549 + <location filename="../src/openhantek.cpp" line="135"/>
539 <source>Print the oscilloscope screen</source> 550 <source>Print the oscilloscope screen</source>
540 <translation>Den Oscilloskopbildschirm drucken</translation> 551 <translation>Den Oscilloskopbildschirm drucken</translation>
541 </message> 552 </message>
542 <message> 553 <message>
543 - <location filename="../src/openhantek.cpp" line="187"/> 554 + <location filename="../src/openhantek.cpp" line="138"/>
544 <source>&amp;Export as...</source> 555 <source>&amp;Export as...</source>
545 <translation>&amp;Exportieren als...</translation> 556 <translation>&amp;Exportieren als...</translation>
546 </message> 557 </message>
547 <message> 558 <message>
548 - <location filename="../src/openhantek.cpp" line="188"/> 559 + <location filename="../src/openhantek.cpp" line="139"/>
549 <source>Ctrl+E</source> 560 <source>Ctrl+E</source>
550 <translation>Strg+E</translation> 561 <translation>Strg+E</translation>
551 </message> 562 </message>
552 <message> 563 <message>
553 - <location filename="../src/openhantek.cpp" line="189"/> 564 + <location filename="../src/openhantek.cpp" line="140"/>
554 <source>Export the oscilloscope data to a file</source> 565 <source>Export the oscilloscope data to a file</source>
555 <translation>Die Oszilloskopdaten in eine Datei exportieren</translation> 566 <translation>Die Oszilloskopdaten in eine Datei exportieren</translation>
556 </message> 567 </message>
557 <message> 568 <message>
558 - <location filename="../src/openhantek.cpp" line="192"/> 569 + <location filename="../src/openhantek.cpp" line="143"/>
559 <source>E&amp;xit</source> 570 <source>E&amp;xit</source>
560 <translation>&amp;Beenden</translation> 571 <translation>&amp;Beenden</translation>
561 </message> 572 </message>
562 <message> 573 <message>
563 - <location filename="../src/openhantek.cpp" line="193"/> 574 + <location filename="../src/openhantek.cpp" line="144"/>
564 <source>Ctrl+Q</source> 575 <source>Ctrl+Q</source>
565 <translation>Strg+Q</translation> 576 <translation>Strg+Q</translation>
566 </message> 577 </message>
567 <message> 578 <message>
568 - <location filename="../src/openhantek.cpp" line="194"/> 579 + <location filename="../src/openhantek.cpp" line="145"/>
569 <source>Exit the application</source> 580 <source>Exit the application</source>
570 <translation>Anwendung beenden</translation> 581 <translation>Anwendung beenden</translation>
571 </message> 582 </message>
572 <message> 583 <message>
573 - <location filename="../src/openhantek.cpp" line="197"/> 584 + <location filename="../src/openhantek.cpp" line="148"/>
574 <source>&amp;Settings</source> 585 <source>&amp;Settings</source>
575 <translation>&amp;Einstellungen</translation> 586 <translation>&amp;Einstellungen</translation>
576 </message> 587 </message>
577 <message> 588 <message>
578 - <location filename="../src/openhantek.cpp" line="199"/> 589 + <location filename="../src/openhantek.cpp" line="150"/>
579 <source>Configure the oscilloscope</source> 590 <source>Configure the oscilloscope</source>
580 <translation>Das Oszilloskop konfigurieren</translation> 591 <translation>Das Oszilloskop konfigurieren</translation>
581 </message> 592 </message>
582 <message> 593 <message>
583 - <location filename="../src/openhantek.cpp" line="243"/> 594 + <location filename="../src/openhantek.cpp" line="179"/>
584 <source>Send command</source> 595 <source>Send command</source>
585 <translation>Befehl senden</translation> 596 <translation>Befehl senden</translation>
586 </message> 597 </message>
587 <message> 598 <message>
588 - <location filename="../src/openhantek.cpp" line="244"/> 599 + <location filename="../src/openhantek.cpp" line="180"/>
589 <source>Shift+C</source> 600 <source>Shift+C</source>
590 <translation>Shift+C</translation> 601 <translation>Shift+C</translation>
591 </message> 602 </message>
592 <message> 603 <message>
593 - <location filename="../src/openhantek.cpp" line="264"/> 604 + <location filename="../src/openhantek.cpp" line="200"/>
594 <source>&amp;Docking windows</source> 605 <source>&amp;Docking windows</source>
595 <translation>&amp;Dockfenster</translation> 606 <translation>&amp;Dockfenster</translation>
596 </message> 607 </message>
597 <message> 608 <message>
598 - <location filename="../src/openhantek.cpp" line="269"/> 609 + <location filename="../src/openhantek.cpp" line="205"/>
599 <source>&amp;Toolbars</source> 610 <source>&amp;Toolbars</source>
600 <translation>&amp;Werkzeugleisten</translation> 611 <translation>&amp;Werkzeugleisten</translation>
601 </message> 612 </message>
602 <message> 613 <message>
603 - <location filename="../src/openhantek.cpp" line="380"/>  
604 - <location filename="../src/openhantek.cpp" line="400"/> 614 + <location filename="../src/openhantek.cpp" line="389"/>
  615 + <location filename="../src/openhantek.cpp" line="409"/>
605 <source>Settings (*.ini)</source> 616 <source>Settings (*.ini)</source>
606 <translation>Einstellungen (*.ini)</translation> 617 <translation>Einstellungen (*.ini)</translation>
607 </message> 618 </message>
608 <message> 619 <message>
609 - <location filename="../src/openhantek.cpp" line="400"/> 620 + <location filename="../src/openhantek.cpp" line="409"/>
610 <source>Save settings</source> 621 <source>Save settings</source>
611 <translation>Einstellungen speichern</translation> 622 <translation>Einstellungen speichern</translation>
612 </message> 623 </message>
613 <message> 624 <message>
614 - <location filename="../src/openhantek.cpp" line="414"/> 625 + <location filename="../src/openhantek.cpp" line="423"/>
615 <source>&amp;Stop</source> 626 <source>&amp;Stop</source>
616 <translation>&amp;Stop</translation> 627 <translation>&amp;Stop</translation>
617 </message> 628 </message>
618 <message> 629 <message>
619 - <location filename="../src/openhantek.cpp" line="463"/> 630 + <location filename="../src/openhantek.cpp" line="472"/>
620 <source>&lt;p&gt;This is a open source software for Hantek USB oscilloscopes.&lt;/p&gt;&lt;p&gt;Copyright &amp;copy; 2010, 2011 Oliver Haag &amp;lt;oliver.haag@gmail.com&amp;gt;&lt;/p&gt;</source> 631 <source>&lt;p&gt;This is a open source software for Hantek USB oscilloscopes.&lt;/p&gt;&lt;p&gt;Copyright &amp;copy; 2010, 2011 Oliver Haag &amp;lt;oliver.haag@gmail.com&amp;gt;&lt;/p&gt;</source>
621 <translation>&lt;p&gt;Dies ist ein Open-Source Programm fรผr Hantek USB Oszilloskope.&lt;/p&gt;&lt;p&gt;Copyright &amp;copy; 2010, 2011 Oliver Haag &amp;lt;oliver.haag@gmail.com&amp;gt;&lt;/p&gt;</translation> 632 <translation>&lt;p&gt;Dies ist ein Open-Source Programm fรผr Hantek USB Oszilloskope.&lt;/p&gt;&lt;p&gt;Copyright &amp;copy; 2010, 2011 Oliver Haag &amp;lt;oliver.haag@gmail.com&amp;gt;&lt;/p&gt;</translation>
622 </message> 633 </message>
623 <message> 634 <message>
624 - <location filename="../src/openhantek.cpp" line="662"/> 635 + <location filename="../src/openhantek.cpp" line="698"/>
625 <source>Invalid command</source> 636 <source>Invalid command</source>
626 <translation>Ungรผltiger Befehl</translation> 637 <translation>Ungรผltiger Befehl</translation>
627 </message> 638 </message>
628 <message> 639 <message>
629 - <location filename="../src/openhantek.cpp" line="203"/> 640 + <location filename="../src/openhantek.cpp" line="154"/>
630 <source>Space</source> 641 <source>Space</source>
631 <translation>Leertaste</translation> 642 <translation>Leertaste</translation>
632 </message> 643 </message>
633 <message> 644 <message>
634 - <location filename="../src/openhantek.cpp" line="416"/> 645 + <location filename="../src/openhantek.cpp" line="425"/>
635 <source>Stop the oscilloscope</source> 646 <source>Stop the oscilloscope</source>
636 <translation>Das Oszilloskop anhalten</translation> 647 <translation>Das Oszilloskop anhalten</translation>
637 </message> 648 </message>
638 <message> 649 <message>
639 - <location filename="../src/openhantek.cpp" line="209"/>  
640 - <source>&amp;Small</source>  
641 - <translation>&amp;Klein</translation>  
642 - </message>  
643 - <message>  
644 - <location filename="../src/openhantek.cpp" line="213"/>  
645 - <source>10240 Samples</source>  
646 - <translation>10240 Werte</translation>  
647 - </message>  
648 - <message>  
649 - <location filename="../src/openhantek.cpp" line="215"/>  
650 - <source>&amp;Large</source>  
651 - <translation>&amp;GroรŸ</translation>  
652 - </message>  
653 - <message>  
654 - <location filename="../src/openhantek.cpp" line="219"/>  
655 - <source>32768 Samples</source>  
656 - <translation>32768 Werte</translation>  
657 - </message>  
658 - <message>  
659 - <location filename="../src/openhantek.cpp" line="221"/> 650 + <location filename="../src/openhantek.cpp" line="157"/>
660 <source>Digital &amp;phosphor</source> 651 <source>Digital &amp;phosphor</source>
661 <translation>Digitaler &amp;Phosphor</translation> 652 <translation>Digitaler &amp;Phosphor</translation>
662 </message> 653 </message>
663 <message> 654 <message>
664 - <location filename="../src/openhantek.cpp" line="227"/> 655 + <location filename="../src/openhantek.cpp" line="163"/>
665 <source>&amp;Zoom</source> 656 <source>&amp;Zoom</source>
666 <translation>&amp;Zoom</translation> 657 <translation>&amp;Zoom</translation>
667 </message> 658 </message>
668 <message> 659 <message>
669 - <location filename="../src/openhantek.cpp" line="234"/> 660 + <location filename="../src/openhantek.cpp" line="170"/>
670 <source>&amp;About</source> 661 <source>&amp;About</source>
671 <translation>&amp;รœber</translation> 662 <translation>&amp;รœber</translation>
672 </message> 663 </message>
673 <message> 664 <message>
674 - <location filename="../src/openhantek.cpp" line="235"/> 665 + <location filename="../src/openhantek.cpp" line="171"/>
675 <source>Show information about this program</source> 666 <source>Show information about this program</source>
676 <translation>Zeige Informationen รผber dieses Programm</translation> 667 <translation>Zeige Informationen รผber dieses Programm</translation>
677 </message> 668 </message>
678 <message> 669 <message>
679 - <location filename="../src/openhantek.cpp" line="238"/> 670 + <location filename="../src/openhantek.cpp" line="174"/>
680 <source>About &amp;Qt</source> 671 <source>About &amp;Qt</source>
681 <translation>รœber &amp;Qt</translation> 672 <translation>รœber &amp;Qt</translation>
682 </message> 673 </message>
683 <message> 674 <message>
684 - <location filename="../src/openhantek.cpp" line="239"/> 675 + <location filename="../src/openhantek.cpp" line="175"/>
685 <source>Show the Qt library&apos;s About box</source> 676 <source>Show the Qt library&apos;s About box</source>
686 <translation>Zeige Dialog zur Qt Bibliothek</translation> 677 <translation>Zeige Dialog zur Qt Bibliothek</translation>
687 </message> 678 </message>
688 <message> 679 <message>
689 - <location filename="../src/openhantek.cpp" line="250"/> 680 + <location filename="../src/openhantek.cpp" line="186"/>
690 <source>&amp;File</source> 681 <source>&amp;File</source>
691 <translation>&amp;Datei</translation> 682 <translation>&amp;Datei</translation>
692 </message> 683 </message>
693 <message> 684 <message>
694 - <location filename="../src/openhantek.cpp" line="260"/> 685 + <location filename="../src/openhantek.cpp" line="196"/>
695 <source>&amp;View</source> 686 <source>&amp;View</source>
696 <translation>&amp;Ansicht</translation> 687 <translation>&amp;Ansicht</translation>
697 </message> 688 </message>
698 <message> 689 <message>
699 - <location filename="../src/openhantek.cpp" line="274"/> 690 + <location filename="../src/openhantek.cpp" line="210"/>
700 <source>&amp;Oscilloscope</source> 691 <source>&amp;Oscilloscope</source>
701 <translation>&amp;Oszilloskop</translation> 692 <translation>&amp;Oszilloskop</translation>
702 </message> 693 </message>
703 <message> 694 <message>
704 - <location filename="../src/openhantek.cpp" line="282"/>  
705 - <source>&amp;Buffer size</source>  
706 - <translation>&amp;PuffergrรถรŸe</translation>  
707 - </message>  
708 - <message>  
709 - <location filename="../src/openhantek.cpp" line="288"/> 695 + <location filename="../src/openhantek.cpp" line="221"/>
710 <source>&amp;Help</source> 696 <source>&amp;Help</source>
711 <translation>&amp;Hilfe</translation> 697 <translation>&amp;Hilfe</translation>
712 </message> 698 </message>
713 <message> 699 <message>
714 - <location filename="../src/openhantek.cpp" line="295"/> 700 + <location filename="../src/openhantek.cpp" line="228"/>
715 <source>File</source> 701 <source>File</source>
716 <translation>Datei</translation> 702 <translation>Datei</translation>
717 </message> 703 </message>
718 <message> 704 <message>
719 - <location filename="../src/openhantek.cpp" line="304"/> 705 + <location filename="../src/openhantek.cpp" line="237"/>
720 <source>Oscilloscope</source> 706 <source>Oscilloscope</source>
721 <translation>Oszilloskop</translation> 707 <translation>Oszilloskop</translation>
722 </message> 708 </message>
723 <message> 709 <message>
724 - <location filename="../src/openhantek.cpp" line="307"/> 710 + <location filename="../src/openhantek.cpp" line="240"/>
725 <source>View</source> 711 <source>View</source>
726 <translation>Ansicht</translation> 712 <translation>Ansicht</translation>
727 </message> 713 </message>
728 <message> 714 <message>
729 - <location filename="../src/openhantek.cpp" line="322"/> 715 + <location filename="../src/openhantek.cpp" line="255"/>
730 <source>Ready</source> 716 <source>Ready</source>
731 <translation>Bereit</translation> 717 <translation>Bereit</translation>
732 </message> 718 </message>
733 <message> 719 <message>
734 - <location filename="../src/openhantek.cpp" line="380"/> 720 + <location filename="../src/openhantek.cpp" line="389"/>
735 <source>Open file</source> 721 <source>Open file</source>
736 <translation>Datei รถffnen</translation> 722 <translation>Datei รถffnen</translation>
737 </message> 723 </message>
738 <message> 724 <message>
739 - <location filename="../src/openhantek.cpp" line="424"/> 725 + <location filename="../src/openhantek.cpp" line="433"/>
740 <source>&amp;Start</source> 726 <source>&amp;Start</source>
741 <translation>&amp;Start</translation> 727 <translation>&amp;Start</translation>
742 </message> 728 </message>
743 <message> 729 <message>
744 - <location filename="../src/openhantek.cpp" line="426"/> 730 + <location filename="../src/openhantek.cpp" line="435"/>
745 <source>Start the oscilloscope</source> 731 <source>Start the oscilloscope</source>
746 <translation>Startet das Oszilloskop</translation> 732 <translation>Startet das Oszilloskop</translation>
747 </message> 733 </message>
748 <message> 734 <message>
749 - <location filename="../src/openhantek.cpp" line="446"/> 735 + <location filename="../src/openhantek.cpp" line="455"/>
750 <source>Disable fading of previous graphs</source> 736 <source>Disable fading of previous graphs</source>
751 <translation>Nachleuchten von vorigen Graphen deaktivieren</translation> 737 <translation>Nachleuchten von vorigen Graphen deaktivieren</translation>
752 </message> 738 </message>
753 <message> 739 <message>
754 - <location filename="../src/openhantek.cpp" line="448"/> 740 + <location filename="../src/openhantek.cpp" line="457"/>
755 <source>Enable fading of previous graphs</source> 741 <source>Enable fading of previous graphs</source>
756 <translation>Nachleuchten von vorigen Graphen aktivieren</translation> 742 <translation>Nachleuchten von vorigen Graphen aktivieren</translation>
757 </message> 743 </message>
758 <message> 744 <message>
759 - <location filename="../src/openhantek.cpp" line="456"/> 745 + <location filename="../src/openhantek.cpp" line="465"/>
760 <source>Hide magnified scope</source> 746 <source>Hide magnified scope</source>
761 <translation>VergrรถรŸerte Anzeige ausblenden</translation> 747 <translation>VergrรถรŸerte Anzeige ausblenden</translation>
762 </message> 748 </message>
763 <message> 749 <message>
764 - <location filename="../src/openhantek.cpp" line="458"/> 750 + <location filename="../src/openhantek.cpp" line="467"/>
765 <source>Show magnified scope</source> 751 <source>Show magnified scope</source>
766 <translation>VergrรถรŸerte Anzeige anzeigen</translation> 752 <translation>VergrรถรŸerte Anzeige anzeigen</translation>
767 </message> 753 </message>
768 <message> 754 <message>
769 - <location filename="../src/openhantek.cpp" line="463"/> 755 + <location filename="../src/openhantek.cpp" line="472"/>
770 <source>About OpenHantek %1</source> 756 <source>About OpenHantek %1</source>
771 <translation>*ber OpenHantek %1</translation> 757 <translation>*ber OpenHantek %1</translation>
772 </message> 758 </message>
@@ -774,187 +760,187 @@ @@ -774,187 +760,187 @@
774 <context> 760 <context>
775 <name>QApplication</name> 761 <name>QApplication</name>
776 <message> 762 <message>
777 - <location filename="../src/helper.cpp" line="47"/> 763 + <location filename="../src/helper.cpp" line="49"/>
778 <source>Success (no error)</source> 764 <source>Success (no error)</source>
779 <translation>Erfolgreich (Kein Fehler)</translation> 765 <translation>Erfolgreich (Kein Fehler)</translation>
780 </message> 766 </message>
781 <message> 767 <message>
782 - <location filename="../src/helper.cpp" line="49"/> 768 + <location filename="../src/helper.cpp" line="51"/>
783 <source>Input/output error</source> 769 <source>Input/output error</source>
784 <translation>Ein-/Ausgabe Fehler</translation> 770 <translation>Ein-/Ausgabe Fehler</translation>
785 </message> 771 </message>
786 <message> 772 <message>
787 - <location filename="../src/helper.cpp" line="51"/> 773 + <location filename="../src/helper.cpp" line="53"/>
788 <source>Invalid parameter</source> 774 <source>Invalid parameter</source>
789 <translation>Ungรผltiger Parameter</translation> 775 <translation>Ungรผltiger Parameter</translation>
790 </message> 776 </message>
791 <message> 777 <message>
792 - <location filename="../src/helper.cpp" line="53"/> 778 + <location filename="../src/helper.cpp" line="55"/>
793 <source>Access denied (insufficient permissions)</source> 779 <source>Access denied (insufficient permissions)</source>
794 <translation>Zugriff verweigert (Unzureichende Berechtigungen)</translation> 780 <translation>Zugriff verweigert (Unzureichende Berechtigungen)</translation>
795 </message> 781 </message>
796 <message> 782 <message>
797 - <location filename="../src/helper.cpp" line="55"/> 783 + <location filename="../src/helper.cpp" line="57"/>
798 <source>No such device (it may have been disconnected)</source> 784 <source>No such device (it may have been disconnected)</source>
799 <translation>Gerรคt nicht vorhanden (Mรถglicherweise wurde es abgesteckt)</translation> 785 <translation>Gerรคt nicht vorhanden (Mรถglicherweise wurde es abgesteckt)</translation>
800 </message> 786 </message>
801 <message> 787 <message>
802 - <location filename="../src/helper.cpp" line="57"/> 788 + <location filename="../src/helper.cpp" line="59"/>
803 <source>Entity not found</source> 789 <source>Entity not found</source>
804 <translation>Datensatz nicht gefunden</translation> 790 <translation>Datensatz nicht gefunden</translation>
805 </message> 791 </message>
806 <message> 792 <message>
807 - <location filename="../src/helper.cpp" line="59"/> 793 + <location filename="../src/helper.cpp" line="61"/>
808 <source>Resource busy</source> 794 <source>Resource busy</source>
809 <translation>Quelle belegt</translation> 795 <translation>Quelle belegt</translation>
810 </message> 796 </message>
811 <message> 797 <message>
812 - <location filename="../src/helper.cpp" line="61"/> 798 + <location filename="../src/helper.cpp" line="63"/>
813 <source>Operation timed out</source> 799 <source>Operation timed out</source>
814 <translation>Zeitรผberschreitung</translation> 800 <translation>Zeitรผberschreitung</translation>
815 </message> 801 </message>
816 <message> 802 <message>
817 - <location filename="../src/helper.cpp" line="63"/> 803 + <location filename="../src/helper.cpp" line="65"/>
818 <source>Overflow</source> 804 <source>Overflow</source>
819 <translation>รœberlauf</translation> 805 <translation>รœberlauf</translation>
820 </message> 806 </message>
821 <message> 807 <message>
822 - <location filename="../src/helper.cpp" line="65"/> 808 + <location filename="../src/helper.cpp" line="67"/>
823 <source>Pipe error</source> 809 <source>Pipe error</source>
824 <translation>Leitungsfehler</translation> 810 <translation>Leitungsfehler</translation>
825 </message> 811 </message>
826 <message> 812 <message>
827 - <location filename="../src/helper.cpp" line="67"/> 813 + <location filename="../src/helper.cpp" line="69"/>
828 <source>System call interrupted (perhaps due to signal)</source> 814 <source>System call interrupted (perhaps due to signal)</source>
829 <translation>Systemaufruf unterbrochen (Mรถglicherweise aufgrund eines Signals)</translation> 815 <translation>Systemaufruf unterbrochen (Mรถglicherweise aufgrund eines Signals)</translation>
830 </message> 816 </message>
831 <message> 817 <message>
832 - <location filename="../src/helper.cpp" line="69"/> 818 + <location filename="../src/helper.cpp" line="71"/>
833 <source>Insufficient memory</source> 819 <source>Insufficient memory</source>
834 <translation>Unzureichender Speicher</translation> 820 <translation>Unzureichender Speicher</translation>
835 </message> 821 </message>
836 <message> 822 <message>
837 - <location filename="../src/helper.cpp" line="71"/> 823 + <location filename="../src/helper.cpp" line="73"/>
838 <source>Operation not supported or unimplemented on this platform</source> 824 <source>Operation not supported or unimplemented on this platform</source>
839 <translation>Vorgang auf diesem System nicht unterstรผtzt oder nicht implementiert</translation> 825 <translation>Vorgang auf diesem System nicht unterstรผtzt oder nicht implementiert</translation>
840 </message> 826 </message>
841 <message> 827 <message>
842 - <location filename="../src/helper.cpp" line="73"/> 828 + <location filename="../src/helper.cpp" line="75"/>
843 <source>Other error</source> 829 <source>Other error</source>
844 <translation>Anderer Fehler</translation> 830 <translation>Anderer Fehler</translation>
845 </message> 831 </message>
846 <message> 832 <message>
847 - <location filename="../src/helper.cpp" line="90"/> 833 + <location filename="../src/helper.cpp" line="92"/>
848 <source>%L1 ยตV</source> 834 <source>%L1 ยตV</source>
849 <translation>%L1 ยตV</translation> 835 <translation>%L1 ยตV</translation>
850 </message> 836 </message>
851 <message> 837 <message>
852 - <location filename="../src/helper.cpp" line="92"/> 838 + <location filename="../src/helper.cpp" line="94"/>
853 <source>%L1 mV</source> 839 <source>%L1 mV</source>
854 <translation>%L1 mV</translation> 840 <translation>%L1 mV</translation>
855 </message> 841 </message>
856 <message> 842 <message>
857 - <location filename="../src/helper.cpp" line="94"/> 843 + <location filename="../src/helper.cpp" line="96"/>
858 <source>%L1 V</source> 844 <source>%L1 V</source>
859 <translation>%L1 V</translation> 845 <translation>%L1 V</translation>
860 </message> 846 </message>
861 <message> 847 <message>
862 - <location filename="../src/helper.cpp" line="98"/> 848 + <location filename="../src/helper.cpp" line="100"/>
863 <source>%L1 dB</source> 849 <source>%L1 dB</source>
864 <translation>%L1 dB</translation> 850 <translation>%L1 dB</translation>
865 </message> 851 </message>
866 <message> 852 <message>
867 - <location filename="../src/helper.cpp" line="103"/> 853 + <location filename="../src/helper.cpp" line="105"/>
868 <source>%L1 ps</source> 854 <source>%L1 ps</source>
869 <translation>%L1 ps</translation> 855 <translation>%L1 ps</translation>
870 </message> 856 </message>
871 <message> 857 <message>
872 - <location filename="../src/helper.cpp" line="105"/> 858 + <location filename="../src/helper.cpp" line="107"/>
873 <source>%L1 ns</source> 859 <source>%L1 ns</source>
874 <translation>%L1 ns</translation> 860 <translation>%L1 ns</translation>
875 </message> 861 </message>
876 <message> 862 <message>
877 - <location filename="../src/helper.cpp" line="107"/> 863 + <location filename="../src/helper.cpp" line="109"/>
878 <source>%L1 ยตs</source> 864 <source>%L1 ยตs</source>
879 <translation>%L1 ยตs</translation> 865 <translation>%L1 ยตs</translation>
880 </message> 866 </message>
881 <message> 867 <message>
882 - <location filename="../src/helper.cpp" line="109"/> 868 + <location filename="../src/helper.cpp" line="111"/>
883 <source>%L1 ms</source> 869 <source>%L1 ms</source>
884 <translation>%L1 ms</translation> 870 <translation>%L1 ms</translation>
885 </message> 871 </message>
886 <message> 872 <message>
887 - <location filename="../src/helper.cpp" line="111"/> 873 + <location filename="../src/helper.cpp" line="113"/>
888 <source>%L1 s</source> 874 <source>%L1 s</source>
889 <translation>%L1 s</translation> 875 <translation>%L1 s</translation>
890 </message> 876 </message>
891 <message> 877 <message>
892 - <location filename="../src/helper.cpp" line="113"/> 878 + <location filename="../src/helper.cpp" line="115"/>
893 <source>%L1 min</source> 879 <source>%L1 min</source>
894 <translation>%L1 min</translation> 880 <translation>%L1 min</translation>
895 </message> 881 </message>
896 <message> 882 <message>
897 - <location filename="../src/helper.cpp" line="115"/> 883 + <location filename="../src/helper.cpp" line="117"/>
898 <source>%L1 h</source> 884 <source>%L1 h</source>
899 <translation>%L1 h</translation> 885 <translation>%L1 h</translation>
900 </message> 886 </message>
901 <message> 887 <message>
902 - <location filename="../src/helper.cpp" line="121"/> 888 + <location filename="../src/helper.cpp" line="123"/>
903 <source>%L1 Hz</source> 889 <source>%L1 Hz</source>
904 <translation>%L1 Hz</translation> 890 <translation>%L1 Hz</translation>
905 </message> 891 </message>
906 <message> 892 <message>
907 - <location filename="../src/helper.cpp" line="123"/> 893 + <location filename="../src/helper.cpp" line="125"/>
908 <source>%L1 kHz</source> 894 <source>%L1 kHz</source>
909 <translation>%L1 kHz</translation> 895 <translation>%L1 kHz</translation>
910 </message> 896 </message>
911 <message> 897 <message>
912 - <location filename="../src/helper.cpp" line="125"/> 898 + <location filename="../src/helper.cpp" line="127"/>
913 <source>%L1 MHz</source> 899 <source>%L1 MHz</source>
914 <translation>%L1 MHz</translation> 900 <translation>%L1 MHz</translation>
915 </message> 901 </message>
916 <message> 902 <message>
917 - <location filename="../src/helper.cpp" line="127"/> 903 + <location filename="../src/helper.cpp" line="129"/>
918 <source>%L1 GHz</source> 904 <source>%L1 GHz</source>
919 <translation>%L1 GHz</translation> 905 <translation>%L1 GHz</translation>
920 </message> 906 </message>
921 <message> 907 <message>
922 - <location filename="../src/helper.cpp" line="133"/> 908 + <location filename="../src/helper.cpp" line="135"/>
923 <source>%L1 S</source> 909 <source>%L1 S</source>
924 <translation>%L1 S</translation> 910 <translation>%L1 S</translation>
925 </message> 911 </message>
926 <message> 912 <message>
927 - <location filename="../src/helper.cpp" line="135"/> 913 + <location filename="../src/helper.cpp" line="137"/>
928 <source>%L1 kS</source> 914 <source>%L1 kS</source>
929 <translation>%L1 kS</translation> 915 <translation>%L1 kS</translation>
930 </message> 916 </message>
931 <message> 917 <message>
932 - <location filename="../src/helper.cpp" line="137"/> 918 + <location filename="../src/helper.cpp" line="139"/>
933 <source>%L1 MS</source> 919 <source>%L1 MS</source>
934 <translation>%L1 MS</translation> 920 <translation>%L1 MS</translation>
935 </message> 921 </message>
936 <message> 922 <message>
937 - <location filename="../src/helper.cpp" line="139"/> 923 + <location filename="../src/helper.cpp" line="141"/>
938 <source>%L1 GS</source> 924 <source>%L1 GS</source>
939 <translation>%L1 GS</translation> 925 <translation>%L1 GS</translation>
940 </message> 926 </message>
941 <message> 927 <message>
942 - <location filename="../src/settings.cpp" line="145"/> 928 + <location filename="../src/settings.cpp" line="146"/>
943 <source>CH%1</source> 929 <source>CH%1</source>
944 <translation>CH%1</translation> 930 <translation>CH%1</translation>
945 </message> 931 </message>
946 <message> 932 <message>
947 - <location filename="../src/settings.cpp" line="135"/> 933 + <location filename="../src/settings.cpp" line="136"/>
948 <source>SP%1</source> 934 <source>SP%1</source>
949 <translation>SP%1</translation> 935 <translation>SP%1</translation>
950 </message> 936 </message>
951 <message> 937 <message>
952 - <location filename="../src/settings.cpp" line="179"/> 938 + <location filename="../src/settings.cpp" line="180"/>
953 <source>MATH</source> 939 <source>MATH</source>
954 <translation>MATH</translation> 940 <translation>MATH</translation>
955 </message> 941 </message>
956 <message> 942 <message>
957 - <location filename="../src/settings.cpp" line="170"/> 943 + <location filename="../src/settings.cpp" line="171"/>
958 <source>SPM</source> 944 <source>SPM</source>
959 <translation>SPM</translation> 945 <translation>SPM</translation>
960 </message> 946 </message>
@@ -1112,7 +1098,7 @@ @@ -1112,7 +1098,7 @@
1112 <context> 1098 <context>
1113 <name>SpectrumDock</name> 1099 <name>SpectrumDock</name>
1114 <message> 1100 <message>
1115 - <location filename="../src/dockwindows.cpp" line="320"/> 1101 + <location filename="../src/dockwindows.cpp" line="405"/>
1116 <source>Spectrum</source> 1102 <source>Spectrum</source>
1117 <translation>Spektrum</translation> 1103 <translation>Spektrum</translation>
1118 </message> 1104 </message>
@@ -1120,27 +1106,27 @@ @@ -1120,27 +1106,27 @@
1120 <context> 1106 <context>
1121 <name>TriggerDock</name> 1107 <name>TriggerDock</name>
1122 <message> 1108 <message>
1123 - <location filename="../src/dockwindows.cpp" line="180"/> 1109 + <location filename="../src/dockwindows.cpp" line="265"/>
1124 <source>Trigger</source> 1110 <source>Trigger</source>
1125 <translation>Trigger</translation> 1111 <translation>Trigger</translation>
1126 </message> 1112 </message>
1127 <message> 1113 <message>
1128 - <location filename="../src/dockwindows.cpp" line="185"/> 1114 + <location filename="../src/dockwindows.cpp" line="270"/>
1129 <source>CH%1</source> 1115 <source>CH%1</source>
1130 <translation>CH%1</translation> 1116 <translation>CH%1</translation>
1131 </message> 1117 </message>
1132 <message> 1118 <message>
1133 - <location filename="../src/dockwindows.cpp" line="189"/> 1119 + <location filename="../src/dockwindows.cpp" line="274"/>
1134 <source>Mode</source> 1120 <source>Mode</source>
1135 <translation>Modus</translation> 1121 <translation>Modus</translation>
1136 </message> 1122 </message>
1137 <message> 1123 <message>
1138 - <location filename="../src/dockwindows.cpp" line="194"/> 1124 + <location filename="../src/dockwindows.cpp" line="279"/>
1139 <source>Slope</source> 1125 <source>Slope</source>
1140 <translation>Flanke</translation> 1126 <translation>Flanke</translation>
1141 </message> 1127 </message>
1142 <message> 1128 <message>
1143 - <location filename="../src/dockwindows.cpp" line="199"/> 1129 + <location filename="../src/dockwindows.cpp" line="284"/>
1144 <source>Source</source> 1130 <source>Source</source>
1145 <translation>Quelle</translation> 1131 <translation>Quelle</translation>
1146 </message> 1132 </message>
@@ -1148,7 +1134,7 @@ @@ -1148,7 +1134,7 @@
1148 <context> 1134 <context>
1149 <name>VoltageDock</name> 1135 <name>VoltageDock</name>
1150 <message> 1136 <message>
1151 - <location filename="../src/dockwindows.cpp" line="445"/> 1137 + <location filename="../src/dockwindows.cpp" line="530"/>
1152 <source>Voltage</source> 1138 <source>Voltage</source>
1153 <translation>Spannung</translation> 1139 <translation>Spannung</translation>
1154 </message> 1140 </message>