From 94f4c67e814a1de81a30c013935740dc4cc8367e Mon Sep 17 00:00:00 2001 From: Bill Wainwright <103082088+billboy111@users.noreply.github.com> Date: Mon, 21 Sep 2026 12:59:54 -0700 Subject: [PATCH 1/4] Checkpoint: working Windows LXI via NI-VISA for Rigol DHO1000 --- scopehal/CMakeLists.txt | 30 ++++++ scopehal/RigolOscilloscope.h | 1 + scopehal/SCPILxiTransport.cpp | 45 ++++++++ scopehal/SCPILxiTransport.h | 189 +++++++++++++++++----------------- 4 files changed, 173 insertions(+), 92 deletions(-) diff --git a/scopehal/CMakeLists.txt b/scopehal/CMakeLists.txt index d7790cda9..38533bd54 100644 --- a/scopehal/CMakeLists.txt +++ b/scopehal/CMakeLists.txt @@ -4,6 +4,26 @@ # Libraries specific to scopehal library not provided by root CMakeLists +if(WIN32) + # Native Windows LXI/VXI-11 support via VISA + find_path(VISA_INCLUDE_DIR + NAMES visa.h + PATHS "C:/Program Files/IVI Foundation/VISA/Win64/Include" + NO_DEFAULT_PATH) + + find_library(VISA_LIBRARY + NAMES visa64 + PATHS "C:/Program Files/IVI Foundation/VISA/Win64/Lib_x64/msc" + NO_DEFAULT_PATH) + + if(VISA_INCLUDE_DIR AND VISA_LIBRARY) + message("-- Found VISA: ${VISA_LIBRARY}") + set(VISA_FOUND TRUE) + else() + message("-- VISA not found, LXI/VXI-11 instrument support will not be available.") + endif() +endif() + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") pkg_check_modules(LXI liblxi QUIET IMPORTED_TARGET) #WORKAROUND LXI on Debian Bullseye lacks a pkgconfig file @@ -287,6 +307,16 @@ if(LXI_FOUND) ) target_compile_definitions(scopehal PUBLIC HAS_LXI) endif() +if(VISA_FOUND) + target_link_libraries(scopehal + ${VISA_LIBRARY} + ) + target_include_directories(scopehal PRIVATE + ${VISA_INCLUDE_DIR} + ) + target_compile_definitions(scopehal PUBLIC HAS_LXI HAS_VISA) +endif() + target_include_directories(scopehal PRIVATE diff --git a/scopehal/RigolOscilloscope.h b/scopehal/RigolOscilloscope.h index da7046b17..ed2c45441 100644 --- a/scopehal/RigolOscilloscope.h +++ b/scopehal/RigolOscilloscope.h @@ -163,6 +163,7 @@ class RigolOscilloscope : public virtual SCPIOscilloscope }}, {"Rigol DHO1000", { { SCPITransportType::TRANSPORT_LAN, ":5555" }, + { SCPITransportType::TRANSPORT_LXI, "" }, { SCPITransportType::TRANSPORT_USBTMC, "/dev/usbtmc" }, }}, {"Rigol DHO4000", { diff --git a/scopehal/SCPILxiTransport.cpp b/scopehal/SCPILxiTransport.cpp index 8b93140e5..f65b1c676 100644 --- a/scopehal/SCPILxiTransport.cpp +++ b/scopehal/SCPILxiTransport.cpp @@ -36,10 +36,14 @@ #ifdef HAS_LXI +#ifdef HAS_VISA +#include +#else extern "C" { #include } +#endif #include "scopehal.h" @@ -52,11 +56,14 @@ bool SCPILxiTransport::m_lxi_initialized = false; SCPILxiTransport::SCPILxiTransport(const string& args) { + m_staging_buf = nullptr; +#ifndef HAS_VISA if (!m_lxi_initialized) { lxi_init(); m_lxi_initialized = true; } +#endif char hostname[128]; unsigned int port = 0; @@ -76,6 +83,14 @@ SCPILxiTransport::SCPILxiTransport(const string& args) LogDebug("Connecting to SCPI device over VXI-11 at %s:%d\n", m_hostname.c_str(), m_port); +#ifdef HAS_VISA + m_resourceManager = VI_NULL; m_device = VI_NULL; + ViStatus status = viOpenDefaultRM(&m_resourceManager); + if(status < VI_SUCCESS) { LogError("Could not open VISA resource manager\n"); return; } + string resource = "TCPIP0::" + m_hostname + "::inst0::INSTR"; + status = viOpen(m_resourceManager, (ViRsrc)resource.c_str(), VI_NULL, 5000, &m_device); + if(status < VI_SUCCESS) { LogError("Could not open VXI-11 device through VISA\n"); viClose(m_resourceManager); m_resourceManager = VI_NULL; return; } +#else string instname = "inst0"; m_device = lxi_connect(&m_hostname[0], m_port, &instname[0], m_timeout, VXI11); @@ -84,6 +99,7 @@ SCPILxiTransport::SCPILxiTransport(const string& args) LogError("Couldn't connect to VXI-11 device\n"); return; } +#endif // When you issue a lxi_receive request, you need to specify the size of the receiving buffer. // However, when the data received is larger than this buffer, liblxi simply discards this data. @@ -104,12 +120,20 @@ SCPILxiTransport::SCPILxiTransport(const string& args) SCPILxiTransport::~SCPILxiTransport() { +#ifdef HAS_VISA + if (m_device != VI_NULL) viClose(m_device); + if (m_resourceManager != VI_NULL) viClose(m_resourceManager); +#endif delete[] m_staging_buf; } bool SCPILxiTransport::IsConnected() { +#ifdef HAS_VISA + return (m_device != VI_NULL); +#else return (m_device != LXI_ERROR); +#endif } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -131,15 +155,25 @@ bool SCPILxiTransport::SendCommand(const string& cmd) { LogTrace("Sending %s\n", cmd.c_str()); +#ifdef HAS_VISA + ViUInt32 written = 0; + ViStatus status = viWrite(m_device, (ViBuf)cmd.data(), (ViUInt32)cmd.length(), &written); + int result = (status >= VI_SUCCESS) ? 0 : -1; +#else //Need the cast when using liblxi versions prior to 63ea109 because they don't have "const" on the argument. //It doesn't actually change the inputs, so safe to cast. int result = lxi_send(m_device, const_cast(&cmd[0]), cmd.length(), m_timeout); +#endif m_data_in_staging_buf = 0; m_data_offset = 0; m_data_depleted = false; +#ifdef HAS_VISA + return (status >= VI_SUCCESS) && (written == cmd.length()); +#else return (result != LXI_ERROR); +#endif } string SCPILxiTransport::ReadReply(bool endOnSemicolon, [[maybe_unused]] function progress) @@ -169,9 +203,14 @@ void SCPILxiTransport::SendRawData(size_t len, const unsigned char* buf) { // XXX: Should this reset m_data_depleted just like SendCommmand? +#ifdef HAS_VISA + ViUInt32 written = 0; + viWrite(m_device, (ViBuf)buf, (ViUInt32)len, &written); +#else //Need the cast when using liblxi versions prior to 63ea109 because they don't have "const" on the argument. //It doesn't actually change the inputs, so safe to cast. lxi_send(m_device, const_cast(reinterpret_cast(buf)), len, m_timeout); +#endif } size_t SCPILxiTransport::ReadRawData(size_t len, unsigned char* buf, std::function /*progress*/) @@ -188,9 +227,15 @@ size_t SCPILxiTransport::ReadRawData(size_t len, unsigned char* buf, std::functi { if (m_data_in_staging_buf == 0) { +#ifdef HAS_VISA + ViUInt32 received = 0; + ViStatus status = viRead(m_device, (ViBuf)m_staging_buf, (ViUInt32)m_staging_buf_size, &received); + m_data_in_staging_buf = (status >= VI_SUCCESS) ? received : 0; +#else m_data_in_staging_buf = lxi_receive(m_device, (char *)m_staging_buf, m_staging_buf_size, m_timeout); if (m_data_in_staging_buf == LXI_ERROR) m_data_in_staging_buf = 0; +#endif m_data_offset = 0; } diff --git a/scopehal/SCPILxiTransport.h b/scopehal/SCPILxiTransport.h index 5a5bdc97b..90849f1b3 100644 --- a/scopehal/SCPILxiTransport.h +++ b/scopehal/SCPILxiTransport.h @@ -1,92 +1,97 @@ -/*********************************************************************************************************************** -* * -* 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 - @author Tom Verbeure - @brief Declaration of SCPILxiTransport - @ingroup transports - */ - -#ifdef HAS_LXI - -#ifndef SCPILxiTransport_h -#define SCPILxiTransport_h - -/** - @brief Abstraction of a transport layer for moving SCPI data between endpoints - @ingroup transports - */ -class SCPILxiTransport : public SCPITransport -{ -public: - SCPILxiTransport(const std::string& args); - virtual ~SCPILxiTransport(); - - //not copyable or assignable - SCPILxiTransport(const SCPILxiTransport&) =delete; - SCPILxiTransport& operator=(const SCPILxiTransport&) =delete; - - virtual std::string GetConnectionString() override; - static std::string GetTransportName(); - - virtual bool SendCommand(const std::string& cmd) override; - virtual std::string ReadReply(bool endOnSemicolon = true, std::function progress = nullptr) override; - virtual size_t ReadRawData(size_t len, unsigned char* buf, std::function progress = nullptr) override; - virtual void SendRawData(size_t len, const unsigned char* buf) override; - - virtual bool IsCommandBatchingSupported() override; - virtual bool IsConnected() override; - - TRANSPORT_INITPROC(SCPILxiTransport) - - const std::string& GetHostname() const - { return m_hostname; } - - virtual void FlushRXBuffer() override; - -protected: - static bool m_lxi_initialized; - - std::string m_hostname; - unsigned short m_port; - - int m_device; - int m_timeout; - - int m_staging_buf_size; - unsigned char *m_staging_buf; - int m_data_in_staging_buf; - int m_data_offset; - bool m_data_depleted; -}; - -#endif - -#endif +/*********************************************************************************************************************** +* * +* 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 + @author Tom Verbeure + @brief Declaration of SCPILxiTransport + @ingroup transports + */ + +#ifdef HAS_LXI + +#ifndef SCPILxiTransport_h +#define SCPILxiTransport_h + +/** + @brief Abstraction of a transport layer for moving SCPI data between endpoints + @ingroup transports + */ +class SCPILxiTransport : public SCPITransport +{ +public: + SCPILxiTransport(const std::string& args); + virtual ~SCPILxiTransport(); + + //not copyable or assignable + SCPILxiTransport(const SCPILxiTransport&) =delete; + SCPILxiTransport& operator=(const SCPILxiTransport&) =delete; + + virtual std::string GetConnectionString() override; + static std::string GetTransportName(); + + virtual bool SendCommand(const std::string& cmd) override; + virtual std::string ReadReply(bool endOnSemicolon = true, std::function progress = nullptr) override; + virtual size_t ReadRawData(size_t len, unsigned char* buf, std::function progress = nullptr) override; + virtual void SendRawData(size_t len, const unsigned char* buf) override; + + virtual bool IsCommandBatchingSupported() override; + virtual bool IsConnected() override; + + TRANSPORT_INITPROC(SCPILxiTransport) + + const std::string& GetHostname() const + { return m_hostname; } + + virtual void FlushRXBuffer() override; + +protected: + static bool m_lxi_initialized; + + std::string m_hostname; + unsigned short m_port; + +#ifdef HAS_VISA + unsigned long m_resourceManager; + unsigned long m_device; +#else + int m_device; +#endif + int m_timeout; + + int m_staging_buf_size; + unsigned char *m_staging_buf; + int m_data_in_staging_buf; + int m_data_offset; + bool m_data_depleted; +}; + +#endif + +#endif From 6d11ecb25118edff063ec5667965b488365d70cb Mon Sep 17 00:00:00 2001 From: Bill Wainwright <103082088+billboy111@users.noreply.github.com> Date: Mon, 21 Sep 2026 12:59:55 -0700 Subject: [PATCH 2/4] Clean up SCPILxiTransport header line endings --- scopehal/SCPILxiTransport.h | 194 ++++++++++++++++++------------------ 1 file changed, 97 insertions(+), 97 deletions(-) diff --git a/scopehal/SCPILxiTransport.h b/scopehal/SCPILxiTransport.h index 90849f1b3..9533143c3 100644 --- a/scopehal/SCPILxiTransport.h +++ b/scopehal/SCPILxiTransport.h @@ -1,97 +1,97 @@ -/*********************************************************************************************************************** -* * -* 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 - @author Tom Verbeure - @brief Declaration of SCPILxiTransport - @ingroup transports - */ - -#ifdef HAS_LXI - -#ifndef SCPILxiTransport_h -#define SCPILxiTransport_h - -/** - @brief Abstraction of a transport layer for moving SCPI data between endpoints - @ingroup transports - */ -class SCPILxiTransport : public SCPITransport -{ -public: - SCPILxiTransport(const std::string& args); - virtual ~SCPILxiTransport(); - - //not copyable or assignable - SCPILxiTransport(const SCPILxiTransport&) =delete; - SCPILxiTransport& operator=(const SCPILxiTransport&) =delete; - - virtual std::string GetConnectionString() override; - static std::string GetTransportName(); - - virtual bool SendCommand(const std::string& cmd) override; - virtual std::string ReadReply(bool endOnSemicolon = true, std::function progress = nullptr) override; - virtual size_t ReadRawData(size_t len, unsigned char* buf, std::function progress = nullptr) override; - virtual void SendRawData(size_t len, const unsigned char* buf) override; - - virtual bool IsCommandBatchingSupported() override; - virtual bool IsConnected() override; - - TRANSPORT_INITPROC(SCPILxiTransport) - - const std::string& GetHostname() const - { return m_hostname; } - - virtual void FlushRXBuffer() override; - -protected: - static bool m_lxi_initialized; - - std::string m_hostname; - unsigned short m_port; - -#ifdef HAS_VISA - unsigned long m_resourceManager; - unsigned long m_device; -#else - int m_device; -#endif - int m_timeout; - - int m_staging_buf_size; - unsigned char *m_staging_buf; - int m_data_in_staging_buf; - int m_data_offset; - bool m_data_depleted; -}; - -#endif - -#endif +/*********************************************************************************************************************** +* * +* 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 + @author Tom Verbeure + @brief Declaration of SCPILxiTransport + @ingroup transports + */ + +#ifdef HAS_LXI + +#ifndef SCPILxiTransport_h +#define SCPILxiTransport_h + +/** + @brief Abstraction of a transport layer for moving SCPI data between endpoints + @ingroup transports + */ +class SCPILxiTransport : public SCPITransport +{ +public: + SCPILxiTransport(const std::string& args); + virtual ~SCPILxiTransport(); + + //not copyable or assignable + SCPILxiTransport(const SCPILxiTransport&) =delete; + SCPILxiTransport& operator=(const SCPILxiTransport&) =delete; + + virtual std::string GetConnectionString() override; + static std::string GetTransportName(); + + virtual bool SendCommand(const std::string& cmd) override; + virtual std::string ReadReply(bool endOnSemicolon = true, std::function progress = nullptr) override; + virtual size_t ReadRawData(size_t len, unsigned char* buf, std::function progress = nullptr) override; + virtual void SendRawData(size_t len, const unsigned char* buf) override; + + virtual bool IsCommandBatchingSupported() override; + virtual bool IsConnected() override; + + TRANSPORT_INITPROC(SCPILxiTransport) + + const std::string& GetHostname() const + { return m_hostname; } + + virtual void FlushRXBuffer() override; + +protected: + static bool m_lxi_initialized; + + std::string m_hostname; + unsigned short m_port; + +#ifdef HAS_VISA + unsigned long m_resourceManager; + unsigned long m_device; +#else + int m_device; +#endif + int m_timeout; + + int m_staging_buf_size; + unsigned char *m_staging_buf; + int m_data_in_staging_buf; + int m_data_offset; + bool m_data_depleted; +}; + +#endif + +#endif From 9a6cabdf91e35beee9ff3cbb4e7b5a3971d80805 Mon Sep 17 00:00:00 2001 From: Bill Wainwright <103082088+billboy111@users.noreply.github.com> Date: Mon, 21 Sep 2026 12:59:56 -0700 Subject: [PATCH 3/4] Remove unused VISA result variable --- scopehal/SCPILxiTransport.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/scopehal/SCPILxiTransport.cpp b/scopehal/SCPILxiTransport.cpp index f65b1c676..dae3f81cb 100644 --- a/scopehal/SCPILxiTransport.cpp +++ b/scopehal/SCPILxiTransport.cpp @@ -158,7 +158,6 @@ bool SCPILxiTransport::SendCommand(const string& cmd) #ifdef HAS_VISA ViUInt32 written = 0; ViStatus status = viWrite(m_device, (ViBuf)cmd.data(), (ViUInt32)cmd.length(), &written); - int result = (status >= VI_SUCCESS) ? 0 : -1; #else //Need the cast when using liblxi versions prior to 63ea109 because they don't have "const" on the argument. //It doesn't actually change the inputs, so safe to cast. From a001ac3a32394b6b24f34e73c50e92b9edbfe88a Mon Sep 17 00:00:00 2001 From: Bill Wainwright <103082088+billboy111@users.noreply.github.com> Date: Mon, 21 Sep 2026 12:59:56 -0700 Subject: [PATCH 4/4] Improve Windows VISA library detection --- scopehal/CMakeLists.txt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/scopehal/CMakeLists.txt b/scopehal/CMakeLists.txt index 38533bd54..7326df30f 100644 --- a/scopehal/CMakeLists.txt +++ b/scopehal/CMakeLists.txt @@ -6,15 +6,22 @@ if(WIN32) # Native Windows LXI/VXI-11 support via VISA + set(VISA_SEARCH_ROOTS "C:/Program Files/IVI Foundation/VISA") + + if(DEFINED ENV{VXIPNPPATH64}) + file(TO_CMAKE_PATH "$ENV{VXIPNPPATH64}" VISA_ENV_ROOT) + list(PREPEND VISA_SEARCH_ROOTS "${VISA_ENV_ROOT}") + endif() + find_path(VISA_INCLUDE_DIR NAMES visa.h - PATHS "C:/Program Files/IVI Foundation/VISA/Win64/Include" - NO_DEFAULT_PATH) + PATHS ${VISA_SEARCH_ROOTS} + PATH_SUFFIXES Win64/Include) find_library(VISA_LIBRARY NAMES visa64 - PATHS "C:/Program Files/IVI Foundation/VISA/Win64/Lib_x64/msc" - NO_DEFAULT_PATH) + PATHS ${VISA_SEARCH_ROOTS} + PATH_SUFFIXES Win64/Lib_x64/msc) if(VISA_INCLUDE_DIR AND VISA_LIBRARY) message("-- Found VISA: ${VISA_LIBRARY}")