From 104958b20f7e739f0950ea51f41dcea685428d15 Mon Sep 17 00:00:00 2001 From: oliverhaag Date: Sun, 29 Aug 2010 13:29:26 +0000 Subject: [PATCH] Added DSO-5200 support and some smaller improvements --- openhantek/ChangeLog | 7 +++++++ openhantek/Doxyfile | 2 +- openhantek/OpenHantek.pro | 12 +++++------- openhantek/src/dsocontrol.cpp | 1 + openhantek/src/hantek/control.cpp | 419 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------- openhantek/src/hantek/control.h | 4 ++++ openhantek/src/hantek/types.cpp | 313 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------- openhantek/src/hantek/types.h | 599 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- openhantek/src/openhantek.cpp | 3 ++- 9 files changed, 944 insertions(+), 416 deletions(-) diff --git a/openhantek/ChangeLog b/openhantek/ChangeLog index 1a865d8..ee76e6b 100644 --- a/openhantek/ChangeLog +++ b/openhantek/ChangeLog @@ -61,3 +61,10 @@ * Added the samplerate formula to the documentation * Documentation updated with additional information from Oleg * Removed Oleg from AUTHORS + +2010-08-29 Oliver Haag +* DSO details are known after Hantek::Control::connectDevice() is executed +* Removed useless initialization in Hantek::Control +* DSO is started after the settings have been transferred +* Added additional debug messages when building as debug binary +* Added support for DSO-5200 diff --git a/openhantek/Doxyfile b/openhantek/Doxyfile index 4a76466..891c6e8 100644 --- a/openhantek/Doxyfile +++ b/openhantek/Doxyfile @@ -611,7 +611,7 @@ EXCLUDE_SYMLINKS = NO # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = */.svn* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the diff --git a/openhantek/OpenHantek.pro b/openhantek/OpenHantek.pro index d7f007d..54aa9e0 100644 --- a/openhantek/OpenHantek.pro +++ b/openhantek/OpenHantek.pro @@ -92,6 +92,10 @@ else { } DEFINES += LIBUSB_VERSION=$${LIBUSB_VERSION} +# Debug output +CONFIG(debug, debug|release): + DEFINES += DEBUG + # Settings for different operating systems unix:!macx { isEmpty(PREFIX):PREFIX = /usr/local @@ -131,13 +135,7 @@ DEFINES += VERSION=\\\"$${VERSION}\\\" # Custom target "doc" for Doxygen doxygen.target = doc -doxygen.commands = rm \ - -r \ - doc/; \ - env \ - DEFINES=\"$${DEFINES}\" \ - doxygen \ - Doxyfile +doxygen.commands = "rm -r doc/; env DEFINES=\"$${DEFINES}\" doxygen Doxyfile" doxygen.depends = $${SOURCES} \ $${HEADERS} \ $${DOXYFILES} diff --git a/openhantek/src/dsocontrol.cpp b/openhantek/src/dsocontrol.cpp index 40fbbe5..42cd595 100644 --- a/openhantek/src/dsocontrol.cpp +++ b/openhantek/src/dsocontrol.cpp @@ -52,6 +52,7 @@ const QStringList *DsoControl::getSpecialTriggerSources() { /// \brief Try to connect to the oscilloscope. void DsoControl::connectDevice() { + this->sampling = false; this->terminate = false; this->start(); } diff --git a/openhantek/src/hantek/control.cpp b/openhantek/src/hantek/control.cpp index 1a3115e..5676b82 100644 --- a/openhantek/src/hantek/control.cpp +++ b/openhantek/src/hantek/control.cpp @@ -58,6 +58,9 @@ namespace Hantek { this->command[COMMAND_SETGAIN] = new CommandSetGain(); this->command[COMMAND_SETLOGICALDATA] = new CommandSetLogicalData(); this->command[COMMAND_GETLOGICALDATA] = new CommandGetLogicalData(); + this->command[COMMAND_SETSAMPLERATE5200] = new CommandSetSamplerate5200(); + this->command[COMMAND_SETBUFFER5200] = new CommandSetBuffer5200(); + this->command[COMMAND_SETTRIGGER5200] = new CommandSetTrigger5200(); // Transmission-ready control commands this->control[CONTROLINDEX_SETOFFSET] = new ControlSetOffset(); @@ -73,20 +76,8 @@ namespace Hantek { } } - // Cached variables - for(unsigned int channel = 0; channel < HANTEK_CHANNELS; channel++) { - this->setChannelUsed(channel, channel == 0); - this->setCoupling(channel, Dso::COUPLING_AC); - this->setGain(channel, 8.0); - this->setOffset(channel, 0.5); - this->setTriggerLevel(channel, 0.0); - } - this->setBufferSize(BUFFER_SMALL); - this->setSamplerate(1e6); - this->setTriggerMode(Dso::TRIGGERMODE_NORMAL); - this->setTriggerPosition(5e3 / (this->samplerateMax / this->samplerateDivider)); - this->setTriggerSlope(Dso::SLOPE_POSITIVE); - this->setTriggerSource(false, 0); + // USB device + this->device = new Device(this); // Sample buffers for(unsigned int channel = 0; channel < HANTEK_CHANNELS; channel++) { @@ -94,9 +85,6 @@ namespace Hantek { this->samplesSize.append(0); } - // USB device - this->device = new Device(this); - connect(this->device, SIGNAL(disconnected()), this, SLOT(disconnectDevice())); } @@ -115,57 +103,6 @@ namespace Hantek { void Control::run() { int errorCode; - emit statusMessage(this->device->search(), 0); - if(!this->device->isConnected()) - return; - - // Set all configuration commands as pending - this->commandPending[COMMAND_SETFILTER] = true; - this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = true; - this->commandPending[COMMAND_FORCETRIGGER] = false; - this->commandPending[COMMAND_STARTSAMPLING] = false; - this->commandPending[COMMAND_ENABLETRIGGER] = false; - this->commandPending[COMMAND_GETDATA] = false; - this->commandPending[COMMAND_GETCAPTURESTATE] = false; - this->commandPending[COMMAND_SETGAIN] = true; - this->commandPending[COMMAND_SETLOGICALDATA] = true; - this->commandPending[COMMAND_GETLOGICALDATA] = false; - for(int control = 0; control < CONTROLINDEX_COUNT; control++) - this->controlPending[control] = true; - - // Maximum possible samplerate for a single channel - switch(this->device->getModel()) { - case MODEL_DSO2090: - case MODEL_DSO2100: - this->samplerateChannelMax = 50e6; - break; - case MODEL_DSO2150: - this->samplerateChannelMax = 75e6; - break; - case MODEL_DSO2250: - case MODEL_DSO5200: - case MODEL_DSO5200A: - this->samplerateChannelMax = 125e6; - break; - default: - this->samplerateChannelMax = 50e6; - break; - } - - // Get channel level data - errorCode = this->device->controlRead(CONTROL_VALUE, (unsigned char*) &(this->channelLevels), sizeof(this->channelLevels), (int) VALUE_CHANNELLEVEL); - if(errorCode < 0) { - this->device->disconnect(); - emit statusMessage(tr("Couldn't get channel level data from oscilloscope"), 0); - return; - } - - // Adapt offsets - for(unsigned int channel = 0; channel < HANTEK_CHANNELS; channel++) - this->setOffset(channel, this->offset[channel]); - this->setSamplerate(this->samplerateMax / this->samplerateDivider); - this->setTriggerPosition(this->triggerPosition); - // The control loop is running until the device is disconnected int captureState = CAPTURE_WAITING; bool samplingStarted = false; @@ -177,6 +114,13 @@ namespace Hantek { if(!this->commandPending[command]) continue; +#ifdef DEBUG + QString hexDump, hexByte; + for(unsigned int index = 0; index < this->command[command]->getSize(); index++) + hexDump.append(hexByte.sprintf(" %02x", this->command[command]->data()[index])); + qDebug("Sending bulk command:%s", hexDump.toLocal8Bit().data()); +#endif + errorCode = this->device->bulkCommand(this->command[command]); if(errorCode < 0) { qDebug("Sending bulk command 0x%02x failed: %s", command, Helper::libUsbErrorString(errorCode).toLocal8Bit().data()); @@ -197,6 +141,13 @@ namespace Hantek { if(!this->controlPending[control]) continue; +#ifdef DEBUG + QString hexDump, hexByte; + for(unsigned int index = 0; index < this->control[control]->getSize(); index++) + hexDump.append(hexByte.sprintf(" %02x", this->control[control]->data()[index])); + qDebug("Sending control command 0x%02x:%s", control, hexDump.toLocal8Bit().data()); +#endif + errorCode = this->device->controlWrite(this->controlCode[control], this->control[control]->data(), this->control[control]->getSize()); if(errorCode < 0) { qDebug("Sending control command 0x%2x failed: %s", control, Helper::libUsbErrorString(errorCode).toLocal8Bit().data()); @@ -346,20 +297,34 @@ namespace Hantek { // Save raw data to temporary buffer unsigned int dataCount = this->bufferSize * HANTEK_CHANNELS; - unsigned char data[dataCount]; - errorCode = this->device->bulkReadMulti(data, dataCount); + unsigned int dataLength = dataCount; + bool using9Bits = false; + if(this->device->getModel() == MODEL_DSO5200 || this->device->getModel() == MODEL_DSO5200A) { + using9Bits = true; + dataLength *= 2; + } + + unsigned char data[dataLength]; + errorCode = this->device->bulkReadMulti(data, dataLength); if(errorCode < 0) return errorCode; // Process the data only if we want it if(process) { + // How much data did we really receive? + dataLength = errorCode; + if(using9Bits) + dataCount = dataLength / 2; + else + dataCount = dataLength; + 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) + if(((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->getUsedChannels() == USED_CH1) channel = 0; else channel = 1; @@ -384,34 +349,57 @@ namespace Hantek { // 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]]; + if(using9Bits) { + // Additional MSBs after the normal data + for(unsigned int realPosition = 0; realPosition < dataCount; realPosition++, bufferPosition++) { + if(bufferPosition >= dataCount) + bufferPosition %= dataCount; + + this->samples[channel][realPosition] = ((double) (data[bufferPosition] + (data[dataCount + bufferPosition] << 8)) / 0x1ff - this->offsetReal[channel]) * this->gainSteps[this->gain[channel]]; + } + } + else { + 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(); + unsigned int channelDataCount = dataCount / HANTEK_CHANNELS; + unsigned char usedChannels = ((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->getUsedChannels(); 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] || this->samplesSize[channel] != channelDataCount) { 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[channelDataCount]; + this->samplesSize[channel] = channelDataCount; } // 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]]; + if(using9Bits) { + // Additional MSBs after the normal data + for(unsigned int realPosition = 0; realPosition < channelDataCount; realPosition++, bufferPosition += 2) { + if(bufferPosition >= dataCount) + bufferPosition %= dataCount; + + this->samples[channel][realPosition] = ((double) (data[bufferPosition + HANTEK_CHANNELS - 1 - channel] + (data[dataCount + bufferPosition + HANTEK_CHANNELS - 1 - channel] << 8)) / 0x1ff - this->offsetReal[channel]) * this->gainSteps[this->gain[channel]]; + } + } + else { + for(unsigned int realPosition = 0; realPosition < channelDataCount; realPosition++, bufferPosition += 2) { + if(bufferPosition >= dataCount) + bufferPosition %= dataCount; + + this->samples[channel][realPosition] = ((double) data[bufferPosition + HANTEK_CHANNELS - 1 - channel] / 0xff - this->offsetReal[channel]) * this->gainSteps[this->gain[channel]]; + } } } else if(this->samples[channel]) { @@ -436,15 +424,113 @@ namespace Hantek { unsigned long int Control::updateBufferSize(unsigned long int size) { BufferSizeId sizeId = (size <= BUFFER_SMALL) ? BUFFERID_SMALL : BUFFERID_LARGE; - // SetTriggerAndSamplerate bulk command for samplerate - ((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->setBufferSize(sizeId); - this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = true; - - this->bufferSize = (sizeId == BUFFERID_SMALL) ? BUFFER_SMALL : BUFFER_LARGE; + switch(this->commandVersion) { + case 0: + // SetTriggerAndSamplerate bulk command for buffer size + ((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->setBufferSize(sizeId); + this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = true; + + this->bufferSize = (sizeId == BUFFERID_SMALL) ? BUFFER_SMALL : BUFFER_LARGE; + break; + + case 1: + // SetBuffer5200 bulk command for buffer size + CommandSetBuffer5200 *commandSetBuffer5200 = (CommandSetBuffer5200 *) this->command[COMMAND_SETBUFFER5200]; + commandSetBuffer5200->setUsedPre(DTRIGGERPOSITION_ON); + commandSetBuffer5200->setUsedPost(DTRIGGERPOSITION_ON); + commandSetBuffer5200->setBufferSize(sizeId); + this->commandPending[COMMAND_SETBUFFER5200] = true; + + this->bufferSize = (sizeId == BUFFERID_SMALL) ? BUFFER_SMALL : BUFFER_LARGE5200; + break; + } return this->bufferSize; } + /// \brief Try to connect to the oscilloscope. + void Control::connectDevice() { + int errorCode; + + emit statusMessage(this->device->search(), 0); + if(!this->device->isConnected()) + return; + + // Set all necessary configuration commands as pending + this->commandPending[COMMAND_SETFILTER] = true; + this->commandPending[COMMAND_FORCETRIGGER] = false; + this->commandPending[COMMAND_STARTSAMPLING] = false; + this->commandPending[COMMAND_ENABLETRIGGER] = false; + this->commandPending[COMMAND_GETDATA] = false; + this->commandPending[COMMAND_GETCAPTURESTATE] = false; + this->commandPending[COMMAND_SETGAIN] = true; + this->commandPending[COMMAND_SETLOGICALDATA] = false; + this->commandPending[COMMAND_GETLOGICALDATA] = false; + + // Determine the command version we need for this model + bool unsupported = false; + switch(this->device->getModel()) { + case MODEL_DSO2100: + case MODEL_DSO2150: + unsupported = true; + case MODEL_DSO2090: + this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = true; + this->commandPending[COMMAND_SETSAMPLERATE5200] = false; + this->commandPending[COMMAND_SETBUFFER5200] = false; + this->commandPending[COMMAND_SETTRIGGER5200] = false; + this->commandVersion = 0; + break; + + case MODEL_DSO2250: + case MODEL_DSO5200A: + unsupported = true; + case MODEL_DSO5200: + this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = false; + this->commandPending[COMMAND_SETSAMPLERATE5200] = true; + this->commandPending[COMMAND_SETBUFFER5200] = true; + this->commandPending[COMMAND_SETTRIGGER5200] = true; + this->commandVersion = 1; + break; + + default: + this->device->disconnect(); + emit statusMessage(tr("Unknown model"), 0); + return; + } + + if(unsupported) + qDebug("Warning: This Hantek DSO model isn't supported officially, so it may not be working as expected. Reports about your experiences are very welcome though (Please open a feature request in the tracker at https://sf.net/projects/openhantek/ or email me directly to oliver.haag@gmail.com). If it's working perfectly I can remove this warning, if not it should be possible to get it working with your help soon."); + + for(int control = 0; control < CONTROLINDEX_COUNT; control++) + this->controlPending[control] = true; + + // Maximum possible samplerate for a single channel + switch(this->device->getModel()) { + case MODEL_DSO2090: + case MODEL_DSO2100: + this->samplerateChannelMax = 50e6; + break; + + case MODEL_DSO2150: + this->samplerateChannelMax = 75e6; + break; + + default: + this->samplerateChannelMax = 125e6; + break; + } + + // Get channel level data + errorCode = this->device->controlRead(CONTROL_VALUE, (unsigned char*) &(this->channelLevels), sizeof(this->channelLevels), (int) VALUE_CHANNELLEVEL); + if(errorCode < 0) { + this->device->disconnect(); + emit statusMessage(tr("Couldn't get channel level data from oscilloscope"), 0); + return; + } + + DsoControl::connectDevice(); + } + /// \brief Sets the size of the oscilloscopes sample buffer. /// \param size The buffer size that should be met (S). /// \return The buffer size that has been set. @@ -465,19 +551,22 @@ namespace Hantek { if(samplerate == 0) return 0; - // SetTriggerAndSamplerate bulk command for samplerate + // Pointers to needed commands CommandSetTriggerAndSamplerate *commandSetTriggerAndSamplerate = (CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE]; + CommandSetSamplerate5200 *commandSetSamplerate5200 = (CommandSetSamplerate5200 *) this->command[COMMAND_SETSAMPLERATE5200]; + CommandSetBuffer5200 *commandSetBuffer5200 = (CommandSetBuffer5200 *) this->command[COMMAND_SETBUFFER5200]; + CommandSetTrigger5200 *commandSetTrigger5200 = (CommandSetTrigger5200 *) this->command[COMMAND_SETTRIGGER5200]; // Calculate with fast rate first if only one channel is used bool fastRate = false; this->samplerateMax = this->samplerateChannelMax; - if(((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->getUsedChannel() != USED_CH1CH2) { + if((this->commandVersion == 0) ? (commandSetTriggerAndSamplerate->getUsedChannels() != USED_CH1CH2) : (commandSetTrigger5200->getUsedChannels() != EUSED_CH1CH2)) { fastRate = true; this->samplerateMax *= HANTEK_CHANNELS; } // The maximum sample rate depends on the buffer size - switch(commandSetTriggerAndSamplerate->getBufferSize()) { + switch((this->commandVersion == 0) ? commandSetTriggerAndSamplerate->getBufferSize() : commandSetBuffer5200->getBufferSize()) { case BUFFERID_ROLL: this->samplerateMax /= 1000; break; @@ -503,14 +592,32 @@ namespace Hantek { long int valueSlow = qMax(((long int) this->samplerateDivider - 3) / 2, (long int) 0); unsigned char valueFast = this->samplerateDivider - valueSlow * 2; - // Store samplerate fast value - commandSetTriggerAndSamplerate->setSamplerateFast(valueFast); - // Store samplerate slow value (two's complement) - commandSetTriggerAndSamplerate->setSamplerateSlow(valueSlow == 0 ? 0 : 0xffff - valueSlow); - // Set fast rate when used - commandSetTriggerAndSamplerate->setFastRate(fastRate); - - this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = true; + switch(this->commandVersion) { + case 0: + // Store samplerate fast value + commandSetTriggerAndSamplerate->setSamplerateFast(valueFast); + // Store samplerate slow value (two's complement) + commandSetTriggerAndSamplerate->setSamplerateSlow(valueSlow == 0 ? 0 : 0xffff - valueSlow); + // Set fast rate when used + commandSetTriggerAndSamplerate->setFastRate(fastRate); + + this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = true; + + break; + + default: + // Store samplerate fast value + commandSetSamplerate5200->setSamplerateFast(4 - valueFast); + // Store samplerate slow value (two's complement) + commandSetSamplerate5200->setSamplerateSlow(valueSlow == 0 ? 0 : 0xffff - valueSlow); + // Set fast rate when used + commandSetTrigger5200->setFastRate(fastRate); + + this->commandPending[COMMAND_SETSAMPLERATE5200] = true; + this->commandPending[COMMAND_SETTRIGGER5200] = true; + + break; + } this->updateBufferSize(this->bufferSize); this->setTriggerSlope(this->triggerSlope); @@ -530,16 +637,33 @@ namespace Hantek { commandSetFilter->setChannel(channel, !used); this->commandPending[COMMAND_SETFILTER] = true; - // SetTriggerAndSamplerate bulk command for trigger source - unsigned char usedChannel = USED_CH1; - if(!commandSetFilter->getChannel(1)) { - if(commandSetFilter->getChannel(0)) - usedChannel = USED_CH2; - else - usedChannel = USED_CH1CH2; + switch(this->commandVersion) { + case 0: { + // SetTriggerAndSamplerate bulk command for trigger source + unsigned char usedChannels = USED_CH1; + if(!commandSetFilter->getChannel(1)) { + if(commandSetFilter->getChannel(0)) + usedChannels = USED_CH2; + else + usedChannels = USED_CH1CH2; + } + ((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->setUsedChannels(usedChannels); + this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = true; + break; + } + case 1: { + unsigned char usedChannels = EUSED_CH1; + if(!commandSetFilter->getChannel(1)) { + if(commandSetFilter->getChannel(0)) + usedChannels = EUSED_CH2; + else + usedChannels = EUSED_CH1CH2; + } + ((CommandSetTrigger5200 *) this->command[COMMAND_SETTRIGGER5200])->setUsedChannels(usedChannels); + this->commandPending[COMMAND_SETTRIGGER5200] = true; + break; + } } - ((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->setUsedChannel(usedChannel); - this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = true; return 0; } @@ -641,9 +765,19 @@ namespace Hantek { else sourceValue = TRIGGER_CH1 - id; - // SetTriggerAndSamplerate bulk command for trigger source - ((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->setTriggerSource(sourceValue); - this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = true; + switch(this->commandVersion) { + case 0: + // SetTriggerAndSamplerate bulk command for trigger source + ((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->setTriggerSource(sourceValue); + this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = true; + break; + + case 1: + // SetTrigger5200 bulk command for trigger source + ((CommandSetTrigger5200 *) this->command[COMMAND_SETTRIGGER5200])->setTriggerSource(sourceValue); + this->commandPending[COMMAND_SETTRIGGER5200] = true; + break; + } // SetRelays control command for external trigger relay ((ControlSetRelays *) this->control[CONTROLINDEX_SETRELAYS])->setTrigger(special); @@ -694,30 +828,61 @@ namespace Hantek { if(slope != Dso::SLOPE_NEGATIVE && slope != Dso::SLOPE_POSITIVE) return -1; - // SetTriggerAndSamplerate bulk command for trigger position - CommandSetTriggerAndSamplerate *commandSetTriggerAndSamplerate = (CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE]; - - commandSetTriggerAndSamplerate->setTriggerSlope((/*this->bufferSize != BUFFER_SMALL ||*/ commandSetTriggerAndSamplerate->getSamplerateFast() % 2 == 0) ? slope : Dso::SLOPE_NEGATIVE - slope); - this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = true; + switch(this->commandVersion) { + case 0: { + // SetTriggerAndSamplerate bulk command for trigger slope + CommandSetTriggerAndSamplerate *commandSetTriggerAndSamplerate = (CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE]; + + commandSetTriggerAndSamplerate->setTriggerSlope((/*this->bufferSize != BUFFER_SMALL ||*/ commandSetTriggerAndSamplerate->getSamplerateFast() % 2 == 0) ? slope : Dso::SLOPE_NEGATIVE - slope); + this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = true; + break; + } + case 1: { + // SetTrigger5200 bulk command for trigger slope + ((CommandSetTrigger5200 *) this->command[COMMAND_SETTRIGGER5200])->setTriggerSlope(slope); + this->commandPending[COMMAND_SETTRIGGER5200] = true; + break; + } + } this->triggerSlope = slope; return 0; } /// \brief Set the trigger position. - /// \param position The new trigger position (0.0 - 1.0). + /// \param position The new trigger position (in s). /// \return The trigger position that has been set. double Control::setTriggerPosition(double position) { - // Calculate the position value (Varying start point, measured in samples) - //unsigned long int positionRange = (this->bufferSize == BUFFER_SMALL) ? 10000 : 32768; - unsigned long int positionStart = (this->bufferSize == BUFFER_SMALL) ? 0x77660 : 0x78000; - unsigned long int positionValue = position * this->samplerateMax / this->samplerateDivider + positionStart; + // All trigger position are measured in samples + unsigned long int positionSamples = position * this->samplerateMax / this->samplerateDivider; - // SetTriggerAndSamplerate bulk command for trigger position - ((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->setTriggerPosition(positionValue); - this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = true; + switch(this->commandVersion) { + case 0: { + // Calculate the position value (Start point depending on buffer size) + unsigned long int positionStart = (this->bufferSize == BUFFER_SMALL) ? 0x77660 : 0x78000; + + // SetTriggerAndSamplerate bulk command for trigger position + ((CommandSetTriggerAndSamplerate *) this->command[COMMAND_SETTRIGGERANDSAMPLERATE])->setTriggerPosition(positionStart + positionSamples); + this->commandPending[COMMAND_SETTRIGGERANDSAMPLERATE] = true; + + break; + } + case 1: { + // Calculate the position values (Inverse, maximum is 0xffff) + unsigned short int positionPre = 0xffff - this->bufferSize + positionSamples; + unsigned short int positionPost = 0xffff - positionSamples; + + // SetBuffer5200 bulk command for trigger position + CommandSetBuffer5200 *commandSetBuffer5200 = (CommandSetBuffer5200 *) this->command[COMMAND_SETBUFFER5200]; + commandSetBuffer5200->setTriggerPositionPre(positionPre); + commandSetBuffer5200->setTriggerPositionPost(positionPost); + this->commandPending[COMMAND_SETBUFFER5200] = true; + + break; + } + } this->triggerPosition = position; - return (double) (positionValue - positionStart) / this->samplerateMax * this->samplerateDivider; + return (double) positionSamples / this->samplerateMax * this->samplerateDivider; } } diff --git a/openhantek/src/hantek/control.h b/openhantek/src/hantek/control.h index 7fe83ae..0e3d70e 100644 --- a/openhantek/src/hantek/control.h +++ b/openhantek/src/hantek/control.h @@ -80,6 +80,8 @@ namespace Hantek { unsigned char controlCode[CONTROLINDEX_COUNT]; ///< Request codes for control commands bool controlPending[CONTROLINDEX_COUNT]; ///< true, when the control command should be executed + short int commandVersion; ///< The used version of the commands + /// Calibration data for the channel offsets unsigned short int channelLevels[HANTEK_CHANNELS][GAIN_COUNT][OFFSET_COUNT]; @@ -107,6 +109,8 @@ namespace Hantek { QList gainSteps; ///< Voltage steps in V/screenheight public slots: + virtual void connectDevice(); + unsigned long int setSamplerate(unsigned long int samplerate); unsigned long int setBufferSize(unsigned long int size); diff --git a/openhantek/src/hantek/types.cpp b/openhantek/src/hantek/types.cpp index 8c2e5c8..7033f59 100644 --- a/openhantek/src/hantek/types.cpp +++ b/openhantek/src/hantek/types.cpp @@ -31,7 +31,7 @@ namespace Hantek { - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class CommandSetFilter /// \brief Sets the data array to the default values. CommandSetFilter::CommandSetFilter() : Helper::DataArray(8) { @@ -93,7 +93,7 @@ namespace Hantek { } - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class CommandSetTriggerAndSamplerate /// \brief Sets the data array to the default values. CommandSetTriggerAndSamplerate::CommandSetTriggerAndSamplerate() : Helper::DataArray(12) { @@ -101,24 +101,24 @@ namespace Hantek { } /// \brief Sets the data bytes to the specified values. - /// \param samplerate The samplerate value. + /// \param samplerateSlow The SamplerateSlow value. /// \param triggerPosition The trigger position value. /// \param triggerSource The trigger source id (Tsr1). - /// \param sampleSize The buffer size id (Tsr1). + /// \param bufferSize The buffer size id (Tsr1). /// \param samplerateFast The samplerateFast value (Tsr1). - /// \param usedChannel The enabled channels (Tsr2). + /// \param usedChannels The enabled channels (Tsr2). /// \param fastRate The fastRate state (Tsr2). /// \param triggerSlope The triggerSlope value (Tsr2). - CommandSetTriggerAndSamplerate::CommandSetTriggerAndSamplerate(unsigned short int samplerate, unsigned long int triggerPosition, unsigned char triggerSource, unsigned char sampleSize, unsigned char samplerateFast, unsigned char usedChannel, bool fastRate, unsigned char triggerSlope) : Helper::DataArray(12) { + CommandSetTriggerAndSamplerate::CommandSetTriggerAndSamplerate(unsigned short int samplerateSlow, unsigned long int triggerPosition, unsigned char triggerSource, unsigned char bufferSize, unsigned char samplerateFast, unsigned char usedChannels, bool fastRate, unsigned char triggerSlope) : Helper::DataArray(12) { this->init(); this->setTriggerSource(triggerSource); - this->setBufferSize(sampleSize); + this->setBufferSize(bufferSize); this->setSamplerateFast(samplerateFast); - this->setUsedChannel(usedChannel); + this->setUsedChannels(usedChannels); this->setFastRate(fastRate); this->setTriggerSlope(triggerSlope); - this->setSamplerateSlow(samplerate); + this->setSamplerateSlow(samplerateSlow); this->setTriggerPosition(triggerPosition); } @@ -134,16 +134,16 @@ namespace Hantek { ((Tsr1Bits *) &(this->array[2]))->triggerSource = value; } - /// \brief Get the sampleSize value in Tsr1Bits. - /// \return The sampleSize value. + /// \brief Get the bufferSize value in Tsr1Bits. + /// \return The #BufferSizeId value. unsigned char CommandSetTriggerAndSamplerate::getBufferSize() { - return ((Tsr1Bits *) &(this->array[2]))->sampleSize; + return ((Tsr1Bits *) &(this->array[2]))->bufferSize; } - /// \brief Set the sampleSize in Tsr1Bits to the given value. - /// \param value The new sampleSize value. + /// \brief Set the bufferSize in Tsr1Bits to the given value. + /// \param value The new #BufferSizeId value. void CommandSetTriggerAndSamplerate::setBufferSize(unsigned char value) { - ((Tsr1Bits *) &(this->array[2]))->sampleSize = value; + ((Tsr1Bits *) &(this->array[2]))->bufferSize = value; } /// \brief Get the samplerateFast value in Tsr1Bits. @@ -158,16 +158,16 @@ namespace Hantek { ((Tsr1Bits *) &(this->array[2]))->samplerateFast = value; } - /// \brief Get the usedChannel value in Tsr2Bits. - /// \return The usedChannel value. - unsigned char CommandSetTriggerAndSamplerate::getUsedChannel() { - return ((Tsr2Bits *) &(this->array[3]))->usedChannel; + /// \brief Get the usedChannels value in Tsr2Bits. + /// \return The usedChannels value. + unsigned char CommandSetTriggerAndSamplerate::getUsedChannels() { + return ((Tsr2Bits *) &(this->array[3]))->usedChannels; } - /// \brief Set the usedChannel in Tsr2Bits to the given value. - /// \param value The new usedChannel value. - void CommandSetTriggerAndSamplerate::setUsedChannel(unsigned char value) { - ((Tsr2Bits *) &(this->array[3]))->usedChannel = value; + /// \brief Set the usedChannels in Tsr2Bits to the given value. + /// \param value The new usedChannels value. + void CommandSetTriggerAndSamplerate::setUsedChannels(unsigned char value) { + ((Tsr2Bits *) &(this->array[3]))->usedChannels = value; } /// \brief Get the fastRate state in Tsr2Bits. @@ -194,14 +194,14 @@ namespace Hantek { ((Tsr2Bits *) &(this->array[3]))->triggerSlope = slope; } - /// \brief Get the Samplerate value. - /// \return The samplerate value. - unsigned short int CommandSetTriggerAndSamplerate::getSamplerate() { + /// \brief Get the SamplerateSlow value. + /// \return The SamplerateSlow value. + unsigned short int CommandSetTriggerAndSamplerate::getSamplerateSlow() { return (unsigned short int) this->array[4] | ((unsigned short int) this->array[5] << 8); } - /// \brief Set the Samplerate to the given value. - /// \param samplerate The new samplerate value. + /// \brief Set the SamplerateSlow to the given value. + /// \param samplerate The new SamplerateSlow value. void CommandSetTriggerAndSamplerate::setSamplerateSlow(unsigned short int samplerate) { this->array[4] = (unsigned char) samplerate; this->array[5] = (unsigned char) (samplerate >> 8); @@ -227,7 +227,7 @@ namespace Hantek { } - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class CommandForceTrigger /// \brief Sets the data array to needed values. CommandForceTrigger::CommandForceTrigger() : Helper::DataArray(2) { @@ -235,7 +235,7 @@ namespace Hantek { } - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class CommandCaptureStart /// \brief Sets the data array to needed values. CommandCaptureStart::CommandCaptureStart() : Helper::DataArray(2) { @@ -243,7 +243,7 @@ namespace Hantek { } - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class CommandTriggerEnabled /// \brief Sets the data array to needed values. CommandTriggerEnabled::CommandTriggerEnabled() : Helper::DataArray(2) { @@ -251,7 +251,7 @@ namespace Hantek { } - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class CommandGetData /// \brief Sets the data array to needed values. CommandGetData::CommandGetData() : Helper::DataArray(2) { @@ -259,7 +259,7 @@ namespace Hantek { } - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class CommandGetCaptureState /// \brief Sets the data array to needed values. CommandGetCaptureState::CommandGetCaptureState() : Helper::DataArray(2) { @@ -267,7 +267,7 @@ namespace Hantek { } - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class ResponseGetCaptureState /// \brief Initializes the array. ResponseGetCaptureState::ResponseGetCaptureState() : Helper::DataArray(512) { @@ -286,7 +286,7 @@ namespace Hantek { } - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class CommandSetGain /// \brief Sets the data array to needed values. CommandSetGain::CommandSetGain() : Helper::DataArray(8) { @@ -333,7 +333,7 @@ namespace Hantek { } - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class CommandSetLogicalData /// \brief Sets the data array to needed values. CommandSetLogicalData::CommandSetLogicalData() : Helper::DataArray(8) { @@ -367,7 +367,7 @@ namespace Hantek { } - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class CommandGetLogicalData /// \brief Sets the data array to needed values. CommandGetLogicalData::CommandGetLogicalData() : Helper::DataArray(2) { @@ -375,7 +375,7 @@ namespace Hantek { } - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class ControlGetSpeed /// \brief Initializes the array. ControlGetSpeed::ControlGetSpeed() : Helper::DataArray(10) { @@ -388,7 +388,7 @@ namespace Hantek { } - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class ControlBeginCommand /// \brief Sets the command index to the given value. /// \param index The CommandIndex for the command. @@ -416,7 +416,7 @@ namespace Hantek { } - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class ControlSetOffset /// \brief Sets the data array to the default values. ControlSetOffset::ControlSetOffset() : Helper::DataArray(17) { @@ -470,7 +470,7 @@ namespace Hantek { } - //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// // class ControlSetRelays /// \brief Sets all relay states. /// \param ch1Below1V Sets the state of the Channel 1 below 1 V relay. @@ -561,4 +561,235 @@ namespace Hantek { void ControlSetRelays::setTrigger(bool ext) { this->array[7] = ext ? 0xfe : 0x01; } + + + ////////////////////////////////////////////////////////////////////////////// + // class CommandSetSamplerate5200 + /// \brief Sets the data array to the default values. + CommandSetSamplerate5200::CommandSetSamplerate5200() : Helper::DataArray(6) { + this->init(); + } + + /// \brief Sets the data bytes to the specified values. + /// \param samplerateSlow The SamplerateSlow value. + /// \param samplerateFast The SamplerateFast value. + CommandSetSamplerate5200::CommandSetSamplerate5200(unsigned short int samplerateSlow, unsigned char samplerateFast) : Helper::DataArray(6) { + this->init(); + + this->setSamplerateFast(samplerateFast); + this->setSamplerateSlow(samplerateSlow); + } + + /// \brief Get the SamplerateFast value. + /// \return The SamplerateFast value. + unsigned char CommandSetSamplerate5200::getSamplerateFast() { + return this->array[4]; + } + + /// \brief Set the SamplerateFast to the given value. + /// \param value The new SamplerateFast value. + void CommandSetSamplerate5200::setSamplerateFast(unsigned char value) { + this->array[4] = value; + } + + /// \brief Get the SamplerateSlow value. + /// \return The SamplerateSlow value. + unsigned short int CommandSetSamplerate5200::getSamplerateSlow() { + return (unsigned short int) this->array[2] | ((unsigned short int) this->array[3] << 8); + } + + /// \brief Set the SamplerateSlow to the given value. + /// \param samplerate The new SamplerateSlow value. + void CommandSetSamplerate5200::setSamplerateSlow(unsigned short int samplerate) { + this->array[2] = (unsigned char) samplerate; + this->array[3] = (unsigned char) (samplerate >> 8); + } + + /// \brief Initialize the array to the needed values. + void CommandSetSamplerate5200::init() { + this->array[0] = COMMAND_SETSAMPLERATE5200; + } + + + ////////////////////////////////////////////////////////////////////////////// + // class CommandSetBuffer5200 + /// \brief Sets the data array to the default values. + CommandSetBuffer5200::CommandSetBuffer5200() : Helper::DataArray(10) { + this->init(); + } + + /// \brief Sets the data bytes to the specified values. + /// \param triggerPositionPre The TriggerPositionPre value. + /// \param triggerPositionPost The TriggerPositionPost value. + /// \param usedPre The TriggerPositionUsedPre value. + /// \param usedPost The TriggerPositionUsedPost value. + /// \param bufferSize The #BufferSizeId value. + CommandSetBuffer5200::CommandSetBuffer5200(unsigned short int triggerPositionPre, unsigned short int triggerPositionPost, unsigned char usedPre, unsigned char usedPost, unsigned char bufferSize) : Helper::DataArray(10) { + this->init(); + + this->setTriggerPositionPre(triggerPositionPre); + this->setTriggerPositionPost(triggerPositionPost); + this->setUsedPre(usedPre); + this->setUsedPost(usedPost); + this->setBufferSize(bufferSize); + } + + /// \brief Get the TriggerPositionPre value. + /// \return The TriggerPositionPre value. + unsigned short int CommandSetBuffer5200::getTriggerPositionPre() { + return (unsigned short int) this->array[2] | ((unsigned short int) this->array[3] << 8); + } + + /// \brief Set the TriggerPositionPre to the given value. + /// \param position The new TriggerPositionPre value. + void CommandSetBuffer5200::setTriggerPositionPre(unsigned short int position) { + this->array[2] = (unsigned char) position; + this->array[3] = (unsigned char) (position >> 8); + } + + /// \brief Get the TriggerPositionPost value. + /// \return The TriggerPositionPost value. + unsigned short int CommandSetBuffer5200::getTriggerPositionPost() { + return (unsigned short int) this->array[6] | ((unsigned short int) this->array[7] << 8); + } + + /// \brief Set the TriggerPositionPost to the given value. + /// \param position The new TriggerPositionPost value. + void CommandSetBuffer5200::setTriggerPositionPost(unsigned short int position) { + this->array[6] = (unsigned char) position; + this->array[7] = (unsigned char) (position >> 8); + } + + /// \brief Get the TriggerPositionUsedPre value. + /// \return The #DTriggerPositionUsed value for the pre position. + unsigned char CommandSetBuffer5200::getUsedPre() { + return this->array[4]; + } + + /// \brief Set the TriggerPositionUsedPre to the given value. + /// \param value The new #DTriggerPositionUsed value for the pre position. + void CommandSetBuffer5200::setUsedPre(unsigned char value) { + this->array[4] = value; + } + + /// \brief Get the TriggerPositionUsedPost value. + /// \return The #DTriggerPositionUsed value for the post position. + unsigned char CommandSetBuffer5200::getUsedPost() { + return ((DBufferBits *) &(this->array[8]))->triggerPositionUsed; + } + + /// \brief Set the TriggerPositionUsedPost to the given value. + /// \param value The new #DTriggerPositionUsed value for the post position. + void CommandSetBuffer5200::setUsedPost(unsigned char value) { + ((DBufferBits *) &(this->array[8]))->triggerPositionUsed = value; + } + + /// \brief Get the bufferSize value in DBufferBits. + /// \return The #BufferSizeId value. + unsigned char CommandSetBuffer5200::getBufferSize() { + return ((DBufferBits *) &(this->array[8]))->bufferSize; + } + + /// \brief Set the bufferSize in DBufferBits to the given value. + /// \param value The new #BufferSizeId value. + void CommandSetBuffer5200::setBufferSize(unsigned char value) { + ((DBufferBits *) &(this->array[8]))->bufferSize = value; + } + + /// \brief Initialize the array to the needed values. + void CommandSetBuffer5200::init() { + this->array[0] = COMMAND_SETBUFFER5200; + this->array[5] = 0xff; + this->array[9] = 0xff; + } + + + ////////////////////////////////////////////////////////////////////////////// + // class CommandSetTrigger5200 + /// \brief Sets the data array to the default values. + CommandSetTrigger5200::CommandSetTrigger5200() : Helper::DataArray(10) { + this->init(); + } + + /// \brief Sets the data bytes to the specified values. + /// \param triggerSource The trigger source id. + /// \param usedChannels The enabled channels. + /// \param fastRate The fastRate state. + /// \param triggerSlope The triggerSlope value. + /// \param triggerPulse The triggerPulse value. + CommandSetTrigger5200::CommandSetTrigger5200(unsigned char triggerSource, unsigned char usedChannels, bool fastRate, unsigned char triggerSlope, unsigned char triggerPulse) : Helper::DataArray(8) { + this->init(); + + this->setTriggerSource(triggerSource); + this->setUsedChannels(usedChannels); + this->setFastRate(fastRate); + this->setTriggerSlope(triggerSlope); + this->setTriggerPulse(triggerPulse); + } + + /// \brief Get the triggerSource value in ETsrBits. + /// \return The #TriggerSource value. + unsigned char CommandSetTrigger5200::getTriggerSource() { + return ((ETsrBits *) &(this->array[2]))->triggerSource; + } + + /// \brief Set the triggerSource in ETsrBits to the given value. + /// \param value The new #TriggerSource value. + void CommandSetTrigger5200::setTriggerSource(unsigned char value) { + ((ETsrBits *) &(this->array[2]))->triggerSource = value; + } + + /// \brief Get the usedChannels value in ETsrBits. + /// \return The #EUsedChannels value. + unsigned char CommandSetTrigger5200::getUsedChannels() { + return ((ETsrBits *) &(this->array[2]))->usedChannels; + } + + /// \brief Set the usedChannels in ETsrBits to the given value. + /// \param value The new #EUsedChannels value. + void CommandSetTrigger5200::setUsedChannels(unsigned char value) { + ((ETsrBits *) &(this->array[2]))->usedChannels = value; + } + + /// \brief Get the fastRate state in ETsrBits. + /// \return The fastRate state (Already inverted). + bool CommandSetTrigger5200::getFastRate() { + return ((ETsrBits *) &(this->array[2]))->fastRate == 0; + } + + /// \brief Set the fastRate in ETsrBits to the given state. + /// \param fastRate The new fastRate state (Automatically inverted). + void CommandSetTrigger5200::setFastRate(bool fastRate) { + ((ETsrBits *) &(this->array[2]))->fastRate = fastRate ? 0 : 1; + } + + /// \brief Get the triggerSlope value in ETsrBits. + /// \return The triggerSlope value. + unsigned char CommandSetTrigger5200::getTriggerSlope() { + return ((ETsrBits *) &(this->array[2]))->triggerSlope; + } + + /// \brief Set the triggerSlope in ETsrBits to the given value. + /// \param slope The new triggerSlope value. + void CommandSetTrigger5200::setTriggerSlope(unsigned char slope) { + ((ETsrBits *) &(this->array[2]))->triggerSlope = slope; + } + + /// \brief Get the triggerPulse state in ETsrBits. + /// \return The triggerPulse state. + bool CommandSetTrigger5200::getTriggerPulse() { + return ((ETsrBits *) &(this->array[2]))->triggerPulse == 1; + } + + /// \brief Set the triggerPulse in ETsrBits to the given state. + /// \param pulse The new triggerPulse state. + void CommandSetTrigger5200::setTriggerPulse(bool pulse) { + ((ETsrBits *) &(this->array[2]))->triggerPulse = pulse ? 1 : 0; + } + + /// \brief Initialize the array to the needed values. + void CommandSetTrigger5200::init() { + this->array[0] = COMMAND_SETTRIGGER5200; + this->array[4] = 0x02; + } } diff --git a/openhantek/src/hantek/types.h b/openhantek/src/hantek/types.h index d61b9ae..82d27d8 100644 --- a/openhantek/src/hantek/types.h +++ b/openhantek/src/hantek/types.h @@ -51,234 +51,287 @@ namespace Hantek { /// \brief All supported bulk commands. /// Indicies given in square brackets specify byte numbers in little endian format. enum CommandCode { - /// This command sets channel and trigger filter: - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
0x000x0fFilterBits0x000x000x000x000x00
+ ///

