Commit 42ed8ef794f435f6a7af1c1562937d82c480b733

Authored by oliverhaag
1 parent a2b77fea

DsoControl improvements

openhantek/ChangeLog
... ... @@ -208,3 +208,7 @@
208 208 * Use std::vector instead of QList
209 209 * Experimental Roll-mode support
210 210 * QThread::msleep is too unprecise, causing problems in Roll-mode
  211 +
  212 +2013-04-11 Oliver Haag <oliver.haag@gmail.com>
  213 +* Replaced QThread::msleep by QTimer and handler method
  214 +* Hantek::Control sends signals after connecting the device
... ...
openhantek/src/dsocontrol.cpp
... ... @@ -30,7 +30,6 @@
30 30 /// \brief Initialize variables.
31 31 DsoControl::DsoControl(QObject *parent) : QThread(parent) {
32 32 this->sampling = false;
33   - this->terminate = false;
34 33 }
35 34  
36 35 /// \brief Start sampling process.
... ... @@ -53,11 +52,10 @@ const QStringList *DsoControl::getSpecialTriggerSources() {
53 52 /// \brief Try to connect to the oscilloscope.
54 53 void DsoControl::connectDevice() {
55 54 this->sampling = false;
56   - this->terminate = false;
57 55 this->start();
58 56 }
59 57  
60 58 /// \brief Disconnect the oscilloscope.
61 59 void DsoControl::disconnectDevice() {
62   - this->terminate = true;
  60 + this->quit();
63 61 }
... ...
openhantek/src/dsocontrol.h
... ... @@ -57,7 +57,6 @@ class DsoControl : public QThread {
57 57  
58 58 protected:
59 59 bool sampling; ///< true, if the oscilloscope is taking samples
60   - bool terminate; ///< true, if the thread should be terminated
61 60  
62 61 QStringList specialTriggerSources; ///< Names of the special trigger sources
63 62  
... ... @@ -69,11 +68,11 @@ class DsoControl : public QThread {
69 68 void statusMessage(const QString &message, int timeout); ///< Status message about the oscilloscope
70 69 void samplesAvailable(const std::vector<std::vector<double> > *data, double samplerate, bool append, QMutex *mutex); ///< New sample data is available
71 70  
  71 + void availableRecordLengthsChanged(const QList<unsigned int> &recordLengths); ///< The available record lengths, empty list for continuous
  72 + void samplerateLimitsChanged(double minimum, double maximum); ///< The minimum or maximum samplerate has changed
72 73 void recordLengthChanged(unsigned long duration); ///< The record length has changed
73 74 void recordTimeChanged(double duration); ///< The record time duration has changed
74 75 void samplerateChanged(double samplerate); ///< The samplerate has changed
75   - void availableRecordLengthsChanged(const QList<unsigned int> &recordLengths); ///< The available record lengths, empty list for continuous
76   - void samplerateLimitsChanged(double minimum, double maximum); ///< The minimum or maximum samplerate has changed
77 76  
78 77 public slots:
79 78 virtual void connectDevice();
... ...
openhantek/src/hantek/control.cpp
... ... @@ -29,7 +29,7 @@
29 29  
30 30 #include <QList>
31 31 #include <QMutex>
32   -#include <QTime>
  32 +#include <QTimer>
33 33  
34 34  
35 35 #include "hantek/control.h"
... ... @@ -86,7 +86,7 @@ namespace Hantek {
86 86 this->settings.voltage[channel].offsetReal = 0.0;
87 87 this->settings.voltage[channel].used = false;
88 88 }
89   - this->settings.recordLengthId = 0;
  89 + this->settings.recordLengthId = 1;
90 90 this->settings.usedChannels = 0;
91 91  
92 92 // Special trigger sources
... ... @@ -110,6 +110,15 @@ namespace Hantek {
110 110 // USB device
111 111 this->device = new Device(this);
112 112  
  113 + // Thread execution timer
  114 + this->timer = 0;
  115 +
  116 + // State of the device
  117 + this->captureState = CAPTURE_WAITING;
  118 + this->rollState = 0;
  119 + this->samplingStarted = false;
  120 + this->lastTriggerMode = (Dso::TriggerMode) -1;
  121 +
113 122 // Sample buffers
114 123 this->samples.resize(HANTEK_CHANNELS);
115 124  
... ... @@ -156,262 +165,53 @@ namespace Hantek {
156 165  
157 166 /// \brief Handles all USB things until the device gets disconnected.
158 167 void Control::run() {
159   - int errorCode, cycleCounter = 0, startCycle = 0;
  168 + // Initialize communication thread state
  169 + this->captureState = CAPTURE_WAITING;
  170 + this->rollState = 0;
  171 + this->samplingStarted = false;
  172 + this->lastTriggerMode = (Dso::TriggerMode) -1;
  173 +
  174 + this->cycleCounter = 0;
  175 + this->startCycle = 0;
  176 +
  177 + // Thread execution timer
  178 + this->timer = new QTimer(this);
  179 + connect(this->timer, SIGNAL(timeout()), this, SLOT(handler()), Qt::DirectConnection);
  180 +
  181 + this->updateInterval();
  182 + this->timer->start();
160 183  
161 184 // The control loop is running until the device is disconnected
162   - int captureState = CAPTURE_WAITING;
163   - int rollState = 0;
164   - bool samplingStarted = false;
165   - Dso::TriggerMode lastTriggerMode = (Dso::TriggerMode) -1;
166   -
167   - while(captureState != LIBUSB_ERROR_NO_DEVICE && !this->terminate) {
168   - // Send all pending bulk commands
169   - for(int command = 0; command < BULK_COUNT; ++command) {
170   - if(!this->commandPending[command])
171   - continue;
172   -
173   -#ifdef DEBUG
174   - Helper::timestampDebug(QString("Sending bulk command:%1").arg(Helper::hexDump(this->command[command]->data(), this->command[command]->getSize())));
175   -#endif
176   -
177   - errorCode = this->device->bulkCommand(this->command[command]);
178   - if(errorCode < 0) {
179   - qWarning("Sending bulk command %02x failed: %s", command, Helper::libUsbErrorString(errorCode).toLocal8Bit().data());
180   -
181   - if(errorCode == LIBUSB_ERROR_NO_DEVICE) {
182   - captureState = LIBUSB_ERROR_NO_DEVICE;
183   - break;
184   - }
185   - }
186   - else
187   - this->commandPending[command] = false;
188   - }
189   - if(captureState == LIBUSB_ERROR_NO_DEVICE)
190   - break;
191   -
192   - // Send all pending control commands
193   - for(int control = 0; control < CONTROLINDEX_COUNT; ++control) {
194   - if(!this->controlPending[control])
195   - continue;
196   -
197   -#ifdef DEBUG
198   - Helper::timestampDebug(QString("Sending control command %1:%2").arg(QString::number(this->controlCode[control], 16), Helper::hexDump(this->control[control]->data(), this->control[control]->getSize())));
199   -#endif
200   -
201   - errorCode = this->device->controlWrite(this->controlCode[control], this->control[control]->data(), this->control[control]->getSize());
202   - if(errorCode < 0) {
203   - qWarning("Sending control command %2x failed: %s", this->controlCode[control], Helper::libUsbErrorString(errorCode).toLocal8Bit().data());
204   -
205   - if(errorCode == LIBUSB_ERROR_NO_DEVICE) {
206   - captureState = LIBUSB_ERROR_NO_DEVICE;
207   - break;
208   - }
209   - }
210   - else
211   - this->controlPending[control] = false;
212   - }
213   - if(captureState == LIBUSB_ERROR_NO_DEVICE)
214   - break;
215   -
216   - // Check the current oscilloscope state everytime 25% of the time the buffer should be refilled
217   - // Not more often than every 10 ms though
218   - int cycleTime;
219   - if(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] == UINT_MAX)
220   - cycleTime = qMax((int) ((double) this->device->getPacketSize() / ((this->settings.samplerate.limits == &this->specification.samplerate.multi) ? 1 : HANTEK_CHANNELS) / this->settings.samplerate.current * 250), 1);
221   - else
222   - cycleTime = qMax((int) ((double) this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] / this->settings.samplerate.current * 250), 10);
223   - this->msleep(cycleTime);
224   -
225   - if(!this->sampling) {
226   - samplingStarted = false;
227   - continue;
228   - }
229   -
230   - if(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] == UINT_MAX) {
231   - // Roll mode
232   - captureState = CAPTURE_WAITING;
233   -
234   - switch(rollState) {
235   - case ROLL_STARTSAMPLING:
236   - // Don't iterate through roll mode steps when stopped
237   - if(!this->sampling)
238   - continue;
239   -
240   - // Sampling hasn't started, update the expected sample count
241   - this->previousSampleCount = this->getSampleCount();
242   -
243   - errorCode = this->device->bulkCommand(this->command[BULK_STARTSAMPLING]);
244   - if(errorCode < 0) {
245   - if(errorCode == LIBUSB_ERROR_NO_DEVICE)
246   - captureState = LIBUSB_ERROR_NO_DEVICE;
247   - break;
248   - }
249   -#ifdef DEBUG
250   - Helper::timestampDebug("Starting to capture");
251   -#endif
252   -
253   - samplingStarted = true;
254   -
255   - break;
256   -
257   - case ROLL_ENABLETRIGGER:
258   - errorCode = this->device->bulkCommand(this->command[BULK_ENABLETRIGGER]);
259   - if(errorCode < 0) {
260   - if(errorCode == LIBUSB_ERROR_NO_DEVICE)
261   - captureState = LIBUSB_ERROR_NO_DEVICE;
262   - break;
263   - }
264   -#ifdef DEBUG
265   - Helper::timestampDebug("Enabling trigger");
266   -#endif
267   -
268   - break;
269   -
270   - case ROLL_FORCETRIGGER:
271   - errorCode = this->device->bulkCommand(this->command[BULK_FORCETRIGGER]);
272   - if(errorCode < 0) {
273   - if(errorCode == LIBUSB_ERROR_NO_DEVICE)
274   - captureState = LIBUSB_ERROR_NO_DEVICE;
275   - break;
276   - }
277   -#ifdef DEBUG
278   - Helper::timestampDebug("Forcing trigger");
279   -#endif
280   -
281   - break;
282   -
283   - case ROLL_GETDATA:
284   - // Get data and process it, if we're still sampling
285   - errorCode = this->getSamples(samplingStarted);
286   - if(errorCode < 0)
287   - qWarning("Getting sample data failed: %s", Helper::libUsbErrorString(errorCode).toLocal8Bit().data());
288   - #ifdef DEBUG
289   - else
290   - Helper::timestampDebug(QString("Received %1 B of sampling data").arg(errorCode));
291   - #endif
292   -
293   - // Check if we're in single trigger mode
294   - if(this->settings.trigger.mode == Dso::TRIGGERMODE_SINGLE && samplingStarted)
295   - this->stopSampling();
296   -
297   - // Sampling completed, restart it when necessary
298   - samplingStarted = false;
299   -
300   - break;
301   -
302   - default:
303   -#ifdef DEBUG
304   - Helper::timestampDebug("Roll mode state unknown");
305   -#endif
306   - break;
307   - }
308   -
309   - // Go to next state, or restart if last state was reached
310   - rollState = (rollState + 1) % ROLL_COUNT;
311   - }
312   - else {
313   - // Standard mode
314   - rollState = ROLL_STARTSAMPLING;
315   -
316   -#ifdef DEBUG
317   - int lastCaptureState = captureState;
318   -#endif
319   - captureState = this->getCaptureState();
320   - if(captureState < 0)
321   - qWarning("Getting capture state failed: %s", Helper::libUsbErrorString(captureState).toLocal8Bit().data());
322   -#ifdef DEBUG
323   - else if(captureState != lastCaptureState)
324   - Helper::timestampDebug(QString("Capture state changed to %1").arg(captureState));
325   -#endif
326   - switch(captureState) {
327   - case CAPTURE_READY:
328   - case CAPTURE_READY2250:
329   - case CAPTURE_READY5200:
330   - // Get data and process it, if we're still sampling
331   - errorCode = this->getSamples(samplingStarted);
332   - if(errorCode < 0)
333   - qWarning("Getting sample data failed: %s", Helper::libUsbErrorString(errorCode).toLocal8Bit().data());
334   -#ifdef DEBUG
335   - else
336   - Helper::timestampDebug(QString("Received %1 B of sampling data").arg(errorCode));
337   -#endif
338   -
339   - // Check if we're in single trigger mode
340   - if(this->settings.trigger.mode == Dso::TRIGGERMODE_SINGLE && samplingStarted)
341   - this->stopSampling();
342   -
343   - // Sampling completed, restart it when necessary
344   - samplingStarted = false;
345   -
346   - // Start next capture if necessary by leaving out the break statement
347   - if(!this->sampling)
348   - break;
349   -
350   - case CAPTURE_WAITING:
351   - // Sampling hasn't started, update the expected sample count
352   - this->previousSampleCount = this->getSampleCount();
353   -
354   - if(samplingStarted && lastTriggerMode == this->settings.trigger.mode) {
355   - ++cycleCounter;
356   -
357   - if(cycleCounter == startCycle && this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] != UINT_MAX) {
358   - // Buffer refilled completely since start of sampling, enable the trigger now
359   - errorCode = this->device->bulkCommand(this->command[BULK_ENABLETRIGGER]);
360   - if(errorCode < 0) {
361   - if(errorCode == LIBUSB_ERROR_NO_DEVICE)
362   - captureState = LIBUSB_ERROR_NO_DEVICE;
363   - break;
364   - }
365   -#ifdef DEBUG
366   - Helper::timestampDebug("Enabling trigger");
367   -#endif
368   - }
369   - else if(cycleCounter >= 8 + startCycle && this->settings.trigger.mode == Dso::TRIGGERMODE_AUTO) {
370   - // Force triggering
371   - errorCode = this->device->bulkCommand(this->command[BULK_FORCETRIGGER]);
372   - if(errorCode < 0) {
373   - if(errorCode == LIBUSB_ERROR_NO_DEVICE)
374   - captureState = LIBUSB_ERROR_NO_DEVICE;
375   - break;
376   - }
377   -#ifdef DEBUG
378   - Helper::timestampDebug("Forcing trigger");
379   -#endif
380   - }
381   -
382   - if(cycleCounter < 20 || cycleCounter < 4000 / cycleTime)
383   - break;
384   - }
385   -
386   - // Start capturing
387   - errorCode = this->device->bulkCommand(this->command[BULK_STARTSAMPLING]);
388   - if(errorCode < 0) {
389   - if(errorCode == LIBUSB_ERROR_NO_DEVICE)
390   - captureState = LIBUSB_ERROR_NO_DEVICE;
391   - break;
392   - }
393   -#ifdef DEBUG
394   - Helper::timestampDebug("Starting to capture");
395   -#endif
396   -
397   - samplingStarted = true;
398   - cycleCounter = 0;
399   - startCycle = this->settings.trigger.position * 1000 / cycleTime + 1;
400   - lastTriggerMode = this->settings.trigger.mode;
401   - break;
402   -
403   - case CAPTURE_SAMPLING:
404   - break;
405   - default:
406   - break;
407   - }
408   - }
409   - }
  185 + exec();
410 186  
  187 + this->timer->stop();
411 188 this->device->disconnect();
  189 +
  190 + delete this->timer;
  191 + this->timer = 0;
  192 +
412 193 emit statusMessage(tr("The device has been disconnected"), 0);
413 194 }
414 195  
  196 + /// \brief Updates the interval of the periodic thread timer.
  197 + void Control::updateInterval() {
  198 + if(!this->timer)
  199 + return;
  200 +
  201 + int cycleTime;
  202 +
  203 + // Check the current oscilloscope state everytime 25% of the time the buffer should be refilled
  204 + if(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] == UINT_MAX)
  205 + cycleTime = (int) ((double) this->device->getPacketSize() / ((this->settings.samplerate.limits == &this->specification.samplerate.multi) ? 1 : HANTEK_CHANNELS) / this->settings.samplerate.current * 250);
  206 + else
  207 + cycleTime = (int) ((double) this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] / this->settings.samplerate.current * 250);
  208 +
  209 + // Not more often than every 10 ms though but at least once every second
  210 + cycleTime = qBound(10, cycleTime, 1000);
  211 +
  212 + this->timer->setInterval(cycleTime);
  213 + }
  214 +
