From a5e17d1429f65cd4ab4d1d46a0706f8503cf4890 Mon Sep 17 00:00:00 2001 From: fredzo <fborry@free.fr> Date: Sat, 31 Aug 2024 20:01:13 +0200 Subject: [PATCH 1/5] Fixed DHO1000 and DHO4000 detection. Fixed bandwidth calculation for DHO80x. --- scopehal/RigolOscilloscope.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/scopehal/RigolOscilloscope.cpp b/scopehal/RigolOscilloscope.cpp index 4f5129d9..07a9c109 100644 --- a/scopehal/RigolOscilloscope.cpp +++ b/scopehal/RigolOscilloscope.cpp @@ -107,16 +107,27 @@ RigolOscilloscope::RigolOscilloscope(SCPITransport* transport) m_transport->SendCommandQueued("CHAN1:BWL " + originalBandwidthLimit); } - else if(1 == sscanf(m_model.c_str(), "DHO%d", &m_modelNumber) && (m_modelNumber < 1000)) - { + else if(1 == sscanf(m_model.c_str(), "DHO%d", &m_modelNumber) && (m_modelNumber < 5000)) + { // Model numbers are : + // - DHO802 (70MHz), DHO804 (70Mhz), DHO812 (100MHz),DHO814 (100MHz) + // - DHO914/DHO914S (125MHz), DHO924/DHO924S (250MHz) + // - DHO1072 (70MHz), DHO1074 (70MHz), DHO1102 (100MHz), DHO1104 (100MHz), DHO1202 (200MHz), DHO1204 (200MHz) + // - DHO4204 (200MHz), DHO4404 (400 MHz), DHO4804 (800MHz) m_protocol = DHO; int model_multiplicator = 100; - if(m_modelNumber > 900) // special handling of DHO900 series - { + int model_modulo = 100; + if(m_modelNumber > 1000) + { // DHO1000 and 4000 + model_multiplicator = 10; + model_modulo = 1000; + } + else if(m_modelNumber > 900) + { // special handling of DHO900 series model_multiplicator = 125; } - m_bandwidth = m_modelNumber % 100 / 10 * model_multiplicator; // should also work for DHO1000/DHO4000 + m_bandwidth = m_modelNumber % model_modulo / 10 * model_multiplicator; + if(m_bandwidth == 0) m_bandwidth = 70; // Fallback for DHO80x models m_opt200M = false; // does not exist in 800/900 series } From 5112c561f68bf4f4b04119095e829a41274accc8 Mon Sep 17 00:00:00 2001 From: fredzo <fborry@free.fr> Date: Sun, 1 Sep 2024 01:32:42 +0200 Subject: [PATCH 2/5] Fixed dho support for high memory depth by using pagination. Added live mode for dho with memory depth = 1k for better performance. --- scopehal/RigolOscilloscope.cpp | 56 +++++++++++++++++++++++++++++++--- scopehal/RigolOscilloscope.h | 4 +++ 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/scopehal/RigolOscilloscope.cpp b/scopehal/RigolOscilloscope.cpp index 07a9c109..02b76650 100644 --- a/scopehal/RigolOscilloscope.cpp +++ b/scopehal/RigolOscilloscope.cpp @@ -49,6 +49,7 @@ RigolOscilloscope::RigolOscilloscope(SCPITransport* transport) , m_triggerArmed(false) , m_triggerWasLive(false) , m_triggerOneShot(false) + , m_liveMode(false) { //Last digit of the model number is the number of channels if(1 == sscanf(m_model.c_str(), "DS%d", &m_modelNumber)) @@ -664,6 +665,9 @@ void RigolOscilloscope::SetChannelOffset(size_t i, size_t /*stream*/, float offs Oscilloscope::TriggerMode RigolOscilloscope::PollTrigger() { + if(m_liveMode) + return TRIGGER_MODE_TRIGGERED; + auto stat = Trim(m_transport->SendCommandQueuedWithReply(":TRIG:STAT?")); if(stat != "STOP") @@ -719,6 +723,11 @@ bool RigolOscilloscope::AcquireData() maxpoints = 8192; // FIXME else if(m_protocol == MSO5) maxpoints = GetSampleDepth(); //You can use 250E6 points too, but it is very slow + else if(m_protocol == DHO && !m_liveMode) + { // DHO models need to set raw mode off and on again to reset the number of points according to the current memory depth + m_transport->SendCommandQueued(":WAV:MODE NORM"); + m_transport->SendCommandQueued(":WAV:MODE RAW"); + } unsigned char* temp_buf = new unsigned char[maxpoints + 1]; map<int, vector<UniformAnalogWaveform*>> pending_waveforms; for(size_t i = 0; i < m_analogChannelCount; i++) @@ -765,8 +774,12 @@ bool RigolOscilloscope::AcquireData() &yincrement, &yorigin, &yreference); + if(sec_per_sample == 0) + { // Sometimes the scope might return a null value for xincrement => replace it with a dummy value to prenvent an Arithmetic exception in WaveformArea::RasterizeAnalogOrDigitalWaveform + sec_per_sample = 0.001; + } fs_per_sample = round(sec_per_sample * FS_PER_SECOND); - //LogDebug("X: %d points, %f origin, ref %f fs/sample %ld\n", npoints, xorigin, xreference, fs_per_sample); + //LogDebug("X: %d points, %f origin, ref %f fs/sample %ld\n", (int) npoints, xorigin, xreference, (long int) fs_per_sample); //LogDebug("Y: %f inc, %f origin, %f ref\n", yincrement, yorigin, yreference); } @@ -786,7 +799,7 @@ bool RigolOscilloscope::AcquireData() //Downloading the waveform is a pain in the butt, because we can only pull 250K points at a time! (Unless you have a MSO5) for(size_t npoint = 0; npoint < npoints;) { - if(m_protocol == MSO5 || m_protocol == DHO) + if(m_protocol == MSO5) { //Ask for the data block m_transport->SendCommandQueued("*WAI"); @@ -910,8 +923,11 @@ bool RigolOscilloscope::AcquireData() } else { - m_transport->SendCommandQueued(":SING"); - m_transport->SendCommandQueued("*WAI"); + if(!m_liveMode) + { + m_transport->SendCommandQueued(":SING"); + m_transport->SendCommandQueued("*WAI"); + } } m_triggerArmed = true; } @@ -921,6 +937,15 @@ bool RigolOscilloscope::AcquireData() return true; } +void RigolOscilloscope::StopLiveMode() +{ + if(m_liveMode) + { // Stop live mode + m_transport->SendCommandQueued(":WAV:MODE RAW"); + m_liveMode = false; + } +} + void RigolOscilloscope::Start() { //LogDebug("Start single trigger\n"); @@ -929,6 +954,24 @@ void RigolOscilloscope::Start() m_transport->SendCommandQueued(":TRIG:EDGE:SWE SING"); m_transport->SendCommandQueued(":RUN"); } + else if(m_protocol == DHO) + { // Check for memory depth : if it is 1k, switch to live mode for better performance + m_mdepthValid = false; + GetSampleDepth(); + m_liveMode = (m_mdepth == 1000); + if(m_liveMode) + { + m_transport->SendCommandQueued(":WAV:MODE NORM"); + m_transport->SendCommandQueued(":RUN"); + m_transport->SendCommandQueued("*WAI"); + } + else + { + m_transport->SendCommandQueued(":WAV:MODE RAW"); + m_transport->SendCommandQueued(":SING"); + m_transport->SendCommandQueued("*WAI"); + } + } else { m_transport->SendCommandQueued(":SING"); @@ -947,6 +990,7 @@ void RigolOscilloscope::StartSingleTrigger() } else { + StopLiveMode(); m_transport->SendCommandQueued(":SING"); m_transport->SendCommandQueued("*WAI"); } @@ -957,6 +1001,7 @@ void RigolOscilloscope::StartSingleTrigger() void RigolOscilloscope::Stop() { m_transport->SendCommandQueued(":STOP"); + StopLiveMode(); m_triggerArmed = false; m_triggerOneShot = true; } @@ -964,7 +1009,10 @@ void RigolOscilloscope::Stop() void RigolOscilloscope::ForceTrigger() { if(m_protocol == DS || m_protocol == DHO) + { + StopLiveMode(); m_transport->SendCommandQueued(":TFOR"); + } else LogError("RigolOscilloscope::ForceTrigger not implemented for this model\n"); } diff --git a/scopehal/RigolOscilloscope.h b/scopehal/RigolOscilloscope.h index 3d3c21b3..982d3256 100644 --- a/scopehal/RigolOscilloscope.h +++ b/scopehal/RigolOscilloscope.h @@ -125,6 +125,8 @@ class RigolOscilloscope : public virtual SCPIOscilloscope bool m_triggerWasLive; bool m_triggerOneShot; + bool m_liveMode; + int m_modelNumber; unsigned int m_bandwidth; bool m_opt200M; @@ -133,6 +135,8 @@ class RigolOscilloscope : public virtual SCPIOscilloscope void PushEdgeTrigger(EdgeTrigger* trig); void PullEdgeTrigger(); + void StopLiveMode(); + public: static std::string GetDriverNameInternal(); OSCILLOSCOPE_INITPROC(RigolOscilloscope) From 6b11d295004cef62afcae16ab51676122ec89348 Mon Sep 17 00:00:00 2001 From: fredzo <fborry@free.fr> Date: Sun, 1 Sep 2024 11:35:00 +0200 Subject: [PATCH 3/5] Fixed live mode / memory mode switch management for dho models --- scopehal/RigolOscilloscope.cpp | 54 ++++++++++++++++++---------------- scopehal/RigolOscilloscope.h | 2 +- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/scopehal/RigolOscilloscope.cpp b/scopehal/RigolOscilloscope.cpp index 02b76650..35c3e87e 100644 --- a/scopehal/RigolOscilloscope.cpp +++ b/scopehal/RigolOscilloscope.cpp @@ -723,11 +723,7 @@ bool RigolOscilloscope::AcquireData() maxpoints = 8192; // FIXME else if(m_protocol == MSO5) maxpoints = GetSampleDepth(); //You can use 250E6 points too, but it is very slow - else if(m_protocol == DHO && !m_liveMode) - { // DHO models need to set raw mode off and on again to reset the number of points according to the current memory depth - m_transport->SendCommandQueued(":WAV:MODE NORM"); - m_transport->SendCommandQueued(":WAV:MODE RAW"); - } + unsigned char* temp_buf = new unsigned char[maxpoints + 1]; map<int, vector<UniformAnalogWaveform*>> pending_waveforms; for(size_t i = 0; i < m_analogChannelCount; i++) @@ -779,6 +775,10 @@ bool RigolOscilloscope::AcquireData() sec_per_sample = 0.001; } fs_per_sample = round(sec_per_sample * FS_PER_SECOND); + if(m_protocol == DHO) + { // DHO models return page size instead of memory depth when paginating + npoints = GetSampleDepth(); + } //LogDebug("X: %d points, %f origin, ref %f fs/sample %ld\n", (int) npoints, xorigin, xreference, (long int) fs_per_sample); //LogDebug("Y: %f inc, %f origin, %f ref\n", yincrement, yorigin, yreference); } @@ -937,12 +937,21 @@ bool RigolOscilloscope::AcquireData() return true; } -void RigolOscilloscope::StopLiveMode() +void RigolOscilloscope::PrepareStart() { - if(m_liveMode) - { // Stop live mode - m_transport->SendCommandQueued(":WAV:MODE RAW"); - m_liveMode = false; + if(m_protocol == DHO) + { + // DHO models need to set raw mode off and on again or vice versa to reset the number of points according to the current memory depth + if(m_liveMode) + { + m_transport->SendCommandQueued(":WAV:MODE RAW"); + m_transport->SendCommandQueued(":WAV:MODE NORM"); + } + else + { + m_transport->SendCommandQueued(":WAV:MODE NORM"); + m_transport->SendCommandQueued(":WAV:MODE RAW"); + } } } @@ -959,18 +968,9 @@ void RigolOscilloscope::Start() m_mdepthValid = false; GetSampleDepth(); m_liveMode = (m_mdepth == 1000); - if(m_liveMode) - { - m_transport->SendCommandQueued(":WAV:MODE NORM"); - m_transport->SendCommandQueued(":RUN"); - m_transport->SendCommandQueued("*WAI"); - } - else - { - m_transport->SendCommandQueued(":WAV:MODE RAW"); - m_transport->SendCommandQueued(":SING"); - m_transport->SendCommandQueued("*WAI"); - } + PrepareStart(); + m_transport->SendCommandQueued(m_liveMode ? ":RUN" : ":SING"); + m_transport->SendCommandQueued("*WAI"); } else { @@ -983,6 +983,9 @@ void RigolOscilloscope::Start() void RigolOscilloscope::StartSingleTrigger() { + m_liveMode = false; + m_mdepthValid = false; // Memory depth might have been changed on scope + PrepareStart(); if(m_protocol == DS_OLD) { m_transport->SendCommandQueued(":TRIG:EDGE:SWE SING"); @@ -990,7 +993,6 @@ void RigolOscilloscope::StartSingleTrigger() } else { - StopLiveMode(); m_transport->SendCommandQueued(":SING"); m_transport->SendCommandQueued("*WAI"); } @@ -1001,16 +1003,18 @@ void RigolOscilloscope::StartSingleTrigger() void RigolOscilloscope::Stop() { m_transport->SendCommandQueued(":STOP"); - StopLiveMode(); + m_liveMode = false; m_triggerArmed = false; m_triggerOneShot = true; } void RigolOscilloscope::ForceTrigger() { + m_liveMode = false; + m_mdepthValid = false; // Memory depth might have been changed on scope + PrepareStart(); if(m_protocol == DS || m_protocol == DHO) { - StopLiveMode(); m_transport->SendCommandQueued(":TFOR"); } else diff --git a/scopehal/RigolOscilloscope.h b/scopehal/RigolOscilloscope.h index 982d3256..4fe139de 100644 --- a/scopehal/RigolOscilloscope.h +++ b/scopehal/RigolOscilloscope.h @@ -135,7 +135,7 @@ class RigolOscilloscope : public virtual SCPIOscilloscope void PushEdgeTrigger(EdgeTrigger* trig); void PullEdgeTrigger(); - void StopLiveMode(); + void PrepareStart(); public: static std::string GetDriverNameInternal(); From 2c9c148d64453efd9201b689fe39b0d8e984eea4 Mon Sep 17 00:00:00 2001 From: fredzo <fborry@free.fr> Date: Sun, 1 Sep 2024 12:13:17 +0200 Subject: [PATCH 4/5] Added LogWarn on null sec_per_sample value. --- scopehal/RigolOscilloscope.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scopehal/RigolOscilloscope.cpp b/scopehal/RigolOscilloscope.cpp index 35c3e87e..600a7bbb 100644 --- a/scopehal/RigolOscilloscope.cpp +++ b/scopehal/RigolOscilloscope.cpp @@ -772,6 +772,7 @@ bool RigolOscilloscope::AcquireData() &yreference); if(sec_per_sample == 0) { // Sometimes the scope might return a null value for xincrement => replace it with a dummy value to prenvent an Arithmetic exception in WaveformArea::RasterizeAnalogOrDigitalWaveform + LogWarning("Got null sec_per_sample value from the scope, forcing it to a dummy non null value to prevent Arithmetic exception.\n"); sec_per_sample = 0.001; } fs_per_sample = round(sec_per_sample * FS_PER_SECOND); @@ -1014,9 +1015,7 @@ void RigolOscilloscope::ForceTrigger() m_mdepthValid = false; // Memory depth might have been changed on scope PrepareStart(); if(m_protocol == DS || m_protocol == DHO) - { m_transport->SendCommandQueued(":TFOR"); - } else LogError("RigolOscilloscope::ForceTrigger not implemented for this model\n"); } From 2d3df11ec35cb39b447a2dbe9632f46c215c5253 Mon Sep 17 00:00:00 2001 From: fredzo <fborry@free.fr> Date: Sun, 1 Sep 2024 22:15:51 +0200 Subject: [PATCH 5/5] Limit the use of live mode to one channel setup to prevent getting waveforms from different triggers on several channels. --- scopehal/Oscilloscope.cpp | 12 ++++++++++++ scopehal/Oscilloscope.h | 7 +++++++ scopehal/RigolOscilloscope.cpp | 14 +++++++++++--- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/scopehal/Oscilloscope.cpp b/scopehal/Oscilloscope.cpp index b2e476e0..0609a91e 100644 --- a/scopehal/Oscilloscope.cpp +++ b/scopehal/Oscilloscope.cpp @@ -119,6 +119,18 @@ bool Oscilloscope::CanEnableChannel(size_t /*i*/) return true; } +int Oscilloscope::GetEnabledChannelCount() +{ + int result = 0; + for(size_t i=0; i<GetChannelCount(); i++) + { + if(IsChannelEnabled(i)) + result++; + } + return result; +} + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Triggering helpers diff --git a/scopehal/Oscilloscope.h b/scopehal/Oscilloscope.h index da35c3b6..a6575cc6 100644 --- a/scopehal/Oscilloscope.h +++ b/scopehal/Oscilloscope.h @@ -132,6 +132,13 @@ class Oscilloscope : public virtual Instrument */ virtual void DisableChannel(size_t i) =0; + /** + @brief Returns the number of enabled channels for this oscilloscope. + + @return the number of enabled channels for this oscilloscope. + */ + int GetEnabledChannelCount(); + /** @brief Gets a channel given the hardware name */ diff --git a/scopehal/RigolOscilloscope.cpp b/scopehal/RigolOscilloscope.cpp index 600a7bbb..7ab02403 100644 --- a/scopehal/RigolOscilloscope.cpp +++ b/scopehal/RigolOscilloscope.cpp @@ -966,9 +966,17 @@ void RigolOscilloscope::Start() } else if(m_protocol == DHO) { // Check for memory depth : if it is 1k, switch to live mode for better performance - m_mdepthValid = false; - GetSampleDepth(); - m_liveMode = (m_mdepth == 1000); + // Limit live mode to one channel setup to prevent grabbing waveforms from to different triggers on seperate channels + if(GetEnabledChannelCount()==1) + { + m_mdepthValid = false; + GetSampleDepth(); + m_liveMode = (m_mdepth == 1000); + } + else + { + m_liveMode = false; + } PrepareStart(); m_transport->SendCommandQueued(m_liveMode ? ":RUN" : ":SING"); m_transport->SendCommandQueued("*WAI");