+ /// This command sets channel and trigger filter: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
0x000x0fFilterBits0x000x000x000x000x00
+ ///

COMMAND_SETFILTER, - /// This command sets trigger and timebase: - /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
0x010x00Tsr1BitsTsr2BitsSamplerateValue[0]SamplerateValue[1]
- /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
TriggerPosition[0]TriggerPosition[1]0x000x00TriggerPosition[2]0x00
- /// The samplerate is set relative to the maximum sample rate by a divider that is set in Tsr1Bits.samplerateFast and the 16-bit value in the two SamplerateValue bytes.
- /// Without using fast rate mode, the samplerate is:
- /// Samplerate = SamplerateMax / (2comp(SamplerateValue) * 2 + Tsr1Bits.samplerateFast)
- /// SamplerateMax is 50 MHz for the DSO-2090.
- /// When using fast rate mode the resulting samplerate is twice as fast, when using the large buffer it is half as fast. When Tsr1Bits.sampleSize is 0 (Roll mode) the sampling rate is divided by 1000. Setting Tsr1Bits.samplerateFast to 0 doesn't work, the result will be the same as Tsr1Bits.samplerateFast = 1. + ///

+ /// This command sets trigger and timebase: + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
0x010x00Tsr1BitsTsr2BitsSamplerateSlow[0]SamplerateSlow[1]
+ /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
TriggerPosition[0]TriggerPosition[1]0x000x00TriggerPosition[2]0x00
+ ///