415 215 /// \brief Calculates the trigger point from the CommandGetCaptureState data.
416 216 /// \param value The data value that contains the trigger point.
417 217 /// \return The calculated trigger point for the given data.
... ... @@ -753,15 +553,17 @@ namespace Hantek {
753 553 }
754 554  
755 555 // Check if the divider has changed and adapt samplerate limits accordingly
756   - if(this->specification.bufferDividers[index] != this->specification.bufferDividers[this->settings.recordLengthId]) {
  556 + bool bDividerChanged = this->specification.bufferDividers[index] != this->specification.bufferDividers[this->settings.recordLengthId];
  557 +
  558 + this->settings.recordLengthId = index;
  559 +
  560 + if(bDividerChanged) {
757 561 this->updateSamplerateLimits();
758 562  
759 563 // Samplerate dividers changed, recalculate it
760 564 this->restoreTargets();
761 565 }
762 566  
763   - this->settings.recordLengthId = index;
764   -
765 567 return this->settings.samplerate.limits->recordLengths[index];
766 568 }
767 569  
... ... @@ -1098,9 +900,6 @@ namespace Hantek {
1098 900 this->specification.sampleSize = 8;
1099 901 break;
1100 902 }
1101   - this->settings.recordLengthId = 1;
1102   - this->settings.samplerate.limits = &(this->specification.samplerate.single);
1103   - this->settings.samplerate.downsampler = 1;
1104 903 this->previousSampleCount = 0;
1105 904  
1106 905 // Get channel level data
... ... @@ -1111,6 +910,14 @@ namespace Hantek {
1111 910 return;
1112 911 }
1113 912  
  913 + // Emit signals for initial settings
  914 + emit availableRecordLengthsChanged(this->settings.samplerate.limits->recordLengths);
  915 + updateSamplerateLimits();
  916 + emit recordLengthChanged(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId]);
  917 + if(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] != UINT_MAX)
  918 + emit recordTimeChanged((double) this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] / this->settings.samplerate.current);
  919 + emit samplerateChanged(this->settings.samplerate.current);
  920 +
