diff --git a/openhantek/ChangeLog b/openhantek/ChangeLog index 9958d71..12494c5 100644 --- a/openhantek/ChangeLog +++ b/openhantek/ChangeLog @@ -32,4 +32,8 @@ 2010-08-16 Oliver Haag * Completed libusb 0.1 downwards compatibility mode (env LIBUSB_VERSION=0) * Bugfix: Grid of scopes drawn even if there aren't any graphs available -* Implemented basics of the XY-mode \ No newline at end of file +* Implemented basics of the XY-mode + +2010-08-18 Oliver Haag +* Bugfix: Trigger levels weren't sent to the oscilloscope +* Implemented single trigger mode diff --git a/openhantek/src/dsocontrol.cpp b/openhantek/src/dsocontrol.cpp index 949fef7..40fbbe5 100644 --- a/openhantek/src/dsocontrol.cpp +++ b/openhantek/src/dsocontrol.cpp @@ -36,11 +36,13 @@ DsoControl::DsoControl(QObject *parent) : QThread(parent) { /// \brief Start sampling process. void DsoControl::startSampling() { this->sampling = true; + emit samplingStarted(); } /// \brief Stop sampling process. void DsoControl::stopSampling() { this->sampling = false; + emit samplingStopped(); } /// \brief Get a list of the names of the special trigger sources. diff --git a/openhantek/src/dsocontrol.h b/openhantek/src/dsocontrol.h index 32436b7..72ecf9f 100644 --- a/openhantek/src/dsocontrol.h +++ b/openhantek/src/dsocontrol.h @@ -46,9 +46,6 @@ class DsoControl : public QThread { public: DsoControl(QObject *parent = 0); - virtual void startSampling(); - virtual void stopSampling(); - virtual unsigned int getChannelCount() = 0; ///< Get the number of channels for this oscilloscope const QStringList *getSpecialTriggerSources(); @@ -62,6 +59,8 @@ class DsoControl : public QThread { signals: void deviceConnected(); ///< The oscilloscope device has been disconnected void deviceDisconnected(); ///< The oscilloscope device has been connected + void samplingStarted(); ///< The oscilloscope started sampling/waiting for trigger + void samplingStopped(); ///< The oscilloscope stopped sampling/waiting for trigger void statusMessage(const QString &message, int timeout); ///< Status message about the oscilloscope void samplesAvailable(const QList *data, const QList *size, double samplerate, QMutex *mutex); ///< New sample data is available @@ -69,6 +68,9 @@ class DsoControl : public QThread { virtual void connectDevice(); virtual void disconnectDevice(); + virtual void startSampling(); + virtual void stopSampling(); + virtual unsigned long int setSamplerate(unsigned long int samplerate) = 0; ///< Set the samplerate that should be met virtual double setBufferSize(unsigned int size) = 0; ///< Set the needed buffer size diff --git a/openhantek/src/hantek/control.cpp b/openhantek/src/hantek/control.cpp index a4ea4e8..9cf090e 100644 --- a/openhantek/src/hantek/control.cpp +++ b/openhantek/src/hantek/control.cpp @@ -150,6 +150,7 @@ namespace Hantek { // The control loop is running until the device is disconnected int captureState = CAPTURE_WAITING; bool samplingStarted = false; + Dso::TriggerMode lastTriggerMode = (Dso::TriggerMode) -1; while(captureState != LIBUSB_ERROR_NO_DEVICE && !this->terminate) { // Send all pending bulk commands @@ -196,23 +197,33 @@ namespace Hantek { /// \todo Maybe the time interval could be improved... this->msleep(50); - if(!this->sampling) + if(!this->sampling) { + samplingStarted = false; continue; + } + captureState = this->getCaptureState(); switch(captureState) { case CAPTURE_READY: case CAPTURE_READY5200: - samplingStarted = false; - - errorCode = this->getSamples(); + // Get data and process it, if we're still sampling + errorCode = this->getSamples(samplingStarted); if(errorCode < 0) qDebug("Getting sample data failed: %s", Helper::libUsbErrorString(errorCode).toLocal8Bit().data()); + // Check if we're in single trigger mode + if(this->triggerMode == Dso::TRIGGERMODE_SINGLE && samplingStarted) + this->stopSampling(); + + // Sampling completed, restart it when necessary + samplingStarted = false; + // Start next capture if necessary by leaving out the break statement if(!this->sampling) break; + case CAPTURE_WAITING: - if(samplingStarted) + if(samplingStarted && lastTriggerMode == this->triggerMode) break; // Start capturing @@ -236,7 +247,9 @@ namespace Hantek { captureState = LIBUSB_ERROR_NO_DEVICE; } samplingStarted = true; + lastTriggerMode = this->triggerMode; break; + case CAPTURE_SAMPLING: break; default: @@ -304,92 +317,97 @@ namespace Hantek { /// \brief Gets sample data from the oscilloscope and converts it. /// \return 0 on success, libusb error code on error. - int Control::getSamples() { + int Control::getSamples(bool process) { int errorCode; + // Request data errorCode = this->device->bulkCommand(this->command[COMMAND_GETDATA], 1); if(errorCode < 0) return errorCode; + // Save raw data to temporary buffer unsigned int dataCount = this->bufferSize * HANTEK_CHANNELS; unsigned char data[dataCount]; errorCode = this->device->bulkReadMulti(data, dataCount); if(errorCode < 0) return errorCode; - this->samplesMutex.lock(); - - // Convert channel data - if(((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->getFastRate()) { - // Fast rate mode, one channel is using all buffers - int channel; - if(((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->getUsedChannel() == USED_CH1) - channel = 0; - else - channel = 1; - - - // Clear unused channels - for(int channelCounter = 0; channelCounter < HANTEK_CHANNELS; channelCounter++) - if(channelCounter != channel && this->samples[channelCounter]) { - - delete this->samples[channelCounter]; - this->samples[channelCounter] = 0; - } + // Process the data only if we want it + if(process) { + this->samplesMutex.lock(); - if(channel < HANTEK_CHANNELS) { - // Reallocate memory for samples if the sample count has changed - if(!this->samples[channel] || this->samplesSize[channel] != dataCount) { - if(this->samples[channel]) - delete this->samples[channel]; - this->samples[channel] = new double[dataCount]; - this->samplesSize[channel] = dataCount; - } + // Convert channel data + if(((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->getFastRate()) { + // Fast rate mode, one channel is using all buffers + int channel; + if(((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->getUsedChannel() == USED_CH1) + channel = 0; + else + channel = 1; - // Convert data from the oscilloscope and write it into the sample buffer - unsigned int bufferPosition = this->triggerPoint; - for(unsigned int realPosition = 0; realPosition < dataCount; realPosition++, bufferPosition++) { - if(bufferPosition >= dataCount) - bufferPosition %= dataCount; - - this->samples[channel][realPosition] = ((double) data[bufferPosition] / 0xff - this->offsetReal[channel]) * this->gainSteps[this->gain[channel]]; - } - } - } - else { - // Normal mode, channel are using their separate buffers - unsigned char usedChannels = ((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->getUsedChannel(); - for(int channel = 0; channel < HANTEK_CHANNELS; channel++) { - if(usedChannels == USED_CH1CH2 || channel == usedChannels) { + + // Clear unused channels + for(int channelCounter = 0; channelCounter < HANTEK_CHANNELS; channelCounter++) + if(channelCounter != channel && this->samples[channelCounter]) { + + delete this->samples[channelCounter]; + this->samples[channelCounter] = 0; + } + + if(channel < HANTEK_CHANNELS) { // Reallocate memory for samples if the sample count has changed - if(!this->samples[channel] || this->samplesSize[channel] != this->bufferSize) { + if(!this->samples[channel] || this->samplesSize[channel] != dataCount) { if(this->samples[channel]) delete this->samples[channel]; - this->samples[channel] = new double[this->bufferSize]; - this->samplesSize[channel] = this->bufferSize; + this->samples[channel] = new double[dataCount]; + this->samplesSize[channel] = dataCount; } // Convert data from the oscilloscope and write it into the sample buffer - unsigned int bufferPosition = this->triggerPoint * 2; - for(unsigned int realPosition = 0; realPosition < this->bufferSize; realPosition++, bufferPosition += 2) { + unsigned int bufferPosition = this->triggerPoint; + for(unsigned int realPosition = 0; realPosition < dataCount; realPosition++, bufferPosition++) { if(bufferPosition >= dataCount) bufferPosition %= dataCount; - this->samples[channel][realPosition] = ((double) data[bufferPosition + HANTEK_CHANNELS - 1 - channel] / 256.0 - this->offsetReal[channel]) * this->gainSteps[this->gain[channel]]; + this->samples[channel][realPosition] = ((double) data[bufferPosition] / 0xff - this->offsetReal[channel]) * this->gainSteps[this->gain[channel]]; } } - else if(this->samples[channel]) { - // Clear unused channels - delete this->samples[channel]; - this->samples[channel] = 0; - this->samplesSize[channel] = 0; + } + else { + // Normal mode, channel are using their separate buffers + unsigned char usedChannels = ((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->getUsedChannel(); + for(int channel = 0; channel < HANTEK_CHANNELS; channel++) { + if(usedChannels == USED_CH1CH2 || channel == usedChannels) { + // Reallocate memory for samples if the sample count has changed + if(!this->samples[channel] || this->samplesSize[channel] != this->bufferSize) { + if(this->samples[channel]) + delete this->samples[channel]; + this->samples[channel] = new double[this->bufferSize]; + this->samplesSize[channel] = this->bufferSize; + } + + // Convert data from the oscilloscope and write it into the sample buffer + unsigned int bufferPosition = this->triggerPoint * 2; + for(unsigned int realPosition = 0; realPosition < this->bufferSize; realPosition++, bufferPosition += 2) { + if(bufferPosition >= dataCount) + bufferPosition %= dataCount; + + this->samples[channel][realPosition] = ((double) data[bufferPosition + HANTEK_CHANNELS - 1 - channel] / 256.0 - this->offsetReal[channel]) * this->gainSteps[this->gain[channel]]; + } + } + else if(this->samples[channel]) { + // Clear unused channels + delete this->samples[channel]; + this->samples[channel] = 0; + this->samplesSize[channel] = 0; + } } } + + this->samplesMutex.unlock(); + emit samplesAvailable(&(this->samples), &(this->samplesSize), this->samplerateSteps[this->samplerate], &(this->samplesMutex)); } - this->samplesMutex.unlock(); - emit samplesAvailable(&(this->samples), &(this->samplesSize), this->samplerateSteps[this->samplerate], &(this->samplesMutex)); - return 0; } @@ -610,7 +628,7 @@ namespace Hantek { // Calculate the trigger level value (0x00 - 0xfe) unsigned short int levelValue = (this->offsetReal[channel] + level / this->gainSteps[this->gain[channel]]) * 0xfe + 0.5; - if(this->triggerSpecial && channel == this->triggerSource) { + if(!this->triggerSpecial && channel == this->triggerSource) { // SetOffset control command for trigger level ((ControlSetOffset *) this->control[CONTROLINDEX_SETOFFSET])->setTrigger(levelValue); this->controlPending[CONTROLINDEX_SETOFFSET] = true; diff --git a/openhantek/src/hantek/control.h b/openhantek/src/hantek/control.h index 038dd28..0e2ba93 100644 --- a/openhantek/src/hantek/control.h +++ b/openhantek/src/hantek/control.h @@ -69,7 +69,7 @@ namespace Hantek { unsigned int calculateTriggerPoint(unsigned int value); int getCaptureState(); - int getSamples(); + int getSamples(bool process); Device *device; ///< The USB device for the oscilloscope diff --git a/openhantek/src/openhantek.cpp b/openhantek/src/openhantek.cpp index d90a1ac..22f71e8 100644 --- a/openhantek/src/openhantek.cpp +++ b/openhantek/src/openhantek.cpp @@ -124,6 +124,10 @@ OpenHantekMainWindow::OpenHantekMainWindow(QWidget *parent, Qt::WindowFlags flag connect(this->spectrumDock, SIGNAL(usedChanged(unsigned int, bool)), this->dsoWidget, SLOT(updateSpectrumUsed(unsigned int, bool))); connect(this->spectrumDock, SIGNAL(magnitudeChanged(unsigned int, double)), this->dsoWidget, SLOT(updateSpectrumMagnitude(unsigned int))); + // Started/stopped signals from oscilloscope + connect(this->dsoControl, SIGNAL(samplingStarted()), this, SLOT(started())); + connect(this->dsoControl, SIGNAL(samplingStopped()), this, SLOT(stopped())); + // Set up the oscilloscope for(unsigned int channel = 0; channel < this->settings->scope.physicalChannels; channel++) { this->dsoControl->setCoupling(channel, (Dso::Coupling) this->settings->scope.voltage[channel].misc); @@ -191,10 +195,9 @@ void OpenHantekMainWindow::createActions() { this->configAction->setStatusTip(tr("Configure the oscilloscope")); connect(this->configAction, SIGNAL(triggered()), this, SLOT(config())); - this->startStopAction = new QAction(QIcon(":actions/stop.png"), tr("&Stop"), this); + this->startStopAction = new QAction(this); this->startStopAction->setShortcut(tr("Space")); - this->startStopAction->setStatusTip(tr("Stop the oscilloscope")); - connect(this->startStopAction, SIGNAL(triggered()), this, SLOT(stop())); + this->stopped(); this->bufferSizeActionGroup = new QActionGroup(this); connect(this->bufferSizeActionGroup, SIGNAL(selected(QAction *)), this, SLOT(bufferSizeSelected(QAction *))); @@ -541,7 +544,7 @@ bool OpenHantekMainWindow::save() { if (this->currentFile.isEmpty()) { return saveAs(); } else { - return false; // TODO + return false; /// \todo Saving of individual setting files } } @@ -552,33 +555,27 @@ bool OpenHantekMainWindow::saveAs() { if (fileName.isEmpty()) return false; - return false; // TODO + return false; /// \todo Saving of individual setting files } -/// \brief Start the oscilloscope. -void OpenHantekMainWindow::start() { +/// \brief The oscilloscope started sampling. +void OpenHantekMainWindow::started() { this->startStopAction->setText(tr("&Stop")); this->startStopAction->setIcon(QIcon(":actions/stop.png")); this->startStopAction->setStatusTip(tr("Stop the oscilloscope")); - disconnect(this->startStopAction, SIGNAL(triggered()), this, SLOT(start())); - connect(this->startStopAction, SIGNAL(triggered()), this, SLOT(stop())); - connect(this->dsoControl, SIGNAL(disconnected()), this, SLOT(stopped())); - - this->dsoControl->startSampling(); + disconnect(this->startStopAction, SIGNAL(triggered()), this->dsoControl, SLOT(startSampling())); + connect(this->startStopAction, SIGNAL(triggered()), this->dsoControl, SLOT(stopSampling())); } -/// \brief Stop the oscilloscope. -void OpenHantekMainWindow::stop() { +/// \brief The oscilloscope stopped sampling. +void OpenHantekMainWindow::stopped() { this->startStopAction->setText(tr("&Start")); this->startStopAction->setIcon(QIcon(":actions/start.png")); this->startStopAction->setStatusTip(tr("Start the oscilloscope")); - disconnect(this->startStopAction, SIGNAL(triggered()), this, SLOT(stop())); - disconnect(this->dsoWidget, SIGNAL(stopped()), this, SLOT(stopped())); - connect(this->startStopAction, SIGNAL(triggered()), this, SLOT(start())); - - this->dsoControl->stopSampling(); + disconnect(this->startStopAction, SIGNAL(triggered()), this->dsoControl, SLOT(stopSampling())); + connect(this->startStopAction, SIGNAL(triggered()), this->dsoControl, SLOT(startSampling())); } /// \brief Configure the oscilloscope. diff --git a/openhantek/src/openhantek.h b/openhantek/src/openhantek.h index 57dd0fc..4c0dc82 100644 --- a/openhantek/src/openhantek.h +++ b/openhantek/src/openhantek.h @@ -118,8 +118,8 @@ class OpenHantekMainWindow : public QMainWindow { void digitalPhosphor(bool enabled); void zoom(bool enabled); // Oscilloscope control - void start(); - void stop(); + void started(); + void stopped(); // Other void config(); void about();