+ ///

+ /// The samplerate is set relative to the maximum sample rate by a divider that is set in Tsr1Bits.samplerateFast and the 16-bit value in the two SamplerateSlow bytes.
+ /// Without using fast rate mode, the samplerate is:
+ /// Samplerate = SamplerateMax / (1comp(SamplerateSlow) * 2 + Tsr1Bits.samplerateFast)
+ /// SamplerateMax is 50 MHz for the DSO-2090.
+ /// When using fast rate mode the resulting samplerate is twice as fast, when using the large buffer it is half as fast. When Tsr1Bits.bufferSize is 0 (Roll mode) the sampling rate is divided by 1000. Setting Tsr1Bits.samplerateFast to 0 doesn't work, the result will be the same as Tsr1Bits.samplerateFast = 1. + ///

+ ///

+ /// The TriggerPosition sets the position of the pretrigger in samples. The left side (0 %) is 0x77660 when using the small buffer and 0x78000 when using the large buffer. + ///

COMMAND_SETTRIGGERANDSAMPLERATE, - /// This command forces triggering: - /// - /// - /// - /// - /// - ///
0x020x00
+ ///

+ /// This command forces triggering: + /// + /// + /// + /// + /// + ///
0x020x00
+ ///

COMMAND_FORCETRIGGER, - /// This command starts to capture data: - /// - /// - /// - /// - /// - ///
0x030x00
+ ///