1114 921 DsoControl::connectDevice();
1115 922 }
1116 923  
... ... @@ -1620,4 +1427,252 @@ namespace Hantek {
1620 1427 return Dso::ERROR_UNSUPPORTED;
1621 1428 }
1622 1429 #endif
  1430 +
  1431 + /// \brief Called periodically in the control thread by a timer.
  1432 + void Control::handler() {
  1433 + int errorCode = 0;
  1434 +
  1435 + // Send all pending bulk commands
  1436 + for(int command = 0; command < BULK_COUNT; ++command) {
  1437 + if(!this->commandPending[command])
  1438 + continue;
  1439 +
  1440 +#ifdef DEBUG
  1441 + Helper::timestampDebug(QString("Sending bulk command:%1").arg(Helper::hexDump(this->command[command]->data(), this->command[command]->getSize())));
  1442 +#endif
  1443 +
  1444 + errorCode = this->device->bulkCommand(this->command[command]);
  1445 + if(errorCode < 0) {
  1446 + qWarning("Sending bulk command %02x failed: %s", command, Helper::libUsbErrorString(errorCode).toLocal8Bit().data());
  1447 +
  1448 + if(errorCode == LIBUSB_ERROR_NO_DEVICE) {
  1449 + this->quit();
  1450 + return;
  1451 + }
  1452 + }
  1453 + else
  1454 + this->commandPending[command] = false;
  1455 + }
  1456 +
  1457 + // Send all pending control commands
  1458 + for(int control = 0; control < CONTROLINDEX_COUNT; ++control) {
  1459 + if(!this->controlPending[control])
  1460 + continue;
  1461 +
  1462 +#ifdef DEBUG
  1463 + Helper::timestampDebug(QString("Sending control command %1:%2").arg(QString::number(this->controlCode[control], 16), Helper::hexDump(this->control[control]->data(), this->control[control]->getSize())));
  1464 +#endif
  1465 +
  1466 + errorCode = this->device->controlWrite(this->controlCode[control], this->control[control]->data(), this->control[control]->getSize());
  1467 + if(errorCode < 0) {
  1468 + qWarning("Sending control command %2x failed: %s", this->controlCode[control], Helper::libUsbErrorString(errorCode).toLocal8Bit().data());
  1469 +
  1470 + if(errorCode == LIBUSB_ERROR_NO_DEVICE) {
  1471 + this->quit();
  1472 + return;
  1473 + }
  1474 + }
  1475 + else
  1476 + this->controlPending[control] = false;
  1477 + }
  1478 +
  1479 + // State machine for the device communication
  1480 + if(this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] == UINT_MAX) {
  1481 + // Roll mode
  1482 + this->captureState = CAPTURE_WAITING;
  1483 + bool toNextState = true;
  1484 +
  1485 + switch(this->rollState) {
  1486 + case ROLL_STARTSAMPLING:
  1487 + // Don't iterate through roll mode steps when stopped
  1488 + if(!this->sampling) {
  1489 + toNextState = false;
  1490 + break;
  1491 + }
  1492 +
  1493 + // Sampling hasn't started, update the expected sample count
  1494 + this->previousSampleCount = this->getSampleCount();
  1495 +
  1496 + errorCode = this->device->bulkCommand(this->command[BULK_STARTSAMPLING]);
  1497 + if(errorCode < 0) {
  1498 + if(errorCode == LIBUSB_ERROR_NO_DEVICE) {
  1499 + this->quit();
  1500 + return;
  1501 + }
  1502 + break;
  1503 + }
  1504 +#ifdef DEBUG
  1505 + Helper::timestampDebug("Starting to capture");
  1506 +#endif
  1507 +
  1508 + this->samplingStarted = true;
  1509 +
  1510 + break;
  1511 +
  1512 + case ROLL_ENABLETRIGGER:
  1513 + errorCode = this->device->bulkCommand(this->command[BULK_ENABLETRIGGER]);
  1514 + if(errorCode < 0) {
  1515 + if(errorCode == LIBUSB_ERROR_NO_DEVICE) {
  1516 + this->quit();
  1517 + return;
  1518 + }
  1519 + break;
  1520 + }
  1521 +#ifdef DEBUG
  1522 + Helper::timestampDebug("Enabling trigger");
  1523 +#endif
  1524 +
  1525 + break;
  1526 +
  1527 + case ROLL_FORCETRIGGER:
  1528 + errorCode = this->device->bulkCommand(this->command[BULK_FORCETRIGGER]);
  1529 + if(errorCode < 0) {
  1530 + if(errorCode == LIBUSB_ERROR_NO_DEVICE) {
  1531 + this->quit();
  1532 + return;
  1533 + }
  1534 + break;
  1535 + }
  1536 +#ifdef DEBUG
  1537 + Helper::timestampDebug("Forcing trigger");
  1538 +#endif
  1539 +
  1540 + break;
  1541 +
  1542 + case ROLL_GETDATA:
  1543 + // Get data and process it, if we're still sampling
  1544 + errorCode = this->getSamples(this->samplingStarted);
  1545 + if(errorCode < 0)
  1546 + qWarning("Getting sample data failed: %s", Helper::libUsbErrorString(errorCode).toLocal8Bit().data());
  1547 +#ifdef DEBUG
  1548 + else
  1549 + Helper::timestampDebug(QString("Received %1 B of sampling data").arg(errorCode));
  1550 +#endif
  1551 +
  1552 + // Check if we're in single trigger mode
  1553 + if(this->settings.trigger.mode == Dso::TRIGGERMODE_SINGLE && this->samplingStarted)
  1554 + this->stopSampling();
  1555 +
  1556 + // Sampling completed, restart it when necessary
  1557 + this->samplingStarted = false;
  1558 +
  1559 + break;
  1560 +
  1561 + default:
  1562 +#ifdef DEBUG
  1563 + Helper::timestampDebug("Roll mode state unknown");
  1564 +#endif
  1565 + break;
  1566 + }
  1567 +
  1568 + // Go to next state, or restart if last state was reached
  1569 + if(toNextState)
  1570 + this->rollState = (this->rollState + 1) % ROLL_COUNT;
  1571 + }
  1572 + else {
  1573 + // Standard mode
  1574 + this->rollState = ROLL_STARTSAMPLING;
  1575 +
  1576 +#ifdef DEBUG
  1577 + int lastCaptureState = this->captureState;
  1578 +#endif
  1579 + this->captureState = this->getCaptureState();
  1580 + if(this->captureState < 0)
  1581 + qWarning("Getting capture state failed: %s", Helper::libUsbErrorString(this->captureState).toLocal8Bit().data());
  1582 +#ifdef DEBUG
  1583 + else if(this->captureState != lastCaptureState)
  1584 + Helper::timestampDebug(QString("Capture state changed to %1").arg(this->captureState));
  1585 +#endif
  1586 + switch(this->captureState) {
  1587 + case CAPTURE_READY:
  1588 + case CAPTURE_READY2250:
  1589 + case CAPTURE_READY5200:
  1590 + // Get data and process it, if we're still sampling
  1591 + errorCode = this->getSamples(this->samplingStarted);
  1592 + if(errorCode < 0)
  1593 + qWarning("Getting sample data failed: %s", Helper::libUsbErrorString(errorCode).toLocal8Bit().data());
  1594 +#ifdef DEBUG
  1595 + else
  1596 + Helper::timestampDebug(QString("Received %1 B of sampling data").arg(errorCode));
  1597 +#endif
  1598 +
  1599 + // Check if we're in single trigger mode
  1600 + if(this->settings.trigger.mode == Dso::TRIGGERMODE_SINGLE && this->samplingStarted)
  1601 + this->stopSampling();
  1602 +
  1603 + // Sampling completed, restart it when necessary
  1604 + this->samplingStarted = false;
  1605 +
  1606 + // Start next capture if necessary by leaving out the break statement
  1607 + if(!this->sampling)
  1608 + break;
  1609 +
  1610 + case CAPTURE_WAITING:
  1611 + // Sampling hasn't started, update the expected sample count
  1612 + this->previousSampleCount = this->getSampleCount();
  1613 +
  1614 + if(this->samplingStarted && this->lastTriggerMode == this->settings.trigger.mode) {
  1615 + ++this->cycleCounter;
  1616 +
  1617 + if(this->cycleCounter == this->startCycle && this->settings.samplerate.limits->recordLengths[this->settings.recordLengthId] != UINT_MAX) {
  1618 + // Buffer refilled completely since start of sampling, enable the trigger now
  1619 + errorCode = this->device->bulkCommand(this->command[BULK_ENABLETRIGGER]);
  1620 + if(errorCode < 0) {
  1621 + if(errorCode == LIBUSB_ERROR_NO_DEVICE) {
  1622 + this->quit();
  1623 + return;
  1624 + }
  1625 + break;
  1626 + }
  1627 +#ifdef DEBUG
  1628 + Helper::timestampDebug("Enabling trigger");
  1629 +#endif
  1630 + }
  1631 + else if(this->cycleCounter >= 8 + this->startCycle && this->settings.trigger.mode == Dso::TRIGGERMODE_AUTO) {
  1632 + // Force triggering
  1633 + errorCode = this->device->bulkCommand(this->command[BULK_FORCETRIGGER]);
  1634 + if(errorCode < 0) {
  1635 + if(errorCode == LIBUSB_ERROR_NO_DEVICE) {
  1636 + this->quit();
  1637 + return;
  1638 + }
  1639 + break;
  1640 + }
  1641 +#ifdef DEBUG
  1642 + Helper::timestampDebug("Forcing trigger");
  1643 +#endif
  1644 + }
  1645 +
  1646 + if(this->cycleCounter < 20 || this->cycleCounter < 4000 / this->timer->interval())
  1647 + break;
  1648 + }
  1649 +
  1650 + // Start capturing
  1651 + errorCode = this->device->bulkCommand(this->command[BULK_STARTSAMPLING]);
  1652 + if(errorCode < 0) {
  1653 + if(errorCode == LIBUSB_ERROR_NO_DEVICE) {
  1654 + this->quit();
  1655 + return;
  1656 + }
  1657 + break;
  1658 + }
  1659 +#ifdef DEBUG
  1660 + Helper::timestampDebug("Starting to capture");
  1661 +#endif
  1662 +
  1663 + this->samplingStarted = true;
  1664 + this->cycleCounter = 0;
  1665 + this->startCycle = this->settings.trigger.position * 1000 / this->timer->interval() + 1;
  1666 + this->lastTriggerMode = this->settings.trigger.mode;
  1667 + break;
  1668 +
  1669 + case CAPTURE_SAMPLING:
  1670 + break;
  1671 + default:
  1672 + break;
  1673 + }
  1674 + }
  1675 +
  1676 + this->updateInterval();
  1677 + }
