Skip to content

Commit f50f90b

Browse files
committed
Upversion to 3.1.1, doc update, robustness improvement
Signed-off-by: Martin <Ho-Ro@users.noreply.github.com>
1 parent 4ffe158 commit f50f90b

30 files changed

+579
-628
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ firmware/hex
1212
*.json
1313
*.kate-swp
1414
.directory
15+
*.autosave
1516
ui_*.h
1617
*.sh

CHANGELOG

+15
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
3.1.1
2+
2020-06-30
3+
Refresh button to restart roll mode trace
4+
Help menu link to AC modification howto
5+
Minor robustness improvements
6+
7+
3.1.1-rc3
8+
2020-06-26
9+
Real roll mode for slow sample rates
10+
11+
3.1.1-rc2
12+
2020-06-23
13+
Scroll wheel moves the markers
14+
Configuration menu parameter to use AC coupling HW modification
15+
116
3.1.1-rc1
217
2020-06-20
318
Slow timebases up to 10s/div

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ if("${CMAKE_SYSTEM}" MATCHES "Linux")
8787
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/CHANGELOG"
8888
"${CMAKE_CURRENT_SOURCE_DIR}/LICENSE"
8989
"${CMAKE_CURRENT_SOURCE_DIR}/docs/OpenHantek6022_User_Manual.pdf"
90+
"${CMAKE_CURRENT_SOURCE_DIR}/docs/HANTEK6022_AC_Modification.pdf"
9091
DESTINATION "/usr/share/doc/openhantek" COMPONENT Runtime)
9192
else()
9293
message(WARNING "Could not find doc directory (/usr/share/doc/), skipping installation of user documentation.")

docs/HANTEK6022_AC_Modification.odt

1.44 MB
Binary file not shown.

docs/HANTEK6022_AC_Modification.pdf

17.2 KB
Binary file not shown.

docs/OpenHantek6022_User_Manual.odt

-1.56 MB
Binary file not shown.

docs/OpenHantek6022_User_Manual.pdf

-1.54 MB
Binary file not shown.

docs/images/screenshot_mainwindow.png

-7.31 KB
Loading

docs/readme.md

+35-8
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ The firmware command parser:
127127
}
128128