+ /// This command starts to capture data: + /// + /// + /// + /// + /// + ///
0x030x00
+ ///

COMMAND_STARTSAMPLING, - /// This command sets the trigger: - /// - /// - /// - /// - /// - ///
0x040x00
+ ///

+ /// This command sets the trigger: + /// + /// + /// + /// + /// + ///
0x040x00
+ ///

COMMAND_ENABLETRIGGER, - /// This command reads data from the hardware: - /// - /// - /// - /// - /// - ///
0x050x00
- /// The oscilloscope returns the sample data, that will be split if it's larger than the IN endpoint packet length: - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
Sample[0]...Sample[511]
Sample[512]...Sample[1023]
Sample[1024]......
- /// Because of the 9 bit data model, the DSO-5200 transmits an additional MSB for each sample afterwards. + ///

+ /// This command reads data from the hardware: + /// + /// + /// + /// + /// + ///
0x050x00
+ ///

+ ///

+ /// The oscilloscope returns the sample data, that will be split if it's larger than the IN endpoint packet length: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
Sample[0]...Sample[511]
Sample[512]...Sample[1023]
Sample[1024]......
+ /// Because of the 9 bit data model, the DSO-5200 transmits an additional MSB for each sample afterwards. + ///

COMMAND_GETDATA, - /// This command checks the capture state: - /// - /// - /// - /// - /// - ///
0x060x00
- /// The oscilloscope returns it's capture state and the trigger point. Not sure about this, looks like 248 16-bit words with nearly constant values. These can be converted to the start address of the data in the buffer (See Hantek::Control::calculateTriggerPoint): - /// - /// - /// - /// - /// - /// - /// - /// - ///
#CaptureState0x00TriggerPoint[0]TriggerPoint[1]...
+ ///

