diff --git a/scopehal/CMakeLists.txt b/scopehal/CMakeLists.txt index 84e4a90b..3766c75e 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/Instrument.cpp b/scopehal/Instrument.cpp index 40cedee2..36920454 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 28c8e077..24a3519b 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/MockInstrument.cpp b/scopehal/MockInstrument.cpp new file mode 100644 index 00000000..0cd2920e --- /dev/null +++ b/scopehal/MockInstrument.cpp @@ -0,0 +1,128 @@ +/*********************************************************************************************************************** +* * +* 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 + */ +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); + + //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)); +} + +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 + +bool MockInstrument::IsOffline() +{ + return true; +} + +string MockInstrument::GetTransportName() +{ + return m_transportName; +} + +string MockInstrument::GetTransportConnectionString() +{ + return m_args; +} + +void MockInstrument::SetTransportConnectionString(const string& args) +{ + m_args = 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 00000000..34252a9c --- /dev/null +++ b/scopehal/MockInstrument.h @@ -0,0 +1,92 @@ +/*********************************************************************************************************************** +* * +* 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 void SetTransportConnectionString(const std::string& args); + 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); + void ClearWarnings(int version, const YAML::Node& node, IDTable& idmap, ConfigWarningList& warnings); + + // 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; + +public: + virtual std::string GetDriverName() const override + { return m_driver; } +}; + +#endif diff --git a/scopehal/MockOscilloscope.cpp b/scopehal/MockOscilloscope.cpp index 26efeb9e..64d43470 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 * @@ -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_loaders.push_front(sigc::mem_fun(*this, &MockOscilloscope::DoLoadConfiguration)); - - m_serializers.push_back(sigc::mem_fun(*this, &MockOscilloscope::DoSerializeConfiguration)); + m_preloaders.push_front(sigc::mem_fun(*this, &MockOscilloscope::DoPreLoadConfiguration)); } 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,14 +126,7 @@ bool MockOscilloscope::IsTriggerArmed() //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Serialization -void MockOscilloscope::DoSerializeConfiguration(YAML::Node& node, IDTable& /*table*/) -{ - node["transport"] = GetTransportName(); - node["args"] = GetTransportConnectionString(); - 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 f10ac582..6467910d 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 * @@ -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; @@ -126,19 +117,13 @@ 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: 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 new file mode 100644 index 00000000..75c7e850 --- /dev/null +++ b/scopehal/MockPowerSupply.cpp @@ -0,0 +1,219 @@ +/*********************************************************************************************************************** +* * +* 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 + */ +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_preloaders.push_front(sigc::mem_fun(*this, &MockPowerSupply::DoPreLoadConfiguration)); +} + +MockPowerSupply::~MockPowerSupply() +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Serialization + +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) + { + auto& cnode = it.second; + + //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); + } + + //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_enabled; + std::map 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/Oscilloscope.cpp b/scopehal/Oscilloscope.cpp index 18feb089..4041ee80 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 43825bb5..364bbb9e 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 diff --git a/scopehal/scopehal.h b/scopehal/scopehal.h index 81ffa77d..6b6e9c6c 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"