Commit f3ea2602f29f961a6369ee6ab1810e55acffdd15

Authored by David Graeff
Committed by David Gräff
1 parent c8f3559b

hantekdsocontrol: Modernize and make it more readable. Use const on all get meth…

…ods. Use error enum consistently
openhantek/src/hantek/definitions.h
... ... @@ -19,7 +19,7 @@
19 19 namespace Dso {
20 20 /// \enum ErrorCode hantek/control.h
21 21 /// \brief The return codes for device control methods.
22   -enum ErrorCode {
  22 +enum class ErrorCode {
23 23 ERROR_NONE = 0, ///< Successful operation
24 24 ERROR_CONNECTION = -1, ///< Device not connected or communication error
25 25 ERROR_UNSUPPORTED = -2, ///< Not supported by this device
... ... @@ -821,7 +821,8 @@ enum CaptureState {
821 821 CAPTURE_SAMPLING = 1, ///< The scope is sampling data after triggering
822 822 CAPTURE_READY = 2, ///< Sampling data is available (DSO-2090/DSO-2150)
823 823 CAPTURE_READY2250 = 3, ///< Sampling data is available (DSO-2250)
824   - CAPTURE_READY5200 = 7 ///< Sampling data is available (DSO-5200/DSO-5200A)
  824 + CAPTURE_READY5200 = 7, ///< Sampling data is available (DSO-5200/DSO-5200A)
  825 + CAPTURE_ERROR = 1000
825 826 };
826 827  
827 828 //////////////////////////////////////////////////////////////////////////////
... ...
openhantek/src/hantek/hantekdsocontrol.cpp
... ... @@ -32,9 +32,7 @@ void HantekDsoControl::startSampling() {
32 32 if (specification.isSoftwareTriggerDevice) {
33 33 // Convert to GUI presentable values (1e5 -> 1.0, 48e6 -> 480.0 etc)
34 34 QList<double> sampleSteps;
35   - for (double v: specification.sampleSteps) {
36   - sampleSteps << v/1e5;
37   - }
  35 + for (double v : specification.sampleSteps) { sampleSteps << v / 1e5; }
38 36 emit samplerateSet(1, sampleSteps);
39 37 }
40 38  
... ... @@ -47,15 +45,12 @@ void HantekDsoControl::stopSampling() {
47 45 emit samplingStopped();
48 46 }
49 47  
50   -/// \brief Get a list of the names of the special trigger sources.
51 48 const QStringList *HantekDsoControl::getSpecialTriggerSources() { return &(specialTriggerSources); }
52 49  
53 50 const USBDevice *HantekDsoControl::getDevice() const { return device; }
54 51  
55 52 const DSOsamples &HantekDsoControl::getLastSamples() { return result; }
56 53  
57   -/// \brief Initializes the command buffers and lists.
58   -/// \param parent The parent widget.
59 54 HantekDsoControl::HantekDsoControl(USBDevice *device) : device(device) {
60 55 if (device == nullptr) throw new std::runtime_error("No usb device for HantekDsoControl");
61 56  
... ... @@ -73,10 +68,8 @@ HantekDsoControl::HantekDsoControl(USBDevice *device) : device(device) {
73 68  
74 69 specification.samplerate.single.base = 50e6;
75 70 specification.samplerate.single.max = 50e6;
76   - specification.samplerate.single.recordLengths << 0;
77 71 specification.samplerate.multi.base = 100e6;
78 72 specification.samplerate.multi.max = 100e6;
79   - specification.samplerate.multi.recordLengths << 0;
80 73  
81 74 for (unsigned channel = 0; channel < HANTEK_CHANNELS; ++channel) {
82 75 for (unsigned gainId = 0; gainId < 9; ++gainId) {
... ... @@ -102,8 +95,8 @@ HantekDsoControl::HantekDsoControl(USBDevice *device) : device(device) {
102 95 controlsettings.voltage[channel].offsetReal = 0.0;
103 96 controlsettings.voltage[channel].used = false;
104 97 }
105   - controlsettings.recordLengthId = 1;
106 98 controlsettings.usedChannels = 0;
  99 + controlsettings.recordLengthId = 1;
107 100  
108 101 // Transmission-ready control commands
109 102 this->control[CONTROLINDEX_SETOFFSET] = new ControlSetOffset();
... ... @@ -113,9 +106,6 @@ HantekDsoControl::HantekDsoControl(USBDevice *device) : device(device) {
113 106  
114 107 for (int cIndex = 0; cIndex < CONTROLINDEX_COUNT; ++cIndex) this->controlPending[cIndex] = false;
115 108  
116   - // Sample buffers
117   - result.data.resize(HANTEK_CHANNELS);
118   -
119 109 int errorCode;
120 110  
121 111 // Instantiate the commands needed for all models
... ... @@ -153,11 +143,11 @@ HantekDsoControl::HantekDsoControl(USBDevice *device) : device(device) {
153 143 specification.samplerate.single.base = 50e6;
154 144 specification.samplerate.single.max = 75e6;
155 145 specification.samplerate.single.maxDownsampler = 131072;
156   - specification.samplerate.single.recordLengths << UINT_MAX << 10240 << 32768;
  146 + specification.samplerate.single.recordLengths = {UINT_MAX, 10240, 32768};
157 147 specification.samplerate.multi.base = 100e6;
158 148 specification.samplerate.multi.max = 150e6;
159 149 specification.samplerate.multi.maxDownsampler = 131072;
160   - specification.samplerate.multi.recordLengths << UINT_MAX << 20480 << 65536;
  150 + specification.samplerate.multi.recordLengths = {UINT_MAX, 20480, 65536};
161 151 specification.bufferDividers << 1000 << 1 << 1;
162 152 specification.gainSteps << 0.08 << 0.16 << 0.40 << 0.80 << 1.60 << 4.00 << 8.0 << 16.0 << 40.0;
163 153 for (int channel = 0; channel < HANTEK_CHANNELS; ++channel)
... ... @@ -179,11 +169,11 @@ HantekDsoControl::HantekDsoControl(USBDevice *device) : device(device) {
179 169 specification.samplerate.single.base = 50e6;
180 170 specification.samplerate.single.max = 50e6;
181 171 specification.samplerate.single.maxDownsampler = 131072;
182   - specification.samplerate.single.recordLengths << UINT_MAX << 10240 << 32768;
  172 + specification.samplerate.single.recordLengths = {UINT_MAX, 10240, 32768};
183 173 specification.samplerate.multi.base = 100e6;
184 174 specification.samplerate.multi.max = 100e6;
185 175 specification.samplerate.multi.maxDownsampler = 131072;
186   - specification.samplerate.multi.recordLengths << UINT_MAX << 20480 << 65536;
  176 + specification.samplerate.multi.recordLengths = {UINT_MAX, 20480, 65536};
187 177 specification.bufferDividers << 1000 << 1 << 1;
188 178 specification.gainSteps << 0.08 << 0.16 << 0.40 << 0.80 << 1.60 << 4.00 << 8.0 << 16.0 << 40.0;
189 179 for (int channel = 0; channel < HANTEK_CHANNELS; ++channel)
... ... @@ -216,11 +206,11 @@ HantekDsoControl::HantekDsoControl(USBDevice *device) : device(device) {
216 206 specification.samplerate.single.base = 100e6;
217 207 specification.samplerate.single.max = 100e6;
218 208 specification.samplerate.single.maxDownsampler = 65536;
219   - specification.samplerate.single.recordLengths << UINT_MAX << 10240 << 524288;
  209 + specification.samplerate.single.recordLengths = {UINT_MAX, 10240, 524288};
220 210 specification.samplerate.multi.base = 200e6;
221 211 specification.samplerate.multi.max = 250e6;
222 212 specification.samplerate.multi.maxDownsampler = 65536;
223   - specification.samplerate.multi.recordLengths << UINT_MAX << 20480 << 1048576;
  213 + specification.samplerate.multi.recordLengths = {UINT_MAX, 20480, 1048576};
224 214 specification.bufferDividers << 1000 << 1 << 1;
225 215 specification.gainSteps << 0.08 << 0.16 << 0.40 << 0.80 << 1.60 << 4.00 << 8.0 << 16.0 << 40.0;
226 216 for (int channel = 0; channel < HANTEK_CHANNELS; ++channel)
... ... @@ -251,11 +241,11 @@ HantekDsoControl::HantekDsoControl(USBDevice *device) : device(device) {
251 241 specification.samplerate.single.base = 100e6;
252 242 specification.samplerate.single.max = 125e6;
253 243 specification.samplerate.single.maxDownsampler = 131072;
254   - specification.samplerate.single.recordLengths << UINT_MAX << 10240 << 14336;
  244 + specification.samplerate.single.recordLengths = {UINT_MAX, 10240, 14336};
255 245 specification.samplerate.multi.base = 200e6;
256 246 specification.samplerate.multi.max = 250e6;
257 247 specification.samplerate.multi.maxDownsampler = 131072;
258   - specification.samplerate.multi.recordLengths << UINT_MAX << 20480 << 28672;
  248 + specification.samplerate.multi.recordLengths = {UINT_MAX, 20480, 28672};
259 249 specification.bufferDividers << 1000 << 1 << 1;
260 250 specification.gainSteps << 0.16 << 0.40 << 0.80 << 1.60 << 4.00 << 8.0 << 16.0 << 40.0 << 80.0;
261 251 /// \todo Use calibration data to get the DSO-5200(A) sample ranges
... ... @@ -297,11 +287,11 @@ HantekDsoControl::HantekDsoControl(USBDevice *device) : device(device) {
297 287 specification.samplerate.single.base = 1e6;
298 288 specification.samplerate.single.max = 48e6;
299 289 specification.samplerate.single.maxDownsampler = 10;
300   - specification.samplerate.single.recordLengths << UINT_MAX << 10240;
  290 + specification.samplerate.single.recordLengths = {UINT_MAX, 10240};
301 291 specification.samplerate.multi.base = 1e6;
302 292 specification.samplerate.multi.max = 48e6;
303 293 specification.samplerate.multi.maxDownsampler = 10;
304   - specification.samplerate.multi.recordLengths << UINT_MAX << 20480;
  294 + specification.samplerate.multi.recordLengths = {UINT_MAX, 20480};
305 295 specification.bufferDividers << 1000 << 1 << 1;
306 296 specification.gainSteps << 0.08 << 0.16 << 0.40 << 0.80 << 1.60 << 4.00 << 8.0 << 16.0 << 40.0;
307 297 // This data was based on testing and depends on Divider.
... ... @@ -318,45 +308,36 @@ HantekDsoControl::HantekDsoControl(USBDevice *device) : device(device) {
318 308 throw new std::runtime_error("unknown model");
319 309 }
320 310  
321   - controlsettings.recordLengthId = 1;
322   - controlsettings.samplerate.limits = &(specification.samplerate.single);
323   - controlsettings.samplerate.downsampler = 1;
324 311 this->previousSampleCount = 0;
325 312  
326 313 // Get channel level data
327 314 errorCode = device->controlRead(CONTROL_VALUE, (unsigned char *)&(specification.offsetLimit),
328 315 sizeof(specification.offsetLimit), (int)VALUE_OFFSETLIMITS);
329 316 if (errorCode < 0) {
330   - device->disconnect();
  317 + qWarning() << tr("Couldn't get channel level data from oscilloscope");
331 318 emit statusMessage(tr("Couldn't get channel level data from oscilloscope"), 0);
  319 + emit communicationError();
332 320 return;
333 321 }
334 322  
335 323 sampling = false;
336 324 }
337 325  
338   -/// \brief Disconnects the device.
339 326 HantekDsoControl::~HantekDsoControl() {
340 327 // Clean up commands
341 328 for (int cIndex = 0; cIndex < BULK_COUNT; ++cIndex) { delete command[cIndex]; }
342 329 }
343 330  
344   -/// \brief Gets the physical channel count for this oscilloscope.
345   -/// \return The number of physical channels.
346 331 unsigned HantekDsoControl::getChannelCount() { return HANTEK_CHANNELS; }
347 332  
348   -/// \brief Get available record lengths for this oscilloscope.
349   -/// \return The number of physical channels, empty list for continuous.
350   -QList<unsigned> *HantekDsoControl::getAvailableRecordLengths() { return &controlsettings.samplerate.limits->recordLengths; }
  333 +const std::vector<unsigned> &HantekDsoControl::getAvailableRecordLengths() { //
  334 + return controlsettings.samplerate.limits->recordLengths;
  335 +}
351 336  
352   -/// \brief Get minimum samplerate for this oscilloscope.
353   -/// \return The minimum samplerate for the current configuration in S/s.
354 337 double HantekDsoControl::getMinSamplerate() {
355 338 return (double)specification.samplerate.single.base / specification.samplerate.single.maxDownsampler;
356 339 }
357 340  
358   -/// \brief Get maximum samplerate for this oscilloscope.
359   -/// \return The maximum samplerate for the current configuration in S/s.
360 341 double HantekDsoControl::getMaxSamplerate() {
361 342 ControlSamplerateLimits *limits =
362 343 (controlsettings.usedChannels <= 1) ? &specification.samplerate.multi : &specification.samplerate.single;
... ... @@ -368,8 +349,7 @@ void HantekDsoControl::updateInterval() {
368 349 // Check the current oscilloscope state everytime 25% of the time the buffer
369 350 // should be refilled
370 351 if (isRollMode())
371   - cycleTime = (int)((double)device->getPacketSize() /
372   - ((controlsettings.samplerate.limits == &specification.samplerate.multi) ? 1 : HANTEK_CHANNELS) /
  352 + cycleTime = (int)((double)device->getPacketSize() / (isFastRate() ? 1 : HANTEK_CHANNELS) /
373 353 controlsettings.samplerate.current * 250);
374 354 else
375 355 cycleTime = (int)((double)getRecordLength() / controlsettings.samplerate.current * 250);
... ... @@ -378,15 +358,18 @@ void HantekDsoControl::updateInterval() {
378 358 cycleTime = qBound(10, cycleTime, 1000);
379 359 }
380 360  
381   -bool HantekDsoControl::isRollMode() {
  361 +bool HantekDsoControl::isRollMode() const {
382 362 return controlsettings.samplerate.limits->recordLengths[controlsettings.recordLengthId] == UINT_MAX;
383 363 }
384 364  
385   -int HantekDsoControl::getRecordLength() { return controlsettings.samplerate.limits->recordLengths[controlsettings.recordLengthId]; }
  365 +bool HantekDsoControl::isFastRate() const {
  366 + return controlsettings.samplerate.limits == &specification.samplerate.multi;
  367 +}
  368 +
  369 +int HantekDsoControl::getRecordLength() const {
  370 + return controlsettings.samplerate.limits->recordLengths[controlsettings.recordLengthId];
  371 +}
386 372  
387   -/// \brief Calculates the trigger point from the CommandGetCaptureState data.
388   -/// \param value The data value that contains the trigger point.
389   -/// \return The calculated trigger point for the given data.
390 373 unsigned HantekDsoControl::calculateTriggerPoint(unsigned value) {
391 374 unsigned result = value;
392 375  
... ... @@ -397,235 +380,192 @@ unsigned HantekDsoControl::calculateTriggerPoint(unsigned value) {
397 380 return result;
398 381 }
399 382  
400   -/// \brief Gets the current state.
401   -/// \return The current CaptureState of the oscilloscope, libusb error code on
402   -/// error.
403   -int HantekDsoControl::getCaptureState() {
  383 +std::pair<int, unsigned> HantekDsoControl::getCaptureState() const {
404 384 int errorCode;
405 385  
406   - if (!specification.supportsCaptureState) return CAPTURE_READY;
  386 + if (!specification.supportsCaptureState) return std::make_pair(CAPTURE_READY, 0);
407 387  
408 388 errorCode = device->bulkCommand(command[BULK_GETCAPTURESTATE], 1);
409   - if (errorCode < 0) return errorCode;
  389 + if (errorCode < 0) {
  390 + qWarning() << "Getting capture state failed: " << libUsbErrorString(errorCode);
  391 + return std::make_pair(CAPTURE_ERROR, 0);
  392 + }
410 393  
411 394 BulkResponseGetCaptureState response;
412 395 errorCode = device->bulkRead(response.data(), response.getSize());
413   - if (errorCode < 0) return errorCode;
414   -
415   - controlsettings.trigger.point = this->calculateTriggerPoint(response.getTriggerPoint());
  396 + if (errorCode < 0) {
  397 + qWarning() << "Getting capture state failed: " << libUsbErrorString(errorCode);
  398 + return std::make_pair(CAPTURE_ERROR, 0);
  399 + }
416 400  
417   - return (int)response.getCaptureState();
  401 + return std::make_pair((int)response.getCaptureState(), response.getTriggerPoint());
418 402 }
419 403  
420   -/// \brief Gets sample data from the oscilloscope and converts it.
421   -/// \return sample count on success, libusb error code on error.
422   -/// TODO Refactor. MODEL_DSO6022BE needs to be handled differently most of the time
423   -int HantekDsoControl::getSamples(bool process) {
424   - int errorCode;
425   -
426   - const unsigned DROP_DSO6022_HEAD = 0x410;
427   - const unsigned DROP_DSO6022_TAIL = 0x3F0;
428   -
429   - if (device->getUniqueModelID() != MODEL_DSO6022BE) {
  404 +std::vector<unsigned char> HantekDsoControl::getSamples(unsigned &previousSampleCount) const {
  405 + if (!specification.useControlNoBulk) {
430 406 // Request data
431   - errorCode = device->bulkCommand(command[BULK_GETDATA], 1);
432   - if (errorCode < 0) return errorCode;
  407 + int errorCode = device->bulkCommand(command[BULK_GETDATA], 1);
  408 + if (errorCode < 0) {
  409 + qWarning() << "Getting sample data failed: " << libUsbErrorString(errorCode);
  410 + emit communicationError();
  411 + return std::vector<unsigned char>();
  412 + }
433 413 }
434 414  
435   - // Save raw data to temporary buffer
436   - bool fastRate = false;
437   - unsigned totalSampleCount = this->getSampleCount(&fastRate);
438   - if (totalSampleCount == UINT_MAX) return LIBUSB_ERROR_INVALID_PARAM;
  415 + unsigned totalSampleCount = this->getSampleCount();
439 416  
440 417 // To make sure no samples will remain in the scope buffer, also check the
441 418 // sample count before the last sampling started
442   - if (totalSampleCount < this->previousSampleCount) {
443   - unsigned currentSampleCount = totalSampleCount;
444   - totalSampleCount = this->previousSampleCount;
445   - this->previousSampleCount = currentSampleCount; // Using sampleCount as temporary buffer since it
446   - // was set to totalSampleCount
  419 + if (totalSampleCount < previousSampleCount) {
  420 + std::swap(totalSampleCount, previousSampleCount);
447 421 } else {
448   - this->previousSampleCount = totalSampleCount;
  422 + previousSampleCount = totalSampleCount;
449 423 }
450 424  
451   - unsigned sampleCount = totalSampleCount;
452   - if (!fastRate) sampleCount /= HANTEK_CHANNELS;
453   - unsigned dataLength = totalSampleCount;
454   - if (specification.sampleSize > 8) dataLength *= 2;
  425 + unsigned dataLength = (specification.sampleSize > 8) ? totalSampleCount * 2 : totalSampleCount;
455 426  
  427 + // Save raw data to temporary buffer
456 428 std::vector<unsigned char> data(dataLength);
457   - errorCode = device->bulkReadMulti(data.data(), dataLength);
458   - if (errorCode < 0) return errorCode;
  429 + int errorcode = device->bulkReadMulti(data.data(), dataLength);
  430 + if (errorcode < 0) {
  431 + qWarning() << "Getting sample data failed: " << libUsbErrorString(errorcode);
  432 + return std::vector<unsigned char>();
  433 + }
  434 + data.resize((size_t)errorcode);
459 435  
460   - // Process the data only if we want it
461   - if (!process) return LIBUSB_SUCCESS;
  436 + static unsigned id = 0;
  437 + ++id;
  438 + timestampDebug(QString("Received packet %1").arg(id));
462 439  
463   - // How much data did we really receive?
464   - dataLength = errorCode;
465   - if (specification.sampleSize > 8)
466   - totalSampleCount = dataLength / 2;
467   - else
468   - totalSampleCount = dataLength;
  440 + return data;
  441 +}
469 442  
470   - // Convert channel data
471   - if (fastRate) {
472   - QWriteLocker locker(&result.lock);
473   - result.samplerate = controlsettings.samplerate.current;
474   - result.append = isRollMode();
  443 +void HantekDsoControl::convertRawDataToSamples(const std::vector<unsigned char> &rawData) {
  444 + const size_t totalSampleCount = (specification.sampleSize > 8) ? rawData.size() / 2 : rawData.size();
  445 +
  446 + QWriteLocker locker(&result.lock);
  447 + result.samplerate = controlsettings.samplerate.current;
  448 + result.append = isRollMode();
  449 + // Prepare result buffers
  450 + result.data.resize(HANTEK_CHANNELS);
  451 + for (int channelCounter = 0; channelCounter < HANTEK_CHANNELS; ++channelCounter)
  452 + result.data[channelCounter].clear();
  453 +
  454 + const unsigned extraBitsSize = specification.sampleSize - 8; // Number of extra bits
  455 + const unsigned short extraBitsMask = (0x00ff << extraBitsSize) & 0xff00; // Mask for extra bits extraction
475 456  
  457 + // Convert channel data
  458 + if (isFastRate()) {
476 459 // Fast rate mode, one channel is using all buffers
477   - sampleCount = totalSampleCount;
478   - int channel = 0;
  460 + unsigned channel = 0;
479 461 for (; channel < HANTEK_CHANNELS; ++channel) {
480 462 if (controlsettings.voltage[channel].used) break;
481 463 }
482 464  
483   - // Clear unused channels
484   - for (int channelCounter = 0; channelCounter < HANTEK_CHANNELS; ++channelCounter)
485   - if (channelCounter != channel) { result.data[channelCounter].clear(); }
  465 + if (channel >= HANTEK_CHANNELS) return;
486 466  
487   - if (channel < HANTEK_CHANNELS) {
488   - // Resize sample vector
489   - result.data[channel].resize(sampleCount);
  467 + // Resize sample vector
  468 + result.data[channel].resize(totalSampleCount);
  469 +
  470 + const int gainID = (int)controlsettings.voltage[channel].gain;
  471 + const unsigned short limit = specification.voltageLimit[channel][gainID];
  472 + const double offset = controlsettings.voltage[channel].offsetReal;
  473 + const double gainStep = specification.gainSteps[gainID];
  474 +
  475 + // Convert data from the oscilloscope and write it into the sample buffer
  476 + unsigned bufferPosition = controlsettings.trigger.point * 2;
  477 + if (specification.sampleSize > 8) {
  478 + for (unsigned pos = 0; pos < totalSampleCount; ++pos, ++bufferPosition) {
  479 + if (bufferPosition >= totalSampleCount) bufferPosition %= totalSampleCount;
  480 +
  481 + const unsigned short low = rawData[bufferPosition];
  482 + const unsigned extraBitsPosition = bufferPosition % HANTEK_CHANNELS;
  483 + const unsigned shift = (8 - (HANTEK_CHANNELS - 1 - extraBitsPosition) * extraBitsSize);
  484 + const unsigned short high =
  485 + ((unsigned short int)rawData[totalSampleCount + bufferPosition - extraBitsPosition] << shift) &
  486 + extraBitsMask;
  487 +
  488 + result.data[channel][pos] = ((double)(low + high) / limit - offset) * gainStep;
  489 + }
  490 + } else {
  491 + for (unsigned pos = 0; pos < totalSampleCount; ++pos, ++bufferPosition) {
  492 + if (bufferPosition >= totalSampleCount) bufferPosition %= totalSampleCount;
  493 +
  494 + double dataBuf = (double)((int)rawData[bufferPosition]);
  495 + result.data[channel][pos] = (dataBuf / limit - offset) * gainStep;
  496 + }
  497 + }
  498 + } else {
  499 + // Normal mode, channels are using their separate buffers
  500 + for (unsigned channel = 0; channel < HANTEK_CHANNELS; ++channel) {
  501 + result.data[channel].resize(totalSampleCount / HANTEK_CHANNELS);
490 502  
491   - // Convert data from the oscilloscope and write it into the sample
492   - // buffer
  503 + const int gainID = controlsettings.voltage[channel].gain;
  504 + const unsigned short limit = specification.voltageLimit[channel][gainID];
  505 + const double offset = controlsettings.voltage[channel].offsetReal;
  506 + const double gainStep = specification.gainSteps[gainID];
  507 +
  508 + // Convert data from the oscilloscope and write it into the sample buffer
493 509 unsigned bufferPosition = controlsettings.trigger.point * 2;
494 510 if (specification.sampleSize > 8) {
495 511 // Additional most significant bits after the normal data
496   - unsigned extraBitsPosition; // Track the position of the extra
497   - // bits in the additional byte
498   - unsigned extraBitsSize = specification.sampleSize - 8; // Number of extra bits
499   - unsigned short int extraBitsMask = (0x00ff << extraBitsSize) & 0xff00; // Mask for extra bits extraction
500   -
501   - for (unsigned realPosition = 0; realPosition < sampleCount; ++realPosition, ++bufferPosition) {
502   - if (bufferPosition >= sampleCount) bufferPosition %= sampleCount;
503   -
504   - extraBitsPosition = bufferPosition % HANTEK_CHANNELS;
505   -
506   - result.data[channel][realPosition] =
507   - ((double)((unsigned short int)data[bufferPosition] +
508   - (((unsigned short int)data[sampleCount + bufferPosition - extraBitsPosition]
509   - << (8 - (HANTEK_CHANNELS - 1 - extraBitsPosition) * extraBitsSize)) &
510   - extraBitsMask)) /
511   - specification.voltageLimit[channel][controlsettings.voltage[channel].gain] -
512   - controlsettings.voltage[channel].offsetReal) *
513   - specification.gainSteps[controlsettings.voltage[channel].gain];
  512 + unsigned extraBitsIndex = 8 - channel * 2; // Bit position offset for extra bits extraction
  513 +
  514 + for (unsigned realPosition = 0; realPosition < result.data[channel].size();
  515 + ++realPosition, bufferPosition += HANTEK_CHANNELS) {
  516 + if (bufferPosition >= totalSampleCount) bufferPosition %= totalSampleCount;
  517 +
  518 + const unsigned short low = rawData[bufferPosition + HANTEK_CHANNELS - 1 - channel];
  519 + const unsigned short high =
  520 + ((unsigned short int)rawData[totalSampleCount + bufferPosition] << extraBitsIndex) &
  521 + extraBitsMask;
  522 +
  523 + result.data[channel][realPosition] = ((double)(low + high) / limit - offset) * gainStep;
514 524 }
515   - } else {
516   - for (unsigned realPosition = 0; realPosition < sampleCount; ++realPosition, ++bufferPosition) {
517   - if (bufferPosition >= sampleCount) bufferPosition %= sampleCount;
518   -
519   - double dataBuf = (double)((int)data[bufferPosition]);
520   - result.data[channel][realPosition] =
521   - (dataBuf / specification.voltageLimit[channel][controlsettings.voltage[channel].gain] -
522   - controlsettings.voltage[channel].offsetReal) *
523   - specification.gainSteps[controlsettings.voltage[channel].gain];
  525 + } else if (device->getUniqueModelID() == MODEL_DSO6022BE) {
  526 + // if device is 6022BE, drop heading & trailing samples
  527 + const unsigned DROP_DSO6022_HEAD = 0x410;
  528 + const unsigned DROP_DSO6022_TAIL = 0x3F0;
  529 + if (!isRollMode()) {
  530 + result.data[channel].resize(result.data[channel].size() - (DROP_DSO6022_HEAD + DROP_DSO6022_TAIL));
  531 + // if device is 6022BE, offset DROP_DSO6022_HEAD incrementally
  532 + bufferPosition += DROP_DSO6022_HEAD * 2;
524 533 }
525   - }
526   - }
527   - } else {
528   - QWriteLocker locker(&result.lock);
529   - result.samplerate = controlsettings.samplerate.current;
530   - result.append = isRollMode();
531   -
532   - // Normal mode, channels are using their separate buffers
533   - sampleCount = totalSampleCount / HANTEK_CHANNELS;
534   - // if device is 6022BE, drop heading & trailing samples
535   - if (device->getUniqueModelID() == MODEL_DSO6022BE) sampleCount -= (DROP_DSO6022_HEAD + DROP_DSO6022_TAIL);
536   - for (int channel = 0; channel < HANTEK_CHANNELS; ++channel) {
537   - if (controlsettings.voltage[channel].used) {
538   - // Resize sample vector
539   - if (result.data[channel].size() < sampleCount) { result.data[channel].resize(sampleCount); }
540   -
541   - // Convert data from the oscilloscope and write it into the sample
542   - // buffer
543   - unsigned bufferPosition = controlsettings.trigger.point * 2;
544   - if (specification.sampleSize > 8) {
545   - // Additional most significant bits after the normal data
546   - unsigned extraBitsSize = specification.sampleSize - 8; // Number of extra bits
547   - unsigned short int extraBitsMask =
548   - (0x00ff << extraBitsSize) & 0xff00; // Mask for extra bits extraction
549   - unsigned extraBitsIndex = 8 - channel * 2; // Bit position offset for extra bits extraction
550   -
551   - for (unsigned realPosition = 0; realPosition < sampleCount;
552   - ++realPosition, bufferPosition += HANTEK_CHANNELS) {
553   - if (bufferPosition >= totalSampleCount) bufferPosition %= totalSampleCount;
554   -
555   - result.data[channel][realPosition] =
556   - ((double)((unsigned short int)data[bufferPosition + HANTEK_CHANNELS - 1 - channel] +
557   - (((unsigned short int)data[totalSampleCount + bufferPosition] << extraBitsIndex) &
558   - extraBitsMask)) /
559   - specification.voltageLimit[channel][controlsettings.voltage[channel].gain] -
560   - controlsettings.voltage[channel].offsetReal) *
561   - specification.gainSteps[controlsettings.voltage[channel].gain];
562   - }
563   - } else {
564   - if (device->getUniqueModelID() == MODEL_DSO6022BE) {
565   - bufferPosition += channel;
566   - // if device is 6022BE, offset DROP_DSO6022_HEAD incrementally
567   - bufferPosition += DROP_DSO6022_HEAD * 2;
568   - } else
569   - bufferPosition += HANTEK_CHANNELS - 1 - channel;
570   -
571   - for (unsigned realPosition = 0; realPosition < sampleCount;
572   - ++realPosition, bufferPosition += HANTEK_CHANNELS) {
573   - if (bufferPosition >= totalSampleCount) bufferPosition %= totalSampleCount;
574   -
575   - if (device->getUniqueModelID() == MODEL_DSO6022BE) {
576   - double dataBuf = (double)((int)(data[bufferPosition] - 0x83));
577   - result.data[channel][realPosition] =
578   - (dataBuf / specification.voltageLimit[channel][controlsettings.voltage[channel].gain]) *
579   - specification.gainSteps[controlsettings.voltage[channel].gain];
580   - } else {
581   - double dataBuf = (double)((int)(data[bufferPosition]));
582   - result.data[channel][realPosition] =
583   - (dataBuf / specification.voltageLimit[channel][controlsettings.voltage[channel].gain] -
584   - controlsettings.voltage[channel].offsetReal) *
585   - specification.gainSteps[controlsettings.voltage[channel].gain];
586   - }
587   - }
  534 + bufferPosition += channel;
  535 + for (unsigned pos = 0; pos < result.data[channel].size(); ++pos, bufferPosition += HANTEK_CHANNELS) {
  536 + if (bufferPosition >= totalSampleCount) bufferPosition %= totalSampleCount;
  537 + double dataBuf = (double)((int)(rawData[bufferPosition] - 0x83));
  538 + result.data[channel][pos] = (dataBuf / limit) * gainStep;
588 539 }
589 540 } else {
590   - // Clear unused channels
591   - result.data[channel].clear();
  541 + bufferPosition += HANTEK_CHANNELS - 1 - channel;
  542 + for (unsigned pos = 0; pos < result.data[channel].size(); ++pos, bufferPosition += HANTEK_CHANNELS) {
  543 + if (bufferPosition >= totalSampleCount) bufferPosition %= totalSampleCount;
  544 + double dataBuf = (double)((int)(rawData[bufferPosition]));
  545 + result.data[channel][pos] = (dataBuf / limit - offset) * gainStep;
  546 + }
592 547 }
593 548 }
594 549 }
595   -
596   - static unsigned id = 0;
597   - ++id;
598   - timestampDebug(QString("Received packet %1").arg(id));
599   -
600   - emit samplesAvailable();
601   -
602   - return errorCode;
603 550 }
604 551  
605   -/// \brief Calculated the nearest samplerate supported by the oscilloscope.
606   -/// \param samplerate The target samplerate, that should be met as good as
607   -/// possible.
608   -/// \param fastRate true, if the fast rate mode is enabled.
609   -/// \param maximum The target samplerate is the maximum allowed when true, the
610   -/// minimum otherwise.
611   -/// \param downsampler Pointer to where the selected downsampling factor should
612   -/// be written.
613   -/// \return The nearest samplerate supported, 0.0 on error.
614   -double HantekDsoControl::getBestSamplerate(double samplerate, bool fastRate, bool maximum, unsigned *downsampler) {
  552 +double HantekDsoControl::getBestSamplerate(double samplerate, bool fastRate, bool maximum,
  553 + unsigned *downsampler) const {
615 554 // Abort if the input value is invalid
616 555 if (samplerate <= 0.0) return 0.0;
617 556  
618 557 double bestSamplerate = 0.0;
619 558  
620 559 // Get samplerate specifications for this mode and model
621   - ControlSamplerateLimits *limits;
  560 + const ControlSamplerateLimits *limits;
622 561 if (fastRate)
623 562 limits = &(specification.samplerate.multi);
624 563 else
625 564 limits = &(specification.samplerate.single);
626 565  
627 566 // Get downsampling factor that would provide the requested rate
628   - double bestDownsampler = (double)limits->base / specification.bufferDividers[controlsettings.recordLengthId] / samplerate;
  567 + double bestDownsampler =
  568 + (double)limits->base / specification.bufferDividers[controlsettings.recordLengthId] / samplerate;
629 569 // Base samplerate sufficient, or is the maximum better?
630 570 if (bestDownsampler < 1.0 &&
631 571 (samplerate <= limits->max / specification.bufferDividers[controlsettings.recordLengthId] || !maximum)) {
... ... @@ -694,30 +634,17 @@ double HantekDsoControl::getBestSamplerate(double samplerate, bool fastRate, boo
694 634 return bestSamplerate;
695 635 }
696 636  
697   -/// \brief Get the count of samples that are expected returned by the scope.
698   -/// \param fastRate Is set to the state of the fast rate mode when provided.
699   -/// \return The total number of samples the scope should return.
700   -unsigned HantekDsoControl::getSampleCount(bool *fastRate) {
701   - unsigned totalSampleCount = getRecordLength();
702   - bool fastRateEnabled = controlsettings.samplerate.limits == &specification.samplerate.multi;
703   -
704   - if (totalSampleCount == UINT_MAX) {
705   - // Roll mode
706   - const int packetSize = device->getPacketSize();
707   - if (packetSize < 0)
708   - totalSampleCount = UINT_MAX;
709   - else
710   - totalSampleCount = packetSize;
  637 +unsigned HantekDsoControl::getSampleCount() const {
  638 + if (isRollMode()) {
  639 + return device->getPacketSize();
711 640 } else {
712   - if (!fastRateEnabled) totalSampleCount *= HANTEK_CHANNELS;
  641 + if (isFastRate())
  642 + return getRecordLength();
  643 + else
  644 + return getRecordLength() * HANTEK_CHANNELS;
713 645 }
714   - if (fastRate) *fastRate = fastRateEnabled;
715   - return totalSampleCount;
716 646 }
717 647  
718   -/// \brief Sets the size of the sample buffer without updating dependencies.
719   -/// \param index The record length index that should be set.
720   -/// \return The record length that has been set, 0 on error.
721 648 unsigned HantekDsoControl::updateRecordLength(unsigned index) {
722 649 if (index >= (unsigned)controlsettings.samplerate.limits->recordLengths.size()) return 0;
723 650  
... ... @@ -754,7 +681,8 @@ unsigned HantekDsoControl::updateRecordLength(unsigned index) {
754 681 }
755 682  
756 683 // Check if the divider has changed and adapt samplerate limits accordingly
757   - bool bDividerChanged = specification.bufferDividers[index] != specification.bufferDividers[controlsettings.recordLengthId];
  684 + bool bDividerChanged =
  685 + specification.bufferDividers[index] != specification.bufferDividers[controlsettings.recordLengthId];
758 686  
759 687 controlsettings.recordLengthId = index;
760 688  
... ... @@ -768,11 +696,6 @@ unsigned HantekDsoControl::updateRecordLength(unsigned index) {
768 696 return controlsettings.samplerate.limits->recordLengths[index];
769 697 }
770 698  
771   -/// \brief Sets the samplerate based on the parameters calculated by
772   -/// Control::getBestSamplerate.
773   -/// \param downsampler The downsampling factor.
774   -/// \param fastRate true, if one channel uses all buffers.
775   -/// \return The downsampling factor that has been set.
776 699 unsigned HantekDsoControl::updateSamplerate(unsigned downsampler, bool fastRate) {
777 700 // Get samplerate limits
778 701 Hantek::ControlSamplerateLimits *limits =
... ... @@ -872,8 +795,8 @@ unsigned HantekDsoControl::updateSamplerate(unsigned downsampler, bool fastRate)
872 795  
873 796 controlsettings.samplerate.downsampler = downsampler;
874 797 if (downsampler)
875   - controlsettings.samplerate.current =
876   - controlsettings.samplerate.limits->base / specification.bufferDividers[controlsettings.recordLengthId] / downsampler;
  798 + controlsettings.samplerate.current = controlsettings.samplerate.limits->base /
  799 + specification.bufferDividers[controlsettings.recordLengthId] / downsampler;
877 800 else
878 801 controlsettings.samplerate.current =
879 802 controlsettings.samplerate.limits->max / specification.bufferDividers[controlsettings.recordLengthId];
... ... @@ -894,7 +817,6 @@ unsigned HantekDsoControl::updateSamplerate(unsigned downsampler, bool fastRate)
894 817 return downsampler;
895 818 }
896 819  
897   -/// \brief Restore the samplerate/timebase targets after divider updates.
898 820 void HantekDsoControl::restoreTargets() {
899 821 if (controlsettings.samplerate.target.samplerateSet)
900 822 this->setSamplerate();
... ... @@ -902,7 +824,6 @@ void HantekDsoControl::restoreTargets() {
902 824 this->setRecordTime();
903 825 }
904 826  
905   -/// \brief Update the minimum and maximum supported samplerate.
906 827 void HantekDsoControl::updateSamplerateLimits() {
907 828 // Works only if the minimum samplerate for normal mode is lower than for fast
908 829 // rate mode, which is the case for all models
... ... @@ -917,24 +838,24 @@ void HantekDsoControl::updateSamplerateLimits() {
917 838 /// \brief Sets the size of the oscilloscopes sample buffer.
918 839 /// \param index The record length index that should be set.
919 840 /// \return The record length that has been set, 0 on error.
920   -unsigned HantekDsoControl::setRecordLength(unsigned index) {
921   - if (!device->isConnected()) return 0;
  841 +Dso::ErrorCode HantekDsoControl::setRecordLength(unsigned index) {
  842 + if (!device->isConnected()) return Dso::ErrorCode::ERROR_CONNECTION;
922 843  
923   - if (!this->updateRecordLength(index)) return 0;
  844 + if (!this->updateRecordLength(index)) return Dso::ErrorCode::ERROR_PARAMETER;
924 845  
925 846 this->restoreTargets();
926 847 this->setPretriggerPosition(controlsettings.trigger.position);
927 848  
928 849 emit recordLengthChanged(getRecordLength());
929   - return getRecordLength();
  850 + return Dso::ErrorCode::ERROR_NONE;
930 851 }
931 852  
932 853 /// \brief Sets the samplerate of the oscilloscope.
933 854 /// \param samplerate The samplerate that should be met (S/s), 0.0 to restore
934 855 /// current samplerate.
935 856 /// \return The samplerate that has been set, 0.0 on error.
936   -double HantekDsoControl::setSamplerate(double samplerate) {
937   - if (!device->isConnected()) return 0.0;
  857 +Dso::ErrorCode HantekDsoControl::setSamplerate(double samplerate) {
  858 + if (!device->isConnected()) return Dso::ErrorCode::ERROR_CONNECTION;
938 859  
939 860 if (samplerate == 0.0) {
940 861 samplerate = controlsettings.samplerate.target.samplerate;
... ... @@ -946,19 +867,19 @@ double HantekDsoControl::setSamplerate(double samplerate) {
946 867 if (!specification.isSoftwareTriggerDevice) {
947 868 // When possible, enable fast rate if it is required to reach the requested
948 869 // samplerate
949   - bool fastRate =
950   - (controlsettings.usedChannels <= 1) &&
951   - (samplerate > specification.samplerate.single.max / specification.bufferDividers[controlsettings.recordLengthId]);
  870 + bool fastRate = (controlsettings.usedChannels <= 1) &&
  871 + (samplerate > specification.samplerate.single.max /
  872 + specification.bufferDividers[controlsettings.recordLengthId]);
952 873  
953 874 // What is the nearest, at least as high samplerate the scope can provide?
954 875 unsigned downsampler = 0;
955   - double bestSamplerate = getBestSamplerate(samplerate, fastRate, false, &(downsampler));
  876 + getBestSamplerate(samplerate, fastRate, false, &(downsampler));
956 877  
957 878 // Set the calculated samplerate
958 879 if (this->updateSamplerate(downsampler, fastRate) == UINT_MAX)
959   - return 0.0;
  880 + return Dso::ErrorCode::ERROR_PARAMETER;
960 881 else {
961   - return bestSamplerate;
  882 + return Dso::ErrorCode::ERROR_NONE;
962 883 }
963 884 } else {
964 885 int sampleId;
... ... @@ -977,7 +898,7 @@ double HantekDsoControl::setSamplerate(double samplerate) {
977 898 emit recordTimeChanged((double)(getRecordLength() - sampleMargin) / controlsettings.samplerate.current);
978 899 emit samplerateChanged(controlsettings.samplerate.current);
979 900  
980   - return samplerate;
  901 + return Dso::ErrorCode::ERROR_NONE;
981 902 }
982 903 }
983 904  
... ... @@ -985,8 +906,8 @@ double HantekDsoControl::setSamplerate(double samplerate) {
985 906 /// \param duration The record time duration that should be met (s), 0.0 to
986 907 /// restore current record time.
987 908 /// \return The record time duration that has been set, 0.0 on error.
988   -double HantekDsoControl::setRecordTime(double duration) {
989   - if (!device->isConnected()) return 0.0;
  909 +Dso::ErrorCode HantekDsoControl::setRecordTime(double duration) {
  910 + if (!device->isConnected()) return Dso::ErrorCode::ERROR_CONNECTION;
990 911  
991 912 if (duration == 0.0) {
992 913 duration = controlsettings.samplerate.target.duration;
... ... @@ -1004,18 +925,17 @@ double HantekDsoControl::setRecordTime(double duration) {
1004 925 // When possible, enable fast rate if the record time can't be set that low
1005 926 // to improve resolution
1006 927 bool fastRate = (controlsettings.usedChannels <= 1) &&
1007   - (maxSamplerate >=
1008   - specification.samplerate.multi.base / specification.bufferDividers[controlsettings.recordLengthId]);
  928 + (maxSamplerate >= specification.samplerate.multi.base /
  929 + specification.bufferDividers[controlsettings.recordLengthId]);
1009 930  
1010 931 // What is the nearest, at most as high samplerate the scope can provide?
1011 932 unsigned downsampler = 0;
1012   - double bestSamplerate = getBestSamplerate(maxSamplerate, fastRate, true, &(downsampler));
1013 933  
1014 934 // Set the calculated samplerate
1015 935 if (this->updateSamplerate(downsampler, fastRate) == UINT_MAX)
1016   - return 0.0;
  936 + return Dso::ErrorCode::ERROR_PARAMETER;
1017 937 else {
1018   - return (double)getRecordLength() / bestSamplerate;
  938 + return Dso::ErrorCode::ERROR_NONE;
1019 939 }
1020 940 } else {
1021 941 // For now - we go for the 10240 size sampling - the other seems not to be
... ... @@ -1039,7 +959,7 @@ double HantekDsoControl::setRecordTime(double duration) {
1039 959 controlsettings.samplerate.current = specification.sampleSteps[sampleId];
1040 960  
1041 961 emit samplerateChanged(controlsettings.samplerate.current);
1042   - return controlsettings.samplerate.current;
  962 + return Dso::ErrorCode::ERROR_NONE;
1043 963 }
1044 964 }
1045 965  
... ... @@ -1047,10 +967,10 @@ double HantekDsoControl::setRecordTime(double duration) {
1047 967 /// \param channel The channel that should be set.
1048 968 /// \param used true if the channel should be sampled.
1049 969 /// \return See ::Dso::ErrorCode.
1050   -int HantekDsoControl::setChannelUsed(unsigned channel, bool used) {
1051   - if (!device->isConnected()) return Dso::ERROR_CONNECTION;
  970 +Dso::ErrorCode HantekDsoControl::setChannelUsed(unsigned channel, bool used) {
  971 + if (!device->isConnected()) return Dso::ErrorCode::ERROR_CONNECTION;
1052 972  
1053   - if (channel >= HANTEK_CHANNELS) return Dso::ERROR_PARAMETER;
  973 + if (channel >= HANTEK_CHANNELS) return Dso::ErrorCode::ERROR_PARAMETER;
1054 974  
1055 975 // Update settings
1056 976 controlsettings.voltage[channel].used = used;
... ... @@ -1105,17 +1025,17 @@ int HantekDsoControl::setChannelUsed(unsigned channel, bool used) {
1105 1025  
1106 1026 if (fastRateChanged) this->updateSamplerateLimits();
1107 1027  
1108   - return Dso::ERROR_NONE;
  1028 + return Dso::ErrorCode::ERROR_NONE;
1109 1029 }
1110 1030  
1111 1031 /// \brief Set the coupling for the given channel.
1112 1032 /// \param channel The channel that should be set.
1113 1033 /// \param coupling The new coupling for the channel.
1114 1034 /// \return See ::Dso::ErrorCode.
1115   -int HantekDsoControl::setCoupling(unsigned channel, Dso::Coupling coupling) {
1116   - if (!device->isConnected()) return Dso::ERROR_CONNECTION;
  1035 +Dso::ErrorCode HantekDsoControl::setCoupling(unsigned channel, Dso::Coupling coupling) {
  1036 + if (!device->isConnected()) return Dso::ErrorCode::ERROR_CONNECTION;
1117 1037  
1118   - if (channel >= HANTEK_CHANNELS) return Dso::ERROR_PARAMETER;
  1038 + if (channel >= HANTEK_CHANNELS) return Dso::ErrorCode::ERROR_PARAMETER;
1119 1039  
1120 1040 // SetRelays control command for coupling relays
1121 1041 if (specification.supportsCouplingRelays) {
... ... @@ -1124,17 +1044,18 @@ int HantekDsoControl::setCoupling(unsigned channel, Dso::Coupling coupling) {
1124 1044 this->controlPending[CONTROLINDEX_SETRELAYS] = true;
1125 1045 }
1126 1046  
1127   - return Dso::ERROR_NONE;
  1047 + return Dso::ErrorCode::ERROR_NONE;
1128 1048 }
1129 1049  
1130 1050 /// \brief Sets the gain for the given channel.
  1051 +/// Get the actual gain by specification.gainSteps[gainId]
1131 1052 /// \param channel The channel that should be set.
1132 1053 /// \param gain The gain that should be met (V/div).
1133 1054 /// \return The gain that has been set, ::Dso::ErrorCode on error.
1134   -double HantekDsoControl::setGain(unsigned channel, double gain) {
1135   - if (!device->isConnected()) return Dso::ERROR_CONNECTION;
  1055 +Dso::ErrorCode HantekDsoControl::setGain(unsigned channel, double gain) {
  1056 + if (!device->isConnected()) return Dso::ErrorCode::ERROR_CONNECTION;
1136 1057  
1137   - if (channel >= HANTEK_CHANNELS) return Dso::ERROR_PARAMETER;
  1058 + if (channel >= HANTEK_CHANNELS) return Dso::ErrorCode::ERROR_PARAMETER;
1138 1059  
1139 1060 // Find lowest gain voltage thats at least as high as the requested
1140 1061 int gainId;
... ... @@ -1168,30 +1089,25 @@ double HantekDsoControl::setGain(unsigned channel, double gain) {
1168 1089  
1169 1090 this->setOffset(channel, controlsettings.voltage[channel].offset);
1170 1091  
1171   - return specification.gainSteps[gainId];
  1092 + return Dso::ErrorCode::ERROR_NONE;
1172 1093 }
1173 1094  
1174 1095 /// \brief Set the offset for the given channel.
  1096 +/// Get the actual offset for the channel from controlsettings.voltage[channel].offsetReal
1175 1097 /// \param channel The channel that should be set.
1176 1098 /// \param offset The new offset value (0.0 - 1.0).
1177   -/// \return The offset that has been set, ::Dso::ErrorCode on error.
1178   -double HantekDsoControl::setOffset(unsigned channel, double offset) {
1179   - if (!device->isConnected()) return Dso::ERROR_CONNECTION;
  1099 +Dso::ErrorCode HantekDsoControl::setOffset(unsigned channel, double offset) {
  1100 + if (!device->isConnected()) return Dso::ErrorCode::ERROR_CONNECTION;
1180 1101  
1181   - if (channel >= HANTEK_CHANNELS) return Dso::ERROR_PARAMETER;
  1102 + if (channel >= HANTEK_CHANNELS) return Dso::ErrorCode::ERROR_PARAMETER;
1182 1103  
  1104 + unsigned short *channelOffLimit = specification.offsetLimit[channel][controlsettings.voltage[channel].gain];
1183 1105 // Calculate the offset value
1184 1106 // The range is given by the calibration data (convert from big endian)
1185   - unsigned short int minimum =
1186   - ((unsigned short int)*(
1187   - (unsigned char *)&(specification.offsetLimit[channel][controlsettings.voltage[channel].gain][OFFSET_START]))
1188   - << 8) +
1189   - *((unsigned char *)&(specification.offsetLimit[channel][controlsettings.voltage[channel].gain][OFFSET_START]) + 1);
1190   - unsigned short int maximum =
1191   - ((unsigned short int)*(
1192   - (unsigned char *)&(specification.offsetLimit[channel][controlsettings.voltage[channel].gain][OFFSET_END]))
1193   - << 8) +
1194   - *((unsigned char *)&(specification.offsetLimit[channel][controlsettings.voltage[channel].gain][OFFSET_END]) + 1);
  1107 + unsigned short int minimum = ((unsigned short int)*((unsigned char *)&(channelOffLimit[OFFSET_START])) << 8) +
  1108 + *((unsigned char *)&(channelOffLimit[OFFSET_START]) + 1);
  1109 + unsigned short int maximum = ((unsigned short int)*((unsigned char *)&(channelOffLimit[OFFSET_END])) << 8) +
  1110 + *((unsigned char *)&(channelOffLimit[OFFSET_END]) + 1);
1195 1111 unsigned short int offsetValue = offset * (maximum - minimum) + minimum + 0.5;
1196 1112 double offsetReal = (double)(offsetValue - minimum) / (maximum - minimum);
1197 1113  
... ... @@ -1205,28 +1121,29 @@ double HantekDsoControl::setOffset(unsigned channel, double offset) {
1205 1121  
1206 1122 this->setTriggerLevel(channel, controlsettings.trigger.level[channel]);
1207 1123  
1208   - return offsetReal;
  1124 + return Dso::ErrorCode::ERROR_NONE;
1209 1125 }
1210 1126  
1211 1127 /// \brief Set the trigger mode.
1212 1128 /// \return See ::Dso::ErrorCode.
1213   -int HantekDsoControl::setTriggerMode(Dso::TriggerMode mode) {
1214   - if (!device->isConnected()) return Dso::ERROR_CONNECTION;
  1129 +Dso::ErrorCode HantekDsoControl::setTriggerMode(Dso::TriggerMode mode) {
  1130 + if (!device->isConnected()) return Dso::ErrorCode::ERROR_CONNECTION;
1215 1131  
1216   - if (mode < Dso::TRIGGERMODE_AUTO || mode >= Dso::TRIGGERMODE_COUNT) return Dso::ERROR_PARAMETER;
  1132 + if (mode < Dso::TRIGGERMODE_AUTO || mode >= Dso::TRIGGERMODE_COUNT) return Dso::ErrorCode::ERROR_PARAMETER;
1217 1133  
1218 1134 controlsettings.trigger.mode = mode;
1219   - return Dso::ERROR_NONE;
  1135 + return Dso::ErrorCode::ERROR_NONE;
1220 1136 }
1221 1137  
1222 1138 /// \brief Set the trigger source.
1223 1139 /// \param special true for a special channel (EXT, ...) as trigger source.
1224 1140 /// \param id The number of the channel, that should be used as trigger.
1225 1141 /// \return See ::Dso::ErrorCode.
1226   -int HantekDsoControl::setTriggerSource(bool special, unsigned id) {
1227   - if (!device->isConnected()) return Dso::ERROR_CONNECTION;
  1142 +Dso::ErrorCode HantekDsoControl::setTriggerSource(bool special, unsigned id) {
  1143 + if (!device->isConnected()) return Dso::ErrorCode::ERROR_CONNECTION;
1228 1144  
1229   - if ((!special && id >= HANTEK_CHANNELS) || (special && id >= HANTEK_SPECIAL_CHANNELS)) return Dso::ERROR_PARAMETER;
  1145 + if ((!special && id >= HANTEK_CHANNELS) || (special && id >= HANTEK_SPECIAL_CHANNELS))
  1146 + return Dso::ErrorCode::ERROR_PARAMETER;
1230 1147  
1231 1148 switch (specification.command.bulk.setTrigger) {
1232 1149 case BULK_SETTRIGGERANDSAMPLERATE:
... ... @@ -1251,7 +1168,7 @@ int HantekDsoControl::setTriggerSource(bool special, unsigned id) {
1251 1168 break;
1252 1169  
1253 1170 default:
1254   - return Dso::ERROR_UNSUPPORTED;
  1171 + return Dso::ErrorCode::ERROR_UNSUPPORTED;
1255 1172 }
1256 1173  
1257 1174 // SetRelays control command for external trigger relay
... ... @@ -1269,32 +1186,27 @@ int HantekDsoControl::setTriggerSource(bool special, unsigned id) {
1269 1186 } else
1270 1187 this->setTriggerLevel(id, controlsettings.trigger.level[id]);
1271 1188  
1272   - return Dso::ERROR_NONE;
  1189 + return Dso::ErrorCode::ERROR_NONE;
1273 1190 }
1274 1191  
1275 1192 /// \brief Set the trigger level.
1276 1193 /// \param channel The channel that should be set.
1277 1194 /// \param level The new trigger level (V).
1278 1195 /// \return The trigger level that has been set, ::Dso::ErrorCode on error.
1279   -double HantekDsoControl::setTriggerLevel(unsigned channel, double level) {
1280   - if (!device->isConnected()) return Dso::ERROR_CONNECTION;
  1196 +Dso::ErrorCode HantekDsoControl::setTriggerLevel(unsigned channel, double level) {
  1197 + if (!device->isConnected()) return Dso::ErrorCode::ERROR_CONNECTION;
1281 1198  
1282   - if (channel >= HANTEK_CHANNELS) return Dso::ERROR_PARAMETER;
  1199 + if (channel >= HANTEK_CHANNELS) return Dso::ErrorCode::ERROR_PARAMETER;
1283 1200  
1284 1201 // Calculate the trigger level value
1285   - unsigned short int minimum, maximum;
1286   - if (specification.sampleSize>8) {
  1202 + unsigned short minimum, maximum;
  1203 + if (specification.sampleSize > 8) {
  1204 + const unsigned short *offsetLimit = specification.offsetLimit[channel][controlsettings.voltage[channel].gain];
1287 1205 // The range is the same as used for the offsets for 10 bit models
1288   - minimum =
1289   - ((unsigned short int)*(
1290   - (unsigned char *)&(specification.offsetLimit[channel][controlsettings.voltage[channel].gain][OFFSET_START]))
1291   - << 8) +
1292   - *((unsigned char *)&(specification.offsetLimit[channel][controlsettings.voltage[channel].gain][OFFSET_START]) + 1);
1293   - maximum =
1294   - ((unsigned short int)*(
1295   - (unsigned char *)&(specification.offsetLimit[channel][controlsettings.voltage[channel].gain][OFFSET_END]))
1296   - << 8) +
1297   - *((unsigned char *)&(specification.offsetLimit[channel][controlsettings.voltage[channel].gain][OFFSET_END]) + 1);
  1206 + minimum = ((unsigned short int)*((unsigned char *)&(offsetLimit[OFFSET_START])) << 8) +
  1207 + *((unsigned char *)&(offsetLimit[OFFSET_START]) + 1);
  1208 + maximum = ((unsigned short int)*((unsigned char *)&(offsetLimit[OFFSET_END])) << 8) +
  1209 + *((unsigned char *)&(offsetLimit[OFFSET_END]) + 1);
1298 1210 } else {
1299 1211 // It's from 0x00 to 0xfd for the 8 bit models
1300 1212 minimum = 0x00;
... ... @@ -1302,14 +1214,10 @@ double HantekDsoControl::setTriggerLevel(unsigned channel, double level) {
1302 1214 }
1303 1215  
1304 1216 // Never get out of the limits
1305   - unsigned short int levelValue =
1306   - qBound((long int)minimum,
1307   - (long int)((controlsettings.voltage[channel].offsetReal +
1308   - level / specification.gainSteps[controlsettings.voltage[channel].gain]) *
1309   - (maximum - minimum) +
1310   - 0.5) +
1311   - minimum,
1312   - (long int)maximum);
  1217 + const double offsetReal = controlsettings.voltage[channel].offsetReal;
  1218 + const double gainStep = specification.gainSteps[controlsettings.voltage[channel].gain];
  1219 + unsigned short levelValue = qBound(
  1220 + minimum, (unsigned short)(((offsetReal + level / gainStep) * (maximum - minimum) + 0.5) + minimum), maximum);
1313 1221  
1314 1222 // Check if the set channel is the trigger source
1315 1223 if (!controlsettings.trigger.special && channel == controlsettings.trigger.source && specification.supportsOffset) {
... ... @@ -1321,17 +1229,16 @@ double HantekDsoControl::setTriggerLevel(unsigned channel, double level) {
1321 1229 /// \todo Get alternating trigger in here
1322 1230  
1323 1231 controlsettings.trigger.level[channel] = level;
1324   - return (double)((levelValue - minimum) / (maximum - minimum) - controlsettings.voltage[channel].offsetReal) *
1325   - specification.gainSteps[controlsettings.voltage[channel].gain];
  1232 + return Dso::ErrorCode::ERROR_NONE;
1326 1233 }
1327 1234  
1328 1235 /// \brief Set the trigger slope.
1329 1236 /// \param slope The Slope that should cause a trigger.
1330 1237 /// \return See ::Dso::ErrorCode.
1331   -int HantekDsoControl::setTriggerSlope(Dso::Slope slope) {
1332   - if (!device->isConnected()) return Dso::ERROR_CONNECTION;
  1238 +Dso::ErrorCode HantekDsoControl::setTriggerSlope(Dso::Slope slope) {
  1239 + if (!device->isConnected()) return Dso::ErrorCode::ERROR_CONNECTION;
1333 1240  
1334   - if (slope >= Dso::SLOPE_COUNT) return Dso::ERROR_PARAMETER;
  1241 + if (slope >= Dso::SLOPE_COUNT) return Dso::ErrorCode::ERROR_PARAMETER;
1335 1242  
1336 1243 switch (specification.command.bulk.setTrigger) {
1337 1244 case BULK_SETTRIGGERANDSAMPLERATE: {
... ... @@ -1353,23 +1260,20 @@ int HantekDsoControl::setTriggerSlope(Dso::Slope slope) {
1353 1260 break;
1354 1261 }
1355 1262 default:
1356   - return Dso::ERROR_UNSUPPORTED;
  1263 + return Dso::ErrorCode::ERROR_UNSUPPORTED;
1357 1264 }
1358 1265  
1359 1266 controlsettings.trigger.slope = slope;
1360   - return Dso::ERROR_NONE;
  1267 + return Dso::ErrorCode::ERROR_NONE;
1361 1268 }
1362 1269  
1363   -int HantekDsoControl::forceTrigger() {
1364   - commandPending[BULK_FORCETRIGGER] = true;
1365   - return 0;
1366   -}
  1270 +void HantekDsoControl::forceTrigger() { commandPending[BULK_FORCETRIGGER] = true; }
1367 1271  
1368 1272 /// \brief Set the trigger position.
1369 1273 /// \param position The new trigger position (in s).
1370 1274 /// \return The trigger position that has been set.
1371   -double HantekDsoControl::setPretriggerPosition(double position) {
1372   - if (!device->isConnected()) return -2;
  1275 +Dso::ErrorCode HantekDsoControl::setPretriggerPosition(double position) {
  1276 + if (!device->isConnected()) return Dso::ErrorCode::ERROR_CONNECTION;
1373 1277  
1374 1278 // All trigger positions are measured in samples
1375 1279 unsigned positionSamples = position * controlsettings.samplerate.current;
... ... @@ -1415,23 +1319,23 @@ double HantekDsoControl::setPretriggerPosition(double position) {
1415 1319 break;
1416 1320 }
1417 1321 default:
1418   - return Dso::ERROR_UNSUPPORTED;
  1322 + return Dso::ErrorCode::ERROR_UNSUPPORTED;
1419 1323 }
1420 1324  
1421 1325 controlsettings.trigger.position = position;
1422   - return (double)positionSamples / controlsettings.samplerate.current;
  1326 + return Dso::ErrorCode::ERROR_NONE;
1423 1327 }
1424 1328  
1425   -int HantekDsoControl::stringCommand(const QString &commandString) {
1426   - if (!device->isConnected()) return Dso::ERROR_CONNECTION;
  1329 +Dso::ErrorCode HantekDsoControl::stringCommand(const QString &commandString) {
  1330 + if (!device->isConnected()) return Dso::ErrorCode::ERROR_CONNECTION;
1427 1331  
1428 1332 QStringList commandParts = commandString.split(' ', QString::SkipEmptyParts);
1429 1333  
1430   - if (commandParts.count() < 1) return Dso::ERROR_PARAMETER;
  1334 + if (commandParts.count() < 1) return Dso::ErrorCode::ERROR_PARAMETER;
1431 1335  
1432   - if (commandParts[0] != "send") return Dso::ERROR_UNSUPPORTED;
  1336 + if (commandParts[0] != "send") return Dso::ErrorCode::ERROR_UNSUPPORTED;
1433 1337  
1434   - if (commandParts.count() < 2) return Dso::ERROR_PARAMETER;
  1338 + if (commandParts.count() < 2) return Dso::ErrorCode::ERROR_PARAMETER;
1435 1339  
1436 1340 if (commandParts[1] == "bulk") {
1437 1341 QString data = commandString.section(' ', 2, -1, QString::SectionSkipEmpty);
... ... @@ -1439,12 +1343,12 @@ int HantekDsoControl::stringCommand(const QString &amp;commandString) {
1439 1343  
1440 1344 // Read command code (First byte)
1441 1345 hexParse(commandParts[2], &commandCode, 1);
1442   - if (commandCode > BULK_COUNT) return Dso::ERROR_UNSUPPORTED;
  1346 + if (commandCode > BULK_COUNT) return Dso::ErrorCode::ERROR_UNSUPPORTED;
1443 1347  
1444 1348 // Update bulk command and mark as pending
1445 1349 hexParse(data, command[commandCode]->data(), command[commandCode]->getSize());
1446 1350 commandPending[commandCode] = true;
1447   - return Dso::ERROR_NONE;
  1351 + return Dso::ErrorCode::ERROR_NONE;
1448 1352 } else if (commandParts[1] == "control") {
1449 1353 unsigned char controlCode = 0;
1450 1354  
... ... @@ -1454,16 +1358,16 @@ int HantekDsoControl::stringCommand(const QString &amp;commandString) {
1454 1358 for (cIndex = 0; cIndex < CONTROLINDEX_COUNT; ++cIndex) {
1455 1359 if (this->controlCode[cIndex] == controlCode) break;
1456 1360 }
1457   - if (cIndex >= CONTROLINDEX_COUNT) return Dso::ERROR_UNSUPPORTED;
  1361 + if (cIndex >= CONTROLINDEX_COUNT) return Dso::ErrorCode::ERROR_UNSUPPORTED;
1458 1362  
1459 1363 QString data = commandString.section(' ', 3, -1, QString::SectionSkipEmpty);
1460 1364  
1461 1365 // Update control command and mark as pending
1462 1366 hexParse(data, this->control[cIndex]->data(), this->control[cIndex]->getSize());
1463 1367 this->controlPending[cIndex] = true;
1464   - return Dso::ERROR_NONE;
  1368 + return Dso::ErrorCode::ERROR_NONE;
1465 1369 } else
1466   - return Dso::ERROR_UNSUPPORTED;
  1370 + return Dso::ErrorCode::ERROR_UNSUPPORTED;
1467 1371 }
1468 1372  
1469 1373 void HantekDsoControl::run() {
... ... @@ -1479,11 +1383,8 @@ void HantekDsoControl::run() {
1479 1383 errorCode = device->bulkCommand(command[cIndex]);
1480 1384 if (errorCode < 0) {
1481 1385 qWarning("Sending bulk command %02x failed: %s", cIndex, libUsbErrorString(errorCode).toLocal8Bit().data());
1482   -
1483   - if (errorCode == LIBUSB_ERROR_NO_DEVICE) {
1484   - emit communicationError();
1485   - return;
1486   - }
  1386 + emit communicationError();
  1387 + return;
1487 1388 } else
1488 1389 commandPending[cIndex] = false;
1489 1390 }
... ... @@ -1570,13 +1471,13 @@ void HantekDsoControl::run() {
1570 1471  
1571 1472 break;
1572 1473  
1573   - case ROLL_GETDATA:
1574   - // Get data and process it, if we're still sampling
1575   - errorCode = this->getSamples(this->_samplingStarted);
1576   - if (errorCode < 0)
1577   - qWarning("Getting sample data failed: %s", libUsbErrorString(errorCode).toLocal8Bit().data());
1578   - else
1579   - timestampDebug(QString("Received %1 B of sampling data").arg(errorCode));
  1474 + case ROLL_GETDATA: {
  1475 + std::vector<unsigned char> rawData = this->getSamples(previousSampleCount);
  1476 + if (this->_samplingStarted) {
  1477 + convertRawDataToSamples(rawData);
  1478 + emit samplesAvailable();
  1479 + }
  1480 + }
1580 1481  
1581 1482 // Check if we're in single trigger mode
1582 1483 if (controlsettings.trigger.mode == Dso::TRIGGERMODE_SINGLE && this->_samplingStarted) this->stopSampling();
... ... @@ -1598,23 +1499,25 @@ void HantekDsoControl::run() {
1598 1499 this->rollState = ROLL_STARTSAMPLING;
1599 1500  
1600 1501 const int lastCaptureState = this->captureState;
1601   - this->captureState = this->getCaptureState();
1602   - if (this->captureState < 0)
1603   - qWarning("Getting capture state failed: %s", libUsbErrorString(this->captureState).toLocal8Bit().data());
1604   -
1605   - else if (this->captureState != lastCaptureState)
  1502 + unsigned triggerPoint;
  1503 + std::tie(captureState, triggerPoint) = this->getCaptureState();
  1504 + controlsettings.trigger.point = calculateTriggerPoint(triggerPoint);
  1505 + if (this->captureState < 0) {
  1506 + qWarning() << tr("Getting capture state failed: %1").arg(libUsbErrorString(this->captureState));
  1507 + emit statusMessage(tr("Getting capture state failed: %1").arg(libUsbErrorString(this->captureState)), 0);
  1508 + } else if (this->captureState != lastCaptureState)
1606 1509 timestampDebug(QString("Capture state changed to %1").arg(this->captureState));
1607 1510  
1608 1511 switch (this->captureState) {
1609 1512 case CAPTURE_READY:
1610 1513 case CAPTURE_READY2250:
1611   - case CAPTURE_READY5200:
1612   - // Get data and process it, if we're still sampling
1613   - errorCode = this->getSamples(this->_samplingStarted);
1614   - if (errorCode < 0)
1615   - qWarning("Getting sample data failed: %s", libUsbErrorString(errorCode).toLocal8Bit().data());
1616   - else
1617   - timestampDebug(QString("Received %1 B of sampling data").arg(errorCode));
  1514 + case CAPTURE_READY5200: {
  1515 + std::vector<unsigned char> rawData = this->getSamples(previousSampleCount);
  1516 + if (this->_samplingStarted) {
  1517 + convertRawDataToSamples(rawData);
  1518 + emit samplesAvailable();
  1519 + }
  1520 + }
1618 1521  
1619 1522 // Check if we're in single trigger mode
1620 1523 if (controlsettings.trigger.mode == Dso::TRIGGERMODE_SINGLE && this->_samplingStarted) this->stopSampling();
... ...
openhantek/src/hantek/hantekdsocontrol.h
... ... @@ -27,10 +27,13 @@ class HantekDsoControl : public QObject {
27 27 * Creates a dsoControl object. The actual event loop / timer is not started.
28 28 * You can optionally create a thread and move the created object to the
29 29 * thread.
30   - * You need to call updateInterval() to start the timer.
31   - * @param device
  30 + * You need to call updateInterval() to start the timer. This is done implicitly
  31 + * if run() is called.
  32 + * @param device The usb device. This object does not take ownership.
32 33 */
33 34 HantekDsoControl(USBDevice *device);
  35 +
  36 + /// \brief Cleans up
34 37 ~HantekDsoControl();
35 38  
36 39 /// Call this to start the processing. This method will call itself
... ... @@ -39,13 +42,29 @@ class HantekDsoControl : public QObject {
39 42 /// there.
40 43 void run();
41 44  
  45 + /// \brief Gets the physical channel count for this oscilloscope.
  46 + /// \return The number of physical channels.
42 47 unsigned getChannelCount();
43   - QList<unsigned> *getAvailableRecordLengths();
  48 +
  49 + /// \brief Get available record lengths for this oscilloscope.
  50 + /// \return The number of physical channels, empty list for continuous.
  51 + const std::vector<unsigned> &getAvailableRecordLengths();
  52 +
  53 + /// \brief Get minimum samplerate for this oscilloscope.
  54 + /// \return The minimum samplerate for the current configuration in S/s.
44 55 double getMinSamplerate();
  56 +
  57 + /// \brief Get maximum samplerate for this oscilloscope.
  58 + /// \return The maximum samplerate for the current configuration in S/s.
45 59 double getMaxSamplerate();
46 60  
  61 + /// \brief Get a list of the names of the special trigger sources.
47 62 const QStringList *getSpecialTriggerSources();
  63 +
  64 + /// Return the associated usb device.
48 65 const USBDevice *getDevice() const;
  66 +
  67 + /// Return the last sample set
49 68 const DSOsamples &getLastSamples();
50 69  
51 70 /// \brief Sends bulk/control commands directly.
... ... @@ -59,63 +78,91 @@ class HantekDsoControl : public QObject {
59 78 /// </p>
60 79 /// \param command The command as string (Has to be parsed).
61 80 /// \return See ::Dso::ErrorCode.
62   - int stringCommand(const QString &commandString);
63   - signals:
64   - void samplingStarted(); ///< The oscilloscope started sampling/waiting for trigger
65   - void samplingStopped(); ///< The oscilloscope stopped sampling/waiting for trigger
66   - void statusMessage(const QString &message, int timeout); ///< Status message about the oscilloscope
67   - void samplesAvailable(); ///< New sample data is available
  81 + Dso::ErrorCode stringCommand(const QString &commandString);
  82 +
  83 + private:
  84 + bool isRollMode() const;
  85 + bool isFastRate() const;
  86 + int getRecordLength() const;
  87 +
  88 + /// \brief Calculated the nearest samplerate supported by the oscilloscope.
  89 + /// \param samplerate The target samplerate, that should be met as good as
  90 + /// possible.
  91 + /// \param fastRate true, if the fast rate mode is enabled.
  92 + /// \param maximum The target samplerate is the maximum allowed when true, the
  93 + /// minimum otherwise.
  94 + /// \param downsampler Pointer to where the selected downsampling factor should
  95 + /// be written.
  96 + /// \return The nearest samplerate supported, 0.0 on error.
  97 + double getBestSamplerate(double samplerate, bool fastRate = false, bool maximum = false,
  98 + unsigned *downsampler = 0) const;
  99 +
  100 + /// Get the number of samples that are expected returned by the scope.
  101 + /// In rolling mode this is depends on the usb speed and packet size.
  102 + /// \return The total number of samples the scope should return.
  103 + unsigned getSampleCount() const;
68 104  
69   - void availableRecordLengthsChanged(const QList<unsigned> &recordLengths); ///< The available record
70   - /// lengths, empty list for
71   - /// continuous
72   - void samplerateLimitsChanged(double minimum, double maximum); ///< The minimum or maximum samplerate has changed
73   - void recordLengthChanged(unsigned long duration); ///< The record length has changed
74   - void recordTimeChanged(double duration); ///< The record time duration has changed
75   - void samplerateChanged(double samplerate); ///< The samplerate has changed
76   - void samplerateSet(int mode, QList<double> sampleSteps); ///< The samplerate has changed
  105 + void updateInterval();
77 106  
78   - void communicationError();
  107 + /// \brief Calculates the trigger point from the CommandGetCaptureState data.
  108 + /// \param value The data value that contains the trigger point.
  109 + /// \return The calculated trigger point for the given data.
  110 + static unsigned calculateTriggerPoint(unsigned value);
79 111  
80   - protected:
81   - bool isRollMode();
82   - int getRecordLength();
83   - void updateInterval();
84   - unsigned calculateTriggerPoint(unsigned value);
85   - int getCaptureState();
86   - int getSamples(bool process);
87   - double getBestSamplerate(double samplerate, bool fastRate = false, bool maximum = false, unsigned *downsampler = 0);
88   - unsigned getSampleCount(bool *fastRate = 0);
  112 + /// \brief Gets the current state.
  113 + /// \return The current CaptureState of the oscilloscope.
  114 + std::pair<int, unsigned> getCaptureState() const;
  115 +
  116 + /// \brief Gets sample data from the oscilloscope
  117 + std::vector<unsigned char> getSamples(unsigned &previousSampleCount) const;
  118 +
  119 + /// \brief Converts raw oscilloscope data to sample data
  120 + void convertRawDataToSamples(const std::vector<unsigned char> &rawData);
  121 +
  122 + /// \brief Sets the size of the sample buffer without updating dependencies.
  123 + /// \param index The record length index that should be set.
  124 + /// \return The record length that has been set, 0 on error.
89 125 unsigned updateRecordLength(unsigned size);
  126 +
  127 + /// \brief Sets the samplerate based on the parameters calculated by
  128 + /// Control::getBestSamplerate.
  129 + /// \param downsampler The downsampling factor.
  130 + /// \param fastRate true, if one channel uses all buffers.
  131 + /// \return The downsampling factor that has been set.
90 132 unsigned updateSamplerate(unsigned downsampler, bool fastRate);
  133 +
  134 + /// \brief Restore the samplerate/timebase targets after divider updates.
91 135 void restoreTargets();
  136 +
  137 + /// \brief Update the minimum and maximum supported samplerate.
92 138 void updateSamplerateLimits();
93 139  
  140 + private:
94 141 // Communication with device
95 142 USBDevice *device; ///< The USB device for the oscilloscope
96 143 bool sampling = false; ///< true, if the oscilloscope is taking samples
97 144  
98   - QStringList specialTriggerSources = {tr("EXT"),tr("EXT/10")}; ///< Names of the special trigger sources
  145 + QStringList specialTriggerSources = {tr("EXT"), tr("EXT/10")}; ///< Names of the special trigger sources
99 146  
100 147 DataArray<unsigned char> *command[Hantek::BULK_COUNT] = {0}; ///< Pointers to bulk
101   - /// commands, ready to
  148 + /// commands, ready to
102 149 /// be transmitted
103   - bool commandPending[Hantek::BULK_COUNT] = {false}; ///< true, when the command should be
104   - /// executed
  150 + bool commandPending[Hantek::BULK_COUNT] = {false}; ///< true, when the command should be
  151 + /// executed
105 152 DataArray<unsigned char> *control[Hantek::CONTROLINDEX_COUNT] = {0}; ///< Pointers to control commands
106   - unsigned char controlCode[Hantek::CONTROLINDEX_COUNT]; ///< Request codes for
107   - /// control commands
108   - bool controlPending[Hantek::CONTROLINDEX_COUNT]= {false}; ///< true, when the control
  153 + unsigned char controlCode[Hantek::CONTROLINDEX_COUNT]; ///< Request codes for
  154 + /// control commands
  155 + bool controlPending[Hantek::CONTROLINDEX_COUNT] = {false}; ///< true, when the control
109 156 /// command should be executed
110 157  
111 158 // Device setup
112 159 Hantek::ControlSpecification specification; ///< The specifications of the device
113   - Hantek::ControlSettings controlsettings; ///< The current settings of the device
  160 + Hantek::ControlSettings controlsettings; ///< The current settings of the device
114 161  
115 162 // Results
116 163 DSOsamples result;
117 164 unsigned previousSampleCount = 0; ///< The expected total number of samples at
118   - /// the last check before sampling started
  165 + /// the last check before sampling started
119 166  
120 167 // State of the communication thread
121 168 int captureState = Hantek::CAPTURE_WAITING;
... ... @@ -130,19 +177,36 @@ class HantekDsoControl : public QObject {
130 177 void startSampling();
131 178 void stopSampling();
132 179  
133   - unsigned setRecordLength(unsigned size);
134   - double setSamplerate(double samplerate = 0.0);
135   - double setRecordTime(double duration = 0.0);
136   -
137   - int setChannelUsed(unsigned channel, bool used);
138   - int setCoupling(unsigned channel, Dso::Coupling coupling);
139   - double setGain(unsigned channel, double gain);
140   - double setOffset(unsigned channel, double offset);
141   -
142   - int setTriggerMode(Dso::TriggerMode mode);
143   - int setTriggerSource(bool special, unsigned id);
144   - double setTriggerLevel(unsigned channel, double level);
145   - int setTriggerSlope(Dso::Slope slope);
146   - double setPretriggerPosition(double position);
147   - int forceTrigger();
  180 + Dso::ErrorCode setRecordLength(unsigned size);
  181 + Dso::ErrorCode setSamplerate(double samplerate = 0.0);
  182 + Dso::ErrorCode setRecordTime(double duration = 0.0);
  183 +
  184 + Dso::ErrorCode setChannelUsed(unsigned channel, bool used);
  185 + Dso::ErrorCode setCoupling(unsigned channel, Dso::Coupling coupling);
  186 + Dso::ErrorCode setGain(unsigned channel, double gain);
  187 + Dso::ErrorCode setOffset(unsigned channel, double offset);
  188 +
  189 + Dso::ErrorCode setTriggerMode(Dso::TriggerMode mode);
  190 + Dso::ErrorCode setTriggerSource(bool special, unsigned id);
  191 + Dso::ErrorCode setTriggerLevel(unsigned channel, double level);
  192 + Dso::ErrorCode setTriggerSlope(Dso::Slope slope);
  193 + Dso::ErrorCode setPretriggerPosition(double position);
  194 + void forceTrigger();
  195 +
  196 + signals:
  197 + void samplingStarted(); ///< The oscilloscope started sampling/waiting for trigger
  198 + void samplingStopped(); ///< The oscilloscope stopped sampling/waiting for trigger
  199 + void statusMessage(const QString &message, int timeout); ///< Status message about the oscilloscope
  200 + void samplesAvailable(); ///< New sample data is available
  201 +
  202 + void availableRecordLengthsChanged(const std::vector<unsigned> &recordLengths); ///< The available record
  203 + /// lengths, empty list for
  204 +
  205 + void samplerateLimitsChanged(double minimum, double maximum); ///< The minimum or maximum samplerate has changed
  206 + void recordLengthChanged(unsigned long duration); ///< The record length has changed
  207 + void recordTimeChanged(double duration); ///< The record time duration has changed
  208 + void samplerateChanged(double samplerate); ///< The samplerate has changed
  209 + void samplerateSet(int mode, QList<double> sampleSteps); ///< The samplerate has changed
  210 +
  211 + void communicationError() const;
148 212 };
... ...
openhantek/src/main.cpp
... ... @@ -93,19 +93,22 @@ int main(int argc, char *argv[]) {
93 93 QString modelName = QString::fromStdString(i->getModel().name);
94 94  
95 95 if (i->needsFirmware()) {
96   - w->addItem(QCoreApplication::translate("Firmware upload dialog", "%1: Firmware upload failed").arg(modelName));
  96 + w->addItem(
  97 + QCoreApplication::translate("Firmware upload dialog", "%1: Firmware upload failed").arg(modelName));
97 98 continue;
98 99 }
99 100 QString errorMessage;
100 101 if (i->connectDevice(errorMessage)) {
101 102 w->addItem(QCoreApplication::translate("Firmware upload dialog", "%1: Ready").arg(modelName));
102   - w->setCurrentRow(w->count()-1);
  103 + w->setCurrentRow(w->count() - 1);
103 104 } else {
104   - w->addItem(QCoreApplication::translate("Firmware upload dialog", "%1: %2").arg(modelName).arg(findDevices.getErrorMessage()));
  105 + w->addItem(QCoreApplication::translate("Firmware upload dialog", "%1: %2")
  106 + .arg(modelName)
  107 + .arg(findDevices.getErrorMessage()));
105 108 }
106 109 }
107 110  
108   - if (w->currentRow() == -1 || devices.size()>1) {
  111 + if (w->currentRow() == -1 || devices.size() > 1) {
109 112 QPushButton *btn = new QPushButton(QCoreApplication::translate("", "Connect to first device"), dialog.get());
110 113 dialog->move(QApplication::desktop()->screen()->rect().center() - w->rect().center());
111 114 dialog->setWindowTitle(QCoreApplication::translate("", "Firmware upload"));
... ...
openhantek/src/mainwindow.cpp
... ... @@ -262,12 +262,12 @@ void OpenHantekMainWindow::addManualCommandEdit() {
262 262 commandEdit->setFocus();
263 263 });
264 264 connect(commandEdit, &QLineEdit::returnPressed, [this]() {
265   - int errorCode = dsoControl->stringCommand(commandEdit->text());
  265 + Dso::ErrorCode errorCode = dsoControl->stringCommand(commandEdit->text());
266 266  
267 267 commandEdit->hide();
268 268 commandEdit->clear();
269 269  
270   - if (errorCode < 0) statusBar()->showMessage(tr("Invalid command"), 3000);
  270 + if (errorCode != Dso::ErrorCode::ERROR_NONE) statusBar()->showMessage(tr("Invalid command"), 3000);
271 271 });
272 272 }
273 273  
... ... @@ -343,10 +343,12 @@ void OpenHantekMainWindow::applySettingsToDevice() {
343 343 samplerateSelected();
344 344 else
345 345 timebaseSelected();
346   - if (dsoControl->getAvailableRecordLengths()->isEmpty())
  346 + if (dsoControl->getAvailableRecordLengths().empty())
347 347 dsoControl->setRecordLength(settings->scope.horizontal.recordLength);
348 348 else {
349   - int index = dsoControl->getAvailableRecordLengths()->indexOf(settings->scope.horizontal.recordLength);
  349 + auto recLenVec = dsoControl->getAvailableRecordLengths();
  350 + ptrdiff_t index = std::distance(
  351 + recLenVec.begin(), std::find(recLenVec.begin(), recLenVec.end(), settings->scope.horizontal.recordLength));
350 352 dsoControl->setRecordLength(index < 0 ? 1 : index);
351 353 }
352 354 dsoControl->setTriggerMode(settings->scope.trigger.mode);
... ...