Commit 42ed8ef794f435f6a7af1c1562937d82c480b733

Authored by oliverhaag
1 parent a2b77fea

DsoControl improvements

openhantek/ChangeLog
@@ -208,3 +208,7 @@ @@ -208,3 +208,7 @@
208 * Use std::vector instead of QList 208 * Use std::vector instead of QList
209 * Experimental Roll-mode support 209 * Experimental Roll-mode support
210 * QThread::msleep is too unprecise, causing problems in Roll-mode 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,7 +30,6 @@
30 /// \brief Initialize variables. 30 /// \brief Initialize variables.
31 DsoControl::DsoControl(QObject *parent) : QThread(parent) { 31 DsoControl::DsoControl(QObject *parent) : QThread(parent) {
32 this->sampling = false; 32 this->sampling = false;
33 - this->terminate = false;  
34 } 33 }
35 34
36 /// \brief Start sampling process. 35 /// \brief Start sampling process.
@@ -53,11 +52,10 @@ const QStringList *DsoControl::getSpecialTriggerSources() { @@ -53,11 +52,10 @@ const QStringList *DsoControl::getSpecialTriggerSources() {
53 /// \brief Try to connect to the oscilloscope. 52 /// \brief Try to connect to the oscilloscope.
54 void DsoControl::connectDevice() { 53 void DsoControl::connectDevice() {
55 this->sampling = false; 54 this->sampling = false;
56 - this->terminate = false;  
57 this->start(); 55 this->start();
58 } 56 }
59 57
60 /// \brief Disconnect the oscilloscope. 58 /// \brief Disconnect the oscilloscope.
61 void DsoControl::disconnectDevice() { 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,7 +57,6 @@ class DsoControl : public QThread {
57 57
58 protected: 58 protected:
59 bool sampling; ///< true, if the oscilloscope is taking samples 59 bool sampling; ///< true, if the oscilloscope is taking samples
60 - bool terminate; ///< true, if the thread should be terminated  
61 60
62 QStringList specialTriggerSources; ///< Names of the special trigger sources 61 QStringList specialTriggerSources; ///< Names of the special trigger sources
63 62
@@ -69,11 +68,11 @@ class DsoControl : public QThread { @@ -69,11 +68,11 @@ class DsoControl : public QThread {
69 void statusMessage(const QString &message, int timeout); ///< Status message about the oscilloscope 68 void statusMessage(const QString &message, int timeout); ///< Status message about the oscilloscope
70 void samplesAvailable(const std::vector<std::vector<double> > *data, double samplerate, bool append, QMutex *mutex); ///< New sample data is available 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 void recordLengthChanged(unsigned long duration); ///< The record length has changed 73 void recordLengthChanged(unsigned long duration); ///< The record length has changed
73 void recordTimeChanged(double duration); ///< The record time duration has changed 74 void recordTimeChanged(double duration); ///< The record time duration has changed
74 void samplerateChanged(double samplerate); ///< The samplerate has changed 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 public slots: 77 public slots:
79 virtual void connectDevice(); 78 virtual void connectDevice();
openhantek/src/hantek/control.cpp
@@ -29,7 +29,7 @@ @@ -29,7 +29,7 @@
29 29
30 #include <QList> 30 #include <QList>
31 #include <QMutex> 31 #include <QMutex>
32 -#include <QTime> 32 +#include <QTimer>
33 33
34 34
35 #include "hantek/control.h" 35 #include "hantek/control.h"
@@ -86,7 +86,7 @@ namespace Hantek { @@ -86,7 +86,7 @@ namespace Hantek {
86 this->settings.voltage[channel].offsetReal = 0.0; 86 this->settings.voltage[channel].offsetReal = 0.0;
87 this->settings.voltage[channel].used = false; 87 this->settings.voltage[channel].used = false;
88 } 88 }
89 - this->settings.recordLengthId = 0; 89 + this->settings.recordLengthId = 1;
90 this->settings.usedChannels = 0; 90 this->settings.usedChannels = 0;
91 91
92 // Special trigger sources 92 // Special trigger sources
@@ -110,6 +110,15 @@ namespace Hantek { @@ -110,6 +110,15 @@ namespace Hantek {
110 // USB device 110 // USB device
111 this->device = new Device(this); 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 // Sample buffers 122 // Sample buffers
114 this->samples.resize(HANTEK_CHANNELS); 123 this->samples.resize(HANTEK_CHANNELS);
115 124
@@ -156,262 +165,53 @@ namespace Hantek { @@ -156,262 +165,53 @@ namespace Hantek {
156 165
157 /// \brief Handles all USB things until the device gets disconnected. 166 /// \brief Handles all USB things until the device gets disconnected.
158 void Control::run() { 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 // The control loop is running until the device is disconnected 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 this->device->disconnect(); 188 this->device->disconnect();
  189 +
  190 + delete this->timer;
  191 + this->timer = 0;
  192 +
412 emit statusMessage(tr("The device has been disconnected"), 0); 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 /// \brief Calculates the trigger point from the CommandGetCaptureState data. 215 /// \brief Calculates the trigger point from the CommandGetCaptureState data.
416 /// \param value The data value that contains the trigger point. 216 /// \param value The data value that contains the trigger point.
417 /// \return The calculated trigger point for the given data. 217 /// \return The calculated trigger point for the given data.
@@ -753,15 +553,17 @@ namespace Hantek { @@ -753,15 +553,17 @@ namespace Hantek {
753 } 553 }
754 554
755 // Check if the divider has changed and adapt samplerate limits accordingly 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 this->updateSamplerateLimits(); 561 this->updateSamplerateLimits();
758 562
759 // Samplerate dividers changed, recalculate it 563 // Samplerate dividers changed, recalculate it
760 this->restoreTargets(); 564 this->restoreTargets();
761 } 565 }
762 566
763 - this->settings.recordLengthId = index;  
764 -  
765 return this->settings.samplerate.limits->recordLengths[index]; 567 return this->settings.samplerate.limits->recordLengths[index];
766 } 568 }
767 569
@@ -1098,9 +900,6 @@ namespace Hantek { @@ -1098,9 +900,6 @@ namespace Hantek {
1098 this->specification.sampleSize = 8; 900 this->specification.sampleSize = 8;
1099 break; 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 this->previousSampleCount = 0; 903 this->previousSampleCount = 0;
1105 904
1106 // Get channel level data 905 // Get channel level data
@@ -1111,6 +910,14 @@ namespace Hantek { @@ -1111,6 +910,14 @@ namespace Hantek {
1111 return; 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 DsoControl::connectDevice(); 921 DsoControl::connectDevice();
1115 } 922 }
1116 923
@@ -1620,4 +1427,252 @@ namespace Hantek { @@ -1620,4 +1427,252 @@ namespace Hantek {
1620 return Dso::ERROR_UNSUPPORTED; 1427 return Dso::ERROR_UNSUPPORTED;
1621 } 1428 }
1622 #endif 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,6 +37,9 @@
37 #include "hantek/types.h" 37 #include "hantek/types.h"
38 38
39 39
  40 +class QTimer;
  41 +
  42 +
40 namespace Hantek { 43 namespace Hantek {
41 class Device; 44 class Device;
42 45
@@ -210,6 +213,7 @@ namespace Hantek { @@ -210,6 +213,7 @@ namespace Hantek {
210 213
211 protected: 214 protected:
212 void run(); 215 void run();
  216 + void updateInterval();
213 217
214 unsigned int calculateTriggerPoint(unsigned int value); 218 unsigned int calculateTriggerPoint(unsigned int value);
215 int getCaptureState(); 219 int getCaptureState();
@@ -223,6 +227,7 @@ namespace Hantek { @@ -223,6 +227,7 @@ namespace Hantek {
223 227
224 // Communication with device 228 // Communication with device
225 Device *device; ///< The USB device for the oscilloscope 229 Device *device; ///< The USB device for the oscilloscope
  230 + QTimer *timer; ///< Timer for periodic communication thread
226 231
227 Helper::DataArray<unsigned char> *command[BULK_COUNT]; ///< Pointers to bulk commands, ready to be transmitted 232 Helper::DataArray<unsigned char> *command[BULK_COUNT]; ///< Pointers to bulk commands, ready to be transmitted
228 bool commandPending[BULK_COUNT]; ///< true, when the command should be executed 233 bool commandPending[BULK_COUNT]; ///< true, when the command should be executed
@@ -238,6 +243,14 @@ namespace Hantek { @@ -238,6 +243,14 @@ namespace Hantek {
238 std::vector<std::vector<double> > samples; ///< Sample data vectors sent to the data analyzer 243 std::vector<std::vector<double> > samples; ///< Sample data vectors sent to the data analyzer
239 unsigned int previousSampleCount; ///< The expected total number of samples at the last check before sampling started 244 unsigned int previousSampleCount; ///< The expected total number of samples at the last check before sampling started
240 QMutex samplesMutex; ///< Mutex for the sample data 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 public slots: 255 public slots:
243 virtual void connectDevice(); 256 virtual void connectDevice();
@@ -260,6 +273,9 @@ namespace Hantek { @@ -260,6 +273,9 @@ namespace Hantek {
260 #ifdef DEBUG 273 #ifdef DEBUG
261 int stringCommand(QString command); 274 int stringCommand(QString command);
262 #endif 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,10 +342,6 @@ void OpenHantekMainWindow::initializeDevice() {
342 this->dsoControl->setPretriggerPosition(this->settings->scope.trigger.position * this->settings->scope.horizontal.timebase * DIVS_TIME); 342 this->dsoControl->setPretriggerPosition(this->settings->scope.trigger.position * this->settings->scope.horizontal.timebase * DIVS_TIME);
343 this->dsoControl->setTriggerSlope(this->settings->scope.trigger.slope); 343 this->dsoControl->setTriggerSlope(this->settings->scope.trigger.slope);
344 this->dsoControl->setTriggerSource(this->settings->scope.trigger.special, this->settings->scope.trigger.source); 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 /// \brief Read the settings from an ini file. 347 /// \brief Read the settings from an ini file.