From 57499d417bf5786f1089c4cf9201b44a92f358f1 Mon Sep 17 00:00:00 2001 From: fredzo Date: Sat, 17 Jan 2026 12:23:49 +0100 Subject: [PATCH 1/9] Moved IsOffline() method at Instrument level. --- scopehal/Instrument.cpp | 5 +++++ scopehal/Instrument.h | 8 ++++++++ scopehal/Oscilloscope.cpp | 5 ----- scopehal/Oscilloscope.h | 8 -------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/scopehal/Instrument.cpp b/scopehal/Instrument.cpp index 40cedee2c..369204549 100644 --- a/scopehal/Instrument.cpp +++ b/scopehal/Instrument.cpp @@ -102,6 +102,11 @@ string Instrument::GetChannelDisplayName(size_t i) return m_channels[i]->GetHwname(); } +bool Instrument::IsOffline() +{ + return false; +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Serialization diff --git a/scopehal/Instrument.h b/scopehal/Instrument.h index 28c8e077b..24a3519b0 100644 --- a/scopehal/Instrument.h +++ b/scopehal/Instrument.h @@ -135,6 +135,14 @@ class Instrument */ virtual std::string GetTransportName() =0; + /** + @brief Checks if the instrument is currently online. + + @return False if the Instrument object is actively connected to a physical scope. + True if working offline, a file import, etc. + */ + virtual bool IsOffline(); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Channel enumeration and identification diff --git a/scopehal/Oscilloscope.cpp b/scopehal/Oscilloscope.cpp index 18feb0894..4041ee804 100644 --- a/scopehal/Oscilloscope.cpp +++ b/scopehal/Oscilloscope.cpp @@ -104,11 +104,6 @@ shared_ptr Oscilloscope::CreateOscilloscope(string driver, SCPITra //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Device properties -bool Oscilloscope::IsOffline() -{ - return false; -} - bool Oscilloscope::CanEnableChannel(size_t /*i*/) { return true; diff --git a/scopehal/Oscilloscope.h b/scopehal/Oscilloscope.h index 43825bb5d..364bbb9e6 100644 --- a/scopehal/Oscilloscope.h +++ b/scopehal/Oscilloscope.h @@ -63,14 +63,6 @@ class Oscilloscope : public virtual Instrument */ virtual std::string IDPing() =0; - /** - @brief Checks if the instrument is currently online. - - @return True if the Oscilloscope object is actively connected to a physical scope. - False if working offline, a file import, etc. - */ - virtual bool IsOffline(); - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Channel information From 625eb0c4d56c58886b606150d3bd3dcaeb6b4ecc Mon Sep 17 00:00:00 2001 From: fredzo Date: Sat, 17 Jan 2026 12:27:55 +0100 Subject: [PATCH 2/9] First step to MockInstrument and MockPowerSupply. --- scopehal/CMakeLists.txt | 2 + scopehal/MockInstrument.cpp | 117 +++++++++++++++++++ scopehal/MockInstrument.h | 93 +++++++++++++++ scopehal/MockPowerSupply.cpp | 216 +++++++++++++++++++++++++++++++++++ scopehal/MockPowerSupply.h | 107 +++++++++++++++++ scopehal/scopehal.h | 1 + 6 files changed, 536 insertions(+) create mode 100644 scopehal/MockInstrument.cpp create mode 100644 scopehal/MockInstrument.h create mode 100644 scopehal/MockPowerSupply.cpp create mode 100644 scopehal/MockPowerSupply.h diff --git a/scopehal/CMakeLists.txt b/scopehal/CMakeLists.txt index 84e4a90ba..3766c75e1 100644 --- a/scopehal/CMakeLists.txt +++ b/scopehal/CMakeLists.txt @@ -126,6 +126,7 @@ set(SCOPEHAL_SOURCES FunctionGeneratorChannel.cpp Load.cpp LoadChannel.cpp + MockInstrument.cpp Multimeter.cpp MultimeterChannel.cpp Oscilloscope.cpp @@ -173,6 +174,7 @@ set(SCOPEHAL_SOURCES LeCroyFWPOscilloscope.cpp MagnovaOscilloscope.cpp MockOscilloscope.cpp + MockPowerSupply.cpp MultiLaneBERT.cpp NanoVNA.cpp OwonXDGFunctionGenerator.cpp diff --git a/scopehal/MockInstrument.cpp b/scopehal/MockInstrument.cpp new file mode 100644 index 000000000..a88ff1bd2 --- /dev/null +++ b/scopehal/MockInstrument.cpp @@ -0,0 +1,117 @@ +/*********************************************************************************************************************** +* * +* libscopehal * +* * +* Copyright (c) 2012-2026 Andrew D. Zonenberg and contributors * +* All rights reserved. * +* * +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the * +* following conditions are met: * +* * +* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other materials provided with the distribution. * +* * +* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products * +* derived from this software without specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * +* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * +* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * +* POSSIBILITY OF SUCH DAMAGE. * +* * +***********************************************************************************************************************/ + +/** + @file + @brief Implementation of MockInstrument + + @ingroup psudrivers + */ + +#include "scopehal.h" +#include "MockInstrument.h" + +using namespace std; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Construction / destruction + +/** + @brief Initialize the driver + + @param transport SCPINullTransport object (this driver does not connect to real hardware) + */ +MockInstrument::MockInstrument(const string& name, + const string& vendor, + const string& serial, + const std::string& transport, + const std::string& driver, + const std::string& args) + : SCPIInstrument(nullptr, false) + , m_name(name) + , m_vendor(vendor) + , m_serial(serial) + , m_transportName(transport) + , m_driver(driver) + , m_args(args) +{ + // Use a null transport + m_transport = new SCPINullTransport(args); + + m_serializers.push_back(sigc::mem_fun(*this, &MockInstrument::DoSerializeConfiguration)); +} + +MockInstrument::~MockInstrument() +{ + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Information queries + +bool MockInstrument::IsOffline() +{ + return true; +} + +string MockInstrument::GetTransportName() +{ + return m_transportName; +} + +string MockInstrument::GetTransportConnectionString() +{ + return m_args; +} + +string MockInstrument::GetName() const +{ + return m_name; +} + +string MockInstrument::GetVendor() const +{ + return m_vendor; +} + +string MockInstrument::GetSerial() const +{ + return m_serial; +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Serialization + +void MockInstrument::DoSerializeConfiguration(YAML::Node& node, IDTable& /*table*/) +{ + node["transport"] = GetTransportName(); + node["args"] = GetTransportConnectionString(); + node["driver"] = GetDriverName(); +} diff --git a/scopehal/MockInstrument.h b/scopehal/MockInstrument.h new file mode 100644 index 000000000..d449b4be4 --- /dev/null +++ b/scopehal/MockInstrument.h @@ -0,0 +1,93 @@ +/*********************************************************************************************************************** +* * +* libscopehal * +* * +* Copyright (c) 2012-2026 Andrew D. Zonenberg and contributors * +* All rights reserved. * +* * +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the * +* following conditions are met: * +* * +* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other materials provided with the distribution. * +* * +* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products * +* derived from this software without specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * +* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * +* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * +* POSSIBILITY OF SUCH DAMAGE. * +* * +***********************************************************************************************************************/ + +/** + @file + @brief Declaration of MockInstrument + + @ingroup psudrivers + */ + +#ifndef MockInstrument_h +#define MockInstrument_h + +/** + @brief Base class for simulated instruments + */ +class MockInstrument: public virtual SCPIInstrument +{ +public: + MockInstrument( + const std::string& name, + const std::string& vendor, + const std::string& serial, + const std::string& transport, + const std::string& driver, + const std::string& args + ); + virtual ~MockInstrument(); + + //Device information + virtual bool IsOffline() override; + + virtual std::string GetTransportConnectionString() override; + virtual std::string GetTransportName() override; + + virtual std::string GetName() const override; + virtual std::string GetVendor() const override; + virtual std::string GetSerial() const override; + + // Serialization + void DoSerializeConfiguration(YAML::Node& node, IDTable& table); + + // SCPI + virtual void BackgroundProcessing() override {} + +protected: + + //standard *IDN? fields + std::string m_name; + std::string m_vendor; + std::string m_serial; + std::string m_fwVersion; + + //Simulated transport information + std::string m_transportName; + std::string m_driver; + std::string m_args; + + std::map m_enabled; + std::map m_names; + +public: + virtual std::string GetDriverName() const + { return m_driver; } +}; + +#endif diff --git a/scopehal/MockPowerSupply.cpp b/scopehal/MockPowerSupply.cpp new file mode 100644 index 000000000..6685d2289 --- /dev/null +++ b/scopehal/MockPowerSupply.cpp @@ -0,0 +1,216 @@ +/*********************************************************************************************************************** +* * +* libscopehal * +* * +* Copyright (c) 2012-2026 Andrew D. Zonenberg and contributors * +* All rights reserved. * +* * +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the * +* following conditions are met: * +* * +* * Redistributions of source code must retain the above copyright notice, this list of conditions, and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other materials provided with the distribution. * +* * +* * Neither the name of the author nor the names of any contributors may be used to endorse or promote products * +* derived from this software without specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * +* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * +* THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * +* POSSIBILITY OF SUCH DAMAGE. * +* * +***********************************************************************************************************************/ + +/** + @file + @brief Implementation of MockPowerSupply + + @ingroup psudrivers + */ + +#include "scopehal.h" +#include "MockPowerSupply.h" + +using namespace std; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Construction / destruction + +/** + @brief Initialize the driver + + @param transport SCPINullTransport object (this driver does not connect to real hardware) + */ +MockPowerSupply::MockPowerSupply(const string& name, + const string& vendor, + const string& serial, + const std::string& transport, + const std::string& driver, + const std::string& args) : SCPIDevice(nullptr, false), SCPIInstrument(nullptr, false), MockInstrument(name, vendor, serial, transport, driver, args) +{ + //Need to run this loader prior to the main Oscilloscope loader + m_loaders.push_front(sigc::mem_fun(*this, &MockPowerSupply::DoLoadConfiguration)); +} + +MockPowerSupply::~MockPowerSupply() +{ + +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Serialization + +void MockPowerSupply::DoLoadConfiguration(int /*version*/, const YAML::Node& node, IDTable& table) +{ + //Load the channels + auto& chans = node["channels"]; + for(auto it : chans) + { + auto& cnode = it.second; + + //if no type, it's probably not a psu channel. skip it + if(!cnode["type"]) + continue; + + //Allocate channel space if we didn't have it yet + size_t index = cnode["index"].as(); + if(m_channels.size() < (index+1)) + m_channels.resize(index+1); + + auto chan = new PowerSupplyChannel( + cnode["name"].as(), + this, + cnode["color"].as(), + index); + m_channels[index] = chan; + + //Create the channel ID + table.emplace(cnode["id"].as(), chan); + LogError("Added PSU channel with id %d\n",cnode["id"].as()); + } + + //If any of our channels are null, we're missing configuration for them in the file + //Create dummy channels so nothing segfaults + for(size_t i=0; i m_constantCurrent; + std::map m_overcurrentShutdown; + std::map m_overcurrentTripped; + std::map m_voltagesActual; + std::map m_currentsActual; + std::map m_voltagesNominal; + std::map m_currentsNominal; + std::map m_voltageSetPoints; + std::map m_currentSetPoints; + +}; + +#endif diff --git a/scopehal/scopehal.h b/scopehal/scopehal.h index 81ffa77d5..6b6e9c6c7 100644 --- a/scopehal/scopehal.h +++ b/scopehal/scopehal.h @@ -170,6 +170,7 @@ uint32_t GetComputeBlockCount(size_t numGlobal, size_t blockSize); #include "RFSignalGenerator.h" #include "RFSignalGeneratorChannel.h" #include "SCPIInstrument.h" +#include "MockInstrument.h" #include "HIDInstrument.h" #include "ModbusInstrument.h" #include "SCPIBERT.h" From a8a195166f174f89dd482ca9b0cd40c1f125cdbe Mon Sep 17 00:00:00 2001 From: fredzo Date: Sat, 17 Jan 2026 23:57:34 +0100 Subject: [PATCH 3/9] Moved channel creation to PreloadConfiguration for MockInstruments (to allow correct instrument state initialization on gui side). Fixed PSU loading. --- scopehal/MockOscilloscope.cpp | 4 ++-- scopehal/MockOscilloscope.h | 2 +- scopehal/MockPowerSupply.cpp | 14 ++++++-------- scopehal/MockPowerSupply.h | 2 +- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/scopehal/MockOscilloscope.cpp b/scopehal/MockOscilloscope.cpp index 26efeb9e0..2c50a84f5 100644 --- a/scopehal/MockOscilloscope.cpp +++ b/scopehal/MockOscilloscope.cpp @@ -59,7 +59,7 @@ MockOscilloscope::MockOscilloscope( , m_args(args) { //Need to run this loader prior to the main Oscilloscope loader - m_loaders.push_front(sigc::mem_fun(*this, &MockOscilloscope::DoLoadConfiguration)); + m_preloaders.push_front(sigc::mem_fun(*this, &MockOscilloscope::DoPreLoadConfiguration)); m_serializers.push_back(sigc::mem_fun(*this, &MockOscilloscope::DoSerializeConfiguration)); } @@ -172,7 +172,7 @@ void MockOscilloscope::DoSerializeConfiguration(YAML::Node& node, IDTable& /*tab node["driver"] = GetDriverName(); } -void MockOscilloscope::DoLoadConfiguration(int /*version*/, const YAML::Node& node, IDTable& table) +void MockOscilloscope::DoPreLoadConfiguration(int /*version*/, const YAML::Node& node, IDTable& table, ConfigWarningList& /*warnings*/) { //Load the channels auto& chans = node["channels"]; diff --git a/scopehal/MockOscilloscope.h b/scopehal/MockOscilloscope.h index f10ac5820..6223009b2 100644 --- a/scopehal/MockOscilloscope.h +++ b/scopehal/MockOscilloscope.h @@ -126,7 +126,7 @@ class MockOscilloscope : public Oscilloscope virtual unsigned int GetInstrumentTypes() const override; virtual uint32_t GetInstrumentTypesForChannel(size_t i) const override; - void DoLoadConfiguration(int version, const YAML::Node& node, IDTable& idmap); + void DoPreLoadConfiguration(int version, const YAML::Node& node, IDTable& idmap, ConfigWarningList& warnings); void DoSerializeConfiguration(YAML::Node& node, IDTable& table); protected: diff --git a/scopehal/MockPowerSupply.cpp b/scopehal/MockPowerSupply.cpp index 6685d2289..63d42d67f 100644 --- a/scopehal/MockPowerSupply.cpp +++ b/scopehal/MockPowerSupply.cpp @@ -55,29 +55,27 @@ MockPowerSupply::MockPowerSupply(const string& name, const std::string& args) : SCPIDevice(nullptr, false), SCPIInstrument(nullptr, false), MockInstrument(name, vendor, serial, transport, driver, args) { //Need to run this loader prior to the main Oscilloscope loader - m_loaders.push_front(sigc::mem_fun(*this, &MockPowerSupply::DoLoadConfiguration)); + m_preloaders.push_front(sigc::mem_fun(*this, &MockPowerSupply::DoPreLoadConfiguration)); } MockPowerSupply::~MockPowerSupply() { - + LogError("Destroying Mock Power Supply !\n"); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Serialization -void MockPowerSupply::DoLoadConfiguration(int /*version*/, const YAML::Node& node, IDTable& table) +void MockPowerSupply::DoPreLoadConfiguration(int /*version*/, const YAML::Node& node, IDTable& table, ConfigWarningList& /*warnings*/) { + LogError("Loading PSU configuration...\n"); //Load the channels auto& chans = node["channels"]; for(auto it : chans) { + LogError("Loading PSU channel...\n"); auto& cnode = it.second; - //if no type, it's probably not a psu channel. skip it - if(!cnode["type"]) - continue; - //Allocate channel space if we didn't have it yet size_t index = cnode["index"].as(); if(m_channels.size() < (index+1)) @@ -137,7 +135,7 @@ bool MockPowerSupply::SupportsOvercurrentShutdown() uint32_t MockPowerSupply::GetInstrumentTypesForChannel(size_t /*i*/) const { - return Instrument::INST_OSCILLOSCOPE; + return Instrument::INST_PSU; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/scopehal/MockPowerSupply.h b/scopehal/MockPowerSupply.h index a3949ba72..973b5f7e3 100644 --- a/scopehal/MockPowerSupply.h +++ b/scopehal/MockPowerSupply.h @@ -82,7 +82,7 @@ class MockPowerSupply : public MockInstrument, public SCPIPowerSupply void SetMasterPowerEnable(bool enable) override; // Serialization - void DoLoadConfiguration(int version, const YAML::Node& node, IDTable& idmap); + void DoPreLoadConfiguration(int version, const YAML::Node& node, IDTable& idmap, ConfigWarningList& warnings); // SCPI virtual void BackgroundProcessing() override {} From 2bfe57fb48f07ddaab0a91482358e1ed99292aab Mon Sep 17 00:00:00 2001 From: fredzo Date: Sun, 18 Jan 2026 00:33:38 +0100 Subject: [PATCH 4/9] Made Mock PSU react to settings. --- scopehal/MockPowerSupply.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scopehal/MockPowerSupply.cpp b/scopehal/MockPowerSupply.cpp index 63d42d67f..39389714c 100644 --- a/scopehal/MockPowerSupply.cpp +++ b/scopehal/MockPowerSupply.cpp @@ -148,6 +148,7 @@ bool MockPowerSupply::IsPowerConstantCurrent(int chan) double MockPowerSupply::GetPowerVoltageActual(int chan) { + if(!GetPowerChannelActive(chan)) return 0; return m_voltagesActual[chan]; } @@ -158,6 +159,7 @@ double MockPowerSupply::GetPowerVoltageNominal(int chan) double MockPowerSupply::GetPowerCurrentActual(int chan) { + if(!GetPowerChannelActive(chan)) return 0; return m_currentsActual[chan]; } @@ -190,12 +192,14 @@ void MockPowerSupply::SetPowerVoltage(int chan, double volts) { m_voltagesNominal[chan] = volts; m_voltageSetPoints[chan] = volts; + m_voltagesActual[chan] = volts; } void MockPowerSupply::SetPowerCurrent(int chan, double amps) { m_currentsNominal[chan] = amps; m_currentSetPoints[chan] = amps; + m_currentsActual[chan] = amps; } void MockPowerSupply::SetPowerChannelActive(int chan, bool on) From 6a61280d964a494110c32dda2055d587c2e61902 Mon Sep 17 00:00:00 2001 From: fredzo Date: Sun, 18 Jan 2026 10:24:11 +0100 Subject: [PATCH 5/9] Remove warnings after Mock instrument preload. --- scopehal/MockInstrument.cpp | 8 ++++++++ scopehal/MockInstrument.h | 1 + 2 files changed, 9 insertions(+) diff --git a/scopehal/MockInstrument.cpp b/scopehal/MockInstrument.cpp index a88ff1bd2..575fbcf85 100644 --- a/scopehal/MockInstrument.cpp +++ b/scopehal/MockInstrument.cpp @@ -64,6 +64,9 @@ MockInstrument::MockInstrument(const string& name, // Use a null transport m_transport = new SCPINullTransport(args); + //Clear warnings after preload for mock instruments + m_preloaders.push_back(sigc::mem_fun(*this, &MockInstrument::ClearWarnings)); + m_serializers.push_back(sigc::mem_fun(*this, &MockInstrument::DoSerializeConfiguration)); } @@ -72,6 +75,11 @@ MockInstrument::~MockInstrument() } +void MockInstrument::ClearWarnings(int /*version*/, const YAML::Node& node, IDTable& table, ConfigWarningList& warnings) +{ // No warnings necessary for Mock instruments + warnings.m_warnings.erase(this); +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Information queries diff --git a/scopehal/MockInstrument.h b/scopehal/MockInstrument.h index d449b4be4..370f9e9c1 100644 --- a/scopehal/MockInstrument.h +++ b/scopehal/MockInstrument.h @@ -65,6 +65,7 @@ class MockInstrument: public virtual SCPIInstrument // Serialization void DoSerializeConfiguration(YAML::Node& node, IDTable& table); + void ClearWarnings(int version, const YAML::Node& node, IDTable& idmap, ConfigWarningList& warnings); // SCPI virtual void BackgroundProcessing() override {} From a112c477dab84a78734f6c39d6bcc97fcaae5ca2 Mon Sep 17 00:00:00 2001 From: fredzo Date: Sun, 18 Jan 2026 11:29:17 +0100 Subject: [PATCH 6/9] Fixed CI compilation. --- scopehal/MockInstrument.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scopehal/MockInstrument.h b/scopehal/MockInstrument.h index 370f9e9c1..e709db9da 100644 --- a/scopehal/MockInstrument.h +++ b/scopehal/MockInstrument.h @@ -87,7 +87,7 @@ class MockInstrument: public virtual SCPIInstrument std::map m_names; public: - virtual std::string GetDriverName() const + virtual std::string GetDriverName() const override { return m_driver; } }; From 3cb18ba8ae1303ee08fa6098f261ede79c6ac9cc Mon Sep 17 00:00:00 2001 From: fredzo Date: Mon, 19 Jan 2026 17:28:30 +0100 Subject: [PATCH 7/9] Made MockInstrument the base class of MockOscilloscope. Added SetTrasnportConnectionString() methode to MockInstrument (to allow path edition from ManageInstrument dialog for offline instruments). Code cleanup. --- scopehal/MockInstrument.cpp | 5 ++++ scopehal/MockInstrument.h | 4 +-- scopehal/MockOscilloscope.cpp | 48 +---------------------------------- scopehal/MockOscilloscope.h | 27 +------------------- scopehal/MockPowerSupply.cpp | 4 --- scopehal/MockPowerSupply.h | 1 + 6 files changed, 9 insertions(+), 80 deletions(-) diff --git a/scopehal/MockInstrument.cpp b/scopehal/MockInstrument.cpp index 575fbcf85..4d04667b1 100644 --- a/scopehal/MockInstrument.cpp +++ b/scopehal/MockInstrument.cpp @@ -98,6 +98,11 @@ string MockInstrument::GetTransportConnectionString() return m_args; } +void MockInstrument::SetTransportConnectionString(const string& args) +{ + m_args = args; +} + string MockInstrument::GetName() const { return m_name; diff --git a/scopehal/MockInstrument.h b/scopehal/MockInstrument.h index e709db9da..34252a9c2 100644 --- a/scopehal/MockInstrument.h +++ b/scopehal/MockInstrument.h @@ -57,6 +57,7 @@ class MockInstrument: public virtual SCPIInstrument virtual bool IsOffline() override; virtual std::string GetTransportConnectionString() override; + virtual void SetTransportConnectionString(const std::string& args); virtual std::string GetTransportName() override; virtual std::string GetName() const override; @@ -83,9 +84,6 @@ class MockInstrument: public virtual SCPIInstrument std::string m_driver; std::string m_args; - std::map m_enabled; - std::map m_names; - public: virtual std::string GetDriverName() const override { return m_driver; } diff --git a/scopehal/MockOscilloscope.cpp b/scopehal/MockOscilloscope.cpp index 2c50a84f5..e4e2aa2bf 100644 --- a/scopehal/MockOscilloscope.cpp +++ b/scopehal/MockOscilloscope.cpp @@ -49,19 +49,10 @@ MockOscilloscope::MockOscilloscope( const string& serial, const std::string& transport, const std::string& driver, - const std::string& args) - : m_name(name) - , m_vendor(vendor) - , m_serial(serial) - , m_extTrigger(NULL) - , m_transport(transport) - , m_driver(driver) - , m_args(args) + const std::string& args) : SCPIDevice(nullptr, false), SCPIInstrument(nullptr, false), MockInstrument(name, vendor, serial, transport, driver, args) { //Need to run this loader prior to the main Oscilloscope loader m_preloaders.push_front(sigc::mem_fun(*this, &MockOscilloscope::DoPreLoadConfiguration)); - - m_serializers.push_back(sigc::mem_fun(*this, &MockOscilloscope::DoSerializeConfiguration)); } MockOscilloscope::~MockOscilloscope() @@ -72,26 +63,11 @@ MockOscilloscope::~MockOscilloscope() //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Information queries -bool MockOscilloscope::IsOffline() -{ - return true; -} - string MockOscilloscope::IDPing() { return ""; } -string MockOscilloscope::GetTransportName() -{ - return m_transport; -} - -string MockOscilloscope::GetTransportConnectionString() -{ - return m_args; -} - unsigned int MockOscilloscope::GetInstrumentTypes() const { return INST_OSCILLOSCOPE; @@ -102,21 +78,6 @@ uint32_t MockOscilloscope::GetInstrumentTypesForChannel(size_t /*i*/) const return Instrument::INST_OSCILLOSCOPE; } -string MockOscilloscope::GetName() const -{ - return m_name; -} - -string MockOscilloscope::GetVendor() const -{ - return m_vendor; -} - -string MockOscilloscope::GetSerial() const -{ - return m_serial; -} - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Triggering @@ -165,13 +126,6 @@ bool MockOscilloscope::IsTriggerArmed() //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Serialization -void MockOscilloscope::DoSerializeConfiguration(YAML::Node& node, IDTable& /*table*/) -{ - node["transport"] = GetTransportName(); - node["args"] = GetTransportConnectionString(); - node["driver"] = GetDriverName(); -} - void MockOscilloscope::DoPreLoadConfiguration(int /*version*/, const YAML::Node& node, IDTable& table, ConfigWarningList& /*warnings*/) { //Load the channels diff --git a/scopehal/MockOscilloscope.h b/scopehal/MockOscilloscope.h index 6223009b2..92bf02465 100644 --- a/scopehal/MockOscilloscope.h +++ b/scopehal/MockOscilloscope.h @@ -41,7 +41,7 @@ @brief Fake oscilloscope driver used for offline waveform analysis @ingroup scopedrivers */ -class MockOscilloscope : public Oscilloscope +class MockOscilloscope : public MockInstrument, public Oscilloscope { public: MockOscilloscope( @@ -54,8 +54,6 @@ class MockOscilloscope : public Oscilloscope ); virtual ~MockOscilloscope(); - virtual bool IsOffline() override; - Unit::UnitType units[7] = { Unit::UNIT_COUNTS, //Unused Unit::UNIT_VOLTS, @@ -75,13 +73,6 @@ class MockOscilloscope : public Oscilloscope virtual std::string IDPing() override; - virtual std::string GetTransportConnectionString() override; - virtual std::string GetTransportName() override; - - virtual std::string GetName() const override; - virtual std::string GetVendor() const override; - virtual std::string GetSerial() const override; - //Channel configuration virtual bool IsChannelEnabled(size_t i) override; virtual void EnableChannel(size_t i) override; @@ -133,12 +124,6 @@ class MockOscilloscope : public Oscilloscope void ArmTrigger(); - //standard *IDN? fields - std::string m_name; - std::string m_vendor; - std::string m_serial; - std::string m_fwVersion; - OscilloscopeChannel* m_extTrigger; std::map m_channelsEnabled; @@ -150,18 +135,8 @@ class MockOscilloscope : public Oscilloscope void AutoscaleVertical(); - //Simulated transport information - std::string m_transport; - std::string m_driver; - std::string m_args; - uint64_t m_sampleRate; uint64_t m_sampleDepth; - -public: - - virtual std::string GetDriverName() - { return m_driver; } }; #endif diff --git a/scopehal/MockPowerSupply.cpp b/scopehal/MockPowerSupply.cpp index 39389714c..042cfffa2 100644 --- a/scopehal/MockPowerSupply.cpp +++ b/scopehal/MockPowerSupply.cpp @@ -60,7 +60,6 @@ MockPowerSupply::MockPowerSupply(const string& name, MockPowerSupply::~MockPowerSupply() { - LogError("Destroying Mock Power Supply !\n"); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -68,12 +67,10 @@ MockPowerSupply::~MockPowerSupply() void MockPowerSupply::DoPreLoadConfiguration(int /*version*/, const YAML::Node& node, IDTable& table, ConfigWarningList& /*warnings*/) { - LogError("Loading PSU configuration...\n"); //Load the channels auto& chans = node["channels"]; for(auto it : chans) { - LogError("Loading PSU channel...\n"); auto& cnode = it.second; //Allocate channel space if we didn't have it yet @@ -90,7 +87,6 @@ void MockPowerSupply::DoPreLoadConfiguration(int /*version*/, const YAML::Node& //Create the channel ID table.emplace(cnode["id"].as(), chan); - LogError("Added PSU channel with id %d\n",cnode["id"].as()); } //If any of our channels are null, we're missing configuration for them in the file diff --git a/scopehal/MockPowerSupply.h b/scopehal/MockPowerSupply.h index 973b5f7e3..23dbb4c92 100644 --- a/scopehal/MockPowerSupply.h +++ b/scopehal/MockPowerSupply.h @@ -92,6 +92,7 @@ class MockPowerSupply : public MockInstrument, public SCPIPowerSupply protected: bool m_masterEnabled; + std::map m_enabled; std::map m_constantCurrent; std::map m_overcurrentShutdown; std::map m_overcurrentTripped; From ef023c1f1ff003f8a6b89b8f7f09b24fc465bbff Mon Sep 17 00:00:00 2001 From: fredzo Date: Mon, 19 Jan 2026 19:02:08 +0100 Subject: [PATCH 8/9] Fixed copyright/comments. --- scopehal/MockInstrument.cpp | 2 -- scopehal/MockOscilloscope.cpp | 2 +- scopehal/MockOscilloscope.h | 2 +- scopehal/MockPowerSupply.cpp | 2 -- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/scopehal/MockInstrument.cpp b/scopehal/MockInstrument.cpp index 4d04667b1..0cd2920e6 100644 --- a/scopehal/MockInstrument.cpp +++ b/scopehal/MockInstrument.cpp @@ -44,8 +44,6 @@ using namespace std; /** @brief Initialize the driver - - @param transport SCPINullTransport object (this driver does not connect to real hardware) */ MockInstrument::MockInstrument(const string& name, const string& vendor, diff --git a/scopehal/MockOscilloscope.cpp b/scopehal/MockOscilloscope.cpp index e4e2aa2bf..64d43470a 100644 --- a/scopehal/MockOscilloscope.cpp +++ b/scopehal/MockOscilloscope.cpp @@ -2,7 +2,7 @@ * * * libscopehal * * * -* Copyright (c) 2012-2024 Andrew D. Zonenberg and contributors * +* Copyright (c) 2012-2026 Andrew D. Zonenberg and contributors * * All rights reserved. * * * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the * diff --git a/scopehal/MockOscilloscope.h b/scopehal/MockOscilloscope.h index 92bf02465..6467910de 100644 --- a/scopehal/MockOscilloscope.h +++ b/scopehal/MockOscilloscope.h @@ -2,7 +2,7 @@ * * * libscopehal * * * -* Copyright (c) 2012-2024 Andrew D. Zonenberg and contributors * +* Copyright (c) 2012-2026 Andrew D. Zonenberg and contributors * * All rights reserved. * * * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the * diff --git a/scopehal/MockPowerSupply.cpp b/scopehal/MockPowerSupply.cpp index 042cfffa2..80982cde1 100644 --- a/scopehal/MockPowerSupply.cpp +++ b/scopehal/MockPowerSupply.cpp @@ -44,8 +44,6 @@ using namespace std; /** @brief Initialize the driver - - @param transport SCPINullTransport object (this driver does not connect to real hardware) */ MockPowerSupply::MockPowerSupply(const string& name, const string& vendor, From b978fa3df600078f0aad1de6fc9a9d36a19e95ea Mon Sep 17 00:00:00 2001 From: fredzo Date: Mon, 19 Jan 2026 22:03:46 +0100 Subject: [PATCH 9/9] Added capabilities loading to MockPowerSupply --- scopehal/MockPowerSupply.cpp | 15 +++++++++++---- scopehal/MockPowerSupply.h | 4 ++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/scopehal/MockPowerSupply.cpp b/scopehal/MockPowerSupply.cpp index 80982cde1..75c7e8507 100644 --- a/scopehal/MockPowerSupply.cpp +++ b/scopehal/MockPowerSupply.cpp @@ -65,6 +65,13 @@ MockPowerSupply::~MockPowerSupply() void MockPowerSupply::DoPreLoadConfiguration(int /*version*/, const YAML::Node& node, IDTable& table, ConfigWarningList& /*warnings*/) { + // Load caps + auto& caps = node["capabilities"]; + m_hasIndividualOutputSwitching = caps["individualSwitching"].as(); + m_hasMasterOutputSwitching = caps["globalSwitch"].as(); + m_hasOvercurrentShutdown = caps["overcurrentShutdown"].as(); + m_hasSoftStart = caps["softstart"].as(); + //Load the channels auto& chans = node["channels"]; for(auto it : chans) @@ -109,22 +116,22 @@ void MockPowerSupply::DoPreLoadConfiguration(int /*version*/, const YAML::Node& bool MockPowerSupply::SupportsSoftStart() { - return false; + return m_hasSoftStart; } bool MockPowerSupply::SupportsIndividualOutputSwitching() { - return true; + return m_hasIndividualOutputSwitching; } bool MockPowerSupply::SupportsMasterOutputSwitching() { - return true; + return m_hasMasterOutputSwitching; } bool MockPowerSupply::SupportsOvercurrentShutdown() { - return true; + return m_hasOvercurrentShutdown; } uint32_t MockPowerSupply::GetInstrumentTypesForChannel(size_t /*i*/) const diff --git a/scopehal/MockPowerSupply.h b/scopehal/MockPowerSupply.h index 23dbb4c92..01907329e 100644 --- a/scopehal/MockPowerSupply.h +++ b/scopehal/MockPowerSupply.h @@ -92,6 +92,10 @@ class MockPowerSupply : public MockInstrument, public SCPIPowerSupply protected: bool m_masterEnabled; + bool m_hasSoftStart; + bool m_hasIndividualOutputSwitching; + bool m_hasMasterOutputSwitching; + bool m_hasOvercurrentShutdown; std::map m_enabled; std::map m_constantCurrent; std::map m_overcurrentShutdown;