1623 1678 }
... ...
openhantek/src/hantek/control.h
... ... @@ -37,6 +37,9 @@
37 37 #include "hantek/types.h"
38 38  
39 39  
  40 +class QTimer;
  41 +
  42 +
40 43 namespace Hantek {
41 44 class Device;
42 45  
... ... @@ -210,6 +213,7 @@ namespace Hantek {
210 213  
211 214 protected:
212 215 void run();
  216 + void updateInterval();
213 217  
214 218 unsigned int calculateTriggerPoint(unsigned int value);
215 219 int getCaptureState();
... ... @@ -223,6 +227,7 @@ namespace Hantek {
223 227  
224 228 // Communication with device
225 229 Device *device; ///< The USB device for the oscilloscope
  230 + QTimer *timer; ///< Timer for periodic communication thread
226 231  
227 232 Helper::DataArray<unsigned char> *command[BULK_COUNT]; ///< Pointers to bulk commands, ready to be transmitted
228 233 bool commandPending[BULK_COUNT]; ///< true, when the command should be executed
... ... @@ -238,6 +243,14 @@ namespace Hantek {
238 243 std::vector<std::vector<double> > samples; ///< Sample data vectors sent to the data analyzer
239 244 unsigned int previousSampleCount; ///< The expected total number of samples at the last check before sampling started
240 245 QMutex samplesMutex; ///< Mutex for the sample data
  246 +
  247 + // State of the communication thread
  248 + int captureState;
  249 + int rollState;
  250 + bool samplingStarted;
  251 + Dso::TriggerMode lastTriggerMode;
  252 + int cycleCounter;
  253 + int startCycle;
241 254  
242 255 public slots:
243 256 virtual void connectDevice();
... ... @@ -260,6 +273,9 @@ namespace Hantek {
260 273 #ifdef DEBUG
261 274 int stringCommand(QString command);
262 275 #endif
  276 +
  277 + protected slots:
  278 + void handler();
263 279 };
264 280 }
265 281  
... ...
openhantek/src/openhantek.cpp
... ... @@ -342,10 +342,6 @@ void OpenHantekMainWindow::initializeDevice() {
342 342 this->dsoControl->setPretriggerPosition(this->settings->scope.trigger.position * this->settings->scope.horizontal.timebase * DIVS_TIME);
343 343 this->dsoControl->setTriggerSlope(this->settings->scope.trigger.slope);
344 344 this->dsoControl->setTriggerSource(this->settings->scope.trigger.special, this->settings->scope.trigger.source);
345   -
346   - // Apply the limits to the dock widgets
347   - this->horizontalDock->availableRecordLengthsChanged(*this->dsoControl->getAvailableRecordLengths());
348   - this->horizontalDock->samplerateLimitsChanged(this->dsoControl->getMinSamplerate(), this->dsoControl->getMaxSamplerate());
349 345 }
350 346  
351 347 /// \brief Read the settings from an ini file.
... ...