+ /// This command checks the capture state: + /// + /// + /// + /// + /// + ///
0x060x00
+ ///

+ ///

+ /// The oscilloscope returns it's capture state and the trigger point. Not sure about this, looks like 248 16-bit words with nearly constant values. These can be converted to the start address of the data in the buffer (See Hantek::Control::calculateTriggerPoint): + /// + /// + /// + /// + /// + /// + /// + /// + ///
#CaptureState0x00TriggerPoint[0]TriggerPoint[1]...
+ ///

COMMAND_GETCAPTURESTATE, - /// This command sets the gain: - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
0x070x0fGainBits0x000x000x000x000x00
- /// It is usually used in combination with #CONTROL_SETRELAYS. + ///

+ /// This command sets the gain: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
0x070x0fGainBits0x000x000x000x000x00
+ /// It is usually used in combination with #CONTROL_SETRELAYS. + ///

COMMAND_SETGAIN, - /// This command sets the logical data (And what the hell is this?...): - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
0x080x0fData | 0x010x000x000x000x000x00
+ ///

+ /// This command sets the logical data (And what the hell is this?...): + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
0x080x0fData | 0x010x000x000x000x000x00
+ ///

COMMAND_SETLOGICALDATA, - /// This command reads the logical data (And what the hell is this?...): - /// - /// - /// - /// - /// - ///
0x090x00
- /// The oscilloscope returns the logical data, which is 64 or 512 bytes long: - /// - /// - /// - /// - /// - /// - /// - ///
???...
+ ///