129129
switch (cmd) {
130-
case 0xa2:
130+
case 0xa2:
131131
return eeprom();
132132

133133
case 0xe0:
@@ -165,18 +165,43 @@ The firmware command parser:
165165

166166

167167
## Data flow
168+
* The procedure `void HantekDsoControl::stateMachine()` controls the raw data capturing, conversion to real world physical values, trigger detection and timing of screen refresh. The `struct Raw` holds all important values of one sampled data block:
169+
170+
171+
struct Raw {
172+
unsigned channels = 0;
173+
double samplerate = 0;
174+
unsigned oversampling = 0;
175+
unsigned gainValue[ 2 ] = {1, 1}; // 1,2,5,10,..
176+
unsigned gainIndex[ 2 ] = {7, 7}; // index 0..7
177+
unsigned tag = 0;
178+
bool freeRun = false; // small buffer, no trigger
179+
bool valid = false; // samples can be processed
180+
bool rollMode = false; // one complete buffer received, start to roll
181+
unsigned size = 0;
182+
unsigned received = 0;
183+
std::vector< unsigned char > data;
184+
mutable QReadWriteLock lock;
185+
};
168186

169-
* Raw 8-bit ADC values are collected via call to `HantekDsoControl::getSamples(..)` (or ...getDemoSamples(..) for the demo device) in `HantekDsoControl::stateMachine()` and converted in `HantekDsoControl::convertRawDataToSamples()` to real-world double samples (scaled with voltage and sample rate).
170-
The 10X..100X oversampling for slower sample rates is done here. Also overdriving of the inputs is detected.
187+
188+
* Raw 8-bit ADC values are collected permanently via call to `HantekDsoControl::getSamples(..)` (or `...getDemoSamples(..)` for the demo device) in an own thread `Capturing::Capturing()`.
189+
At fast sample rates (>= 10 kS/s) one big block is requested via USB command to make the transfer more robust against USB interruptions by other traffic,
190+
while at slow sample rates it requests the data in small chunks to allow a permanent screen update in roll mode.
191+
* Raw values are converted in `HantekDsoControl::convertRawDataToSamples()` to real-world double samples (scaled with voltage and sample rate).
192+
The 2X..200X oversampling for slower sample rates is done here. Also overdriving of the inputs is detected.
193+
In `Roll` mode the latest sample values are always put at the end of the result buffer while older samples move toward the beginning of the buffer,
194+
this rolls the displayed trace permanently to the left.
171195
The conversion uses either the factory calibration values from EEPROM or from a user supplied config file.
172196
Read more about [calibration](https://github.com/Ho-Ro/Hantek6022API/blob/master/README.md#create-calibration-values-for-openhantek).
173-
* `searchTriggerPosition()`
174-
* which checks if the signal is triggered and calculates the starting point for a stable display.
197+
* `searchTriggerPosition()`
198+
* Checks if the signal is triggered and calculates the starting point for a stable display.
175199
The time distance to the following opposite slope is measured and displayed as pulse width in the top row.
176-
* `provideTriggeredData()` handles the trigger mode:
200+
* `provideTriggeredData()` handles the trigger mode:
177201
* If the **trigger condition is false** and the **trigger mode is Normal** then we reuse the last triggered samples so that voltage and spectrum traces as well as the measurement at the scope's bottom lines are frozen until the trigger condition becomes true again.
178202
* If the **trigger condition is false** and the **trigger mode is not Normal** then we display a free running trace and discard the last saved samples.
179-
* The converted samples are emitted to PostProcessing::input() via signal/slot:
203+
* The converted `DSOsamples` are emitted to PostProcessing::input() via signal/slot:
204+
180205
`QObject::connect( &dsoControl, &HantekDsoControl::samplesAvailable, &postProcessing, &PostProcessing::input );`
181206

182207

@@ -185,9 +210,11 @@ Read more about [calibration](https://github.com/Ho-Ro/Hantek6022API/blob/master
185210
double samplerate = 0.0; ///< The samplerate of the input data
186211
unsigned char clipped = 0; ///< Bitmask of clipped channels
187212
bool liveTrigger = false; ///< live samples are triggered
188-
unsigned triggerPosition = 0; ///< position for a triggered trace, 0 = not triggered
213+
unsigned triggeredPosition = 0; ///< position for a triggered trace, 0 = not triggered
189214
double pulseWidth1 = 0.0; ///< width from trigger point to next opposite slope
190215
double pulseWidth2 = 0.0; ///< width from next opposite slope to third slope
216+
bool freeRunning = false; ///< trigger: NONE, half sample count
217+
unsigned tag = 0; ///< track individual sample blocks (debug support)
191218
mutable QReadWriteLock lock;
192219
};
193220

openhantek/src/OH_BUILD.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
// Do not edit, will be re-created at each commit!
2-
#define OH_BUILD "20200628 build 710"
2+
#define OH_BUILD "20200630 build 712"

openhantek/src/OH_VERSION.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// define the version that is shown on top of the program
22
// if undefined (for development commits) the build will be shown by OpenHantek
33

4-
// #define OH_VERSION "3.1.1"
4+
#define OH_VERSION "3.1.1"
55

66
#ifdef OH_VERSION
77
#undef VERSION

openhantek/src/dsosettings.h

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
/// \brief Holds the settings of the program.
2020
class DsoSettings {
2121
Q_DECLARE_TR_FUNCTIONS( DsoSettings )
22+
2223
public:
2324
explicit DsoSettings( const Dso::ControlSpecification *deviceSpecification );
2425
bool setFilename( const QString &filename );

openhantek/src/hantekdso/capturing.cpp

+16-5
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ void Capturing::capture() {
8282
uint8_t sampleIndex = controlCommand->data()[ 1 ];
8383
oversampling = uint8_t( hdc->specification->fixedSampleRates[ sampleIndex ].oversampling );
8484
effectiveSamplerate = hdc->specification->fixedSampleRates[ sampleIndex ].samplerate;
85+
if ( !realSlow && effectiveSamplerate < 10e3 &&
86+
hdc->scope->trigger.mode == Dso::TriggerMode::ROLL ) { // switch to real slow rolling
87+
for ( auto it = data.begin(); it != data.end(); ++it )
88+
*it = 0x80; // fill with "zeros"
89+
QWriteLocker locker( &hdc->raw.lock );
90+
hdc->raw.rollMode = false;
91+
swap( data, hdc->raw.data ); // "clear screen"
92+
}
8593
realSlow = effectiveSamplerate < 10e3;
8694
if ( realSlow && channels != 2 ) // always switch to two channels if roll mode is possible
8795
hdc->modifyCommand< ControlSetNumChannels >( ControlCode::CONTROL_SETNUMCHANNELS )->setNumChannels( 2 );
@@ -131,6 +139,7 @@ void Capturing::capture() {
131139
for ( auto it = dp->begin(); it != end; ++it )
132140
*it = 0x80; // fill with "zeros"
133141
valid = false;
142+
hdc->raw.rollMode = false;
134143
} else {
135144
hdc->raw.rollMode = true; // one complete buffer available, start to roll
136145
}
@@ -148,15 +157,17 @@ unsigned Capturing::getRealSamples() {
148157
return 0;
149158
}
150159
// Save raw data to temporary buffer
151-
timestampDebug( QString( "Request packet %1: %2" ).arg( tag ).arg( rawSamplesize ) );
160+
timestampDebug( QString( "Request packet %1: %2 bytes" ).arg( tag ).arg( rawSamplesize ) );
152161
hdc->raw.received = 0;
153162
int retval = hdc->scopeDevice->bulkReadMulti( dp->data(), rawSamplesize, realSlow, hdc->raw.received );
154163
if ( retval < 0 ) {
164+
if ( retval == LIBUSB_ERROR_NO_DEVICE )
165+
hdc->scopeDevice->disconnectFromDevice();
155166
qWarning() << "bulkReadMulti: Getting sample data failed: " << libUsbErrorString( retval );
156167
dp->clear();
157168
return 0;
158169
}
159-
timestampDebug( QString( "Received packet %1: %2" ).arg( tag ).arg( retval ) );
170+
timestampDebug( QString( "Received packet %1: %2 bytes" ).arg( tag ).arg( retval ) );
160171
return unsigned( retval );
161172
}
162173

@@ -175,7 +186,7 @@ unsigned Capturing::getDemoSamples() {
175186
static int counter = 0;
176187
unsigned received = 0;
177188
hdc->raw.received = 0;
178-
timestampDebug( QString( "Request dummy packet %1: %2" ).arg( tag ).arg( rawSamplesize ) );
189+
timestampDebug( QString( "Request dummy packet %1: %2 bytes" ).arg( tag ).arg( rawSamplesize ) );
179190
int deltaT = 99;
180191
// deltaT (=99) defines the frequency of the dummy signals:
181192
// ch1 = 1 kHz and ch2 = 500 Hz
@@ -190,7 +201,7 @@ unsigned Capturing::getDemoSamples() {
190201
dp->resize( rawSamplesize, binaryOffset );
191202
auto end = dp->end();
192203
unsigned packet = 0;
193-
// bool couplingAC1 = hdc->scope->coupling( 0, hdc->specification ) == Dso::Coupling::AC;
204+
// bool couplingAC1 = hdc->scope->coupling( 0, hdc->specification ) == Dso::Coupling::AC; // not yet used
194205
bool couplingAC2 = hdc->scope->coupling( 1, hdc->specification ) == Dso::Coupling::AC;
195206
for ( auto it = dp->begin(); it != end; ++it ) {
196207
if ( ++counter >= deltaT ) {
@@ -218,6 +229,6 @@ unsigned Capturing::getDemoSamples() {
218229
break;
219230
}
220231
}
221-
timestampDebug( QString( "Received dummy packet %1: %2" ).arg( packet ).arg( rawSamplesize ) );
232+
timestampDebug( QString( "Received dummy packet %1: %2 bytes" ).arg( packet ).arg( rawSamplesize ) );
222233
return received;
223234
}

openhantek/src/hantekdso/capturing.h

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
class Capturing : public QThread {
88
Q_OBJECT
9+
910
public:
1011
Capturing( HantekDsoControl *hdc );
1112
void quitCapturing() { hdc->capturing = false; }

openhantek/src/hantekdso/hantekdsocontrol.cpp

+11-11
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ bool HantekDsoControl::deviceNotConnected() { return !scopeDevice->isConnected()
5555
void HantekDsoControl::restoreTargets() {
5656
// qDebug() << "restoreTargets()";
5757
if ( controlsettings.samplerate.target.samplerateSet == ControlSettingsSamplerateTarget::Samplerrate )
58-
this->setSamplerate();
58+
setSamplerate();
5959
else
60-
this->setRecordTime();
60+
setRecordTime();
6161
}
6262

6363

@@ -82,7 +82,7 @@ void HantekDsoControl::controlSetSamplerate( uint8_t sampleIndex ) {
8282
static uint8_t lastIndex = 0xFF;
8383
uint8_t id = specification->fixedSampleRates[ sampleIndex ].id;
8484
modifyCommand< ControlSetSamplerate >( ControlCode::CONTROL_SETSAMPLERATE )->setSamplerate( id, sampleIndex );
85-
if ( sampleIndex != lastIndex ) {
85+
if ( sampleIndex != lastIndex ) { // samplerate has changed, start new sampling
8686
restartSampling();
8787
}
8888
lastIndex = sampleIndex;
@@ -132,7 +132,7 @@ Dso::ErrorCode HantekDsoControl::setRecordTime( double duration ) {
132132
srLimit = ( specification->samplerate.single ).max;
133133
else
134134
srLimit = ( specification->samplerate.multi ).max;
135-
// For now - we go for the SAMPLESIZE_USED (= 20000) size sampling, defined in hantekdsocontrol.h
135+
// For now - we go for the SAMPLESIZE (= 20000) size sampling, defined in hantekdsocontrol.h
136136
// Find highest samplerate using less equal half of these samples to obtain our duration.
137137
uint8_t sampleIndex = 0;
138138
for ( uint8_t iii = 0; iii < specification->fixedSampleRates.size(); ++iii ) {
@@ -592,14 +592,8 @@ unsigned HantekDsoControl::searchTriggeredPosition() {
592592
double timeDisplay = controlsettings.samplerate.target.duration; // time for full screen width
593593
double sampleRate = result.samplerate; //
594594
double samplesDisplay = timeDisplay * controlsettings.samplerate.current;
595-
// unsigned preTrigSamples = (unsigned)(controlsettings.trigger.position * samplesDisplay);
596-
if ( sampleCount < samplesDisplay ) {
597-
// For sure not enough samples to adjust for jitter.
598-
qDebug() << "Too few samples to make a steady picture. Decrease sample rate";
599-
printf( "sampleCount %lu, timeDisplay %g, sampleRate %g, samplesDisplay %g\n", sampleCount, timeDisplay, sampleRate,
600-
samplesDisplay );
595+
if ( sampleCount < samplesDisplay ) // not enough samples to adjust for jitter.
601596
return result.triggeredPosition = 0;
602-
}
603597
// search for trigger point in a range that leaves enough samples left and right of trigger for display
604598
// find also the alternate slope after trigger point -> calculate pulse width.
605599
if ( controlsettings.trigger.slope != Dso::Slope::Both ) {
@@ -703,6 +697,12 @@ void HantekDsoControl::stateMachine() {
703697
triggered = false;
704698
result.triggeredPosition = 0;
705699
}
700+
} else { // start with correct calibration frequency
701+
static bool firstTime = true;
702+
if ( firstTime && scope ) {
703+
setCalFreq( scope->horizontal.calfreq );
704+
firstTime = false;
705+
}
706706
}
707707
delayDisplay += qMax( acquireInterval, 1 );
708708
// always run the display (slowly at t=displayInterval) to allow user interaction

openhantek/src/main.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ int main( int argc, char *argv[] ) {
163163
SelectSupportedDevice().showLibUSBFailedDialogModel( error );
164164
return -1;
165165
}
166+
if ( useLocale ) // localize USB error messages, supported: "en", "nl", "fr", "ru"
167+
libusb_setlocale( QLocale::system().name().toLocal8Bit().constData() );
168+
166169
// SelectSupportedDevive returns a real device unless demoMode is true
167170
scopeDevice = SelectSupportedDevice().showSelectDeviceModal( context );
168171
if ( scopeDevice && scopeDevice->isDemoDevice() ) {
@@ -248,6 +251,9 @@ int main( int argc, char *argv[] ) {
248251

249252
//////// Application closed, clean up step by step ////////
250253

254+
std::cout << std::unitbuf; // enable automatic flushing
255+
std::cout << "OpenHantek6022 ";
256+
251257
dsoControl.quitSampling(); // send USB control command, stop bulk transfer
252258

253259
// stop the capturing thread
@@ -257,8 +263,7 @@ int main( int argc, char *argv[] ) {
257263
capturing.requestInterruption();
258264
capturing.wait( waitForCapturing );
259265

260-
std::cout << std::unitbuf; // enable automatic flushing
261-
std::cout << "OpenHantek6022 ";
266+
std::cout << "has ";
262267

263268
// now quit the data acquisition thread
264269
// wait 2 * record time (delay is ms) for dso to finish

openhantek/src/mainwindow.cpp

+18-3
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,9 @@ MainWindow::MainWindow( HantekDsoControl *dsoControl, DsoSettings *settings, Exp
7373
ui->actionSave->setIcon( iconFont->icon( fa::save, colorMap ) );
7474
ui->actionSettings->setIcon( iconFont->icon( fa::gear, colorMap ) );
7575
ui->actionManualCommand->setIcon( iconFont->icon( fa::edit, colorMap ) );
76-
ui->actionAbout->setIcon( iconFont->icon( fa::questioncircle, colorMap ) );
7776
ui->actionUserManual->setIcon( iconFont->icon( fa::filepdfo, colorMap ) );
77+
ui->actionACmodification->setIcon( iconFont->icon( fa::filepdfo, colorMap ) );
78+
ui->actionAbout->setIcon( iconFont->icon( fa::questioncircle, colorMap ) );
7879

7980
// Window title
8081
setWindowIcon( QIcon( ":/images/OpenHantek.svg" ) );
@@ -193,8 +194,12 @@ MainWindow::MainWindow( HantekDsoControl *dsoControl, DsoSettings *settings, Exp
193194

194195
connect( triggerDock, &TriggerDock::modeChanged, dsoControl, &HantekDsoControl::setTriggerMode );
195196
connect( triggerDock, &TriggerDock::modeChanged, dsoWidget, &DsoWidget::updateTriggerMode );
196-
connect( triggerDock, &TriggerDock::modeChanged,
197-
[this]( Dso::TriggerMode mode ) { ui->actionRefresh->setEnabled( Dso::TriggerMode::ROLL == mode ); } );
197+
connect( triggerDock, &TriggerDock::modeChanged, [this]( Dso::TriggerMode mode ) {
198+
ui->actionRefresh->setEnabled( Dso::TriggerMode::ROLL == mode && dsoSettings->scope.horizontal.samplerate < 10e3 );
199+
} );
200+
connect( dsoControl, &HantekDsoControl::samplerateChanged, [this]( double samplerate ) {
201+
ui->actionRefresh->setEnabled( Dso::TriggerMode::ROLL == dsoSettings->scope.trigger.mode && samplerate < 10e3 );
202+
} );
198203
connect( triggerDock, &TriggerDock::sourceChanged, dsoControl, &HantekDsoControl::setTriggerSource );
199204
connect( triggerDock, &TriggerDock::sourceChanged, dsoWidget, &DsoWidget::updateTriggerSource );
200205
connect( triggerDock, &TriggerDock::slopeChanged, dsoControl, &HantekDsoControl::setTriggerSlope );
@@ -378,6 +383,16 @@ MainWindow::MainWindow( HantekDsoControl *dsoControl, DsoSettings *settings, Exp
378383
QUrl( "https://github.com/OpenHantek/OpenHantek6022/blob/master/docs/OpenHantek6022_User_Manual.pdf" ) );
379384
} );
380385

386+
connect( ui->actionACmodification, &QAction::triggered, []() {
387+
QString ACmodPath( AC_MODIFICATION_PATH );
388+
QFile ACmod( ACmodPath );
389+
if ( ACmod.exists() )
390+
QDesktopServices::openUrl( QUrl( "file://" + ACmodPath ) );
391+
else
392+
QDesktopServices::openUrl(
393+
QUrl( "https://github.com/OpenHantek/OpenHantek6022/blob/master/docs/HANTEK6022_AC_Modification.pdf" ) );
394+
} );
395+
381396
connect( ui->actionAbout, &QAction::triggered, [this]() {
382397
QMessageBox::about(
383398
this, tr( "About OpenHantek6022 (%1)" ).arg( VERSION ),

openhantek/src/mainwindow.ui

+6
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
<string>&amp;Help</string>
6060
</property>
6161
<addaction name="actionUserManual"/>
62+
<addaction name="actionACmodification"/>
6263
<addaction name="actionAbout"/>
6364
</widget>
6465
<widget class="QMenu" name="menuExport">
@@ -205,6 +206,11 @@
205206
<string>&amp;Manual command</string>
206207
</property>
207208
</action>
209+
<action name="actionACmodification">
210+
<property name="text">
211+
<string>AC &amp;Modification</string>
212+
</property>
213+
</action>
208214
</widget>
209215
<resources/>
210216
<connections/>

openhantek/src/post/mathchannelgenerator.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ struct DsoSettingsScope;
88
class PPresult;
99

1010
class MathChannelGenerator : public Processor {
11+
1112
public:
1213
MathChannelGenerator( const DsoSettingsScope *scope, unsigned physicalChannels );
13-
virtual ~MathChannelGenerator() override;
14+
~MathChannelGenerator() override;
1415
void process( PPresult * ) override;
1516

1617
private:

openhantek/src/post/spectrumgenerator.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ struct DsoSettingsScope;
2222
/// Calculates the spectrum and various data about the signal and saves the
2323
/// time-/frequencysteps between two values.
2424
class SpectrumGenerator : public Processor {
25+
2526
public:
2627
SpectrumGenerator( const DsoSettingsScope *scope, const DsoSettingsPostProcessing *postprocessing );
27-
virtual ~SpectrumGenerator() override;
28+
~SpectrumGenerator() override;
2829

2930
private:
3031
const DsoSettingsScope *scope;

0 commit comments

Comments
 (0)