+ /// This command reads the logical data (And what the hell is this?...): + /// + /// + /// + /// + /// + ///
0x090x00
+ ///

+ ///

+ /// The oscilloscope returns the logical data, which is 64 or 512 bytes long: + /// + /// + /// + /// + /// + /// + /// + ///
???...
+ ///

COMMAND_GETLOGICALDATA, - /// This command isn't used for the DSO-2090 and DSO-5200: - /// - /// - /// - /// - /// - ///
0x0a...
+ ///

+ /// This command isn't used for the DSO-2090 and DSO-5200: + /// + /// + /// + /// + /// + ///
0x0a...
+ ///

COMMAND_UNKNOWN_0A, - /// This command isn't used for the DSO-2090 and DSO-5200: - /// - /// - /// - /// - /// - ///
0x0b...
+ ///

+ /// This command isn't used for the DSO-2090 and DSO-5200: + /// + /// + /// + /// + /// + ///
0x0b...
+ ///

COMMAND_UNKNOWN_0B, - /// This command seems to set the sampling rate for the DSO-5200: - /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
0x0c0x00Samplerate[0] (?)Samplerate[1] (?)Tsr1.samplerateFast replacement (?)0x00
+ ///

+ /// This command sets the sampling rate for the DSO-5200: + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
0x0c0x00SamplerateSlow[0]SamplerateSlow[1]SamplerateFast0x00
+ ///

+ ///

+ /// The values are similar to the ones used on the DSO-2090. The formula is a bit different here:
+ /// Samplerate = SamplerateMax / (2comp(SamplerateSlow) * 2 + 4 - SamplerateFast)
+ /// SamplerateMax is 125 MHz for the DSO-5200 in default configuration though, the modifications regarding fast rate and buffer size are the the same that apply for the DSO-2090. + ///

COMMAND_SETSAMPLERATE5200, - /// This command seems to set trigger settings for the DSO-5200: - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
0x0d0x00UnknownUnknownTriggerPoint (?)0xffTriggerPoint (?)0xffTriggerPoint (?)0xff
- COMMAND_DSO5200_0D, + ///

+ /// This command sets the trigger position and buffer size for the DSO-5200: + /// + /// + /// + /// + /// + /// + /// + /// + ///
0x0d0x00TriggerPositionPre[0]TriggerPositionPre[1]#DTriggerPositionUsed
+ /// + /// + /// + /// + /// + /// + /// + /// + ///
0xffTriggerPositionPost[0]TriggerPositionPost[1]DBufferBits0xff
+ ///

+ ///

+ /// The TriggerPositionPre and TriggerPositionPost values set the pretrigger position. Both values have a range from 0xd7ff (0xc7ff for 14 kiS buffer) to 0xfffe. On the left side (0 %) the TriggerPositionPre value is minimal, on the right side (100 %) it is maximal. The TriggerPositionPost value is maximal for 0 % and minimal for 100%. + ///

+ COMMAND_SETBUFFER5200, - /// This command seems to set some additional settings for the DSO-5200: - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - ///
0x0e0x00Unknown0x00Unknown0x000x000x00
- COMMAND_DSO5200_0E, + ///

+ /// This command sets the channel and trigger settings for the DSO-5200: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
0x0e0x00ETsrBits0x00Unknown (0x02)0x000x000x00
+ ///

+ COMMAND_SETTRIGGER5200, COMMAND_COUNT ///< Total number of commands }; @@ -466,6 +519,7 @@ namespace Hantek { /// \brief The size of the sample buffer. enum BufferSize { BUFFER_SMALL = 10240, + BUFFER_LARGE5200 = 14336, BUFFER_LARGE = 32768 }; @@ -473,9 +527,9 @@ namespace Hantek { /// \enum BufferSizeId hantek/types.h /// \brief The size id for CommandSetTriggerAndSamplerate. enum BufferSizeId { - BUFFERID_ROLL = 0, - BUFFERID_SMALL, - BUFFERID_LARGE + BUFFERID_ROLL = 0, ///< Used for the roll mode + BUFFERID_SMALL, ///< The standard buffer with 10240 samples + BUFFERID_LARGE ///< The large buffer, 32768 samples (14336 for DSO-5200) }; ////////////////////////////////////////////////////////////////////////////// @@ -510,6 +564,22 @@ namespace Hantek { }; ////////////////////////////////////////////////////////////////////////////// + /// \enum DTriggerPositionUsed hantek/types.h + /// \brief The trigger position states for the 0x0d command. + enum DTriggerPositionUsed { + DTRIGGERPOSITION_OFF = 0, ///< Used for Roll mode + DTRIGGERPOSITION_ON = 7 ///< Used for normal operation + }; + + ////////////////////////////////////////////////////////////////////////////// + /// \enum EUsedChannels hantek/types.h + /// \brief The enabled channels in command 0x0e. + enum EUsedChannels { + EUSED_CH1 = 2, EUSED_CH2 = 3, + EUSED_CH1CH2 = 0 + }; + + ////////////////////////////////////////////////////////////////////////////// /// \struct FilterBits hantek/types.h /// \brief The bits for COMMAND_SETFILTER. struct FilterBits { @@ -520,14 +590,6 @@ namespace Hantek { }; ////////////////////////////////////////////////////////////////////////////// - /// \union FilterByte hantek/types.h - /// \brief Allows to read the FilterBits as unsigned char. - union FilterByte { - FilterBits bits; ///< Bitfield representation - unsigned char byte; ///< Full byte as unsigned char - }; - - ////////////////////////////////////////////////////////////////////////////// /// \struct GainBits hantek/types.h /// \brief The gain bits for COMMAND_SETGAIN. struct GainBits { @@ -537,46 +599,42 @@ namespace Hantek { }; ////////////////////////////////////////////////////////////////////////////// - /// \union GainByte hantek/types.h - /// \brief Allows to read the GainBits as unsigned char. - union GainByte { - GainBits bits; ///< Bitfield representation - unsigned char byte; ///< Full byte as unsigned char - }; - - ////////////////////////////////////////////////////////////////////////////// /// \struct Tsr1Bits hantek/types.h /// \brief Trigger and samplerate bits (Byte 1). struct Tsr1Bits { unsigned char triggerSource:2; ///< The trigger source, see Hantek::TriggerSource - unsigned char sampleSize:3; ///< Buffer size, 0 = Roll, 1 = 10240 S, 2 = 32768 S + unsigned char bufferSize:3; ///< See #BufferSizeId unsigned char samplerateFast:3; ///< samplerate value for fast sampling rates }; ////////////////////////////////////////////////////////////////////////////// - /// \union Tsr1Byte hantek/types.h - /// \brief Allows to read the Tsr1Bits as unsigned char. - union Tsr1Byte { - Tsr1Bits bits; ///< Bitfield representation. - unsigned char byte; ///< Full byte as unsigned char. - }; - - ////////////////////////////////////////////////////////////////////////////// /// \struct Tsr2Bits hantek/types.h /// \brief Trigger and samplerate bits (Byte 2). struct Tsr2Bits { - unsigned char usedChannel:2; ///< Used channels, see Hantek::UsedChannels + unsigned char usedChannels:2; ///< Used channels, see Hantek::UsedChannels unsigned char fastRate:1; ///< true, if one channels uses all buffers unsigned char triggerSlope:1; ///< The trigger slope, see Dso::Slope, inverted when Tsr1Bits.samplerateFast is uneven unsigned char reserved:4; ///< Unused bits }; ////////////////////////////////////////////////////////////////////////////// - /// \union Tsr2Byte hantek/types.h - /// \brief Allows to read the Tsr2Bits as unsigned char. - union Tsr2Byte { - Tsr2Bits bits; ///< Bitfield representation - unsigned char byte; ///< Full byte as unsigned char + /// \struct DBufferBits hantek/types.h + /// \brief Buffer mode bits for 0x0d command. + struct DBufferBits { + unsigned char triggerPositionUsed:3; ///< See #DTriggerPositionUsed + unsigned char bufferSize:3; ///< See #BufferSizeId + unsigned char reserved:2; ///< Unused bits + }; + + ////////////////////////////////////////////////////////////////////////////// + /// \struct ETsrBits hantek/types.h + /// \brief Trigger and samplerate bits for 0x0e command. + struct ETsrBits { + unsigned char fastRate:1; ///< false, if one channels uses all buffers + unsigned char usedChannels:2; ///< Used channels, see Hantek::EUsedChannels + unsigned char triggerSource:2; ///< The trigger source, see Hantek::TriggerSource + unsigned char triggerSlope:2; ///< The trigger slope, see Dso::Slope + unsigned char triggerPulse:1; ///< Pulses are causing trigger events }; ////////////////////////////////////////////////////////////////////////////// @@ -602,7 +660,7 @@ namespace Hantek { class CommandSetTriggerAndSamplerate : public Helper::DataArray { public: CommandSetTriggerAndSamplerate(); - CommandSetTriggerAndSamplerate(unsigned short int samplerate, unsigned long int triggerPosition, unsigned char triggerSource = 0, unsigned char sampleSize = 0, unsigned char timebaseFast = 0, unsigned char usedChannel = 0, bool fastRate = false, unsigned char triggerSlope = 0); + CommandSetTriggerAndSamplerate(unsigned short int samplerateSlow, unsigned long int triggerPosition, unsigned char triggerSource = 0, unsigned char bufferSize = 0, unsigned char samplerateFast = 0, unsigned char usedChannels = 0, bool fastRate = false, unsigned char triggerSlope = 0); unsigned char getTriggerSource(); void setTriggerSource(unsigned char value); @@ -610,13 +668,13 @@ namespace Hantek { void setBufferSize(unsigned char value); unsigned char getSamplerateFast(); void setSamplerateFast(unsigned char value); - unsigned char getUsedChannel(); - void setUsedChannel(unsigned char value); + unsigned char getUsedChannels(); + void setUsedChannels(unsigned char value); bool getFastRate(); void setFastRate(bool fastRate); unsigned char getTriggerSlope(); void setTriggerSlope(unsigned char slope); - unsigned short int getSamplerate(); + unsigned short int getSamplerateSlow(); void setSamplerateSlow(unsigned short int samplerate); unsigned long int getTriggerPosition(); void setTriggerPosition(unsigned long int position); @@ -771,6 +829,69 @@ namespace Hantek { bool getTrigger(); void setTrigger(bool ext); }; + + ////////////////////////////////////////////////////////////////////////////// + /// \class CommandSetSamplerate5200 hantek/types.h + /// \brief The COMMAND_SETSAMPLERATE5200 builder. + class CommandSetSamplerate5200 : public Helper::DataArray { + public: + CommandSetSamplerate5200(); + CommandSetSamplerate5200(unsigned short int samplerateSlow, unsigned char samplerateFast); + + unsigned char getSamplerateFast(); + void setSamplerateFast(unsigned char value); + unsigned short int getSamplerateSlow(); + void setSamplerateSlow(unsigned short int samplerate); + + private: + void init(); + }; + + ////////////////////////////////////////////////////////////////////////////// + /// \class CommandSetBuffer5200 hantek/types.h + /// \brief The COMMAND_SETBUFFER5200 builder. + class CommandSetBuffer5200 : public Helper::DataArray { + public: + CommandSetBuffer5200(); + CommandSetBuffer5200(unsigned short int triggerPositionPre, unsigned short int triggerPositionPost, unsigned char usedPre = 0, unsigned char usedPost = 0, unsigned char bufferSize = 0); + + unsigned short int getTriggerPositionPre(); + void setTriggerPositionPre(unsigned short int value); + unsigned short int getTriggerPositionPost(); + void setTriggerPositionPost(unsigned short int value); + unsigned char getUsedPre(); + void setUsedPre(unsigned char value); + unsigned char getUsedPost(); + void setUsedPost(unsigned char value); + unsigned char getBufferSize(); + void setBufferSize(unsigned char value); + + private: + void init(); + }; + + ////////////////////////////////////////////////////////////////////////////// + /// \class CommandSetTrigger5200 hantek/types.h + /// \brief The COMMAND_SETTRIGGER5200 builder. + class CommandSetTrigger5200 : public Helper::DataArray { + public: + CommandSetTrigger5200(); + CommandSetTrigger5200(unsigned char triggerSource, unsigned char usedChannels, bool fastRate = false, unsigned char triggerSlope = 0, unsigned char triggerPulse = 0); + + unsigned char getTriggerSource(); + void setTriggerSource(unsigned char value); + unsigned char getUsedChannels(); + void setUsedChannels(unsigned char value); + bool getFastRate(); + void setFastRate(bool fastRate); + unsigned char getTriggerSlope(); + void setTriggerSlope(unsigned char slope); + bool getTriggerPulse(); + void setTriggerPulse(bool pulse); + + private: + void init(); + }; } diff --git a/openhantek/src/openhantek.cpp b/openhantek/src/openhantek.cpp index b783b6f..c5a2ea2 100644 --- a/openhantek/src/openhantek.cpp +++ b/openhantek/src/openhantek.cpp @@ -129,6 +129,8 @@ OpenHantekMainWindow::OpenHantekMainWindow(QWidget *parent, Qt::WindowFlags flag connect(this->dsoControl, SIGNAL(samplingStopped()), this, SLOT(stopped())); // Set up the oscilloscope + this->dsoControl->connectDevice(); + for(unsigned int channel = 0; channel < this->settings->scope.physicalChannels; channel++) { this->dsoControl->setCoupling(channel, (Dso::Coupling) this->settings->scope.voltage[channel].misc); this->updateVoltageGain(channel); @@ -143,7 +145,6 @@ OpenHantekMainWindow::OpenHantekMainWindow(QWidget *parent, Qt::WindowFlags flag this->dsoControl->setTriggerSlope(this->settings->scope.trigger.slope); this->dsoControl->setTriggerSource(this->settings->scope.trigger.special, this->settings->scope.trigger.source); - this->dsoControl->connectDevice(); this->dsoControl->startSampling(); } -- libgit2 0.21.4