From aef1b1e0a40d0ef1cb3c61e47e9b07e043fcf07f Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Mon, 2 Oct 2023 16:41:19 -0400 Subject: [PATCH 01/91] Adding project from initial meeting --- .../ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj | 106 ++++++++++++++ .../ThorlabsCHROLIS.vcxproj.filters | 27 ++++ .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 25 ++++ .../ThorlabsCHROLIS/ThorlabsChrolis.h | 138 ++++++++++++++++++ micromanager.sln | 6 + 5 files changed, 302 insertions(+) create mode 100644 DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj create mode 100644 DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj.filters create mode 100644 DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp create mode 100644 DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj new file mode 100644 index 000000000..1fdc18c60 --- /dev/null +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj @@ -0,0 +1,106 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + {b8c95f39-54bf-40a9-807b-598df2821d55} + + + + 16.0 + Win32Proj + {f93128a5-b344-4662-bfb8-b4caecf1fe52} + ThorlabsCHROLIS + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + true + + + false + + + + true + _DEBUG;THORLABSCHROLIS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + pch.h + C:\Program Files\IVI Foundation\VISA\Win64\Include;%(AdditionalIncludeDirectories) + + + Windows + true + false + C:\Program Files\IVI Foundation\VISA\Win64\Lib_x64\msc;%(AdditionalLibraryDirectories) + TL6WL_64.lib;%(AdditionalDependencies) + + + + + true + true + true + NDEBUG;THORLABSCHROLIS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + pch.h + C:\Program Files\IVI Foundation\VISA\Win64\Include;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + false + C:\Program Files\IVI Foundation\VISA\Win64\Lib_x64\msc;%(AdditionalLibraryDirectories) + TL6WL_64.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj.filters b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj.filters new file mode 100644 index 000000000..d86ca4679 --- /dev/null +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp new file mode 100644 index 000000000..91ebf03f3 --- /dev/null +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -0,0 +1,25 @@ +#include "ThorlabsChrolis.h" +#include "ModuleInterface.h" + +#include + +MODULE_API void InitializeModuleData() { + RegisterDevice(CHROLIS_SHUTTER_NAME, // deviceName: model identifier and default device label + MM::ShutterDevice, + "Thorlabs CHROLIS Shutter"); // description +} + +MODULE_API MM::Device* CreateDevice(char const* name) { + if (!name) + return nullptr; + + if (name == std::string(CHROLIS_SHUTTER_NAME)) + return new ChrolisShutter(); + + return nullptr; +} + + +MODULE_API void DeleteDevice(MM::Device* device) { + delete device; +} \ No newline at end of file diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h new file mode 100644 index 000000000..1adba8749 --- /dev/null +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -0,0 +1,138 @@ +#pragma once +#include +#include "DeviceBase.h" +#define CHROLIS_SHUTTER_NAME "CHROLIS_Shutter" + +class ChrolisShutter : public CShutterBase //CRTP +{ + ViSession deviceHandle_ = -1; + ViBoolean savedEnabledStates[6]{ false,false,false,false,false,false}; + ViUInt16 powerStates[6]{0,0,1000,0,0,0}; + bool connected = false; + bool masterShutterState = false; + +public: + ChrolisShutter() + { + } + ~ChrolisShutter() {} + + int Initialize() + { + int err = 0; + ViUInt32 numDevices; + CDeviceUtils::SleepMs(2000); + err = TL6WL_findRsrc(NULL, &numDevices); + if (err != 0) + { + LogMessage("Find Resource Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + if (numDevices == 0) + { + LogMessage("Chrolis devices not found"); // to log file + return DEVICE_ERR; + } + + ViChar resource[512] = ""; + err = TL6WL_getRsrcName(NULL, 0, resource); + if (err != 0) + { + LogMessage("Get Resource Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + + err = TL6WL_init(resource, false, false, &deviceHandle_); + if (err != 0) + { + LogMessage("Initialize Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + connected = true; + + err = TL6WL_getLED_HeadPowerStates(deviceHandle_, &savedEnabledStates[0], &savedEnabledStates[1], &savedEnabledStates[2], &savedEnabledStates[3], &savedEnabledStates[4], &savedEnabledStates[5]); + if (err != 0) + { + LogMessage("Get Enable States Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + + err = TL6WL_getLED_HeadBrightness(deviceHandle_, &powerStates[0], &powerStates[1], &powerStates[2], &powerStates[3], &powerStates[4], &powerStates[5]); + if (err != 0) + { + LogMessage("Get Power States Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + + err = TL6WL_setLED_HeadBrightness(deviceHandle_, powerStates[0], powerStates[1], powerStates[2], powerStates[3], powerStates[4], powerStates[5]); + if (err != 0) + { + LogMessage("Set Power States Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + + return DEVICE_OK; + } + + int Shutdown() + { + if (connected) + { + auto err = TL6WL_close(deviceHandle_); + if (err != 0) + { + LogMessage("Close Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + connected = false; + CDeviceUtils::SleepMs(1000); + } + return DEVICE_OK; + } + + void GetName(char* name) const + { + CDeviceUtils::CopyLimitedString(name, CHROLIS_SHUTTER_NAME); + } + + bool Busy() + { + return false; + } + + // Shutter API + int SetOpen(bool open = true) + { + if (!open) + { + if (int err = TL6WL_setLED_HeadPowerStates(deviceHandle_, false, false, false, false, false, false) != 0) + { + LogMessage("Get Enable States Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + masterShutterState = false; + } + else + { + if (int err = TL6WL_setLED_HeadPowerStates(deviceHandle_, true, true, true, true, true, true) != 0) + { + LogMessage("Get Enable States Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + masterShutterState = true; + } + return DEVICE_OK; + } + + int GetOpen(bool& open) + { + open = masterShutterState; + return DEVICE_OK; + } + + int Fire(double /*deltaT*/) + { + return DEVICE_UNSUPPORTED_COMMAND; + } +}; + diff --git a/micromanager.sln b/micromanager.sln index 0874f84bf..7d3a419fb 100644 --- a/micromanager.sln +++ b/micromanager.sln @@ -476,6 +476,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ESP32", "DeviceAdapters\ESP EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WOSM", "DeviceAdapters\WOSM\WOSM.vcxproj", "{64E94A9E-B3AE-47EF-8F5A-0356B0E6B9DA}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ThorlabsCHROLIS", "DeviceAdapters\ThorlabsCHROLIS\ThorlabsCHROLIS.vcxproj", "{F93128A5-B344-4662-BFB8-B4CAECF1FE52}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -1430,6 +1432,10 @@ Global {64E94A9E-B3AE-47EF-8F5A-0356B0E6B9DA}.Debug|x64.Build.0 = Debug|x64 {64E94A9E-B3AE-47EF-8F5A-0356B0E6B9DA}.Release|x64.ActiveCfg = Release|x64 {64E94A9E-B3AE-47EF-8F5A-0356B0E6B9DA}.Release|x64.Build.0 = Release|x64 + {F93128A5-B344-4662-BFB8-B4CAECF1FE52}.Debug|x64.ActiveCfg = Debug|x64 + {F93128A5-B344-4662-BFB8-B4CAECF1FE52}.Debug|x64.Build.0 = Debug|x64 + {F93128A5-B344-4662-BFB8-B4CAECF1FE52}.Release|x64.ActiveCfg = Release|x64 + {F93128A5-B344-4662-BFB8-B4CAECF1FE52}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 59fe0b6b6b53937c1add75ec7c9f391e88f8260a Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Fri, 6 Oct 2023 16:48:10 -0400 Subject: [PATCH 02/91] Updated chrolis adapter with new class definitions and structure --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 66 ++++++++++++++++- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 73 +++++++++++++++++++ 2 files changed, 136 insertions(+), 3 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 91ebf03f3..653e119a1 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -4,22 +4,82 @@ #include MODULE_API void InitializeModuleData() { - RegisterDevice(CHROLIS_SHUTTER_NAME, // deviceName: model identifier and default device label - MM::ShutterDevice, - "Thorlabs CHROLIS Shutter"); // description + RegisterDevice(CHROLIS_HUB_NAME, // deviceName: model identifier and default device label + MM::HubDevice, + "Thorlabs CHROLIS Hub"); // description + RegisterDevice(CHROLIS_SHUTTER_NAME, + MM::ShutterDevice, + "Thorlabs CHROLIS Shutter"); + RegisterDevice(CHROLIS_STATE_NAME, + MM::StateDevice, + "Thorlabs CHROLIS Enable State"); + RegisterDevice(CHROLIS_GENERIC_DEVICE_NAME, + MM::GenericDevice, + "Thorlabs CHROLIS Power Control"); } MODULE_API MM::Device* CreateDevice(char const* name) { if (!name) return nullptr; + if (name == std::string(CHROLIS_HUB_NAME)) + return new ChrolisHub(); + if (name == std::string(CHROLIS_SHUTTER_NAME)) return new ChrolisShutter(); + if (name == std::string(CHROLIS_STATE_NAME)) + return new ChrolisStateDevice(); + + if (name == std::string(CHROLIS_GENERIC_DEVICE_NAME)) + return new ChrolisPowerControl(); + return nullptr; } MODULE_API void DeleteDevice(MM::Device* device) { delete device; +} + +int ChrolisHub::DetectInstalledDevices() +{ + ClearInstalledDevices(); + + // make sure this method is called before we look for available devices + InitializeModuleData(); + + char hubName[MM::MaxStrLength]; + GetName(hubName); // this device name + for (unsigned i = 0; i < GetNumberOfDevices(); i++) + { + char deviceName[MM::MaxStrLength]; + bool success = GetDeviceName(i, deviceName, MM::MaxStrLength); + if (success && (strcmp(hubName, deviceName) != 0)) + { + MM::Device* pDev = CreateDevice(deviceName); + AddInstalledDevice(pDev); + } + } + return DEVICE_OK; +} + +int ChrolisHub::Initialize() +{ + return DEVICE_OK; +} + +int ChrolisHub::Shutdown() +{ + return DEVICE_OK; +} + +void ChrolisHub::GetName(char* name) const +{ + CDeviceUtils::CopyLimitedString(name, CHROLIS_SHUTTER_NAME); +} + +bool ChrolisHub::Busy() +{ + return false; } \ No newline at end of file diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 1adba8749..80546ebac 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -1,7 +1,37 @@ #pragma once #include #include "DeviceBase.h" +#define CHROLIS_HUB_NAME "CHROLIS_Hub" #define CHROLIS_SHUTTER_NAME "CHROLIS_Shutter" +#define CHROLIS_STATE_NAME "CHROLIS_State_Device" +#define CHROLIS_GENERIC_DEVICE_NAME "CHROLIS_Generic_Device" + +class ChrolisHub : public HubBase +{ +public: + ChrolisHub() : + initialized_(false), + busy_(false), + deviceHandle_(-1) + {} + ~ChrolisHub() {} + + int Initialize(); //TODO: Create property for serial number + int Shutdown(); + void GetName(char* pszName) const; + bool Busy(); + + // HUB api + int DetectInstalledDevices(); + + int GetDeviceHandle(ViPSession deviceHandle); + bool IsInitialized(); + +private: + bool initialized_; + bool busy_; + ViSession deviceHandle_; +}; class ChrolisShutter : public CShutterBase //CRTP { @@ -136,3 +166,46 @@ class ChrolisShutter : public CShutterBase //CRTP } }; +class ChrolisStateDevice : public CStateDeviceBase +{ +public: + ChrolisStateDevice() + {} + + ~ChrolisStateDevice() + {} + + int Initialize(); + int Shutdown(); + void GetName(char* pszName) const; + bool Busy(); + + unsigned long GetNumberOfPositions()const { return numPos_; } + + // action interface + // ---------------- + int OnState(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct); + +private: + long numPos_; +}; + +class ChrolisPowerControl : public CGenericBase +{ +public: + ChrolisPowerControl() + {} + + ~ChrolisPowerControl() + {} + + int Initialize(); + int Shutdown(); + void GetName(char* pszName) const; + bool Busy(); + +private: + +}; + From 9a4034d8c5a7d506f084da75271cd9ce57ecb243 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Fri, 6 Oct 2023 17:09:19 -0400 Subject: [PATCH 03/91] finished method definitions for classes in cpp --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 89 ++++++++++++++++++- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 3 +- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 653e119a1..fd8e95e9c 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -41,7 +41,7 @@ MODULE_API MM::Device* CreateDevice(char const* name) { MODULE_API void DeleteDevice(MM::Device* device) { delete device; } - +//Hub Methods int ChrolisHub::DetectInstalledDevices() { ClearInstalledDevices(); @@ -80,6 +80,93 @@ void ChrolisHub::GetName(char* name) const } bool ChrolisHub::Busy() +{ + return false; +} + +bool ChrolisHub::IsInitialized() +{ + return initialized_ && deviceHandle_ != -1; +} + +int ChrolisHub::GetDeviceHandle(ViPSession deviceHandle) +{ + deviceHandle = &deviceHandle_; + return DEVICE_OK; +} + + +//Chrolis State Device Methods +int ChrolisStateDevice::Initialize() +{ + return DEVICE_OK; +} + +int ChrolisStateDevice::Shutdown() +{ + return DEVICE_OK; +} + +void ChrolisStateDevice::GetName(char* name) const +{ + CDeviceUtils::CopyLimitedString(name, CHROLIS_SHUTTER_NAME); +} + +bool ChrolisStateDevice::Busy() +{ + return false; +} + +int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + return DEVICE_OK; +} + +int ChrolisStateDevice::OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + return DEVICE_OK; +} + + +//Chrolis Shutter Methods +int ChrolisShutter::Initialize() +{ + return DEVICE_OK; +} + +int ChrolisShutter::Shutdown() +{ + return DEVICE_OK; +} + +void ChrolisShutter::GetName(char* name) const +{ + CDeviceUtils::CopyLimitedString(name, CHROLIS_SHUTTER_NAME); +} + +bool ChrolisShutter::Busy() +{ + return false; +} + + +//Chrolis Power Control (Genric Device) Methods +int ChrolisPowerControl::Initialize() +{ + return DEVICE_OK; +} + +int ChrolisPowerControl::Shutdown() +{ + return DEVICE_OK; +} + +void ChrolisPowerControl::GetName(char* name) const +{ + CDeviceUtils::CopyLimitedString(name, CHROLIS_SHUTTER_NAME); +} + +bool ChrolisPowerControl::Busy() { return false; } \ No newline at end of file diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 80546ebac..6687c70c6 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -169,7 +169,8 @@ class ChrolisShutter : public CShutterBase //CRTP class ChrolisStateDevice : public CStateDeviceBase { public: - ChrolisStateDevice() + ChrolisStateDevice(): + numPos_(6) {} ~ChrolisStateDevice() From c11416df824ef00358b4938752e3acb3d8943013 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Mon, 9 Oct 2023 08:49:51 -0400 Subject: [PATCH 04/91] Added init and shutdown implementation for hub --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 40 +++++++++++++++++++ .../ThorlabsCHROLIS/ThorlabsChrolis.h | 4 +- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index fd8e95e9c..8f43beb05 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -66,11 +66,51 @@ int ChrolisHub::DetectInstalledDevices() int ChrolisHub::Initialize() { + int err = 0; + ViUInt32 numDevices; + CDeviceUtils::SleepMs(2000); + err = TL6WL_findRsrc(NULL, &numDevices); + if (err != 0) + { + LogMessage("Find Resource Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + if (numDevices == 0) + { + LogMessage("Chrolis devices not found"); // to log file + return DEVICE_ERR; + } + + ViChar resource[512] = ""; + err = TL6WL_getRsrcName(NULL, 0, resource); + if (err != 0) + { + LogMessage("Get Resource Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + + err = TL6WL_init(resource, false, false, &deviceHandle_); + if (err != 0) + { + LogMessage("Initialize Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + initialized_ = true; return DEVICE_OK; } int ChrolisHub::Shutdown() { + if (initialized_) + { + auto err = TL6WL_close(deviceHandle_); + if (err != 0) + { + LogMessage("Close Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + initialized_ = false; + } return DEVICE_OK; } diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 6687c70c6..f71d2076f 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -13,7 +13,9 @@ class ChrolisHub : public HubBase initialized_(false), busy_(false), deviceHandle_(-1) - {} + { + CreateHubIDProperty(); + } ~ChrolisHub() {} int Initialize(); //TODO: Create property for serial number From cf1c147a58388654c7b5f3481f13f0c2338c3f7a Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Mon, 9 Oct 2023 13:22:18 -0400 Subject: [PATCH 05/91] Added new class to wrap chrolis functions and control hardware functionality --- .../ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj | 1 + .../ThorlabsCHROLIS.vcxproj.filters | 3 + .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 89 +++++++------ .../ThorlabsCHROLIS/ThorlabsChrolis.h | 117 ++++-------------- .../ThorlabsChrolisDeviceWrapper.cpp | 43 +++++++ 5 files changed, 120 insertions(+), 133 deletions(-) create mode 100644 DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj index 1fdc18c60..ae223f7ae 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj @@ -15,6 +15,7 @@ + diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj.filters b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj.filters index d86ca4679..656515cea 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj.filters +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj.filters @@ -23,5 +23,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 8f43beb05..9a33fa4f1 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -66,35 +66,7 @@ int ChrolisHub::DetectInstalledDevices() int ChrolisHub::Initialize() { - int err = 0; - ViUInt32 numDevices; - CDeviceUtils::SleepMs(2000); - err = TL6WL_findRsrc(NULL, &numDevices); - if (err != 0) - { - LogMessage("Find Resource Failed: " + std::to_string(err)); - return DEVICE_ERR; - } - if (numDevices == 0) - { - LogMessage("Chrolis devices not found"); // to log file - return DEVICE_ERR; - } - - ViChar resource[512] = ""; - err = TL6WL_getRsrcName(NULL, 0, resource); - if (err != 0) - { - LogMessage("Get Resource Failed: " + std::to_string(err)); - return DEVICE_ERR; - } - err = TL6WL_init(resource, false, false, &deviceHandle_); - if (err != 0) - { - LogMessage("Initialize Failed: " + std::to_string(err)); - return DEVICE_ERR; - } initialized_ = true; return DEVICE_OK; } @@ -136,59 +108,96 @@ int ChrolisHub::GetDeviceHandle(ViPSession deviceHandle) } -//Chrolis State Device Methods -int ChrolisStateDevice::Initialize() +//Chrolis Shutter Methods +int ChrolisShutter::Initialize() { return DEVICE_OK; } -int ChrolisStateDevice::Shutdown() +int ChrolisShutter::Shutdown() { return DEVICE_OK; } -void ChrolisStateDevice::GetName(char* name) const +void ChrolisShutter::GetName(char* name) const { CDeviceUtils::CopyLimitedString(name, CHROLIS_SHUTTER_NAME); } -bool ChrolisStateDevice::Busy() +bool ChrolisShutter::Busy() { return false; } -int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) +int ChrolisShutter::SetOpen(bool open = true) { + ChrolisHub* pHub = static_cast(GetParentHub()); + if (!pHub || !pHub->IsInitialized()) + { + return DEVICE_ERR; // TODO Add custom error messages + } + ViSession deviceHandle = -1; + pHub->GetDeviceHandle(&deviceHandle); + + if (!open) + { + if (int err = TL6WL_setLED_HeadPowerStates(deviceHandle, false, false, false, false, false, false) != 0) + { + LogMessage("Set Enable States Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + masterShutterState = false; + } + else + { + if (int err = TL6WL_setLED_HeadPowerStates(deviceHandle, true, true, true, true, true, true) != 0) + { + LogMessage("Set Enable States Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + masterShutterState = true; + } return DEVICE_OK; } -int ChrolisStateDevice::OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct) +int ChrolisShutter::GetOpen(bool& open) { + open = masterShutterState; return DEVICE_OK; } -//Chrolis Shutter Methods -int ChrolisShutter::Initialize() +//Chrolis State Device Methods +int ChrolisStateDevice::Initialize() { return DEVICE_OK; } -int ChrolisShutter::Shutdown() +int ChrolisStateDevice::Shutdown() { return DEVICE_OK; } -void ChrolisShutter::GetName(char* name) const +void ChrolisStateDevice::GetName(char* name) const { CDeviceUtils::CopyLimitedString(name, CHROLIS_SHUTTER_NAME); } -bool ChrolisShutter::Busy() +bool ChrolisStateDevice::Busy() { return false; } +int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + return DEVICE_OK; +} + +int ChrolisStateDevice::OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + return DEVICE_OK; +} + //Chrolis Power Control (Genric Device) Methods int ChrolisPowerControl::Initialize() diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index f71d2076f..1adc113a1 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -37,10 +37,7 @@ class ChrolisHub : public HubBase class ChrolisShutter : public CShutterBase //CRTP { - ViSession deviceHandle_ = -1; ViBoolean savedEnabledStates[6]{ false,false,false,false,false,false}; - ViUInt16 powerStates[6]{0,0,1000,0,0,0}; - bool connected = false; bool masterShutterState = false; public: @@ -51,74 +48,11 @@ class ChrolisShutter : public CShutterBase //CRTP int Initialize() { - int err = 0; - ViUInt32 numDevices; - CDeviceUtils::SleepMs(2000); - err = TL6WL_findRsrc(NULL, &numDevices); - if (err != 0) - { - LogMessage("Find Resource Failed: " + std::to_string(err)); - return DEVICE_ERR; - } - if (numDevices == 0) - { - LogMessage("Chrolis devices not found"); // to log file - return DEVICE_ERR; - } - - ViChar resource[512] = ""; - err = TL6WL_getRsrcName(NULL, 0, resource); - if (err != 0) - { - LogMessage("Get Resource Failed: " + std::to_string(err)); - return DEVICE_ERR; - } - - err = TL6WL_init(resource, false, false, &deviceHandle_); - if (err != 0) - { - LogMessage("Initialize Failed: " + std::to_string(err)); - return DEVICE_ERR; - } - connected = true; - - err = TL6WL_getLED_HeadPowerStates(deviceHandle_, &savedEnabledStates[0], &savedEnabledStates[1], &savedEnabledStates[2], &savedEnabledStates[3], &savedEnabledStates[4], &savedEnabledStates[5]); - if (err != 0) - { - LogMessage("Get Enable States Failed: " + std::to_string(err)); - return DEVICE_ERR; - } - - err = TL6WL_getLED_HeadBrightness(deviceHandle_, &powerStates[0], &powerStates[1], &powerStates[2], &powerStates[3], &powerStates[4], &powerStates[5]); - if (err != 0) - { - LogMessage("Get Power States Failed: " + std::to_string(err)); - return DEVICE_ERR; - } - - err = TL6WL_setLED_HeadBrightness(deviceHandle_, powerStates[0], powerStates[1], powerStates[2], powerStates[3], powerStates[4], powerStates[5]); - if (err != 0) - { - LogMessage("Set Power States Failed: " + std::to_string(err)); - return DEVICE_ERR; - } - return DEVICE_OK; } int Shutdown() { - if (connected) - { - auto err = TL6WL_close(deviceHandle_); - if (err != 0) - { - LogMessage("Close Failed: " + std::to_string(err)); - return DEVICE_ERR; - } - connected = false; - CDeviceUtils::SleepMs(1000); - } return DEVICE_OK; } @@ -133,34 +67,9 @@ class ChrolisShutter : public CShutterBase //CRTP } // Shutter API - int SetOpen(bool open = true) - { - if (!open) - { - if (int err = TL6WL_setLED_HeadPowerStates(deviceHandle_, false, false, false, false, false, false) != 0) - { - LogMessage("Get Enable States Failed: " + std::to_string(err)); - return DEVICE_ERR; - } - masterShutterState = false; - } - else - { - if (int err = TL6WL_setLED_HeadPowerStates(deviceHandle_, true, true, true, true, true, true) != 0) - { - LogMessage("Get Enable States Failed: " + std::to_string(err)); - return DEVICE_ERR; - } - masterShutterState = true; - } - return DEVICE_OK; - } + int SetOpen(bool open = true); - int GetOpen(bool& open) - { - open = masterShutterState; - return DEVICE_OK; - } + int GetOpen(bool& open); int Fire(double /*deltaT*/) { @@ -212,3 +121,25 @@ class ChrolisPowerControl : public CGenericBase }; +class ThorlabsChrolisDeviceWrapper +{ +public: + ThorlabsChrolisDeviceWrapper(); + ~ThorlabsChrolisDeviceWrapper(); + + int InitializeDevice(std::string serialNumber = ""); + int ShutdownDevice(); + int GetDeviceHandle(); + int SetLEDEnableStates(ViBoolean states[6]); + int SetLEDPowerStates(ViUInt32 states[6]); + int SetShutterState(bool state); + int GetShutterState(bool& state); + +private: + ViSession deviceHandle_; + bool masterSwitchState_; + ViBoolean savedEnabledStates[6]{false,false,false,false,false,false}; + ViUInt32 savedPowerStates[6]{0,0,0,0,0,0}; + +}; + diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp new file mode 100644 index 000000000..605f26ada --- /dev/null +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -0,0 +1,43 @@ +#include "ThorlabsChrolis.h" +#include + +ThorlabsChrolisDeviceWrapper::ThorlabsChrolisDeviceWrapper() +{ + masterSwitchState_ = false; + deviceHandle_ = -1; +} + +ThorlabsChrolisDeviceWrapper::~ThorlabsChrolisDeviceWrapper() +{} + +int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber = "") +{ + + return 0; +} + +int ThorlabsChrolisDeviceWrapper::ShutdownDevice() +{ + return 0; +} + +int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) +{ + return 0; +} + +int ThorlabsChrolisDeviceWrapper::SetLEDPowerStates(ViUInt32 states[6]) +{ + return 0; +} + +int ThorlabsChrolisDeviceWrapper::SetShutterState(bool state) +{ + return 0; +} + +int ThorlabsChrolisDeviceWrapper::GetShutterState(bool& state) +{ + state = masterSwitchState_; + return 0; +} \ No newline at end of file From 3f8a9ec6ef249156a59e34ca24e241098742a7a0 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Mon, 9 Oct 2023 14:12:23 -0400 Subject: [PATCH 06/91] Bringing over initialization code --- .../ThorlabsChrolisDeviceWrapper.cpp | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 605f26ada..b800c3d75 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -12,7 +12,35 @@ ThorlabsChrolisDeviceWrapper::~ThorlabsChrolisDeviceWrapper() int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber = "") { + int err = 0; + ViUInt32 numDevices; + CDeviceUtils::SleepMs(2000); + err = TL6WL_findRsrc(NULL, &numDevices); + if (err != 0) + { + LogMessage("Find Resource Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + if (numDevices == 0) + { + LogMessage("Chrolis devices not found"); // to log file + return DEVICE_ERR; + } + ViChar resource[512] = ""; + err = TL6WL_getRsrcName(NULL, 0, resource); + if (err != 0) + { + LogMessage("Get Resource Failed: " + std::to_string(err)); + return DEVICE_ERR; + } + + err = TL6WL_init(resource, false, false, &deviceHandle_); + if (err != 0) + { + LogMessage("Initialize Failed: " + std::to_string(err)); + return DEVICE_ERR; + } return 0; } From 231ac2a0cb04e05f7935a6a8cf6aa2f8aa43f7ad Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Mon, 9 Oct 2023 16:58:20 -0400 Subject: [PATCH 07/91] Additions for new class and testing implementation in hub --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 63 ++++---- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 52 +++---- .../ThorlabsChrolisDeviceWrapper.cpp | 137 +++++++++++++++--- 3 files changed, 174 insertions(+), 78 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 9a33fa4f1..1a2e9cfbb 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -42,6 +42,14 @@ MODULE_API void DeleteDevice(MM::Device* device) { delete device; } //Hub Methods +ChrolisHub::ChrolisHub() : + initialized_(false), + busy_(false) +{ + CreateHubIDProperty(); + chrolisDeviceInstance_ = new ThorlabsChrolisDeviceWrapper(); +} + int ChrolisHub::DetectInstalledDevices() { ClearInstalledDevices(); @@ -66,7 +74,11 @@ int ChrolisHub::DetectInstalledDevices() int ChrolisHub::Initialize() { - + auto err = static_cast(chrolisDeviceInstance_)->InitializeDevice(); + if (err != 0) + { + return DEVICE_ERR; + } initialized_ = true; return DEVICE_OK; } @@ -75,10 +87,9 @@ int ChrolisHub::Shutdown() { if (initialized_) { - auto err = TL6WL_close(deviceHandle_); + auto err = static_cast(chrolisDeviceInstance_)->ShutdownDevice(); if (err != 0) { - LogMessage("Close Failed: " + std::to_string(err)); return DEVICE_ERR; } initialized_ = false; @@ -98,16 +109,14 @@ bool ChrolisHub::Busy() bool ChrolisHub::IsInitialized() { - return initialized_ && deviceHandle_ != -1; + return initialized_; } -int ChrolisHub::GetDeviceHandle(ViPSession deviceHandle) +void* ChrolisHub::GetChrolisDeviceInstance() { - deviceHandle = &deviceHandle_; - return DEVICE_OK; + return chrolisDeviceInstance_; } - //Chrolis Shutter Methods int ChrolisShutter::Initialize() { @@ -129,40 +138,40 @@ bool ChrolisShutter::Busy() return false; } -int ChrolisShutter::SetOpen(bool open = true) +int ChrolisShutter::SetOpen(bool open) { ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { return DEVICE_ERR; // TODO Add custom error messages } - ViSession deviceHandle = -1; - pHub->GetDeviceHandle(&deviceHandle); - - if (!open) + ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + if (!wrapperInstance->IsDeviceConnected()) { - if (int err = TL6WL_setLED_HeadPowerStates(deviceHandle, false, false, false, false, false, false) != 0) - { - LogMessage("Set Enable States Failed: " + std::to_string(err)); - return DEVICE_ERR; - } - masterShutterState = false; + return DEVICE_ERR; } - else + auto err = wrapperInstance->SetShutterState(open); + if (err != 0) { - if (int err = TL6WL_setLED_HeadPowerStates(deviceHandle, true, true, true, true, true, true) != 0) - { - LogMessage("Set Enable States Failed: " + std::to_string(err)); - return DEVICE_ERR; - } - masterShutterState = true; + return DEVICE_ERR; } + return DEVICE_OK; } int ChrolisShutter::GetOpen(bool& open) { - open = masterShutterState; + ChrolisHub* pHub = static_cast(GetParentHub()); + if (!pHub || !pHub->IsInitialized()) + { + return DEVICE_ERR; // TODO Add custom error messages + } + ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + if (!wrapperInstance->IsDeviceConnected()) + { + return DEVICE_ERR; + } + wrapperInstance->GetShutterState(open); return DEVICE_OK; } diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 1adc113a1..c215199c0 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -9,16 +9,10 @@ class ChrolisHub : public HubBase { public: - ChrolisHub() : - initialized_(false), - busy_(false), - deviceHandle_(-1) - { - CreateHubIDProperty(); - } + ChrolisHub(); ~ChrolisHub() {} - int Initialize(); //TODO: Create property for serial number + int Initialize(); int Shutdown(); void GetName(char* pszName) const; bool Busy(); @@ -26,13 +20,13 @@ class ChrolisHub : public HubBase // HUB api int DetectInstalledDevices(); - int GetDeviceHandle(ViPSession deviceHandle); bool IsInitialized(); + void* GetChrolisDeviceInstance(); private: + void* chrolisDeviceInstance_; bool initialized_; bool busy_; - ViSession deviceHandle_; }; class ChrolisShutter : public CShutterBase //CRTP @@ -46,25 +40,13 @@ class ChrolisShutter : public CShutterBase //CRTP } ~ChrolisShutter() {} - int Initialize() - { - return DEVICE_OK; - } + int Initialize(); - int Shutdown() - { - return DEVICE_OK; - } + int Shutdown(); - void GetName(char* name) const - { - CDeviceUtils::CopyLimitedString(name, CHROLIS_SHUTTER_NAME); - } + void GetName(char* name)const; - bool Busy() - { - return false; - } + bool Busy(); // Shutter API int SetOpen(bool open = true); @@ -121,6 +103,7 @@ class ChrolisPowerControl : public CGenericBase }; +//Wrapper for the basic functions used in this device adapter class ThorlabsChrolisDeviceWrapper { public: @@ -129,17 +112,22 @@ class ThorlabsChrolisDeviceWrapper int InitializeDevice(std::string serialNumber = ""); int ShutdownDevice(); - int GetDeviceHandle(); + bool IsDeviceConnected(); int SetLEDEnableStates(ViBoolean states[6]); - int SetLEDPowerStates(ViUInt32 states[6]); - int SetShutterState(bool state); - int GetShutterState(bool& state); + int SetLEDPowerStates(ViInt16 states[6]); + int SetShutterState(bool open); + int GetShutterState(bool& open); private: + int numLEDs_; + bool deviceConnected_; ViSession deviceHandle_; + ViBoolean deviceInUse_; //only used by the chrolis API + ViChar deviceName_[256]; + ViChar serialNumber_[256]; + ViChar manufacturerName_[256]; bool masterSwitchState_; ViBoolean savedEnabledStates[6]{false,false,false,false,false,false}; - ViUInt32 savedPowerStates[6]{0,0,0,0,0,0}; - + ViInt16 savedPowerStates[6]{0,0,0,0,0,0}; }; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index b800c3d75..5b749f0dc 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -3,14 +3,16 @@ ThorlabsChrolisDeviceWrapper::ThorlabsChrolisDeviceWrapper() { + deviceConnected_ = false; masterSwitchState_ = false; deviceHandle_ = -1; + numLEDs_ = 6; } ThorlabsChrolisDeviceWrapper::~ThorlabsChrolisDeviceWrapper() {} -int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber = "") +int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) { int err = 0; ViUInt32 numDevices; @@ -18,54 +20,151 @@ int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber = "" err = TL6WL_findRsrc(NULL, &numDevices); if (err != 0) { - LogMessage("Find Resource Failed: " + std::to_string(err)); return DEVICE_ERR; } if (numDevices == 0) { - LogMessage("Chrolis devices not found"); // to log file return DEVICE_ERR; } ViChar resource[512] = ""; - err = TL6WL_getRsrcName(NULL, 0, resource); - if (err != 0) + if(serialNumber.compare("")) { - LogMessage("Get Resource Failed: " + std::to_string(err)); - return DEVICE_ERR; + err = TL6WL_getRsrcName(NULL, 0, resource); + if (err != 0) + { + return DEVICE_ERR; + } + err = TL6WL_getRsrcInfo(NULL, 0, deviceName_, serialNumber_, manufacturerName_, &deviceInUse_); + if (err != 0) + { + return DEVICE_ERR; + } + } + else + { + bool found = false; + int i = 0; + for (i = 0; i < numDevices; i++) + { + err = TL6WL_getRsrcName(NULL, i, resource); + if (err != 0) + { + return DEVICE_ERR; + } + err = TL6WL_getRsrcInfo(NULL, i, deviceName_, serialNumber_, manufacturerName_, &deviceInUse_); + if (err != 0) + { + return DEVICE_ERR; + } + if (strcmp((char*)serialNumber_, serialNumber.c_str())) + { + found = true; + break; + } + } + if(!found) + { + return DEVICE_ERR; + } } - err = TL6WL_init(resource, false, false, &deviceHandle_); if (err != 0) { - LogMessage("Initialize Failed: " + std::to_string(err)); return DEVICE_ERR; } - return 0; + deviceConnected_ = true; + + return DEVICE_OK; } int ThorlabsChrolisDeviceWrapper::ShutdownDevice() { - return 0; + if (deviceHandle_ != -1) + { + auto err = TL6WL_close(deviceHandle_); + if (err != 0) + { + return DEVICE_ERR; + } + deviceConnected_ = false; + } + return DEVICE_OK; +} + +bool ThorlabsChrolisDeviceWrapper::IsDeviceConnected() +{ + return deviceConnected_; } int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) { - return 0; + if (states == NULL) + { + return DEVICE_ERR; + } + int i; + for (i = 0; i < numLEDs_; i++) + { + savedEnabledStates[i] = states[i]; + } + + if (masterSwitchState_) + { + if (auto err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates[0], savedEnabledStates[1], savedEnabledStates[2], + savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]) != 0) + { + return DEVICE_ERR; + } + } + + return DEVICE_OK; } -int ThorlabsChrolisDeviceWrapper::SetLEDPowerStates(ViUInt32 states[6]) +int ThorlabsChrolisDeviceWrapper::SetLEDPowerStates(ViInt16 states[6]) { - return 0; + if (states == NULL) + { + return DEVICE_ERR; + } + int i; + for (i = 0; i < numLEDs_; i++) + { + savedPowerStates[i] = states[i]; + } + + if (auto err = TL6WL_setLED_HeadBrightness(deviceHandle_, savedPowerStates[0], savedPowerStates[1], savedPowerStates[2], + savedPowerStates[3], savedPowerStates[4], savedPowerStates[5]) != 0) + { + return DEVICE_ERR; + } + + return DEVICE_OK; } -int ThorlabsChrolisDeviceWrapper::SetShutterState(bool state) +int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) { - return 0; + if (!open) + { + if (int err = TL6WL_setLED_HeadPowerStates(deviceHandle_, false, false, false, false, false, false) != 0) + { + return DEVICE_ERR; + } + masterSwitchState_ = false; + } + else + { + if (int err = TL6WL_setLED_HeadPowerStates(deviceHandle_, true, true, true, true, true, true) != 0) + { + return DEVICE_ERR; + } + masterSwitchState_ = true; + } + return DEVICE_OK; } -int ThorlabsChrolisDeviceWrapper::GetShutterState(bool& state) +int ThorlabsChrolisDeviceWrapper::GetShutterState(bool& open) { - state = masterSwitchState_; - return 0; + open = masterSwitchState_; + return DEVICE_OK; } \ No newline at end of file From e54f61bed9d4d6ac1dda91cd82ae8edbf390ac61 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Tue, 10 Oct 2023 11:29:37 -0400 Subject: [PATCH 08/91] Continuing adapter build out --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 169 +++++++++++++++++- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 32 +++- .../ThorlabsChrolisDeviceWrapper.cpp | 44 ++++- 3 files changed, 234 insertions(+), 11 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 1a2e9cfbb..9f95b0b14 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -3,6 +3,14 @@ #include +/* +* Questions for Mark +* 1- Pre-init properties +* 2- Sequencer action for properties and utilizing the sequencer +* 3- Slider bars? +* 4- Non-default property states for state devices +*/ + MODULE_API void InitializeModuleData() { RegisterDevice(CHROLIS_HUB_NAME, // deviceName: model identifier and default device label MM::HubDevice, @@ -118,8 +126,27 @@ void* ChrolisHub::GetChrolisDeviceInstance() } //Chrolis Shutter Methods +//TODO test on property change with label for shutter state +ChrolisShutter::ChrolisShutter() +{ + InitializeDefaultErrorMessages(); + //SetErrorText(ERR_UNKNOWN_POSITION, "Requested position not available in this device"); + //EnableDelay(); // signals that the delay setting will be used + CreateHubIDProperty(); +} + int ChrolisShutter::Initialize() { + ChrolisHub* pHub = static_cast(GetParentHub()); + if (pHub) + { + char hubLabel[MM::MaxStrLength]; + pHub->GetLabel(hubLabel); + SetParentID(hubLabel); // for backward comp. + } + else + LogMessage(NoHubError); + return DEVICE_OK; } @@ -177,8 +204,43 @@ int ChrolisShutter::GetOpen(bool& open) //Chrolis State Device Methods +ChrolisStateDevice::ChrolisStateDevice() : + numPos_(6), + curLedState_(0) +{ + InitializeDefaultErrorMessages(); + //SetErrorText(ERR_UNKNOWN_POSITION, "Requested position not available in this device"); + //EnableDelay(); // signals that the delay setting will be used + CreateHubIDProperty(); +} + int ChrolisStateDevice::Initialize() { + ChrolisHub* pHub = static_cast(GetParentHub()); + if (pHub) + { + char hubLabel[MM::MaxStrLength]; + pHub->GetLabel(hubLabel); + SetParentID(hubLabel); // for backward comp. + } + else + LogMessage(NoHubError); + + // create default positions and labels + const int bufSize = 1024; + char buf[bufSize]; + for (long i = 0; i < numPos_; i++) + { + snprintf(buf, bufSize, "-%ld", i); + SetPositionLabel(i, buf); + } + + //State Property + CPropertyAction* pAct = new CPropertyAction(this, &ChrolisStateDevice::OnState); + auto err = CreateIntegerProperty(MM::g_Keyword_State, 0, false, pAct); + if (err != DEVICE_OK) + return err; + return DEVICE_OK; } @@ -199,6 +261,50 @@ bool ChrolisStateDevice::Busy() int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) { + if (eAct == MM::BeforeGet) + { + pProp->Set(curLedState_); + // nothing to do, let the caller to use cached property + } + else if (eAct == MM::AfterSet) + { + long pos; + pProp->Get(pos); + if (pos >= numPos_ || pos < 0) + { + pProp->Set(curLedState_); // revert + return ERR_UNKNOWN_LED_STATE; + } + // Do something with the incoming state info + ChrolisHub* pHub = static_cast(GetParentHub()); + if (!pHub || !pHub->IsInitialized()) + { + return DEVICE_ERR; // TODO Add custom error messages + } + ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + if (!wrapperInstance->IsDeviceConnected()) + { + return DEVICE_ERR; + } + + ViBoolean curStates[6]; + wrapperInstance->GetLEDEnableStates(curStates); + for (int i = 0; i < 6; i++) + { + curStates[i] = false; + } + curStates[pos] = true; + int err = wrapperInstance->SetLEDEnableStates(curStates); + if (err != 0) + { + return DEVICE_ERR; + } + + curLedState_ = pos; + return DEVICE_OK; + } + else if (eAct == MM::IsSequenceable) + {} return DEVICE_OK; } @@ -209,8 +315,30 @@ int ChrolisStateDevice::OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct) //Chrolis Power Control (Genric Device) Methods +ChrolisPowerControl::ChrolisPowerControl() : ledMaxPower_(100), ledMinPower_(0), ledPower_(0) +{ + InitializeDefaultErrorMessages(); + //SetErrorText(ERR_UNKNOWN_POSITION, "Requested position not available in this device"); + //EnableDelay(); // signals that the delay setting will be used + CreateHubIDProperty(); +} + + int ChrolisPowerControl::Initialize() { + ChrolisHub* pHub = static_cast(GetParentHub()); + if (pHub) + { + char hubLabel[MM::MaxStrLength]; + pHub->GetLabel(hubLabel); + SetParentID(hubLabel); // for backward comp. + } + else + LogMessage(NoHubError); + + //State Property + CPropertyAction* pAct = new CPropertyAction(this, &ChrolisPowerControl::OnPowerChange); + auto err = CreateIntegerProperty(MM::g_Keyword_Label, 0, false, pAct); return DEVICE_OK; } @@ -227,4 +355,43 @@ void ChrolisPowerControl::GetName(char* name) const bool ChrolisPowerControl::Busy() { return false; -} \ No newline at end of file +} + +int ChrolisPowerControl::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + if (eAct == MM::BeforeGet) + { + pProp->Set((long)ledPower_); + // nothing to do, let the caller to use cached property + } + else if (eAct == MM::AfterSet) + { + long val; + pProp->Get(val); + if (val > ledMaxPower_ || val < ledMinPower_) + { + pProp->Set((long)ledPower_); // revert + return ERR_UNKNOWN_LED_STATE; + } + // Do something with the incoming state info + ChrolisHub* pHub = static_cast(GetParentHub()); + if (!pHub || !pHub->IsInitialized()) + { + return DEVICE_ERR; // TODO Add custom error messages + } + ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + if (!wrapperInstance->IsDeviceConnected()) + { + return DEVICE_ERR; + } + + //TODO Add code for power control + + return DEVICE_OK; + } + else if (eAct == MM::IsSequenceable) + { + } + return DEVICE_OK; +} + diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index c215199c0..913459d85 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -6,6 +6,16 @@ #define CHROLIS_STATE_NAME "CHROLIS_State_Device" #define CHROLIS_GENERIC_DEVICE_NAME "CHROLIS_Generic_Device" +//Custom Error Codes +#define ERR_UNKNOWN_MODE 102 +#define ERR_UNKNOWN_LED_STATE 103 +#define ERR_IN_SEQUENCE 104 +#define ERR_SEQUENCE_INACTIVE 105 +#define ERR_STAGE_MOVING 106 +#define HUB_NOT_AVAILABLE 107 + +const char* NoHubError = "Parent Hub not defined."; + class ChrolisHub : public HubBase { public: @@ -35,9 +45,7 @@ class ChrolisShutter : public CShutterBase //CRTP bool masterShutterState = false; public: - ChrolisShutter() - { - } + ChrolisShutter(); ~ChrolisShutter() {} int Initialize(); @@ -62,9 +70,7 @@ class ChrolisShutter : public CShutterBase //CRTP class ChrolisStateDevice : public CStateDeviceBase { public: - ChrolisStateDevice(): - numPos_(6) - {} + ChrolisStateDevice(); ~ChrolisStateDevice() {} @@ -82,14 +88,14 @@ class ChrolisStateDevice : public CStateDeviceBase int OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct); private: + long curLedState_; long numPos_; }; class ChrolisPowerControl : public CGenericBase { public: - ChrolisPowerControl() - {} + ChrolisPowerControl(); ~ChrolisPowerControl() {} @@ -98,9 +104,14 @@ class ChrolisPowerControl : public CGenericBase int Shutdown(); void GetName(char* pszName) const; bool Busy(); + + //Label Update + int OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct); private: - + ViInt16 ledPower_; + ViInt16 ledMaxPower_; + ViInt16 ledMinPower_; }; //Wrapper for the basic functions used in this device adapter @@ -113,8 +124,11 @@ class ThorlabsChrolisDeviceWrapper int InitializeDevice(std::string serialNumber = ""); int ShutdownDevice(); bool IsDeviceConnected(); + int GetLEDEnableStates(ViBoolean (&states)[6]); int SetLEDEnableStates(ViBoolean states[6]); int SetLEDPowerStates(ViInt16 states[6]); + int SetSingleLEDEnableState(int LED, ViBoolean state); + int SetSingleLEDPowerState(int LED, ViInt16 state); int SetShutterState(bool open); int GetShutterState(bool& open); diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 5b749f0dc..532464c20 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -87,8 +87,8 @@ int ThorlabsChrolisDeviceWrapper::ShutdownDevice() { return DEVICE_ERR; } - deviceConnected_ = false; } + deviceConnected_ = false; return DEVICE_OK; } @@ -97,6 +97,11 @@ bool ThorlabsChrolisDeviceWrapper::IsDeviceConnected() return deviceConnected_; } +int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean(&states)[6]) +{ + *states = *savedEnabledStates; +} + int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) { if (states == NULL) @@ -142,6 +147,43 @@ int ThorlabsChrolisDeviceWrapper::SetLEDPowerStates(ViInt16 states[6]) return DEVICE_OK; } +int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean state) +{ + if (LED < 6 && LED >= 0) + { + savedEnabledStates[LED] = state; + if (SetLEDEnableStates(savedEnabledStates)) + { + return DEVICE_OK; + } + else + { + //revert in case of error + savedEnabledStates[LED] = !state; + } + } + return DEVICE_ERR; +} + +int ThorlabsChrolisDeviceWrapper::SetSingleLEDPowerState(int LED, ViInt16 state) +{ + if (LED < 6 && LED >= 0) + { + ViInt16 tmpPower = savedPowerStates[LED]; + savedPowerStates[LED] = state; + if (SetLEDPowerStates(savedPowerStates)) + { + return DEVICE_OK; + } + else + { + //revert in case of error + savedPowerStates[LED] = tmpPower; + } + } + return DEVICE_ERR; +} + int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) { if (!open) From 67b973994b5c54e2c4ead43a604327e198e4ea1b Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Tue, 10 Oct 2023 16:13:36 -0400 Subject: [PATCH 09/91] Some bug fixes and cleanup --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 59 +++++++++++++------ .../ThorlabsCHROLIS/ThorlabsChrolis.h | 16 +++-- .../ThorlabsChrolisDeviceWrapper.cpp | 2 + 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 9f95b0b14..58a08cbae 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -11,6 +11,14 @@ * 4- Non-default property states for state devices */ +/*TODO +* Set states of properties based on current LED states +* Properties for device ID and stuff +* Error handling on device control methods +* custom errors and messages +* logs for errors +*/ + MODULE_API void InitializeModuleData() { RegisterDevice(CHROLIS_HUB_NAME, // deviceName: model identifier and default device label MM::HubDevice, @@ -82,12 +90,17 @@ int ChrolisHub::DetectInstalledDevices() int ChrolisHub::Initialize() { - auto err = static_cast(chrolisDeviceInstance_)->InitializeDevice(); - if (err != 0) + if (!initialized_) { - return DEVICE_ERR; + + auto err = static_cast(chrolisDeviceInstance_)->InitializeDevice(); + if (err != 0) + { + LogMessage("Error in CHROLIS Initialization"); + return DEVICE_ERR; + } + initialized_ = true; } - initialized_ = true; return DEVICE_OK; } @@ -98,6 +111,7 @@ int ChrolisHub::Shutdown() auto err = static_cast(chrolisDeviceInstance_)->ShutdownDevice(); if (err != 0) { + LogMessage("Error shutting down device"); return DEVICE_ERR; } initialized_ = false; @@ -107,7 +121,7 @@ int ChrolisHub::Shutdown() void ChrolisHub::GetName(char* name) const { - CDeviceUtils::CopyLimitedString(name, CHROLIS_SHUTTER_NAME); + CDeviceUtils::CopyLimitedString(name, CHROLIS_HUB_NAME); } bool ChrolisHub::Busy() @@ -145,7 +159,7 @@ int ChrolisShutter::Initialize() SetParentID(hubLabel); // for backward comp. } else - LogMessage(NoHubError); + LogMessage("No Hub"); return DEVICE_OK; } @@ -224,7 +238,7 @@ int ChrolisStateDevice::Initialize() SetParentID(hubLabel); // for backward comp. } else - LogMessage(NoHubError); + LogMessage("No Hub"); // create default positions and labels const int bufSize = 1024; @@ -251,7 +265,7 @@ int ChrolisStateDevice::Shutdown() void ChrolisStateDevice::GetName(char* name) const { - CDeviceUtils::CopyLimitedString(name, CHROLIS_SHUTTER_NAME); + CDeviceUtils::CopyLimitedString(name, CHROLIS_STATE_NAME); } bool ChrolisStateDevice::Busy() @@ -315,7 +329,8 @@ int ChrolisStateDevice::OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct) //Chrolis Power Control (Genric Device) Methods -ChrolisPowerControl::ChrolisPowerControl() : ledMaxPower_(100), ledMinPower_(0), ledPower_(0) +ChrolisPowerControl::ChrolisPowerControl() : + ledMaxPower_(100), ledMinPower_(0), led1Power_(0), led2Power_(0), led3Power_(0), led4Power_(0), led5Power_(0), led6Power_(0) { InitializeDefaultErrorMessages(); //SetErrorText(ERR_UNKNOWN_POSITION, "Requested position not available in this device"); @@ -334,11 +349,18 @@ int ChrolisPowerControl::Initialize() SetParentID(hubLabel); // for backward comp. } else - LogMessage(NoHubError); + LogMessage("No Hub"); - //State Property + //Properties for power control CPropertyAction* pAct = new CPropertyAction(this, &ChrolisPowerControl::OnPowerChange); - auto err = CreateIntegerProperty(MM::g_Keyword_Label, 0, false, pAct); + auto err = CreateFloatProperty("LED 1", 0, false, pAct); + SetPropertyLimits("LED 1 Power", ledMinPower_, ledMaxPower_); + if (err != 0) + { + return DEVICE_ERR; + LogMessage("Error with property set in power control"); + } + return DEVICE_OK; } @@ -349,7 +371,7 @@ int ChrolisPowerControl::Shutdown() void ChrolisPowerControl::GetName(char* name) const { - CDeviceUtils::CopyLimitedString(name, CHROLIS_SHUTTER_NAME); + CDeviceUtils::CopyLimitedString(name, CHROLIS_GENERIC_DEVICE_NAME); } bool ChrolisPowerControl::Busy() @@ -361,16 +383,16 @@ int ChrolisPowerControl::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType e { if (eAct == MM::BeforeGet) { - pProp->Set((long)ledPower_); + pProp->Set((long)led1Power_); // nothing to do, let the caller to use cached property } else if (eAct == MM::AfterSet) { - long val; + double val; pProp->Get(val); if (val > ledMaxPower_ || val < ledMinPower_) { - pProp->Set((long)ledPower_); // revert + pProp->Set((long)led1Power_); // revert return ERR_UNKNOWN_LED_STATE; } // Do something with the incoming state info @@ -385,7 +407,10 @@ int ChrolisPowerControl::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType e return DEVICE_ERR; } - //TODO Add code for power control + ViInt16 states[] = {0,(int)val,(int)val,(int)val,(int)val,0}; + wrapperInstance->SetLEDPowerStates(states); + led1Power_ = (int)val; + return DEVICE_OK; } diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 913459d85..22f968f1a 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -1,10 +1,10 @@ #pragma once #include #include "DeviceBase.h" -#define CHROLIS_HUB_NAME "CHROLIS_Hub" +#define CHROLIS_HUB_NAME "CHROLIS" #define CHROLIS_SHUTTER_NAME "CHROLIS_Shutter" -#define CHROLIS_STATE_NAME "CHROLIS_State_Device" -#define CHROLIS_GENERIC_DEVICE_NAME "CHROLIS_Generic_Device" +#define CHROLIS_STATE_NAME "CHROLIS_Enable_States" +#define CHROLIS_GENERIC_DEVICE_NAME "CHROLIS_Power_Control" //Custom Error Codes #define ERR_UNKNOWN_MODE 102 @@ -14,8 +14,6 @@ #define ERR_STAGE_MOVING 106 #define HUB_NOT_AVAILABLE 107 -const char* NoHubError = "Parent Hub not defined."; - class ChrolisHub : public HubBase { public: @@ -109,7 +107,13 @@ class ChrolisPowerControl : public CGenericBase int OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct); private: - ViInt16 ledPower_; + ViInt16 led1Power_; + ViInt16 led2Power_; + ViInt16 led3Power_; + ViInt16 led4Power_; + ViInt16 led5Power_; + ViInt16 led6Power_; + ViInt16 ledMaxPower_; ViInt16 ledMinPower_; }; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 532464c20..74a97d2b9 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -3,6 +3,7 @@ ThorlabsChrolisDeviceWrapper::ThorlabsChrolisDeviceWrapper() { + deviceInUse_ = false; deviceConnected_ = false; masterSwitchState_ = false; deviceHandle_ = -1; @@ -100,6 +101,7 @@ bool ThorlabsChrolisDeviceWrapper::IsDeviceConnected() int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean(&states)[6]) { *states = *savedEnabledStates; + return DEVICE_OK; } int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) From 4c252ca3e85b101699848d68f94dcdb40e01f99d Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Wed, 11 Oct 2023 13:44:59 -0400 Subject: [PATCH 10/91] removing power control generic device. Commented for now while it's transferred --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 151 +++++++++++------- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 49 +++--- 2 files changed, 127 insertions(+), 73 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 58a08cbae..b2be6406d 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -2,6 +2,8 @@ #include "ModuleInterface.h" #include +#include +using namespace std; /* * Questions for Mark @@ -17,6 +19,23 @@ * Error handling on device control methods * custom errors and messages * logs for errors +* Remove HubID Property +* Integer property range 0 to 1 for each LED on off +* Is sequencable property for each device check arduino implementation +* No need for sequence stuff in CHROLIS. Should check if breakout box needs to be enabled in software +* no need for event callbacks in UI for triggering +* Keep LED control in State Device +* Maybe keep triggering in Generic if that gets implemented +* pre-init properties in constructor +* set error text in constructor +* enumerate in constructor +* no logging in constructor +* store error in device instance +* after constructor, needs to be safe to call shutdown or destructor +* device specific properties in the hub +* state device allowed values added individually for drop down +* leave state as text box - integer property +* put wavelength in property name */ MODULE_API void InitializeModuleData() { @@ -29,9 +48,9 @@ MODULE_API void InitializeModuleData() { RegisterDevice(CHROLIS_STATE_NAME, MM::StateDevice, "Thorlabs CHROLIS Enable State"); - RegisterDevice(CHROLIS_GENERIC_DEVICE_NAME, - MM::GenericDevice, - "Thorlabs CHROLIS Power Control"); + //RegisterDevice(CHROLIS_GENERIC_DEVICE_NAME, + // MM::GenericDevice, + // "Thorlabs CHROLIS Power Control"); } MODULE_API MM::Device* CreateDevice(char const* name) { @@ -47,8 +66,8 @@ MODULE_API MM::Device* CreateDevice(char const* name) { if (name == std::string(CHROLIS_STATE_NAME)) return new ChrolisStateDevice(); - if (name == std::string(CHROLIS_GENERIC_DEVICE_NAME)) - return new ChrolisPowerControl(); + //if (name == std::string(CHROLIS_GENERIC_DEVICE_NAME)) + // return new ChrolisPowerControl(); return nullptr; } @@ -240,6 +259,16 @@ int ChrolisStateDevice::Initialize() else LogMessage("No Hub"); + //Properties for power control + CPropertyAction* pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); + auto err = CreateFloatProperty("LED 1", 0, false, pAct); + SetPropertyLimits("LED 1 Power", ledMinPower_, ledMaxPower_); + if (err != 0) + { + return DEVICE_ERR; + LogMessage("Error with property set in power control"); + } + // create default positions and labels const int bufSize = 1024; char buf[bufSize]; @@ -327,60 +356,19 @@ int ChrolisStateDevice::OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct) return DEVICE_OK; } - -//Chrolis Power Control (Genric Device) Methods -ChrolisPowerControl::ChrolisPowerControl() : - ledMaxPower_(100), ledMinPower_(0), led1Power_(0), led2Power_(0), led3Power_(0), led4Power_(0), led5Power_(0), led6Power_(0) +int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct) { - InitializeDefaultErrorMessages(); - //SetErrorText(ERR_UNKNOWN_POSITION, "Requested position not available in this device"); - //EnableDelay(); // signals that the delay setting will be used - CreateHubIDProperty(); -} + regex regexp("s[a-z_]+"); + match_results m; + regex_search(pProp->GetName().c_str(), m, regexp); - -int ChrolisPowerControl::Initialize() -{ - ChrolisHub* pHub = static_cast(GetParentHub()); - if (pHub) + ViPInt16 ledBeingControlled; + switch () { - char hubLabel[MM::MaxStrLength]; - pHub->GetLabel(hubLabel); - SetParentID(hubLabel); // for backward comp. + default: + break; } - else - LogMessage("No Hub"); - //Properties for power control - CPropertyAction* pAct = new CPropertyAction(this, &ChrolisPowerControl::OnPowerChange); - auto err = CreateFloatProperty("LED 1", 0, false, pAct); - SetPropertyLimits("LED 1 Power", ledMinPower_, ledMaxPower_); - if (err != 0) - { - return DEVICE_ERR; - LogMessage("Error with property set in power control"); - } - - return DEVICE_OK; -} - -int ChrolisPowerControl::Shutdown() -{ - return DEVICE_OK; -} - -void ChrolisPowerControl::GetName(char* name) const -{ - CDeviceUtils::CopyLimitedString(name, CHROLIS_GENERIC_DEVICE_NAME); -} - -bool ChrolisPowerControl::Busy() -{ - return false; -} - -int ChrolisPowerControl::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct) -{ if (eAct == MM::BeforeGet) { pProp->Set((long)led1Power_); @@ -407,7 +395,7 @@ int ChrolisPowerControl::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType e return DEVICE_ERR; } - ViInt16 states[] = {0,(int)val,(int)val,(int)val,(int)val,0}; + ViInt16 states[] = { 0,(int)val,(int)val,(int)val,(int)val,0 }; wrapperInstance->SetLEDPowerStates(states); led1Power_ = (int)val; @@ -420,3 +408,56 @@ int ChrolisPowerControl::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType e return DEVICE_OK; } + +//Chrolis Power Control (Genric Device) Methods +//ChrolisPowerControl::ChrolisPowerControl() : +// ledMaxPower_(100), ledMinPower_(0), led1Power_(0), led2Power_(0), led3Power_(0), led4Power_(0), led5Power_(0), led6Power_(0) +//{ +// InitializeDefaultErrorMessages(); +// //SetErrorText(ERR_UNKNOWN_POSITION, "Requested position not available in this device"); +// //EnableDelay(); // signals that the delay setting will be used +// CreateHubIDProperty(); +//} +// + +//int ChrolisPowerControl::Initialize() +//{ +// ChrolisHub* pHub = static_cast(GetParentHub()); +// if (pHub) +// { +// char hubLabel[MM::MaxStrLength]; +// pHub->GetLabel(hubLabel); +// SetParentID(hubLabel); // for backward comp. +// } +// else +// LogMessage("No Hub"); +// +// //Properties for power control +// CPropertyAction* pAct = new CPropertyAction(this, &ChrolisPowerControl::OnPowerChange); +// auto err = CreateFloatProperty("LED 1", 0, false, pAct); +// SetPropertyLimits("LED 1 Power", ledMinPower_, ledMaxPower_); +// if (err != 0) +// { +// return DEVICE_ERR; +// LogMessage("Error with property set in power control"); +// } +// +// return DEVICE_OK; +//} +// +//int ChrolisPowerControl::Shutdown() +//{ +// return DEVICE_OK; +//} +// +//void ChrolisPowerControl::GetName(char* name) const +//{ +// CDeviceUtils::CopyLimitedString(name, CHROLIS_GENERIC_DEVICE_NAME); +//} +// +//bool ChrolisPowerControl::Busy() +//{ +// return false; +//} + + diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 22f968f1a..8124c8b34 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -85,28 +85,13 @@ class ChrolisStateDevice : public CStateDeviceBase int OnState(MM::PropertyBase* pProp, MM::ActionType eAct); int OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct); + //LED Control Methods + int OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct); + private: long curLedState_; long numPos_; -}; - -class ChrolisPowerControl : public CGenericBase -{ -public: - ChrolisPowerControl(); - - ~ChrolisPowerControl() - {} - int Initialize(); - int Shutdown(); - void GetName(char* pszName) const; - bool Busy(); - - //Label Update - int OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct); - -private: ViInt16 led1Power_; ViInt16 led2Power_; ViInt16 led3Power_; @@ -118,6 +103,34 @@ class ChrolisPowerControl : public CGenericBase ViInt16 ledMinPower_; }; +//class ChrolisPowerControl : public CGenericBase +//{ +//public: +// ChrolisPowerControl(); +// +// ~ChrolisPowerControl() +// {} +// +// int Initialize(); +// int Shutdown(); +// void GetName(char* pszName) const; +// bool Busy(); +// +// //Label Update +// int OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct); +// +//private: +// ViInt16 led1Power_; +// ViInt16 led2Power_; +// ViInt16 led3Power_; +// ViInt16 led4Power_; +// ViInt16 led5Power_; +// ViInt16 led6Power_; +// +// ViInt16 ledMaxPower_; +// ViInt16 ledMinPower_; +//}; + //Wrapper for the basic functions used in this device adapter class ThorlabsChrolisDeviceWrapper { From 1b0c7d902fc2757e0c02d8fb7f1edbacadbd7be4 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Thu, 12 Oct 2023 08:28:30 -0400 Subject: [PATCH 11/91] bug fixes and some property changes --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 283 ++++++++++++++++-- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 12 +- .../ThorlabsChrolisDeviceWrapper.cpp | 9 +- 3 files changed, 274 insertions(+), 30 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index b2be6406d..b288cdef9 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -36,6 +36,7 @@ using namespace std; * state device allowed values added individually for drop down * leave state as text box - integer property * put wavelength in property name +* position labels? */ MODULE_API void InitializeModuleData() { @@ -47,7 +48,7 @@ MODULE_API void InitializeModuleData() { "Thorlabs CHROLIS Shutter"); RegisterDevice(CHROLIS_STATE_NAME, MM::StateDevice, - "Thorlabs CHROLIS Enable State"); + "Thorlabs CHROLIS LED Control"); //RegisterDevice(CHROLIS_GENERIC_DEVICE_NAME, // MM::GenericDevice, // "Thorlabs CHROLIS Power Control"); @@ -238,8 +239,9 @@ int ChrolisShutter::GetOpen(bool& open) //Chrolis State Device Methods ChrolisStateDevice::ChrolisStateDevice() : - numPos_(6), - curLedState_(0) + numPos_(6),curLedState_(0), ledMaxPower_(100), ledMinPower_(0), + led1Power_(0), led2Power_(0), led3Power_(0), led4Power_(0), led5Power_(0), led6Power_(0), + led1State_(false), led2State_(false), led3State_(false), led4State_(false), led5State_(false), led6State_(false) { InitializeDefaultErrorMessages(); //SetErrorText(ERR_UNKNOWN_POSITION, "Requested position not available in this device"); @@ -247,7 +249,7 @@ ChrolisStateDevice::ChrolisStateDevice() : CreateHubIDProperty(); } -int ChrolisStateDevice::Initialize() +int ChrolisStateDevice::Initialize() //TODO: Initialized property? { ChrolisHub* pHub = static_cast(GetParentHub()); if (pHub) @@ -259,16 +261,6 @@ int ChrolisStateDevice::Initialize() else LogMessage("No Hub"); - //Properties for power control - CPropertyAction* pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - auto err = CreateFloatProperty("LED 1", 0, false, pAct); - SetPropertyLimits("LED 1 Power", ledMinPower_, ledMaxPower_); - if (err != 0) - { - return DEVICE_ERR; - LogMessage("Error with property set in power control"); - } - // create default positions and labels const int bufSize = 1024; char buf[bufSize]; @@ -284,6 +276,118 @@ int ChrolisStateDevice::Initialize() if (err != DEVICE_OK) return err; + + ////Properties for power control + pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); + err = CreateFloatProperty("LED 1 Power", 0.0, false, pAct); + if (err != 0) + { + LogMessage("Error with property set in power control"); + return DEVICE_ERR; + } + SetPropertyLimits("LED 1 Power", ledMinPower_, ledMaxPower_); + + pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); + err = CreateFloatProperty("LED 2 Power", 0, false, pAct); + SetPropertyLimits("LED 2 Power", ledMinPower_, ledMaxPower_); + if (err != 0) + { + return DEVICE_ERR; + LogMessage("Error with property set in state control"); + } + + pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); + err = CreateFloatProperty("LED 3 Power", 0, false, pAct); + SetPropertyLimits("LED 3 Power", ledMinPower_, ledMaxPower_); + if (err != 0) + { + return DEVICE_ERR; + LogMessage("Error with property set in state control"); + } + + pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); + err = CreateFloatProperty("LED 4 Power", 0, false, pAct); + SetPropertyLimits("LED 4 Power", ledMinPower_, ledMaxPower_); + if (err != 0) + { + return DEVICE_ERR; + LogMessage("Error with property set in state control"); + } + + pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); + err = CreateFloatProperty("LED 5 Power", 0, false, pAct); + SetPropertyLimits("LED 5 Power", ledMinPower_, ledMaxPower_); + if (err != 0) + { + return DEVICE_ERR; + LogMessage("Error with property set in state control"); + } + + pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); + err = CreateFloatProperty("LED 6 Power", 0, false, pAct); + SetPropertyLimits("LED 6 Power", ledMinPower_, ledMaxPower_); + if (err != 0) + { + return DEVICE_ERR; + LogMessage("Error with property set in state control"); + } + + + //Properties for state control + pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); + err = CreateIntegerProperty("LED Enable State 1", 0, false, pAct); + if (err != 0) + { + LogMessage("Error with property set in state control"); + return DEVICE_ERR; + } + SetPropertyLimits("LED Enable State 1", 0, 1); + + pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); + err = CreateIntegerProperty("LED Enable State 2", 0, false, pAct); + if (err != 0) + { + LogMessage("Error with property set in state control"); + return DEVICE_ERR; + } + SetPropertyLimits("LED Enable State 2", 0, 1); + + pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); + err = CreateIntegerProperty("LED Enable State 3", 0, false, pAct); + if (err != 0) + { + LogMessage("Error with property set in state control"); + return DEVICE_ERR; + } + SetPropertyLimits("LED Enable State 3", 0, 1); + + pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); + err = CreateIntegerProperty("LED Enable State 4", 0, false, pAct); + if (err != 0) + { + LogMessage("Error with property set in state control"); + return DEVICE_ERR; + } + SetPropertyLimits("LED Enable State 4", 0, 1); + + pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); + err = CreateIntegerProperty("LED Enable State 5", 0, false, pAct); + if (err != 0) + { + LogMessage("Error with property set in state control"); + return DEVICE_ERR; + } + SetPropertyLimits("LED Enable State 5", 0, 1); + + pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); + err = CreateIntegerProperty("LED Enable State 6", 0, false, pAct); + if (err != 0) + { + LogMessage("Error with property set in state control"); + return DEVICE_ERR; + } + SetPropertyLimits("LED Enable State 6", 0, 1); + return DEVICE_OK; } @@ -302,6 +406,16 @@ bool ChrolisStateDevice::Busy() return false; } +int ChrolisStateDevice::OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + return DEVICE_OK; +} + +//OnPropertyChanged("AsyncPropertyFollower", leaderValue.c_str()); +//Update onState to use binary value +//single state changes should modify the single led, verify that it was changed, update global state long, onchange OnState +// Update states of properties based on initial values +//Error check hardware calls and revert properties if something fails int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) { if (eAct == MM::BeforeGet) @@ -347,31 +461,149 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) return DEVICE_OK; } else if (eAct == MM::IsSequenceable) - {} + { + } return DEVICE_OK; } -int ChrolisStateDevice::OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct) +int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct) { + ViPBoolean ledBeingControlled; + int numFromName = -1; + std::string searchString = pProp->GetName(); + regex regexp("[-+]?([0-9]*\.[0-9]+|[0-9]+)"); + std::smatch sm; + regex_search(searchString, sm, regexp); + + //The names for the LED's should contain only a single number representing the LED + //Use this to set the power + if (sm.size() > 0) + { + if (sm[0].str().length() > 0) + { + numFromName = stoi(sm[0].str()); + } + } + else + { + LogMessage("Regex match failed"); + return DEVICE_ERR; + } + + switch (numFromName) + { + case 1: + ledBeingControlled = &led1State_; + break; + case 2: + ledBeingControlled = &led2State_; + break; + case 3: + ledBeingControlled = &led3State_; + break; + case 4: + ledBeingControlled = &led4State_; + break; + case 5: + ledBeingControlled = &led5State_; + break; + case 6: + ledBeingControlled = &led6State_; + break; + default: + return DEVICE_ERR; + break; + } + + if (eAct == MM::BeforeGet) + { + pProp->Set((long)*ledBeingControlled); + // nothing to do, let the caller to use cached property + } + else if (eAct == MM::AfterSet) + { + double val; + pProp->Get(val); + if (val > ledMaxPower_ || val < ledMinPower_) + { + pProp->Set((long)*ledBeingControlled); // revert + return ERR_UNKNOWN_LED_STATE; + } + // Do something with the incoming state info + ChrolisHub* pHub = static_cast(GetParentHub()); + if (!pHub || !pHub->IsInitialized()) + { + return DEVICE_ERR; // TODO Add custom error messages + } + ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + if (!wrapperInstance->IsDeviceConnected()) + { + return DEVICE_ERR; + } + + wrapperInstance->SetSingleLEDEnableState(numFromName-1, (ViBoolean)val); + *ledBeingControlled = (ViBoolean)val; + + return DEVICE_OK; + } + else if (eAct == MM::IsSequenceable) + { + } return DEVICE_OK; } int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct) { - regex regexp("s[a-z_]+"); - match_results m; - regex_search(pProp->GetName().c_str(), m, regexp); - ViPInt16 ledBeingControlled; - switch () + int numFromName = -1; + std::string searchString = pProp->GetName(); + regex regexp("[-+]?([0-9]*\.[0-9]+|[0-9]+)"); + std::smatch sm; + regex_search(searchString, sm, regexp); + + //The names for the LED's should contain only a single number representing the LED + //Use this to set the power + if (sm.size() > 0) + { + if (sm[0].str().length() > 0) + { + numFromName = stoi(sm[0].str()); + } + } + else + { + LogMessage("Regex match failed"); + return DEVICE_ERR; + } + + switch (numFromName) { + case 1: + ledBeingControlled = &led1Power_; + break; + case 2: + ledBeingControlled = &led2Power_; + break; + case 3: + ledBeingControlled = &led3Power_; + break; + case 4: + ledBeingControlled = &led4Power_; + break; + case 5: + ledBeingControlled = &led5Power_; + break; + case 6: + ledBeingControlled = &led6Power_; + break; default: + return DEVICE_ERR; break; } if (eAct == MM::BeforeGet) { - pProp->Set((long)led1Power_); + pProp->Set((long)*ledBeingControlled); // nothing to do, let the caller to use cached property } else if (eAct == MM::AfterSet) @@ -380,7 +612,7 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA pProp->Get(val); if (val > ledMaxPower_ || val < ledMinPower_) { - pProp->Set((long)led1Power_); // revert + pProp->Set((long)*ledBeingControlled); // revert return ERR_UNKNOWN_LED_STATE; } // Do something with the incoming state info @@ -395,9 +627,8 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA return DEVICE_ERR; } - ViInt16 states[] = { 0,(int)val,(int)val,(int)val,(int)val,0 }; - wrapperInstance->SetLEDPowerStates(states); - led1Power_ = (int)val; + wrapperInstance->SetSingleLEDPowerState(numFromName-1, val); + *ledBeingControlled = (int)val; return DEVICE_OK; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 8124c8b34..3c6cf001e 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -3,8 +3,8 @@ #include "DeviceBase.h" #define CHROLIS_HUB_NAME "CHROLIS" #define CHROLIS_SHUTTER_NAME "CHROLIS_Shutter" -#define CHROLIS_STATE_NAME "CHROLIS_Enable_States" -#define CHROLIS_GENERIC_DEVICE_NAME "CHROLIS_Power_Control" +#define CHROLIS_STATE_NAME "CHROLIS_LED_Control" +//#define CHROLIS_GENERIC_DEVICE_NAME "CHROLIS_Power_Control" //Custom Error Codes #define ERR_UNKNOWN_MODE 102 @@ -87,6 +87,7 @@ class ChrolisStateDevice : public CStateDeviceBase //LED Control Methods int OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct); private: long curLedState_; @@ -99,6 +100,13 @@ class ChrolisStateDevice : public CStateDeviceBase ViInt16 led5Power_; ViInt16 led6Power_; + ViBoolean led1State_; + ViBoolean led2State_; + ViBoolean led3State_; + ViBoolean led4State_; + ViBoolean led5State_; + ViBoolean led6State_; + ViInt16 ledMaxPower_; ViInt16 ledMinPower_; }; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 74a97d2b9..01397d7df 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -154,7 +154,7 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean sta if (LED < 6 && LED >= 0) { savedEnabledStates[LED] = state; - if (SetLEDEnableStates(savedEnabledStates)) + if (!SetLEDEnableStates(savedEnabledStates)) { return DEVICE_OK; } @@ -173,7 +173,7 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDPowerState(int LED, ViInt16 state) { ViInt16 tmpPower = savedPowerStates[LED]; savedPowerStates[LED] = state; - if (SetLEDPowerStates(savedPowerStates)) + if (!SetLEDPowerStates(savedPowerStates)) { return DEVICE_OK; } @@ -211,4 +211,9 @@ int ThorlabsChrolisDeviceWrapper::GetShutterState(bool& open) { open = masterSwitchState_; return DEVICE_OK; +} + +long GetIntegerStateValue() +{ + return 0; } \ No newline at end of file From ec29cdff6836e5331dbf6a6a9a7c26d8af15bbf3 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Thu, 12 Oct 2023 10:40:21 -0400 Subject: [PATCH 12/91] new methods in wrapper and property updates in hub init --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 38 ++++++++++++++ .../ThorlabsCHROLIS/ThorlabsChrolis.h | 4 ++ .../ThorlabsChrolisDeviceWrapper.cpp | 49 ++++++++++++++++++- 3 files changed, 90 insertions(+), 1 deletion(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index b288cdef9..7aefcbb38 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -119,6 +119,44 @@ int ChrolisHub::Initialize() LogMessage("Error in CHROLIS Initialization"); return DEVICE_ERR; } + + ViChar sNum[256]; + static_cast(chrolisDeviceInstance_)->GetSerialNumber(sNum); + err = CreateStringProperty("Serial Number", sNum, true); + if (err != 0) + { + LogMessage("Error with property set in hub control"); + return DEVICE_ERR; + } + + ViChar manfName[256]; + static_cast(chrolisDeviceInstance_)->GetManufacturerName(manfName); + err = CreateStringProperty("Manufacturer Name", manfName, true); + if (err != 0) + { + LogMessage("Error with property set in hub control"); + return DEVICE_ERR; + } + + std::string wavelengthList = ""; + ViUInt16 wavelengths[6]; + err = static_cast(chrolisDeviceInstance_)->GetLEDWavelengths(wavelengths); + if (err == NULL) + { + LogMessage("Error with property set in hub control"); + return DEVICE_ERR; + } + for (int i = 0; i < 6; i ++) + { + wavelengthList += wavelengths[i] + ","; + } + err = CreateStringProperty("Available Wavelengths", wavelengthList.c_str(), true); + if (err != 0) + { + LogMessage("Error with property set in hub control"); + return DEVICE_ERR; + } + initialized_ = true; } return DEVICE_OK; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 3c6cf001e..0db24e5d0 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -149,6 +149,9 @@ class ThorlabsChrolisDeviceWrapper int InitializeDevice(std::string serialNumber = ""); int ShutdownDevice(); bool IsDeviceConnected(); + int GetSerialNumber(ViChar* serialNumber); + int GetManufacturerName(ViChar* manfName); + int GetLEDWavelengths(ViUInt16(&wavelengths)[6]); int GetLEDEnableStates(ViBoolean (&states)[6]); int SetLEDEnableStates(ViBoolean states[6]); int SetLEDPowerStates(ViInt16 states[6]); @@ -168,5 +171,6 @@ class ThorlabsChrolisDeviceWrapper bool masterSwitchState_; ViBoolean savedEnabledStates[6]{false,false,false,false,false,false}; ViInt16 savedPowerStates[6]{0,0,0,0,0,0}; + ViUInt16 ledWavelengths[6]{0,0,0,0,0,0}; }; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 01397d7df..948ee3784 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -76,6 +76,16 @@ int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) } deviceConnected_ = true; + for (int i = 0; i < numLEDs_; i++) + { + err = TL6WL_readLED_HeadCentroidWL(deviceHandle_, i, &ledWavelengths[i]); + if (err != 0) + { + //Error reading head wavelengths + return DEVICE_ERR; + } + } + return DEVICE_OK; } @@ -98,6 +108,43 @@ bool ThorlabsChrolisDeviceWrapper::IsDeviceConnected() return deviceConnected_; } +int ThorlabsChrolisDeviceWrapper::GetSerialNumber(ViChar* serialNumber) +{ + if (deviceConnected_) + { + serialNumber = serialNumber_; + } + else + { + serialNumber = (ViChar*)"NOT INITIALIZED"; + } + return DEVICE_OK; +} + +int ThorlabsChrolisDeviceWrapper::GetManufacturerName(ViChar* manfName) +{ + if (deviceConnected_) + { + manfName = manufacturerName_; + } + else + { + manfName = (ViChar*)"NOT INITIALIZED"; + } + return DEVICE_OK; +} + +int ThorlabsChrolisDeviceWrapper::GetLEDWavelengths(ViUInt16(&wavelengths)[6]) +{ + if (!deviceConnected_) + { + *wavelengths = NULL; + return DEVICE_ERR; + } + *wavelengths = *ledWavelengths; + return DEVICE_OK; +} + int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean(&states)[6]) { *states = *savedEnabledStates; @@ -198,7 +245,7 @@ int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) } else { - if (int err = TL6WL_setLED_HeadPowerStates(deviceHandle_, true, true, true, true, true, true) != 0) + if (int err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates[0], savedEnabledStates[1], savedEnabledStates[2], savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]) != 0) { return DEVICE_ERR; } From b9d80b592c3b2fc6e4ef789bf2f9de65b5b171dd Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Thu, 12 Oct 2023 11:39:43 -0400 Subject: [PATCH 13/91] Updated init code for state and hub --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 36 +++++---- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 26 +++--- .../ThorlabsChrolisDeviceWrapper.cpp | 81 ++++++++++++++++++- 3 files changed, 116 insertions(+), 27 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 7aefcbb38..4a736c8ef 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -307,17 +307,25 @@ int ChrolisStateDevice::Initialize() //TODO: Initialized property? snprintf(buf, bufSize, "-%ld", i); SetPositionLabel(i, buf); } + int err; + + ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + if (wrapperInstance->IsDeviceConnected()) + { + err = wrapperInstance->GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_); + err = wrapperInstance->GetLEDPowerStates(led1Power_, led2Power_, led3Power_, led4Power_, led5Power_, led6Power_); + } //State Property CPropertyAction* pAct = new CPropertyAction(this, &ChrolisStateDevice::OnState); - auto err = CreateIntegerProperty(MM::g_Keyword_State, 0, false, pAct); + err = CreateIntegerProperty(MM::g_Keyword_State, 0, false, pAct); if (err != DEVICE_OK) return err; ////Properties for power control pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateFloatProperty("LED 1 Power", 0.0, false, pAct); + err = CreateIntegerProperty("LED 1 Power", led1Power_, false, pAct); if (err != 0) { LogMessage("Error with property set in power control"); @@ -326,7 +334,7 @@ int ChrolisStateDevice::Initialize() //TODO: Initialized property? SetPropertyLimits("LED 1 Power", ledMinPower_, ledMaxPower_); pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateFloatProperty("LED 2 Power", 0, false, pAct); + err = CreateIntegerProperty("LED 2 Power", led2Power_, false, pAct); SetPropertyLimits("LED 2 Power", ledMinPower_, ledMaxPower_); if (err != 0) { @@ -335,7 +343,7 @@ int ChrolisStateDevice::Initialize() //TODO: Initialized property? } pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateFloatProperty("LED 3 Power", 0, false, pAct); + err = CreateIntegerProperty("LED 3 Power", led3Power_, false, pAct); SetPropertyLimits("LED 3 Power", ledMinPower_, ledMaxPower_); if (err != 0) { @@ -344,7 +352,7 @@ int ChrolisStateDevice::Initialize() //TODO: Initialized property? } pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateFloatProperty("LED 4 Power", 0, false, pAct); + err = CreateIntegerProperty("LED 4 Power", led4Power_, false, pAct); SetPropertyLimits("LED 4 Power", ledMinPower_, ledMaxPower_); if (err != 0) { @@ -353,7 +361,7 @@ int ChrolisStateDevice::Initialize() //TODO: Initialized property? } pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateFloatProperty("LED 5 Power", 0, false, pAct); + err = CreateIntegerProperty("LED 5 Power", led5Power_, false, pAct); SetPropertyLimits("LED 5 Power", ledMinPower_, ledMaxPower_); if (err != 0) { @@ -362,7 +370,7 @@ int ChrolisStateDevice::Initialize() //TODO: Initialized property? } pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateFloatProperty("LED 6 Power", 0, false, pAct); + err = CreateIntegerProperty("LED 6 Power", led6Power_, false, pAct); SetPropertyLimits("LED 6 Power", ledMinPower_, ledMaxPower_); if (err != 0) { @@ -373,7 +381,7 @@ int ChrolisStateDevice::Initialize() //TODO: Initialized property? //Properties for state control pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 1", 0, false, pAct); + err = CreateIntegerProperty("LED Enable State 1", led1State_, false, pAct); if (err != 0) { LogMessage("Error with property set in state control"); @@ -382,7 +390,7 @@ int ChrolisStateDevice::Initialize() //TODO: Initialized property? SetPropertyLimits("LED Enable State 1", 0, 1); pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 2", 0, false, pAct); + err = CreateIntegerProperty("LED Enable State 2", led2State_, false, pAct); if (err != 0) { LogMessage("Error with property set in state control"); @@ -391,7 +399,7 @@ int ChrolisStateDevice::Initialize() //TODO: Initialized property? SetPropertyLimits("LED Enable State 2", 0, 1); pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 3", 0, false, pAct); + err = CreateIntegerProperty("LED Enable State 3", led3State_, false, pAct); if (err != 0) { LogMessage("Error with property set in state control"); @@ -400,7 +408,7 @@ int ChrolisStateDevice::Initialize() //TODO: Initialized property? SetPropertyLimits("LED Enable State 3", 0, 1); pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 4", 0, false, pAct); + err = CreateIntegerProperty("LED Enable State 4", led4State_, false, pAct); if (err != 0) { LogMessage("Error with property set in state control"); @@ -409,7 +417,7 @@ int ChrolisStateDevice::Initialize() //TODO: Initialized property? SetPropertyLimits("LED Enable State 4", 0, 1); pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 5", 0, false, pAct); + err = CreateIntegerProperty("LED Enable State 5", led5State_, false, pAct); if (err != 0) { LogMessage("Error with property set in state control"); @@ -418,7 +426,7 @@ int ChrolisStateDevice::Initialize() //TODO: Initialized property? SetPropertyLimits("LED Enable State 5", 0, 1); pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 6", 0, false, pAct); + err = CreateIntegerProperty("LED Enable State 6", led6Power_, false, pAct); if (err != 0) { LogMessage("Error with property set in state control"); @@ -592,7 +600,7 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct) { - ViPInt16 ledBeingControlled; + ViPUInt16 ledBeingControlled; int numFromName = -1; std::string searchString = pProp->GetName(); regex regexp("[-+]?([0-9]*\.[0-9]+|[0-9]+)"); diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 0db24e5d0..8da0c7f34 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -39,7 +39,7 @@ class ChrolisHub : public HubBase class ChrolisShutter : public CShutterBase //CRTP { - ViBoolean savedEnabledStates[6]{ false,false,false,false,false,false}; + ViBoolean savedEnabledStates[6]{ false,false,false,false,false,false}; // should remove these bool masterShutterState = false; public: @@ -93,12 +93,12 @@ class ChrolisStateDevice : public CStateDeviceBase long curLedState_; long numPos_; - ViInt16 led1Power_; - ViInt16 led2Power_; - ViInt16 led3Power_; - ViInt16 led4Power_; - ViInt16 led5Power_; - ViInt16 led6Power_; + ViUInt16 led1Power_; + ViUInt16 led2Power_; + ViUInt16 led3Power_; + ViUInt16 led4Power_; + ViUInt16 led5Power_; + ViUInt16 led6Power_; ViBoolean led1State_; ViBoolean led2State_; @@ -152,13 +152,17 @@ class ThorlabsChrolisDeviceWrapper int GetSerialNumber(ViChar* serialNumber); int GetManufacturerName(ViChar* manfName); int GetLEDWavelengths(ViUInt16(&wavelengths)[6]); - int GetLEDEnableStates(ViBoolean (&states)[6]); + int GetLEDEnableStates(ViBoolean(&states)[6]); + int GetLEDEnableStates(ViBoolean& led1State, ViBoolean& led2State, ViBoolean& led3State, ViBoolean& led4State, ViBoolean& led5State, ViBoolean& led6State); int SetLEDEnableStates(ViBoolean states[6]); - int SetLEDPowerStates(ViInt16 states[6]); + int GetLEDPowerStates(ViUInt16(&states)[6]); + int GetLEDPowerStates(ViUInt16 &led1Power, ViUInt16&led2Power, ViUInt16&led3Power, ViUInt16&led4Power, ViUInt16&led5Power, ViUInt16&led6Power); + int SetLEDPowerStates(ViUInt16 states[6]); int SetSingleLEDEnableState(int LED, ViBoolean state); - int SetSingleLEDPowerState(int LED, ViInt16 state); + int SetSingleLEDPowerState(int LED, ViUInt16 state); int SetShutterState(bool open); int GetShutterState(bool& open); + bool VerifyLEDStates(); private: int numLEDs_; @@ -170,7 +174,7 @@ class ThorlabsChrolisDeviceWrapper ViChar manufacturerName_[256]; bool masterSwitchState_; ViBoolean savedEnabledStates[6]{false,false,false,false,false,false}; - ViInt16 savedPowerStates[6]{0,0,0,0,0,0}; + ViUInt16 savedPowerStates[6]{0,0,0,0,0,0}; ViUInt16 ledWavelengths[6]{0,0,0,0,0,0}; }; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 948ee3784..bc59f6d68 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -85,6 +85,7 @@ int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) return DEVICE_ERR; } } + VerifyLEDStates(); return DEVICE_OK; } @@ -147,10 +148,31 @@ int ThorlabsChrolisDeviceWrapper::GetLEDWavelengths(ViUInt16(&wavelengths)[6]) int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean(&states)[6]) { + if (!deviceConnected_) + { + *states = NULL; + return DEVICE_ERR; + } *states = *savedEnabledStates; return DEVICE_OK; } +int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean& led1State, ViBoolean& led2State, ViBoolean& led3State, ViBoolean& led4State, ViBoolean& led5State, ViBoolean& led6State) +{ + if (!deviceConnected_) + { + return DEVICE_ERR; + } + led1State = savedEnabledStates[0]; + led2State = savedEnabledStates[1]; + led3State = savedEnabledStates[2]; + led4State = savedEnabledStates[2]; + led5State = savedEnabledStates[4]; + led6State = savedEnabledStates[5]; + + return DEVICE_OK; +} + int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) { if (states == NULL) @@ -175,7 +197,34 @@ int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) return DEVICE_OK; } -int ThorlabsChrolisDeviceWrapper::SetLEDPowerStates(ViInt16 states[6]) +int ThorlabsChrolisDeviceWrapper::GetLEDPowerStates(ViUInt16(&states)[6]) +{ + if (!deviceConnected_) + { + *states = NULL; + return DEVICE_ERR; + } + *states = *savedPowerStates; + return DEVICE_OK; +} + +int ThorlabsChrolisDeviceWrapper::GetLEDPowerStates(ViUInt16& led1Power, ViUInt16& led2Power, ViUInt16& led3Power, ViUInt16& led4Power, ViUInt16& led5Power, ViUInt16& led6Power) +{ + if (!deviceConnected_) + { + return DEVICE_ERR; + } + led1Power = savedPowerStates[0]; + led2Power = savedPowerStates[1]; + led3Power = savedPowerStates[2]; + led4Power = savedPowerStates[2]; + led5Power = savedPowerStates[4]; + led6Power = savedPowerStates[5]; + + return DEVICE_OK; +} + +int ThorlabsChrolisDeviceWrapper::SetLEDPowerStates(ViUInt16 states[6]) { if (states == NULL) { @@ -214,7 +263,7 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean sta return DEVICE_ERR; } -int ThorlabsChrolisDeviceWrapper::SetSingleLEDPowerState(int LED, ViInt16 state) +int ThorlabsChrolisDeviceWrapper::SetSingleLEDPowerState(int LED, ViUInt16 state) { if (LED < 6 && LED >= 0) { @@ -260,6 +309,34 @@ int ThorlabsChrolisDeviceWrapper::GetShutterState(bool& open) return DEVICE_OK; } +//set or fix any issues with the stored led vals. Return if a correction needed to be made +bool ThorlabsChrolisDeviceWrapper::VerifyLEDStates() +{ + if (!deviceConnected_) + { + return false; + } + + bool stateCorrect = true; + ViUInt16 tempPowerStates[6] = {0,0,0,0,0,0}; + ViBoolean tempEnableStates[6] = { false, false, false, false, false, false }; + + TL6WL_getLED_HeadPowerStates(deviceHandle_, &tempEnableStates[0], &tempEnableStates[1], &tempEnableStates[2], &tempEnableStates[3], &tempEnableStates[4], &tempEnableStates[5]); + TL6WL_getLED_HeadBrightness(deviceHandle_, &tempPowerStates[0], &tempPowerStates[1], &tempPowerStates[2], &tempPowerStates[3], &tempPowerStates[4], &tempPowerStates[5]); + + for (int i = 0; i < numLEDs_; i++) + { + if (tempEnableStates[i] != savedEnabledStates[i] || tempPowerStates[i] != savedPowerStates[i]) + { + stateCorrect = false; + savedEnabledStates[i] = tempEnableStates[i]; + savedPowerStates[i] = tempPowerStates[i]; + } + } + + return stateCorrect; +} + long GetIntegerStateValue() { return 0; From a7e5160ead4132746253bf8f6c9b87bcddbadde3 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Thu, 12 Oct 2023 17:10:35 -0400 Subject: [PATCH 14/91] improved error reporting (needs handling) and implementation for state to use binary mask --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 98 +++++++------ .../ThorlabsCHROLIS/ThorlabsChrolis.h | 15 +- .../ThorlabsChrolisDeviceWrapper.cpp | 138 +++++++++++------- 3 files changed, 155 insertions(+), 96 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 4a736c8ef..b607f9dce 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -5,27 +5,19 @@ #include using namespace std; -/* -* Questions for Mark -* 1- Pre-init properties -* 2- Sequencer action for properties and utilizing the sequencer -* 3- Slider bars? -* 4- Non-default property states for state devices -*/ - /*TODO -* Set states of properties based on current LED states -* Properties for device ID and stuff +* Set states of properties based on current LED states - x +* Properties for device ID and stuff - x * Error handling on device control methods * custom errors and messages * logs for errors * Remove HubID Property -* Integer property range 0 to 1 for each LED on off +* Integer property range 0 to 1 for each LED on off - x * Is sequencable property for each device check arduino implementation * No need for sequence stuff in CHROLIS. Should check if breakout box needs to be enabled in software * no need for event callbacks in UI for triggering -* Keep LED control in State Device -* Maybe keep triggering in Generic if that gets implemented +* Keep LED control in State Device - x +* Maybe keep triggering in Generic if that gets implemented * pre-init properties in constructor * set error text in constructor * enumerate in constructor @@ -36,7 +28,8 @@ using namespace std; * state device allowed values added individually for drop down * leave state as text box - integer property * put wavelength in property name -* position labels? +* handle cases for initialization failing +* Julian tester */ MODULE_API void InitializeModuleData() { @@ -141,14 +134,18 @@ int ChrolisHub::Initialize() std::string wavelengthList = ""; ViUInt16 wavelengths[6]; err = static_cast(chrolisDeviceInstance_)->GetLEDWavelengths(wavelengths); - if (err == NULL) + if (err != 0) { LogMessage("Error with property set in hub control"); return DEVICE_ERR; } for (int i = 0; i < 6; i ++) { - wavelengthList += wavelengths[i] + ","; + wavelengthList += std::to_string(wavelengths[i]); + if (i != 5) + { + wavelengthList += ", "; + } } err = CreateStringProperty("Available Wavelengths", wavelengthList.c_str(), true); if (err != 0) @@ -219,6 +216,16 @@ int ChrolisShutter::Initialize() else LogMessage("No Hub"); + ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + if (wrapperInstance->IsDeviceConnected()) + { + auto err = wrapperInstance->SetShutterState(false); + if (err != 0) + { + LogMessage("Could not close shutter on it"); + } + } + return DEVICE_OK; } @@ -314,11 +321,14 @@ int ChrolisStateDevice::Initialize() //TODO: Initialized property? { err = wrapperInstance->GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_); err = wrapperInstance->GetLEDPowerStates(led1Power_, led2Power_, led3Power_, led4Power_, led5Power_, led6Power_); + curLedState_ = + ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) + | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5)); } //State Property CPropertyAction* pAct = new CPropertyAction(this, &ChrolisStateDevice::OnState); - err = CreateIntegerProperty(MM::g_Keyword_State, 0, false, pAct); + err = CreateIntegerProperty(MM::g_Keyword_State, curLedState_, false, pAct); if (err != DEVICE_OK) return err; @@ -466,16 +476,16 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) { if (eAct == MM::BeforeGet) { - pProp->Set(curLedState_); + pProp->Set((long)curLedState_); // nothing to do, let the caller to use cached property } else if (eAct == MM::AfterSet) { - long pos; - pProp->Get(pos); - if (pos >= numPos_ || pos < 0) + long val; + pProp->Get(val); + if (val >= pow(2, numPos_) || val < 0) { - pProp->Set(curLedState_); // revert + pProp->Set((long)curLedState_); // revert return ERR_UNKNOWN_LED_STATE; } // Do something with the incoming state info @@ -490,25 +500,33 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) return DEVICE_ERR; } - ViBoolean curStates[6]; - wrapperInstance->GetLEDEnableStates(curStates); - for (int i = 0; i < 6; i++) + ViBoolean newStates[6] { - curStates[i] = false; - } - curStates[pos] = true; - int err = wrapperInstance->SetLEDEnableStates(curStates); + static_cast(val & (1 << 0)), + static_cast(val & (1 << 1)), + static_cast(val & (1 << 2)), + static_cast(val & (1 << 3)), + static_cast(val & (1 << 4)), + static_cast(val & (1 << 5)) + }; + int err = wrapperInstance->SetLEDEnableStates(newStates); if (err != 0) { return DEVICE_ERR; } - curLedState_ = pos; + led1State_ = static_cast(val & (1 << 0)); + led2State_ = static_cast(val & (1 << 1)); + led3State_ = static_cast(val & (1 << 2)); + led4State_ = static_cast(val & (1 << 3)); + led5State_ = static_cast(val & (1 << 4)); + led6State_ = static_cast(val & (1 << 5)); + + OnPropertiesChanged(); + + curLedState_ = val; return DEVICE_OK; } - else if (eAct == MM::IsSequenceable) - { - } return DEVICE_OK; } @@ -589,12 +607,13 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT wrapperInstance->SetSingleLEDEnableState(numFromName-1, (ViBoolean)val); *ledBeingControlled = (ViBoolean)val; - + curLedState_ = + ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) + | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5)); + OnPropertiesChanged(); return DEVICE_OK; } - else if (eAct == MM::IsSequenceable) - { - } + return DEVICE_OK; } @@ -675,13 +694,10 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA wrapperInstance->SetSingleLEDPowerState(numFromName-1, val); *ledBeingControlled = (int)val; - + OnPropertiesChanged(); return DEVICE_OK; } - else if (eAct == MM::IsSequenceable) - { - } return DEVICE_OK; } diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 8da0c7f34..c61a31e1f 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -9,10 +9,15 @@ //Custom Error Codes #define ERR_UNKNOWN_MODE 102 #define ERR_UNKNOWN_LED_STATE 103 -#define ERR_IN_SEQUENCE 104 -#define ERR_SEQUENCE_INACTIVE 105 -#define ERR_STAGE_MOVING 106 -#define HUB_NOT_AVAILABLE 107 +#define HUB_NOT_AVAILABLE 104 +#define ERR_CHROLIS_NOT_AVAIL 105 +#define ERR_CHROLIS_SET 106 +#define ERR_CHROLIS_GET 107 +#define ERR_PARAM_NOT_VALID 108 + +//CHROLIS Specific Error Codes +#define ERR_UNKOWN_HW_STATE -1073676421 +#define ERR_VAL_OVERFLOW -1073481985 class ChrolisHub : public HubBase { @@ -90,7 +95,7 @@ class ChrolisStateDevice : public CStateDeviceBase int OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct); private: - long curLedState_; + uint8_t curLedState_; long numPos_; ViUInt16 led1Power_; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index bc59f6d68..981b17dc1 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -21,11 +21,11 @@ int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) err = TL6WL_findRsrc(NULL, &numDevices); if (err != 0) { - return DEVICE_ERR; + return err; } if (numDevices == 0) { - return DEVICE_ERR; + return err; } ViChar resource[512] = ""; @@ -34,12 +34,12 @@ int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) err = TL6WL_getRsrcName(NULL, 0, resource); if (err != 0) { - return DEVICE_ERR; + return err; } err = TL6WL_getRsrcInfo(NULL, 0, deviceName_, serialNumber_, manufacturerName_, &deviceInUse_); if (err != 0) { - return DEVICE_ERR; + return err; } } else @@ -56,7 +56,7 @@ int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) err = TL6WL_getRsrcInfo(NULL, i, deviceName_, serialNumber_, manufacturerName_, &deviceInUse_); if (err != 0) { - return DEVICE_ERR; + return err; } if (strcmp((char*)serialNumber_, serialNumber.c_str())) { @@ -66,23 +66,22 @@ int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) } if(!found) { - return DEVICE_ERR; + return err; } } err = TL6WL_init(resource, false, false, &deviceHandle_); if (err != 0) { - return DEVICE_ERR; + return err; } deviceConnected_ = true; for (int i = 0; i < numLEDs_; i++) { - err = TL6WL_readLED_HeadCentroidWL(deviceHandle_, i, &ledWavelengths[i]); + err = TL6WL_readLED_HeadPeakWL(deviceHandle_, i+1, &ledWavelengths[i]); if (err != 0) { - //Error reading head wavelengths - return DEVICE_ERR; + return err; } } VerifyLEDStates(); @@ -97,7 +96,7 @@ int ThorlabsChrolisDeviceWrapper::ShutdownDevice() auto err = TL6WL_close(deviceHandle_); if (err != 0) { - return DEVICE_ERR; + return err; } } deviceConnected_ = false; @@ -113,11 +112,11 @@ int ThorlabsChrolisDeviceWrapper::GetSerialNumber(ViChar* serialNumber) { if (deviceConnected_) { - serialNumber = serialNumber_; + strcpy(serialNumber, serialNumber_); } else { - serialNumber = (ViChar*)"NOT INITIALIZED"; + strcpy(serialNumber, "Not Initialized"); } return DEVICE_OK; } @@ -126,11 +125,11 @@ int ThorlabsChrolisDeviceWrapper::GetManufacturerName(ViChar* manfName) { if (deviceConnected_) { - manfName = manufacturerName_; + strcpy(manfName, manufacturerName_); } else { - manfName = (ViChar*)"NOT INITIALIZED"; + strcpy(manfName, "Not Initialized"); } return DEVICE_OK; } @@ -140,9 +139,15 @@ int ThorlabsChrolisDeviceWrapper::GetLEDWavelengths(ViUInt16(&wavelengths)[6]) if (!deviceConnected_) { *wavelengths = NULL; - return DEVICE_ERR; + return ERR_CHROLIS_NOT_AVAIL; } - *wavelengths = *ledWavelengths; + wavelengths[0] = ledWavelengths[0]; + wavelengths[1] = ledWavelengths[1]; + wavelengths[2] = ledWavelengths[2]; + wavelengths[3] = ledWavelengths[3]; + wavelengths[4] = ledWavelengths[4]; + wavelengths[5] = ledWavelengths[5]; + return DEVICE_OK; } @@ -150,10 +155,16 @@ int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean(&states)[6]) { if (!deviceConnected_) { - *states = NULL; - return DEVICE_ERR; + for (int i = 0; i < 6; i++) + { + states[i] = false; + } + return ERR_CHROLIS_NOT_AVAIL; + } + for (int i = 0; i < 6; i++) + { + states[i] = savedEnabledStates[i]; } - *states = *savedEnabledStates; return DEVICE_OK; } @@ -161,7 +172,13 @@ int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean& led1State, ViBoo { if (!deviceConnected_) { - return DEVICE_ERR; + led1State = false; + led2State = false; + led3State = false; + led4State = false; + led5State = false; + led6State = false; + return ERR_CHROLIS_NOT_AVAIL; } led1State = savedEnabledStates[0]; led2State = savedEnabledStates[1]; @@ -175,9 +192,9 @@ int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean& led1State, ViBoo int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) { - if (states == NULL) + if (!deviceConnected_) { - return DEVICE_ERR; + return ERR_CHROLIS_NOT_AVAIL; } int i; for (i = 0; i < numLEDs_; i++) @@ -201,10 +218,16 @@ int ThorlabsChrolisDeviceWrapper::GetLEDPowerStates(ViUInt16(&states)[6]) { if (!deviceConnected_) { - *states = NULL; - return DEVICE_ERR; + for (int i = 0; i < 6; i++) + { + states[i] = 0; + } + return ERR_CHROLIS_NOT_AVAIL; + } + for (int i = 0; i < 6; i++) + { + states[i] = savedPowerStates[i]; } - *states = *savedPowerStates; return DEVICE_OK; } @@ -212,7 +235,13 @@ int ThorlabsChrolisDeviceWrapper::GetLEDPowerStates(ViUInt16& led1Power, ViUInt1 { if (!deviceConnected_) { - return DEVICE_ERR; + led1Power = 0; + led2Power = 0; + led3Power = 0; + led4Power = 0; + led5Power = 0; + led6Power = 0; + return ERR_CHROLIS_NOT_AVAIL; } led1Power = savedPowerStates[0]; led2Power = savedPowerStates[1]; @@ -226,9 +255,9 @@ int ThorlabsChrolisDeviceWrapper::GetLEDPowerStates(ViUInt16& led1Power, ViUInt1 int ThorlabsChrolisDeviceWrapper::SetLEDPowerStates(ViUInt16 states[6]) { - if (states == NULL) + if (!deviceConnected_) { - return DEVICE_ERR; + return ERR_CHROLIS_NOT_AVAIL; } int i; for (i = 0; i < numLEDs_; i++) @@ -249,54 +278,63 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean sta { if (LED < 6 && LED >= 0) { + int err = 0; savedEnabledStates[LED] = state; - if (!SetLEDEnableStates(savedEnabledStates)) - { - return DEVICE_OK; - } - else + err = SetLEDEnableStates(savedEnabledStates); + if (err != 0) { //revert in case of error savedEnabledStates[LED] = !state; + return err; } + return DEVICE_OK; + } + else + { + return ERR_PARAM_NOT_VALID; } - return DEVICE_ERR; } int ThorlabsChrolisDeviceWrapper::SetSingleLEDPowerState(int LED, ViUInt16 state) { if (LED < 6 && LED >= 0) { + int err = 0; ViInt16 tmpPower = savedPowerStates[LED]; savedPowerStates[LED] = state; - if (!SetLEDPowerStates(savedPowerStates)) - { - return DEVICE_OK; - } - else + err = SetLEDPowerStates(savedPowerStates); + if (err != 0) { //revert in case of error savedPowerStates[LED] = tmpPower; + return err; } + return DEVICE_OK; + } + else + { + return ERR_PARAM_NOT_VALID; } - return DEVICE_ERR; } int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) { + int err; if (!open) { - if (int err = TL6WL_setLED_HeadPowerStates(deviceHandle_, false, false, false, false, false, false) != 0) + err = TL6WL_setLED_HeadPowerStates(deviceHandle_, false, false, false, false, false, false); + if (err != 0) { - return DEVICE_ERR; + return err; } masterSwitchState_ = false; } else { - if (int err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates[0], savedEnabledStates[1], savedEnabledStates[2], savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]) != 0) + err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates[0], savedEnabledStates[1], savedEnabledStates[2], savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]); + if (err != 0) { - return DEVICE_ERR; + return err; } masterSwitchState_ = true; } @@ -305,6 +343,11 @@ int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) int ThorlabsChrolisDeviceWrapper::GetShutterState(bool& open) { + if (!deviceConnected_) + { + open = false; + return ERR_CHROLIS_NOT_AVAIL; + } open = masterSwitchState_; return DEVICE_OK; } @@ -335,9 +378,4 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDStates() } return stateCorrect; -} - -long GetIntegerStateValue() -{ - return 0; } \ No newline at end of file From 848657369cd698d9874481a6df3a309fd27642bc Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Mon, 16 Oct 2023 08:14:32 -0400 Subject: [PATCH 15/91] Some updates to add a polling thread --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 139 ++++++++++++++---- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 47 ++---- .../ThorlabsChrolisDeviceWrapper.cpp | 35 ++++- 3 files changed, 157 insertions(+), 64 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index b607f9dce..6a91615a7 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -26,8 +26,8 @@ using namespace std; * after constructor, needs to be safe to call shutdown or destructor * device specific properties in the hub * state device allowed values added individually for drop down -* leave state as text box - integer property -* put wavelength in property name +* leave state as text box - integer property - X +* put wavelength in property name - X * handle cases for initialization failing * Julian tester */ @@ -42,9 +42,6 @@ MODULE_API void InitializeModuleData() { RegisterDevice(CHROLIS_STATE_NAME, MM::StateDevice, "Thorlabs CHROLIS LED Control"); - //RegisterDevice(CHROLIS_GENERIC_DEVICE_NAME, - // MM::GenericDevice, - // "Thorlabs CHROLIS Power Control"); } MODULE_API MM::Device* CreateDevice(char const* name) { @@ -60,9 +57,6 @@ MODULE_API MM::Device* CreateDevice(char const* name) { if (name == std::string(CHROLIS_STATE_NAME)) return new ChrolisStateDevice(); - //if (name == std::string(CHROLIS_GENERIC_DEVICE_NAME)) - // return new ChrolisPowerControl(); - return nullptr; } @@ -73,7 +67,10 @@ MODULE_API void DeleteDevice(MM::Device* device) { //Hub Methods ChrolisHub::ChrolisHub() : initialized_(false), - busy_(false) + busy_(false), + threadRunning_(false), + currentDeviceStatusCode_(0), + deviceStatusMessage_("No Errors") { CreateHubIDProperty(); chrolisDeviceInstance_ = new ThorlabsChrolisDeviceWrapper(); @@ -82,12 +79,10 @@ ChrolisHub::ChrolisHub() : int ChrolisHub::DetectInstalledDevices() { ClearInstalledDevices(); - - // make sure this method is called before we look for available devices - InitializeModuleData(); + InitializeModuleData();// make sure this method is called before we look for available devices char hubName[MM::MaxStrLength]; - GetName(hubName); // this device name + GetName(hubName); for (unsigned i = 0; i < GetNumberOfDevices(); i++) { char deviceName[MM::MaxStrLength]; @@ -101,33 +96,33 @@ int ChrolisHub::DetectInstalledDevices() return DEVICE_OK; } +//Should have boolean to indicate device is initialized so it can be cleaned up in case of other errors in init int ChrolisHub::Initialize() { if (!initialized_) { - auto err = static_cast(chrolisDeviceInstance_)->InitializeDevice(); if (err != 0) { LogMessage("Error in CHROLIS Initialization"); - return DEVICE_ERR; + return err; } - ViChar sNum[256]; + ViChar sNum[TL6WL_LONG_STRING_SIZE]; static_cast(chrolisDeviceInstance_)->GetSerialNumber(sNum); err = CreateStringProperty("Serial Number", sNum, true); if (err != 0) { - LogMessage("Error with property set in hub control"); + LogMessage("Error with property set in hub initialize"); return DEVICE_ERR; } - ViChar manfName[256]; + ViChar manfName[TL6WL_LONG_STRING_SIZE]; static_cast(chrolisDeviceInstance_)->GetManufacturerName(manfName); err = CreateStringProperty("Manufacturer Name", manfName, true); if (err != 0) { - LogMessage("Error with property set in hub control"); + LogMessage("Error with property set in hub initialize"); return DEVICE_ERR; } @@ -136,8 +131,8 @@ int ChrolisHub::Initialize() err = static_cast(chrolisDeviceInstance_)->GetLEDWavelengths(wavelengths); if (err != 0) { - LogMessage("Error with property set in hub control"); - return DEVICE_ERR; + LogMessage("Unable to get wavelengths from device"); + return err; } for (int i = 0; i < 6; i ++) { @@ -150,10 +145,19 @@ int ChrolisHub::Initialize() err = CreateStringProperty("Available Wavelengths", wavelengthList.c_str(), true); if (err != 0) { - LogMessage("Error with property set in hub control"); + LogMessage("Error with property set in hub initialize"); + return DEVICE_ERR; + } + + err = CreateStringProperty("Device Status", deviceStatusMessage_.c_str(), true); + if (err != 0) + { + LogMessage("Error with property set in hub initialize"); return DEVICE_ERR; } + threadRunning_ = true; + updateThread_ = thread(&StatusChangedPollingThread); initialized_ = true; } return DEVICE_OK; @@ -161,7 +165,14 @@ int ChrolisHub::Initialize() int ChrolisHub::Shutdown() { - if (initialized_) + //Shutdown thread before anything else + if (threadRunning_) + { + threadRunning_ = false; + updateThread_.join(); + } + + if (initialized_ || static_cast(chrolisDeviceInstance_)->IsDeviceConnected()) { auto err = static_cast(chrolisDeviceInstance_)->ShutdownDevice(); if (err != 0) @@ -194,13 +205,79 @@ void* ChrolisHub::GetChrolisDeviceInstance() return chrolisDeviceInstance_; } +void ChrolisHub::StatusChangedPollingThread() +{ + while (threadRunning_) + { + ChrolisHub* pHub = static_cast(GetParentHub()); + if (pHub) + { + char hubLabel[MM::MaxStrLength]; + pHub->GetLabel(hubLabel); + SetParentID(hubLabel); + } + else + LogMessage("No Hub"); + + ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + if (wrapperInstance->IsDeviceConnected()) + { + ViUInt32 tempStatus; + auto err = wrapperInstance->GetDeviceStatus(tempStatus); + if (err != 0) + { + LogMessage("Error Getting Status"); + } + else + { + currentDeviceStatusCode_ = tempStatus; + if (currentDeviceStatusCode_ == 0) + { + OnPropertyChanged("Device Status", "No Error"); + } + else if (currentDeviceStatusCode_ & 0x01 == 1) + { + OnPropertyChanged("Device Status", "Box is Open"); + } + else if (currentDeviceStatusCode_ & 0x02 == 1) + { + OnPropertyChanged("Device Status", "LLG not connected"); + } + else if (currentDeviceStatusCode_ & 0x04 == 1) + { + OnPropertyChanged("Device Status", "Interlock is Open"); + } + else if (currentDeviceStatusCode_ & 0x08 == 1) + { + OnPropertyChanged("Device Status", "Using default adjustment"); + } + else if (currentDeviceStatusCode_ & 0x10 == 1) + { + OnPropertyChanged("Device Status", "Box overheated"); + } + else if (currentDeviceStatusCode_ & 0x20 == 1) + { + OnPropertyChanged("Device Status", "LED overheated"); + } + else if (currentDeviceStatusCode_ & 0x40 == 1) + { + OnPropertyChanged("Device Status", "Invalid box setup"); + } + else + { + OnPropertyChanged("Device Status", "Unkown Status"); + } + } + + } + Sleep(2000); + } +} + //Chrolis Shutter Methods -//TODO test on property change with label for shutter state ChrolisShutter::ChrolisShutter() { InitializeDefaultErrorMessages(); - //SetErrorText(ERR_UNKNOWN_POSITION, "Requested position not available in this device"); - //EnableDelay(); // signals that the delay setting will be used CreateHubIDProperty(); } @@ -211,7 +288,7 @@ int ChrolisShutter::Initialize() { char hubLabel[MM::MaxStrLength]; pHub->GetLabel(hubLabel); - SetParentID(hubLabel); // for backward comp. + SetParentID(hubLabel); } else LogMessage("No Hub"); @@ -222,7 +299,7 @@ int ChrolisShutter::Initialize() auto err = wrapperInstance->SetShutterState(false); if (err != 0) { - LogMessage("Could not close shutter on it"); + LogMessage("Could not close shutter on init"); } } @@ -249,17 +326,17 @@ int ChrolisShutter::SetOpen(bool open) ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { - return DEVICE_ERR; // TODO Add custom error messages + return HUB_NOT_AVAILABLE; // TODO Add custom error messages } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) { - return DEVICE_ERR; + return ERR_CHROLIS_NOT_AVAIL; } auto err = wrapperInstance->SetShutterState(open); if (err != 0) { - return DEVICE_ERR; + return err; } return DEVICE_OK; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index c61a31e1f..8f2ba16de 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -1,10 +1,11 @@ #pragma once +#include #include #include "DeviceBase.h" + #define CHROLIS_HUB_NAME "CHROLIS" #define CHROLIS_SHUTTER_NAME "CHROLIS_Shutter" #define CHROLIS_STATE_NAME "CHROLIS_LED_Control" -//#define CHROLIS_GENERIC_DEVICE_NAME "CHROLIS_Power_Control" //Custom Error Codes #define ERR_UNKNOWN_MODE 102 @@ -34,12 +35,19 @@ class ChrolisHub : public HubBase int DetectInstalledDevices(); bool IsInitialized(); + //void TL6WL_StatusChangedHandler(ViUInt32 statRegist); void* GetChrolisDeviceInstance(); + void StatusChangedPollingThread(); + private: void* chrolisDeviceInstance_; bool initialized_; bool busy_; + bool threadRunning_; + std::thread updateThread_; + atomic_uint32_t currentDeviceStatusCode_; + std::string deviceStatusMessage_; }; class ChrolisShutter : public CShutterBase //CRTP @@ -116,34 +124,6 @@ class ChrolisStateDevice : public CStateDeviceBase ViInt16 ledMinPower_; }; -//class ChrolisPowerControl : public CGenericBase -//{ -//public: -// ChrolisPowerControl(); -// -// ~ChrolisPowerControl() -// {} -// -// int Initialize(); -// int Shutdown(); -// void GetName(char* pszName) const; -// bool Busy(); -// -// //Label Update -// int OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct); -// -//private: -// ViInt16 led1Power_; -// ViInt16 led2Power_; -// ViInt16 led3Power_; -// ViInt16 led4Power_; -// ViInt16 led5Power_; -// ViInt16 led6Power_; -// -// ViInt16 ledMaxPower_; -// ViInt16 ledMinPower_; -//}; - //Wrapper for the basic functions used in this device adapter class ThorlabsChrolisDeviceWrapper { @@ -167,6 +147,9 @@ class ThorlabsChrolisDeviceWrapper int SetSingleLEDPowerState(int LED, ViUInt16 state); int SetShutterState(bool open); int GetShutterState(bool& open); + int RegisterStatusChangedHandler(void* handler); + int RegisterStatusChangedHandler(Box6WL_StatusChangedHandler& handler); + int GetDeviceStatus(ViUInt32& status); bool VerifyLEDStates(); private: @@ -174,9 +157,9 @@ class ThorlabsChrolisDeviceWrapper bool deviceConnected_; ViSession deviceHandle_; ViBoolean deviceInUse_; //only used by the chrolis API - ViChar deviceName_[256]; - ViChar serialNumber_[256]; - ViChar manufacturerName_[256]; + ViChar deviceName_[TL6WL_LONG_STRING_SIZE]; + ViChar serialNumber_[TL6WL_LONG_STRING_SIZE]; + ViChar manufacturerName_[TL6WL_LONG_STRING_SIZE]; bool masterSwitchState_; ViBoolean savedEnabledStates[6]{false,false,false,false,false,false}; ViUInt16 savedPowerStates[6]{0,0,0,0,0,0}; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 981b17dc1..54cb0bd32 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -98,6 +98,7 @@ int ThorlabsChrolisDeviceWrapper::ShutdownDevice() { return err; } + deviceHandle_ = -1; } deviceConnected_ = false; return DEVICE_OK; @@ -138,7 +139,10 @@ int ThorlabsChrolisDeviceWrapper::GetLEDWavelengths(ViUInt16(&wavelengths)[6]) { if (!deviceConnected_) { - *wavelengths = NULL; + for (int i = 0; i < 6; i++) + { + wavelengths[i] = 0; + } return ERR_CHROLIS_NOT_AVAIL; } wavelengths[0] = ledWavelengths[0]; @@ -352,6 +356,35 @@ int ThorlabsChrolisDeviceWrapper::GetShutterState(bool& open) return DEVICE_OK; } +int ThorlabsChrolisDeviceWrapper::GetDeviceStatus(ViUInt32& status) +{ + if (!deviceConnected_) + { + status = 0; + return ERR_CHROLIS_NOT_AVAIL; + } + auto err = TL6WL_getBoxStatus(deviceHandle_, &status); + if (err != 0) + { + return err; + } + return DEVICE_OK; +} + +int ThorlabsChrolisDeviceWrapper::RegisterStatusChangedHandler(void* handler) +{ + if (!deviceConnected_) + { + return ERR_CHROLIS_NOT_AVAIL; + } + auto err = TL6WL_registerBoxStatusChangedHandler(deviceHandle_, (Box6WL_StatusChangedHandler)handler); + if (err != 0) + { + return err; + } + return DEVICE_OK; +} + //set or fix any issues with the stored led vals. Return if a correction needed to be made bool ThorlabsChrolisDeviceWrapper::VerifyLEDStates() { From b2e76ea38b1a581a722133da9915e7057f2f522e Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Mon, 16 Oct 2023 09:00:52 -0400 Subject: [PATCH 16/91] build fixes --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 27 +++++++++---------- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 4 +-- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 6a91615a7..733c0bb6a 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -23,13 +23,12 @@ using namespace std; * enumerate in constructor * no logging in constructor * store error in device instance -* after constructor, needs to be safe to call shutdown or destructor +* after constructor, needs to be safe to call shutdown or destructor- x * device specific properties in the hub * state device allowed values added individually for drop down * leave state as text box - integer property - X * put wavelength in property name - X * handle cases for initialization failing -* Julian tester */ MODULE_API void InitializeModuleData() { @@ -69,11 +68,11 @@ ChrolisHub::ChrolisHub() : initialized_(false), busy_(false), threadRunning_(false), - currentDeviceStatusCode_(0), deviceStatusMessage_("No Errors") { CreateHubIDProperty(); chrolisDeviceInstance_ = new ThorlabsChrolisDeviceWrapper(); + atomic_init(¤tDeviceStatusCode_, 0); } int ChrolisHub::DetectInstalledDevices() @@ -96,7 +95,6 @@ int ChrolisHub::DetectInstalledDevices() return DEVICE_OK; } -//Should have boolean to indicate device is initialized so it can be cleaned up in case of other errors in init int ChrolisHub::Initialize() { if (!initialized_) @@ -157,7 +155,7 @@ int ChrolisHub::Initialize() } threadRunning_ = true; - updateThread_ = thread(&StatusChangedPollingThread); + updateThread_ = thread(&ChrolisHub::StatusChangedPollingThread, this); initialized_ = true; } return DEVICE_OK; @@ -165,7 +163,6 @@ int ChrolisHub::Initialize() int ChrolisHub::Shutdown() { - //Shutdown thread before anything else if (threadRunning_) { threadRunning_ = false; @@ -230,36 +227,36 @@ void ChrolisHub::StatusChangedPollingThread() } else { - currentDeviceStatusCode_ = tempStatus; - if (currentDeviceStatusCode_ == 0) + currentDeviceStatusCode_.store(tempStatus); + if (currentDeviceStatusCode_.load() == 0) { OnPropertyChanged("Device Status", "No Error"); } - else if (currentDeviceStatusCode_ & 0x01 == 1) + else if (currentDeviceStatusCode_.load() & 0x01 == 1) { OnPropertyChanged("Device Status", "Box is Open"); } - else if (currentDeviceStatusCode_ & 0x02 == 1) + else if (currentDeviceStatusCode_.load() & 0x02 == 1) { OnPropertyChanged("Device Status", "LLG not connected"); } - else if (currentDeviceStatusCode_ & 0x04 == 1) + else if (currentDeviceStatusCode_.load() & 0x04 == 1) { OnPropertyChanged("Device Status", "Interlock is Open"); } - else if (currentDeviceStatusCode_ & 0x08 == 1) + else if (currentDeviceStatusCode_.load() & 0x08 == 1) { OnPropertyChanged("Device Status", "Using default adjustment"); } - else if (currentDeviceStatusCode_ & 0x10 == 1) + else if (currentDeviceStatusCode_.load() & 0x10 == 1) { OnPropertyChanged("Device Status", "Box overheated"); } - else if (currentDeviceStatusCode_ & 0x20 == 1) + else if (currentDeviceStatusCode_.load() & 0x20 == 1) { OnPropertyChanged("Device Status", "LED overheated"); } - else if (currentDeviceStatusCode_ & 0x40 == 1) + else if (currentDeviceStatusCode_.load() & 0x40 == 1) { OnPropertyChanged("Device Status", "Invalid box setup"); } diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 8f2ba16de..a26298d54 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include "DeviceBase.h" #define CHROLIS_HUB_NAME "CHROLIS" @@ -35,7 +36,6 @@ class ChrolisHub : public HubBase int DetectInstalledDevices(); bool IsInitialized(); - //void TL6WL_StatusChangedHandler(ViUInt32 statRegist); void* GetChrolisDeviceInstance(); void StatusChangedPollingThread(); @@ -46,7 +46,7 @@ class ChrolisHub : public HubBase bool busy_; bool threadRunning_; std::thread updateThread_; - atomic_uint32_t currentDeviceStatusCode_; + std::atomic_uint32_t currentDeviceStatusCode_; std::string deviceStatusMessage_; }; From da50e87ed2bca73b4aff220f295615dece8b5832 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Mon, 16 Oct 2023 11:45:25 -0400 Subject: [PATCH 17/91] Added method to get available serial numbers and pre-init property in constructor. Testing in init to see if this works --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 47 ++++++++++++------- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 7 +++ .../ThorlabsChrolisDeviceWrapper.cpp | 31 ++++++++++-- 3 files changed, 66 insertions(+), 19 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 733c0bb6a..05b09efa6 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -71,8 +71,20 @@ ChrolisHub::ChrolisHub() : deviceStatusMessage_("No Errors") { CreateHubIDProperty(); + SetErrorText(ERR_INSUF_INFO, "Insufficient location information of the device or the resource is not present on the system"); + chrolisDeviceInstance_ = new ThorlabsChrolisDeviceWrapper(); atomic_init(¤tDeviceStatusCode_, 0); + + std::vector serialNumbers; + static_cast(chrolisDeviceInstance_)->GetAvailableSerialNumbers(serialNumbers); + + CreateStringProperty("Serial Number", "DEFAULT", false, 0, true); + for (int i = 0; i < serialNumbers.size(); i++) + { + AddAllowedValue("Serial Number", serialNumbers[i].c_str()); + } + } int ChrolisHub::DetectInstalledDevices() @@ -99,21 +111,24 @@ int ChrolisHub::Initialize() { if (!initialized_) { - auto err = static_cast(chrolisDeviceInstance_)->InitializeDevice(); + char buf[MM::MaxStrLength]; + int ret = GetProperty("Serial Number", buf); + + auto err = static_cast(chrolisDeviceInstance_)->InitializeDevice(buf); if (err != 0) { LogMessage("Error in CHROLIS Initialization"); return err; } - ViChar sNum[TL6WL_LONG_STRING_SIZE]; - static_cast(chrolisDeviceInstance_)->GetSerialNumber(sNum); - err = CreateStringProperty("Serial Number", sNum, true); - if (err != 0) - { - LogMessage("Error with property set in hub initialize"); - return DEVICE_ERR; - } + //ViChar sNum[TL6WL_LONG_STRING_SIZE]; + //static_cast(chrolisDeviceInstance_)->GetSerialNumber(sNum); + //err = CreateStringProperty("Serial Number", sNum, true); + //if (err != 0) + //{ + // LogMessage("Error with property set in hub initialize"); + // return DEVICE_ERR; + //} ViChar manfName[TL6WL_LONG_STRING_SIZE]; static_cast(chrolisDeviceInstance_)->GetManufacturerName(manfName); @@ -232,31 +247,31 @@ void ChrolisHub::StatusChangedPollingThread() { OnPropertyChanged("Device Status", "No Error"); } - else if (currentDeviceStatusCode_.load() & 0x01 == 1) + else if ((currentDeviceStatusCode_.load() & 0x01) == 1) { OnPropertyChanged("Device Status", "Box is Open"); } - else if (currentDeviceStatusCode_.load() & 0x02 == 1) + else if ((currentDeviceStatusCode_.load() & 0x02) == 1) { OnPropertyChanged("Device Status", "LLG not connected"); } - else if (currentDeviceStatusCode_.load() & 0x04 == 1) + else if ((currentDeviceStatusCode_.load() & 0x04) == 1) { OnPropertyChanged("Device Status", "Interlock is Open"); } - else if (currentDeviceStatusCode_.load() & 0x08 == 1) + else if ((currentDeviceStatusCode_.load() & 0x08) == 1) { OnPropertyChanged("Device Status", "Using default adjustment"); } - else if (currentDeviceStatusCode_.load() & 0x10 == 1) + else if ((currentDeviceStatusCode_.load() & 0x10) == 1) { OnPropertyChanged("Device Status", "Box overheated"); } - else if (currentDeviceStatusCode_.load() & 0x20 == 1) + else if ((currentDeviceStatusCode_.load() & 0x20) == 1) { OnPropertyChanged("Device Status", "LED overheated"); } - else if (currentDeviceStatusCode_.load() & 0x40 == 1) + else if ((currentDeviceStatusCode_.load() & 0x40) == 1) { OnPropertyChanged("Device Status", "Invalid box setup"); } diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index a26298d54..743d5e6bc 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -2,6 +2,7 @@ #include #include #include +#include #include "DeviceBase.h" #define CHROLIS_HUB_NAME "CHROLIS" @@ -16,8 +17,12 @@ #define ERR_CHROLIS_SET 106 #define ERR_CHROLIS_GET 107 #define ERR_PARAM_NOT_VALID 108 +#define ERR_NO_AVAIL_DEVICES 109 //CHROLIS Specific Error Codes + +//VISA Error Codes +#define ERR_INSUF_INFO -1073807343 #define ERR_UNKOWN_HW_STATE -1073676421 #define ERR_VAL_OVERFLOW -1073481985 @@ -131,6 +136,7 @@ class ThorlabsChrolisDeviceWrapper ThorlabsChrolisDeviceWrapper(); ~ThorlabsChrolisDeviceWrapper(); + int GetAvailableSerialNumbers(std::vector &serialNumbers); int InitializeDevice(std::string serialNumber = ""); int ShutdownDevice(); bool IsDeviceConnected(); @@ -154,6 +160,7 @@ class ThorlabsChrolisDeviceWrapper private: int numLEDs_; + std::vector serialNumberList_; bool deviceConnected_; ViSession deviceHandle_; ViBoolean deviceInUse_; //only used by the chrolis API diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 54cb0bd32..053191c41 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -13,7 +13,7 @@ ThorlabsChrolisDeviceWrapper::ThorlabsChrolisDeviceWrapper() ThorlabsChrolisDeviceWrapper::~ThorlabsChrolisDeviceWrapper() {} -int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) +int ThorlabsChrolisDeviceWrapper::GetAvailableSerialNumbers(std::vector &serialNumbers) { int err = 0; ViUInt32 numDevices; @@ -24,12 +24,37 @@ int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) return err; } if (numDevices == 0) + { + return ERR_NO_AVAIL_DEVICES; + } + for (int i = 0; i < numDevices; i++) + { + err = TL6WL_getRsrcInfo(NULL, i, deviceName_, serialNumber_, manufacturerName_, &deviceInUse_); + if (err != 0) + { + return err; + } + serialNumbers.push_back(serialNumber_); + } +} + +int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) +{ + int err = 0; + ViUInt32 numDevices; + CDeviceUtils::SleepMs(2000); + err = TL6WL_findRsrc(NULL, &numDevices); + if (err != 0) { return err; } + if (numDevices == 0) + { + return ERR_NO_AVAIL_DEVICES; + } ViChar resource[512] = ""; - if(serialNumber.compare("")) + if(serialNumber.compare("") || serialNumber.compare("DEFAULT")) { err = TL6WL_getRsrcName(NULL, 0, resource); if (err != 0) @@ -51,7 +76,7 @@ int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) err = TL6WL_getRsrcName(NULL, i, resource); if (err != 0) { - return DEVICE_ERR; + return err; } err = TL6WL_getRsrcInfo(NULL, i, deviceName_, serialNumber_, manufacturerName_, &deviceInUse_); if (err != 0) From e31404294c756e1f4e7701c34e7933f0b1d6b1e1 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Mon, 16 Oct 2023 17:08:56 -0400 Subject: [PATCH 18/91] Some code cleanup and additional error handling --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 92 +++++-------------- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 3 - 2 files changed, 25 insertions(+), 70 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 05b09efa6..c78b3af72 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -338,7 +338,7 @@ int ChrolisShutter::SetOpen(bool open) ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { - return HUB_NOT_AVAILABLE; // TODO Add custom error messages + return HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) @@ -359,7 +359,7 @@ int ChrolisShutter::GetOpen(bool& open) ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { - return DEVICE_ERR; // TODO Add custom error messages + return DEVICE_ERR; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) @@ -383,7 +383,7 @@ ChrolisStateDevice::ChrolisStateDevice() : CreateHubIDProperty(); } -int ChrolisStateDevice::Initialize() //TODO: Initialized property? +int ChrolisStateDevice::Initialize() { ChrolisHub* pHub = static_cast(GetParentHub()); if (pHub) @@ -577,7 +577,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) pProp->Set((long)curLedState_); // revert return ERR_UNKNOWN_LED_STATE; } - // Do something with the incoming state info + ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { @@ -601,7 +601,8 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) int err = wrapperInstance->SetLEDEnableStates(newStates); if (err != 0) { - return DEVICE_ERR; + pProp->Set((long)curLedState_); + return err; } led1State_ = static_cast(val & (1 << 0)); @@ -679,22 +680,27 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT pProp->Get(val); if (val > ledMaxPower_ || val < ledMinPower_) { - pProp->Set((long)*ledBeingControlled); // revert + pProp->Set((long)*ledBeingControlled); return ERR_UNKNOWN_LED_STATE; } - // Do something with the incoming state info ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { - return DEVICE_ERR; // TODO Add custom error messages + return HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) { - return DEVICE_ERR; + pProp->Set((long)*ledBeingControlled); + return ERR_CHROLIS_NOT_AVAIL; } - wrapperInstance->SetSingleLEDEnableState(numFromName-1, (ViBoolean)val); + int err = wrapperInstance->SetSingleLEDEnableState(numFromName-1, (ViBoolean)val); + if (err != 0) + { + pProp->Set((long)*ledBeingControlled); + return err; + } *ledBeingControlled = (ViBoolean)val; curLedState_ = ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) @@ -773,15 +779,21 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { - return DEVICE_ERR; // TODO Add custom error messages + return HUB_NOT_AVAILABLE; // TODO Add custom error messages } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) { - return DEVICE_ERR; + pProp->Set((long)*ledBeingControlled); + return ERR_CHROLIS_NOT_AVAIL; } - wrapperInstance->SetSingleLEDPowerState(numFromName-1, val); + int err = wrapperInstance->SetSingleLEDPowerState(numFromName-1, val); + if (err != 0) + { + pProp->Set((long)*ledBeingControlled); + return err; + } *ledBeingControlled = (int)val; OnPropertiesChanged(); @@ -789,57 +801,3 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA } return DEVICE_OK; } - - -//Chrolis Power Control (Genric Device) Methods -//ChrolisPowerControl::ChrolisPowerControl() : -// ledMaxPower_(100), ledMinPower_(0), led1Power_(0), led2Power_(0), led3Power_(0), led4Power_(0), led5Power_(0), led6Power_(0) -//{ -// InitializeDefaultErrorMessages(); -// //SetErrorText(ERR_UNKNOWN_POSITION, "Requested position not available in this device"); -// //EnableDelay(); // signals that the delay setting will be used -// CreateHubIDProperty(); -//} -// - -//int ChrolisPowerControl::Initialize() -//{ -// ChrolisHub* pHub = static_cast(GetParentHub()); -// if (pHub) -// { -// char hubLabel[MM::MaxStrLength]; -// pHub->GetLabel(hubLabel); -// SetParentID(hubLabel); // for backward comp. -// } -// else -// LogMessage("No Hub"); -// -// //Properties for power control -// CPropertyAction* pAct = new CPropertyAction(this, &ChrolisPowerControl::OnPowerChange); -// auto err = CreateFloatProperty("LED 1", 0, false, pAct); -// SetPropertyLimits("LED 1 Power", ledMinPower_, ledMaxPower_); -// if (err != 0) -// { -// return DEVICE_ERR; -// LogMessage("Error with property set in power control"); -// } -// -// return DEVICE_OK; -//} -// -//int ChrolisPowerControl::Shutdown() -//{ -// return DEVICE_OK; -//} -// -//void ChrolisPowerControl::GetName(char* name) const -//{ -// CDeviceUtils::CopyLimitedString(name, CHROLIS_GENERIC_DEVICE_NAME); -//} -// -//bool ChrolisPowerControl::Busy() -//{ -// return false; -//} - - diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 743d5e6bc..8bf6ff8d9 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -57,9 +57,6 @@ class ChrolisHub : public HubBase class ChrolisShutter : public CShutterBase //CRTP { - ViBoolean savedEnabledStates[6]{ false,false,false,false,false,false}; // should remove these - bool masterShutterState = false; - public: ChrolisShutter(); ~ChrolisShutter() {} From 26598ace3d5b7b5d6b93bf7b01baba8fe510d28d Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Mon, 16 Oct 2023 18:07:30 -0400 Subject: [PATCH 19/91] More error handling --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 24 ++++++++++--------- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index c78b3af72..3a75409ee 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -338,7 +338,7 @@ int ChrolisShutter::SetOpen(bool open) ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { - return HUB_NOT_AVAILABLE; + return ERR_HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) @@ -359,12 +359,12 @@ int ChrolisShutter::GetOpen(bool& open) ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { - return DEVICE_ERR; + return ERR_HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) { - return DEVICE_ERR; + return ERR_CHROLIS_NOT_AVAIL; } wrapperInstance->GetShutterState(open); return DEVICE_OK; @@ -566,7 +566,6 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) if (eAct == MM::BeforeGet) { pProp->Set((long)curLedState_); - // nothing to do, let the caller to use cached property } else if (eAct == MM::AfterSet) { @@ -581,12 +580,13 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { - return DEVICE_ERR; // TODO Add custom error messages + return ERR_HUB_NOT_AVAILABLE; // TODO Add custom error messages } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) { - return DEVICE_ERR; + pProp->Set((long)curLedState_); + return ERR_CHROLIS_NOT_AVAIL; } ViBoolean newStates[6] @@ -612,9 +612,11 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) led5State_ = static_cast(val & (1 << 4)); led6State_ = static_cast(val & (1 << 5)); + pProp->Set((long)val); + curLedState_ = val; + OnPropertiesChanged(); - curLedState_ = val; return DEVICE_OK; } return DEVICE_OK; @@ -686,7 +688,7 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { - return HUB_NOT_AVAILABLE; + return ERR_HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) @@ -772,14 +774,14 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA pProp->Get(val); if (val > ledMaxPower_ || val < ledMinPower_) { - pProp->Set((long)*ledBeingControlled); // revert + pProp->Set((long)*ledBeingControlled); return ERR_UNKNOWN_LED_STATE; } - // Do something with the incoming state info + ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { - return HUB_NOT_AVAILABLE; // TODO Add custom error messages + return ERR_HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 8bf6ff8d9..0ac99f160 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -12,7 +12,7 @@ //Custom Error Codes #define ERR_UNKNOWN_MODE 102 #define ERR_UNKNOWN_LED_STATE 103 -#define HUB_NOT_AVAILABLE 104 +#define ERR_HUB_NOT_AVAILABLE 104 #define ERR_CHROLIS_NOT_AVAIL 105 #define ERR_CHROLIS_SET 106 #define ERR_CHROLIS_GET 107 From 6553570f5bbd01dcad59b020814838a69eed7da9 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Mon, 16 Oct 2023 18:09:20 -0400 Subject: [PATCH 20/91] Re-enabled property --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 3a75409ee..859b62471 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -8,7 +8,7 @@ using namespace std; /*TODO * Set states of properties based on current LED states - x * Properties for device ID and stuff - x -* Error handling on device control methods +* Error handling on device control methods - x * custom errors and messages * logs for errors * Remove HubID Property @@ -24,7 +24,7 @@ using namespace std; * no logging in constructor * store error in device instance * after constructor, needs to be safe to call shutdown or destructor- x -* device specific properties in the hub +* device specific properties in the hub - x * state device allowed values added individually for drop down * leave state as text box - integer property - X * put wavelength in property name - X @@ -121,14 +121,14 @@ int ChrolisHub::Initialize() return err; } - //ViChar sNum[TL6WL_LONG_STRING_SIZE]; - //static_cast(chrolisDeviceInstance_)->GetSerialNumber(sNum); - //err = CreateStringProperty("Serial Number", sNum, true); - //if (err != 0) - //{ - // LogMessage("Error with property set in hub initialize"); - // return DEVICE_ERR; - //} + ViChar sNum[TL6WL_LONG_STRING_SIZE]; + static_cast(chrolisDeviceInstance_)->GetSerialNumber(sNum); + err = CreateStringProperty("Device Serial Number", sNum, true); + if (err != 0) + { + LogMessage("Error with property set in hub initialize"); + return DEVICE_ERR; + } ViChar manfName[TL6WL_LONG_STRING_SIZE]; static_cast(chrolisDeviceInstance_)->GetManufacturerName(manfName); From a259ae971ab1f043dc441d945a4c8d471f379cec Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Mon, 16 Oct 2023 18:20:09 -0400 Subject: [PATCH 21/91] Added complete logging for errors --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 859b62471..a2bfbcf62 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -10,7 +10,7 @@ using namespace std; * Properties for device ID and stuff - x * Error handling on device control methods - x * custom errors and messages -* logs for errors +* logs for errors - x * Remove HubID Property * Integer property range 0 to 1 for each LED on off - x * Is sequencable property for each device check arduino implementation @@ -18,7 +18,7 @@ using namespace std; * no need for event callbacks in UI for triggering * Keep LED control in State Device - x * Maybe keep triggering in Generic if that gets implemented -* pre-init properties in constructor +* pre-init properties in constructor - x * set error text in constructor * enumerate in constructor * no logging in constructor @@ -28,7 +28,7 @@ using namespace std; * state device allowed values added individually for drop down * leave state as text box - integer property - X * put wavelength in property name - X -* handle cases for initialization failing +* handle cases for initialization failing - x */ MODULE_API void InitializeModuleData() { @@ -338,16 +338,19 @@ int ChrolisShutter::SetOpen(bool open) ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { + LogMessage("Hub not available"); return ERR_HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) { + LogMessage("CHROLIS not available"); return ERR_CHROLIS_NOT_AVAIL; } auto err = wrapperInstance->SetShutterState(open); if (err != 0) { + LogMessage("Error setting shutter state"); return err; } @@ -359,11 +362,13 @@ int ChrolisShutter::GetOpen(bool& open) ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { + LogMessage("Hub not available"); return ERR_HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) { + LogMessage("CHROLIS not available"); return ERR_CHROLIS_NOT_AVAIL; } wrapperInstance->GetShutterState(open); @@ -393,7 +398,9 @@ int ChrolisStateDevice::Initialize() SetParentID(hubLabel); // for backward comp. } else - LogMessage("No Hub"); + { + LogMessage("Hub not available"); + } // create default positions and labels const int bufSize = 1024; @@ -573,6 +580,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) pProp->Get(val); if (val >= pow(2, numPos_) || val < 0) { + LogMessage("Requested state out of bounds"); pProp->Set((long)curLedState_); // revert return ERR_UNKNOWN_LED_STATE; } @@ -580,11 +588,13 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { + LogMessage("Hub not available"); return ERR_HUB_NOT_AVAILABLE; // TODO Add custom error messages } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) { + LogMessage("CHROLIS not available"); pProp->Set((long)curLedState_); return ERR_CHROLIS_NOT_AVAIL; } @@ -601,6 +611,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) int err = wrapperInstance->SetLEDEnableStates(newStates); if (err != 0) { + LogMessage("Error Setting LED state"); pProp->Set((long)curLedState_); return err; } @@ -667,6 +678,7 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT ledBeingControlled = &led6State_; break; default: + LogMessage("Error selecting LED state"); return DEVICE_ERR; break; } @@ -674,7 +686,6 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT if (eAct == MM::BeforeGet) { pProp->Set((long)*ledBeingControlled); - // nothing to do, let the caller to use cached property } else if (eAct == MM::AfterSet) { @@ -682,17 +693,20 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT pProp->Get(val); if (val > ledMaxPower_ || val < ledMinPower_) { + LogMessage("Error Setting LED state"); pProp->Set((long)*ledBeingControlled); return ERR_UNKNOWN_LED_STATE; } ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { + LogMessage("Hub not available"); return ERR_HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) { + LogMessage("CHROLIS not available"); pProp->Set((long)*ledBeingControlled); return ERR_CHROLIS_NOT_AVAIL; } @@ -700,6 +714,7 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT int err = wrapperInstance->SetSingleLEDEnableState(numFromName-1, (ViBoolean)val); if (err != 0) { + LogMessage("Error Setting LED state"); pProp->Set((long)*ledBeingControlled); return err; } @@ -759,6 +774,7 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA ledBeingControlled = &led6Power_; break; default: + LogMessage("Error selecting LED state"); return DEVICE_ERR; break; } @@ -766,7 +782,6 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA if (eAct == MM::BeforeGet) { pProp->Set((long)*ledBeingControlled); - // nothing to do, let the caller to use cached property } else if (eAct == MM::AfterSet) { @@ -774,6 +789,7 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA pProp->Get(val); if (val > ledMaxPower_ || val < ledMinPower_) { + LogMessage("Requested power value out of range"); pProp->Set((long)*ledBeingControlled); return ERR_UNKNOWN_LED_STATE; } @@ -781,11 +797,13 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { + LogMessage("Hub not available"); return ERR_HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) { + LogMessage("CHROLIS not available"); pProp->Set((long)*ledBeingControlled); return ERR_CHROLIS_NOT_AVAIL; } @@ -793,6 +811,7 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA int err = wrapperInstance->SetSingleLEDPowerState(numFromName-1, val); if (err != 0) { + LogMessage("Error setting LED power"); pProp->Set((long)*ledBeingControlled); return err; } From e515564781c3a92a841b893af307f52ad7476998 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Wed, 18 Oct 2023 14:29:06 -0400 Subject: [PATCH 22/91] Updates for the status message --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 106 +++++++++++------- 1 file changed, 66 insertions(+), 40 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index a2bfbcf62..ceaa15943 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -29,6 +29,8 @@ using namespace std; * leave state as text box - integer property - X * put wavelength in property name - X * handle cases for initialization failing - x +* Verify LED's all turned off with Shutter button +* Shutter off in case of Device Status LLG open */ MODULE_API void InitializeModuleData() { @@ -68,7 +70,7 @@ ChrolisHub::ChrolisHub() : initialized_(false), busy_(false), threadRunning_(false), - deviceStatusMessage_("No Errors") + deviceStatusMessage_("No Error") { CreateHubIDProperty(); SetErrorText(ERR_INSUF_INFO, "Insufficient location information of the device or the resource is not present on the system"); @@ -241,48 +243,78 @@ void ChrolisHub::StatusChangedPollingThread() LogMessage("Error Getting Status"); } else - { + { + bool verified = wrapperInstance->VerifyLEDStates(); + std::string message = ""; currentDeviceStatusCode_.store(tempStatus); if (currentDeviceStatusCode_.load() == 0) { - OnPropertyChanged("Device Status", "No Error"); - } - else if ((currentDeviceStatusCode_.load() & 0x01) == 1) - { - OnPropertyChanged("Device Status", "Box is Open"); - } - else if ((currentDeviceStatusCode_.load() & 0x02) == 1) - { - OnPropertyChanged("Device Status", "LLG not connected"); - } - else if ((currentDeviceStatusCode_.load() & 0x04) == 1) - { - OnPropertyChanged("Device Status", "Interlock is Open"); - } - else if ((currentDeviceStatusCode_.load() & 0x08) == 1) - { - OnPropertyChanged("Device Status", "Using default adjustment"); - } - else if ((currentDeviceStatusCode_.load() & 0x10) == 1) - { - OnPropertyChanged("Device Status", "Box overheated"); - } - else if ((currentDeviceStatusCode_.load() & 0x20) == 1) - { - OnPropertyChanged("Device Status", "LED overheated"); - } - else if ((currentDeviceStatusCode_.load() & 0x40) == 1) - { - OnPropertyChanged("Device Status", "Invalid box setup"); + message += "No Error"; } else { - OnPropertyChanged("Device Status", "Unkown Status"); + if ((currentDeviceStatusCode_.load() & (1 << 0)) >= 1) + { + message += "Box is Open"; + } + if ((currentDeviceStatusCode_.load() & (1 << 1)) >= 1) + { + if (message.length() > 0) + { + message += ", "; + } + message += "LLG not Connected"; + } + if ((currentDeviceStatusCode_.load() & (1 << 2)) >= 1) + { + if (message.length() > 0) + { + message += ", "; + } + message += "Interlock is Open"; + } + if ((currentDeviceStatusCode_.load() & (1 << 3)) >= 1) + { + if (message.length() > 0) + { + message += ", "; + } + message += "Using Default Adjustment"; + } + if ((currentDeviceStatusCode_.load() & (1 << 4)) >= 1) + { + if (message.length() > 0) + { + message += ", "; + } + message += "Box Overheated"; + } + if ((currentDeviceStatusCode_.load() & (1 << 5)) >= 1) + { + if (message.length() > 0) + { + message += ", "; + } + message += "LED Overheated"; + } + if ((currentDeviceStatusCode_.load() & (1 << 6)) >= 1) + { + if (message.length() > 0) + { + message += ", "; + } + message += "Invalid Box Setup"; + } + if(message.length() == 0) + { + message = "Unknown Status"; + } } + OnPropertyChanged("Device Status", message.c_str()); } } - Sleep(2000); + Sleep(100); } } @@ -298,9 +330,6 @@ int ChrolisShutter::Initialize() ChrolisHub* pHub = static_cast(GetParentHub()); if (pHub) { - char hubLabel[MM::MaxStrLength]; - pHub->GetLabel(hubLabel); - SetParentID(hubLabel); } else LogMessage("No Hub"); @@ -393,9 +422,6 @@ int ChrolisStateDevice::Initialize() ChrolisHub* pHub = static_cast(GetParentHub()); if (pHub) { - char hubLabel[MM::MaxStrLength]; - pHub->GetLabel(hubLabel); - SetParentID(hubLabel); // for backward comp. } else { @@ -589,7 +615,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) if (!pHub || !pHub->IsInitialized()) { LogMessage("Hub not available"); - return ERR_HUB_NOT_AVAILABLE; // TODO Add custom error messages + return ERR_HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) From 4e65814d15d7b5ace07ac12a2e4279ae771b9eaa Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Wed, 18 Oct 2023 15:28:11 -0400 Subject: [PATCH 23/91] Small thread update --- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp | 6 +++++- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h | 1 + .../ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index ceaa15943..436698e9f 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -231,7 +231,10 @@ void ChrolisHub::StatusChangedPollingThread() SetParentID(hubLabel); } else + { LogMessage("No Hub"); + threadRunning_ = false; + } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (wrapperInstance->IsDeviceConnected()) @@ -241,6 +244,7 @@ void ChrolisHub::StatusChangedPollingThread() if (err != 0) { LogMessage("Error Getting Status"); + threadRunning_ = false; } else { @@ -314,7 +318,7 @@ void ChrolisHub::StatusChangedPollingThread() } } - Sleep(100); + Sleep(500); } } diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 0ac99f160..37d99ed56 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -157,6 +157,7 @@ class ThorlabsChrolisDeviceWrapper private: int numLEDs_; + uint8_t curLedState_; std::vector serialNumberList_; bool deviceConnected_; ViSession deviceHandle_; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 053191c41..a48023e19 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -8,6 +8,7 @@ ThorlabsChrolisDeviceWrapper::ThorlabsChrolisDeviceWrapper() masterSwitchState_ = false; deviceHandle_ = -1; numLEDs_ = 6; + curLedState_ = 0; } ThorlabsChrolisDeviceWrapper::~ThorlabsChrolisDeviceWrapper() From b5496c33f3bf27e3f78e1e52deb4564725dadaed Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Wed, 18 Oct 2023 16:00:00 -0400 Subject: [PATCH 24/91] removed local state variable. No need to keep track of this when there are individual led states available --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 24 +++++++++---------- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 2 -- .../ThorlabsChrolisDeviceWrapper.cpp | 1 - 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 436698e9f..c6078f56a 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -411,7 +411,7 @@ int ChrolisShutter::GetOpen(bool& open) //Chrolis State Device Methods ChrolisStateDevice::ChrolisStateDevice() : - numPos_(6),curLedState_(0), ledMaxPower_(100), ledMinPower_(0), + numPos_(6), ledMaxPower_(100), ledMinPower_(0), led1Power_(0), led2Power_(0), led3Power_(0), led4Power_(0), led5Power_(0), led6Power_(0), led1State_(false), led2State_(false), led3State_(false), led4State_(false), led5State_(false), led6State_(false) { @@ -443,18 +443,19 @@ int ChrolisStateDevice::Initialize() int err; ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + uint32_t tmpLedState = 0; if (wrapperInstance->IsDeviceConnected()) { err = wrapperInstance->GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_); err = wrapperInstance->GetLEDPowerStates(led1Power_, led2Power_, led3Power_, led4Power_, led5Power_, led6Power_); - curLedState_ = + tmpLedState = ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5)); } //State Property CPropertyAction* pAct = new CPropertyAction(this, &ChrolisStateDevice::OnState); - err = CreateIntegerProperty(MM::g_Keyword_State, curLedState_, false, pAct); + err = CreateIntegerProperty(MM::g_Keyword_State, tmpLedState, false, pAct); if (err != DEVICE_OK) return err; @@ -602,7 +603,8 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) { if (eAct == MM::BeforeGet) { - pProp->Set((long)curLedState_); + pProp->Set((long)((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) + | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5))); } else if (eAct == MM::AfterSet) { @@ -611,7 +613,8 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) if (val >= pow(2, numPos_) || val < 0) { LogMessage("Requested state out of bounds"); - pProp->Set((long)curLedState_); // revert + pProp->Set((long)((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) + | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5))); return ERR_UNKNOWN_LED_STATE; } @@ -625,7 +628,8 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); - pProp->Set((long)curLedState_); + pProp->Set((long)((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) + | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5))); return ERR_CHROLIS_NOT_AVAIL; } @@ -642,7 +646,8 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) if (err != 0) { LogMessage("Error Setting LED state"); - pProp->Set((long)curLedState_); + pProp->Set((long)((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) + | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5))); return err; } @@ -654,8 +659,6 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) led6State_ = static_cast(val & (1 << 5)); pProp->Set((long)val); - curLedState_ = val; - OnPropertiesChanged(); return DEVICE_OK; @@ -749,9 +752,6 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT return err; } *ledBeingControlled = (ViBoolean)val; - curLedState_ = - ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) - | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5)); OnPropertiesChanged(); return DEVICE_OK; } diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 37d99ed56..8e66032e7 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -105,7 +105,6 @@ class ChrolisStateDevice : public CStateDeviceBase int OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct); private: - uint8_t curLedState_; long numPos_; ViUInt16 led1Power_; @@ -157,7 +156,6 @@ class ThorlabsChrolisDeviceWrapper private: int numLEDs_; - uint8_t curLedState_; std::vector serialNumberList_; bool deviceConnected_; ViSession deviceHandle_; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index a48023e19..053191c41 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -8,7 +8,6 @@ ThorlabsChrolisDeviceWrapper::ThorlabsChrolisDeviceWrapper() masterSwitchState_ = false; deviceHandle_ = -1; numLEDs_ = 6; - curLedState_ = 0; } ThorlabsChrolisDeviceWrapper::~ThorlabsChrolisDeviceWrapper() From 67cfd97caaf50a8a3e9aa16662950945072e9136 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Thu, 19 Oct 2023 08:47:29 -0400 Subject: [PATCH 25/91] Added method to verify LED states --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 45 ++++++++++++++----- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 2 +- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index c6078f56a..b98240542 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -248,7 +248,6 @@ void ChrolisHub::StatusChangedPollingThread() } else { - bool verified = wrapperInstance->VerifyLEDStates(); std::string message = ""; currentDeviceStatusCode_.store(tempStatus); if (currentDeviceStatusCode_.load() == 0) @@ -609,12 +608,14 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) else if (eAct == MM::AfterSet) { long val; + uint8_t currentLEDState = ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) + | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5)); + pProp->Get(val); if (val >= pow(2, numPos_) || val < 0) { LogMessage("Requested state out of bounds"); - pProp->Set((long)((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) - | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5))); + pProp->Set((long)currentLEDState); return ERR_UNKNOWN_LED_STATE; } @@ -628,8 +629,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); - pProp->Set((long)((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) - | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5))); + pProp->Set((long)currentLEDState); return ERR_CHROLIS_NOT_AVAIL; } @@ -646,8 +646,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) if (err != 0) { LogMessage("Error Setting LED state"); - pProp->Set((long)((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) - | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5))); + pProp->Set((long)currentLEDState); return err; } @@ -659,8 +658,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) led6State_ = static_cast(val & (1 << 5)); pProp->Set((long)val); - OnPropertiesChanged(); - + VerifyLedStates(); return DEVICE_OK; } return DEVICE_OK; @@ -752,7 +750,8 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT return err; } *ledBeingControlled = (ViBoolean)val; - OnPropertiesChanged(); + pProp->Set((long)*ledBeingControlled); + VerifyLedStates(); return DEVICE_OK; } @@ -846,9 +845,31 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA return err; } *ledBeingControlled = (int)val; - OnPropertiesChanged(); - + pProp->Set((long)*ledBeingControlled); + VerifyLedStates(); return DEVICE_OK; } return DEVICE_OK; } + +void ChrolisStateDevice::VerifyLedStates() +{ + ChrolisHub* pHub = static_cast(GetParentHub()); + if (!pHub || !pHub->IsInitialized()) + { + LogMessage("Hub not available"); + } + ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + if (!wrapperInstance->IsDeviceConnected()) + { + LogMessage("CHROLIS not available"); + } + + if (!wrapperInstance->VerifyLEDStates()) + { + LogMessage("LED States not valid... resetting"); + wrapperInstance->GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_); + wrapperInstance->GetLEDPowerStates(led1Power_, led2Power_, led3Power_, led4Power_, led5Power_, led6Power_); + OnPropertiesChanged(); + } +} diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 8e66032e7..a6c595b5c 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -103,6 +103,7 @@ class ChrolisStateDevice : public CStateDeviceBase //LED Control Methods int OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct); int OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct); + void VerifyLedStates(); private: long numPos_; @@ -150,7 +151,6 @@ class ThorlabsChrolisDeviceWrapper int SetShutterState(bool open); int GetShutterState(bool& open); int RegisterStatusChangedHandler(void* handler); - int RegisterStatusChangedHandler(Box6WL_StatusChangedHandler& handler); int GetDeviceStatus(ViUInt32& status); bool VerifyLEDStates(); From a31af337da634d96cf54f3b10f0cb329ae741343 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Thu, 19 Oct 2023 15:26:52 -0400 Subject: [PATCH 26/91] Code organization --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 31 ++- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 21 +- .../ThorlabsChrolisDeviceWrapper.cpp | 198 ++++++++++-------- 3 files changed, 153 insertions(+), 97 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index b98240542..641d9b5c0 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -31,6 +31,7 @@ using namespace std; * handle cases for initialization failing - x * Verify LED's all turned off with Shutter button * Shutter off in case of Device Status LLG open +* Can a message be displayed in popup box without a return code? */ MODULE_API void InitializeModuleData() { @@ -86,7 +87,6 @@ ChrolisHub::ChrolisHub() : { AddAllowedValue("Serial Number", serialNumbers[i].c_str()); } - } int ChrolisHub::DetectInstalledDevices() @@ -195,6 +195,7 @@ int ChrolisHub::Shutdown() return DEVICE_ERR; } initialized_ = false; + delete chrolisDeviceInstance_; } return DEVICE_OK; } @@ -852,7 +853,7 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA return DEVICE_OK; } -void ChrolisStateDevice::VerifyLedStates() +bool ChrolisStateDevice::VerifyLedStates() { ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) @@ -865,11 +866,27 @@ void ChrolisStateDevice::VerifyLedStates() LogMessage("CHROLIS not available"); } - if (!wrapperInstance->VerifyLEDStates()) + bool statesCorrect = true; + ViBoolean tmpEnableStates[6]; + ViUInt16 tmpPowerStates[6]; + + int err = wrapperInstance->GetLEDEnableStates(tmpEnableStates); + if (err != 0) + { + return false; + } + int err = wrapperInstance->GetLEDPowerStates(tmpPowerStates); + if (err != 0) + { + return false; + } + + if (tmpEnableStates[0] != led1State_ || tmpPowerStates[0] != led1Power_) { - LogMessage("LED States not valid... resetting"); - wrapperInstance->GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_); - wrapperInstance->GetLEDPowerStates(led1Power_, led2Power_, led3Power_, led4Power_, led5Power_, led6Power_); - OnPropertiesChanged(); } + + delete tmpEnableStates; + delete tmpPowerStates; + + return statesCorrect; } diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index a6c595b5c..0acb2b059 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -12,14 +12,16 @@ //Custom Error Codes #define ERR_UNKNOWN_MODE 102 #define ERR_UNKNOWN_LED_STATE 103 -#define ERR_HUB_NOT_AVAILABLE 104 +#define ERR_HUB_NOT_AVAILABLE 104 #define ERR_CHROLIS_NOT_AVAIL 105 #define ERR_CHROLIS_SET 106 #define ERR_CHROLIS_GET 107 #define ERR_PARAM_NOT_VALID 108 #define ERR_NO_AVAIL_DEVICES 109 +#define ERR_IMPROPER_SET 110 //CHROLIS Specific Error Codes +//TODO See if these need to be filled out //VISA Error Codes #define ERR_INSUF_INFO -1073807343 @@ -103,7 +105,7 @@ class ChrolisStateDevice : public CStateDeviceBase //LED Control Methods int OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct); int OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct); - void VerifyLedStates(); + bool VerifyLedStates(); private: long numPos_; @@ -139,20 +141,23 @@ class ThorlabsChrolisDeviceWrapper bool IsDeviceConnected(); int GetSerialNumber(ViChar* serialNumber); int GetManufacturerName(ViChar* manfName); + int GetDeviceStatus(ViUInt32& status); int GetLEDWavelengths(ViUInt16(&wavelengths)[6]); + int GetShutterState(bool& open); int GetLEDEnableStates(ViBoolean(&states)[6]); int GetLEDEnableStates(ViBoolean& led1State, ViBoolean& led2State, ViBoolean& led3State, ViBoolean& led4State, ViBoolean& led5State, ViBoolean& led6State); - int SetLEDEnableStates(ViBoolean states[6]); int GetLEDPowerStates(ViUInt16(&states)[6]); int GetLEDPowerStates(ViUInt16 &led1Power, ViUInt16&led2Power, ViUInt16&led3Power, ViUInt16&led4Power, ViUInt16&led5Power, ViUInt16&led6Power); - int SetLEDPowerStates(ViUInt16 states[6]); + + int SetShutterState(bool open); + int SetLEDEnableStates(ViBoolean states[6]); int SetSingleLEDEnableState(int LED, ViBoolean state); + int SetLEDPowerStates(ViUInt16 states[6]); int SetSingleLEDPowerState(int LED, ViUInt16 state); - int SetShutterState(bool open); - int GetShutterState(bool& open); - int RegisterStatusChangedHandler(void* handler); - int GetDeviceStatus(ViUInt32& status); + bool VerifyLEDStates(); + bool VerifyLEDPowerStates(); + bool VerifyLEDEnableStates(); private: int numLEDs_; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 053191c41..bf328ba75 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -160,6 +160,32 @@ int ThorlabsChrolisDeviceWrapper::GetManufacturerName(ViChar* manfName) return DEVICE_OK; } +int ThorlabsChrolisDeviceWrapper::GetDeviceStatus(ViUInt32& status) +{ + if (!deviceConnected_) + { + status = 0; + return ERR_CHROLIS_NOT_AVAIL; + } + auto err = TL6WL_getBoxStatus(deviceHandle_, &status); + if (err != 0) + { + return err; + } + return DEVICE_OK; +} + +int ThorlabsChrolisDeviceWrapper::GetShutterState(bool& open) +{ + if (!deviceConnected_) + { + open = false; + return ERR_CHROLIS_NOT_AVAIL; + } + open = masterSwitchState_; + return DEVICE_OK; +} + int ThorlabsChrolisDeviceWrapper::GetLEDWavelengths(ViUInt16(&wavelengths)[6]) { if (!deviceConnected_) @@ -219,30 +245,6 @@ int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean& led1State, ViBoo return DEVICE_OK; } -int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) -{ - if (!deviceConnected_) - { - return ERR_CHROLIS_NOT_AVAIL; - } - int i; - for (i = 0; i < numLEDs_; i++) - { - savedEnabledStates[i] = states[i]; - } - - if (masterSwitchState_) - { - if (auto err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates[0], savedEnabledStates[1], savedEnabledStates[2], - savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]) != 0) - { - return DEVICE_ERR; - } - } - - return DEVICE_OK; -} - int ThorlabsChrolisDeviceWrapper::GetLEDPowerStates(ViUInt16(&states)[6]) { if (!deviceConnected_) @@ -282,25 +284,28 @@ int ThorlabsChrolisDeviceWrapper::GetLEDPowerStates(ViUInt16& led1Power, ViUInt1 return DEVICE_OK; } -int ThorlabsChrolisDeviceWrapper::SetLEDPowerStates(ViUInt16 states[6]) +int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) { - if (!deviceConnected_) - { - return ERR_CHROLIS_NOT_AVAIL; - } - int i; - for (i = 0; i < numLEDs_; i++) + int err; + if (!open) { - savedPowerStates[i] = states[i]; + err = TL6WL_setLED_HeadPowerStates(deviceHandle_, false, false, false, false, false, false); + if (err != 0) + { + return err; + } + masterSwitchState_ = false; } - - if (auto err = TL6WL_setLED_HeadBrightness(deviceHandle_, savedPowerStates[0], savedPowerStates[1], savedPowerStates[2], - savedPowerStates[3], savedPowerStates[4], savedPowerStates[5]) != 0) + else { - return DEVICE_ERR; + err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates[0], savedEnabledStates[1], savedEnabledStates[2], savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]); + if (err != 0) + { + return err; + } + masterSwitchState_ = true; } - - return DEVICE_OK; + return DEVICE_OK; } int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean state) @@ -324,6 +329,30 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean sta } } +int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) +{ + if (!deviceConnected_) + { + return ERR_CHROLIS_NOT_AVAIL; + } + int i; + for (i = 0; i < numLEDs_; i++) + { + savedEnabledStates[i] = states[i]; + } + + if (masterSwitchState_) + { + if (auto err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates[0], savedEnabledStates[1], savedEnabledStates[2], + savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]) != 0) + { + return DEVICE_ERR; + } + } + + return DEVICE_OK; +} + int ThorlabsChrolisDeviceWrapper::SetSingleLEDPowerState(int LED, ViUInt16 state) { if (LED < 6 && LED >= 0) @@ -346,72 +375,80 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDPowerState(int LED, ViUInt16 state } } -int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) +int ThorlabsChrolisDeviceWrapper::SetLEDPowerStates(ViUInt16 states[6]) { - int err; - if (!open) + if (!deviceConnected_) { - err = TL6WL_setLED_HeadPowerStates(deviceHandle_, false, false, false, false, false, false); - if (err != 0) - { - return err; - } - masterSwitchState_ = false; + return ERR_CHROLIS_NOT_AVAIL; } - else + int i; + for (i = 0; i < numLEDs_; i++) { - err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates[0], savedEnabledStates[1], savedEnabledStates[2], savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]); - if (err != 0) - { - return err; - } - masterSwitchState_ = true; + savedPowerStates[i] = states[i]; } - return DEVICE_OK; -} -int ThorlabsChrolisDeviceWrapper::GetShutterState(bool& open) -{ - if (!deviceConnected_) + if (auto err = TL6WL_setLED_HeadBrightness(deviceHandle_, savedPowerStates[0], savedPowerStates[1], savedPowerStates[2], + savedPowerStates[3], savedPowerStates[4], savedPowerStates[5]) != 0) { - open = false; - return ERR_CHROLIS_NOT_AVAIL; + return DEVICE_ERR; } - open = masterSwitchState_; + return DEVICE_OK; } -int ThorlabsChrolisDeviceWrapper::GetDeviceStatus(ViUInt32& status) +//set or fix any issues with the stored led vals. Return if a correction needed to be made +bool ThorlabsChrolisDeviceWrapper::VerifyLEDStates() { if (!deviceConnected_) { - status = 0; - return ERR_CHROLIS_NOT_AVAIL; + return false; } - auto err = TL6WL_getBoxStatus(deviceHandle_, &status); - if (err != 0) + + bool stateCorrect = true; + ViUInt16 tempPowerStates[6] = {0,0,0,0,0,0}; + ViBoolean tempEnableStates[6] = { false, false, false, false, false, false }; + + TL6WL_getLED_HeadPowerStates(deviceHandle_, &tempEnableStates[0], &tempEnableStates[1], &tempEnableStates[2], &tempEnableStates[3], &tempEnableStates[4], &tempEnableStates[5]); + TL6WL_getLED_HeadBrightness(deviceHandle_, &tempPowerStates[0], &tempPowerStates[1], &tempPowerStates[2], &tempPowerStates[3], &tempPowerStates[4], &tempPowerStates[5]); + + for (int i = 0; i < numLEDs_; i++) { - return err; + if (tempEnableStates[i] != savedEnabledStates[i] || tempPowerStates[i] != savedPowerStates[i]) + { + stateCorrect = false; + savedEnabledStates[i] = tempEnableStates[i]; + savedPowerStates[i] = tempPowerStates[i]; + } } - return DEVICE_OK; + + return stateCorrect; } -int ThorlabsChrolisDeviceWrapper::RegisterStatusChangedHandler(void* handler) +bool ThorlabsChrolisDeviceWrapper::VerifyLEDEnableStates() { if (!deviceConnected_) { - return ERR_CHROLIS_NOT_AVAIL; + return false; } - auto err = TL6WL_registerBoxStatusChangedHandler(deviceHandle_, (Box6WL_StatusChangedHandler)handler); - if (err != 0) + + bool stateCorrect = true; + ViBoolean tempEnableStates[6] = { false, false, false, false, false, false }; + + TL6WL_getLED_HeadPowerStates(deviceHandle_, &tempEnableStates[0], &tempEnableStates[1], &tempEnableStates[2], &tempEnableStates[3], &tempEnableStates[4], &tempEnableStates[5]); + + for (int i = 0; i < numLEDs_; i++) { - return err; + if (tempEnableStates[i] != savedEnabledStates[i]) + { + stateCorrect = false; + savedEnabledStates[i] = tempEnableStates[i]; + } } - return DEVICE_OK; + + return stateCorrect; } -//set or fix any issues with the stored led vals. Return if a correction needed to be made -bool ThorlabsChrolisDeviceWrapper::VerifyLEDStates() +bool ThorlabsChrolisDeviceWrapper::VerifyLEDPowerStates() { if (!deviceConnected_) { @@ -419,18 +456,15 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDStates() } bool stateCorrect = true; - ViUInt16 tempPowerStates[6] = {0,0,0,0,0,0}; - ViBoolean tempEnableStates[6] = { false, false, false, false, false, false }; + ViUInt16 tempPowerStates[6] = { 0,0,0,0,0,0 }; - TL6WL_getLED_HeadPowerStates(deviceHandle_, &tempEnableStates[0], &tempEnableStates[1], &tempEnableStates[2], &tempEnableStates[3], &tempEnableStates[4], &tempEnableStates[5]); TL6WL_getLED_HeadBrightness(deviceHandle_, &tempPowerStates[0], &tempPowerStates[1], &tempPowerStates[2], &tempPowerStates[3], &tempPowerStates[4], &tempPowerStates[5]); for (int i = 0; i < numLEDs_; i++) { - if (tempEnableStates[i] != savedEnabledStates[i] || tempPowerStates[i] != savedPowerStates[i]) + if (tempPowerStates[i] != savedPowerStates[i]) { stateCorrect = false; - savedEnabledStates[i] = tempEnableStates[i]; savedPowerStates[i] = tempPowerStates[i]; } } From 962f8a7232e471a8363b1ac9a0f143a9499c2ca1 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Fri, 20 Oct 2023 08:54:52 -0400 Subject: [PATCH 27/91] Some led state sync updates to the wrapper --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 22 ++++++--- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 2 +- .../ThorlabsChrolisDeviceWrapper.cpp | 48 +++++++++++++------ 3 files changed, 50 insertions(+), 22 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 641d9b5c0..f5788cca2 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -644,7 +644,13 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) static_cast(val & (1 << 5)) }; int err = wrapperInstance->SetLEDEnableStates(newStates); - if (err != 0) + if (err == ERR_IMPROPER_SET) + { + LogMessage("LED(s) were not able to set as requested"); + SyncLEDStates(); + return err; + } + else if (err != 0) { LogMessage("Error Setting LED state"); pProp->Set((long)currentLEDState); @@ -659,7 +665,6 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) led6State_ = static_cast(val & (1 << 5)); pProp->Set((long)val); - VerifyLedStates(); return DEVICE_OK; } return DEVICE_OK; @@ -744,15 +749,21 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT } int err = wrapperInstance->SetSingleLEDEnableState(numFromName-1, (ViBoolean)val); - if (err != 0) + if (err == ERR_IMPROPER_SET) + { + SyncLEDStates(); + LogMessage("LED(s) were not able to set as requested"); + return err; + } + else if (err != 0) { LogMessage("Error Setting LED state"); pProp->Set((long)*ledBeingControlled); return err; } + *ledBeingControlled = (ViBoolean)val; pProp->Set((long)*ledBeingControlled); - VerifyLedStates(); return DEVICE_OK; } @@ -847,13 +858,12 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA } *ledBeingControlled = (int)val; pProp->Set((long)*ledBeingControlled); - VerifyLedStates(); return DEVICE_OK; } return DEVICE_OK; } -bool ChrolisStateDevice::VerifyLedStates() +bool ChrolisStateDevice::SyncLEDStates() { ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 0acb2b059..107d91276 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -105,7 +105,7 @@ class ChrolisStateDevice : public CStateDeviceBase //LED Control Methods int OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct); int OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct); - bool VerifyLedStates(); + bool SyncLEDStates(); private: long numPos_; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index bf328ba75..cfa19c3c9 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -310,18 +310,30 @@ int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean state) { - if (LED < 6 && LED >= 0) + if (LED < numLEDs_ && LED >= 0) { + if (!deviceConnected_) + { + return ERR_CHROLIS_NOT_AVAIL; + } + int err = 0; savedEnabledStates[LED] = state; - err = SetLEDEnableStates(savedEnabledStates); - if (err != 0) + + if (masterSwitchState_) { - //revert in case of error - savedEnabledStates[LED] = !state; - return err; + err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates[0], savedEnabledStates[1], savedEnabledStates[2], + savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]); + if (err != 0) + { + return err; + } + if (!VerifyLEDEnableStates()) + { + err = ERR_IMPROPER_SET; + } } - return DEVICE_OK; + return err; } else { @@ -335,22 +347,26 @@ int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) { return ERR_CHROLIS_NOT_AVAIL; } - int i; - for (i = 0; i < numLEDs_; i++) + int err = 0; + for (int i = 0; i < numLEDs_; i++) { savedEnabledStates[i] = states[i]; } - if (masterSwitchState_) { - if (auto err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates[0], savedEnabledStates[1], savedEnabledStates[2], - savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]) != 0) + err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates[0], savedEnabledStates[1], savedEnabledStates[2], + savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]); + if (err != 0) + { + return err; + } + if (!VerifyLEDEnableStates()) { - return DEVICE_ERR; + err = ERR_IMPROPER_SET; } } - return DEVICE_OK; + return err; } int ThorlabsChrolisDeviceWrapper::SetSingleLEDPowerState(int LED, ViUInt16 state) @@ -444,6 +460,7 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDEnableStates() savedEnabledStates[i] = tempEnableStates[i]; } } + delete tempEnableStates; return stateCorrect; } @@ -468,6 +485,7 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDPowerStates() savedPowerStates[i] = tempPowerStates[i]; } } - + delete tempPowerStates; + return stateCorrect; } \ No newline at end of file From 770965d2ee2763e68b73287f5394760f61667b18 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Fri, 20 Oct 2023 11:36:31 -0400 Subject: [PATCH 28/91] Changes for properties using the chrolis instance vals instead of stored. --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 121 +++++++++++------- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 2 + .../ThorlabsChrolisDeviceWrapper.cpp | 58 ++++++++- 3 files changed, 134 insertions(+), 47 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index f5788cca2..54f65cc89 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -594,36 +594,47 @@ int ChrolisStateDevice::OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct) return DEVICE_OK; } -//OnPropertyChanged("AsyncPropertyFollower", leaderValue.c_str()); -//Update onState to use binary value -//single state changes should modify the single led, verify that it was changed, update global state long, onchange OnState -// Update states of properties based on initial values -//Error check hardware calls and revert properties if something fails + +// Get set process +// Get: pull instances of hub and chrolis, get the latest led states and set local vars to these states, if error use stored vals. +// This ensures UI is always updated with the current chrolis vals when possible +// Set: use local stored vals as a fallback if the instances cannot be retrieved, set the val in the wrapper, wrapper takes care of hardware verification. +// In the event of an error, leave property unset and let OnChange handle update. The get uses the current instance so this would keep values synced int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) { if (eAct == MM::BeforeGet) { + ChrolisHub* pHub = static_cast(GetParentHub()); + if (!pHub || !pHub->IsInitialized()) + { + LogMessage("Hub not available"); + } + ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + if (!wrapperInstance->IsDeviceConnected()) + { + LogMessage("CHROLIS not available"); + } + if (wrapperInstance->GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_) != 0) + { + LogMessage("Error getting info from chrolis"); + } + pProp->Set((long)((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5))); } else if (eAct == MM::AfterSet) { - long val; + //temp state from last set used as fallback uint8_t currentLEDState = ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5)); - pProp->Get(val); - if (val >= pow(2, numPos_) || val < 0) - { - LogMessage("Requested state out of bounds"); - pProp->Set((long)currentLEDState); - return ERR_UNKNOWN_LED_STATE; - } - + //Get the current instances for hub and chrolis + //In the event of error do not set the property. Set old value. Updated values will be pulled from getters if possible ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { LogMessage("Hub not available"); + pProp->Set((long)currentLEDState); return ERR_HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); @@ -634,6 +645,16 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) return ERR_CHROLIS_NOT_AVAIL; } + + long val; // incoming value from user + pProp->Get(val); + if (val >= pow(2, numPos_) || val < 0) + { + LogMessage("Requested state out of bounds"); + pProp->Set((long)currentLEDState); + return ERR_UNKNOWN_LED_STATE; + } + ViBoolean newStates[6] { static_cast(val & (1 << 0)), @@ -644,27 +665,25 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) static_cast(val & (1 << 5)) }; int err = wrapperInstance->SetLEDEnableStates(newStates); - if (err == ERR_IMPROPER_SET) - { - LogMessage("LED(s) were not able to set as requested"); - SyncLEDStates(); - return err; - } - else if (err != 0) + if (err != 0) { + //Do not set the property in the case of this error. Let the property change handle it. + //This will cover error where LED failed to set but chrolis is still ok LogMessage("Error Setting LED state"); - pProp->Set((long)currentLEDState); + OnPropertiesChanged(); return err; } - - led1State_ = static_cast(val & (1 << 0)); - led2State_ = static_cast(val & (1 << 1)); - led3State_ = static_cast(val & (1 << 2)); - led4State_ = static_cast(val & (1 << 3)); - led5State_ = static_cast(val & (1 << 4)); - led6State_ = static_cast(val & (1 << 5)); - pProp->Set((long)val); + + //Probably don't need these but leaving for now + //led1State_ = static_cast(val & (1 << 0)); + //led2State_ = static_cast(val & (1 << 1)); + //led3State_ = static_cast(val & (1 << 2)); + //led4State_ = static_cast(val & (1 << 3)); + //led5State_ = static_cast(val & (1 << 4)); + //led6State_ = static_cast(val & (1 << 5)); + + delete newStates; return DEVICE_OK; } return DEVICE_OK; @@ -722,22 +741,32 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT if (eAct == MM::BeforeGet) { + ChrolisHub* pHub = static_cast(GetParentHub()); + if (!pHub || !pHub->IsInitialized()) + { + LogMessage("Hub not available"); + } + ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + if (!wrapperInstance->IsDeviceConnected()) + { + LogMessage("CHROLIS not available"); + } + if (wrapperInstance->GetSingleLEDEnableState(numFromName, *ledBeingControlled) != 0) + { + LogMessage("Error getting info from chrolis"); + } pProp->Set((long)*ledBeingControlled); } else if (eAct == MM::AfterSet) { double val; pProp->Get(val); - if (val > ledMaxPower_ || val < ledMinPower_) - { - LogMessage("Error Setting LED state"); - pProp->Set((long)*ledBeingControlled); - return ERR_UNKNOWN_LED_STATE; - } + ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { LogMessage("Hub not available"); + pProp->Set((long)*ledBeingControlled); return ERR_HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); @@ -748,17 +777,19 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT return ERR_CHROLIS_NOT_AVAIL; } + //int err = wrapperInstance->GetSingleLEDEnableState(numFromName - 1, *ledBeingControlled); + //if (err != 0) + //{ + // LogMessage("Error Setting LED state"); + // pProp->Set((long)*ledBeingControlled); + // return err; + //} + int err = wrapperInstance->SetSingleLEDEnableState(numFromName-1, (ViBoolean)val); - if (err == ERR_IMPROPER_SET) - { - SyncLEDStates(); - LogMessage("LED(s) were not able to set as requested"); - return err; - } - else if (err != 0) + if (err != 0) { LogMessage("Error Setting LED state"); - pProp->Set((long)*ledBeingControlled); + OnPropertiesChanged(); return err; } @@ -885,7 +916,7 @@ bool ChrolisStateDevice::SyncLEDStates() { return false; } - int err = wrapperInstance->GetLEDPowerStates(tmpPowerStates); + err = wrapperInstance->GetLEDPowerStates(tmpPowerStates); if (err != 0) { return false; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 107d91276..275925798 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -144,8 +144,10 @@ class ThorlabsChrolisDeviceWrapper int GetDeviceStatus(ViUInt32& status); int GetLEDWavelengths(ViUInt16(&wavelengths)[6]); int GetShutterState(bool& open); + int GetSingleLEDEnableState(int led, ViBoolean& state); int GetLEDEnableStates(ViBoolean(&states)[6]); int GetLEDEnableStates(ViBoolean& led1State, ViBoolean& led2State, ViBoolean& led3State, ViBoolean& led4State, ViBoolean& led5State, ViBoolean& led6State); + int GetSingleLEDPowerState(int led, ViUInt16& state); int GetLEDPowerStates(ViUInt16(&states)[6]); int GetLEDPowerStates(ViUInt16 &led1Power, ViUInt16&led2Power, ViUInt16&led3Power, ViUInt16&led4Power, ViUInt16&led5Power, ViUInt16&led6Power); diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index cfa19c3c9..9cbd13e1a 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -206,6 +206,24 @@ int ThorlabsChrolisDeviceWrapper::GetLEDWavelengths(ViUInt16(&wavelengths)[6]) return DEVICE_OK; } +int ThorlabsChrolisDeviceWrapper::GetSingleLEDEnableState(int led, ViBoolean& state) +{ + if (led < numLEDs_ && led >= 0) + { + if (!deviceConnected_) + { + return ERR_CHROLIS_NOT_AVAIL; + } + state = savedEnabledStates[led]; + } + else + { + return ERR_PARAM_NOT_VALID; + } + + return DEVICE_OK; +} + int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean(&states)[6]) { if (!deviceConnected_) @@ -245,6 +263,24 @@ int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean& led1State, ViBoo return DEVICE_OK; } +int ThorlabsChrolisDeviceWrapper::GetSingleLEDPowerState(int led, ViUInt16& state) +{ + if (led < numLEDs_ && led >= 0) + { + if (!deviceConnected_) + { + return ERR_CHROLIS_NOT_AVAIL; + } + state = savedPowerStates[led]; + } + else + { + return ERR_PARAM_NOT_VALID; + } + + return DEVICE_OK; +} + int ThorlabsChrolisDeviceWrapper::GetLEDPowerStates(ViUInt16(&states)[6]) { if (!deviceConnected_) @@ -286,14 +322,27 @@ int ThorlabsChrolisDeviceWrapper::GetLEDPowerStates(ViUInt16& led1Power, ViUInt1 int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) { - int err; + int err = DEVICE_OK; if (!open) { + ViBoolean tempEnableStates[6]; err = TL6WL_setLED_HeadPowerStates(deviceHandle_, false, false, false, false, false, false); if (err != 0) { return err; } + err = TL6WL_getLED_HeadPowerStates(deviceHandle_, &tempEnableStates[0], &tempEnableStates[1], &tempEnableStates[2], &tempEnableStates[3], &tempEnableStates[4], &tempEnableStates[5]); + for (int i = 0; i < numLEDs_; i++) + { + if (tempEnableStates[i]) + { + //led(s) failed to turn off handle error in mm device + err = ERR_IMPROPER_SET; + masterSwitchState_ = true; + break; + } + } + delete tempEnableStates; masterSwitchState_ = false; } else @@ -304,8 +353,13 @@ int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) return err; } masterSwitchState_ = true; + if (!VerifyLEDEnableStates()) + { + err = ERR_IMPROPER_SET; + } + } - return DEVICE_OK; + return err; } int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean state) From 051b35b5749e1530d1d3911d62bd0306be6cd01d Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Fri, 20 Oct 2023 11:43:27 -0400 Subject: [PATCH 29/91] comment --- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 54f65cc89..7edd30c18 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -599,7 +599,7 @@ int ChrolisStateDevice::OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct) // Get: pull instances of hub and chrolis, get the latest led states and set local vars to these states, if error use stored vals. // This ensures UI is always updated with the current chrolis vals when possible // Set: use local stored vals as a fallback if the instances cannot be retrieved, set the val in the wrapper, wrapper takes care of hardware verification. -// In the event of an error, leave property unset and let OnChange handle update. The get uses the current instance so this would keep values synced +// In the event of an error, leave property unset and let OnChange handle update. The get uses the current instance so this would keep values synced int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) { if (eAct == MM::BeforeGet) From dd9072b99ee3594a785a86b75e24babd11bf1fee Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Mon, 23 Oct 2023 14:27:03 -0400 Subject: [PATCH 30/91] Mutex changes Property verification changes Added Error Text --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 366 +++++++++++------- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 23 +- .../ThorlabsChrolisDeviceWrapper.cpp | 57 ++- 3 files changed, 276 insertions(+), 170 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 7edd30c18..34b22cf50 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -3,7 +3,6 @@ #include #include -using namespace std; /*TODO * Set states of properties based on current LED states - x @@ -11,7 +10,7 @@ using namespace std; * Error handling on device control methods - x * custom errors and messages * logs for errors - x -* Remove HubID Property +* Remove HubID Property -x * Integer property range 0 to 1 for each LED on off - x * Is sequencable property for each device check arduino implementation * No need for sequence stuff in CHROLIS. Should check if breakout box needs to be enabled in software @@ -19,7 +18,7 @@ using namespace std; * Keep LED control in State Device - x * Maybe keep triggering in Generic if that gets implemented * pre-init properties in constructor - x -* set error text in constructor +* set error text in constructor -x * enumerate in constructor * no logging in constructor * store error in device instance @@ -29,9 +28,10 @@ using namespace std; * leave state as text box - integer property - X * put wavelength in property name - X * handle cases for initialization failing - x -* Verify LED's all turned off with Shutter button -* Shutter off in case of Device Status LLG open +* Verify LED's all turned off with Shutter button -x +* Shutter off in case of Device Status LLG open -x * Can a message be displayed in popup box without a return code? +* Check if lock is needed for multi threading -x */ MODULE_API void InitializeModuleData() { @@ -73,11 +73,34 @@ ChrolisHub::ChrolisHub() : threadRunning_(false), deviceStatusMessage_("No Error") { - CreateHubIDProperty(); + //Custom Errors + SetErrorText(ERR_HUB_NOT_AVAILABLE, "Hub is not available"); + SetErrorText(ERR_CHROLIS_NOT_AVAIL, "CHROLIS Device is not available"); + SetErrorText(ERR_IMPROPER_SET, "Error setting property value. Value will be reset"); + SetErrorText(ERR_PARAM_NOT_VALID, "Value passed to property was out of bounds."); + SetErrorText(ERR_NO_AVAIL_DEVICES, "No available devices were found on the system."); + + //VISA Errors SetErrorText(ERR_INSUF_INFO, "Insufficient location information of the device or the resource is not present on the system"); + SetErrorText(ERR_UNKOWN_HW_STATE, "Unknown Hardware State"); + SetErrorText(ERR_VAL_OVERFLOW, "Parameter Value Overflow"); + + + //CHROLIS Device Specific Errors. Located in TL6WL.h + SetErrorText(INSTR_RUNTIME_ERROR, "CHROLIS Instrument Runtime Error"); + SetErrorText(INSTR_REM_INTER_ERROR, "CHROLIS Instrument Internal Error"); + SetErrorText(INSTR_AUTHENTICATION_ERROR, "CHROLIS Instrument Authentication Error"); + SetErrorText(INSTR_PARAM_ERROR, "CHROLIS Invalid Parameter Error"); + SetErrorText(INSTR_HW_ERROR, "CHROLIS Instrument Hardware Error. Please verify that no hardware faults are present."); + SetErrorText(INSTR_PARAM_CHNG_ERROR, "CHROLIS Instrument Parameter Error"); + SetErrorText(INSTR_INTERNAL_TX_ERR, "CHROLIS Instrument Internal Command Sending Error"); + SetErrorText(INSTR_INTERNAL_RX_ERR, "CHROLIS Instrument Internal Command Receiving Error"); + SetErrorText(INSTR_INVAL_MODE_ERR, "CHROLIS Instrument Invalid Mode Error"); + SetErrorText(INSTR_SERVICE_ERR, "CHROLIS Instrument Service Error"); chrolisDeviceInstance_ = new ThorlabsChrolisDeviceWrapper(); atomic_init(¤tDeviceStatusCode_, 0); + atomic_init(&threadRunning_, false); std::vector serialNumbers; static_cast(chrolisDeviceInstance_)->GetAvailableSerialNumbers(serialNumbers); @@ -171,8 +194,8 @@ int ChrolisHub::Initialize() return DEVICE_ERR; } - threadRunning_ = true; - updateThread_ = thread(&ChrolisHub::StatusChangedPollingThread, this); + threadRunning_.store(true); + updateThread_ = std::thread(&ChrolisHub::StatusChangedPollingThread, this); initialized_ = true; } return DEVICE_OK; @@ -180,9 +203,9 @@ int ChrolisHub::Initialize() int ChrolisHub::Shutdown() { - if (threadRunning_) + if (threadRunning_.load()) { - threadRunning_ = false; + threadRunning_.store(false); // TODO make this atmoic or mutex updateThread_.join(); } @@ -222,101 +245,145 @@ void* ChrolisHub::GetChrolisDeviceInstance() void ChrolisHub::StatusChangedPollingThread() { - while (threadRunning_) + bool statusChangedFlag = false; + ViUInt32 tempStatus = 0; + std::string message = ""; + ViBoolean tempEnableStates[6]; + while (threadRunning_.load()) { ChrolisHub* pHub = static_cast(GetParentHub()); - if (pHub) - { - char hubLabel[MM::MaxStrLength]; - pHub->GetLabel(hubLabel); - SetParentID(hubLabel); - } - else + if (!pHub || !pHub->IsInitialized()) { - LogMessage("No Hub"); - threadRunning_ = false; + LogMessage("Hub not available"); + threadRunning_.store(false); + continue; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (wrapperInstance->IsDeviceConnected()) { - ViUInt32 tempStatus; + message = ""; auto err = wrapperInstance->GetDeviceStatus(tempStatus); if (err != 0) { LogMessage("Error Getting Status"); - threadRunning_ = false; + threadRunning_.store(false); + continue; + } + if (currentDeviceStatusCode_.load() != tempStatus) + { + statusChangedFlag = true; + } + currentDeviceStatusCode_.store(tempStatus); + if (currentDeviceStatusCode_.load() == 0) + { + message += "No Error"; } else - { - std::string message = ""; - currentDeviceStatusCode_.store(tempStatus); - if (currentDeviceStatusCode_.load() == 0) + { + if ((currentDeviceStatusCode_.load() & (1 << 0)) >= 1) { - message += "No Error"; + message += "Box is Open"; } - else + if ((currentDeviceStatusCode_.load() & (1 << 1)) >= 1) { - if ((currentDeviceStatusCode_.load() & (1 << 0)) >= 1) + if (message.length() > 0) { - message += "Box is Open"; + message += ", "; } - if ((currentDeviceStatusCode_.load() & (1 << 1)) >= 1) + message += "LLG not Connected"; + } + if ((currentDeviceStatusCode_.load() & (1 << 2)) >= 1) + { + if (message.length() > 0) { - if (message.length() > 0) - { - message += ", "; - } - message += "LLG not Connected"; + message += ", "; } - if ((currentDeviceStatusCode_.load() & (1 << 2)) >= 1) + message += "Interlock is Open"; + } + if ((currentDeviceStatusCode_.load() & (1 << 3)) >= 1) + { + if (message.length() > 0) { - if (message.length() > 0) - { - message += ", "; - } - message += "Interlock is Open"; + message += ", "; } - if ((currentDeviceStatusCode_.load() & (1 << 3)) >= 1) + message += "Using Default Adjustment"; + } + if ((currentDeviceStatusCode_.load() & (1 << 4)) >= 1) + { + if (message.length() > 0) { - if (message.length() > 0) - { - message += ", "; - } - message += "Using Default Adjustment"; + message += ", "; } - if ((currentDeviceStatusCode_.load() & (1 << 4)) >= 1) + message += "Box Overheated"; + } + if ((currentDeviceStatusCode_.load() & (1 << 5)) >= 1) + { + if (message.length() > 0) { - if (message.length() > 0) - { - message += ", "; - } - message += "Box Overheated"; + message += ", "; } - if ((currentDeviceStatusCode_.load() & (1 << 5)) >= 1) + message += "LED Overheated"; + } + if ((currentDeviceStatusCode_.load() & (1 << 6)) >= 1) + { + if (message.length() > 0) { - if (message.length() > 0) - { - message += ", "; - } - message += "LED Overheated"; + message += ", "; } - if ((currentDeviceStatusCode_.load() & (1 << 6)) >= 1) + message += "Invalid Box Setup"; + } + if (message.length() == 0) + { + message = "Unknown Status"; + } + } + if (statusChangedFlag) + { + if (currentDeviceStatusCode_.load() != 0) + { + wrapperInstance->SyncLEDEnableStates(); + if (wrapperInstance->GetLEDEnableStates(tempEnableStates[0], + tempEnableStates[1], tempEnableStates[2], tempEnableStates[3], tempEnableStates[4], tempEnableStates[5]) != 0) { - if (message.length() > 0) - { - message += ", "; - } - message += "Invalid Box Setup"; + LogMessage("Error getting info from chrolis"); } - if(message.length() == 0) + else { - message = "Unknown Status"; + std::ostringstream os; + os << tempEnableStates[0]; + pHub->GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 1", os.str().c_str()); + + os.clear(); + os << tempEnableStates[1]; + pHub->GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 2", os.str().c_str()); + + os.clear(); + os << tempEnableStates[2]; + pHub->GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 3", os.str().c_str()); + + os.clear(); + os << tempEnableStates[3]; + pHub->GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 4", os.str().c_str()); + + os.clear(); + os << tempEnableStates[4]; + pHub->GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 5", os.str().c_str()); + + os.clear(); + os << tempEnableStates[5]; + pHub->GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 6", os.str().c_str()); + + os.clear(); + os << ((static_cast(tempEnableStates[0]) << 0) | (static_cast(tempEnableStates[1]) << 1) | (static_cast(tempEnableStates[2]) << 2) + | (static_cast(tempEnableStates[3]) << 3) | (static_cast(tempEnableStates[4]) << 4 | (static_cast(tempEnableStates[5]) << 5))); + pHub->GetDevice(CHROLIS_STATE_NAME)->SetProperty("State", os.str().c_str()); + } } - OnPropertyChanged("Device Status", message.c_str()); + statusChangedFlag = false; } - + OnPropertyChanged("Device Status", message.c_str()); } Sleep(500); } @@ -326,7 +393,6 @@ void ChrolisHub::StatusChangedPollingThread() ChrolisShutter::ChrolisShutter() { InitializeDefaultErrorMessages(); - CreateHubIDProperty(); } int ChrolisShutter::Initialize() @@ -342,6 +408,7 @@ int ChrolisShutter::Initialize() if (wrapperInstance->IsDeviceConnected()) { auto err = wrapperInstance->SetShutterState(false); + //return error but reset if needed if (err != 0) { LogMessage("Could not close shutter on init"); @@ -418,7 +485,6 @@ ChrolisStateDevice::ChrolisStateDevice() : InitializeDefaultErrorMessages(); //SetErrorText(ERR_UNKNOWN_POSITION, "Requested position not available in this device"); //EnableDelay(); // signals that the delay setting will be used - CreateHubIDProperty(); } int ChrolisStateDevice::Initialize() @@ -634,14 +700,18 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) if (!pHub || !pHub->IsInitialized()) { LogMessage("Hub not available"); - pProp->Set((long)currentLEDState); + std::ostringstream os; + os << currentLEDState; + OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); - pProp->Set((long)currentLEDState); + std::ostringstream os; + os << currentLEDState; + OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_CHROLIS_NOT_AVAIL; } @@ -651,8 +721,10 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) if (val >= pow(2, numPos_) || val < 0) { LogMessage("Requested state out of bounds"); - pProp->Set((long)currentLEDState); - return ERR_UNKNOWN_LED_STATE; + std::ostringstream os; + os << currentLEDState; + OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); + return ERR_PARAM_NOT_VALID; } ViBoolean newStates[6] @@ -670,10 +742,28 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) //Do not set the property in the case of this error. Let the property change handle it. //This will cover error where LED failed to set but chrolis is still ok LogMessage("Error Setting LED state"); - OnPropertiesChanged(); + if (err != ERR_CHROLIS_NOT_AVAIL) + { + if (wrapperInstance->GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_) != 0) + { + LogMessage("Error getting info from chrolis"); + } + currentLEDState = ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) + | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5)); + + std::ostringstream os; + os << currentLEDState; + OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); + } + return err; } - pProp->Set((long)val); + + std::ostringstream os; + os << val; + OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); + + //pProp->Set((long)val); //Probably don't need these but leaving for now //led1State_ = static_cast(val & (1 << 0)); @@ -683,20 +773,21 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) //led5State_ = static_cast(val & (1 << 4)); //led6State_ = static_cast(val & (1 << 5)); - delete newStates; + //delete newStates; return DEVICE_OK; } return DEVICE_OK; } +//On properties change only way to update range of property int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct) { ViPBoolean ledBeingControlled; int numFromName = -1; std::string searchString = pProp->GetName(); - regex regexp("[-+]?([0-9]*\.[0-9]+|[0-9]+)"); + std::regex regexp("[-+]?([0-9]*\.[0-9]+|[0-9]+)"); std::smatch sm; - regex_search(searchString, sm, regexp); + std::regex_search(searchString, sm, regexp); //The names for the LED's should contain only a single number representing the LED //Use this to set the power @@ -751,7 +842,7 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT { LogMessage("CHROLIS not available"); } - if (wrapperInstance->GetSingleLEDEnableState(numFromName, *ledBeingControlled) != 0) + if (wrapperInstance->GetSingleLEDEnableState(numFromName-1, *ledBeingControlled) != 0) { LogMessage("Error getting info from chrolis"); } @@ -766,35 +857,36 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT if (!pHub || !pHub->IsInitialized()) { LogMessage("Hub not available"); - pProp->Set((long)*ledBeingControlled); + std::ostringstream os; + os << *ledBeingControlled; + OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); - pProp->Set((long)*ledBeingControlled); + std::ostringstream os; + os << *ledBeingControlled; + OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_CHROLIS_NOT_AVAIL; } - //int err = wrapperInstance->GetSingleLEDEnableState(numFromName - 1, *ledBeingControlled); - //if (err != 0) - //{ - // LogMessage("Error Setting LED state"); - // pProp->Set((long)*ledBeingControlled); - // return err; - //} - int err = wrapperInstance->SetSingleLEDEnableState(numFromName-1, (ViBoolean)val); if (err != 0) { LogMessage("Error Setting LED state"); - OnPropertiesChanged(); + wrapperInstance->GetSingleLEDEnableState(numFromName - 1, *ledBeingControlled); + std::ostringstream os; + os << *ledBeingControlled; + OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return err; } *ledBeingControlled = (ViBoolean)val; - pProp->Set((long)*ledBeingControlled); + std::ostringstream os; + os << *ledBeingControlled; + OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return DEVICE_OK; } @@ -806,9 +898,9 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA ViPUInt16 ledBeingControlled; int numFromName = -1; std::string searchString = pProp->GetName(); - regex regexp("[-+]?([0-9]*\.[0-9]+|[0-9]+)"); + std::regex regexp("[-+]?([0-9]*\.[0-9]+|[0-9]+)"); std::smatch sm; - regex_search(searchString, sm, regexp); + std::regex_search(searchString, sm, regexp); //The names for the LED's should contain only a single number representing the LED //Use this to set the power @@ -853,81 +945,63 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA if (eAct == MM::BeforeGet) { + ChrolisHub* pHub = static_cast(GetParentHub()); + if (!pHub || !pHub->IsInitialized()) + { + LogMessage("Hub not available"); + } + ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + if (!wrapperInstance->IsDeviceConnected()) + { + LogMessage("CHROLIS not available"); + } + if (wrapperInstance->GetSingleLEDPowerState(numFromName - 1, *ledBeingControlled) != 0) + { + LogMessage("Error getting info from chrolis"); + } pProp->Set((long)*ledBeingControlled); } else if (eAct == MM::AfterSet) { double val; pProp->Get(val); - if (val > ledMaxPower_ || val < ledMinPower_) - { - LogMessage("Requested power value out of range"); - pProp->Set((long)*ledBeingControlled); - return ERR_UNKNOWN_LED_STATE; - } ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { LogMessage("Hub not available"); - return ERR_HUB_NOT_AVAILABLE; + std::ostringstream os; + os << *ledBeingControlled; + OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); + return ERR_HUB_NOT_AVAILABLE; } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); - pProp->Set((long)*ledBeingControlled); + std::ostringstream os; + os << *ledBeingControlled; + OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_CHROLIS_NOT_AVAIL; } - int err = wrapperInstance->SetSingleLEDPowerState(numFromName-1, val); + int err = wrapperInstance->SetSingleLEDPowerState(numFromName - 1, (ViUInt16)val); if (err != 0) { - LogMessage("Error setting LED power"); - pProp->Set((long)*ledBeingControlled); + LogMessage("Error Setting LED state"); + wrapperInstance->GetSingleLEDPowerState(numFromName - 1, *ledBeingControlled); + std::ostringstream os; + os << *ledBeingControlled; + OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return err; } - *ledBeingControlled = (int)val; - pProp->Set((long)*ledBeingControlled); + + *ledBeingControlled = (ViUInt16)val; + std::ostringstream os; + os << *ledBeingControlled; + OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return DEVICE_OK; } return DEVICE_OK; } -bool ChrolisStateDevice::SyncLEDStates() -{ - ChrolisHub* pHub = static_cast(GetParentHub()); - if (!pHub || !pHub->IsInitialized()) - { - LogMessage("Hub not available"); - } - ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); - if (!wrapperInstance->IsDeviceConnected()) - { - LogMessage("CHROLIS not available"); - } - - bool statesCorrect = true; - ViBoolean tmpEnableStates[6]; - ViUInt16 tmpPowerStates[6]; - - int err = wrapperInstance->GetLEDEnableStates(tmpEnableStates); - if (err != 0) - { - return false; - } - err = wrapperInstance->GetLEDPowerStates(tmpPowerStates); - if (err != 0) - { - return false; - } - - if (tmpEnableStates[0] != led1State_ || tmpPowerStates[0] != led1Power_) - { - } - - delete tmpEnableStates; - delete tmpPowerStates; - - return statesCorrect; -} diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 275925798..fd52348bd 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "DeviceBase.h" #define CHROLIS_HUB_NAME "CHROLIS" @@ -10,18 +11,18 @@ #define CHROLIS_STATE_NAME "CHROLIS_LED_Control" //Custom Error Codes -#define ERR_UNKNOWN_MODE 102 -#define ERR_UNKNOWN_LED_STATE 103 +#define ERR_UNKNOWN_MODE 102 // not currently used +#define ERR_UNKNOWN_LED_STATE 103// don't think this is used #define ERR_HUB_NOT_AVAILABLE 104 #define ERR_CHROLIS_NOT_AVAIL 105 -#define ERR_CHROLIS_SET 106 -#define ERR_CHROLIS_GET 107 +#define ERR_CHROLIS_SET 106 //don't think this is used +#define ERR_CHROLIS_GET 107 // don't think this is used #define ERR_PARAM_NOT_VALID 108 #define ERR_NO_AVAIL_DEVICES 109 #define ERR_IMPROPER_SET 110 //CHROLIS Specific Error Codes -//TODO See if these need to be filled out +#define ERR_HARDWARE_FAULT -1074001669 //VISA Error Codes #define ERR_INSUF_INFO -1073807343 @@ -51,7 +52,7 @@ class ChrolisHub : public HubBase void* chrolisDeviceInstance_; bool initialized_; bool busy_; - bool threadRunning_; + std::atomic_bool threadRunning_; std::thread updateThread_; std::atomic_uint32_t currentDeviceStatusCode_; std::string deviceStatusMessage_; @@ -105,7 +106,6 @@ class ChrolisStateDevice : public CStateDeviceBase //LED Control Methods int OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct); int OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct); - bool SyncLEDStates(); private: long numPos_; @@ -157,13 +157,12 @@ class ThorlabsChrolisDeviceWrapper int SetLEDPowerStates(ViUInt16 states[6]); int SetSingleLEDPowerState(int LED, ViUInt16 state); - bool VerifyLEDStates(); - bool VerifyLEDPowerStates(); - bool VerifyLEDEnableStates(); + bool SyncLEDEnableStates(); private: int numLEDs_; std::vector serialNumberList_; + std::mutex instanceMutex_; bool deviceConnected_; ViSession deviceHandle_; ViBoolean deviceInUse_; //only used by the chrolis API @@ -174,5 +173,9 @@ class ThorlabsChrolisDeviceWrapper ViBoolean savedEnabledStates[6]{false,false,false,false,false,false}; ViUInt16 savedPowerStates[6]{0,0,0,0,0,0}; ViUInt16 ledWavelengths[6]{0,0,0,0,0,0}; + + bool VerifyLEDStates(); + bool VerifyLEDPowerStates(); + bool VerifyLEDEnableStates(); }; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 9cbd13e1a..3e73b0efe 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -118,6 +118,7 @@ int ThorlabsChrolisDeviceWrapper::ShutdownDevice() { if (deviceHandle_ != -1) { + std::lock_guard lock(instanceMutex_); auto err = TL6WL_close(deviceHandle_); if (err != 0) { @@ -167,6 +168,7 @@ int ThorlabsChrolisDeviceWrapper::GetDeviceStatus(ViUInt32& status) status = 0; return ERR_CHROLIS_NOT_AVAIL; } + std::lock_guard lock(instanceMutex_); auto err = TL6WL_getBoxStatus(deviceHandle_, &status); if (err != 0) { @@ -256,7 +258,7 @@ int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean& led1State, ViBoo led1State = savedEnabledStates[0]; led2State = savedEnabledStates[1]; led3State = savedEnabledStates[2]; - led4State = savedEnabledStates[2]; + led4State = savedEnabledStates[3]; led5State = savedEnabledStates[4]; led6State = savedEnabledStates[5]; @@ -323,6 +325,8 @@ int ThorlabsChrolisDeviceWrapper::GetLEDPowerStates(ViUInt16& led1Power, ViUInt1 int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) { int err = DEVICE_OK; + //TODO add checks for device not being open here + std::lock_guard lock(instanceMutex_); if (!open) { ViBoolean tempEnableStates[6]; @@ -342,7 +346,7 @@ int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) break; } } - delete tempEnableStates; + //delete tempEnableStates; masterSwitchState_ = false; } else @@ -370,7 +374,7 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean sta { return ERR_CHROLIS_NOT_AVAIL; } - + std::lock_guard lock(instanceMutex_); int err = 0; savedEnabledStates[LED] = state; @@ -380,6 +384,7 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean sta savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]); if (err != 0) { + VerifyLEDEnableStates(); // try to synch values if possible return err; } if (!VerifyLEDEnableStates()) @@ -401,6 +406,7 @@ int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) { return ERR_CHROLIS_NOT_AVAIL; } + std::lock_guard lock(instanceMutex_); int err = 0; for (int i = 0; i < numLEDs_; i++) { @@ -412,6 +418,7 @@ int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]); if (err != 0) { + VerifyLEDEnableStates(); return err; } if (!VerifyLEDEnableStates()) @@ -427,17 +434,25 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDPowerState(int LED, ViUInt16 state { if (LED < 6 && LED >= 0) { + if (!deviceConnected_) + { + return ERR_CHROLIS_NOT_AVAIL; + } + std::lock_guard lock(instanceMutex_); int err = 0; - ViInt16 tmpPower = savedPowerStates[LED]; savedPowerStates[LED] = state; - err = SetLEDPowerStates(savedPowerStates); + err = TL6WL_setLED_HeadBrightness(deviceHandle_, savedPowerStates[0], savedPowerStates[1], savedPowerStates[2], + savedPowerStates[3], savedPowerStates[4], savedPowerStates[5]); if (err != 0) { - //revert in case of error - savedPowerStates[LED] = tmpPower; + VerifyLEDPowerStates(); return err; } - return DEVICE_OK; + if (!VerifyLEDPowerStates()) + { + err = ERR_IMPROPER_SET; + } + return err; } else { @@ -451,21 +466,35 @@ int ThorlabsChrolisDeviceWrapper::SetLEDPowerStates(ViUInt16 states[6]) { return ERR_CHROLIS_NOT_AVAIL; } + std::lock_guard lock(instanceMutex_); int i; for (i = 0; i < numLEDs_; i++) { savedPowerStates[i] = states[i]; } - - if (auto err = TL6WL_setLED_HeadBrightness(deviceHandle_, savedPowerStates[0], savedPowerStates[1], savedPowerStates[2], - savedPowerStates[3], savedPowerStates[4], savedPowerStates[5]) != 0) + int err = 0; + err = TL6WL_setLED_HeadBrightness(deviceHandle_, savedPowerStates[0], savedPowerStates[1], savedPowerStates[2], + savedPowerStates[3], savedPowerStates[4], savedPowerStates[5]); + if (err != 0) + { + VerifyLEDPowerStates(); + return err; + } + if (!VerifyLEDPowerStates()) { - return DEVICE_ERR; + err = ERR_IMPROPER_SET; } + return err; return DEVICE_OK; } +bool ThorlabsChrolisDeviceWrapper::SyncLEDEnableStates() +{ + std::lock_guard lock(instanceMutex_); + return VerifyLEDEnableStates(); +} + //set or fix any issues with the stored led vals. Return if a correction needed to be made bool ThorlabsChrolisDeviceWrapper::VerifyLEDStates() { @@ -514,7 +543,7 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDEnableStates() savedEnabledStates[i] = tempEnableStates[i]; } } - delete tempEnableStates; + //delete tempEnableStates; return stateCorrect; } @@ -539,7 +568,7 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDPowerStates() savedPowerStates[i] = tempPowerStates[i]; } } - delete tempPowerStates; + //delete tempPowerStates; return stateCorrect; } \ No newline at end of file From 52861ba04eef411e048021b26d1dbbbf4dcb3919 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Mon, 23 Oct 2023 14:31:45 -0400 Subject: [PATCH 31/91] Name change --- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp | 2 +- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h | 2 +- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 34b22cf50..f9f6ff13e 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -342,7 +342,7 @@ void ChrolisHub::StatusChangedPollingThread() { if (currentDeviceStatusCode_.load() != 0) { - wrapperInstance->SyncLEDEnableStates(); + wrapperInstance->VerifyLEDEnableStatesWithLock(); if (wrapperInstance->GetLEDEnableStates(tempEnableStates[0], tempEnableStates[1], tempEnableStates[2], tempEnableStates[3], tempEnableStates[4], tempEnableStates[5]) != 0) { diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index fd52348bd..773b2f8c0 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -157,7 +157,7 @@ class ThorlabsChrolisDeviceWrapper int SetLEDPowerStates(ViUInt16 states[6]); int SetSingleLEDPowerState(int LED, ViUInt16 state); - bool SyncLEDEnableStates(); + bool VerifyLEDEnableStatesWithLock(); private: int numLEDs_; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 3e73b0efe..ebf938f29 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -489,7 +489,7 @@ int ThorlabsChrolisDeviceWrapper::SetLEDPowerStates(ViUInt16 states[6]) return DEVICE_OK; } -bool ThorlabsChrolisDeviceWrapper::SyncLEDEnableStates() +bool ThorlabsChrolisDeviceWrapper::VerifyLEDEnableStatesWithLock() { std::lock_guard lock(instanceMutex_); return VerifyLEDEnableStates(); From 3ecbcc94ca283d1be91952191fd1872f10233386 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Wed, 25 Oct 2023 10:48:17 -0400 Subject: [PATCH 32/91] power --- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index f9f6ff13e..055e8e462 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -478,7 +478,7 @@ int ChrolisShutter::GetOpen(bool& open) //Chrolis State Device Methods ChrolisStateDevice::ChrolisStateDevice() : - numPos_(6), ledMaxPower_(100), ledMinPower_(0), + numPos_(6), ledMaxPower_(1000), ledMinPower_(0), led1Power_(0), led2Power_(0), led3Power_(0), led4Power_(0), led5Power_(0), led6Power_(0), led1State_(false), led2State_(false), led3State_(false), led4State_(false), led5State_(false), led6State_(false) { From 1f624e1ad70a0ab5bbedd4fde50a20761a910c36 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Wed, 25 Oct 2023 16:13:47 -0400 Subject: [PATCH 33/91] Code cleanup --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 63 ++----------------- .../ThorlabsChrolisDeviceWrapper.cpp | 4 -- 2 files changed, 6 insertions(+), 61 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 055e8e462..d368ed7e5 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -4,40 +4,10 @@ #include #include -/*TODO -* Set states of properties based on current LED states - x -* Properties for device ID and stuff - x -* Error handling on device control methods - x -* custom errors and messages -* logs for errors - x -* Remove HubID Property -x -* Integer property range 0 to 1 for each LED on off - x -* Is sequencable property for each device check arduino implementation -* No need for sequence stuff in CHROLIS. Should check if breakout box needs to be enabled in software -* no need for event callbacks in UI for triggering -* Keep LED control in State Device - x -* Maybe keep triggering in Generic if that gets implemented -* pre-init properties in constructor - x -* set error text in constructor -x -* enumerate in constructor -* no logging in constructor -* store error in device instance -* after constructor, needs to be safe to call shutdown or destructor- x -* device specific properties in the hub - x -* state device allowed values added individually for drop down -* leave state as text box - integer property - X -* put wavelength in property name - X -* handle cases for initialization failing - x -* Verify LED's all turned off with Shutter button -x -* Shutter off in case of Device Status LLG open -x -* Can a message be displayed in popup box without a return code? -* Check if lock is needed for multi threading -x -*/ - MODULE_API void InitializeModuleData() { - RegisterDevice(CHROLIS_HUB_NAME, // deviceName: model identifier and default device label + RegisterDevice(CHROLIS_HUB_NAME, MM::HubDevice, - "Thorlabs CHROLIS Hub"); // description + "Thorlabs CHROLIS Hub"); RegisterDevice(CHROLIS_SHUTTER_NAME, MM::ShutterDevice, "Thorlabs CHROLIS Shutter"); @@ -690,6 +660,8 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) } else if (eAct == MM::AfterSet) { + std::ostringstream os; + //temp state from last set used as fallback uint8_t currentLEDState = ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5)); @@ -700,7 +672,6 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) if (!pHub || !pHub->IsInitialized()) { LogMessage("Hub not available"); - std::ostringstream os; os << currentLEDState; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_HUB_NOT_AVAILABLE; @@ -709,7 +680,6 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); - std::ostringstream os; os << currentLEDState; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_CHROLIS_NOT_AVAIL; @@ -721,7 +691,6 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) if (val >= pow(2, numPos_) || val < 0) { LogMessage("Requested state out of bounds"); - std::ostringstream os; os << currentLEDState; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_PARAM_NOT_VALID; @@ -751,7 +720,6 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) currentLEDState = ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5)); - std::ostringstream os; os << currentLEDState; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); } @@ -759,27 +727,14 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) return err; } - std::ostringstream os; os << val; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); - //pProp->Set((long)val); - - //Probably don't need these but leaving for now - //led1State_ = static_cast(val & (1 << 0)); - //led2State_ = static_cast(val & (1 << 1)); - //led3State_ = static_cast(val & (1 << 2)); - //led4State_ = static_cast(val & (1 << 3)); - //led5State_ = static_cast(val & (1 << 4)); - //led6State_ = static_cast(val & (1 << 5)); - - //delete newStates; return DEVICE_OK; } return DEVICE_OK; } -//On properties change only way to update range of property int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct) { ViPBoolean ledBeingControlled; @@ -852,12 +807,12 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT { double val; pProp->Get(val); + std::ostringstream os; ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { LogMessage("Hub not available"); - std::ostringstream os; os << *ledBeingControlled; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_HUB_NOT_AVAILABLE; @@ -866,7 +821,6 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); - std::ostringstream os; os << *ledBeingControlled; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_CHROLIS_NOT_AVAIL; @@ -877,14 +831,12 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT { LogMessage("Error Setting LED state"); wrapperInstance->GetSingleLEDEnableState(numFromName - 1, *ledBeingControlled); - std::ostringstream os; os << *ledBeingControlled; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return err; } *ledBeingControlled = (ViBoolean)val; - std::ostringstream os; os << *ledBeingControlled; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return DEVICE_OK; @@ -965,12 +917,12 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA { double val; pProp->Get(val); + std::ostringstream os; ChrolisHub* pHub = static_cast(GetParentHub()); if (!pHub || !pHub->IsInitialized()) { LogMessage("Hub not available"); - std::ostringstream os; os << *ledBeingControlled; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_HUB_NOT_AVAILABLE; @@ -979,7 +931,6 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); - std::ostringstream os; os << *ledBeingControlled; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_CHROLIS_NOT_AVAIL; @@ -990,14 +941,12 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA { LogMessage("Error Setting LED state"); wrapperInstance->GetSingleLEDPowerState(numFromName - 1, *ledBeingControlled); - std::ostringstream os; os << *ledBeingControlled; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return err; } *ledBeingControlled = (ViUInt16)val; - std::ostringstream os; os << *ledBeingControlled; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return DEVICE_OK; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index ebf938f29..1f7514e22 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -346,7 +346,6 @@ int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) break; } } - //delete tempEnableStates; masterSwitchState_ = false; } else @@ -495,7 +494,6 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDEnableStatesWithLock() return VerifyLEDEnableStates(); } -//set or fix any issues with the stored led vals. Return if a correction needed to be made bool ThorlabsChrolisDeviceWrapper::VerifyLEDStates() { if (!deviceConnected_) @@ -543,7 +541,6 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDEnableStates() savedEnabledStates[i] = tempEnableStates[i]; } } - //delete tempEnableStates; return stateCorrect; } @@ -568,7 +565,6 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDPowerStates() savedPowerStates[i] = tempPowerStates[i]; } } - //delete tempPowerStates; return stateCorrect; } \ No newline at end of file From 60f5721d6e36f7d62fe76f15f3df84401c41613f Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Wed, 25 Oct 2023 17:04:20 -0400 Subject: [PATCH 34/91] Code cleanup and some variable name changes to better match the device sdk --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 50 +++---- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 34 ++--- .../ThorlabsChrolisDeviceWrapper.cpp | 125 ++++++++++-------- 3 files changed, 112 insertions(+), 97 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index d368ed7e5..0ea564d9f 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -448,8 +448,8 @@ int ChrolisShutter::GetOpen(bool& open) //Chrolis State Device Methods ChrolisStateDevice::ChrolisStateDevice() : - numPos_(6), ledMaxPower_(1000), ledMinPower_(0), - led1Power_(0), led2Power_(0), led3Power_(0), led4Power_(0), led5Power_(0), led6Power_(0), + numPos_(6), ledMaxBrightness_(1000), ledMinBrightness_(0), + led1Brightness_(0), led2Brightness_(0), led3Brightness_(0), led4Brightness_(0), led5Brightness_(0), led6Brightness_(0), led1State_(false), led2State_(false), led3State_(false), led4State_(false), led5State_(false), led6State_(false) { InitializeDefaultErrorMessages(); @@ -483,7 +483,7 @@ int ChrolisStateDevice::Initialize() if (wrapperInstance->IsDeviceConnected()) { err = wrapperInstance->GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_); - err = wrapperInstance->GetLEDPowerStates(led1Power_, led2Power_, led3Power_, led4Power_, led5Power_, led6Power_); + err = wrapperInstance->GetLEDBrightnessStates(led1Brightness_, led2Brightness_, led3Brightness_, led4Brightness_, led5Brightness_, led6Brightness_); tmpLedState = ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5)); @@ -498,17 +498,17 @@ int ChrolisStateDevice::Initialize() ////Properties for power control pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 1 Power", led1Power_, false, pAct); + err = CreateIntegerProperty("LED 1 Power", led1Brightness_, false, pAct); if (err != 0) { LogMessage("Error with property set in power control"); return DEVICE_ERR; } - SetPropertyLimits("LED 1 Power", ledMinPower_, ledMaxPower_); + SetPropertyLimits("LED 1 Power", ledMinBrightness_, ledMaxBrightness_); pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 2 Power", led2Power_, false, pAct); - SetPropertyLimits("LED 2 Power", ledMinPower_, ledMaxPower_); + err = CreateIntegerProperty("LED 2 Power", led2Brightness_, false, pAct); + SetPropertyLimits("LED 2 Power", ledMinBrightness_, ledMaxBrightness_); if (err != 0) { return DEVICE_ERR; @@ -516,8 +516,8 @@ int ChrolisStateDevice::Initialize() } pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 3 Power", led3Power_, false, pAct); - SetPropertyLimits("LED 3 Power", ledMinPower_, ledMaxPower_); + err = CreateIntegerProperty("LED 3 Power", led3Brightness_, false, pAct); + SetPropertyLimits("LED 3 Power", ledMinBrightness_, ledMaxBrightness_); if (err != 0) { return DEVICE_ERR; @@ -525,8 +525,8 @@ int ChrolisStateDevice::Initialize() } pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 4 Power", led4Power_, false, pAct); - SetPropertyLimits("LED 4 Power", ledMinPower_, ledMaxPower_); + err = CreateIntegerProperty("LED 4 Power", led4Brightness_, false, pAct); + SetPropertyLimits("LED 4 Power", ledMinBrightness_, ledMaxBrightness_); if (err != 0) { return DEVICE_ERR; @@ -534,8 +534,8 @@ int ChrolisStateDevice::Initialize() } pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 5 Power", led5Power_, false, pAct); - SetPropertyLimits("LED 5 Power", ledMinPower_, ledMaxPower_); + err = CreateIntegerProperty("LED 5 Power", led5Brightness_, false, pAct); + SetPropertyLimits("LED 5 Power", ledMinBrightness_, ledMaxBrightness_); if (err != 0) { return DEVICE_ERR; @@ -543,8 +543,8 @@ int ChrolisStateDevice::Initialize() } pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 6 Power", led6Power_, false, pAct); - SetPropertyLimits("LED 6 Power", ledMinPower_, ledMaxPower_); + err = CreateIntegerProperty("LED 6 Power", led6Brightness_, false, pAct); + SetPropertyLimits("LED 6 Power", ledMinBrightness_, ledMaxBrightness_); if (err != 0) { return DEVICE_ERR; @@ -599,7 +599,7 @@ int ChrolisStateDevice::Initialize() SetPropertyLimits("LED Enable State 5", 0, 1); pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 6", led6Power_, false, pAct); + err = CreateIntegerProperty("LED Enable State 6", led6Brightness_, false, pAct); if (err != 0) { LogMessage("Error with property set in state control"); @@ -872,22 +872,22 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA switch (numFromName) { case 1: - ledBeingControlled = &led1Power_; + ledBeingControlled = &led1Brightness_; break; case 2: - ledBeingControlled = &led2Power_; + ledBeingControlled = &led2Brightness_; break; case 3: - ledBeingControlled = &led3Power_; + ledBeingControlled = &led3Brightness_; break; case 4: - ledBeingControlled = &led4Power_; + ledBeingControlled = &led4Brightness_; break; case 5: - ledBeingControlled = &led5Power_; + ledBeingControlled = &led5Brightness_; break; case 6: - ledBeingControlled = &led6Power_; + ledBeingControlled = &led6Brightness_; break; default: LogMessage("Error selecting LED state"); @@ -907,7 +907,7 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA { LogMessage("CHROLIS not available"); } - if (wrapperInstance->GetSingleLEDPowerState(numFromName - 1, *ledBeingControlled) != 0) + if (wrapperInstance->GetSingleLEDBrightnessState(numFromName - 1, *ledBeingControlled) != 0) { LogMessage("Error getting info from chrolis"); } @@ -936,11 +936,11 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA return ERR_CHROLIS_NOT_AVAIL; } - int err = wrapperInstance->SetSingleLEDPowerState(numFromName - 1, (ViUInt16)val); + int err = wrapperInstance->SetSingleLEDBrightnessState(numFromName - 1, (ViUInt16)val); if (err != 0) { LogMessage("Error Setting LED state"); - wrapperInstance->GetSingleLEDPowerState(numFromName - 1, *ledBeingControlled); + wrapperInstance->GetSingleLEDBrightnessState(numFromName - 1, *ledBeingControlled); os << *ledBeingControlled; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return err; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 773b2f8c0..223e5412a 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -110,12 +110,12 @@ class ChrolisStateDevice : public CStateDeviceBase private: long numPos_; - ViUInt16 led1Power_; - ViUInt16 led2Power_; - ViUInt16 led3Power_; - ViUInt16 led4Power_; - ViUInt16 led5Power_; - ViUInt16 led6Power_; + ViUInt16 led1Brightness_; + ViUInt16 led2Brightness_; + ViUInt16 led3Brightness_; + ViUInt16 led4Brightness_; + ViUInt16 led5Brightness_; + ViUInt16 led6Brightness_; ViBoolean led1State_; ViBoolean led2State_; @@ -124,8 +124,8 @@ class ChrolisStateDevice : public CStateDeviceBase ViBoolean led5State_; ViBoolean led6State_; - ViInt16 ledMaxPower_; - ViInt16 ledMinPower_; + ViInt16 ledMaxBrightness_; + ViInt16 ledMinBrightness_; }; //Wrapper for the basic functions used in this device adapter @@ -147,15 +147,15 @@ class ThorlabsChrolisDeviceWrapper int GetSingleLEDEnableState(int led, ViBoolean& state); int GetLEDEnableStates(ViBoolean(&states)[6]); int GetLEDEnableStates(ViBoolean& led1State, ViBoolean& led2State, ViBoolean& led3State, ViBoolean& led4State, ViBoolean& led5State, ViBoolean& led6State); - int GetSingleLEDPowerState(int led, ViUInt16& state); - int GetLEDPowerStates(ViUInt16(&states)[6]); - int GetLEDPowerStates(ViUInt16 &led1Power, ViUInt16&led2Power, ViUInt16&led3Power, ViUInt16&led4Power, ViUInt16&led5Power, ViUInt16&led6Power); + int GetSingleLEDBrightnessState(int led, ViUInt16& state); + int GetLEDBrightnessStates(ViUInt16(&states)[6]); + int GetLEDBrightnessStates(ViUInt16 &led1Brightness, ViUInt16&led2Brightness, ViUInt16&led3Brightness, ViUInt16&led4Brightness, ViUInt16&led5Brightness, ViUInt16&led6Brightness); int SetShutterState(bool open); int SetLEDEnableStates(ViBoolean states[6]); int SetSingleLEDEnableState(int LED, ViBoolean state); - int SetLEDPowerStates(ViUInt16 states[6]); - int SetSingleLEDPowerState(int LED, ViUInt16 state); + int SetLEDBrightnessStates(ViUInt16 states[6]); + int SetSingleLEDBrightnessState(int LED, ViUInt16 state); bool VerifyLEDEnableStatesWithLock(); @@ -170,12 +170,12 @@ class ThorlabsChrolisDeviceWrapper ViChar serialNumber_[TL6WL_LONG_STRING_SIZE]; ViChar manufacturerName_[TL6WL_LONG_STRING_SIZE]; bool masterSwitchState_; - ViBoolean savedEnabledStates[6]{false,false,false,false,false,false}; - ViUInt16 savedPowerStates[6]{0,0,0,0,0,0}; - ViUInt16 ledWavelengths[6]{0,0,0,0,0,0}; + ViBoolean savedEnabledStates_[6]{false,false,false,false,false,false}; + ViUInt16 savedBrightnessStates_[6]{0,0,0,0,0,0}; + ViUInt16 ledWavelengths_[6]{0,0,0,0,0,0}; bool VerifyLEDStates(); bool VerifyLEDPowerStates(); bool VerifyLEDEnableStates(); -}; +}; \ No newline at end of file diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 1f7514e22..83c5a1468 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -103,7 +103,7 @@ int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) for (int i = 0; i < numLEDs_; i++) { - err = TL6WL_readLED_HeadPeakWL(deviceHandle_, i+1, &ledWavelengths[i]); + err = TL6WL_readLED_HeadPeakWL(deviceHandle_, i+1, &ledWavelengths_[i]); if (err != 0) { return err; @@ -163,12 +163,13 @@ int ThorlabsChrolisDeviceWrapper::GetManufacturerName(ViChar* manfName) int ThorlabsChrolisDeviceWrapper::GetDeviceStatus(ViUInt32& status) { + std::lock_guard lock(instanceMutex_); + if (!deviceConnected_) { status = 0; return ERR_CHROLIS_NOT_AVAIL; } - std::lock_guard lock(instanceMutex_); auto err = TL6WL_getBoxStatus(deviceHandle_, &status); if (err != 0) { @@ -179,6 +180,8 @@ int ThorlabsChrolisDeviceWrapper::GetDeviceStatus(ViUInt32& status) int ThorlabsChrolisDeviceWrapper::GetShutterState(bool& open) { + std::lock_guard lock(instanceMutex_); + if (!deviceConnected_) { open = false; @@ -198,25 +201,27 @@ int ThorlabsChrolisDeviceWrapper::GetLEDWavelengths(ViUInt16(&wavelengths)[6]) } return ERR_CHROLIS_NOT_AVAIL; } - wavelengths[0] = ledWavelengths[0]; - wavelengths[1] = ledWavelengths[1]; - wavelengths[2] = ledWavelengths[2]; - wavelengths[3] = ledWavelengths[3]; - wavelengths[4] = ledWavelengths[4]; - wavelengths[5] = ledWavelengths[5]; + wavelengths[0] = ledWavelengths_[0]; + wavelengths[1] = ledWavelengths_[1]; + wavelengths[2] = ledWavelengths_[2]; + wavelengths[3] = ledWavelengths_[3]; + wavelengths[4] = ledWavelengths_[4]; + wavelengths[5] = ledWavelengths_[5]; return DEVICE_OK; } int ThorlabsChrolisDeviceWrapper::GetSingleLEDEnableState(int led, ViBoolean& state) { + std::lock_guard lock(instanceMutex_); + if (led < numLEDs_ && led >= 0) { if (!deviceConnected_) { return ERR_CHROLIS_NOT_AVAIL; } - state = savedEnabledStates[led]; + state = savedEnabledStates_[led]; } else { @@ -228,6 +233,8 @@ int ThorlabsChrolisDeviceWrapper::GetSingleLEDEnableState(int led, ViBoolean& st int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean(&states)[6]) { + std::lock_guard lock(instanceMutex_); + if (!deviceConnected_) { for (int i = 0; i < 6; i++) @@ -238,13 +245,15 @@ int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean(&states)[6]) } for (int i = 0; i < 6; i++) { - states[i] = savedEnabledStates[i]; + states[i] = savedEnabledStates_[i]; } return DEVICE_OK; } int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean& led1State, ViBoolean& led2State, ViBoolean& led3State, ViBoolean& led4State, ViBoolean& led5State, ViBoolean& led6State) { + std::lock_guard lock(instanceMutex_); + if (!deviceConnected_) { led1State = false; @@ -255,25 +264,27 @@ int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean& led1State, ViBoo led6State = false; return ERR_CHROLIS_NOT_AVAIL; } - led1State = savedEnabledStates[0]; - led2State = savedEnabledStates[1]; - led3State = savedEnabledStates[2]; - led4State = savedEnabledStates[3]; - led5State = savedEnabledStates[4]; - led6State = savedEnabledStates[5]; + led1State = savedEnabledStates_[0]; + led2State = savedEnabledStates_[1]; + led3State = savedEnabledStates_[2]; + led4State = savedEnabledStates_[3]; + led5State = savedEnabledStates_[4]; + led6State = savedEnabledStates_[5]; return DEVICE_OK; } -int ThorlabsChrolisDeviceWrapper::GetSingleLEDPowerState(int led, ViUInt16& state) +int ThorlabsChrolisDeviceWrapper::GetSingleLEDBrightnessState(int led, ViUInt16& state) { + std::lock_guard lock(instanceMutex_); + if (led < numLEDs_ && led >= 0) { if (!deviceConnected_) { return ERR_CHROLIS_NOT_AVAIL; } - state = savedPowerStates[led]; + state = savedBrightnessStates_[led]; } else { @@ -283,8 +294,10 @@ int ThorlabsChrolisDeviceWrapper::GetSingleLEDPowerState(int led, ViUInt16& stat return DEVICE_OK; } -int ThorlabsChrolisDeviceWrapper::GetLEDPowerStates(ViUInt16(&states)[6]) +int ThorlabsChrolisDeviceWrapper::GetLEDBrightnessStates(ViUInt16(&states)[6]) { + std::lock_guard lock(instanceMutex_); + if (!deviceConnected_) { for (int i = 0; i < 6; i++) @@ -295,29 +308,31 @@ int ThorlabsChrolisDeviceWrapper::GetLEDPowerStates(ViUInt16(&states)[6]) } for (int i = 0; i < 6; i++) { - states[i] = savedPowerStates[i]; + states[i] = savedBrightnessStates_[i]; } return DEVICE_OK; } -int ThorlabsChrolisDeviceWrapper::GetLEDPowerStates(ViUInt16& led1Power, ViUInt16& led2Power, ViUInt16& led3Power, ViUInt16& led4Power, ViUInt16& led5Power, ViUInt16& led6Power) +int ThorlabsChrolisDeviceWrapper::GetLEDBrightnessStates(ViUInt16& led1Brightness, ViUInt16& led2Brightness, ViUInt16& led3Brightness, ViUInt16& led4Brightness, ViUInt16& led5Brightness, ViUInt16& led6Brightness) { + std::lock_guard lock(instanceMutex_); + if (!deviceConnected_) { - led1Power = 0; - led2Power = 0; - led3Power = 0; - led4Power = 0; - led5Power = 0; - led6Power = 0; + led1Brightness = 0; + led2Brightness = 0; + led3Brightness = 0; + led4Brightness = 0; + led5Brightness = 0; + led6Brightness = 0; return ERR_CHROLIS_NOT_AVAIL; } - led1Power = savedPowerStates[0]; - led2Power = savedPowerStates[1]; - led3Power = savedPowerStates[2]; - led4Power = savedPowerStates[2]; - led5Power = savedPowerStates[4]; - led6Power = savedPowerStates[5]; + led1Brightness = savedBrightnessStates_[0]; + led2Brightness = savedBrightnessStates_[1]; + led3Brightness = savedBrightnessStates_[2]; + led4Brightness = savedBrightnessStates_[2]; + led5Brightness = savedBrightnessStates_[4]; + led6Brightness = savedBrightnessStates_[5]; return DEVICE_OK; } @@ -350,7 +365,7 @@ int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) } else { - err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates[0], savedEnabledStates[1], savedEnabledStates[2], savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]); + err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates_[0], savedEnabledStates_[1], savedEnabledStates_[2], savedEnabledStates_[3], savedEnabledStates_[4], savedEnabledStates_[5]); if (err != 0) { return err; @@ -375,12 +390,12 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean sta } std::lock_guard lock(instanceMutex_); int err = 0; - savedEnabledStates[LED] = state; + savedEnabledStates_[LED] = state; if (masterSwitchState_) { - err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates[0], savedEnabledStates[1], savedEnabledStates[2], - savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]); + err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates_[0], savedEnabledStates_[1], savedEnabledStates_[2], + savedEnabledStates_[3], savedEnabledStates_[4], savedEnabledStates_[5]); if (err != 0) { VerifyLEDEnableStates(); // try to synch values if possible @@ -409,12 +424,12 @@ int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) int err = 0; for (int i = 0; i < numLEDs_; i++) { - savedEnabledStates[i] = states[i]; + savedEnabledStates_[i] = states[i]; } if (masterSwitchState_) { - err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates[0], savedEnabledStates[1], savedEnabledStates[2], - savedEnabledStates[3], savedEnabledStates[4], savedEnabledStates[5]); + err = TL6WL_setLED_HeadPowerStates(deviceHandle_, savedEnabledStates_[0], savedEnabledStates_[1], savedEnabledStates_[2], + savedEnabledStates_[3], savedEnabledStates_[4], savedEnabledStates_[5]); if (err != 0) { VerifyLEDEnableStates(); @@ -429,7 +444,7 @@ int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) return err; } -int ThorlabsChrolisDeviceWrapper::SetSingleLEDPowerState(int LED, ViUInt16 state) +int ThorlabsChrolisDeviceWrapper::SetSingleLEDBrightnessState(int LED, ViUInt16 state) { if (LED < 6 && LED >= 0) { @@ -439,9 +454,9 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDPowerState(int LED, ViUInt16 state } std::lock_guard lock(instanceMutex_); int err = 0; - savedPowerStates[LED] = state; - err = TL6WL_setLED_HeadBrightness(deviceHandle_, savedPowerStates[0], savedPowerStates[1], savedPowerStates[2], - savedPowerStates[3], savedPowerStates[4], savedPowerStates[5]); + savedBrightnessStates_[LED] = state; + err = TL6WL_setLED_HeadBrightness(deviceHandle_, savedBrightnessStates_[0], savedBrightnessStates_[1], savedBrightnessStates_[2], + savedBrightnessStates_[3], savedBrightnessStates_[4], savedBrightnessStates_[5]); if (err != 0) { VerifyLEDPowerStates(); @@ -459,7 +474,7 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDPowerState(int LED, ViUInt16 state } } -int ThorlabsChrolisDeviceWrapper::SetLEDPowerStates(ViUInt16 states[6]) +int ThorlabsChrolisDeviceWrapper::SetLEDBrightnessStates(ViUInt16 states[6]) { if (!deviceConnected_) { @@ -469,11 +484,11 @@ int ThorlabsChrolisDeviceWrapper::SetLEDPowerStates(ViUInt16 states[6]) int i; for (i = 0; i < numLEDs_; i++) { - savedPowerStates[i] = states[i]; + savedBrightnessStates_[i] = states[i]; } int err = 0; - err = TL6WL_setLED_HeadBrightness(deviceHandle_, savedPowerStates[0], savedPowerStates[1], savedPowerStates[2], - savedPowerStates[3], savedPowerStates[4], savedPowerStates[5]); + err = TL6WL_setLED_HeadBrightness(deviceHandle_, savedBrightnessStates_[0], savedBrightnessStates_[1], savedBrightnessStates_[2], + savedBrightnessStates_[3], savedBrightnessStates_[4], savedBrightnessStates_[5]); if (err != 0) { VerifyLEDPowerStates(); @@ -510,11 +525,11 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDStates() for (int i = 0; i < numLEDs_; i++) { - if (tempEnableStates[i] != savedEnabledStates[i] || tempPowerStates[i] != savedPowerStates[i]) + if (tempEnableStates[i] != savedEnabledStates_[i] || tempPowerStates[i] != savedBrightnessStates_[i]) { stateCorrect = false; - savedEnabledStates[i] = tempEnableStates[i]; - savedPowerStates[i] = tempPowerStates[i]; + savedEnabledStates_[i] = tempEnableStates[i]; + savedBrightnessStates_[i] = tempPowerStates[i]; } } @@ -535,10 +550,10 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDEnableStates() for (int i = 0; i < numLEDs_; i++) { - if (tempEnableStates[i] != savedEnabledStates[i]) + if (tempEnableStates[i] != savedEnabledStates_[i]) { stateCorrect = false; - savedEnabledStates[i] = tempEnableStates[i]; + savedEnabledStates_[i] = tempEnableStates[i]; } } @@ -559,10 +574,10 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDPowerStates() for (int i = 0; i < numLEDs_; i++) { - if (tempPowerStates[i] != savedPowerStates[i]) + if (tempPowerStates[i] != savedBrightnessStates_[i]) { stateCorrect = false; - savedPowerStates[i] = tempPowerStates[i]; + savedBrightnessStates_[i] = tempPowerStates[i]; } } From 2977ebb0d5dff6311f5b5907f39bc09120513f98 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Thu, 26 Oct 2023 11:47:05 -0400 Subject: [PATCH 35/91] small change to the initialize method --- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 83c5a1468..e28dc7864 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -54,7 +54,7 @@ int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) } ViChar resource[512] = ""; - if(serialNumber.compare("") || serialNumber.compare("DEFAULT")) + if(serialNumber.compare("") == 0 || serialNumber.compare("DEFAULT") == 0) { err = TL6WL_getRsrcName(NULL, 0, resource); if (err != 0) From 811894356c9d33272c9ad051a84d91770b22263b Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Thu, 26 Oct 2023 12:22:09 -0400 Subject: [PATCH 36/91] changes to mutex --- .../ThorlabsChrolisDeviceWrapper.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index e28dc7864..58937db01 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -193,6 +193,8 @@ int ThorlabsChrolisDeviceWrapper::GetShutterState(bool& open) int ThorlabsChrolisDeviceWrapper::GetLEDWavelengths(ViUInt16(&wavelengths)[6]) { + std::lock_guard lock(instanceMutex_); + if (!deviceConnected_) { for (int i = 0; i < 6; i++) @@ -340,7 +342,6 @@ int ThorlabsChrolisDeviceWrapper::GetLEDBrightnessStates(ViUInt16& led1Brightnes int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) { int err = DEVICE_OK; - //TODO add checks for device not being open here std::lock_guard lock(instanceMutex_); if (!open) { @@ -384,11 +385,12 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean sta { if (LED < numLEDs_ && LED >= 0) { + std::lock_guard lock(instanceMutex_); + if (!deviceConnected_) { return ERR_CHROLIS_NOT_AVAIL; } - std::lock_guard lock(instanceMutex_); int err = 0; savedEnabledStates_[LED] = state; @@ -416,11 +418,13 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean sta int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) { + std::lock_guard lock(instanceMutex_); + if (!deviceConnected_) { return ERR_CHROLIS_NOT_AVAIL; } - std::lock_guard lock(instanceMutex_); + int err = 0; for (int i = 0; i < numLEDs_; i++) { @@ -448,11 +452,13 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDBrightnessState(int LED, ViUInt16 { if (LED < 6 && LED >= 0) { + std::lock_guard lock(instanceMutex_); + if (!deviceConnected_) { return ERR_CHROLIS_NOT_AVAIL; } - std::lock_guard lock(instanceMutex_); + int err = 0; savedBrightnessStates_[LED] = state; err = TL6WL_setLED_HeadBrightness(deviceHandle_, savedBrightnessStates_[0], savedBrightnessStates_[1], savedBrightnessStates_[2], @@ -476,11 +482,13 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDBrightnessState(int LED, ViUInt16 int ThorlabsChrolisDeviceWrapper::SetLEDBrightnessStates(ViUInt16 states[6]) { + std::lock_guard lock(instanceMutex_); + if (!deviceConnected_) { return ERR_CHROLIS_NOT_AVAIL; } - std::lock_guard lock(instanceMutex_); + int i; for (i = 0; i < numLEDs_; i++) { From 0255610efd8c7ecce2dd09004a6a36d850568d6a Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Thu, 2 Nov 2023 09:07:50 -0400 Subject: [PATCH 37/91] Updates for error messages --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 260 ++++++++---------- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 38 ++- .../ThorlabsChrolisDeviceWrapper.cpp | 3 +- 3 files changed, 153 insertions(+), 148 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 0ea564d9f..9ac00d487 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -38,35 +38,13 @@ MODULE_API void DeleteDevice(MM::Device* device) { } //Hub Methods ChrolisHub::ChrolisHub() : - initialized_(false), - busy_(false), threadRunning_(false), deviceStatusMessage_("No Error") { - //Custom Errors - SetErrorText(ERR_HUB_NOT_AVAILABLE, "Hub is not available"); - SetErrorText(ERR_CHROLIS_NOT_AVAIL, "CHROLIS Device is not available"); - SetErrorText(ERR_IMPROPER_SET, "Error setting property value. Value will be reset"); - SetErrorText(ERR_PARAM_NOT_VALID, "Value passed to property was out of bounds."); - SetErrorText(ERR_NO_AVAIL_DEVICES, "No available devices were found on the system."); - - //VISA Errors - SetErrorText(ERR_INSUF_INFO, "Insufficient location information of the device or the resource is not present on the system"); - SetErrorText(ERR_UNKOWN_HW_STATE, "Unknown Hardware State"); - SetErrorText(ERR_VAL_OVERFLOW, "Parameter Value Overflow"); - - - //CHROLIS Device Specific Errors. Located in TL6WL.h - SetErrorText(INSTR_RUNTIME_ERROR, "CHROLIS Instrument Runtime Error"); - SetErrorText(INSTR_REM_INTER_ERROR, "CHROLIS Instrument Internal Error"); - SetErrorText(INSTR_AUTHENTICATION_ERROR, "CHROLIS Instrument Authentication Error"); - SetErrorText(INSTR_PARAM_ERROR, "CHROLIS Invalid Parameter Error"); - SetErrorText(INSTR_HW_ERROR, "CHROLIS Instrument Hardware Error. Please verify that no hardware faults are present."); - SetErrorText(INSTR_PARAM_CHNG_ERROR, "CHROLIS Instrument Parameter Error"); - SetErrorText(INSTR_INTERNAL_TX_ERR, "CHROLIS Instrument Internal Command Sending Error"); - SetErrorText(INSTR_INTERNAL_RX_ERR, "CHROLIS Instrument Internal Command Receiving Error"); - SetErrorText(INSTR_INVAL_MODE_ERR, "CHROLIS Instrument Invalid Mode Error"); - SetErrorText(INSTR_SERVICE_ERR, "CHROLIS Instrument Service Error"); + for (const auto& errMessage : ErrorMessages()) + { + SetErrorText(errMessage.first, errMessage.second.c_str()); + } chrolisDeviceInstance_ = new ThorlabsChrolisDeviceWrapper(); atomic_init(¤tDeviceStatusCode_, 0); @@ -102,72 +80,68 @@ int ChrolisHub::DetectInstalledDevices() return DEVICE_OK; } -int ChrolisHub::Initialize() +int ChrolisHub::Initialize() // only gets called once { - if (!initialized_) - { - char buf[MM::MaxStrLength]; - int ret = GetProperty("Serial Number", buf); + char buf[MM::MaxStrLength]; + int ret = GetProperty("Serial Number", buf); - auto err = static_cast(chrolisDeviceInstance_)->InitializeDevice(buf); - if (err != 0) - { - LogMessage("Error in CHROLIS Initialization"); - return err; - } - - ViChar sNum[TL6WL_LONG_STRING_SIZE]; - static_cast(chrolisDeviceInstance_)->GetSerialNumber(sNum); - err = CreateStringProperty("Device Serial Number", sNum, true); - if (err != 0) - { - LogMessage("Error with property set in hub initialize"); - return DEVICE_ERR; - } + auto err = static_cast(chrolisDeviceInstance_)->InitializeDevice(buf); + if (err != 0) + { + LogMessage("Error in CHROLIS Initialization"); + return err; + } - ViChar manfName[TL6WL_LONG_STRING_SIZE]; - static_cast(chrolisDeviceInstance_)->GetManufacturerName(manfName); - err = CreateStringProperty("Manufacturer Name", manfName, true); - if (err != 0) - { - LogMessage("Error with property set in hub initialize"); - return DEVICE_ERR; - } + ViChar sNum[TL6WL_LONG_STRING_SIZE]; + static_cast(chrolisDeviceInstance_)->GetSerialNumber(sNum); + err = CreateStringProperty("Device Serial Number", sNum, true); + if (err != 0) + { + LogMessage("Error with property set in hub initialize"); + return DEVICE_ERR; + } - std::string wavelengthList = ""; - ViUInt16 wavelengths[6]; - err = static_cast(chrolisDeviceInstance_)->GetLEDWavelengths(wavelengths); - if (err != 0) - { - LogMessage("Unable to get wavelengths from device"); - return err; - } - for (int i = 0; i < 6; i ++) - { - wavelengthList += std::to_string(wavelengths[i]); - if (i != 5) - { - wavelengthList += ", "; - } - } - err = CreateStringProperty("Available Wavelengths", wavelengthList.c_str(), true); - if (err != 0) - { - LogMessage("Error with property set in hub initialize"); - return DEVICE_ERR; - } + ViChar manfName[TL6WL_LONG_STRING_SIZE]; + static_cast(chrolisDeviceInstance_)->GetManufacturerName(manfName); + err = CreateStringProperty("Manufacturer Name", manfName, true); + if (err != 0) + { + LogMessage("Error with property set in hub initialize"); + return DEVICE_ERR; + } - err = CreateStringProperty("Device Status", deviceStatusMessage_.c_str(), true); - if (err != 0) + std::string wavelengthList = ""; + ViUInt16 wavelengths[6]; + err = static_cast(chrolisDeviceInstance_)->GetLEDWavelengths(wavelengths); + if (err != 0) + { + LogMessage("Unable to get wavelengths from device"); + return err; + } + for (int i = 0; i < 6; i++) + { + wavelengthList += std::to_string(wavelengths[i]); + if (i != 5) { - LogMessage("Error with property set in hub initialize"); - return DEVICE_ERR; + wavelengthList += ", "; } + } + err = CreateStringProperty("Available Wavelengths", wavelengthList.c_str(), true); + if (err != 0) + { + LogMessage("Error with property set in hub initialize"); + return DEVICE_ERR; + } - threadRunning_.store(true); - updateThread_ = std::thread(&ChrolisHub::StatusChangedPollingThread, this); - initialized_ = true; + err = CreateStringProperty("Device Status", deviceStatusMessage_.c_str(), true); + if (err != 0) + { + LogMessage("Error with property set in hub initialize"); + return DEVICE_ERR; } + + threadRunning_.store(true); + updateThread_ = std::thread(&ChrolisHub::StatusChangedPollingThread, this); return DEVICE_OK; } @@ -179,7 +153,7 @@ int ChrolisHub::Shutdown() updateThread_.join(); } - if (initialized_ || static_cast(chrolisDeviceInstance_)->IsDeviceConnected()) + if (static_cast(chrolisDeviceInstance_)->IsDeviceConnected()) { auto err = static_cast(chrolisDeviceInstance_)->ShutdownDevice(); if (err != 0) @@ -187,7 +161,6 @@ int ChrolisHub::Shutdown() LogMessage("Error shutting down device"); return DEVICE_ERR; } - initialized_ = false; delete chrolisDeviceInstance_; } return DEVICE_OK; @@ -203,11 +176,6 @@ bool ChrolisHub::Busy() return false; } -bool ChrolisHub::IsInitialized() -{ - return initialized_; -} - void* ChrolisHub::GetChrolisDeviceInstance() { return chrolisDeviceInstance_; @@ -215,47 +183,36 @@ void* ChrolisHub::GetChrolisDeviceInstance() void ChrolisHub::StatusChangedPollingThread() { - bool statusChangedFlag = false; ViUInt32 tempStatus = 0; - std::string message = ""; + std::string message; ViBoolean tempEnableStates[6]; while (threadRunning_.load()) { - ChrolisHub* pHub = static_cast(GetParentHub()); - if (!pHub || !pHub->IsInitialized()) - { - LogMessage("Hub not available"); - threadRunning_.store(false); - continue; - } - - ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(GetChrolisDeviceInstance()); if (wrapperInstance->IsDeviceConnected()) { - message = ""; + message.clear(); auto err = wrapperInstance->GetDeviceStatus(tempStatus); if (err != 0) { LogMessage("Error Getting Status"); threadRunning_.store(false); - continue; - } - if (currentDeviceStatusCode_.load() != tempStatus) - { - statusChangedFlag = true; + return; } + const auto curStatus = currentDeviceStatusCode_.load(); + const bool statusChanged = curStatus != tempStatus; currentDeviceStatusCode_.store(tempStatus); - if (currentDeviceStatusCode_.load() == 0) + if (curStatus == 0) { message += "No Error"; } else { - if ((currentDeviceStatusCode_.load() & (1 << 0)) >= 1) + if ((curStatus & (1 << 0)) >= 1) { message += "Box is Open"; } - if ((currentDeviceStatusCode_.load() & (1 << 1)) >= 1) + if ((curStatus & (1 << 1)) >= 1) { if (message.length() > 0) { @@ -263,7 +220,7 @@ void ChrolisHub::StatusChangedPollingThread() } message += "LLG not Connected"; } - if ((currentDeviceStatusCode_.load() & (1 << 2)) >= 1) + if ((curStatus & (1 << 2)) >= 1) { if (message.length() > 0) { @@ -271,7 +228,7 @@ void ChrolisHub::StatusChangedPollingThread() } message += "Interlock is Open"; } - if ((currentDeviceStatusCode_.load() & (1 << 3)) >= 1) + if ((curStatus & (1 << 3)) >= 1) { if (message.length() > 0) { @@ -279,7 +236,7 @@ void ChrolisHub::StatusChangedPollingThread() } message += "Using Default Adjustment"; } - if ((currentDeviceStatusCode_.load() & (1 << 4)) >= 1) + if ((curStatus & (1 << 4)) >= 1) { if (message.length() > 0) { @@ -287,7 +244,7 @@ void ChrolisHub::StatusChangedPollingThread() } message += "Box Overheated"; } - if ((currentDeviceStatusCode_.load() & (1 << 5)) >= 1) + if ((curStatus & (1 << 5)) >= 1) { if (message.length() > 0) { @@ -295,7 +252,7 @@ void ChrolisHub::StatusChangedPollingThread() } message += "LED Overheated"; } - if ((currentDeviceStatusCode_.load() & (1 << 6)) >= 1) + if ((curStatus & (1 << 6)) >= 1) { if (message.length() > 0) { @@ -308,9 +265,9 @@ void ChrolisHub::StatusChangedPollingThread() message = "Unknown Status"; } } - if (statusChangedFlag) + if (statusChanged) { - if (currentDeviceStatusCode_.load() != 0) + if (curStatus != 0) { wrapperInstance->VerifyLEDEnableStatesWithLock(); if (wrapperInstance->GetLEDEnableStates(tempEnableStates[0], @@ -322,36 +279,35 @@ void ChrolisHub::StatusChangedPollingThread() { std::ostringstream os; os << tempEnableStates[0]; - pHub->GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 1", os.str().c_str()); + GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 1", os.str().c_str()); os.clear(); os << tempEnableStates[1]; - pHub->GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 2", os.str().c_str()); + GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 2", os.str().c_str()); os.clear(); os << tempEnableStates[2]; - pHub->GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 3", os.str().c_str()); + GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 3", os.str().c_str()); os.clear(); os << tempEnableStates[3]; - pHub->GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 4", os.str().c_str()); + GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 4", os.str().c_str()); os.clear(); os << tempEnableStates[4]; - pHub->GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 5", os.str().c_str()); + GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 5", os.str().c_str()); os.clear(); os << tempEnableStates[5]; - pHub->GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 6", os.str().c_str()); + GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 6", os.str().c_str()); os.clear(); os << ((static_cast(tempEnableStates[0]) << 0) | (static_cast(tempEnableStates[1]) << 1) | (static_cast(tempEnableStates[2]) << 2) | (static_cast(tempEnableStates[3]) << 3) | (static_cast(tempEnableStates[4]) << 4 | (static_cast(tempEnableStates[5]) << 5))); - pHub->GetDevice(CHROLIS_STATE_NAME)->SetProperty("State", os.str().c_str()); + GetDevice(CHROLIS_STATE_NAME)->SetProperty("State", os.str().c_str()); } } - statusChangedFlag = false; } OnPropertyChanged("Device Status", message.c_str()); } @@ -359,9 +315,23 @@ void ChrolisHub::StatusChangedPollingThread() } } +void ChrolisHub::SetShutterCallback(std::function function) +{ + shutterCallback_ = function; +} + +void ChrolisHub::SetStateCallback(std::function function) +{ + stateCallback_ = function; +} + //Chrolis Shutter Methods ChrolisShutter::ChrolisShutter() { + for (const auto& errMessage : ErrorMessages()) + { + SetErrorText(errMessage.first, errMessage.second.c_str()); + } InitializeDefaultErrorMessages(); } @@ -372,7 +342,10 @@ int ChrolisShutter::Initialize() { } else + { LogMessage("No Hub"); + return ERR_HUB_NOT_AVAILABLE; + } ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); if (wrapperInstance->IsDeviceConnected()) @@ -385,11 +358,20 @@ int ChrolisShutter::Initialize() } } + pHub->SetShutterCallback([this](int ledNum, int state) + { + }); + return DEVICE_OK; } int ChrolisShutter::Shutdown() { + ChrolisHub* pHub = static_cast(GetParentHub()); + if (pHub) + { + pHub->SetShutterCallback([](int , int) {}); + } return DEVICE_OK; } @@ -406,7 +388,7 @@ bool ChrolisShutter::Busy() int ChrolisShutter::SetOpen(bool open) { ChrolisHub* pHub = static_cast(GetParentHub()); - if (!pHub || !pHub->IsInitialized()) + if (!pHub) { LogMessage("Hub not available"); return ERR_HUB_NOT_AVAILABLE; @@ -429,8 +411,8 @@ int ChrolisShutter::SetOpen(bool open) int ChrolisShutter::GetOpen(bool& open) { - ChrolisHub* pHub = static_cast(GetParentHub()); - if (!pHub || !pHub->IsInitialized()) + ChrolisHub* pHub = static_cast(GetParentHub()); + if (!pHub) { LogMessage("Hub not available"); return ERR_HUB_NOT_AVAILABLE; @@ -452,9 +434,11 @@ ChrolisStateDevice::ChrolisStateDevice() : led1Brightness_(0), led2Brightness_(0), led3Brightness_(0), led4Brightness_(0), led5Brightness_(0), led6Brightness_(0), led1State_(false), led2State_(false), led3State_(false), led4State_(false), led5State_(false), led6State_(false) { + for (const auto& errMessage : ErrorMessages()) + { + SetErrorText(errMessage.first, errMessage.second.c_str()); + } InitializeDefaultErrorMessages(); - //SetErrorText(ERR_UNKNOWN_POSITION, "Requested position not available in this device"); - //EnableDelay(); // signals that the delay setting will be used } int ChrolisStateDevice::Initialize() @@ -641,7 +625,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) if (eAct == MM::BeforeGet) { ChrolisHub* pHub = static_cast(GetParentHub()); - if (!pHub || !pHub->IsInitialized()) + if (!pHub) { LogMessage("Hub not available"); } @@ -669,7 +653,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) //Get the current instances for hub and chrolis //In the event of error do not set the property. Set old value. Updated values will be pulled from getters if possible ChrolisHub* pHub = static_cast(GetParentHub()); - if (!pHub || !pHub->IsInitialized()) + if (!pHub) { LogMessage("Hub not available"); os << currentLEDState; @@ -740,7 +724,7 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT ViPBoolean ledBeingControlled; int numFromName = -1; std::string searchString = pProp->GetName(); - std::regex regexp("[-+]?([0-9]*\.[0-9]+|[0-9]+)"); + std::regex regexp(R"([-+]?([0-9]*\.[0-9]+|[0-9]+))"); std::smatch sm; std::regex_search(searchString, sm, regexp); @@ -788,7 +772,7 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT if (eAct == MM::BeforeGet) { ChrolisHub* pHub = static_cast(GetParentHub()); - if (!pHub || !pHub->IsInitialized()) + if (!pHub) { LogMessage("Hub not available"); } @@ -810,7 +794,7 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT std::ostringstream os; ChrolisHub* pHub = static_cast(GetParentHub()); - if (!pHub || !pHub->IsInitialized()) + if (!pHub) { LogMessage("Hub not available"); os << *ledBeingControlled; @@ -850,7 +834,7 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA ViPUInt16 ledBeingControlled; int numFromName = -1; std::string searchString = pProp->GetName(); - std::regex regexp("[-+]?([0-9]*\.[0-9]+|[0-9]+)"); + std::regex regexp(R"([-+]?([0-9]*\.[0-9]+|[0-9]+))"); std::smatch sm; std::regex_search(searchString, sm, regexp); @@ -898,7 +882,7 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA if (eAct == MM::BeforeGet) { ChrolisHub* pHub = static_cast(GetParentHub()); - if (!pHub || !pHub->IsInitialized()) + if (!pHub) { LogMessage("Hub not available"); } @@ -920,7 +904,7 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA std::ostringstream os; ChrolisHub* pHub = static_cast(GetParentHub()); - if (!pHub || !pHub->IsInitialized()) + if (!pHub) { LogMessage("Hub not available"); os << *ledBeingControlled; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 223e5412a..f9f8b721d 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -5,6 +5,7 @@ #include #include #include "DeviceBase.h" +#include #define CHROLIS_HUB_NAME "CHROLIS" #define CHROLIS_SHUTTER_NAME "CHROLIS_Shutter" @@ -29,6 +30,30 @@ #define ERR_UNKOWN_HW_STATE -1073676421 #define ERR_VAL_OVERFLOW -1073481985 +static std::map ErrorMessages() +{ + return { + {ERR_HUB_NOT_AVAILABLE, "Hub is not available"}, + {ERR_CHROLIS_NOT_AVAIL, "CHROLIS Device is not available"}, + {ERR_IMPROPER_SET, "Error setting property value. Value will be reset"}, + {ERR_PARAM_NOT_VALID, "Value passed to property was out of bounds."}, + {ERR_NO_AVAIL_DEVICES, "No available devices were found on the system."}, + {ERR_INSUF_INFO, "Insufficient location information of the device or the resource is not present on the system"}, + {ERR_UNKOWN_HW_STATE, "Unknown Hardware State"}, + {ERR_VAL_OVERFLOW, "Parameter Value Overflow"}, + {INSTR_RUNTIME_ERROR, "CHROLIS Instrument Runtime Error"}, + {INSTR_REM_INTER_ERROR, "CHROLIS Instrument Internal Error"}, + {INSTR_AUTHENTICATION_ERROR, "CHROLIS Instrument Authentication Error"}, + {INSTR_PARAM_ERROR, "CHROLIS Invalid Parameter Error"}, + {INSTR_INTERNAL_TX_ERR, "CHROLIS Instrument Internal Command Sending Error"}, + {INSTR_INTERNAL_RX_ERR, "CHROLIS Instrument Internal Command Receiving Error"}, + {INSTR_INVAL_MODE_ERR, "CHROLIS Instrument Invalid Mode Error"}, + {INSTR_SERVICE_ERR, "CHROLIS Instrument Service Error"} + }; +} + +// TODO: add mutex + class ChrolisHub : public HubBase { public: @@ -43,19 +68,19 @@ class ChrolisHub : public HubBase // HUB api int DetectInstalledDevices(); - bool IsInitialized(); void* GetChrolisDeviceInstance(); void StatusChangedPollingThread(); - + void SetShutterCallback(std::function); + void SetStateCallback(std::function); private: void* chrolisDeviceInstance_; - bool initialized_; - bool busy_; std::atomic_bool threadRunning_; std::thread updateThread_; std::atomic_uint32_t currentDeviceStatusCode_; std::string deviceStatusMessage_; + std::function shutterCallback_; + std::function stateCallback_; }; class ChrolisShutter : public CShutterBase //CRTP @@ -65,18 +90,13 @@ class ChrolisShutter : public CShutterBase //CRTP ~ChrolisShutter() {} int Initialize(); - int Shutdown(); - void GetName(char* name)const; - bool Busy(); // Shutter API int SetOpen(bool open = true); - int GetOpen(bool& open); - int Fire(double /*deltaT*/) { return DEVICE_UNSUPPORTED_COMMAND; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 58937db01..8962264c9 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -137,6 +137,7 @@ bool ThorlabsChrolisDeviceWrapper::IsDeviceConnected() int ThorlabsChrolisDeviceWrapper::GetSerialNumber(ViChar* serialNumber) { + std::lock_guard lock(instanceMutex_); if (deviceConnected_) { strcpy(serialNumber, serialNumber_); @@ -150,6 +151,7 @@ int ThorlabsChrolisDeviceWrapper::GetSerialNumber(ViChar* serialNumber) int ThorlabsChrolisDeviceWrapper::GetManufacturerName(ViChar* manfName) { + std::lock_guard lock(instanceMutex_); if (deviceConnected_) { strcpy(manfName, manufacturerName_); @@ -164,7 +166,6 @@ int ThorlabsChrolisDeviceWrapper::GetManufacturerName(ViChar* manfName) int ThorlabsChrolisDeviceWrapper::GetDeviceStatus(ViUInt32& status) { std::lock_guard lock(instanceMutex_); - if (!deviceConnected_) { status = 0; From bb478291c91146b7b1cf9c256c7f405bc072111a Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Thu, 2 Nov 2023 09:28:29 -0400 Subject: [PATCH 38/91] Updated the chrolisDeviceInstance_ and getter --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 24 +++++++++---------- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 5 ++-- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 9ac00d487..2d0ead676 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -176,7 +176,7 @@ bool ChrolisHub::Busy() return false; } -void* ChrolisHub::GetChrolisDeviceInstance() +ThorlabsChrolisDeviceWrapper* ChrolisHub::GetChrolisDeviceInstance() { return chrolisDeviceInstance_; } @@ -188,7 +188,7 @@ void ChrolisHub::StatusChangedPollingThread() ViBoolean tempEnableStates[6]; while (threadRunning_.load()) { - ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(GetChrolisDeviceInstance()); + ThorlabsChrolisDeviceWrapper* wrapperInstance = GetChrolisDeviceInstance(); if (wrapperInstance->IsDeviceConnected()) { message.clear(); @@ -347,7 +347,7 @@ int ChrolisShutter::Initialize() return ERR_HUB_NOT_AVAILABLE; } - ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); if (wrapperInstance->IsDeviceConnected()) { auto err = wrapperInstance->SetShutterState(false); @@ -393,7 +393,7 @@ int ChrolisShutter::SetOpen(bool open) LogMessage("Hub not available"); return ERR_HUB_NOT_AVAILABLE; } - ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); @@ -417,7 +417,7 @@ int ChrolisShutter::GetOpen(bool& open) LogMessage("Hub not available"); return ERR_HUB_NOT_AVAILABLE; } - ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); @@ -462,7 +462,7 @@ int ChrolisStateDevice::Initialize() } int err; - ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); uint32_t tmpLedState = 0; if (wrapperInstance->IsDeviceConnected()) { @@ -629,7 +629,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) { LogMessage("Hub not available"); } - ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); @@ -660,7 +660,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_HUB_NOT_AVAILABLE; } - ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); @@ -776,7 +776,7 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT { LogMessage("Hub not available"); } - ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); @@ -801,7 +801,7 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_HUB_NOT_AVAILABLE; } - ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); @@ -886,7 +886,7 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA { LogMessage("Hub not available"); } - ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); @@ -911,7 +911,7 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_HUB_NOT_AVAILABLE; } - ThorlabsChrolisDeviceWrapper* wrapperInstance = static_cast(pHub->GetChrolisDeviceInstance()); + ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); if (!wrapperInstance->IsDeviceConnected()) { LogMessage("CHROLIS not available"); diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index f9f8b721d..500072437 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -53,6 +53,7 @@ static std::map ErrorMessages() } // TODO: add mutex +class ThorlabsChrolisDeviceWrapper; class ChrolisHub : public HubBase { @@ -68,13 +69,13 @@ class ChrolisHub : public HubBase // HUB api int DetectInstalledDevices(); - void* GetChrolisDeviceInstance(); + ThorlabsChrolisDeviceWrapper* GetChrolisDeviceInstance(); void StatusChangedPollingThread(); void SetShutterCallback(std::function); void SetStateCallback(std::function); private: - void* chrolisDeviceInstance_; + ThorlabsChrolisDeviceWrapper* chrolisDeviceInstance_; std::atomic_bool threadRunning_; std::thread updateThread_; std::atomic_uint32_t currentDeviceStatusCode_; From 9a35bf8a60f54a651933f3ee0570a2603f100c6c Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Thu, 2 Nov 2023 10:22:25 -0400 Subject: [PATCH 39/91] code cleanup --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 11 ++-- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 52 +++++++++---------- .../ThorlabsChrolisDeviceWrapper.cpp | 8 +-- 3 files changed, 30 insertions(+), 41 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 2d0ead676..1c5991790 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -37,9 +37,7 @@ MODULE_API void DeleteDevice(MM::Device* device) { delete device; } //Hub Methods -ChrolisHub::ChrolisHub() : - threadRunning_(false), - deviceStatusMessage_("No Error") +ChrolisHub::ChrolisHub() { for (const auto& errMessage : ErrorMessages()) { @@ -47,8 +45,8 @@ ChrolisHub::ChrolisHub() : } chrolisDeviceInstance_ = new ThorlabsChrolisDeviceWrapper(); - atomic_init(¤tDeviceStatusCode_, 0); atomic_init(&threadRunning_, false); + atomic_init(¤tDeviceStatusCode_, 0); std::vector serialNumbers; static_cast(chrolisDeviceInstance_)->GetAvailableSerialNumbers(serialNumbers); @@ -429,10 +427,7 @@ int ChrolisShutter::GetOpen(bool& open) //Chrolis State Device Methods -ChrolisStateDevice::ChrolisStateDevice() : - numPos_(6), ledMaxBrightness_(1000), ledMinBrightness_(0), - led1Brightness_(0), led2Brightness_(0), led3Brightness_(0), led4Brightness_(0), led5Brightness_(0), led6Brightness_(0), - led1State_(false), led2State_(false), led3State_(false), led4State_(false), led5State_(false), led6State_(false) +ChrolisStateDevice::ChrolisStateDevice() { for (const auto& errMessage : ErrorMessages()) { diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 500072437..be0f0c8a7 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -79,7 +79,7 @@ class ChrolisHub : public HubBase std::atomic_bool threadRunning_; std::thread updateThread_; std::atomic_uint32_t currentDeviceStatusCode_; - std::string deviceStatusMessage_; + std::string deviceStatusMessage_ = "No Error"; std::function shutterCallback_; std::function stateCallback_; }; @@ -129,24 +129,24 @@ class ChrolisStateDevice : public CStateDeviceBase int OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct); private: - long numPos_; - - ViUInt16 led1Brightness_; - ViUInt16 led2Brightness_; - ViUInt16 led3Brightness_; - ViUInt16 led4Brightness_; - ViUInt16 led5Brightness_; - ViUInt16 led6Brightness_; - - ViBoolean led1State_; - ViBoolean led2State_; - ViBoolean led3State_; - ViBoolean led4State_; - ViBoolean led5State_; - ViBoolean led6State_; - - ViInt16 ledMaxBrightness_; - ViInt16 ledMinBrightness_; + long numPos_= 6; + + ViUInt16 led1Brightness_ = 0; + ViUInt16 led2Brightness_ = 0; + ViUInt16 led3Brightness_ = 0; + ViUInt16 led4Brightness_ = 0; + ViUInt16 led5Brightness_ = 0; + ViUInt16 led6Brightness_ = 0; + + ViBoolean led1State_ = false; + ViBoolean led2State_ = false; + ViBoolean led3State_ = false; + ViBoolean led4State_ = false; + ViBoolean led5State_ = false; + ViBoolean led6State_ = false; + + ViInt16 ledMaxBrightness_ = 1000; + ViInt16 ledMinBrightness_ = 0; }; //Wrapper for the basic functions used in this device adapter @@ -181,16 +181,16 @@ class ThorlabsChrolisDeviceWrapper bool VerifyLEDEnableStatesWithLock(); private: - int numLEDs_; + int numLEDs_ = 6; std::vector serialNumberList_; std::mutex instanceMutex_; - bool deviceConnected_; + bool deviceConnected_ = false; ViSession deviceHandle_; - ViBoolean deviceInUse_; //only used by the chrolis API - ViChar deviceName_[TL6WL_LONG_STRING_SIZE]; - ViChar serialNumber_[TL6WL_LONG_STRING_SIZE]; - ViChar manufacturerName_[TL6WL_LONG_STRING_SIZE]; - bool masterSwitchState_; + ViBoolean deviceInUse_ = false; //only used by the chrolis API + ViChar deviceName_[TL6WL_LONG_STRING_SIZE] = ""; + ViChar serialNumber_[TL6WL_LONG_STRING_SIZE] = ""; + ViChar manufacturerName_[TL6WL_LONG_STRING_SIZE] = ""; + bool masterSwitchState_ = false; ViBoolean savedEnabledStates_[6]{false,false,false,false,false,false}; ViUInt16 savedBrightnessStates_[6]{0,0,0,0,0,0}; ViUInt16 ledWavelengths_[6]{0,0,0,0,0,0}; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 8962264c9..6a11986c9 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -2,13 +2,7 @@ #include ThorlabsChrolisDeviceWrapper::ThorlabsChrolisDeviceWrapper() -{ - deviceInUse_ = false; - deviceConnected_ = false; - masterSwitchState_ = false; - deviceHandle_ = -1; - numLEDs_ = 6; -} +{} ThorlabsChrolisDeviceWrapper::~ThorlabsChrolisDeviceWrapper() {} From 4e8fb6eb755b0e1542709b29fb01329e7e13cfd9 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Thu, 2 Nov 2023 10:42:22 -0400 Subject: [PATCH 40/91] Removed unused error codes --- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index be0f0c8a7..f36c2878f 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -12,15 +12,11 @@ #define CHROLIS_STATE_NAME "CHROLIS_LED_Control" //Custom Error Codes -#define ERR_UNKNOWN_MODE 102 // not currently used -#define ERR_UNKNOWN_LED_STATE 103// don't think this is used -#define ERR_HUB_NOT_AVAILABLE 104 -#define ERR_CHROLIS_NOT_AVAIL 105 -#define ERR_CHROLIS_SET 106 //don't think this is used -#define ERR_CHROLIS_GET 107 // don't think this is used -#define ERR_PARAM_NOT_VALID 108 -#define ERR_NO_AVAIL_DEVICES 109 -#define ERR_IMPROPER_SET 110 +#define ERR_HUB_NOT_AVAILABLE 101 +#define ERR_CHROLIS_NOT_AVAIL 102 +#define ERR_PARAM_NOT_VALID 103 +#define ERR_NO_AVAIL_DEVICES 104 +#define ERR_IMPROPER_SET 105 //CHROLIS Specific Error Codes #define ERR_HARDWARE_FAULT -1074001669 From 8937cc5abc5048a5bc4b7f7a540935fac6addf48 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Thu, 2 Nov 2023 12:54:03 -0400 Subject: [PATCH 41/91] Callback for LED state changes --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 78 ++++++++----- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 109 +++++++++--------- 2 files changed, 101 insertions(+), 86 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 1c5991790..2995e6207 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -275,35 +275,15 @@ void ChrolisHub::StatusChangedPollingThread() } else { - std::ostringstream os; - os << tempEnableStates[0]; - GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 1", os.str().c_str()); - - os.clear(); - os << tempEnableStates[1]; - GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 2", os.str().c_str()); - - os.clear(); - os << tempEnableStates[2]; - GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 3", os.str().c_str()); - - os.clear(); - os << tempEnableStates[3]; - GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 4", os.str().c_str()); - - os.clear(); - os << tempEnableStates[4]; - GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 5", os.str().c_str()); - - os.clear(); - os << tempEnableStates[5]; - GetDevice(CHROLIS_STATE_NAME)->SetProperty("LED Enable State 6", os.str().c_str()); - - os.clear(); - os << ((static_cast(tempEnableStates[0]) << 0) | (static_cast(tempEnableStates[1]) << 1) | (static_cast(tempEnableStates[2]) << 2) - | (static_cast(tempEnableStates[3]) << 3) | (static_cast(tempEnableStates[4]) << 4 | (static_cast(tempEnableStates[5]) << 5))); - GetDevice(CHROLIS_STATE_NAME)->SetProperty("State", os.str().c_str()); - + stateCallback_(0, ((static_cast(tempEnableStates[0]) << 0) | (static_cast(tempEnableStates[1]) << 1) | (static_cast(tempEnableStates[2]) << 2) + | (static_cast(tempEnableStates[3]) << 3) | (static_cast(tempEnableStates[4]) << 4 | (static_cast(tempEnableStates[5]) << 5)))); + + stateCallback_(1, tempEnableStates[0]); + stateCallback_(2, tempEnableStates[1]); + stateCallback_(3, tempEnableStates[2]); + stateCallback_(4, tempEnableStates[3]); + stateCallback_(5, tempEnableStates[4]); + stateCallback_(6, tempEnableStates[5]); } } } @@ -441,12 +421,46 @@ int ChrolisStateDevice::Initialize() ChrolisHub* pHub = static_cast(GetParentHub()); if (pHub) { + } else { LogMessage("Hub not available"); + return ERR_HUB_NOT_AVAILABLE; } + pHub->SetStateCallback([this](int ledNum, int state) + { + std::ostringstream os; + os << (ledNum == 0 ? state : (ViBoolean)state); + switch (ledNum) + { + case 0: + OnPropertyChanged("state", os.str().c_str()); + break; + case 1: + OnPropertyChanged("LED Enable State 1", os.str().c_str()); + break; + case 2: + OnPropertyChanged("LED Enable State 2", os.str().c_str()); + break; + case 3: + OnPropertyChanged("LED Enable State 3", os.str().c_str()); + break; + case 4: + OnPropertyChanged("LED Enable State 4", os.str().c_str()); + break; + case 5: + OnPropertyChanged("LED Enable State 5", os.str().c_str()); + break; + case 6: + OnPropertyChanged("LED Enable State 6", os.str().c_str()); + break; + default: + break; + } + }); + // create default positions and labels const int bufSize = 1024; char buf[bufSize]; @@ -456,7 +470,6 @@ int ChrolisStateDevice::Initialize() SetPositionLabel(i, buf); } int err; - ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); uint32_t tmpLedState = 0; if (wrapperInstance->IsDeviceConnected()) @@ -591,6 +604,11 @@ int ChrolisStateDevice::Initialize() int ChrolisStateDevice::Shutdown() { + ChrolisHub* pHub = static_cast(GetParentHub()); + if (pHub) + { + pHub->SetStateCallback([](int, int) {}); + } return DEVICE_OK; } diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index f36c2878f..02b04ec9b 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -48,8 +48,57 @@ static std::map ErrorMessages() }; } -// TODO: add mutex -class ThorlabsChrolisDeviceWrapper; +//Wrapper for the basic functions used in this device adapter +class ThorlabsChrolisDeviceWrapper +{ +public: + ThorlabsChrolisDeviceWrapper(); + ~ThorlabsChrolisDeviceWrapper(); + + int GetAvailableSerialNumbers(std::vector& serialNumbers); + int InitializeDevice(std::string serialNumber = ""); + int ShutdownDevice(); + bool IsDeviceConnected(); + int GetSerialNumber(ViChar* serialNumber); + int GetManufacturerName(ViChar* manfName); + int GetDeviceStatus(ViUInt32& status); + int GetLEDWavelengths(ViUInt16(&wavelengths)[6]); + int GetShutterState(bool& open); + int GetSingleLEDEnableState(int led, ViBoolean& state); + int GetLEDEnableStates(ViBoolean(&states)[6]); + int GetLEDEnableStates(ViBoolean& led1State, ViBoolean& led2State, ViBoolean& led3State, ViBoolean& led4State, ViBoolean& led5State, ViBoolean& led6State); + int GetSingleLEDBrightnessState(int led, ViUInt16& state); + int GetLEDBrightnessStates(ViUInt16(&states)[6]); + int GetLEDBrightnessStates(ViUInt16& led1Brightness, ViUInt16& led2Brightness, ViUInt16& led3Brightness, ViUInt16& led4Brightness, ViUInt16& led5Brightness, ViUInt16& led6Brightness); + + int SetShutterState(bool open); + int SetLEDEnableStates(ViBoolean states[6]); + int SetSingleLEDEnableState(int LED, ViBoolean state); + int SetLEDBrightnessStates(ViUInt16 states[6]); + int SetSingleLEDBrightnessState(int LED, ViUInt16 state); + + bool VerifyLEDEnableStatesWithLock(); + +private: + int numLEDs_ = 6; + std::vector serialNumberList_; + std::mutex instanceMutex_; + bool deviceConnected_ = false; + ViSession deviceHandle_; + ViBoolean deviceInUse_ = false; //only used by the chrolis API + ViChar deviceName_[TL6WL_LONG_STRING_SIZE] = ""; + ViChar serialNumber_[TL6WL_LONG_STRING_SIZE] = ""; + ViChar manufacturerName_[TL6WL_LONG_STRING_SIZE] = ""; + bool masterSwitchState_ = false; + ViBoolean savedEnabledStates_[6]{ false,false,false,false,false,false }; + ViUInt16 savedBrightnessStates_[6]{ 0,0,0,0,0,0 }; + ViUInt16 ledWavelengths_[6]{ 0,0,0,0,0,0 }; + + bool VerifyLEDStates(); + bool VerifyLEDPowerStates(); + bool VerifyLEDEnableStates(); + +}; class ChrolisHub : public HubBase { @@ -77,10 +126,10 @@ class ChrolisHub : public HubBase std::atomic_uint32_t currentDeviceStatusCode_; std::string deviceStatusMessage_ = "No Error"; std::function shutterCallback_; - std::function stateCallback_; + std::function stateCallback_; }; -class ChrolisShutter : public CShutterBase //CRTP +class ChrolisShutter : public CShutterBase { public: ChrolisShutter(); @@ -143,56 +192,4 @@ class ChrolisStateDevice : public CStateDeviceBase ViInt16 ledMaxBrightness_ = 1000; ViInt16 ledMinBrightness_ = 0; -}; - -//Wrapper for the basic functions used in this device adapter -class ThorlabsChrolisDeviceWrapper -{ -public: - ThorlabsChrolisDeviceWrapper(); - ~ThorlabsChrolisDeviceWrapper(); - - int GetAvailableSerialNumbers(std::vector &serialNumbers); - int InitializeDevice(std::string serialNumber = ""); - int ShutdownDevice(); - bool IsDeviceConnected(); - int GetSerialNumber(ViChar* serialNumber); - int GetManufacturerName(ViChar* manfName); - int GetDeviceStatus(ViUInt32& status); - int GetLEDWavelengths(ViUInt16(&wavelengths)[6]); - int GetShutterState(bool& open); - int GetSingleLEDEnableState(int led, ViBoolean& state); - int GetLEDEnableStates(ViBoolean(&states)[6]); - int GetLEDEnableStates(ViBoolean& led1State, ViBoolean& led2State, ViBoolean& led3State, ViBoolean& led4State, ViBoolean& led5State, ViBoolean& led6State); - int GetSingleLEDBrightnessState(int led, ViUInt16& state); - int GetLEDBrightnessStates(ViUInt16(&states)[6]); - int GetLEDBrightnessStates(ViUInt16 &led1Brightness, ViUInt16&led2Brightness, ViUInt16&led3Brightness, ViUInt16&led4Brightness, ViUInt16&led5Brightness, ViUInt16&led6Brightness); - - int SetShutterState(bool open); - int SetLEDEnableStates(ViBoolean states[6]); - int SetSingleLEDEnableState(int LED, ViBoolean state); - int SetLEDBrightnessStates(ViUInt16 states[6]); - int SetSingleLEDBrightnessState(int LED, ViUInt16 state); - - bool VerifyLEDEnableStatesWithLock(); - -private: - int numLEDs_ = 6; - std::vector serialNumberList_; - std::mutex instanceMutex_; - bool deviceConnected_ = false; - ViSession deviceHandle_; - ViBoolean deviceInUse_ = false; //only used by the chrolis API - ViChar deviceName_[TL6WL_LONG_STRING_SIZE] = ""; - ViChar serialNumber_[TL6WL_LONG_STRING_SIZE] = ""; - ViChar manufacturerName_[TL6WL_LONG_STRING_SIZE] = ""; - bool masterSwitchState_ = false; - ViBoolean savedEnabledStates_[6]{false,false,false,false,false,false}; - ViUInt16 savedBrightnessStates_[6]{0,0,0,0,0,0}; - ViUInt16 ledWavelengths_[6]{0,0,0,0,0,0}; - - bool VerifyLEDStates(); - bool VerifyLEDPowerStates(); - bool VerifyLEDEnableStates(); - }; \ No newline at end of file From 40fc2027523428ff9f1ecb2f2e0f77af4ae2a1a4 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Fri, 3 Nov 2023 09:42:03 -0400 Subject: [PATCH 42/91] Updated device instance to a class member --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 88 ++++++++----------- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 4 +- 2 files changed, 37 insertions(+), 55 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 2995e6207..f87c94236 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -44,12 +44,11 @@ ChrolisHub::ChrolisHub() SetErrorText(errMessage.first, errMessage.second.c_str()); } - chrolisDeviceInstance_ = new ThorlabsChrolisDeviceWrapper(); atomic_init(&threadRunning_, false); atomic_init(¤tDeviceStatusCode_, 0); std::vector serialNumbers; - static_cast(chrolisDeviceInstance_)->GetAvailableSerialNumbers(serialNumbers); + ChrolisDevice.GetAvailableSerialNumbers(serialNumbers); CreateStringProperty("Serial Number", "DEFAULT", false, 0, true); for (int i = 0; i < serialNumbers.size(); i++) @@ -83,7 +82,7 @@ int ChrolisHub::Initialize() // only gets called once char buf[MM::MaxStrLength]; int ret = GetProperty("Serial Number", buf); - auto err = static_cast(chrolisDeviceInstance_)->InitializeDevice(buf); + int err = ChrolisDevice.InitializeDevice(buf); if (err != 0) { LogMessage("Error in CHROLIS Initialization"); @@ -91,7 +90,7 @@ int ChrolisHub::Initialize() // only gets called once } ViChar sNum[TL6WL_LONG_STRING_SIZE]; - static_cast(chrolisDeviceInstance_)->GetSerialNumber(sNum); + ChrolisDevice.GetSerialNumber(sNum); err = CreateStringProperty("Device Serial Number", sNum, true); if (err != 0) { @@ -100,7 +99,7 @@ int ChrolisHub::Initialize() // only gets called once } ViChar manfName[TL6WL_LONG_STRING_SIZE]; - static_cast(chrolisDeviceInstance_)->GetManufacturerName(manfName); + ChrolisDevice.GetManufacturerName(manfName); err = CreateStringProperty("Manufacturer Name", manfName, true); if (err != 0) { @@ -110,7 +109,7 @@ int ChrolisHub::Initialize() // only gets called once std::string wavelengthList = ""; ViUInt16 wavelengths[6]; - err = static_cast(chrolisDeviceInstance_)->GetLEDWavelengths(wavelengths); + err = ChrolisDevice.GetLEDWavelengths(wavelengths); if (err != 0) { LogMessage("Unable to get wavelengths from device"); @@ -151,15 +150,14 @@ int ChrolisHub::Shutdown() updateThread_.join(); } - if (static_cast(chrolisDeviceInstance_)->IsDeviceConnected()) + if (ChrolisDevice.IsDeviceConnected()) { - auto err = static_cast(chrolisDeviceInstance_)->ShutdownDevice(); + auto err = ChrolisDevice.ShutdownDevice(); if (err != 0) { LogMessage("Error shutting down device"); return DEVICE_ERR; } - delete chrolisDeviceInstance_; } return DEVICE_OK; } @@ -174,11 +172,6 @@ bool ChrolisHub::Busy() return false; } -ThorlabsChrolisDeviceWrapper* ChrolisHub::GetChrolisDeviceInstance() -{ - return chrolisDeviceInstance_; -} - void ChrolisHub::StatusChangedPollingThread() { ViUInt32 tempStatus = 0; @@ -186,11 +179,10 @@ void ChrolisHub::StatusChangedPollingThread() ViBoolean tempEnableStates[6]; while (threadRunning_.load()) { - ThorlabsChrolisDeviceWrapper* wrapperInstance = GetChrolisDeviceInstance(); - if (wrapperInstance->IsDeviceConnected()) + if (ChrolisDevice.IsDeviceConnected()) { message.clear(); - auto err = wrapperInstance->GetDeviceStatus(tempStatus); + auto err = ChrolisDevice.GetDeviceStatus(tempStatus); if (err != 0) { LogMessage("Error Getting Status"); @@ -267,8 +259,8 @@ void ChrolisHub::StatusChangedPollingThread() { if (curStatus != 0) { - wrapperInstance->VerifyLEDEnableStatesWithLock(); - if (wrapperInstance->GetLEDEnableStates(tempEnableStates[0], + ChrolisDevice.VerifyLEDEnableStatesWithLock(); + if (ChrolisDevice.GetLEDEnableStates(tempEnableStates[0], tempEnableStates[1], tempEnableStates[2], tempEnableStates[3], tempEnableStates[4], tempEnableStates[5]) != 0) { LogMessage("Error getting info from chrolis"); @@ -325,10 +317,9 @@ int ChrolisShutter::Initialize() return ERR_HUB_NOT_AVAILABLE; } - ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); - if (wrapperInstance->IsDeviceConnected()) + if (pHub->ChrolisDevice.IsDeviceConnected()) { - auto err = wrapperInstance->SetShutterState(false); + auto err = pHub->ChrolisDevice.SetShutterState(false); //return error but reset if needed if (err != 0) { @@ -371,13 +362,12 @@ int ChrolisShutter::SetOpen(bool open) LogMessage("Hub not available"); return ERR_HUB_NOT_AVAILABLE; } - ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); - if (!wrapperInstance->IsDeviceConnected()) + if (!pHub->ChrolisDevice.IsDeviceConnected()) { LogMessage("CHROLIS not available"); return ERR_CHROLIS_NOT_AVAIL; } - auto err = wrapperInstance->SetShutterState(open); + auto err = pHub->ChrolisDevice.SetShutterState(open); if (err != 0) { LogMessage("Error setting shutter state"); @@ -395,13 +385,12 @@ int ChrolisShutter::GetOpen(bool& open) LogMessage("Hub not available"); return ERR_HUB_NOT_AVAILABLE; } - ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); - if (!wrapperInstance->IsDeviceConnected()) + if (!pHub->ChrolisDevice.IsDeviceConnected()) { LogMessage("CHROLIS not available"); return ERR_CHROLIS_NOT_AVAIL; } - wrapperInstance->GetShutterState(open); + pHub->ChrolisDevice.GetShutterState(open); return DEVICE_OK; } @@ -470,12 +459,11 @@ int ChrolisStateDevice::Initialize() SetPositionLabel(i, buf); } int err; - ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); uint32_t tmpLedState = 0; - if (wrapperInstance->IsDeviceConnected()) + if (pHub->ChrolisDevice.IsDeviceConnected()) { - err = wrapperInstance->GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_); - err = wrapperInstance->GetLEDBrightnessStates(led1Brightness_, led2Brightness_, led3Brightness_, led4Brightness_, led5Brightness_, led6Brightness_); + err = pHub->ChrolisDevice.GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_); + err = pHub->ChrolisDevice.GetLEDBrightnessStates(led1Brightness_, led2Brightness_, led3Brightness_, led4Brightness_, led5Brightness_, led6Brightness_); tmpLedState = ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5)); @@ -642,12 +630,11 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) { LogMessage("Hub not available"); } - ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); - if (!wrapperInstance->IsDeviceConnected()) + if (!pHub->ChrolisDevice.IsDeviceConnected()) { LogMessage("CHROLIS not available"); } - if (wrapperInstance->GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_) != 0) + if (pHub->ChrolisDevice.GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_) != 0) { LogMessage("Error getting info from chrolis"); } @@ -673,8 +660,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_HUB_NOT_AVAILABLE; } - ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); - if (!wrapperInstance->IsDeviceConnected()) + if (!pHub->ChrolisDevice.IsDeviceConnected()) { LogMessage("CHROLIS not available"); os << currentLEDState; @@ -702,7 +688,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) static_cast(val & (1 << 4)), static_cast(val & (1 << 5)) }; - int err = wrapperInstance->SetLEDEnableStates(newStates); + int err = pHub->ChrolisDevice.SetLEDEnableStates(newStates); if (err != 0) { //Do not set the property in the case of this error. Let the property change handle it. @@ -710,7 +696,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) LogMessage("Error Setting LED state"); if (err != ERR_CHROLIS_NOT_AVAIL) { - if (wrapperInstance->GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_) != 0) + if (pHub->ChrolisDevice.GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_) != 0) { LogMessage("Error getting info from chrolis"); } @@ -789,12 +775,11 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT { LogMessage("Hub not available"); } - ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); - if (!wrapperInstance->IsDeviceConnected()) + if (!pHub->ChrolisDevice.IsDeviceConnected()) { LogMessage("CHROLIS not available"); } - if (wrapperInstance->GetSingleLEDEnableState(numFromName-1, *ledBeingControlled) != 0) + if (pHub->ChrolisDevice.GetSingleLEDEnableState(numFromName-1, *ledBeingControlled) != 0) { LogMessage("Error getting info from chrolis"); } @@ -814,8 +799,7 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_HUB_NOT_AVAILABLE; } - ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); - if (!wrapperInstance->IsDeviceConnected()) + if (!pHub->ChrolisDevice.IsDeviceConnected()) { LogMessage("CHROLIS not available"); os << *ledBeingControlled; @@ -823,11 +807,11 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT return ERR_CHROLIS_NOT_AVAIL; } - int err = wrapperInstance->SetSingleLEDEnableState(numFromName-1, (ViBoolean)val); + int err = pHub->ChrolisDevice.SetSingleLEDEnableState(numFromName-1, (ViBoolean)val); if (err != 0) { LogMessage("Error Setting LED state"); - wrapperInstance->GetSingleLEDEnableState(numFromName - 1, *ledBeingControlled); + pHub->ChrolisDevice.GetSingleLEDEnableState(numFromName - 1, *ledBeingControlled); os << *ledBeingControlled; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return err; @@ -899,12 +883,11 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA { LogMessage("Hub not available"); } - ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); - if (!wrapperInstance->IsDeviceConnected()) + if (!pHub->ChrolisDevice.IsDeviceConnected()) { LogMessage("CHROLIS not available"); } - if (wrapperInstance->GetSingleLEDBrightnessState(numFromName - 1, *ledBeingControlled) != 0) + if (pHub->ChrolisDevice.GetSingleLEDBrightnessState(numFromName - 1, *ledBeingControlled) != 0) { LogMessage("Error getting info from chrolis"); } @@ -924,8 +907,7 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return ERR_HUB_NOT_AVAILABLE; } - ThorlabsChrolisDeviceWrapper* wrapperInstance = pHub->GetChrolisDeviceInstance(); - if (!wrapperInstance->IsDeviceConnected()) + if (!pHub->ChrolisDevice.IsDeviceConnected()) { LogMessage("CHROLIS not available"); os << *ledBeingControlled; @@ -933,11 +915,11 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA return ERR_CHROLIS_NOT_AVAIL; } - int err = wrapperInstance->SetSingleLEDBrightnessState(numFromName - 1, (ViUInt16)val); + int err = pHub->ChrolisDevice.SetSingleLEDBrightnessState(numFromName - 1, (ViUInt16)val); if (err != 0) { LogMessage("Error Setting LED state"); - wrapperInstance->GetSingleLEDBrightnessState(numFromName - 1, *ledBeingControlled); + pHub->ChrolisDevice.GetSingleLEDBrightnessState(numFromName - 1, *ledBeingControlled); os << *ledBeingControlled; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return err; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 02b04ec9b..0677194ac 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -106,6 +106,8 @@ class ChrolisHub : public HubBase ChrolisHub(); ~ChrolisHub() {} + ThorlabsChrolisDeviceWrapper ChrolisDevice; + int Initialize(); int Shutdown(); void GetName(char* pszName) const; @@ -114,13 +116,11 @@ class ChrolisHub : public HubBase // HUB api int DetectInstalledDevices(); - ThorlabsChrolisDeviceWrapper* GetChrolisDeviceInstance(); void StatusChangedPollingThread(); void SetShutterCallback(std::function); void SetStateCallback(std::function); private: - ThorlabsChrolisDeviceWrapper* chrolisDeviceInstance_; std::atomic_bool threadRunning_; std::thread updateThread_; std::atomic_uint32_t currentDeviceStatusCode_; From 108a98c94cdbc628f616976163a51bf09d9d7849 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Fri, 3 Nov 2023 10:44:18 -0400 Subject: [PATCH 43/91] cleanup --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 19 ++++++++----------- .../ThorlabsChrolisDeviceWrapper.cpp | 1 + 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index f87c94236..304b48076 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -77,7 +77,7 @@ int ChrolisHub::DetectInstalledDevices() return DEVICE_OK; } -int ChrolisHub::Initialize() // only gets called once +int ChrolisHub::Initialize() { char buf[MM::MaxStrLength]; int ret = GetProperty("Serial Number", buf); @@ -146,7 +146,7 @@ int ChrolisHub::Shutdown() { if (threadRunning_.load()) { - threadRunning_.store(false); // TODO make this atmoic or mutex + threadRunning_.store(false); updateThread_.join(); } @@ -308,10 +308,7 @@ ChrolisShutter::ChrolisShutter() int ChrolisShutter::Initialize() { ChrolisHub* pHub = static_cast(GetParentHub()); - if (pHub) - { - } - else + if (!pHub) { LogMessage("No Hub"); return ERR_HUB_NOT_AVAILABLE; @@ -329,6 +326,7 @@ int ChrolisShutter::Initialize() pHub->SetShutterCallback([this](int ledNum, int state) { + //Might not be needed }); return DEVICE_OK; @@ -408,11 +406,7 @@ ChrolisStateDevice::ChrolisStateDevice() int ChrolisStateDevice::Initialize() { ChrolisHub* pHub = static_cast(GetParentHub()); - if (pHub) - { - - } - else + if (!pHub) { LogMessage("Hub not available"); return ERR_HUB_NOT_AVAILABLE; @@ -629,6 +623,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) if (!pHub) { LogMessage("Hub not available"); + return ERR_HUB_NOT_AVAILABLE; } if (!pHub->ChrolisDevice.IsDeviceConnected()) { @@ -774,6 +769,7 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT if (!pHub) { LogMessage("Hub not available"); + return ERR_HUB_NOT_AVAILABLE; } if (!pHub->ChrolisDevice.IsDeviceConnected()) { @@ -882,6 +878,7 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA if (!pHub) { LogMessage("Hub not available"); + return ERR_HUB_NOT_AVAILABLE; } if (!pHub->ChrolisDevice.IsDeviceConnected()) { diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 6a11986c9..73c7f4b75 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -126,6 +126,7 @@ int ThorlabsChrolisDeviceWrapper::ShutdownDevice() bool ThorlabsChrolisDeviceWrapper::IsDeviceConnected() { + std::lock_guard lock(instanceMutex_); return deviceConnected_; } From 7f2582ee93b5cc13895cf78ad94daac35dab9178 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Mon, 20 Nov 2023 17:13:19 -0600 Subject: [PATCH 44/91] Make number of LEDs a constant And use more consistently. Also remove unnecessary zeroes from array initializers. --- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 8 ++-- .../ThorlabsChrolisDeviceWrapper.cpp | 44 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 0677194ac..81d36594c 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -80,7 +80,7 @@ class ThorlabsChrolisDeviceWrapper bool VerifyLEDEnableStatesWithLock(); private: - int numLEDs_ = 6; + static constexpr int NUM_LEDS = 6; std::vector serialNumberList_; std::mutex instanceMutex_; bool deviceConnected_ = false; @@ -90,9 +90,9 @@ class ThorlabsChrolisDeviceWrapper ViChar serialNumber_[TL6WL_LONG_STRING_SIZE] = ""; ViChar manufacturerName_[TL6WL_LONG_STRING_SIZE] = ""; bool masterSwitchState_ = false; - ViBoolean savedEnabledStates_[6]{ false,false,false,false,false,false }; - ViUInt16 savedBrightnessStates_[6]{ 0,0,0,0,0,0 }; - ViUInt16 ledWavelengths_[6]{ 0,0,0,0,0,0 }; + ViBoolean savedEnabledStates_[NUM_LEDS]{}; + ViUInt16 savedBrightnessStates_[NUM_LEDS]{}; + ViUInt16 ledWavelengths_[NUM_LEDS]{}; bool VerifyLEDStates(); bool VerifyLEDPowerStates(); diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 73c7f4b75..2f13799a1 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -95,7 +95,7 @@ int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) } deviceConnected_ = true; - for (int i = 0; i < numLEDs_; i++) + for (int i = 0; i < NUM_LEDS; i++) { err = TL6WL_readLED_HeadPeakWL(deviceHandle_, i+1, &ledWavelengths_[i]); if (err != 0) @@ -187,13 +187,13 @@ int ThorlabsChrolisDeviceWrapper::GetShutterState(bool& open) return DEVICE_OK; } -int ThorlabsChrolisDeviceWrapper::GetLEDWavelengths(ViUInt16(&wavelengths)[6]) +int ThorlabsChrolisDeviceWrapper::GetLEDWavelengths(ViUInt16(&wavelengths)[ThorlabsChrolisDeviceWrapper::NUM_LEDS]) { std::lock_guard lock(instanceMutex_); if (!deviceConnected_) { - for (int i = 0; i < 6; i++) + for (int i = 0; i < NUM_LEDS; i++) { wavelengths[i] = 0; } @@ -213,7 +213,7 @@ int ThorlabsChrolisDeviceWrapper::GetSingleLEDEnableState(int led, ViBoolean& st { std::lock_guard lock(instanceMutex_); - if (led < numLEDs_ && led >= 0) + if (led < NUM_LEDS && led >= 0) { if (!deviceConnected_) { @@ -235,13 +235,13 @@ int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean(&states)[6]) if (!deviceConnected_) { - for (int i = 0; i < 6; i++) + for (int i = 0; i < NUM_LEDS; i++) { states[i] = false; } return ERR_CHROLIS_NOT_AVAIL; } - for (int i = 0; i < 6; i++) + for (int i = 0; i < NUM_LEDS; i++) { states[i] = savedEnabledStates_[i]; } @@ -276,7 +276,7 @@ int ThorlabsChrolisDeviceWrapper::GetSingleLEDBrightnessState(int led, ViUInt16& { std::lock_guard lock(instanceMutex_); - if (led < numLEDs_ && led >= 0) + if (led < NUM_LEDS && led >= 0) { if (!deviceConnected_) { @@ -298,13 +298,13 @@ int ThorlabsChrolisDeviceWrapper::GetLEDBrightnessStates(ViUInt16(&states)[6]) if (!deviceConnected_) { - for (int i = 0; i < 6; i++) + for (int i = 0; i < NUM_LEDS; i++) { states[i] = 0; } return ERR_CHROLIS_NOT_AVAIL; } - for (int i = 0; i < 6; i++) + for (int i = 0; i < NUM_LEDS; i++) { states[i] = savedBrightnessStates_[i]; } @@ -341,14 +341,14 @@ int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) std::lock_guard lock(instanceMutex_); if (!open) { - ViBoolean tempEnableStates[6]; + ViBoolean tempEnableStates[NUM_LEDS]; err = TL6WL_setLED_HeadPowerStates(deviceHandle_, false, false, false, false, false, false); if (err != 0) { return err; } err = TL6WL_getLED_HeadPowerStates(deviceHandle_, &tempEnableStates[0], &tempEnableStates[1], &tempEnableStates[2], &tempEnableStates[3], &tempEnableStates[4], &tempEnableStates[5]); - for (int i = 0; i < numLEDs_; i++) + for (int i = 0; i < NUM_LEDS; i++) { if (tempEnableStates[i]) { @@ -379,7 +379,7 @@ int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean state) { - if (LED < numLEDs_ && LED >= 0) + if (LED < NUM_LEDS && LED >= 0) { std::lock_guard lock(instanceMutex_); @@ -422,7 +422,7 @@ int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) } int err = 0; - for (int i = 0; i < numLEDs_; i++) + for (int i = 0; i < NUM_LEDS; i++) { savedEnabledStates_[i] = states[i]; } @@ -446,7 +446,7 @@ int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) int ThorlabsChrolisDeviceWrapper::SetSingleLEDBrightnessState(int LED, ViUInt16 state) { - if (LED < 6 && LED >= 0) + if (LED < NUM_LEDS && LED >= 0) { std::lock_guard lock(instanceMutex_); @@ -486,7 +486,7 @@ int ThorlabsChrolisDeviceWrapper::SetLEDBrightnessStates(ViUInt16 states[6]) } int i; - for (i = 0; i < numLEDs_; i++) + for (i = 0; i < NUM_LEDS; i++) { savedBrightnessStates_[i] = states[i]; } @@ -521,13 +521,13 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDStates() } bool stateCorrect = true; - ViUInt16 tempPowerStates[6] = {0,0,0,0,0,0}; - ViBoolean tempEnableStates[6] = { false, false, false, false, false, false }; + ViUInt16 tempPowerStates[NUM_LEDS]{}; + ViBoolean tempEnableStates[NUM_LEDS]{}; TL6WL_getLED_HeadPowerStates(deviceHandle_, &tempEnableStates[0], &tempEnableStates[1], &tempEnableStates[2], &tempEnableStates[3], &tempEnableStates[4], &tempEnableStates[5]); TL6WL_getLED_HeadBrightness(deviceHandle_, &tempPowerStates[0], &tempPowerStates[1], &tempPowerStates[2], &tempPowerStates[3], &tempPowerStates[4], &tempPowerStates[5]); - for (int i = 0; i < numLEDs_; i++) + for (int i = 0; i < NUM_LEDS; i++) { if (tempEnableStates[i] != savedEnabledStates_[i] || tempPowerStates[i] != savedBrightnessStates_[i]) { @@ -548,11 +548,11 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDEnableStates() } bool stateCorrect = true; - ViBoolean tempEnableStates[6] = { false, false, false, false, false, false }; + ViBoolean tempEnableStates[NUM_LEDS]{}; TL6WL_getLED_HeadPowerStates(deviceHandle_, &tempEnableStates[0], &tempEnableStates[1], &tempEnableStates[2], &tempEnableStates[3], &tempEnableStates[4], &tempEnableStates[5]); - for (int i = 0; i < numLEDs_; i++) + for (int i = 0; i < NUM_LEDS; i++) { if (tempEnableStates[i] != savedEnabledStates_[i]) { @@ -572,11 +572,11 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDPowerStates() } bool stateCorrect = true; - ViUInt16 tempPowerStates[6] = { 0,0,0,0,0,0 }; + ViUInt16 tempPowerStates[NUM_LEDS]{}; TL6WL_getLED_HeadBrightness(deviceHandle_, &tempPowerStates[0], &tempPowerStates[1], &tempPowerStates[2], &tempPowerStates[3], &tempPowerStates[4], &tempPowerStates[5]); - for (int i = 0; i < numLEDs_; i++) + for (int i = 0; i < NUM_LEDS; i++) { if (tempPowerStates[i] != savedBrightnessStates_[i]) { From ae6f059359c67925bbe860455d15a1f699742ab7 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Mon, 20 Nov 2023 17:27:37 -0600 Subject: [PATCH 45/91] Use std::array to simplify code This removes all raw "6"s from ThorlabsChrolisDeviceWrapper (except for the functions accepting 6 separate parameters). --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 9 ++-- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 30 +++++++------ .../ThorlabsChrolisDeviceWrapper.cpp | 42 +++++-------------- 3 files changed, 32 insertions(+), 49 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 304b48076..8b839d903 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -108,7 +108,7 @@ int ChrolisHub::Initialize() } std::string wavelengthList = ""; - ViUInt16 wavelengths[6]; + std::array wavelengths; err = ChrolisDevice.GetLEDWavelengths(wavelengths); if (err != 0) { @@ -176,7 +176,6 @@ void ChrolisHub::StatusChangedPollingThread() { ViUInt32 tempStatus = 0; std::string message; - ViBoolean tempEnableStates[6]; while (threadRunning_.load()) { if (ChrolisDevice.IsDeviceConnected()) @@ -259,9 +258,9 @@ void ChrolisHub::StatusChangedPollingThread() { if (curStatus != 0) { + std::array tempEnableStates{}; ChrolisDevice.VerifyLEDEnableStatesWithLock(); - if (ChrolisDevice.GetLEDEnableStates(tempEnableStates[0], - tempEnableStates[1], tempEnableStates[2], tempEnableStates[3], tempEnableStates[4], tempEnableStates[5]) != 0) + if (ChrolisDevice.GetLEDEnableStates(tempEnableStates) != 0) { LogMessage("Error getting info from chrolis"); } @@ -674,7 +673,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) return ERR_PARAM_NOT_VALID; } - ViBoolean newStates[6] + std::array newStates { static_cast(val & (1 << 0)), static_cast(val & (1 << 1)), diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 81d36594c..ae2f99f4a 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -1,11 +1,14 @@ #pragma once -#include + +#include "DeviceBase.h" #include + +#include #include -#include -#include -#include "DeviceBase.h" #include +#include +#include +#include #define CHROLIS_HUB_NAME "CHROLIS" #define CHROLIS_SHUTTER_NAME "CHROLIS_Shutter" @@ -26,6 +29,8 @@ #define ERR_UNKOWN_HW_STATE -1073676421 #define ERR_VAL_OVERFLOW -1073481985 +constexpr int NUM_LEDS = 6; + static std::map ErrorMessages() { return { @@ -62,25 +67,24 @@ class ThorlabsChrolisDeviceWrapper int GetSerialNumber(ViChar* serialNumber); int GetManufacturerName(ViChar* manfName); int GetDeviceStatus(ViUInt32& status); - int GetLEDWavelengths(ViUInt16(&wavelengths)[6]); + int GetLEDWavelengths(std::array &wavelengths); int GetShutterState(bool& open); int GetSingleLEDEnableState(int led, ViBoolean& state); - int GetLEDEnableStates(ViBoolean(&states)[6]); + int GetLEDEnableStates(std::array &states); int GetLEDEnableStates(ViBoolean& led1State, ViBoolean& led2State, ViBoolean& led3State, ViBoolean& led4State, ViBoolean& led5State, ViBoolean& led6State); int GetSingleLEDBrightnessState(int led, ViUInt16& state); - int GetLEDBrightnessStates(ViUInt16(&states)[6]); + int GetLEDBrightnessStates(std::array &states); int GetLEDBrightnessStates(ViUInt16& led1Brightness, ViUInt16& led2Brightness, ViUInt16& led3Brightness, ViUInt16& led4Brightness, ViUInt16& led5Brightness, ViUInt16& led6Brightness); int SetShutterState(bool open); - int SetLEDEnableStates(ViBoolean states[6]); + int SetLEDEnableStates(std::array states); int SetSingleLEDEnableState(int LED, ViBoolean state); - int SetLEDBrightnessStates(ViUInt16 states[6]); + int SetLEDBrightnessStates(std::array states); int SetSingleLEDBrightnessState(int LED, ViUInt16 state); bool VerifyLEDEnableStatesWithLock(); private: - static constexpr int NUM_LEDS = 6; std::vector serialNumberList_; std::mutex instanceMutex_; bool deviceConnected_ = false; @@ -90,9 +94,9 @@ class ThorlabsChrolisDeviceWrapper ViChar serialNumber_[TL6WL_LONG_STRING_SIZE] = ""; ViChar manufacturerName_[TL6WL_LONG_STRING_SIZE] = ""; bool masterSwitchState_ = false; - ViBoolean savedEnabledStates_[NUM_LEDS]{}; - ViUInt16 savedBrightnessStates_[NUM_LEDS]{}; - ViUInt16 ledWavelengths_[NUM_LEDS]{}; + std::array savedEnabledStates_{}; + std::array savedBrightnessStates_{}; + std::array ledWavelengths_{}; bool VerifyLEDStates(); bool VerifyLEDPowerStates(); diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 2f13799a1..6f5bae8c8 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -187,24 +187,16 @@ int ThorlabsChrolisDeviceWrapper::GetShutterState(bool& open) return DEVICE_OK; } -int ThorlabsChrolisDeviceWrapper::GetLEDWavelengths(ViUInt16(&wavelengths)[ThorlabsChrolisDeviceWrapper::NUM_LEDS]) +int ThorlabsChrolisDeviceWrapper::GetLEDWavelengths(std::array &wavelengths) { std::lock_guard lock(instanceMutex_); if (!deviceConnected_) { - for (int i = 0; i < NUM_LEDS; i++) - { - wavelengths[i] = 0; - } + wavelengths.fill(false); return ERR_CHROLIS_NOT_AVAIL; } - wavelengths[0] = ledWavelengths_[0]; - wavelengths[1] = ledWavelengths_[1]; - wavelengths[2] = ledWavelengths_[2]; - wavelengths[3] = ledWavelengths_[3]; - wavelengths[4] = ledWavelengths_[4]; - wavelengths[5] = ledWavelengths_[5]; + wavelengths = ledWavelengths_; return DEVICE_OK; } @@ -229,22 +221,16 @@ int ThorlabsChrolisDeviceWrapper::GetSingleLEDEnableState(int led, ViBoolean& st return DEVICE_OK; } -int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(ViBoolean(&states)[6]) +int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(std::array &states) { std::lock_guard lock(instanceMutex_); if (!deviceConnected_) { - for (int i = 0; i < NUM_LEDS; i++) - { - states[i] = false; - } + states.fill(false); return ERR_CHROLIS_NOT_AVAIL; } - for (int i = 0; i < NUM_LEDS; i++) - { - states[i] = savedEnabledStates_[i]; - } + states = savedEnabledStates_; return DEVICE_OK; } @@ -292,22 +278,16 @@ int ThorlabsChrolisDeviceWrapper::GetSingleLEDBrightnessState(int led, ViUInt16& return DEVICE_OK; } -int ThorlabsChrolisDeviceWrapper::GetLEDBrightnessStates(ViUInt16(&states)[6]) +int ThorlabsChrolisDeviceWrapper::GetLEDBrightnessStates(std::array &states) { std::lock_guard lock(instanceMutex_); if (!deviceConnected_) { - for (int i = 0; i < NUM_LEDS; i++) - { - states[i] = 0; - } + states.fill(0); return ERR_CHROLIS_NOT_AVAIL; } - for (int i = 0; i < NUM_LEDS; i++) - { - states[i] = savedBrightnessStates_[i]; - } + states = savedBrightnessStates_; return DEVICE_OK; } @@ -412,7 +392,7 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDEnableState(int LED, ViBoolean sta } } -int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(ViBoolean states[6]) +int ThorlabsChrolisDeviceWrapper::SetLEDEnableStates(std::array states) { std::lock_guard lock(instanceMutex_); @@ -476,7 +456,7 @@ int ThorlabsChrolisDeviceWrapper::SetSingleLEDBrightnessState(int LED, ViUInt16 } } -int ThorlabsChrolisDeviceWrapper::SetLEDBrightnessStates(ViUInt16 states[6]) +int ThorlabsChrolisDeviceWrapper::SetLEDBrightnessStates(std::array states) { std::lock_guard lock(instanceMutex_); From faa52630aaa28847a76f4c07be0567927f40b52e Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Mon, 20 Nov 2023 17:44:16 -0600 Subject: [PATCH 46/91] Replace more raw arrays with std::array --- .../ThorlabsChrolisDeviceWrapper.cpp | 49 +++++-------------- 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 6f5bae8c8..f1d22cc96 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -321,7 +321,7 @@ int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) std::lock_guard lock(instanceMutex_); if (!open) { - ViBoolean tempEnableStates[NUM_LEDS]; + std::array tempEnableStates; err = TL6WL_setLED_HeadPowerStates(deviceHandle_, false, false, false, false, false, false); if (err != 0) { @@ -500,23 +500,16 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDStates() return false; } - bool stateCorrect = true; - ViUInt16 tempPowerStates[NUM_LEDS]{}; - ViBoolean tempEnableStates[NUM_LEDS]{}; + std::array tempPowerStates{}; + std::arraytempEnableStates{}; TL6WL_getLED_HeadPowerStates(deviceHandle_, &tempEnableStates[0], &tempEnableStates[1], &tempEnableStates[2], &tempEnableStates[3], &tempEnableStates[4], &tempEnableStates[5]); TL6WL_getLED_HeadBrightness(deviceHandle_, &tempPowerStates[0], &tempPowerStates[1], &tempPowerStates[2], &tempPowerStates[3], &tempPowerStates[4], &tempPowerStates[5]); - for (int i = 0; i < NUM_LEDS; i++) - { - if (tempEnableStates[i] != savedEnabledStates_[i] || tempPowerStates[i] != savedBrightnessStates_[i]) - { - stateCorrect = false; - savedEnabledStates_[i] = tempEnableStates[i]; - savedBrightnessStates_[i] = tempPowerStates[i]; - } - } - + bool stateCorrect = (tempEnableStates == savedEnabledStates_ && + tempPowerStates == savedBrightnessStates_); + savedEnabledStates_ = tempEnableStates; + savedBrightnessStates_ = tempPowerStates; return stateCorrect; } @@ -527,20 +520,12 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDEnableStates() return false; } - bool stateCorrect = true; - ViBoolean tempEnableStates[NUM_LEDS]{}; + std::array tempEnableStates{}; TL6WL_getLED_HeadPowerStates(deviceHandle_, &tempEnableStates[0], &tempEnableStates[1], &tempEnableStates[2], &tempEnableStates[3], &tempEnableStates[4], &tempEnableStates[5]); - for (int i = 0; i < NUM_LEDS; i++) - { - if (tempEnableStates[i] != savedEnabledStates_[i]) - { - stateCorrect = false; - savedEnabledStates_[i] = tempEnableStates[i]; - } - } - + bool stateCorrect = (tempEnableStates == savedEnabledStates_); + savedEnabledStates_ = tempEnableStates; return stateCorrect; } @@ -551,19 +536,11 @@ bool ThorlabsChrolisDeviceWrapper::VerifyLEDPowerStates() return false; } - bool stateCorrect = true; - ViUInt16 tempPowerStates[NUM_LEDS]{}; + std::array tempPowerStates{}; TL6WL_getLED_HeadBrightness(deviceHandle_, &tempPowerStates[0], &tempPowerStates[1], &tempPowerStates[2], &tempPowerStates[3], &tempPowerStates[4], &tempPowerStates[5]); - for (int i = 0; i < NUM_LEDS; i++) - { - if (tempPowerStates[i] != savedBrightnessStates_[i]) - { - stateCorrect = false; - savedBrightnessStates_[i] = tempPowerStates[i]; - } - } - + bool stateCorrect = (tempPowerStates == savedBrightnessStates_); + savedBrightnessStates_ = tempPowerStates; return stateCorrect; } \ No newline at end of file From cf19976c7477dae0a8c9f900b9677ad65d16ebc6 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Mon, 20 Nov 2023 17:45:56 -0600 Subject: [PATCH 47/91] Remove redundant definition of numPos_ --- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp | 4 ++-- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 8b839d903..55e52c5e2 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -446,7 +446,7 @@ int ChrolisStateDevice::Initialize() // create default positions and labels const int bufSize = 1024; char buf[bufSize]; - for (long i = 0; i < numPos_; i++) + for (long i = 0; i < NUM_LEDS; i++) { snprintf(buf, bufSize, "-%ld", i); SetPositionLabel(i, buf); @@ -665,7 +665,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) long val; // incoming value from user pProp->Get(val); - if (val >= pow(2, numPos_) || val < 0) + if (val >= pow(2, NUM_LEDS) || val < 0) { LogMessage("Requested state out of bounds"); os << currentLEDState; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index ae2f99f4a..3fc42bc11 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -166,7 +166,7 @@ class ChrolisStateDevice : public CStateDeviceBase void GetName(char* pszName) const; bool Busy(); - unsigned long GetNumberOfPositions()const { return numPos_; } + unsigned long GetNumberOfPositions()const { return NUM_LEDS; } // action interface // ---------------- @@ -178,8 +178,6 @@ class ChrolisStateDevice : public CStateDeviceBase int OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct); private: - long numPos_= 6; - ViUInt16 led1Brightness_ = 0; ViUInt16 led2Brightness_ = 0; ViUInt16 led3Brightness_ = 0; From f9b82246a02913036741f6ea6f7619432e378e0f Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Mon, 20 Nov 2023 18:00:44 -0600 Subject: [PATCH 48/91] Replace 6 separate vars with std::array Fixed one bug: wrong initial value given to "LED Enable State 6" (was using brightness instead of state). --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 123 ++++++++---------- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 15 +-- 2 files changed, 57 insertions(+), 81 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 55e52c5e2..a2049fcd3 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -455,11 +455,15 @@ int ChrolisStateDevice::Initialize() uint32_t tmpLedState = 0; if (pHub->ChrolisDevice.IsDeviceConnected()) { - err = pHub->ChrolisDevice.GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_); - err = pHub->ChrolisDevice.GetLEDBrightnessStates(led1Brightness_, led2Brightness_, led3Brightness_, led4Brightness_, led5Brightness_, led6Brightness_); + err = pHub->ChrolisDevice.GetLEDEnableStates(ledStates_); + err = pHub->ChrolisDevice.GetLEDBrightnessStates(ledBrightnesses_); tmpLedState = - ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) - | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5)); + ((static_cast(ledStates_[0]) << 0) | + (static_cast(ledStates_[1]) << 1) | + (static_cast(ledStates_[2]) << 2) | + (static_cast(ledStates_[3]) << 3) | + (static_cast(ledStates_[4]) << 4) | + (static_cast(ledStates_[5]) << 5)); } //State Property @@ -471,7 +475,7 @@ int ChrolisStateDevice::Initialize() ////Properties for power control pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 1 Power", led1Brightness_, false, pAct); + err = CreateIntegerProperty("LED 1 Power", ledBrightnesses_[0], false, pAct); if (err != 0) { LogMessage("Error with property set in power control"); @@ -480,7 +484,7 @@ int ChrolisStateDevice::Initialize() SetPropertyLimits("LED 1 Power", ledMinBrightness_, ledMaxBrightness_); pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 2 Power", led2Brightness_, false, pAct); + err = CreateIntegerProperty("LED 2 Power", ledBrightnesses_[1], false, pAct); SetPropertyLimits("LED 2 Power", ledMinBrightness_, ledMaxBrightness_); if (err != 0) { @@ -489,7 +493,7 @@ int ChrolisStateDevice::Initialize() } pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 3 Power", led3Brightness_, false, pAct); + err = CreateIntegerProperty("LED 3 Power", ledBrightnesses_[2], false, pAct); SetPropertyLimits("LED 3 Power", ledMinBrightness_, ledMaxBrightness_); if (err != 0) { @@ -498,7 +502,7 @@ int ChrolisStateDevice::Initialize() } pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 4 Power", led4Brightness_, false, pAct); + err = CreateIntegerProperty("LED 4 Power", ledBrightnesses_[3], false, pAct); SetPropertyLimits("LED 4 Power", ledMinBrightness_, ledMaxBrightness_); if (err != 0) { @@ -507,7 +511,7 @@ int ChrolisStateDevice::Initialize() } pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 5 Power", led5Brightness_, false, pAct); + err = CreateIntegerProperty("LED 5 Power", ledBrightnesses_[4], false, pAct); SetPropertyLimits("LED 5 Power", ledMinBrightness_, ledMaxBrightness_); if (err != 0) { @@ -516,7 +520,7 @@ int ChrolisStateDevice::Initialize() } pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 6 Power", led6Brightness_, false, pAct); + err = CreateIntegerProperty("LED 6 Power", ledBrightnesses_[5], false, pAct); SetPropertyLimits("LED 6 Power", ledMinBrightness_, ledMaxBrightness_); if (err != 0) { @@ -527,7 +531,7 @@ int ChrolisStateDevice::Initialize() //Properties for state control pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 1", led1State_, false, pAct); + err = CreateIntegerProperty("LED Enable State 1", ledStates_[0], false, pAct); if (err != 0) { LogMessage("Error with property set in state control"); @@ -536,7 +540,7 @@ int ChrolisStateDevice::Initialize() SetPropertyLimits("LED Enable State 1", 0, 1); pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 2", led2State_, false, pAct); + err = CreateIntegerProperty("LED Enable State 2", ledStates_[1], false, pAct); if (err != 0) { LogMessage("Error with property set in state control"); @@ -545,7 +549,7 @@ int ChrolisStateDevice::Initialize() SetPropertyLimits("LED Enable State 2", 0, 1); pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 3", led3State_, false, pAct); + err = CreateIntegerProperty("LED Enable State 3", ledStates_[2], false, pAct); if (err != 0) { LogMessage("Error with property set in state control"); @@ -554,7 +558,7 @@ int ChrolisStateDevice::Initialize() SetPropertyLimits("LED Enable State 3", 0, 1); pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 4", led4State_, false, pAct); + err = CreateIntegerProperty("LED Enable State 4", ledStates_[3], false, pAct); if (err != 0) { LogMessage("Error with property set in state control"); @@ -563,7 +567,7 @@ int ChrolisStateDevice::Initialize() SetPropertyLimits("LED Enable State 4", 0, 1); pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 5", led5State_, false, pAct); + err = CreateIntegerProperty("LED Enable State 5", ledStates_[4], false, pAct); if (err != 0) { LogMessage("Error with property set in state control"); @@ -572,7 +576,7 @@ int ChrolisStateDevice::Initialize() SetPropertyLimits("LED Enable State 5", 0, 1); pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 6", led6Brightness_, false, pAct); + err = CreateIntegerProperty("LED Enable State 6", ledStates_[5], false, pAct); if (err != 0) { LogMessage("Error with property set in state control"); @@ -628,21 +632,31 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) { LogMessage("CHROLIS not available"); } - if (pHub->ChrolisDevice.GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_) != 0) + if (pHub->ChrolisDevice.GetLEDEnableStates(ledStates_) != 0) { LogMessage("Error getting info from chrolis"); } - pProp->Set((long)((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) - | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5))); + pProp->Set((long)( + (static_cast(ledStates_[0]) << 0) | + (static_cast(ledStates_[1]) << 1) | + (static_cast(ledStates_[2]) << 2) | + (static_cast(ledStates_[3]) << 3) | + (static_cast(ledStates_[4]) << 4) | + (static_cast(ledStates_[5]) << 5))); } else if (eAct == MM::AfterSet) { std::ostringstream os; //temp state from last set used as fallback - uint8_t currentLEDState = ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) - | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5)); + uint8_t currentLEDState = + ((static_cast(ledStates_[0]) << 0) | + (static_cast(ledStates_[1]) << 1) | + (static_cast(ledStates_[2]) << 2) | + (static_cast(ledStates_[3]) << 3) | + (static_cast(ledStates_[4]) << 4) | + (static_cast(ledStates_[5]) << 5)); //Get the current instances for hub and chrolis //In the event of error do not set the property. Set old value. Updated values will be pulled from getters if possible @@ -690,12 +704,17 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) LogMessage("Error Setting LED state"); if (err != ERR_CHROLIS_NOT_AVAIL) { - if (pHub->ChrolisDevice.GetLEDEnableStates(led1State_, led2State_, led3State_, led4State_, led5State_, led6State_) != 0) + if (pHub->ChrolisDevice.GetLEDEnableStates(ledStates_) != 0) { LogMessage("Error getting info from chrolis"); } - currentLEDState = ((static_cast(led1State_) << 0) | (static_cast(led2State_) << 1) | (static_cast(led3State_) << 2) - | (static_cast(led4State_) << 3) | (static_cast(led5State_) << 4) | (static_cast(led6State_) << 5)); + currentLEDState = + ((static_cast(ledStates_[0]) << 0) | + (static_cast(ledStates_[1]) << 1) | + (static_cast(ledStates_[2]) << 2) | + (static_cast(ledStates_[3]) << 3) | + (static_cast(ledStates_[4]) << 4) | + (static_cast(ledStates_[5]) << 5)); os << currentLEDState; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); @@ -736,30 +755,14 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT return DEVICE_ERR; } - switch (numFromName) - { - case 1: - ledBeingControlled = &led1State_; - break; - case 2: - ledBeingControlled = &led2State_; - break; - case 3: - ledBeingControlled = &led3State_; - break; - case 4: - ledBeingControlled = &led4State_; - break; - case 5: - ledBeingControlled = &led5State_; - break; - case 6: - ledBeingControlled = &led6State_; - break; - default: + if (numFromName > 0 && numFromName <= NUM_LEDS) + { + ledBeingControlled = &ledStates_[numFromName - 1]; + } + else + { LogMessage("Error selecting LED state"); return DEVICE_ERR; - break; } if (eAct == MM::BeforeGet) @@ -845,30 +848,14 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA return DEVICE_ERR; } - switch (numFromName) - { - case 1: - ledBeingControlled = &led1Brightness_; - break; - case 2: - ledBeingControlled = &led2Brightness_; - break; - case 3: - ledBeingControlled = &led3Brightness_; - break; - case 4: - ledBeingControlled = &led4Brightness_; - break; - case 5: - ledBeingControlled = &led5Brightness_; - break; - case 6: - ledBeingControlled = &led6Brightness_; - break; - default: + if (numFromName > 0 && numFromName <= NUM_LEDS) + { + ledBeingControlled = &ledBrightnesses_[numFromName - 1]; + } + else + { LogMessage("Error selecting LED state"); return DEVICE_ERR; - break; } if (eAct == MM::BeforeGet) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 3fc42bc11..4df3086b8 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -178,19 +178,8 @@ class ChrolisStateDevice : public CStateDeviceBase int OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct); private: - ViUInt16 led1Brightness_ = 0; - ViUInt16 led2Brightness_ = 0; - ViUInt16 led3Brightness_ = 0; - ViUInt16 led4Brightness_ = 0; - ViUInt16 led5Brightness_ = 0; - ViUInt16 led6Brightness_ = 0; - - ViBoolean led1State_ = false; - ViBoolean led2State_ = false; - ViBoolean led3State_ = false; - ViBoolean led4State_ = false; - ViBoolean led5State_ = false; - ViBoolean led6State_ = false; + std::array ledBrightnesses_{}; + std::array ledStates_{}; ViInt16 ledMaxBrightness_ = 1000; ViInt16 ledMinBrightness_ = 0; From d540f8de537492c4b9478321242f94b6142d1744 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Mon, 20 Nov 2023 18:02:05 -0600 Subject: [PATCH 49/91] Delete functions no longer used --- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 2 - .../ThorlabsChrolisDeviceWrapper.cpp | 48 ------------------- 2 files changed, 50 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 4df3086b8..e6ba7ea87 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -71,10 +71,8 @@ class ThorlabsChrolisDeviceWrapper int GetShutterState(bool& open); int GetSingleLEDEnableState(int led, ViBoolean& state); int GetLEDEnableStates(std::array &states); - int GetLEDEnableStates(ViBoolean& led1State, ViBoolean& led2State, ViBoolean& led3State, ViBoolean& led4State, ViBoolean& led5State, ViBoolean& led6State); int GetSingleLEDBrightnessState(int led, ViUInt16& state); int GetLEDBrightnessStates(std::array &states); - int GetLEDBrightnessStates(ViUInt16& led1Brightness, ViUInt16& led2Brightness, ViUInt16& led3Brightness, ViUInt16& led4Brightness, ViUInt16& led5Brightness, ViUInt16& led6Brightness); int SetShutterState(bool open); int SetLEDEnableStates(std::array states); diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index f1d22cc96..1cb832c71 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -234,30 +234,6 @@ int ThorlabsChrolisDeviceWrapper::GetLEDEnableStates(std::array lock(instanceMutex_); - - if (!deviceConnected_) - { - led1State = false; - led2State = false; - led3State = false; - led4State = false; - led5State = false; - led6State = false; - return ERR_CHROLIS_NOT_AVAIL; - } - led1State = savedEnabledStates_[0]; - led2State = savedEnabledStates_[1]; - led3State = savedEnabledStates_[2]; - led4State = savedEnabledStates_[3]; - led5State = savedEnabledStates_[4]; - led6State = savedEnabledStates_[5]; - - return DEVICE_OK; -} - int ThorlabsChrolisDeviceWrapper::GetSingleLEDBrightnessState(int led, ViUInt16& state) { std::lock_guard lock(instanceMutex_); @@ -291,30 +267,6 @@ int ThorlabsChrolisDeviceWrapper::GetLEDBrightnessStates(std::array lock(instanceMutex_); - - if (!deviceConnected_) - { - led1Brightness = 0; - led2Brightness = 0; - led3Brightness = 0; - led4Brightness = 0; - led5Brightness = 0; - led6Brightness = 0; - return ERR_CHROLIS_NOT_AVAIL; - } - led1Brightness = savedBrightnessStates_[0]; - led2Brightness = savedBrightnessStates_[1]; - led3Brightness = savedBrightnessStates_[2]; - led4Brightness = savedBrightnessStates_[2]; - led5Brightness = savedBrightnessStates_[4]; - led6Brightness = savedBrightnessStates_[5]; - - return DEVICE_OK; -} - int ThorlabsChrolisDeviceWrapper::SetShutterState(bool open) { int err = DEVICE_OK; From 304b05c60ab75fe8ac8167c81037ed901c77b431 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Mon, 20 Nov 2023 18:14:09 -0600 Subject: [PATCH 50/91] Use parameterized loops for repeated code --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 135 +++--------------- 1 file changed, 22 insertions(+), 113 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index a2049fcd3..e1ca4af7e 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -421,22 +421,13 @@ int ChrolisStateDevice::Initialize() OnPropertyChanged("state", os.str().c_str()); break; case 1: - OnPropertyChanged("LED Enable State 1", os.str().c_str()); - break; case 2: - OnPropertyChanged("LED Enable State 2", os.str().c_str()); - break; case 3: - OnPropertyChanged("LED Enable State 3", os.str().c_str()); - break; case 4: - OnPropertyChanged("LED Enable State 4", os.str().c_str()); - break; case 5: - OnPropertyChanged("LED Enable State 5", os.str().c_str()); - break; case 6: - OnPropertyChanged("LED Enable State 6", os.str().c_str()); + OnPropertyChanged(("LED Enable State " + std::to_string(ledNum)).c_str(), + os.str().c_str()); break; default: break; @@ -474,115 +465,33 @@ int ChrolisStateDevice::Initialize() ////Properties for power control - pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 1 Power", ledBrightnesses_[0], false, pAct); - if (err != 0) - { - LogMessage("Error with property set in power control"); - return DEVICE_ERR; - } - SetPropertyLimits("LED 1 Power", ledMinBrightness_, ledMaxBrightness_); - - pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 2 Power", ledBrightnesses_[1], false, pAct); - SetPropertyLimits("LED 2 Power", ledMinBrightness_, ledMaxBrightness_); - if (err != 0) - { - return DEVICE_ERR; - LogMessage("Error with property set in state control"); - } - - pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 3 Power", ledBrightnesses_[2], false, pAct); - SetPropertyLimits("LED 3 Power", ledMinBrightness_, ledMaxBrightness_); - if (err != 0) + for (int i = 0; i < NUM_LEDS; i++) { - return DEVICE_ERR; - LogMessage("Error with property set in state control"); - } - - pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 4 Power", ledBrightnesses_[3], false, pAct); - SetPropertyLimits("LED 4 Power", ledMinBrightness_, ledMaxBrightness_); - if (err != 0) - { - return DEVICE_ERR; - LogMessage("Error with property set in state control"); - } - - pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 5 Power", ledBrightnesses_[4], false, pAct); - SetPropertyLimits("LED 5 Power", ledMinBrightness_, ledMaxBrightness_); - if (err != 0) - { - return DEVICE_ERR; - LogMessage("Error with property set in state control"); - } - - pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); - err = CreateIntegerProperty("LED 6 Power", ledBrightnesses_[5], false, pAct); - SetPropertyLimits("LED 6 Power", ledMinBrightness_, ledMaxBrightness_); - if (err != 0) - { - return DEVICE_ERR; - LogMessage("Error with property set in state control"); + pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); + std::string propName = "LED " + std::to_string(i + 1) + " Power"; + err = CreateIntegerProperty(propName.c_str(), ledBrightnesses_[i], false, pAct); + if (err != 0) + { + LogMessage("Error with property set in power control"); + return DEVICE_ERR; + } + SetPropertyLimits(propName.c_str(), ledMinBrightness_, ledMaxBrightness_); } //Properties for state control - pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 1", ledStates_[0], false, pAct); - if (err != 0) - { - LogMessage("Error with property set in state control"); - return DEVICE_ERR; - } - SetPropertyLimits("LED Enable State 1", 0, 1); - - pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 2", ledStates_[1], false, pAct); - if (err != 0) - { - LogMessage("Error with property set in state control"); - return DEVICE_ERR; - } - SetPropertyLimits("LED Enable State 2", 0, 1); - - pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 3", ledStates_[2], false, pAct); - if (err != 0) - { - LogMessage("Error with property set in state control"); - return DEVICE_ERR; - } - SetPropertyLimits("LED Enable State 3", 0, 1); - - pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 4", ledStates_[3], false, pAct); - if (err != 0) + for (int i = 0; i < NUM_LEDS; i++) { - LogMessage("Error with property set in state control"); - return DEVICE_ERR; - } - SetPropertyLimits("LED Enable State 4", 0, 1); - - pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 5", ledStates_[4], false, pAct); - if (err != 0) - { - LogMessage("Error with property set in state control"); - return DEVICE_ERR; - } - SetPropertyLimits("LED Enable State 5", 0, 1); - - pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); - err = CreateIntegerProperty("LED Enable State 6", ledStates_[5], false, pAct); - if (err != 0) - { - LogMessage("Error with property set in state control"); - return DEVICE_ERR; + pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); + std::string propName = "LED Enable State " + std::to_string(i + 1); + err = CreateIntegerProperty(propName.c_str(), ledStates_[i], false, pAct); + if (err != 0) + { + LogMessage("Error with property set in state control"); + return DEVICE_ERR; + } + SetPropertyLimits(propName.c_str(), 0, 1); } - SetPropertyLimits("LED Enable State 6", 0, 1); return DEVICE_OK; } From e9828441a3a3675182ddfac629aaaafc92f530a5 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Mon, 20 Nov 2023 18:21:33 -0600 Subject: [PATCH 51/91] Use PropertyActionEx for LED index --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 89 +++---------------- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 4 +- 2 files changed, 16 insertions(+), 77 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index e1ca4af7e..3efbdc2f8 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -2,7 +2,6 @@ #include "ModuleInterface.h" #include -#include MODULE_API void InitializeModuleData() { RegisterDevice(CHROLIS_HUB_NAME, @@ -467,9 +466,9 @@ int ChrolisStateDevice::Initialize() ////Properties for power control for (int i = 0; i < NUM_LEDS; i++) { - pAct = new CPropertyAction(this, &ChrolisStateDevice::OnPowerChange); + auto* pActEx = new CPropertyActionEx(this, &ChrolisStateDevice::OnPowerChange, i); std::string propName = "LED " + std::to_string(i + 1) + " Power"; - err = CreateIntegerProperty(propName.c_str(), ledBrightnesses_[i], false, pAct); + err = CreateIntegerProperty(propName.c_str(), ledBrightnesses_[i], false, pActEx); if (err != 0) { LogMessage("Error with property set in power control"); @@ -482,9 +481,9 @@ int ChrolisStateDevice::Initialize() //Properties for state control for (int i = 0; i < NUM_LEDS; i++) { - pAct = new CPropertyAction(this, &ChrolisStateDevice::OnEnableStateChange); + auto* pActEx = new CPropertyActionEx(this, &ChrolisStateDevice::OnEnableStateChange, i); std::string propName = "LED Enable State " + std::to_string(i + 1); - err = CreateIntegerProperty(propName.c_str(), ledStates_[i], false, pAct); + err = CreateIntegerProperty(propName.c_str(), ledStates_[i], false, pActEx); if (err != 0) { LogMessage("Error with property set in state control"); @@ -640,39 +639,9 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) return DEVICE_OK; } -int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct) +int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct, long ledIndex) { - ViPBoolean ledBeingControlled; - int numFromName = -1; - std::string searchString = pProp->GetName(); - std::regex regexp(R"([-+]?([0-9]*\.[0-9]+|[0-9]+))"); - std::smatch sm; - std::regex_search(searchString, sm, regexp); - - //The names for the LED's should contain only a single number representing the LED - //Use this to set the power - if (sm.size() > 0) - { - if (sm[0].str().length() > 0) - { - numFromName = stoi(sm[0].str()); - } - } - else - { - LogMessage("Regex match failed"); - return DEVICE_ERR; - } - - if (numFromName > 0 && numFromName <= NUM_LEDS) - { - ledBeingControlled = &ledStates_[numFromName - 1]; - } - else - { - LogMessage("Error selecting LED state"); - return DEVICE_ERR; - } + ViPBoolean ledBeingControlled = &ledStates_[ledIndex]; if (eAct == MM::BeforeGet) { @@ -686,7 +655,7 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT { LogMessage("CHROLIS not available"); } - if (pHub->ChrolisDevice.GetSingleLEDEnableState(numFromName-1, *ledBeingControlled) != 0) + if (pHub->ChrolisDevice.GetSingleLEDEnableState(ledIndex, *ledBeingControlled) != 0) { LogMessage("Error getting info from chrolis"); } @@ -714,11 +683,11 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT return ERR_CHROLIS_NOT_AVAIL; } - int err = pHub->ChrolisDevice.SetSingleLEDEnableState(numFromName-1, (ViBoolean)val); + int err = pHub->ChrolisDevice.SetSingleLEDEnableState(ledIndex, (ViBoolean)val); if (err != 0) { LogMessage("Error Setting LED state"); - pHub->ChrolisDevice.GetSingleLEDEnableState(numFromName - 1, *ledBeingControlled); + pHub->ChrolisDevice.GetSingleLEDEnableState(ledIndex, *ledBeingControlled); os << *ledBeingControlled; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return err; @@ -733,39 +702,9 @@ int ChrolisStateDevice::OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionT return DEVICE_OK; } -int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct) +int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct, long ledIndex) { - ViPUInt16 ledBeingControlled; - int numFromName = -1; - std::string searchString = pProp->GetName(); - std::regex regexp(R"([-+]?([0-9]*\.[0-9]+|[0-9]+))"); - std::smatch sm; - std::regex_search(searchString, sm, regexp); - - //The names for the LED's should contain only a single number representing the LED - //Use this to set the power - if (sm.size() > 0) - { - if (sm[0].str().length() > 0) - { - numFromName = stoi(sm[0].str()); - } - } - else - { - LogMessage("Regex match failed"); - return DEVICE_ERR; - } - - if (numFromName > 0 && numFromName <= NUM_LEDS) - { - ledBeingControlled = &ledBrightnesses_[numFromName - 1]; - } - else - { - LogMessage("Error selecting LED state"); - return DEVICE_ERR; - } + ViPUInt16 ledBeingControlled = &ledBrightnesses_[ledIndex]; if (eAct == MM::BeforeGet) { @@ -779,7 +718,7 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA { LogMessage("CHROLIS not available"); } - if (pHub->ChrolisDevice.GetSingleLEDBrightnessState(numFromName - 1, *ledBeingControlled) != 0) + if (pHub->ChrolisDevice.GetSingleLEDBrightnessState(ledIndex, *ledBeingControlled) != 0) { LogMessage("Error getting info from chrolis"); } @@ -807,11 +746,11 @@ int ChrolisStateDevice::OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eA return ERR_CHROLIS_NOT_AVAIL; } - int err = pHub->ChrolisDevice.SetSingleLEDBrightnessState(numFromName - 1, (ViUInt16)val); + int err = pHub->ChrolisDevice.SetSingleLEDBrightnessState(ledIndex, (ViUInt16)val); if (err != 0) { LogMessage("Error Setting LED state"); - pHub->ChrolisDevice.GetSingleLEDBrightnessState(numFromName - 1, *ledBeingControlled); + pHub->ChrolisDevice.GetSingleLEDBrightnessState(ledIndex, *ledBeingControlled); os << *ledBeingControlled; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); return err; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index e6ba7ea87..1d2054a2b 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -172,8 +172,8 @@ class ChrolisStateDevice : public CStateDeviceBase int OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct); //LED Control Methods - int OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct); - int OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct, long ledIndex); + int OnEnableStateChange(MM::PropertyBase* pProp, MM::ActionType eAct, long ledIndex); private: std::array ledBrightnesses_{}; From c90ef13da997cab528d619fd0b839e825b251bf4 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Mon, 20 Nov 2023 18:24:11 -0600 Subject: [PATCH 52/91] Fix property name "state" -> "State" --- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 3efbdc2f8..f1281855c 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -417,7 +417,7 @@ int ChrolisStateDevice::Initialize() switch (ledNum) { case 0: - OnPropertyChanged("state", os.str().c_str()); + OnPropertyChanged(MM::g_Keyword_State, os.str().c_str()); break; case 1: case 2: From 947611a9b128cbe324609d5329579986eb15c54b Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Mon, 20 Nov 2023 18:33:28 -0600 Subject: [PATCH 53/91] Address compiler warnings Also add missing initialization to deviceHandle_ (to -1). --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 32 +++++++++++++++---- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 25 +-------------- .../ThorlabsChrolisDeviceWrapper.cpp | 11 +++---- 3 files changed, 32 insertions(+), 36 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index f1281855c..20fa5f660 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -35,6 +35,29 @@ MODULE_API MM::Device* CreateDevice(char const* name) { MODULE_API void DeleteDevice(MM::Device* device) { delete device; } + +static std::map ErrorMessages() +{ + return { + {ERR_HUB_NOT_AVAILABLE, "Hub is not available"}, + {ERR_CHROLIS_NOT_AVAIL, "CHROLIS Device is not available"}, + {ERR_IMPROPER_SET, "Error setting property value. Value will be reset"}, + {ERR_PARAM_NOT_VALID, "Value passed to property was out of bounds."}, + {ERR_NO_AVAIL_DEVICES, "No available devices were found on the system."}, + {ERR_INSUF_INFO, "Insufficient location information of the device or the resource is not present on the system"}, + {ERR_UNKOWN_HW_STATE, "Unknown Hardware State"}, + {ERR_VAL_OVERFLOW, "Parameter Value Overflow"}, + {INSTR_RUNTIME_ERROR, "CHROLIS Instrument Runtime Error"}, + {INSTR_REM_INTER_ERROR, "CHROLIS Instrument Internal Error"}, + {INSTR_AUTHENTICATION_ERROR, "CHROLIS Instrument Authentication Error"}, + {INSTR_PARAM_ERROR, "CHROLIS Invalid Parameter Error"}, + {INSTR_INTERNAL_TX_ERR, "CHROLIS Instrument Internal Command Sending Error"}, + {INSTR_INTERNAL_RX_ERR, "CHROLIS Instrument Internal Command Receiving Error"}, + {INSTR_INVAL_MODE_ERR, "CHROLIS Instrument Invalid Mode Error"}, + {INSTR_SERVICE_ERR, "CHROLIS Instrument Service Error"} + }; +} + //Hub Methods ChrolisHub::ChrolisHub() { @@ -79,7 +102,7 @@ int ChrolisHub::DetectInstalledDevices() int ChrolisHub::Initialize() { char buf[MM::MaxStrLength]; - int ret = GetProperty("Serial Number", buf); + (void)GetProperty("Serial Number", buf); int err = ChrolisDevice.InitializeDevice(buf); if (err != 0) @@ -325,6 +348,8 @@ int ChrolisShutter::Initialize() pHub->SetShutterCallback([this](int ledNum, int state) { //Might not be needed + (void)ledNum; + (void)state; }); return DEVICE_OK; @@ -515,11 +540,6 @@ bool ChrolisStateDevice::Busy() return false; } -int ChrolisStateDevice::OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct) -{ - return DEVICE_OK; -} - // Get set process // Get: pull instances of hub and chrolis, get the latest led states and set local vars to these states, if error use stored vals. diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 1d2054a2b..994d46ed2 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -31,28 +31,6 @@ constexpr int NUM_LEDS = 6; -static std::map ErrorMessages() -{ - return { - {ERR_HUB_NOT_AVAILABLE, "Hub is not available"}, - {ERR_CHROLIS_NOT_AVAIL, "CHROLIS Device is not available"}, - {ERR_IMPROPER_SET, "Error setting property value. Value will be reset"}, - {ERR_PARAM_NOT_VALID, "Value passed to property was out of bounds."}, - {ERR_NO_AVAIL_DEVICES, "No available devices were found on the system."}, - {ERR_INSUF_INFO, "Insufficient location information of the device or the resource is not present on the system"}, - {ERR_UNKOWN_HW_STATE, "Unknown Hardware State"}, - {ERR_VAL_OVERFLOW, "Parameter Value Overflow"}, - {INSTR_RUNTIME_ERROR, "CHROLIS Instrument Runtime Error"}, - {INSTR_REM_INTER_ERROR, "CHROLIS Instrument Internal Error"}, - {INSTR_AUTHENTICATION_ERROR, "CHROLIS Instrument Authentication Error"}, - {INSTR_PARAM_ERROR, "CHROLIS Invalid Parameter Error"}, - {INSTR_INTERNAL_TX_ERR, "CHROLIS Instrument Internal Command Sending Error"}, - {INSTR_INTERNAL_RX_ERR, "CHROLIS Instrument Internal Command Receiving Error"}, - {INSTR_INVAL_MODE_ERR, "CHROLIS Instrument Invalid Mode Error"}, - {INSTR_SERVICE_ERR, "CHROLIS Instrument Service Error"} - }; -} - //Wrapper for the basic functions used in this device adapter class ThorlabsChrolisDeviceWrapper { @@ -86,7 +64,7 @@ class ThorlabsChrolisDeviceWrapper std::vector serialNumberList_; std::mutex instanceMutex_; bool deviceConnected_ = false; - ViSession deviceHandle_; + ViSession deviceHandle_ = ViSession(-1); ViBoolean deviceInUse_ = false; //only used by the chrolis API ViChar deviceName_[TL6WL_LONG_STRING_SIZE] = ""; ViChar serialNumber_[TL6WL_LONG_STRING_SIZE] = ""; @@ -169,7 +147,6 @@ class ChrolisStateDevice : public CStateDeviceBase // action interface // ---------------- int OnState(MM::PropertyBase* pProp, MM::ActionType eAct); - int OnDelay(MM::PropertyBase* pProp, MM::ActionType eAct); //LED Control Methods int OnPowerChange(MM::PropertyBase* pProp, MM::ActionType eAct, long ledIndex); diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 1cb832c71..3d1d238d3 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -21,7 +21,7 @@ int ThorlabsChrolisDeviceWrapper::GetAvailableSerialNumbers(std::vector(i + 1), &ledWavelengths_[i]); if (err != 0) { return err; @@ -110,7 +109,7 @@ int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) int ThorlabsChrolisDeviceWrapper::ShutdownDevice() { - if (deviceHandle_ != -1) + if (deviceHandle_ != ViSession(-1)) { std::lock_guard lock(instanceMutex_); auto err = TL6WL_close(deviceHandle_); @@ -118,7 +117,7 @@ int ThorlabsChrolisDeviceWrapper::ShutdownDevice() { return err; } - deviceHandle_ = -1; + deviceHandle_ = ViSession(-1); } deviceConnected_ = false; return DEVICE_OK; From 785737b73a8dcd3a1dfafb148e6d873bda19b7b4 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Tue, 21 Nov 2023 13:32:20 -0600 Subject: [PATCH 54/91] Fix misplaced closing paren --- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 20fa5f660..af6cf394f 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -288,8 +288,13 @@ void ChrolisHub::StatusChangedPollingThread() } else { - stateCallback_(0, ((static_cast(tempEnableStates[0]) << 0) | (static_cast(tempEnableStates[1]) << 1) | (static_cast(tempEnableStates[2]) << 2) - | (static_cast(tempEnableStates[3]) << 3) | (static_cast(tempEnableStates[4]) << 4 | (static_cast(tempEnableStates[5]) << 5)))); + stateCallback_(0, + ((static_cast(tempEnableStates[0]) << 0) | + (static_cast(tempEnableStates[1]) << 1) | + (static_cast(tempEnableStates[2]) << 2) | + (static_cast(tempEnableStates[3]) << 3) | + (static_cast(tempEnableStates[4]) << 4) | + (static_cast(tempEnableStates[5]) << 5))); stateCallback_(1, tempEnableStates[0]); stateCallback_(2, tempEnableStates[1]); From f9a1e54128b956b4e3c00588ef464bece6f5ec99 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Tue, 21 Nov 2023 13:50:49 -0600 Subject: [PATCH 55/91] Factor out bit encode/decode for LED states --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 70 +++++++------------ 1 file changed, 26 insertions(+), 44 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index af6cf394f..63eefda4a 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -58,6 +58,25 @@ static std::map ErrorMessages() }; } +static std::uint8_t EncodeLEDStatesInBits(std::array states) { + std::uint8_t ret = 0; + for (auto i = 0; i < NUM_LEDS; i++) + { + bool state = states[i] != VI_FALSE; // Ensure 0 or 1, just in case + ret |= static_cast(static_cast(state) << i); + } + return ret; +} + +static std::array DecodeLEDStatesFromBits(std::uint8_t bits) { + std::array ret{}; + for (auto i = 0; i < NUM_LEDS; i++) + { + ret[i] = ((bits & (1 << i)) != 0); + } + return ret; +} + //Hub Methods ChrolisHub::ChrolisHub() { @@ -288,13 +307,7 @@ void ChrolisHub::StatusChangedPollingThread() } else { - stateCallback_(0, - ((static_cast(tempEnableStates[0]) << 0) | - (static_cast(tempEnableStates[1]) << 1) | - (static_cast(tempEnableStates[2]) << 2) | - (static_cast(tempEnableStates[3]) << 3) | - (static_cast(tempEnableStates[4]) << 4) | - (static_cast(tempEnableStates[5]) << 5))); + stateCallback_(0, EncodeLEDStatesInBits(tempEnableStates)); stateCallback_(1, tempEnableStates[0]); stateCallback_(2, tempEnableStates[1]); @@ -477,13 +490,7 @@ int ChrolisStateDevice::Initialize() { err = pHub->ChrolisDevice.GetLEDEnableStates(ledStates_); err = pHub->ChrolisDevice.GetLEDBrightnessStates(ledBrightnesses_); - tmpLedState = - ((static_cast(ledStates_[0]) << 0) | - (static_cast(ledStates_[1]) << 1) | - (static_cast(ledStates_[2]) << 2) | - (static_cast(ledStates_[3]) << 3) | - (static_cast(ledStates_[4]) << 4) | - (static_cast(ledStates_[5]) << 5)); + tmpLedState = EncodeLEDStatesInBits(ledStates_); } //State Property @@ -570,26 +577,14 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) LogMessage("Error getting info from chrolis"); } - pProp->Set((long)( - (static_cast(ledStates_[0]) << 0) | - (static_cast(ledStates_[1]) << 1) | - (static_cast(ledStates_[2]) << 2) | - (static_cast(ledStates_[3]) << 3) | - (static_cast(ledStates_[4]) << 4) | - (static_cast(ledStates_[5]) << 5))); + pProp->Set(static_cast(EncodeLEDStatesInBits(ledStates_))); } else if (eAct == MM::AfterSet) { std::ostringstream os; //temp state from last set used as fallback - uint8_t currentLEDState = - ((static_cast(ledStates_[0]) << 0) | - (static_cast(ledStates_[1]) << 1) | - (static_cast(ledStates_[2]) << 2) | - (static_cast(ledStates_[3]) << 3) | - (static_cast(ledStates_[4]) << 4) | - (static_cast(ledStates_[5]) << 5)); + uint8_t currentLEDState = EncodeLEDStatesInBits(ledStates_); //Get the current instances for hub and chrolis //In the event of error do not set the property. Set old value. Updated values will be pulled from getters if possible @@ -620,15 +615,8 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) return ERR_PARAM_NOT_VALID; } - std::array newStates - { - static_cast(val & (1 << 0)), - static_cast(val & (1 << 1)), - static_cast(val & (1 << 2)), - static_cast(val & (1 << 3)), - static_cast(val & (1 << 4)), - static_cast(val & (1 << 5)) - }; + std::array newStates = + DecodeLEDStatesFromBits(static_cast(val)); int err = pHub->ChrolisDevice.SetLEDEnableStates(newStates); if (err != 0) { @@ -641,13 +629,7 @@ int ChrolisStateDevice::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) { LogMessage("Error getting info from chrolis"); } - currentLEDState = - ((static_cast(ledStates_[0]) << 0) | - (static_cast(ledStates_[1]) << 1) | - (static_cast(ledStates_[2]) << 2) | - (static_cast(ledStates_[3]) << 3) | - (static_cast(ledStates_[4]) << 4) | - (static_cast(ledStates_[5]) << 5)); + currentLEDState = EncodeLEDStatesInBits(ledStates_); os << currentLEDState; OnPropertyChanged(pProp->GetName().c_str(), os.str().c_str()); From a397a4a34999124c644af79bcd6616cd66657a78 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Tue, 21 Nov 2023 15:22:39 -0600 Subject: [PATCH 56/91] Remove an unnecessary data member --- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp | 2 +- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 63eefda4a..2ad0d4f78 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -171,7 +171,7 @@ int ChrolisHub::Initialize() return DEVICE_ERR; } - err = CreateStringProperty("Device Status", deviceStatusMessage_.c_str(), true); + err = CreateStringProperty("Device Status", "No Error", true); if (err != 0) { LogMessage("Error with property set in hub initialize"); diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 994d46ed2..ddf79a1e6 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -104,7 +104,6 @@ class ChrolisHub : public HubBase std::atomic_bool threadRunning_; std::thread updateThread_; std::atomic_uint32_t currentDeviceStatusCode_; - std::string deviceStatusMessage_ = "No Error"; std::function shutterCallback_; std::function stateCallback_; }; From 3fd104902d849afd2cbc1e2dabdf3bcb4302c012 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Tue, 21 Nov 2023 15:24:03 -0600 Subject: [PATCH 57/91] Fix a compiler warning --- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 3d1d238d3..1b01ca440 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -30,6 +30,7 @@ int ThorlabsChrolisDeviceWrapper::GetAvailableSerialNumbers(std::vector Date: Tue, 21 Nov 2023 15:37:18 -0600 Subject: [PATCH 58/91] Protect hub callbacks with mutex Typically the peripheral devices will shut down (unregistering their callbacks) before the hub's polling loop exits, so it is important to synchronize. Also change the atomic variables to plain ones and rely on a single mutex. --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 42 ++++++++++++++----- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 12 ++++-- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 2ad0d4f78..1cf07a079 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -85,9 +85,6 @@ ChrolisHub::ChrolisHub() SetErrorText(errMessage.first, errMessage.second.c_str()); } - atomic_init(&threadRunning_, false); - atomic_init(¤tDeviceStatusCode_, 0); - std::vector serialNumbers; ChrolisDevice.GetAvailableSerialNumbers(serialNumbers); @@ -178,16 +175,21 @@ int ChrolisHub::Initialize() return DEVICE_ERR; } - threadRunning_.store(true); + threadRunning_ = true; updateThread_ = std::thread(&ChrolisHub::StatusChangedPollingThread, this); return DEVICE_OK; } int ChrolisHub::Shutdown() { - if (threadRunning_.load()) { - threadRunning_.store(false); + // Tell the polling thread to exit if running. + std::lock_guard lock(pollingMutex_); + threadRunning_ = false; + } + + if (updateThread_.joinable()) + { updateThread_.join(); } @@ -217,8 +219,16 @@ void ChrolisHub::StatusChangedPollingThread() { ViUInt32 tempStatus = 0; std::string message; - while (threadRunning_.load()) + for (;;) { + { + std::lock_guard lock(pollingMutex_); + if (!threadRunning_) + { + return; + } + } + if (ChrolisDevice.IsDeviceConnected()) { message.clear(); @@ -226,12 +236,15 @@ void ChrolisHub::StatusChangedPollingThread() if (err != 0) { LogMessage("Error Getting Status"); - threadRunning_.store(false); + { + std::lock_guard lock(pollingMutex_); + threadRunning_ = false; + } return; } - const auto curStatus = currentDeviceStatusCode_.load(); + const auto curStatus = currentDeviceStatusCode_; const bool statusChanged = curStatus != tempStatus; - currentDeviceStatusCode_.store(tempStatus); + currentDeviceStatusCode_ = tempStatus; if (curStatus == 0) { message += "No Error"; @@ -305,8 +318,13 @@ void ChrolisHub::StatusChangedPollingThread() { LogMessage("Error getting info from chrolis"); } - else + else { + std::lock_guard lock(pollingMutex_); + // Usually it is not a good idea to call arbitrary + // functions with a mutex held, but in this case we + // need to ensure that the callback remains valid. + stateCallback_(0, EncodeLEDStatesInBits(tempEnableStates)); stateCallback_(1, tempEnableStates[0]); @@ -326,11 +344,13 @@ void ChrolisHub::StatusChangedPollingThread() void ChrolisHub::SetShutterCallback(std::function function) { + std::lock_guard lock(pollingMutex_); shutterCallback_ = function; } void ChrolisHub::SetStateCallback(std::function function) { + std::lock_guard lock(pollingMutex_); stateCallback_ = function; } diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index ddf79a1e6..0b622bf04 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -101,11 +100,18 @@ class ChrolisHub : public HubBase void SetStateCallback(std::function); private: - std::atomic_bool threadRunning_; std::thread updateThread_; - std::atomic_uint32_t currentDeviceStatusCode_; + + // The following variables are shared with the polling thread and must only + // be accessed with pollingMutex_ held. + std::mutex pollingMutex_; + bool threadRunning_ = false; std::function shutterCallback_; std::function stateCallback_; + + // The following variable is only accessed from the polling thread (once + // started). + std::uint32_t currentDeviceStatusCode_ = 0; }; class ChrolisShutter : public CShutterBase From 6ee8bfde22404d9685731a0887dfe65f9291b218 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Tue, 21 Nov 2023 15:39:15 -0600 Subject: [PATCH 59/91] Prevent uncaught exception when callback unset --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 1cf07a079..12087342e 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -324,15 +324,17 @@ void ChrolisHub::StatusChangedPollingThread() // Usually it is not a good idea to call arbitrary // functions with a mutex held, but in this case we // need to ensure that the callback remains valid. - - stateCallback_(0, EncodeLEDStatesInBits(tempEnableStates)); - - stateCallback_(1, tempEnableStates[0]); - stateCallback_(2, tempEnableStates[1]); - stateCallback_(3, tempEnableStates[2]); - stateCallback_(4, tempEnableStates[3]); - stateCallback_(5, tempEnableStates[4]); - stateCallback_(6, tempEnableStates[5]); + if (stateCallback_) + { + stateCallback_(0, EncodeLEDStatesInBits(tempEnableStates)); + + stateCallback_(1, tempEnableStates[0]); + stateCallback_(2, tempEnableStates[1]); + stateCallback_(3, tempEnableStates[2]); + stateCallback_(4, tempEnableStates[3]); + stateCallback_(5, tempEnableStates[4]); + stateCallback_(6, tempEnableStates[5]); + } } } } From f718be6e313d84e7d98bc8f17576345041d28bf5 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Tue, 21 Nov 2023 15:42:35 -0600 Subject: [PATCH 60/91] Use flag solely to request stop We can check if the thread was started using .joinable(), so no need to have this flag carry double meaning. --- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp | 10 ++-------- DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 12087342e..636f1798a 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -175,7 +175,6 @@ int ChrolisHub::Initialize() return DEVICE_ERR; } - threadRunning_ = true; updateThread_ = std::thread(&ChrolisHub::StatusChangedPollingThread, this); return DEVICE_OK; } @@ -183,9 +182,8 @@ int ChrolisHub::Initialize() int ChrolisHub::Shutdown() { { - // Tell the polling thread to exit if running. std::lock_guard lock(pollingMutex_); - threadRunning_ = false; + pollingStopRequested_ = true; } if (updateThread_.joinable()) @@ -223,7 +221,7 @@ void ChrolisHub::StatusChangedPollingThread() { { std::lock_guard lock(pollingMutex_); - if (!threadRunning_) + if (pollingStopRequested_) { return; } @@ -236,10 +234,6 @@ void ChrolisHub::StatusChangedPollingThread() if (err != 0) { LogMessage("Error Getting Status"); - { - std::lock_guard lock(pollingMutex_); - threadRunning_ = false; - } return; } const auto curStatus = currentDeviceStatusCode_; diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 0b622bf04..a239abe9c 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -105,7 +105,7 @@ class ChrolisHub : public HubBase // The following variables are shared with the polling thread and must only // be accessed with pollingMutex_ held. std::mutex pollingMutex_; - bool threadRunning_ = false; + bool pollingStopRequested_ = false; std::function shutterCallback_; std::function stateCallback_; From 516845f25b148e6439a4dc85f3f35800ae7c5e1f Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Tue, 21 Nov 2023 17:15:15 -0600 Subject: [PATCH 61/91] Use correct parameter types for callbacks --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 56 +++++++++---------- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 4 +- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 636f1798a..b8b1e36e4 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -318,16 +318,16 @@ void ChrolisHub::StatusChangedPollingThread() // Usually it is not a good idea to call arbitrary // functions with a mutex held, but in this case we // need to ensure that the callback remains valid. + if (stateBitsCallback_) + { + stateBitsCallback_(EncodeLEDStatesInBits(tempEnableStates)); + } if (stateCallback_) { - stateCallback_(0, EncodeLEDStatesInBits(tempEnableStates)); - - stateCallback_(1, tempEnableStates[0]); - stateCallback_(2, tempEnableStates[1]); - stateCallback_(3, tempEnableStates[2]); - stateCallback_(4, tempEnableStates[3]); - stateCallback_(5, tempEnableStates[4]); - stateCallback_(6, tempEnableStates[5]); + for (int i = 0; i < NUM_LEDS; i++) + { + stateCallback_(i, tempEnableStates[i]); + } } } } @@ -344,7 +344,13 @@ void ChrolisHub::SetShutterCallback(std::function function) shutterCallback_ = function; } -void ChrolisHub::SetStateCallback(std::function function) +void ChrolisHub::SetStateBitsCallback(std::function function) +{ + std::lock_guard lock(pollingMutex_); + stateBitsCallback_ = function; +} + +void ChrolisHub::SetStateCallback(std::function function) { std::lock_guard lock(pollingMutex_); stateCallback_ = function; @@ -469,27 +475,16 @@ int ChrolisStateDevice::Initialize() return ERR_HUB_NOT_AVAILABLE; } - pHub->SetStateCallback([this](int ledNum, int state) + pHub->SetStateBitsCallback([this](std::uint8_t bits) { - std::ostringstream os; - os << (ledNum == 0 ? state : (ViBoolean)state); - switch (ledNum) - { - case 0: - OnPropertyChanged(MM::g_Keyword_State, os.str().c_str()); - break; - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - OnPropertyChanged(("LED Enable State " + std::to_string(ledNum)).c_str(), - os.str().c_str()); - break; - default: - break; - } + OnPropertyChanged(MM::g_Keyword_State, std::to_string(bits).c_str()); + }); + + pHub->SetStateCallback([this](int ledIndex, ViBoolean state) + { + int ledNum = ledIndex + 1; + OnPropertyChanged(("LED Enable State " + std::to_string(ledNum)).c_str(), + std::to_string(state).c_str()); }); // create default positions and labels @@ -553,7 +548,8 @@ int ChrolisStateDevice::Shutdown() ChrolisHub* pHub = static_cast(GetParentHub()); if (pHub) { - pHub->SetStateCallback([](int, int) {}); + pHub->SetStateCallback([](auto, auto) {}); + pHub->SetStateBitsCallback([](auto) {}); } return DEVICE_OK; } diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index a239abe9c..44b210c4e 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -97,7 +97,8 @@ class ChrolisHub : public HubBase void StatusChangedPollingThread(); void SetShutterCallback(std::function); - void SetStateCallback(std::function); + void SetStateBitsCallback(std::function); + void SetStateCallback(std::function); private: std::thread updateThread_; @@ -107,6 +108,7 @@ class ChrolisHub : public HubBase std::mutex pollingMutex_; bool pollingStopRequested_ = false; std::function shutterCallback_; + std::function stateBitsCallback_; std::function stateCallback_; // The following variable is only accessed from the polling thread (once From a6a00fce7e3cd2241b86013139c64f4d394d6536 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Tue, 21 Nov 2023 17:16:07 -0600 Subject: [PATCH 62/91] Remove unused shutter callback (To avoid confusion, since it doesn't do anything. Can be re-added if needed.) --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 18 ------------------ .../ThorlabsCHROLIS/ThorlabsChrolis.h | 2 -- 2 files changed, 20 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index b8b1e36e4..d6ce0c706 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -338,12 +338,6 @@ void ChrolisHub::StatusChangedPollingThread() } } -void ChrolisHub::SetShutterCallback(std::function function) -{ - std::lock_guard lock(pollingMutex_); - shutterCallback_ = function; -} - void ChrolisHub::SetStateBitsCallback(std::function function) { std::lock_guard lock(pollingMutex_); @@ -385,23 +379,11 @@ int ChrolisShutter::Initialize() } } - pHub->SetShutterCallback([this](int ledNum, int state) - { - //Might not be needed - (void)ledNum; - (void)state; - }); - return DEVICE_OK; } int ChrolisShutter::Shutdown() { - ChrolisHub* pHub = static_cast(GetParentHub()); - if (pHub) - { - pHub->SetShutterCallback([](int , int) {}); - } return DEVICE_OK; } diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 44b210c4e..b00b49ac9 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -96,7 +96,6 @@ class ChrolisHub : public HubBase int DetectInstalledDevices(); void StatusChangedPollingThread(); - void SetShutterCallback(std::function); void SetStateBitsCallback(std::function); void SetStateCallback(std::function); @@ -107,7 +106,6 @@ class ChrolisHub : public HubBase // be accessed with pollingMutex_ held. std::mutex pollingMutex_; bool pollingStopRequested_ = false; - std::function shutterCallback_; std::function stateBitsCallback_; std::function stateCallback_; From 7fe237895a7b0bcd44ac9cd95e10da791a8e4083 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Tue, 21 Nov 2023 17:26:26 -0600 Subject: [PATCH 63/91] Provide correct readout for 'Device Status' The property now returns the same value as what is passed to OnPropertyChanged(). --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 22 ++++++++++++++++++- .../ThorlabsCHROLIS/ThorlabsChrolis.h | 5 ++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index d6ce0c706..dbc805dfe 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -168,7 +168,8 @@ int ChrolisHub::Initialize() return DEVICE_ERR; } - err = CreateStringProperty("Device Status", "No Error", true); + err = CreateStringProperty("Device Status", deviceStatus_.c_str(), true, + new CPropertyAction(this, &ChrolisHub::OnDeviceStatus)); if (err != 0) { LogMessage("Error with property set in hub initialize"); @@ -213,6 +214,20 @@ bool ChrolisHub::Busy() return false; } +int ChrolisHub::OnDeviceStatus(MM::PropertyBase *pProp, MM::ActionType eAct) +{ + if (eAct == MM::BeforeGet) + { + std::string status; + { + std::lock_guard lock(pollingMutex_); + status = deviceStatus_; + } + pProp->Set(status.c_str()); + } + return DEVICE_OK; +} + void ChrolisHub::StatusChangedPollingThread() { ViUInt32 tempStatus = 0; @@ -332,6 +347,11 @@ void ChrolisHub::StatusChangedPollingThread() } } } + + { + std::lock_guard lock(pollingMutex_); + deviceStatus_ = message; + } OnPropertyChanged("Device Status", message.c_str()); } Sleep(500); diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index b00b49ac9..7b2b05050 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -95,6 +95,8 @@ class ChrolisHub : public HubBase // HUB api int DetectInstalledDevices(); + int OnDeviceStatus(MM::PropertyBase* pProp, MM::ActionType eAct); + void StatusChangedPollingThread(); void SetStateBitsCallback(std::function); void SetStateCallback(std::function); @@ -103,9 +105,10 @@ class ChrolisHub : public HubBase std::thread updateThread_; // The following variables are shared with the polling thread and must only - // be accessed with pollingMutex_ held. + // be accessed with pollingMutex_ held (once the thread is started). std::mutex pollingMutex_; bool pollingStopRequested_ = false; + std::string deviceStatus_ = "No Error"; std::function stateBitsCallback_; std::function stateCallback_; From ec9101fce455265c8ee92ddd30dfe1e538b9a709 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Tue, 21 Nov 2023 17:45:33 -0600 Subject: [PATCH 64/91] Factor out DeviceStatusAsString() --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 104 +++++++----------- 1 file changed, 38 insertions(+), 66 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index dbc805dfe..e82834641 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -77,6 +77,42 @@ static std::array DecodeLEDStatesFromBits(std::uint8_t bits return ret; } +static std::string DeviceStatusAsString(std::uint32_t status) +{ + if (status == 0) + { + return "No Error"; + } + + static const std::array bitToMsg{ + "Box is Open", + "LLG not Connected", + "Interlock is Open", + "Using Default Adjustment", + "Box Overheated", + "LED Overheated", + "Invalid Box Setup", + }; + + std::string message; + for (int i = 0; i < bitToMsg.size(); i++) + { + if ((status & (1 << i)) != 0) + { + if (!message.empty()) + { + message += ", "; + } + message += bitToMsg[i]; + } + } + if (!message.empty()) + { + return message; + } + return "Unknown Status"; +} + //Hub Methods ChrolisHub::ChrolisHub() { @@ -230,8 +266,6 @@ int ChrolisHub::OnDeviceStatus(MM::PropertyBase *pProp, MM::ActionType eAct) void ChrolisHub::StatusChangedPollingThread() { - ViUInt32 tempStatus = 0; - std::string message; for (;;) { { @@ -244,7 +278,7 @@ void ChrolisHub::StatusChangedPollingThread() if (ChrolisDevice.IsDeviceConnected()) { - message.clear(); + ViUInt32 tempStatus = 0; auto err = ChrolisDevice.GetDeviceStatus(tempStatus); if (err != 0) { @@ -254,69 +288,6 @@ void ChrolisHub::StatusChangedPollingThread() const auto curStatus = currentDeviceStatusCode_; const bool statusChanged = curStatus != tempStatus; currentDeviceStatusCode_ = tempStatus; - if (curStatus == 0) - { - message += "No Error"; - } - else - { - if ((curStatus & (1 << 0)) >= 1) - { - message += "Box is Open"; - } - if ((curStatus & (1 << 1)) >= 1) - { - if (message.length() > 0) - { - message += ", "; - } - message += "LLG not Connected"; - } - if ((curStatus & (1 << 2)) >= 1) - { - if (message.length() > 0) - { - message += ", "; - } - message += "Interlock is Open"; - } - if ((curStatus & (1 << 3)) >= 1) - { - if (message.length() > 0) - { - message += ", "; - } - message += "Using Default Adjustment"; - } - if ((curStatus & (1 << 4)) >= 1) - { - if (message.length() > 0) - { - message += ", "; - } - message += "Box Overheated"; - } - if ((curStatus & (1 << 5)) >= 1) - { - if (message.length() > 0) - { - message += ", "; - } - message += "LED Overheated"; - } - if ((curStatus & (1 << 6)) >= 1) - { - if (message.length() > 0) - { - message += ", "; - } - message += "Invalid Box Setup"; - } - if (message.length() == 0) - { - message = "Unknown Status"; - } - } if (statusChanged) { if (curStatus != 0) @@ -348,6 +319,7 @@ void ChrolisHub::StatusChangedPollingThread() } } + std::string message = DeviceStatusAsString(curStatus); { std::lock_guard lock(pollingMutex_); deviceStatus_ = message; From c4ea40526f100cf656fe7902cf1c4cc5d6fa1471 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Wed, 22 Nov 2023 11:54:04 -0500 Subject: [PATCH 65/91] Updates to the polling thread structure --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index e82834641..c830c8d73 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -266,7 +266,7 @@ int ChrolisHub::OnDeviceStatus(MM::PropertyBase *pProp, MM::ActionType eAct) void ChrolisHub::StatusChangedPollingThread() { - for (;;) + for (;;) { { std::lock_guard lock(pollingMutex_); @@ -278,19 +278,19 @@ void ChrolisHub::StatusChangedPollingThread() if (ChrolisDevice.IsDeviceConnected()) { - ViUInt32 tempStatus = 0; - auto err = ChrolisDevice.GetDeviceStatus(tempStatus); + ViUInt32 newStatus = 0; + auto err = ChrolisDevice.GetDeviceStatus(newStatus); if (err != 0) { LogMessage("Error Getting Status"); return; } - const auto curStatus = currentDeviceStatusCode_; - const bool statusChanged = curStatus != tempStatus; - currentDeviceStatusCode_ = tempStatus; + const auto oldStatus = currentDeviceStatusCode_; + const bool statusChanged = oldStatus != newStatus; + currentDeviceStatusCode_ = newStatus; if (statusChanged) { - if (curStatus != 0) + if (newStatus != 0) { std::array tempEnableStates{}; ChrolisDevice.VerifyLEDEnableStatesWithLock(); @@ -316,15 +316,14 @@ void ChrolisHub::StatusChangedPollingThread() } } } + std::string message = DeviceStatusAsString(newStatus); + { + std::lock_guard lock(pollingMutex_); + deviceStatus_ = message; + } + OnPropertyChanged("Device Status", message.c_str()); } } - - std::string message = DeviceStatusAsString(curStatus); - { - std::lock_guard lock(pollingMutex_); - deviceStatus_ = message; - } - OnPropertyChanged("Device Status", message.c_str()); } Sleep(500); } From 143a1a66772123ec44c10019e254e5aaa8918dbc Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Wed, 22 Nov 2023 12:36:00 -0500 Subject: [PATCH 66/91] Update to ClearInstalledDevices --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index c830c8d73..6b4fb0865 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -134,20 +134,13 @@ ChrolisHub::ChrolisHub() int ChrolisHub::DetectInstalledDevices() { ClearInstalledDevices(); - InitializeModuleData();// make sure this method is called before we look for available devices - char hubName[MM::MaxStrLength]; - GetName(hubName); - for (unsigned i = 0; i < GetNumberOfDevices(); i++) - { - char deviceName[MM::MaxStrLength]; - bool success = GetDeviceName(i, deviceName, MM::MaxStrLength); - if (success && (strcmp(hubName, deviceName) != 0)) - { - MM::Device* pDev = CreateDevice(deviceName); - AddInstalledDevice(pDev); - } - } + MM::Device* pDev = CreateDevice(CHROLIS_SHUTTER_NAME); + AddInstalledDevice(pDev); + + pDev = CreateDevice(CHROLIS_STATE_NAME); + AddInstalledDevice(pDev); + return DEVICE_OK; } From 3e28092933899e90d1c60425c19e51134c5d893b Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Thu, 1 Feb 2024 14:27:13 -0500 Subject: [PATCH 67/91] final bug fixes --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 47 +++++++++---------- .../ThorlabsChrolisDeviceWrapper.cpp | 2 +- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index 6b4fb0865..a94a5320e 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -283,39 +283,36 @@ void ChrolisHub::StatusChangedPollingThread() currentDeviceStatusCode_ = newStatus; if (statusChanged) { - if (newStatus != 0) + std::array tempEnableStates{}; + ChrolisDevice.VerifyLEDEnableStatesWithLock(); + if (ChrolisDevice.GetLEDEnableStates(tempEnableStates) != 0) { - std::array tempEnableStates{}; - ChrolisDevice.VerifyLEDEnableStatesWithLock(); - if (ChrolisDevice.GetLEDEnableStates(tempEnableStates) != 0) + LogMessage("Error getting info from chrolis"); + } + else + { + std::lock_guard lock(pollingMutex_); + // Usually it is not a good idea to call arbitrary + // functions with a mutex held, but in this case we + // need to ensure that the callback remains valid. + if (stateBitsCallback_) { - LogMessage("Error getting info from chrolis"); + stateBitsCallback_(EncodeLEDStatesInBits(tempEnableStates)); } - else + if (stateCallback_) { - std::lock_guard lock(pollingMutex_); - // Usually it is not a good idea to call arbitrary - // functions with a mutex held, but in this case we - // need to ensure that the callback remains valid. - if (stateBitsCallback_) - { - stateBitsCallback_(EncodeLEDStatesInBits(tempEnableStates)); - } - if (stateCallback_) + for (int i = 0; i < NUM_LEDS; i++) { - for (int i = 0; i < NUM_LEDS; i++) - { - stateCallback_(i, tempEnableStates[i]); - } + stateCallback_(i, tempEnableStates[i]); } } - std::string message = DeviceStatusAsString(newStatus); - { - std::lock_guard lock(pollingMutex_); - deviceStatus_ = message; - } - OnPropertyChanged("Device Status", message.c_str()); } + std::string message = DeviceStatusAsString(newStatus); + { + std::lock_guard lock(pollingMutex_); + deviceStatus_ = message; + } + OnPropertyChanged("Device Status", message.c_str()); } } Sleep(500); diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 1b01ca440..17af20270 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -77,7 +77,7 @@ int ThorlabsChrolisDeviceWrapper::InitializeDevice(std::string serialNumber) { return err; } - if (strcmp((char*)serialNumber_, serialNumber.c_str())) + if (serialNumber.compare(serialNumber_) == 0) { found = true; break; From 4c1088be15bcd5c88eed4a5e006d5d9551fd2fe3 Mon Sep 17 00:00:00 2001 From: Matthew Anzelmi Date: Fri, 2 Feb 2024 15:24:17 -0500 Subject: [PATCH 68/91] Added license headers to the source files --- .../ThorlabsCHROLIS/ThorlabsChrolis.cpp | 22 +++++++++++++++++++ .../ThorlabsCHROLIS/ThorlabsChrolis.h | 22 +++++++++++++++++++ .../ThorlabsChrolisDeviceWrapper.cpp | 22 +++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp index a94a5320e..b6b684288 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.cpp @@ -1,3 +1,25 @@ +/////////////////////////////////////////////////////////////////////////////// +// FILE: ThorlabsChrolis.cpp +// PROJECT: Micro-Manager +// SUBSYSTEM: DeviceAdapters +//----------------------------------------------------------------------------- +// DESCRIPTION: Thorlabs device adapters: CHROLIS +// +// COPYRIGHT: Thorlabs Inc, 1999 +// +// LICENSE: This file is distributed under the BSD license. +// +// DISCLAIMER: This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// +// IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES. +// +// AUTHOR: Thorlabs Inc. Support Contact: TechSupport@Thorlabs.com +// + #include "ThorlabsChrolis.h" #include "ModuleInterface.h" diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h index 7b2b05050..f9e706799 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolis.h @@ -1,3 +1,25 @@ +/////////////////////////////////////////////////////////////////////////////// +// FILE: ThorlabsChrolis.h +// PROJECT: Micro-Manager +// SUBSYSTEM: DeviceAdapters +//----------------------------------------------------------------------------- +// DESCRIPTION: Thorlabs device adapters: CHROLIS +// +// COPYRIGHT: Thorlabs Inc, 1999 +// +// LICENSE: This file is distributed under the BSD license. +// +// DISCLAIMER: This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// +// IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES. +// +// AUTHOR: Thorlabs Inc. Support Contact: TechSupport@Thorlabs.com +// + #pragma once #include "DeviceBase.h" diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp index 17af20270..1af41f5ff 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsChrolisDeviceWrapper.cpp @@ -1,3 +1,25 @@ +/////////////////////////////////////////////////////////////////////////////// +// FILE: ThorlabsChrolisDeviceWrapper.cpp +// PROJECT: Micro-Manager +// SUBSYSTEM: DeviceAdapters +//----------------------------------------------------------------------------- +// DESCRIPTION: Thorlabs device adapters: CHROLIS +// +// COPYRIGHT: Thorlabs Inc, 1999 +// +// LICENSE: This file is distributed under the BSD license. +// +// DISCLAIMER: This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// +// IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES. +// +// AUTHOR: Thorlabs Inc. Support Contact: TechSupport@Thorlabs.com +// + #include "ThorlabsChrolis.h" #include From 200d17f5946904d11ef5a23f823087342c14af96 Mon Sep 17 00:00:00 2001 From: Hazen Babcock Date: Tue, 6 Feb 2024 16:53:25 -0500 Subject: [PATCH 69/91] Add Spinnaker device adapter to linux build. --- DeviceAdapters/Makefile.am | 1 + DeviceAdapters/Spinnaker/Makefile.am | 27 +++++++++++++++++++++++++++ DeviceAdapters/configure.ac | 1 + 3 files changed, 29 insertions(+) create mode 100644 DeviceAdapters/Spinnaker/Makefile.am diff --git a/DeviceAdapters/Makefile.am b/DeviceAdapters/Makefile.am index 5d590152f..4fc25eb8b 100644 --- a/DeviceAdapters/Makefile.am +++ b/DeviceAdapters/Makefile.am @@ -182,6 +182,7 @@ SUBDIRS = \ SmarActHCU-3D \ SouthPort \ SpectralLMM5 \ + Spinnaker \ StarlightXpress \ SutterLambda \ SutterLambda2 \ diff --git a/DeviceAdapters/Spinnaker/Makefile.am b/DeviceAdapters/Spinnaker/Makefile.am new file mode 100644 index 000000000..a8492d629 --- /dev/null +++ b/DeviceAdapters/Spinnaker/Makefile.am @@ -0,0 +1,27 @@ + +SPINNAKERLDFLAGS = +SPINLIBADD = +SPINLDFLAGS = +SPINNAKERCPPFLAGS = +AM_CXXFLAGS=$(MMDEVAPI_CXXFLAGS) +libmmgr_dal_SpinnakerCamera_la_SOURCES=SpinnakerCamera.cpp SpinnakerCamera.h +deviceadapter_LTLIBRARIES=libmmgr_dal_SpinnakerCamera.la + + +#if BUILD_SPINNAKER_LINUX +SPINNAKER_ROOT=/opt/spinnaker + +SPINNAKERLDFLAGS +=-Wl,--enable-new-dtags -Wl,-rpath,$(SPINNAKER_ROOT)/lib,-L$(SPINNAKER_ROOT)/lib + +SPINNAKERCPPFLAGS +=-I$(SPINNAKER_ROOT)/include +SPINNAKERLDLIBS =-lSpinnaker + +SPINLIBADD+=$(MMDEVAPI_LIBADD) $(SPINNAKERLDLIBS) +SPINLDFLAGS+=$(MMDEVAPI_LDFLAGS) $(SPINNAKERLDLIBS) $(SPINNAKERLDFLAGS) +#endif + +libmmgr_dal_SpinnakerCamera_la_CPPFLAGS=$(SPINNAKERCPPFLAGS) +libmmgr_dal_SpinnakerCamera_la_LIBADD=$(SPINLIBADD) +libmmgr_dal_SpinnakerCamera_la_LDFLAGS=$(SPINLDFLAGS) + +EXTRA_DIST = diff --git a/DeviceAdapters/configure.ac b/DeviceAdapters/configure.ac index 13ad336a2..73a38f3a9 100644 --- a/DeviceAdapters/configure.ac +++ b/DeviceAdapters/configure.ac @@ -619,6 +619,7 @@ m4_define([device_adapter_dirs], [m4_strip([ SmarActHCU-3D SouthPort SpectralLMM5 + Spinnaker Spot StarlightXpress SutterLambda From e65c6a2afa9a0e28062646ba1e9d35a6d1552ff4 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Tue, 6 Feb 2024 17:14:34 -0600 Subject: [PATCH 70/91] Use ThorlabsCHROLIS dependencies in 3rdparty --- DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj index ae223f7ae..4b12160c8 100644 --- a/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj +++ b/DeviceAdapters/ThorlabsCHROLIS/ThorlabsCHROLIS.vcxproj @@ -71,13 +71,13 @@ _DEBUG;THORLABSCHROLIS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true pch.h - C:\Program Files\IVI Foundation\VISA\Win64\Include;%(AdditionalIncludeDirectories) + $(MM_3RDPARTYPRIVATE)\Thorlabs\CHROLIS-3.0\Win64\Include;%(AdditionalIncludeDirectories) Windows true false - C:\Program Files\IVI Foundation\VISA\Win64\Lib_x64\msc;%(AdditionalLibraryDirectories) + $(MM_3RDPARTYPRIVATE)\Thorlabs\CHROLIS-3.0\Win64\Lib_x64\msc;%(AdditionalLibraryDirectories) TL6WL_64.lib;%(AdditionalDependencies) @@ -89,7 +89,7 @@ NDEBUG;THORLABSCHROLIS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true pch.h - C:\Program Files\IVI Foundation\VISA\Win64\Include;%(AdditionalIncludeDirectories) + $(MM_3RDPARTYPRIVATE)\Thorlabs\CHROLIS-3.0\Win64\Include;%(AdditionalIncludeDirectories) Windows @@ -97,7 +97,7 @@ true true false - C:\Program Files\IVI Foundation\VISA\Win64\Lib_x64\msc;%(AdditionalLibraryDirectories) + $(MM_3RDPARTYPRIVATE)\Thorlabs\CHROLIS-3.0\Win64\Lib_x64\msc;%(AdditionalLibraryDirectories) TL6WL_64.lib;%(AdditionalDependencies) From 308179c1a567c5abe90af0795a0820fccf746295 Mon Sep 17 00:00:00 2001 From: Lars Kool Date: Tue, 6 Feb 2024 17:03:53 +0100 Subject: [PATCH 71/91] Made Device Adapter compatible with the multi-camera utility --- DeviceAdapters/IDSPeak/Changelog.txt | 5 +- DeviceAdapters/IDSPeak/IDSPeak.cpp | 470 +++++++++++++++------------ DeviceAdapters/IDSPeak/IDSPeak.h | 42 ++- DeviceAdapters/IDSPeak/README.md | 16 +- 4 files changed, 309 insertions(+), 224 deletions(-) diff --git a/DeviceAdapters/IDSPeak/Changelog.txt b/DeviceAdapters/IDSPeak/Changelog.txt index 2cbc6ddfe..c9fe4ee13 100644 --- a/DeviceAdapters/IDSPeak/Changelog.txt +++ b/DeviceAdapters/IDSPeak/Changelog.txt @@ -5,4 +5,7 @@ Changelog IDSPeak: 2023.10.10 - Changed .dll to Release version (no longer requires MS Visual Studio to work) -- Added multi-camera support \ No newline at end of file +- Added multi-camera support + +2024.02.06 +- Multi-camera support is now compatible with the multicam utility \ No newline at end of file diff --git a/DeviceAdapters/IDSPeak/IDSPeak.cpp b/DeviceAdapters/IDSPeak/IDSPeak.cpp index 0eb68067c..4733a189f 100644 --- a/DeviceAdapters/IDSPeak/IDSPeak.cpp +++ b/DeviceAdapters/IDSPeak/IDSPeak.cpp @@ -35,6 +35,7 @@ #include "ModuleInterface.h" #include #include +#include "WriteCompactTiffRGB.h" #include #include @@ -47,35 +48,140 @@ const char* g_PixelType_32bitRGBA = "32bit RGBA"; // External names used used by the rest of the system // to load particular device from the "IDSPeak.dll" library const char* g_CameraDeviceName = "IDSCam"; +const char* g_IDSPeakHubName = "IDS Peak Hub"; /////////////////////////////////////////////////////////////////////////////// -// Exported MMDevice API +// MMDevice API /////////////////////////////////////////////////////////////////////////////// MODULE_API void InitializeModuleData() { - RegisterDevice(g_CameraDeviceName, MM::CameraDevice, "IDS camera"); + RegisterDevice(g_IDSPeakHubName, MM::HubDevice, "Hub for IDS cameras"); + RegisterDevice(g_CameraDeviceName, MM::CameraDevice, "Device adapter for IDS peak cameras"); } MODULE_API MM::Device* CreateDevice(const char* deviceName) { - if (deviceName == 0) - return 0; - - // decide which device class to create based on the deviceName parameter - if (strcmp(deviceName, g_CameraDeviceName) == 0) + cout << deviceName << endl; + if (!deviceName) + { + return 0; // Trying to create nothing, return nothing + } + if (strcmp(deviceName, g_IDSPeakHubName) == 0) + { + return new IDSPeakHub(); // Create Hub + } + if (strncmp(deviceName, g_CameraDeviceName, strlen(g_CameraDeviceName)) == 0) { - // create camera - return new CIDSPeak(); + string name_s = deviceName; + string substr = name_s.substr(strlen(g_CameraDeviceName), strlen(deviceName)); + int deviceIdx = stoi(substr); + //if (!deviceIdx) { return 0; } // If somehow the channel index is incorrect, return nothing + return new CIDSPeak(deviceIdx); // Create channel } + return 0; // If an unexpected name is provided, return nothing +} + +MODULE_API void DeleteDevice(MM::Device* device) +{ + delete device; +} + +////////////////////////////////////////////////////////////////////////////// +// IDSPeakHub class +// Hub for IDS Peak cameras +////////////////////////////////////////////////////////////////////////////// + +IDSPeakHub::IDSPeakHub() : + initialized_(false), + busy_(false), + nCameras_(0), + errorCode_(0), + testVal(10) +{ + CreateIntegerProperty("Test", testVal, false); +} + +IDSPeakHub::~IDSPeakHub() { + Shutdown(); +} + +/** +* Obtains device name. +* Required by the MM::Device API. +*/ +void IDSPeakHub::GetName(char* name) const +{ + // Return the name used to refer to this device adapter + string deviceName = g_IDSPeakHubName; + CDeviceUtils::CopyLimitedString(name, deviceName.c_str()); +} + +int IDSPeakHub::Initialize() +{ + if (initialized_) + return DEVICE_OK; + + // Initalize peak status + status = PEAK_STATUS_SUCCESS; + + // Initialize peak library + status = peak_Library_Init(); + if (status != PEAK_STATUS_SUCCESS) { return ERR_LIBRARY_NOT_INIT; } + + // Name + int ret = CreateStringProperty(MM::g_Keyword_Name, g_IDSPeakHubName, true); + if (DEVICE_OK != ret) + return ret; + + // Description + ret = CreateStringProperty(MM::g_Keyword_Description, "Hub for IDS Peak cameras", true); + if (DEVICE_OK != ret) + return ret; + + // Detect number of cameras + status = peak_CameraList_Update(NULL); + if (status != PEAK_STATUS_SUCCESS) { return ERR_CAMERA_NOT_FOUND; } + + status = peak_CameraList_Get(NULL, &nCameras_); // get length of camera list + if (status != PEAK_STATUS_SUCCESS) { return ERR_CAMERA_NOT_FOUND; } // exit program if no camera was found + + initialized_ = true; + return DEVICE_OK; +} + +/** +* Shuts down (unloads) the device. +* Required by the MM::Device API. +* Ideally this method will completely unload the device and release all resources. +* Shutdown() may be called multiple times in a row. +* After Shutdown() we should be allowed to call Initialize() again to load the device +* without causing problems. +*/ +int IDSPeakHub::Shutdown() +{ + peak_Library_Exit(); + initialized_ = false; + return DEVICE_OK; +} - // ...supplied name not recognized - return 0; +int IDSPeakHub::DetectInstalledDevices() +{ + ClearInstalledDevices(); + for (int i = 0; i < nCameras_; i++) + { + MM::Device* device = new CIDSPeak(i); + if (device) + { + AddInstalledDevice(device); + } + } + return DEVICE_OK; } -MODULE_API void DeleteDevice(MM::Device* pDevice) +bool IDSPeakHub::Busy() { - delete pDevice; + return false; } /////////////////////////////////////////////////////////////////////////////// @@ -92,7 +198,7 @@ MODULE_API void DeleteDevice(MM::Device* pDevice) * the constructor. We should do as little as possible in the constructor and * perform most of the initialization in the Initialize() method. */ -CIDSPeak::CIDSPeak() : +CIDSPeak::CIDSPeak(int idx) : CCameraBase (), initialized_(false), readoutUs_(0.0), @@ -121,7 +227,7 @@ CIDSPeak::CIDSPeak() : exposureInc_(1.0), exposureCur_(10.0), framerateCur_(10), - framerateMax_(200), + framerateMax_(1000), framerateMin_(0.1), framerateInc_(0.1), imageCounter_(0), @@ -134,6 +240,10 @@ CIDSPeak::CIDSPeak() : InitializeDefaultErrorMessages(); readoutStartTime_ = GetCurrentMMTime(); thd_ = new MySequenceThread(this); + deviceIdx_ = idx; + + // parent ID display + CreateHubIDProperty(); } /** @@ -145,6 +255,7 @@ CIDSPeak::CIDSPeak() : */ CIDSPeak::~CIDSPeak() { + Shutdown(); StopSequenceAcquisition(); delete thd_; } @@ -156,7 +267,9 @@ CIDSPeak::~CIDSPeak() void CIDSPeak::GetName(char* name) const { // Return the name used to referr to this device adapte - CDeviceUtils::CopyLimitedString(name, g_CameraDeviceName); + string deviceName = g_CameraDeviceName; + deviceName.append(std::to_string(deviceIdx_)); + CDeviceUtils::CopyLimitedString(name, deviceName.c_str()); } /** @@ -173,58 +286,35 @@ int CIDSPeak::Initialize() if (initialized_) return DEVICE_OK; + IDSPeakHub* pHub = static_cast(GetParentHub()); + if (pHub) + { + char hubLabel[MM::MaxStrLength]; + pHub->GetLabel(hubLabel); + SetParentID(hubLabel); // for backward comp. + } + else + LogMessage(NoHubError); + // Initalize peak status status = PEAK_STATUS_SUCCESS; - // Initialize peak library - status = peak_Library_Init(); - if (status != PEAK_STATUS_SUCCESS) { return ERR_LIBRARY_NOT_INIT; } - - // update camera list + // Retrieve Cam handle + size_t nCameras = 0; status = peak_CameraList_Update(NULL); if (status != PEAK_STATUS_SUCCESS) { return ERR_CAMERA_NOT_FOUND; } - // get length of camera list - size_t cameraListLength = 0; - status = peak_CameraList_Get(NULL, &cameraListLength); - - // exit program if no camera was found - if (status != PEAK_STATUS_SUCCESS) { return ERR_CAMERA_NOT_FOUND; } + status = peak_CameraList_Get(NULL, &nCameras); // get length of camera list + if (status != PEAK_STATUS_SUCCESS) { return ERR_CAMERA_NOT_FOUND; } // exit program if no camera was found - // allocate memory for the camera list peak_camera_descriptor* cameraList = (peak_camera_descriptor*)calloc( - cameraListLength, sizeof(peak_camera_descriptor)); + nCameras, sizeof(peak_camera_descriptor)); // allocate memory for the camera list + status = peak_CameraList_Get(cameraList, &nCameras); // get the camera list + if (status != PEAK_STATUS_SUCCESS) { return ERR_CAMERA_NOT_FOUND; } // exit program if no camera was found - // get the camera list - status = peak_CameraList_Get(cameraList, &cameraListLength); - if (status != PEAK_STATUS_SUCCESS) { return ERR_CAMERA_NOT_FOUND; } - - // Open the cameras and assign cameraIDs - vector cameraIndices; - CPropertyAction* pAct = new CPropertyAction(this, &CIDSPeak::OnChangeCamera); - int nRet = CreateStringProperty(MM::g_Keyword_CameraID, "0", false, pAct); - for (int i = 0; i < cameraListLength; i++) - { - if (peak_Camera_GetAccessStatus(cameraList[i].cameraID) == PEAK_ACCESS_READWRITE) - { - hCams.push_back(PEAK_INVALID_HANDLE); - status = peak_Camera_Open(cameraList[i].cameraID, &hCams[i]); - if (status == PEAK_STATUS_SUCCESS) - { - cameraIndices.push_back(CDeviceUtils::ConvertToString(i)); - } - } - } - // free the camera list, not needed any longer - free(cameraList); - if (cameraIndices.size() == 0) { return ERR_CAMERA_NOT_FOUND; } - - CamID_ = stoi(cameraIndices[0]); - - nRet = SetAllowedValues(MM::g_Keyword_CameraID, cameraIndices); - nCameras_ = cameraIndices.size(); - nRet = CreateIntegerProperty("nCameras", (long)nCameras_, true); - hCam = hCams[CamID_]; + status = peak_Camera_Open(cameraList[deviceIdx_].cameraID, &hCam); // Get the camera handle + if (status != PEAK_STATUS_SUCCESS) { return ERR_CAMERA_NOT_FOUND; } // exit if this is unsuccessful + free(cameraList); // free the camera list, not needed any longer // check which camera was actually opened peak_camera_descriptor cameraInfo; @@ -233,9 +323,29 @@ int CIDSPeak::Initialize() // set property list // ----------------- + + + + + + + + + + + + + + + + + + + + // Name - nRet = CreateStringProperty(MM::g_Keyword_Name, g_CameraDeviceName, true); + int nRet = CreateStringProperty(MM::g_Keyword_Name, g_CameraDeviceName, true); assert(nRet == DEVICE_OK); // Description @@ -244,34 +354,72 @@ int CIDSPeak::Initialize() // CameraName modelName_ = cameraInfo.modelName; - pAct = new CPropertyAction(this, &CIDSPeak::OnModelName); - nRet = CreateStringProperty(MM::g_Keyword_CameraName, "model name placeholder", true, pAct); + nRet = CreateStringProperty(MM::g_Keyword_CameraName, modelName_.c_str(), true); assert(nRet == DEVICE_OK); // SerialNumber serialNum_ = cameraInfo.serialNumber; - pAct = new CPropertyAction(this, &CIDSPeak::OnSerialNumber); - nRet = CreateStringProperty("Serial Number", "serial number placeholder", true, pAct); + nRet = CreateStringProperty("Serial Number", serialNum_.c_str(), true); assert(nRet == DEVICE_OK); - // binning - pAct = new CPropertyAction(this, &CIDSPeak::OnBinning); + // Binning + CPropertyAction* pAct = new CPropertyAction(this, &CIDSPeak::OnBinning); nRet = CreateIntegerProperty(MM::g_Keyword_Binning, 0, false, pAct); assert(nRet == DEVICE_OK); + nRet = SetAllowedBinning(); + if (nRet != DEVICE_OK) { return nRet; } - // pixel type + // Pixel type pAct = new CPropertyAction(this, &CIDSPeak::OnPixelType); nRet = CreateStringProperty(MM::g_Keyword_PixelType, "pixeltype placeholder", false, pAct); assert(nRet == DEVICE_OK); + vector pixelTypeValues; + pixelTypeValues.push_back(g_PixelType_8bit); + if (isColorCamera()) + { + pixelTypeValues.push_back(g_PixelType_32bitRGBA); + } + nRet = ClearAllowedValues(MM::g_Keyword_PixelType); + nRet = SetAllowedValues(MM::g_Keyword_PixelType, pixelTypeValues); + if (nRet != DEVICE_OK) + return nRet; + + //peak_pixel_format format; + //status = peak_PixelFormat_Get(hCam, &format); + //if (format == PEAK_PIXEL_FORMAT_MONO8) + //{ + // pixelType_ = g_PixelType_8bit; + // nComponents_ = 1; + // SetProperty(MM::g_Keyword_PixelType, g_PixelType_8bit); + //} + //else + //{ + // pixelType_ = g_PixelType_32bitRGBA; + // nComponents_ = 8; + // SetProperty(MM::g_Keyword_PixelType, g_PixelType_32bitRGBA); + //} // Exposure time nRet = CreateFloatProperty(MM::g_Keyword_Exposure, exposureCur_, false); assert(nRet == DEVICE_OK); + status = peak_ExposureTime_GetRange(hCam, &exposureMin_, &exposureMax_, &exposureInc_); + if (status != PEAK_STATUS_SUCCESS) { return ERR_DEVICE_NOT_AVAILABLE; } + exposureMin_ /= 1000; + exposureMax_ /= 1000; + exposureInc_ /= 1000; + nRet = SetPropertyLimits(MM::g_Keyword_Exposure, exposureMin_, exposureMax_); + assert(nRet == DEVICE_OK); + status = peak_ExposureTime_Get(hCam, &exposureCur_); + exposureCur_ /= 1000; // Frame rate pAct = new CPropertyAction(this, &CIDSPeak::OnFrameRate); nRet = CreateFloatProperty("MDA framerate", 1, false, pAct); assert(nRet == DEVICE_OK); + status = peak_FrameRate_GetRange(hCam, &framerateMin_, &framerateMax_, &framerateInc_); + nRet = SetPropertyLimits("MDA framerate", framerateMin_, framerateMax_); + assert(nRet == DEVICE_OK); + status = peak_FrameRate_Get(hCam, &framerateCur_); // Auto white balance initializeAutoWBConversion(); @@ -339,6 +487,7 @@ int CIDSPeak::Initialize() // CCD size of the camera we are modeling // getSensorInfo needs to be called before the CreateIntegerProperty // calls, othewise the default (512) values will be displayed. + nRet = getSensorInfo(); pAct = new CPropertyAction(this, &CIDSPeak::OnCameraCCDXSize); nRet = CreateIntegerProperty("OnCameraCCDXSize", 512, true, pAct); assert(nRet == DEVICE_OK); @@ -378,8 +527,26 @@ int CIDSPeak::Initialize() // initialize image buffer GenerateEmptyImage(img_); - // initialize first camera - nRet = cameraChanged(); + // Obtain ROI properties + // The SetROI function used the CCD size, so this function should + // always be put after the getSensorInfo call + // It is assumed that the maximum ROI size is the size of the CCD + // and that the increment in X and Y are identical + // Also the ROI needs to be initialized beforehand, hence it should be + // placed after GenerateEmptyImage() + peak_size roi_size_min; + peak_size roi_size_max; + peak_size roi_size_inc; + peak_roi roi; + status = peak_ROI_Size_GetRange(hCam, &roi_size_min, &roi_size_max, &roi_size_inc); + if (status != PEAK_STATUS_SUCCESS) { return DEVICE_ERR; } + roiMinSizeX_ = roi_size_min.width; + roiMinSizeY_ = roi_size_min.height; + roiInc_ = roi_size_inc.height; + status = peak_ROI_Get(hCam, &roi); + SetROI(roi.offset.x, roi.offset.y, roi.size.width, roi.size.height); + img_.Resize(roi.size.width, roi.size.height, nComponents_ * (bitDepth_ / 8)); + if (nRet != DEVICE_OK) { return nRet; } // synchronize all properties @@ -402,17 +569,9 @@ int CIDSPeak::Initialize() */ int CIDSPeak::Shutdown() { - // Close open camera and set pointer to NULL - for (size_t i = 0; i < nCameras_; i++) - peak_Camera_Close(hCams[i]); - nCameras_ = 0; - hCam = NULL; - - // Close peak library - status = peak_Library_Exit(); - + if (initialized_ == false) { return DEVICE_OK; } + cleanExit(); initialized_ = false; - return DEVICE_OK; } @@ -914,6 +1073,13 @@ int CIDSPeak::SendExposureSequence() const { return DEVICE_OK; } +/** +* Function that requests the possible binning values from the camera driver +* It implicitly assumes that the allowed binning factors in X and Y are the same +* It then restricts the allowed binning values to the possible ones +* It also checks whether the current binning value is allowed. If, somehow, it +* is not, it will set it to 1 (which it assumes is always available) +**/ int CIDSPeak::SetAllowedBinning() { int nRet = DEVICE_OK; @@ -1062,7 +1228,7 @@ int CIDSPeak::RunSequenceOnThread() } } - uint32_t three_frame_times_timeout_ms = (uint32_t)(3000 / framerateCur_ + 10); + uint32_t three_frame_times_timeout_ms = (uint32_t)(3000 / framerateCur_); peak_frame_handle hFrame; status = peak_Acquisition_WaitForFrame(hCam, three_frame_times_timeout_ms, &hFrame); @@ -1251,9 +1417,9 @@ int CIDSPeak::OnBinning(MM::PropertyBase* pProp, MM::ActionType eAct) { case MM::AfterSet: { - if (IsCapturing()) - return DEVICE_CAMERA_BUSY_ACQUIRING; - + // Should not change binning during acquisition + if (IsCapturing()) { return DEVICE_CAMERA_BUSY_ACQUIRING; } + // the user just set the new value for the property, so we have to // apply this value to the 'hardware'. long binFactor; @@ -1688,24 +1854,6 @@ int CIDSPeak::OnIsSequenceable(MM::PropertyBase* pProp, MM::ActionType eAct) return DEVICE_OK; } -int CIDSPeak::OnChangeCamera(MM::PropertyBase* pProp, MM::ActionType eAct) -{ - int nRet = DEVICE_OK; - if (eAct == MM::BeforeGet) - { - pProp->Set(CDeviceUtils::ConvertToString(CamID_)); - } - else if (eAct == MM::AfterSet) - { - string CamID_temp; - pProp->Get(CamID_temp); - CamID_ = stoi(CamID_temp); - hCam = hCams[CamID_]; - cameraChanged(); - } - return nRet; -} - /////////////////////////////////////////////////////////////////////////////// // Private CIDSPeak methods /////////////////////////////////////////////////////////////////////////////// @@ -1752,31 +1900,21 @@ peak_status CIDSPeak::getTemperature(double* sensorTemp) return status; } +/** +* Cleanly exit camera, called during Shutdown() +**/ int CIDSPeak::cleanExit() { - - // Clean up before exit - // Stop acquisition, if running - if (peak_Acquisition_IsStarted(hCam)) - { - // Stop acquisition - status = peak_Acquisition_Stop(hCam); - checkForSuccess(status, PEAK_TRUE); - } - - // Close camera, if open - if (hCam != PEAK_INVALID_HANDLE) + if (hCam != PEAK_INVALID_HANDLE && hCam != NULL) // Check if camera is open { - // Close Camera - status = peak_Camera_Close(hCam); - checkForSuccess(status, PEAK_TRUE); + if (peak_Acquisition_IsStarted(hCam)) // Check if camera is acquiring data + { + status = peak_Acquisition_Stop(hCam); // Stop acquisition + } + status = peak_Camera_Close(hCam); // Close Camera } - - // Exit library - status = peak_Library_Exit(); - checkForSuccess(status, PEAK_TRUE); - - return status; + hCam = NULL; + return DEVICE_OK; } //Returns PEAK_TRUE, if function was successful. @@ -1993,95 +2131,7 @@ int CIDSPeak::framerateSet(double framerate) // Actual initialization of the camera (is called every time camera is swapped). int CIDSPeak::cameraChanged() { - int nRet = DEVICE_OK; - peak_camera_descriptor cameraInfo; - status = peak_Camera_GetDescriptor(peak_Camera_ID_FromHandle(hCam), &cameraInfo); - if (status != PEAK_STATUS_SUCCESS) { return ERR_CAMERA_NOT_FOUND; } - - // CameraName - modelName_ = cameraInfo.modelName; - // CameraID - serialNum_ = cameraInfo.serialNumber; - - // Binning - nRet = SetAllowedBinning(); - if (nRet != DEVICE_OK) - return nRet; - uint32_t binx; - uint32_t biny; - status = peak_Binning_Get(hCam, &binx, &biny); - binSize_ = (long)binx; - nRet = SetBinning(binSize_); - - // PixelType, assumes 8bit mono is always possible - vector pixelTypeValues; - pixelTypeValues.push_back(g_PixelType_8bit); - if (isColorCamera()) - { - pixelTypeValues.push_back(g_PixelType_32bitRGBA); - } - nRet = ClearAllowedValues(MM::g_Keyword_PixelType); - nRet = SetAllowedValues(MM::g_Keyword_PixelType, pixelTypeValues); - if (nRet != DEVICE_OK) - return nRet; - - peak_pixel_format format; - status = peak_PixelFormat_Get(hCam, &format); - if (format == PEAK_PIXEL_FORMAT_MONO8) - { - pixelType_ = g_PixelType_8bit; - nComponents_ = 1; - SetProperty(MM::g_Keyword_PixelType, g_PixelType_8bit); - } - else - { - pixelType_ = g_PixelType_32bitRGBA; - nComponents_ = 8; - SetProperty(MM::g_Keyword_PixelType, g_PixelType_32bitRGBA); - } - - // Exposure time - status = peak_ExposureTime_GetRange(hCam, &exposureMin_, &exposureMax_, &exposureInc_); - if (status != PEAK_STATUS_SUCCESS) { return ERR_DEVICE_NOT_AVAILABLE; } - exposureMin_ /= 1000; - exposureMax_ /= 1000; - exposureInc_ /= 1000; - nRet = SetPropertyLimits(MM::g_Keyword_Exposure, exposureMin_, exposureMax_); - if (nRet != DEVICE_OK) - return nRet; - status = peak_ExposureTime_Get(hCam, &exposureCur_); - exposureCur_ /= 1000; - - // Framerate range - status = peak_FrameRate_GetRange(hCam, &framerateMin_, &framerateMax_, &framerateInc_); - nRet = SetPropertyLimits("MDA framerate", framerateMin_, framerateMax_); - status = peak_FrameRate_Get(hCam, &framerateCur_); - - // Get sensor size - nRet = getSensorInfo(); - - // Obtain ROI properties - // The SetROI function used the CCD size, so this function should - // always be put after the getSensorInfo call - // It is assumed that the maximum ROI size is the size of the CCD - // and that the increment in X and Y are identical - peak_size roi_size_min; - peak_size roi_size_max; - peak_size roi_size_inc; - peak_roi roi; - status = peak_ROI_Size_GetRange(hCam, &roi_size_min, &roi_size_max, &roi_size_inc); - if (status != PEAK_STATUS_SUCCESS) { return DEVICE_ERR; } - roiMinSizeX_ = roi_size_min.width; - roiMinSizeY_ = roi_size_min.height; - roiInc_ = roi_size_inc.height; - status = peak_ROI_Get(hCam, &roi); - SetROI(roi.offset.x, roi.offset.y, roi.size.width, roi.size.height); - img_.Resize(roi.size.width, roi.size.height, nComponents_ * (bitDepth_ / 8)); - - if (nRet != DEVICE_OK) - return nRet; - return nRet; } // Checks if camera supportes color image formats diff --git a/DeviceAdapters/IDSPeak/IDSPeak.h b/DeviceAdapters/IDSPeak/IDSPeak.h index 5210be769..b67a882cc 100644 --- a/DeviceAdapters/IDSPeak/IDSPeak.h +++ b/DeviceAdapters/IDSPeak/IDSPeak.h @@ -69,6 +69,43 @@ using namespace std; const char* NoHubError = "Parent Hub not defined."; +////////////////////////////////////////////////////////////////////////////// +// IDSPeakHub class +// Hub for IDS Peak cameras +////////////////////////////////////////////////////////////////////////////// + +class IDSPeakHub : public HubBase +{ +public: + IDSPeakHub(); + ~IDSPeakHub(); + + // Device API + int Initialize(); + int Shutdown(); + void GetName(char* pName) const; + bool Busy(); + + // HUB api + int DetectInstalledDevices(); + + // Hub parameters + peak_status status = PEAK_STATUS_SUCCESS; + size_t nCameras_ = 0; + vector hCams; + int testVal; + + // Hub action handlers + + // Hub members + +private: + bool initialized_; + bool busy_; + unsigned char errorCode_; + string unit_; +}; + ////////////////////////////////////////////////////////////////////////////// // CIDSPeak class ////////////////////////////////////////////////////////////////////////////// @@ -78,7 +115,7 @@ class MySequenceThread; class CIDSPeak : public CCameraBase { public: - CIDSPeak(); + CIDSPeak(int deviceIdx); ~CIDSPeak(); // MMDevice API @@ -86,11 +123,10 @@ class CIDSPeak : public CCameraBase int Initialize(); int Shutdown(); - vector hCams; peak_camera_handle hCam = PEAK_INVALID_HANDLE; peak_status status = PEAK_STATUS_SUCCESS; void GetName(char* name) const; - int CamID_; + int deviceIdx_; // MMCamera API // ------------ diff --git a/DeviceAdapters/IDSPeak/README.md b/DeviceAdapters/IDSPeak/README.md index 4bd26162c..86d21a1f7 100644 --- a/DeviceAdapters/IDSPeak/README.md +++ b/DeviceAdapters/IDSPeak/README.md @@ -1,15 +1,14 @@ # Micro-Manager Device Adapter for IDS Peak cameras Micro-Manager is an application to control microscope hardware, such as cameras. It includes a hardware abstraction layer written in C++ and a user interface written in Java. Micro-Manager needs a translation layer between the driver (written by the manufacturer) and Micro-Manager's C++ backend. This translation layer is called a "Device Adapter" (Micro-Manager has chosen not to call it a "Driver" to distinguish it from the libraries provided by the manufacturers of the devices). -This GitHub repository contains a Device Adapter for IDS cameras. It contains both the already built .dll (mmgr_dal_IDSPeak.dll) and the C++/h files to build it yourself. Instructions can be found below. The Device Adapter was tested with an IDS USB3-3040CP-HQ Rev 2.2 on Windows 10, and not with any other camera or operating system. Although camera model should not matter, there might be assumed default settings that might not be universally present. A different operating system could be more problematic. +This GitHub repository contains a Device Adapter for IDS cameras. It contains both the already built .dll (mmgr_dal_IDSPeak.dll) and the C++/h files to build it yourself. Instructions can be found below. The Device Adapter was tested with multiple IDS USB3-3040CP-HQ Rev 2.2 on Windows 10, and not with any other camera or operating system. Although camera model should not matter, there might be assumed default settings that might not be universally present. A different operating system could be more problematic. ## Using the precompiled .dll -The following steps will guide you through the process of "installing" the .dll, allowing you to use IDS cameras with Micro-Manager. -1. Clone/download this repository. +As of Dec 11 2023, the IDS Peak device adapter is included in the nightly build of Micro-Manager. Greatly simplifying the use of IDS cameras with Micro-Manager. The following steps will guide you through the process of "installing" the .dll, allowing you to use IDS cameras with Micro-Manager. +1. Install the most recent nightly build of Micro-Manager (or at least a version after Dec 11 2023). **NOTE: it is NOT included in version 2.0.0, as it dates from July 13, 2021. Use the following link to the latest nightly builds instead** https://micro-manager.org/Micro-Manager_Nightly_Builds. 2. Download and install "IDS Peak" from the IDS website https://en.ids-imaging.com/downloads.html -3. Copy the "mmgr_dal_IDSPeak.dll" into the root folder of Micro-Manager (e.g. "C:\Program Files\Micro-Manager-2.0") -4. Copy all .dll and .lib files from the IDS Peak software into the root folder of Micro-Manager. The .dll and .lib files can be found in ".\PATH_TO_INSTALL\IDS\ids_peak\comfort_sdk\api\lib\x86_64" (.\PATH_TO_INSTALL is the folder you installed IDS Peak, e.g. "C:\Program Files"). -5. Start Micro-Manager and either walk through the Hardware configuration wizard, or load the .cfg file included in this repository. Make sure the camera is plugged into a USB3 port before launching Micro-Manager. +3. Copy all .dll and .lib files from the IDS Peak software into the root folder of Micro-Manager. The .dll and .lib files can be found in ".\PATH_TO_INSTALL\IDS\ids_peak\comfort_sdk\api\lib\x86_64" (.\PATH_TO_INSTALL is the folder you installed IDS Peak, e.g. "C:\Program Files"). +4. Start Micro-Manager and either walk through the Hardware configuration wizard. Make sure the camera is plugged into a USB3 port before launching Micro-Manager. ## Building the device adapter yourself More advanced users could build the device adapter themselves, allowing them to tailor the device adapter to their needs. If you just plan to use the default device adapter, there is no benefit to building it yourself. Below you will find a brief walkthrough on building the device adapter. @@ -25,20 +24,17 @@ More advanced users could build the device adapter themselves, allowing them to ## Features - Imaging in grayscale and 32bit RGBA. One can switch between 8bit grayscale and 32bit RGBA in **Device -> Device Property Browser -> IDSCam - PixelType** -- Multi-camera support. One can switch between cameras using the dropdown in **Device -> Device Property Browser -> IDSCam-CameraID**. The actual ID is an arbitrary zero-indexed identifier. To know which camera is actually open, you can check the **IDSCam-Serial Number** and/or **IDSCam-CameraName**, and compare them to the model and serialnumber of the cameras. Note that switching cameras does not automatically switch settings. +- Multi-camera support. One can load multiple cameras cameras from the Hardware configuration wizard. The settings of each camera can be changed separately. To record simultaneously with IDS cameras, one should also load the "Utilities->Multi camera" Device Adapter. The "Multi Camera" device adapter should be listed as the default camera. After finishing the "Hardware configuration wizard". One should go to the "Device Property Browser" and under "Multi Camera - Physical Camera X" select the desired cameras. ## Known limitations - **The maximum framerate of the 32bit RBGA pixel format is much lower than advertized or with IDS Peak Cockpit.** - This is indeed true, the problem is that the camera doesn't support recording BGRA8, which is the only accepted color format of Micro-Manager. Hence, the image has to be recorded in a different pixel format (in this case Bayer RG8) and then converted to BGRA8 on the fly. The maximum obtainable framerate then depends heavily on the (single core) processing speed of your PC. A potential solution is to not do the conversion (just pass the raw bayer data) and perform the debayering after all data is collected. However his methods is not yet implemented. - **The minimum interval during the Multi-Dimensional Acquisition (MDA) is approximately 200 ms, even at low exposure times (e.g. 10 ms)** - This is a limitation of how MDA events are processed. When the interval is set to less than the exposure time, it will record at the maximum framerate possible ~1/exposureTime. Otherwise it will perform something like a timelapse, where it will start the process of acquiring an image after the interval has passed. Sadly the second process has a lot of overhead, which leads to a maximum framerate of ~5 fps. We're currently thinking of ways to fix this. -- **When switching to a cameras, some settings are reset, while others are kept** - - Currently, when switching cameras, the device adapter asks the new camera for its current settings and adapts displayed settings accordingly. Some settings are kept from session to session (typically PixelType, exposureTime and frameRate), while most others are not. If this heavily inhibits the work of others, we could work on a solution where all settings are kept whithin each session, and/or maybe load settings from a config-file. - **When MM is open, I can't open any IDS camera in another software (e.g. IDS Peak Cockpit)** - Currently, when MM is started, it opens all cameras and keeps them open untill MM is closed. This allows quicker switching between cameras. But this means that none of the other softwares can communicate with any of the connected IDS cameras (even when they are seemingly not in use by MM). ## Future features -- Rembering last settings of each camera instance - More support for other pixel types (10/12 bit grayscale/color) - Recording Bayer / Packed images in RAW format (to post-process afterwards) - Give more meaningful error messages From a9bb08ba5d897b778f54a5c78aee06eb1a537728 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Tue, 6 Feb 2024 17:29:56 -0600 Subject: [PATCH 72/91] IDSPeak: Remove unused #include --- DeviceAdapters/IDSPeak/IDSPeak.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/DeviceAdapters/IDSPeak/IDSPeak.cpp b/DeviceAdapters/IDSPeak/IDSPeak.cpp index 4733a189f..310ade461 100644 --- a/DeviceAdapters/IDSPeak/IDSPeak.cpp +++ b/DeviceAdapters/IDSPeak/IDSPeak.cpp @@ -35,7 +35,6 @@ #include "ModuleInterface.h" #include #include -#include "WriteCompactTiffRGB.h" #include #include From 3197a8868e76c205ac527080e134ad96fbafc4b8 Mon Sep 17 00:00:00 2001 From: Hazen Babcock Date: Tue, 6 Feb 2024 21:38:10 -0500 Subject: [PATCH 73/91] Initial work on conditional build of Spinnaker camere device. --- DeviceAdapters/Spinnaker/Makefile.am | 17 +++++++++-------- DeviceAdapters/configure.ac | 11 +++++++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/DeviceAdapters/Spinnaker/Makefile.am b/DeviceAdapters/Spinnaker/Makefile.am index a8492d629..039dd0cc6 100644 --- a/DeviceAdapters/Spinnaker/Makefile.am +++ b/DeviceAdapters/Spinnaker/Makefile.am @@ -8,17 +8,18 @@ libmmgr_dal_SpinnakerCamera_la_SOURCES=SpinnakerCamera.cpp SpinnakerCamera.h deviceadapter_LTLIBRARIES=libmmgr_dal_SpinnakerCamera.la -#if BUILD_SPINNAKER_LINUX -SPINNAKER_ROOT=/opt/spinnaker +if BUILD_SPINNAKER_LINUX + SPINNAKER_ROOT=/opt/spinnaker -SPINNAKERLDFLAGS +=-Wl,--enable-new-dtags -Wl,-rpath,$(SPINNAKER_ROOT)/lib,-L$(SPINNAKER_ROOT)/lib + SPINNAKERLDFLAGS +=-Wl,--enable-new-dtags -Wl,-rpath,$(SPINNAKER_ROOT)/lib,-L$(SPINNAKER_ROOT)/lib -SPINNAKERCPPFLAGS +=-I$(SPINNAKER_ROOT)/include -SPINNAKERLDLIBS =-lSpinnaker + SPINNAKERCPPFLAGS +=-I$(SPINNAKER_ROOT)/include + SPINNAKERLDLIBS =-lSpinnaker + + SPINLIBADD+=$(MMDEVAPI_LIBADD) $(SPINNAKERLDLIBS) + SPINLDFLAGS+=$(MMDEVAPI_LDFLAGS) $(SPINNAKERLDLIBS) $(SPINNAKERLDFLAGS) +endif -SPINLIBADD+=$(MMDEVAPI_LIBADD) $(SPINNAKERLDLIBS) -SPINLDFLAGS+=$(MMDEVAPI_LDFLAGS) $(SPINNAKERLDLIBS) $(SPINNAKERLDFLAGS) -#endif libmmgr_dal_SpinnakerCamera_la_CPPFLAGS=$(SPINNAKERCPPFLAGS) libmmgr_dal_SpinnakerCamera_la_LIBADD=$(SPINLIBADD) diff --git a/DeviceAdapters/configure.ac b/DeviceAdapters/configure.ac index 73a38f3a9..935a3424a 100644 --- a/DeviceAdapters/configure.ac +++ b/DeviceAdapters/configure.ac @@ -394,6 +394,17 @@ AS_IF([test "x$want_opencv" != xno], AM_CONDITIONAL([BUILD_OPENCV], [test "x$use_opencv" = xyes]) + +# Spinnaker (FLIR). +AC_MSG_CHECKING(for Spinnaker_Linux) +AM_CONDITIONAL([BUILD_SPINNAKER_LINUX],[test -f "/opt/spinnaker/include/Spinnaker.h"]) +if test -f "/opt/spinnaker/include/Spinnaker.h"; then + AC_MSG_RESULT([found]) +else + AC_MSG_RESULT([not found]) +fi + + # Vimba X (Allied Vision) SDK MM_ARG_WITH_OPTIONAL_LIB([Vimba X], [vimba-x], [VIMBA_X]) AS_IF([test "x$want_vimba_x" != xno], From a895608da824a6ec18772c709cd46f91775f6e01 Mon Sep 17 00:00:00 2001 From: Hazen Babcock Date: Tue, 6 Feb 2024 21:39:05 -0500 Subject: [PATCH 74/91] Add conditional definition of SpinnakerAcquisitionThread. --- DeviceAdapters/Spinnaker/SpinnakerCamera.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/DeviceAdapters/Spinnaker/SpinnakerCamera.h b/DeviceAdapters/Spinnaker/SpinnakerCamera.h index 482805bc2..bd2e7d445 100644 --- a/DeviceAdapters/Spinnaker/SpinnakerCamera.h +++ b/DeviceAdapters/Spinnaker/SpinnakerCamera.h @@ -11,6 +11,10 @@ #define GENICAM Spinnaker::GenICam #define SPKR_ERROR 10002 + +class SpinnakerAcquisitionThread; + + class SpinnakerCamera : public CCameraBase { public: From 25e983fea3aafe63ad8b81350706850f748f4d79 Mon Sep 17 00:00:00 2001 From: Hazen Babcock Date: Tue, 6 Feb 2024 21:45:57 -0500 Subject: [PATCH 75/91] Use std::min to fix gcc compile error. Replace NULL with nullptr to reduce warnings. --- DeviceAdapters/Spinnaker/SpinnakerCamera.cpp | 34 ++++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/DeviceAdapters/Spinnaker/SpinnakerCamera.cpp b/DeviceAdapters/Spinnaker/SpinnakerCamera.cpp index f3aeac44d..bd44d57bc 100644 --- a/DeviceAdapters/Spinnaker/SpinnakerCamera.cpp +++ b/DeviceAdapters/Spinnaker/SpinnakerCamera.cpp @@ -88,7 +88,7 @@ std::vector GetSpinnakeerCameraNamesAndSNs() } camList.Clear(); - system = NULL; + system = nullptr; return out; } @@ -124,10 +124,10 @@ MODULE_API void DeleteDevice(MM::Device* pDevice) SpinnakerCamera::SpinnakerCamera(GENICAM::gcstring name) : CCameraBase(), - m_system(NULL), - m_cam(NULL), - m_imageBuff(NULL), - m_aqThread(NULL) + m_system(nullptr), + m_cam(nullptr), + m_imageBuff(nullptr), + m_aqThread(nullptr) { InitializeDefaultErrorMessages(); @@ -178,7 +178,7 @@ int SpinnakerCamera::Initialize() } m_system = SPKR::System::GetInstance(); - if (m_system == NULL) + if (m_system == nullptr) { SetErrorText(SPKR_ERROR, "Spinnaker System Object Pointer is Null!"); return SPKR_ERROR; @@ -215,7 +215,7 @@ int SpinnakerCamera::Initialize() } camList.Clear(); - if (m_cam == NULL) + if (m_cam == nullptr) { this->Shutdown(); SetErrorText(SPKR_ERROR, "Could not find camera with serial number: " + m_SN); @@ -489,10 +489,10 @@ int SpinnakerCamera::Shutdown() if (m_imageBuff) delete[] m_imageBuff; m_imageBuff = NULL; - m_cam = NULL; - if (m_system != NULL) + m_cam = nullptr; + if (m_system != nullptr) m_system->ReleaseInstance(); - m_system = NULL; + m_system = nullptr; } catch (SPKR::Exception ex) { @@ -923,7 +923,7 @@ const unsigned char* SpinnakerCamera::GetImageBuffer() LogMessage(SPKR::Image::GetImageStatusDescription(m_imagePtr->GetImageStatus())); } - if (m_imagePtr != NULL) + if (m_imagePtr != nullptr) m_imagePtr->Release(); } catch (SPKR::Exception &ex) @@ -1076,15 +1076,15 @@ int SpinnakerCamera::SetROI(unsigned x, unsigned y, unsigned xSize, unsigned ySi m_cam->OffsetY.SetValue(m_cam->OffsetY.GetMin()); // Force width and height to be multiple of Width.GetInc() and Height.GetInc() - xSize = (unsigned) min(xSize - xSize % m_cam->Width.GetInc(), m_cam->Width.GetMax()); - ySize = (unsigned) min(ySize - ySize % m_cam->Height.GetInc(), m_cam->Height.GetMax()); + xSize = (unsigned) std::min(xSize - xSize % m_cam->Width.GetInc(), m_cam->Width.GetMax()); + ySize = (unsigned) std::min(ySize - ySize % m_cam->Height.GetInc(), m_cam->Height.GetMax()); m_cam->Width.SetValue(xSize); m_cam->Height.SetValue(ySize); //Force offsets to be multiples of OffsetX.GetInc() and OffsetY.GetInc() - x = (unsigned) min(x - x % m_cam->OffsetX.GetInc(), m_cam->OffsetX.GetMax()); - y = (unsigned) min(y - y % m_cam->OffsetY.GetInc(), m_cam->OffsetY.GetMax()); + x = (unsigned) std::min(x - x % m_cam->OffsetX.GetInc(), m_cam->OffsetX.GetMax()); + y = (unsigned) std::min(y - y % m_cam->OffsetY.GetInc(), m_cam->OffsetY.GetMax()); m_cam->OffsetX.SetValue(x); m_cam->OffsetY.SetValue(y); @@ -1661,7 +1661,7 @@ int SpinnakerCamera::MoveImageToCircularBuffer() } else { - if (ip != NULL) + if (ip != nullptr) ip->Release(); return ret; @@ -1672,7 +1672,7 @@ int SpinnakerCamera::MoveImageToCircularBuffer() LogMessage(SPKR::Image::GetImageStatusDescription(ip->GetImageStatus())); } - if (ip != NULL) + if (ip != nullptr) ip->Release(); } catch (SPKR::Exception &ex) From f2343919ea3a95d0c884f480571af107a17f5d40 Mon Sep 17 00:00:00 2001 From: Hazen Babcock Date: Wed, 7 Feb 2024 08:53:05 -0500 Subject: [PATCH 76/91] Use BUILD_SPINNAKER for build environment variable name. Remove linux build logic and clean up Spinnaker makefile. --- DeviceAdapters/Spinnaker/Makefile.am | 32 +++++++++------------------- DeviceAdapters/configure.ac | 6 +++--- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/DeviceAdapters/Spinnaker/Makefile.am b/DeviceAdapters/Spinnaker/Makefile.am index 039dd0cc6..6d33cb7b1 100644 --- a/DeviceAdapters/Spinnaker/Makefile.am +++ b/DeviceAdapters/Spinnaker/Makefile.am @@ -1,28 +1,16 @@ -SPINNAKERLDFLAGS = -SPINLIBADD = -SPINLDFLAGS = -SPINNAKERCPPFLAGS = -AM_CXXFLAGS=$(MMDEVAPI_CXXFLAGS) -libmmgr_dal_SpinnakerCamera_la_SOURCES=SpinnakerCamera.cpp SpinnakerCamera.h -deviceadapter_LTLIBRARIES=libmmgr_dal_SpinnakerCamera.la - - -if BUILD_SPINNAKER_LINUX - SPINNAKER_ROOT=/opt/spinnaker +AM_CXXFLAGS=$(MMDEVAPI_CXXFLAGS) - SPINNAKERLDFLAGS +=-Wl,--enable-new-dtags -Wl,-rpath,$(SPINNAKER_ROOT)/lib,-L$(SPINNAKER_ROOT)/lib - - SPINNAKERCPPFLAGS +=-I$(SPINNAKER_ROOT)/include - SPINNAKERLDLIBS =-lSpinnaker - - SPINLIBADD+=$(MMDEVAPI_LIBADD) $(SPINNAKERLDLIBS) - SPINLDFLAGS+=$(MMDEVAPI_LDFLAGS) $(SPINNAKERLDLIBS) $(SPINNAKERLDFLAGS) -endif +# Linux default install location? +SPINNAKER_ROOT=/opt/spinnaker +SPINNAKERCPPFLAGS = -I$(SPINNAKER_ROOT)/include +SPINNAKERLDFLAGS = -Wl,--enable-new-dtags -Wl,-rpath,$(SPINNAKER_ROOT)/lib,-L$(SPINNAKER_ROOT)/lib +SPINNAKERLDLIBS =-lSpinnaker +deviceadapter_LTLIBRARIES=libmmgr_dal_SpinnakerCamera.la +libmmgr_dal_SpinnakerCamera_la_SOURCES=SpinnakerCamera.cpp SpinnakerCamera.h libmmgr_dal_SpinnakerCamera_la_CPPFLAGS=$(SPINNAKERCPPFLAGS) -libmmgr_dal_SpinnakerCamera_la_LIBADD=$(SPINLIBADD) -libmmgr_dal_SpinnakerCamera_la_LDFLAGS=$(SPINLDFLAGS) +libmmgr_dal_SpinnakerCamera_la_LIBADD=$(MMDEVAPI_LIBADD) $(SPINNAKERLDLIBS) +libmmgr_dal_SpinnakerCamera_la_LDFLAGS=$(MMDEVAPI_LDFLAGS) $(SPINNAKERLDLIBS) $(SPINNAKERLDFLAGS) -EXTRA_DIST = diff --git a/DeviceAdapters/configure.ac b/DeviceAdapters/configure.ac index 935a3424a..1759beff5 100644 --- a/DeviceAdapters/configure.ac +++ b/DeviceAdapters/configure.ac @@ -395,9 +395,9 @@ AS_IF([test "x$want_opencv" != xno], AM_CONDITIONAL([BUILD_OPENCV], [test "x$use_opencv" = xyes]) -# Spinnaker (FLIR). -AC_MSG_CHECKING(for Spinnaker_Linux) -AM_CONDITIONAL([BUILD_SPINNAKER_LINUX],[test -f "/opt/spinnaker/include/Spinnaker.h"]) +# Spinnaker SDK (FLIR). +AC_MSG_CHECKING(for Spinnaker) +AM_CONDITIONAL([BUILD_SPINNAKER],[test -f "/opt/spinnaker/include/Spinnaker.h"]) if test -f "/opt/spinnaker/include/Spinnaker.h"; then AC_MSG_RESULT([found]) else From 3a1ffea45147261ae47abc4e882da7ead3feea00 Mon Sep 17 00:00:00 2001 From: Hazen Babcock Date: Wed, 7 Feb 2024 08:53:44 -0500 Subject: [PATCH 77/91] Only build Spinnaker when SDK is found. --- DeviceAdapters/Makefile.am | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/DeviceAdapters/Makefile.am b/DeviceAdapters/Makefile.am index 4fc25eb8b..5325c1738 100644 --- a/DeviceAdapters/Makefile.am +++ b/DeviceAdapters/Makefile.am @@ -59,6 +59,9 @@ endif if BUILD_SIMPLECAM SIMPLECAM = SimpleCam endif +if BUILD_SPINNAKER + SPINNAKER = Spinnaker +endif if BUILD_SPOT SPOT = Spot endif @@ -94,6 +97,7 @@ SUBDIRS = \ $(SENSICAM) \ $(SEQUENCE_TESTER) \ $(SIMPLECAM) \ + $(SPINNAKER) \ $(SPOT) \ $(USBMANAGER) \ $(V4L) \ @@ -182,7 +186,6 @@ SUBDIRS = \ SmarActHCU-3D \ SouthPort \ SpectralLMM5 \ - Spinnaker \ StarlightXpress \ SutterLambda \ SutterLambda2 \ From 29adc678a67f4b2a5d23d1c450c309dd0195c084 Mon Sep 17 00:00:00 2001 From: Hazen Babcock Date: Wed, 7 Feb 2024 09:02:33 -0500 Subject: [PATCH 78/91] Add linux section. --- DeviceAdapters/Spinnaker/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/DeviceAdapters/Spinnaker/README.md b/DeviceAdapters/Spinnaker/README.md index 3d5452e17..f3807aaba 100644 --- a/DeviceAdapters/Spinnaker/README.md +++ b/DeviceAdapters/Spinnaker/README.md @@ -18,3 +18,8 @@ For support with installation and use of the cameras/adapters in MicroManager pl These device adapters were initially developed by Elliot Steele as part of a final year masters project in Electrical and Electronic Engineering at Imperial College London. The project was undertaken with the Photonics Group in Imperial College's Department of Physics and in conjunction with Cairn Research Ltd. Since the completion of the project maintenance has continued and the drivers have been made freely available by Cairn Research. The code was integrated into MicroManager's source on TODO Special acknowledgements and thanks go to Professor Paul French and the rest of the Photonics Group for hosting the project and to Cairn Research for distribution of the device adapters before their integration into the MicroManager project and their continued support in the adapters' development. + + +## Linux + +These device adapters can also be used on a linux system. This was developed and tested with Spinnaker SDK version 3.1.0. The Spinnaker SDK should be installed in `/opt/spinnaker/`. From 245acefe184c53ebc9b08f5f1161455e26b0c731 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Fri, 9 Feb 2024 15:44:59 -0600 Subject: [PATCH 79/91] SpinnakerCamera: Use NOMINMAX on Windows --- DeviceAdapters/Spinnaker/SpinnakerCamera.vcxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DeviceAdapters/Spinnaker/SpinnakerCamera.vcxproj b/DeviceAdapters/Spinnaker/SpinnakerCamera.vcxproj index 0985e821a..53197c8e3 100644 --- a/DeviceAdapters/Spinnaker/SpinnakerCamera.vcxproj +++ b/DeviceAdapters/Spinnaker/SpinnakerCamera.vcxproj @@ -59,7 +59,7 @@ Disabled - _DEBUG;_WINDOWS;_USRDLL;SPINNAKERCAMERA_EXPORTS;%(PreprocessorDefinitions) + NOMINMAX;_DEBUG;_WINDOWS;_USRDLL;SPINNAKERCAMERA_EXPORTS;%(PreprocessorDefinitions) true @@ -73,7 +73,7 @@ MaxSpeed true true - NDEBUG;_WINDOWS;_USRDLL;SPINNAKERCAMERA_EXPORTS;%(PreprocessorDefinitions) + NOMINMAX;NDEBUG;_WINDOWS;_USRDLL;SPINNAKERCAMERA_EXPORTS;%(PreprocessorDefinitions) true From a97d96a507936e7624a4133ad3faf120590167ab Mon Sep 17 00:00:00 2001 From: alejandrcastro Date: Thu, 22 Feb 2024 18:47:24 +0100 Subject: [PATCH 80/91] Tried to address bug that only allowed changing the last channel of the CoolLED pE2. --- DeviceAdapters/PrecisExcite/PrecisExcite.cpp | 56 +++++++++++++++----- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/DeviceAdapters/PrecisExcite/PrecisExcite.cpp b/DeviceAdapters/PrecisExcite/PrecisExcite.cpp index b81d11fcb..c80134b61 100644 --- a/DeviceAdapters/PrecisExcite/PrecisExcite.cpp +++ b/DeviceAdapters/PrecisExcite/PrecisExcite.cpp @@ -33,6 +33,22 @@ #include "ModuleInterface.h" #include "DeviceUtils.h" #include +#include +#include + + +int debug(std::string text) { + + /* + * //LogMessage(text); use LogMessage within the class for better results. + * + ofstream myfile; + myfile.open("albert_precisexcite_debut.txt", std::ios_base::app); + myfile << text; + myfile.close(); + */ + return 0; +} // Controller const char* g_ControllerName = "PrecisExcite"; @@ -375,15 +391,20 @@ int Controller::OnChannelLabel(MM::PropertyBase* pProp, MM::ActionType eAct) int Controller::OnState(MM::PropertyBase* pProp, MM::ActionType eAct) { + stringstream txt; if (eAct == MM::BeforeGet) { GetState(state_); pProp->Set(state_); + txt << "current state in event OnState - beforeget=" << state_; + debug(txt.str()); } else if (eAct == MM::AfterSet) { pProp->Get(state_); SetState(state_); + txt << "current state in event OnState - afterset=" << state_; + debug(txt.str()); } return HandleErrors(); @@ -457,8 +478,9 @@ void Controller::Illuminate() stringstream msg; if (state_==0) { - if (triggerMode_ == OFF || triggerMode_ == FOLLOW_PULSE) - msg << "SQX" << carriage_return << "C" << channelLetters_[currentChannel_] << "F" << carriage_return << "AZ"; + if (triggerMode_ == OFF || triggerMode_ == FOLLOW_PULSE) { + msg << "SQX" << carriage_return << "C" << channelLetters_[currentChannel_] << "F" << carriage_return << "AZ"; + } else msg << "SQX" << "AZ"; } @@ -467,20 +489,20 @@ void Controller::Illuminate() if (triggerMode_ == OFF) { msg << "SQZ" << carriage_return; for (unsigned int i=0; i Date: Tue, 5 Mar 2024 11:47:38 -0800 Subject: [PATCH 81/91] Utilities: added ability to run polygons (points so far only). --- DeviceAdapters/Utilities/DAGalvo.cpp | 37 ++++++++++++++++++++++++---- DeviceAdapters/Utilities/Utilities.h | 33 +++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/DeviceAdapters/Utilities/DAGalvo.cpp b/DeviceAdapters/Utilities/DAGalvo.cpp index 5e0e50e4d..1a2f7fbff 100644 --- a/DeviceAdapters/Utilities/DAGalvo.cpp +++ b/DeviceAdapters/Utilities/DAGalvo.cpp @@ -34,6 +34,7 @@ #include #include +#include extern const char* g_NoDevice; @@ -46,6 +47,7 @@ DAGalvo::DAGalvo() : pulseIntervalUs_(100000), initialized_(false) { + polygons_ = new std::vector(); } DAGalvo::~DAGalvo() @@ -236,21 +238,40 @@ double DAGalvo::GetYMinimum() return yMin; } -int DAGalvo::AddPolygonVertex(int /* polygonIndex */, double /* x */, double /* y */) +int DAGalvo::AddPolygonVertex(int index, double x, double y) { - return DEVICE_NOT_YET_IMPLEMENTED; + if (index > 0) { + size_t nrPolygons = polygons_->size(); + if (index < nrPolygons) { + DAPolygon* polygon = polygons_->at(index); + polygon->addVertex(x, y); + return true; + } + else if (index == nrPolygons) { + DAPolygon* polygon = new DAPolygon(x, y); + polygons_->push_back(polygon); + return true; + } + } + return false; // the index is more than nrPolygons and our vector does not accomodate this } + int DAGalvo::DeletePolygons() { - return DEVICE_NOT_YET_IMPLEMENTED; + for (int i = 0; i < polygons_->size(); i++) { + delete(polygons_->at(i)); + } + return polygons_->empty(); } + int DAGalvo::RunSequence() { return DEVICE_NOT_YET_IMPLEMENTED; } + int DAGalvo::LoadPolygons() { - return DEVICE_NOT_YET_IMPLEMENTED; + return DEVICE_OK; // Not sure how we can benefit, this is supposed to load the polygons to the device } int DAGalvo::SetPolygonRepetitions(int repetitions) @@ -262,8 +283,14 @@ int DAGalvo::SetPolygonRepetitions(int repetitions) int DAGalvo::RunPolygons() { - return DEVICE_NOT_YET_IMPLEMENTED; + for (int i = 0; i < polygons_->size(); i++) { + DAPolygon* polygon = polygons_->at(i); + std::pair xyPair = polygon->getVertex(0); + this->PointAndFire(xyPair.first, xyPair.second, pulseIntervalUs_); + } + return DEVICE_OK; } + int DAGalvo::StopSequence() { return DEVICE_NOT_YET_IMPLEMENTED; diff --git a/DeviceAdapters/Utilities/Utilities.h b/DeviceAdapters/Utilities/Utilities.h index 4fd288116..a16b6e163 100644 --- a/DeviceAdapters/Utilities/Utilities.h +++ b/DeviceAdapters/Utilities/Utilities.h @@ -29,6 +29,7 @@ #include "ImgBuffer.h" #include #include +#include ////////////////////////////////////////////////////////////////////////////// // Error codes @@ -632,6 +633,37 @@ class DATTLStateDevice : public CStateDeviceBase MM::MMTime lastChangeTime_; }; +class DAPolygon +{ +private: + std::vector> polygon_; +public: + DAPolygon(double x, double y) { + polygon_.push_back(std::make_pair(x, y)); + } + void addVertex(double x, double y) { + polygon_.push_back(std::make_pair(x, y)); + } + + boolean hasVertex(size_t index) { + return polygon_.size() <= index + 1; + } + + std::pair getVertex(size_t index) { + if (polygon_.size() <= index + 1) { + return polygon_[index]; + } + else { + // TODO: throw exception + } + } + + size_t getNumberOfVertices() { + return polygon_.size(); + } +}; + + class DAGalvo : public CGalvoBase { @@ -673,6 +705,7 @@ class DAGalvo : public CGalvoBase long nrRepetitions_; double pulseIntervalUs_; std::string shutter_; + std::vector *polygons_; }; From f08536166d2cd5ef1fcad876d09dd808896e47e0 Mon Sep 17 00:00:00 2001 From: Nico Stuurman Date: Tue, 5 Mar 2024 11:48:03 -0800 Subject: [PATCH 82/91] DemoCamera: bit of work on demo galvo device --- DeviceAdapters/DemoCamera/DemoCamera.cpp | 42 ++++++++++++++++-------- DeviceAdapters/DemoCamera/DemoCamera.h | 1 + 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/DeviceAdapters/DemoCamera/DemoCamera.cpp b/DeviceAdapters/DemoCamera/DemoCamera.cpp index d5dd386c0..bc5dec49b 100644 --- a/DeviceAdapters/DemoCamera/DemoCamera.cpp +++ b/DeviceAdapters/DemoCamera/DemoCamera.cpp @@ -33,6 +33,14 @@ #include #include +#ifdef _WIN32 +#include + +static NTSTATUS(__stdcall* NtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval) = (NTSTATUS(__stdcall*)(BOOL, PLARGE_INTEGER)) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtDelayExecution"); +static NTSTATUS(__stdcall* ZwSetTimerResolution)(IN ULONG RequestedResolution, IN BOOLEAN Set, OUT PULONG ActualResolution) = (NTSTATUS(__stdcall*)(ULONG, BOOLEAN, PULONG)) GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwSetTimerResolution"); + +#endif + using namespace std; @@ -612,7 +620,11 @@ int CDemoCamera::SnapImage() { while (exp > (GetCurrentMMTime() - startTime).getMsec()) { +#ifdef _WIN32 + // SleepShort(1); +#elif CDeviceUtils::SleepMs(1); +#endif } } else @@ -2413,17 +2425,17 @@ void CDemoCamera::GenerateSyntheticImage(ImgBuffer& img, double exp) // this function. for (unsigned int i = 0; i < imgWidth; ++i) { - for (unsigned j = 0; j < img.Height(); ++j) + for (unsigned h = 0; h < img.Height(); ++h) { bool shouldKeep = false; - for (unsigned int k = 0; k < multiROIXs_.size(); ++k) + for (unsigned int mr = 0; mr < multiROIXs_.size(); ++mr) { - unsigned xOffset = multiROIXs_[k] - roiX_; - unsigned yOffset = multiROIYs_[k] - roiY_; - unsigned width = multiROIWidths_[k]; - unsigned height = multiROIHeights_[k]; + unsigned xOffset = multiROIXs_[mr] - roiX_; + unsigned yOffset = multiROIYs_[mr] - roiY_; + unsigned width = multiROIWidths_[mr]; + unsigned height = multiROIHeights_[mr]; if (i >= xOffset && i < xOffset + width && - j >= yOffset && j < yOffset + height) + h >= yOffset && h < yOffset + height) { // Pixel is inside an ROI. shouldKeep = true; @@ -2433,7 +2445,7 @@ void CDemoCamera::GenerateSyntheticImage(ImgBuffer& img, double exp) if (!shouldKeep) { // Blank the pixel. - long lIndex = imgWidth * j + i; + long lIndex = imgWidth * h + i; if (pixelType.compare(g_PixelType_8bit) == 0) { *((unsigned char*) rawBuf + lIndex) = static_cast(multiROIFillValue_); @@ -4224,7 +4236,8 @@ DemoGalvo::DemoGalvo() : offsetX_(20), vMaxX_(10.0), offsetY_(15), - vMaxY_(10.0) + vMaxY_(10.0), + pulseTime_Us_(100000.0) { // handwritten 5x5 gaussian kernel, no longer used /* @@ -4312,8 +4325,9 @@ int DemoGalvo::PointAndFire(double x, double y, double pulseTime_us) return DEVICE_OK; } -int DemoGalvo::SetSpotInterval(double /* pulseInterval_us */) +int DemoGalvo::SetSpotInterval(double pulseTime_Us) { + pulseTime_Us_ = pulseTime_Us; return DEVICE_OK; } @@ -4371,17 +4385,19 @@ int DemoGalvo::SetPolygonRepetitions(int /* repetitions */) int DemoGalvo::RunPolygons() { - /* std::ostringstream os; os << "# of polygons: " << vertices_.size() << std::endl; for (std::map >::iterator it = vertices_.begin(); it != vertices_.end(); ++it) { os << "ROI " << it->first << " has " << it->second.size() << " points" << std::endl; + // illuminate just the first point + this->PointAndFire(it->second.at(0).x, it->second.at(0).y, pulseTime_Us_); + CDeviceUtils::SleepMs(pulseTime_Us_ / 1000); } LogMessage(os.str().c_str()); - */ - runROIS_ = true; + + //runROIS_ = true; return DEVICE_OK; } diff --git a/DeviceAdapters/DemoCamera/DemoCamera.h b/DeviceAdapters/DemoCamera/DemoCamera.h index acd3df13a..694416a5f 100644 --- a/DeviceAdapters/DemoCamera/DemoCamera.h +++ b/DeviceAdapters/DemoCamera/DemoCamera.h @@ -1192,6 +1192,7 @@ class DemoGalvo : public CGalvoBase, ImgManipulator double vMaxX_; int offsetY_; double vMaxY_; + double pulseTime_Us_; }; From 99f848d1392adce6bdff370709e6a9cdb4afc07a Mon Sep 17 00:00:00 2001 From: Nico Stuurman Date: Tue, 5 Mar 2024 14:04:45 -0800 Subject: [PATCH 83/91] Utilities: minor fixes in DAGalvo --- DeviceAdapters/Utilities/DAGalvo.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/DeviceAdapters/Utilities/DAGalvo.cpp b/DeviceAdapters/Utilities/DAGalvo.cpp index 1a2f7fbff..25c2bcc11 100644 --- a/DeviceAdapters/Utilities/DAGalvo.cpp +++ b/DeviceAdapters/Utilities/DAGalvo.cpp @@ -142,11 +142,15 @@ int DAGalvo::PointAndFire(double x, double y, double timeUs) return ERR_NO_SHUTTER_DEVICE_FOUND; // Should we do this non-blocking instead? + bool open = false; + ret = s->GetOpen(open); + if (ret != DEVICE_OK) + return ret; ret = s->SetOpen(true); if (ret != DEVICE_OK) return ret; std::this_thread::sleep_for(std::chrono::microseconds((long long)timeUs)); - return s->SetOpen(false); + return s->SetOpen(open); } @@ -240,20 +244,20 @@ double DAGalvo::GetYMinimum() int DAGalvo::AddPolygonVertex(int index, double x, double y) { - if (index > 0) { + if (index >= 0) { size_t nrPolygons = polygons_->size(); if (index < nrPolygons) { DAPolygon* polygon = polygons_->at(index); polygon->addVertex(x, y); - return true; + return DEVICE_OK; } else if (index == nrPolygons) { DAPolygon* polygon = new DAPolygon(x, y); polygons_->push_back(polygon); - return true; + return DEVICE_OK; } } - return false; // the index is more than nrPolygons and our vector does not accomodate this + return DEVICE_UNKNOWN_POSITION; // the index is more than nrPolygons and our vector does not accomodate this } int DAGalvo::DeletePolygons() @@ -261,7 +265,8 @@ int DAGalvo::DeletePolygons() for (int i = 0; i < polygons_->size(); i++) { delete(polygons_->at(i)); } - return polygons_->empty(); + polygons_->clear(); + return DEVICE_OK; } int DAGalvo::RunSequence() From f6c45a68b6ed29b59965613b19ab34966b6fcc64 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Tue, 5 Mar 2024 17:52:35 -0600 Subject: [PATCH 84/91] Fix build after #446 Did not compile on either Windows or macOS without this. --- DeviceAdapters/DemoCamera/DemoCamera.cpp | 4 ++-- DeviceAdapters/Utilities/Utilities.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DeviceAdapters/DemoCamera/DemoCamera.cpp b/DeviceAdapters/DemoCamera/DemoCamera.cpp index 3558767c8..008a4f505 100644 --- a/DeviceAdapters/DemoCamera/DemoCamera.cpp +++ b/DeviceAdapters/DemoCamera/DemoCamera.cpp @@ -611,10 +611,10 @@ int CDemoCamera::SnapImage() { #ifdef _WIN32 // SleepShort(1); -#elif +#else CDeviceUtils::SleepMs(1); #endif - } + } } else { diff --git a/DeviceAdapters/Utilities/Utilities.h b/DeviceAdapters/Utilities/Utilities.h index a16b6e163..9b7864728 100644 --- a/DeviceAdapters/Utilities/Utilities.h +++ b/DeviceAdapters/Utilities/Utilities.h @@ -645,7 +645,7 @@ class DAPolygon polygon_.push_back(std::make_pair(x, y)); } - boolean hasVertex(size_t index) { + bool hasVertex(size_t index) { return polygon_.size() <= index + 1; } @@ -867,4 +867,4 @@ class SerialDTRShutter : public CShutterBase }; -#endif //_UTILITIES_H_ \ No newline at end of file +#endif //_UTILITIES_H_ From 624df52727ade379813710405d099ee88fb37695 Mon Sep 17 00:00:00 2001 From: Nico Stuurman Date: Tue, 5 Mar 2024 16:11:20 -0800 Subject: [PATCH 85/91] DemoCamera: revert accidental removal of Sleep in SnapIMage on WIndows. --- DeviceAdapters/DemoCamera/DemoCamera.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/DeviceAdapters/DemoCamera/DemoCamera.cpp b/DeviceAdapters/DemoCamera/DemoCamera.cpp index 008a4f505..c0444e2e0 100644 --- a/DeviceAdapters/DemoCamera/DemoCamera.cpp +++ b/DeviceAdapters/DemoCamera/DemoCamera.cpp @@ -609,11 +609,7 @@ int CDemoCamera::SnapImage() { while (exp > (GetCurrentMMTime() - startTime).getMsec()) { -#ifdef _WIN32 - // SleepShort(1); -#else CDeviceUtils::SleepMs(1); -#endif } } else From 9669416b2191a37923215bfe50c4f97566440e42 Mon Sep 17 00:00:00 2001 From: Nico Stuurman Date: Thu, 7 Mar 2024 11:52:20 -0800 Subject: [PATCH 86/91] MMDevice: adds more documentation mainly to Galvo device. --- MMDevice/MMDevice.h | 110 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 104 insertions(+), 6 deletions(-) diff --git a/MMDevice/MMDevice.h b/MMDevice/MMDevice.h index d6a7db5e0..cddfebd00 100644 --- a/MMDevice/MMDevice.h +++ b/MMDevice/MMDevice.h @@ -964,7 +964,11 @@ namespace MM { /** - * SLM API + * Spatial Ligh Modulator (SLM) API. An SLM is a device that can display images. + * It is expected to represent a rectangular grid (i.e. it has width and height) + * of pixels that can be either 8 bit or 32 bit. Illumination (light source on + * or off) is logically independent of displaying the image. Likely the most + * widely used implmentation is the GenericSLM. */ class SLM : public Device { @@ -1113,6 +1117,17 @@ namespace MM { /** * Galvo API + * A Galvo in Micro-Manager is a two-axis (conveniently labeled x and y) that can illuminate + * a sample in the microscope. It therefore also has the capability to switch a light source + * on and off (note that this functionality can be offloaded to a shutter device + * that can be obtained through a callback). Galvos can illuminate a point, or + * possibly be directed to illuminate a polygon by scanning the two axis and controlling + * the light source so that only the area with the polygon is illuminated. + * Currently known implementations are Utilities-DAGalvo (which uses two DAs to + * control a Galvo), Democamera-Galvo, ASITiger-ASIScanner, and Rapp. + * There is no integration with a detector as would be needed for a confocal microscope, + * and there is also no support for waveforms. + * */ class Galvo : public Device { @@ -1128,15 +1143,40 @@ namespace MM { /** * Moves the galvo devices to the requested position, activates the light * source, waits for the specified amount of time (in microseconds), and - * deactivates the light source + * deactivates the light source. + * @return errorcode (DEVICE_OK if no error) */ virtual int PointAndFire(double x, double y, double time_us) = 0; + /** + * This function seems to be misnamed. Its name suggest that it is the + * interval between illuminating two consecutive spots, but in practice it + * is used to set the time a single spot is illuminated (and the time + * to move between two spots is usually extremely short). + * @return errorcode (DEVICE_OK if no error) + */ virtual int SetSpotInterval(double pulseInterval_us) = 0; + /** + * Sets the position of the two axes of the Galvo device in native + * unit (usually through a voltage that controls the galvo posiution). + * @return errorcode (DEVICE_OK if no error) + */ virtual int SetPosition(double x, double y) = 0; + /** + * Returns the current position of the two axes (usually the last position + * that was set, although this may be different for Galvo devices that also + * can be controlled through another source). + * @return errorcode (DEVICE_OK if no error) + */ virtual int GetPosition(double& x, double& y) = 0; + /** + * Switches the light source under control of this device on or off. If light control + * through a Shutter device is desired, a property should be added that can be set + * to the name of the lightsource. + * @return errorcode (DEVICE_OK if no error) + */ virtual int SetIlluminationState(bool on) = 0; /** - * X range of the device in native units + * X range of the device in native units. */ virtual double GetXRange() = 0; /** @@ -1145,21 +1185,69 @@ namespace MM { */ virtual double GetXMinimum() = 0; /** - * Y range of the device in native units + * Y range of the device in native units. */ virtual double GetYRange() = 0; /** - * Minimum Y value for the device in native units - * Must be implemented if it is not 0.0 + * Minimum Y value for the device in native units. + * Must be implemented if it is not 0.0. */ virtual double GetYMinimum() = 0; + /** + * A galvo device in principle can draw arbitrary polygons. Polygons are + * added added here point by point. There is nothing in the API that prevents + * adding polygons in random order, but most implementations so far + * do not deal with that well (i.e. expect polygons to be added in incremental + * order). Vertex points are added in order and can not be modified through the API + * after adding (only way is to delete all polygons and start anew). + * + * @return errorcode (DEVICE_OK if no error) + */ virtual int AddPolygonVertex(int polygonIndex, double x, double y) = 0; + /** + * Deletes all polygons previously stored in the device adapater. + * @return errorcode (DEVICE_OK if no error) + */ virtual int DeletePolygons() = 0; + /** + * Presumably the idea of this function is to have the Galvo draw the + * each polygon in the pre-loaded sequence after its controller receives + * a TTL trigger. This is not likely to be supported by all Galvo devices. + * There currently is no API method to query whether Sequences are supported. + * When the number of TTLs exceeds the number of polygons, the desired behavior + * is to repeat the sequence from the beginning. + * @return errorcode (DEVICE_OK if no error) + */ virtual int RunSequence() = 0; + /** + * Transfers the polygons from the device adapter memory to the Galvo controller. + * Should be called before RunPolygons() or RunSequence(). This is mainly an + * optimization so that the device adapter does not need to transfer each vertex + * individually. Some Galvo device adapters will do nothing in this function. + * @return errorcode (DEVICE_OK if no error) + */ virtual int LoadPolygons() = 0; + /** + * Sets the number of times the polygons should be displayed in the RunPolygons + * function. + * @return errorcode (DEVICE_OK if no error) + */ virtual int SetPolygonRepetitions(int repetitions) = 0; + /** + * Displays each pre-loaded polygon in sequence, each illuminated for pulseinterval_us + * micro-seconds. + * @return errorcode (DEVICE_OK if no error) + */ virtual int RunPolygons() = 0; + /** + * Stops the TTL triggered transitions of drawing polygons started in RunSequence(). + * @return errorcode (DEVICE_OK if no error) + */ virtual int StopSequence() = 0; + /** + * It is completely unclear what this function is supposed to do. Deprecate?. + * @return errorcode (DEVICE_OK if no error) + */ virtual int GetChannel(char* channelName) = 0; }; @@ -1228,7 +1316,17 @@ namespace MM { Core() {} virtual ~Core() {} + /** + * Logs a message (msg) in the Corelog output, labeled with the device name (derived + * from caller). If debugOnly flag is true, the output will only be logged if the + * general system has been set to output debug logging. + */ virtual int LogMessage(const Device* caller, const char* msg, bool debugOnly) const = 0; + /** + * Callback that allows this device adapter to get a pointer to another device. Be aware of + * potential threading issues. Provide a valid label for the device and receive a pointer + * to the desired device. + */ virtual Device* GetDevice(const Device* caller, const char* label) = 0; virtual int GetDeviceProperty(const char* deviceName, const char* propName, char* value) = 0; virtual int SetDeviceProperty(const char* deviceName, const char* propName, const char* value) = 0; From 6e9a93795b367bf5617fbe781120b5efd3e79a07 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Thu, 21 Mar 2024 23:22:31 -0400 Subject: [PATCH 87/91] Add algorithm header to CoreCallback.cpp --- MMCore/CoreCallback.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/MMCore/CoreCallback.cpp b/MMCore/CoreCallback.cpp index 471313c24..7cd1b0e5c 100644 --- a/MMCore/CoreCallback.cpp +++ b/MMCore/CoreCallback.cpp @@ -36,6 +36,7 @@ #include #include #include +#include CoreCallback::CoreCallback(CMMCore* c) : From 2e1de6753435fa0ea905c95f5a521746747320ae Mon Sep 17 00:00:00 2001 From: Nico Stuurman Date: Wed, 27 Mar 2024 09:22:43 -0700 Subject: [PATCH 88/91] DahengGalaxy: based on code from Daheng (which was based on the BaslerPylon adapter code). Daheng grants free re-distribtion of their SDK to support building this code. --- DeviceAdapters/DahengGalaxy/ClassGalaxy.cpp | 2163 +++++++++++++++++ DeviceAdapters/DahengGalaxy/ClassGalaxy.h | 232 ++ .../DahengGalaxy/DahengGalaxy.vcxproj | 113 + .../DahengGalaxy/DahengGalaxy.vcxproj.filters | 27 + DeviceAdapters/DahengGalaxy/GalaxySDK.props | 16 + micromanager.sln | 6 + 6 files changed, 2557 insertions(+) create mode 100644 DeviceAdapters/DahengGalaxy/ClassGalaxy.cpp create mode 100644 DeviceAdapters/DahengGalaxy/ClassGalaxy.h create mode 100644 DeviceAdapters/DahengGalaxy/DahengGalaxy.vcxproj create mode 100644 DeviceAdapters/DahengGalaxy/DahengGalaxy.vcxproj.filters create mode 100644 DeviceAdapters/DahengGalaxy/GalaxySDK.props diff --git a/DeviceAdapters/DahengGalaxy/ClassGalaxy.cpp b/DeviceAdapters/DahengGalaxy/ClassGalaxy.cpp new file mode 100644 index 000000000..0c4dc32f9 --- /dev/null +++ b/DeviceAdapters/DahengGalaxy/ClassGalaxy.cpp @@ -0,0 +1,2163 @@ +#include "ClassGalaxy.h" +//#include + +using namespace std; + +const char* g_CameraDeviceName = "DahengCamera"; + +static const char* g_PropertyChannel = "PropertyNAme"; +//8bit monoMono8 +static const char* g_PixelType_8bit = "8bit mono"; +static const char* g_PixelType_10bit = "10bit mono"; +static const char* g_PixelType_12bit = "12bit mono"; +static const char* g_PixelType_16bit = "16bit mono"; +static const char* g_PixelType_10packedbit = "10bit mono"; +static const char* g_PixelType_12packedbit = "12bit mono"; + +static const char* g_PixelType_8bitRGBA = "8bitBGRA"; +static const char* g_PixelType_8bitRGB = "8bitRGB"; +static const char* g_PixelType_8bitBGR = "8bitBGR"; + +MODULE_API void InitializeModuleData() +{ + RegisterDevice(g_CameraDeviceName, MM::CameraDevice, "Daheng Camera"); +} +//Camera Device +MODULE_API MM::Device* CreateDevice(const char* deviceName) +{ + if (deviceName == 0) + return 0; + + // decide which device class to create based on the deviceName parameter ±È½Ï½á¹û + if (strcmp(deviceName, g_CameraDeviceName) == 0) { + // create camera + return new ClassGalaxy(); + } + // ...supplied name not recognized + return 0; +} + +MODULE_API void DeleteDevice(MM::Device* pDevice) +{ + delete pDevice; +} +ClassGalaxy::ClassGalaxy() : + CCameraBase(), + ImageHandler_(0), + Width_(0), + Height_(0), + imageBufferSize_(0), + maxWidth_(0), + maxHeight_(0), + DeviceLinkThroughputLimit_(0), + exposure_us_(0), + exposureMax_(0), + exposureMin_(0), + gain_(0), + gainMax_(0), + gainMin_(0), + bitDepth_(8), + bytesPerPixel_(1), + temperatureState_("Undefined"), + reverseX_("0"), + reverseY_("0"), + imgBuffer_(NULL), + // Buffer4ContinuesShot(NULL), + colorCamera_(false), + pixelType_("Undefined"), + sensorReadoutMode_("Undefined"), + shutterMode_("None"), + imgBufferSize_(0), + initialized_(false) +{ + // call the base class method to set-up default error codes/messages + InitializeDefaultErrorMessages(); + //SetErrorText(ERR_SERIAL_NUMBER_REQUIRED, "Serial number is required"); + //SetErrorText(ERR_SERIAL_NUMBER_NOT_FOUND, "No camera with the given serial number was found"); + //SetErrorText(ERR_CANNOT_CONNECT, "Cannot connect to camera; it may be in use"); + IGXFactory::GetInstance().Init(); + + IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo); + + CreateStringProperty("SerialNumber", "Undefined", false, 0, true); + + //pre-init properties + //PylonInitialize(); // Initialize/Terminate is reference counted by Pylon + + // Get the available cameras. TODO: This can be very slow and perhaps the + // result should be cached. + // or setting up TL Filter, currently it enumerates all pylon TL, eg. GigE , USB Camemu, CXP, CL etc.. + //DeviceInfoList_t devices; + + if (vectorDeviceInfo.size() <= 0) + { + AddToLog("No camera present."); + //PylonTerminate(); + //throw RUNTIME_EXCEPTION("No camera present."); + } + vector SnString; + bool first = false; + string serialNumberstr; + if (true) + { + //const CDeviceInfo& device = *it; + //String_t s = device.GetSerialNumber(); + for (size_t i = 0; i < vectorDeviceInfo.size(); i++) + { + serialNumberstr = vectorDeviceInfo[i].GetSN().c_str(); + AddAllowedValue("SerialNumber", serialNumberstr.c_str()); + SnString.push_back(serialNumberstr); + first = true; + } + if (first) + { + SetProperty("SerialNumber", SnString[0].c_str()); + first = false; + } + } + //PylonTerminate(); +} + +ClassGalaxy::~ClassGalaxy(void) +{ + +} + +int ClassGalaxy::Initialize() +{ + if (initialized_) + return DEVICE_OK; + + try + { + // Before calling any Galaxy SDK methods, the runtime must be initialized. + IGXFactory::GetInstance().Init(); + + if (1) + { + char serialNumber[MM::MaxStrLength]; + int ret = GetProperty("SerialNumber", serialNumber); + if (ret != DEVICE_OK) { + return DEVICE_NOT_CONNECTED; + } + } + + + vectorDeviceInfo.clear(); + //ö¾ÙÉ豸 + IGXFactory::GetInstance().UpdateDeviceList(1000, vectorDeviceInfo); + + //ÅжÏö¾Ùµ½µÄÉ豸ÊÇ·ñ´óÓÚÁ㣬Èç¹û²»ÊÇÔòµ¯¿òÌáʾ + if (vectorDeviceInfo.size() <= 0) + { + return DEVICE_NOT_CONNECTED; + } + //»ñÈ¡¿ÉÖ´ÐгÌÐòµÄµ±Ç°Â·¾¶,ĬÈÏ¿ªÆôµÚÒ»¸ö + initialized_ = false; + // This checks, among other things, that the camera is not already in use. + // Without that check, the following CreateDevice() may crash on duplicate + // serial number. Unfortunately, this call is slow. ĬÈÏ´ò¿ªµÚÒ»¸öÉ豸 + int index = 0; + + string serialNumberstr = vectorDeviceInfo[index].GetSN().c_str(); + + const char* serialNumber = serialNumberstr.c_str(); + + if (strlen(serialNumber) == 0 || strcmp(serialNumber, "Undefined") == 0) + return 0; + SetProperty("SerialNumber", serialNumber); + //´ò¿ªÉ豸 + m_objDevicePtr = IGXFactory::GetInstance().OpenDeviceBySN(vectorDeviceInfo[index].GetSN(), GX_ACCESS_MODE::GX_ACCESS_EXCLUSIVE); + + m_objFeatureControlPtr = m_objDevicePtr->GetRemoteFeatureControl(); + + //m_objFeatureControlPtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("NewestOnly"); + //ÅжÏÉ豸Á÷ÊÇ·ñ´óÓÚÁ㣬Èç¹û´óÓÚÁãÔò´ò¿ªÁ÷ + + int nStreamCount = m_objDevicePtr->GetStreamCount(); + //CPropertyAction* pAct; + + if (nStreamCount > 0) + { + m_objStreamPtr = m_objDevicePtr->OpenStream(0); + //m_objStreamPtr->SetAcqusitionBufferNumber(1); + m_objStreamFeatureControlPtr = m_objStreamPtr->GetFeatureControl(); + m_objStreamFeatureControlPtr->GetEnumFeature("StreamBufferHandlingMode")->SetValue("NewestOnly"); + initialized_ = true; + } + else + { + throw exception("δ·¢ÏÖÉ豸Á÷!"); + } + + + GX_DEVICE_CLASS_LIST objDeviceClass = m_objDevicePtr->GetDeviceInfo().GetDeviceClass(); + if (GX_DEVICE_CLASS_GEV == objDeviceClass) + { + // ÅжÏÉ豸ÊÇ·ñÖ§³ÖÁ÷ͨµÀÊý¾Ý°ü¹¦ÄÜ + if (true == m_objFeatureControlPtr->IsImplemented("GevSCPSPacketSize")) + { + // »ñÈ¡µ±Ç°ÍøÂç»·¾³µÄ×îÓÅ°ü³¤Öµ + int nPacketSize = m_objStreamPtr->GetOptimalPacketSize(); + // ½«×îÓÅ°ü³¤ÖµÉèÖÃΪµ±Ç°É豸µÄÁ÷ͨµÀ°ü³¤Öµ + CIntFeaturePointer GevSCPD = m_objFeatureControlPtr->GetIntFeature("GevSCPSPacketSize"); + m_objFeatureControlPtr->GetIntFeature("GevSCPSPacketSize")->SetValue(nPacketSize); + m_objFeatureControlPtr->GetIntFeature("GevHeartbeatTimeout")->SetValue(300000); + ////Inter packet delay for GigE Camera + CPropertyAction* pAct = new CPropertyAction(this, &ClassGalaxy::OnInterPacketDelay); + int ret = CreateProperty("InterPacketDelay", CDeviceUtils::ConvertToString((long)nPacketSize), MM::Integer, false, pAct); + SetPropertyLimits("InterPacketDelay", (double)GevSCPD->GetMin(), (double)GevSCPD->GetMax()); + assert(ret == DEVICE_OK); + } + //µÚ¶þ¸ö²ÎÊýΪÓû§Ë½ÓвÎÊý£¬Óû§¿ÉÒÔÔڻص÷º¯ÊýÄÚ²¿½«Æ仹ԭȻʹÓã¬Èç¹û²»ÐèÒªÔò¿É´«Èë NULL ¼´¿É + //hDeviceOffline = m_objDevicePtr->RegisterDeviceOfflineCallback(pDeviceOfflineEventHandler, this); + } + else if (GX_DEVICE_CLASS_U3V == objDeviceClass) + { + CIntFeaturePointer DeviceLinkThroughputLimit = m_objFeatureControlPtr->GetIntFeature("DeviceLinkThroughputLimit"); + if (1) + { + DeviceLinkThroughputLimit_ = DeviceLinkThroughputLimit->GetValue(); + CPropertyAction* pAct = new CPropertyAction(this, &ClassGalaxy::OnDeviceLinkThroughputLimit); + + int ret = CreateProperty("DeviceLinkThroughputLimit", CDeviceUtils::ConvertToString((long)DeviceLinkThroughputLimit_), MM::Integer, false, pAct); + SetPropertyLimits("DeviceLinkThroughputLimit", (double)DeviceLinkThroughputLimit->GetMin(), (double)DeviceLinkThroughputLimit->GetMax()); + assert(ret == DEVICE_OK); + } + } + + //ÑÕÉ«ÅÐ¶Ï + gxstring strValue = ""; + if (m_objDevicePtr->GetRemoteFeatureControl()->IsImplemented("PixelColorFilter")) + { + strValue = m_objDevicePtr->GetRemoteFeatureControl()->GetEnumFeature("PixelColorFilter")->GetValue(); + + if ("None" != strValue) + { + colorCamera_ = true; + + } + } + stringstream msg; + //msg << "using camera " << m_objDevicePtr->GetDeviceInfo().GetDisplayName(); + //AddToLog(msg.str()); + msg << "using camera " << m_objFeatureControlPtr->GetStringFeature("DeviceUserID")->GetValue(); + AddToLog(msg.str()); + // initialize the pylon image formatter. ÅжÏÏà»úͼÏñÊä³ö¸ñʽ-ÕÔΰ¸¦ + // + // Name + int ret = CreateProperty(MM::g_Keyword_Name, g_CameraDeviceName, MM::String, true); + if (DEVICE_OK != ret) + return ret; + + // Description + ret = CreateProperty(MM::g_Keyword_Description, "Daheng Camera device adapter", MM::String, true); + if (DEVICE_OK != ret) + return ret; + + // Serial Number + ret = CreateProperty(MM::g_Keyword_CameraID, serialNumber, MM::String, true); + if (DEVICE_OK != ret) + return ret; + + //Get information about camera (e.g. height, width, byte depth) + //check if given Camera support event. //Register Camera events + //ÕÔΰ¸¦£º×¢²áÏà»úʼþ£¬×¢²á²É¼¯»Øµ÷-δ¼Ó ζÈʼþ + + CIntFeaturePointer width = m_objFeatureControlPtr->GetIntFeature("Width"); + CIntFeaturePointer height = m_objFeatureControlPtr->GetIntFeature("Height"); + + //×ÜÊôÐÔÆ÷ + if (1) + { + CPropertyAction* pAct = new CPropertyAction(this, &ClassGalaxy::OnWidth); + ret = CreateProperty("SensorWidth", CDeviceUtils::ConvertToString((int)width->GetValue()), MM::Integer, false, pAct); + SetPropertyLimits("SensorWidth", (double)width->GetMin(), (double)width->GetMax()); + assert(ret == DEVICE_OK); + } + + if (1) + { + CPropertyAction* pAct = new CPropertyAction(this, &ClassGalaxy::OnHeight); + ret = CreateProperty("SensorHeight", CDeviceUtils::ConvertToString((int)height->GetValue()), MM::Integer, false, pAct); + SetPropertyLimits("SensorHeight", (double)height->GetMin(), (double)height->GetMax()); + assert(ret == DEVICE_OK); + } + + maxWidth_ = (unsigned int) m_objFeatureControlPtr->GetIntFeature("WidthMax")->GetValue(); + maxHeight_ = (unsigned int) m_objFeatureControlPtr->GetIntFeature("HeightMax")->GetValue(); + + + //end of Sensor size + long bytes = (long)(height->GetValue() * width->GetValue() * 4); + //20221020ÕÔΰ¸¦ + //Buffer4ContinuesShot = malloc(bytes); + + + CFloatFeaturePointer exposure = m_objFeatureControlPtr->GetFloatFeature("ExposureTime"); + exposure_us_ = exposure->GetValue(); + exposureMax_ = exposure->GetMax(); + exposureMin_ = exposure->GetMin(); + CPropertyAction* pAct = new CPropertyAction(this, &ClassGalaxy::OnExposure); + ret = CreateProperty("Exposure(us)", CDeviceUtils::ConvertToString((long)exposure->GetValue()), MM::Float, false, pAct); + SetPropertyLimits("Exposure(us)", exposureMin_, exposureMax_); + assert(ret == DEVICE_OK); + + pAct = new CPropertyAction(this, &ClassGalaxy::OnPixelType); + ret = CreateProperty(MM::g_Keyword_PixelType, "NA", MM::String, false, pAct); + assert(ret == DEVICE_OK); + vector pixelTypeValues; + CEnumFeaturePointer PixelFormatList = m_objFeatureControlPtr->GetEnumFeature("PixelFormat"); + gxstring_vector LisePixelFormat = PixelFormatList->GetEnumEntryList(); + //ΪÁ˸³ÖµÓà + for (size_t i = 0; i < LisePixelFormat.size(); i++) + { + string strValue(LisePixelFormat[i]); + pixelTypeValues.push_back(strValue); + + } + pixelType_ = PixelFormatList->GetValue(); + SetAllowedValues(MM::g_Keyword_PixelType, pixelTypeValues); + CEnumFeaturePointer pixelFormat_ = m_objFeatureControlPtr->GetEnumFeature("PixelFormat"); + SetProperty(MM::g_Keyword_PixelType, pixelFormat_->GetValue().c_str()); + + + if (1) + { + // ResultingFrameRatePrevious = 8; + // acqFramerate_ = 8, acqFramerateMax_ = 8, acqFramerateMin_ = 0.1; + gain_ = 8, gainMax_ = 8, gainMin_ = 0; + offset_ = 0, offsetMin_ = 0, offsetMax_ = 8; + + binningFactor_ = "1"; + reverseX_ = "0"; reverseY_ = "0"; + sensorReadoutMode_ = "Undefined"; + setAcqFrm_ = ""; + shutterMode_ = "None"; + temperature_ = ""; + temperatureState_ = "Undefined"; + } + + if (m_objDevicePtr->GetRemoteFeatureControl()->IsImplemented("BinningHorizontal") + && m_objDevicePtr->GetRemoteFeatureControl()->IsImplemented("BinningVertical")) + { + pAct = new CPropertyAction(this, &ClassGalaxy::OnBinning); + ret = CreateProperty(MM::g_Keyword_Binning, "1", MM::Integer, false, pAct); + + assert(ret == DEVICE_OK); + CIntFeaturePointer BinningHorizontal = m_objFeatureControlPtr->GetIntFeature("BinningHorizontal"); + CIntFeaturePointer BinningVertical = m_objFeatureControlPtr->GetIntFeature("BinningVertical"); + //assumed that BinningHorizontal and BinningVertical allow same steps + SetPropertyLimits(MM::g_Keyword_Binning, (double)BinningHorizontal->GetMin(), (double)BinningHorizontal->GetMax()); + binningFactor_.assign(CDeviceUtils::ConvertToString((long)BinningHorizontal->GetValue())); + CheckForBinningMode(pAct); + + } + /////Trigger Mode////// + //CEnumerationPtr TriggerMode(nodeMap_->GetNode("TriggerMode")); + + CEnumFeaturePointer TriggerMode = m_objFeatureControlPtr->GetEnumFeature("TriggerMode"); + if (!TriggerMode.IsNull()) + { + pAct = new CPropertyAction(this, &ClassGalaxy::OnTriggerMode); + ret = CreateProperty("TriggerMode", "Off", MM::String, false, pAct); + vector LSPVals; + LSPVals.push_back("Off"); + LSPVals.push_back("On"); + SetAllowedValues("TriggerMode", LSPVals); + } + /////Trigger Source////// + CEnumFeaturePointer triggersource = m_objFeatureControlPtr->GetEnumFeature("TriggerSource"); + //CEnumerationPtr triggersource(nodeMap_->GetNode("TriggerSource")); + if (!triggersource.IsNull()) + { + pAct = new CPropertyAction(this, &ClassGalaxy::OnTriggerSource); + ret = CreateProperty("TriggerSource", "NA", MM::String, false, pAct); + vector LSPVals; + //NodeList_t entries; + //triggersource->GetEntries(entries); + gxstring_vector entries = triggersource->GetEnumEntryList(); + for (size_t i = 0; i < entries.size(); i++) + { + string strValue(entries[i]); + /*if (strValue.find("Software") == std::string::npos) + {*/ + //Software Execute button not implement yet. + LSPVals.push_back(strValue); + //} + } + SetAllowedValues("TriggerSource", LSPVals); + } + //20230217ÉèÖÃÆÚÍûÖ¡ÂÊʹÄÜ + if (m_objDevicePtr->GetRemoteFeatureControl()->IsImplemented("AcquisitionFrameRateMode")) + { + CEnumFeaturePointer AdjFrameRateMode = m_objFeatureControlPtr->GetEnumFeature("AcquisitionFrameRateMode"); + pAct = new CPropertyAction(this, &ClassGalaxy::OnAdjFrameRateMode); + ret = CreateProperty("AcquisitionFrameRateMode", "NA", MM::String, false, pAct); + vector LSPVals; + gxstring_vector entries = AdjFrameRateMode->GetEnumEntryList(); + for (size_t i = 0; i < entries.size(); i++) + { + string strValue(entries[i]); + LSPVals.push_back(strValue); + } + SetAllowedValues("AcquisitionFrameRateMode", LSPVals); + } + + if (m_objDevicePtr->GetRemoteFeatureControl()->IsImplemented("AcquisitionFrameRate")) + { + CFloatFeaturePointer AdjFrameRate = m_objFeatureControlPtr->GetFloatFeature("AcquisitionFrameRate"); + pAct = new CPropertyAction(this, &ClassGalaxy::OnAcquisitionFrameRate); + ret = CreateProperty("AcquisitionFrameRate", CDeviceUtils::ConvertToString((float)0), MM::Float, false, pAct); + //µ±Ç°²É¼¯Ö¡ÂÊÐèÖØмÆËã + SetPropertyLimits("AcquisitionFrameRate", (double)AdjFrameRate->GetMin(), (double)AdjFrameRate->GetMax()); + assert(ret == DEVICE_OK); + } + //TriggerActivation + if (m_objDevicePtr->GetRemoteFeatureControl()->IsImplemented("TriggerSelector")) + { + m_objFeatureControlPtr->GetEnumFeature("TriggerSelector")->SetValue("FrameStart"); + pAct = new CPropertyAction(this, &ClassGalaxy::OnTriggerActivation); + ret = CreateProperty("TriggerActivation", "NA", MM::String, false, pAct); + vector LSPVals; + gxstring_vector entries = triggersource->GetEnumEntryList(); + for (size_t i = 0; i < entries.size(); i++) + { + string strValue(entries[i]); + LSPVals.push_back(strValue); + } + SetAllowedValues("TriggerActivation", LSPVals); + m_objFeatureControlPtr->GetEnumFeature("TriggerActivation")->SetValue("RisingEdge"); + + //string s = m_objFeatureControlPtr->GetEnumFeature("TriggerActivation")->GetValue(); + } + //TriggerDelay + if (m_objDevicePtr->GetRemoteFeatureControl()->IsImplemented("TriggerDelay")) + { + CFloatFeaturePointer TriggerDelay = m_objFeatureControlPtr->GetFloatFeature("TriggerDelay"); + + pAct = new CPropertyAction(this, &ClassGalaxy::OnTriggerDelay); + ret = CreateProperty("TriggerDelay", CDeviceUtils::ConvertToString((double)0), MM::Integer, false, pAct); + + SetPropertyLimits("TriggerDelay", (double)TriggerDelay->GetMin(), (double)TriggerDelay->GetMax()); + assert(ret == DEVICE_OK); + } + //TriggerFilterRaisingEdge + if (m_objDevicePtr->GetRemoteFeatureControl()->IsImplemented("TriggerFilterRaisingEdge")) + { + CFloatFeaturePointer TriggerFilterRaisingEdge = m_objFeatureControlPtr->GetFloatFeature("TriggerFilterRaisingEdge"); + + pAct = new CPropertyAction(this, &ClassGalaxy::OnTriggerFilterRaisingEdge); + ret = CreateProperty("TriggerFilterRaisingEdge", CDeviceUtils::ConvertToString((double)0), MM::Integer, false, pAct); + + SetPropertyLimits("TriggerFilterRaisingEdge", (double)TriggerFilterRaisingEdge->GetMin(), (double)TriggerFilterRaisingEdge->GetMax()); + + assert(ret == DEVICE_OK); + + } + //ÔöÒæ + m_objFeatureControlPtr->GetEnumFeature("GainSelector")->SetValue("AnalogAll"); + m_objFeatureControlPtr->GetFloatFeature("Gain")->SetValue(0.0000); + double d = m_objFeatureControlPtr->GetFloatFeature("Gain")->GetValue(); + if (m_objDevicePtr->GetRemoteFeatureControl()->IsImplemented("Gain")) + { + CFloatFeaturePointer Gain = m_objFeatureControlPtr->GetFloatFeature("Gain"); + + pAct = new CPropertyAction(this, &ClassGalaxy::OnGain); + ret = CreateProperty("Gain", CDeviceUtils::ConvertToString((double)0), MM::Integer, false, pAct); + SetPropertyLimits("Gain", (double)Gain->GetMin(), (double)Gain->GetMax()); + assert(ret == DEVICE_OK); + } + //20230220ÉèÖÃͼÏñת»»RGBA8 + ret = UpdateStatus(); + + if (ret != DEVICE_OK) + return ret; + //preparation for snaps + ResizeSnapBuffer(); + //preparation for sequences + //camera_->RegisterImageEventHandler( &ImageHandler_, RegistrationMode_Append, Cleanup_Delete); + ///////////////////////////////////////////////////////////////////////////////////////// + initialized_ = true; + return DEVICE_OK; + } + catch (CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + } + return DEVICE_ERR; + +} + +void ClassGalaxy::CoverToRGB(GX_PIXEL_FORMAT_ENTRY emDstFormat,void* DstBuffer, CImageDataPointer pObjSrcImageData) +{ + try + { + TestFormatConvertPtr = IGXFactory::GetInstance().CreateImageFormatConvert(); + TestFormatConvertPtr->SetDstFormat(emDstFormat); + TestFormatConvertPtr->SetInterpolationType(GX_RAW2RGB_NEIGHBOUR); + TestFormatConvertPtr->SetAlphaValue(255); + uint64_t Size = TestFormatConvertPtr->GetBufferSizeForConversion(pObjSrcImageData); + TestFormatConvertPtr->Convert(pObjSrcImageData, DstBuffer, Size, false); //modify by LXM in 20240305 + //×¢ÒⶼÄÜÏÔʾ16λͼÏñRGB + } + catch (CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + } + + + +} +int ClassGalaxy::CheckForBinningMode(CPropertyAction* pAct) +{ + // Binning Mode + //INodeMap& nodeMap(camera_->GetNodeMap()); + CEnumFeaturePointer BinningHorizontalMode = m_objFeatureControlPtr->GetEnumFeature("BinningHorizontalMode"); + + CEnumFeaturePointer BinningVerticalMode = m_objFeatureControlPtr->GetEnumFeature("BinningVerticalMode"); + + pAct = new CPropertyAction(this, &ClassGalaxy::OnBinningMode); + + vector LSPVals; + + gxstring_vector LiseBinningHorizontalMode = BinningHorizontalMode->GetEnumEntryList(); + //ΪÁ˸³ÖµÓà + for (size_t i = 0; i < LiseBinningHorizontalMode.size(); i++) + { + string strValue(LiseBinningHorizontalMode[i]); + LSPVals.push_back(strValue); + } + SetAllowedValues("BinningHorizontalMode", LSPVals); + SetAllowedValues("BinningVerticalMode", LSPVals); + return DEVICE_OK; +} +int ClassGalaxy::OnBinningMode(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + CEnumFeaturePointer BinningHorizontalMode = m_objFeatureControlPtr->GetEnumFeature("BinningHorizontalMode"); + + CEnumFeaturePointer BinningVerticalMode = m_objFeatureControlPtr->GetEnumFeature("BinningVerticalMode"); + + if (eAct == MM::AfterSet) + { + try + { + string binningMode; + pProp->Get(binningMode); + BinningHorizontalMode->SetValue(binningMode.c_str()); + BinningVerticalMode->SetValue(binningMode.c_str()); + } + catch (CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + } + else if (eAct == MM::BeforeGet) + { + try { + pProp->Set(((BinningVerticalMode->GetValue()).c_str())); + } + catch (CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + } + return DEVICE_OK; +} +int ClassGalaxy::Shutdown() +{ + //¹Ø±ÕÏà»ú + try + { + //ÅжÏÊÇ·ñÍ£Ö¹²É¼¯ + if (m_objStreamFeatureControlPtr->GetBoolFeature("StreamIsGrabbing")->GetValue()) + { + //·¢ËÍÍ£²ÉÃüÁî + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); + //¹Ø±ÕÁ÷²ã²É¼¯ + m_objStreamPtr->StopGrab(); + //×¢Ïú²É¼¯»Øµ÷º¯Êý + m_objStreamPtr->UnregisterCaptureCallback(); + + } + } + catch (CGalaxyException& e) + { + LogMessage(e.what()); + } + try + { + //¹Ø±ÕÁ÷¶ÔÏó + m_objStreamPtr->Close(); + + //¹Ø±ÕÉ豸 + m_objDevicePtr->Close(); + } + catch (CGalaxyException& e) + { + LogMessage(e.what()); + } + m_bIsOpen = false; + AddToLog("ShutDown"); + return 0; +} + +void ClassGalaxy::GetName(char* name) const +{ + CDeviceUtils::CopyLimitedString(name, g_CameraDeviceName); +} + + +int ClassGalaxy::SnapImage() +{ + try + { + AddToLog("ReadySnapImage"); + //camera_->StartGrabbing(1, GrabStrategy_OneByOne, GrabLoop_ProvidedByUser); + // modify by LXM in 20240305 + //if (m_bIsOpen) + { + //AddToLog("---------------ÅжÏÊÇ·ñ¿ª²É"); + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); + m_objStreamPtr->StopGrab(); + //camera_->DeregisterImageEventHandler(ImageHandler_); + if (ImageHandler_ != NULL) + { + m_objStreamPtr->UnregisterCaptureCallback(); + delete ImageHandler_; + ImageHandler_ = NULL; + + } + } + //end modify + + int timeout_ms = 5000; + //¿ªÆôÁ÷²ã²É¼¯ + m_objStreamPtr->StartGrab(); + //·¢ËÍ¿ª²ÉÃüÁî + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute(); + m_bIsOpen = true;//modify by LXM + m_objStreamPtr->FlushQueue(); + //¿ÉÒÔʹÓòɵ¥Ö¡À´»ñÈ¡ + CImageDataPointer ptrGrabResult = m_objStreamPtr->GetImage(timeout_ms); + uint64_t length = ptrGrabResult->GetPayloadSize(); + + if (ptrGrabResult->GetPayloadSize() != imgBufferSize_) + { // due to parameter change on binning + ResizeSnapBuffer(); + } + CopyToImageBuffer(ptrGrabResult); + + } + catch (const CGalaxyException& e) + { + + string a = e.what(); + AddToLog(e.what()); + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); + //¹Ø±ÕÁ÷²ã²É¼¯ + m_objStreamPtr->StopGrab(); + return DEVICE_ERR; + } + catch (const std::exception& e) + { + AddToLog(e.what()); + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); + //¹Ø±ÕÁ÷²ã²É¼¯ + m_objStreamPtr->StopGrab(); + return DEVICE_ERR; + } + AddToLog("SnapImage"); + return DEVICE_OK; + +} +void ClassGalaxy::CopyToImageBuffer(CImageDataPointer& objImageDataPointer) +{ + + if (1) + { + GetImageSize(); + const char* subject("Bayer"); + //gxstring pixelFormat_gx = m_objFeatureControlPtr->GetEnumFeature("PixelFormat")->GetValue(); + + std::size_t found = pixelType_.find(subject); + //pixelType_.assign(pixelFormat_gx); + //Ïà»úÀàÐÍ-Ã÷È·Ïà»úµÄÊä³öÐÎʽ--´ýÈ·ÈÏ + GX_VALID_BIT_LIST emValidBits = GX_BIT_0_7; + //Ã÷È·Ïà»úµÄ²Éͼ¸ñʽ + emValidBits = GetBestValudBit(objImageDataPointer->GetPixelFormat()); + + if (found != std::string::npos) + { + IsByerFormat = true; + } + if (pixelType_.compare("Mono8") == 0) + { + // Workaround : OnPixelType call back will not be fired always. + //copy image buffer to a snap buffer allocated by device adapter + const void* buffer = objImageDataPointer->GetBuffer(); + memcpy(imgBuffer_, buffer, GetImageBufferSize()); + SetProperty(MM::g_Keyword_PixelType, g_PixelType_8bit); + } + //20221025´ý¶¨ÆäËûÑÕÉ«¸ñʽ + else if (pixelType_.compare("Mono16") == 0 || pixelType_.compare("Mono12") == 0 || pixelType_.compare("Mono10") == 0) + { + //ºÚ°×8-16λ + //copy image buffer to a snap buffer allocated by device adapter + void* buffer = objImageDataPointer->GetBuffer(); + memcpy(imgBuffer_, buffer, GetImageBufferSize()); + SetProperty(MM::g_Keyword_PixelType, g_PixelType_16bit); + } + else if (IsByerFormat && pixelType_.size() == 8) + { + try + { + RG8ToRGB24Packed(imgBuffer_, objImageDataPointer); + + SetProperty(MM::g_Keyword_PixelType, g_PixelType_8bitRGBA); + } + catch (const CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + } + else if (IsByerFormat && pixelType_.size() == 9) + { + try + { + RG10ToRGB24Packed(imgBuffer_, objImageDataPointer); + SetProperty(MM::g_Keyword_PixelType, g_PixelType_8bitRGBA); + } + catch (const CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + + } + } +} + +int ClassGalaxy::StartSequenceAcquisition(long /* numImages */, double /* interval_ms */, bool /* stopOnOverflow */) { + try + { + AddToLog("ReadyMuiltySequenceAcquisition"); + ImageHandler_ = new CircularBufferInserter(this); + //camera_->RegisterImageEventHandler(ImageHandler_, RegistrationMode_Append, Cleanup_Delete); + m_objStreamPtr->RegisterCaptureCallback(ImageHandler_, this); + + //camera_->StartGrabbing(numImages, GrabStrategy_OneByOne, GrabLoop_ProvidedByInstantCamera); + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute(); + //¿ªÆôÁ÷²ã²É¼¯ + m_objStreamPtr->StartGrab(); + + int ret = GetCoreCallback()->PrepareForAcq(this); + if (ret != DEVICE_OK) { + return ret; + } + + AddToLog("StartSequenceAcquisition"); + } + catch (const CGalaxyException& e) + { + string a = e.what(); + AddToLog(e.what()); + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); + //¹Ø±ÕÁ÷²ã²É¼¯ + m_objStreamPtr->StopGrab(); + return DEVICE_ERR; + } + catch (const std::exception& e) + { + AddToLog(e.what()); + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); + //¹Ø±ÕÁ÷²ã²É¼¯ + m_objStreamPtr->StopGrab(); + return DEVICE_ERR; + } + return DEVICE_OK; +} +int ClassGalaxy::StartSequenceAcquisition(double /* interval_ms */) { + try + { + AddToLog("ReadySequenceAcquisition"); + //modify by LXM in 20240306 + //if (m_bIsOpen) + { + //AddToLog("---------------ÅжÏÊÇ·ñ¿ª²É"); + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); + m_objStreamPtr->StopGrab(); + } + //end modify + + ImageHandler_ = new CircularBufferInserter(this); + //camera_->RegisterImageEventHandler(ImageHandler_, RegistrationMode_Append, Cleanup_Delete); + m_objStreamPtr->RegisterCaptureCallback(ImageHandler_, this); + + int ret = GetCoreCallback()->PrepareForAcq(this); + if (ret != DEVICE_OK) { + return ret; + } + //camera_->StartGrabbing(numImages, GrabStrategy_OneByOne, GrabLoop_ProvidedByInstantCamera); + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute(); + //¿ªÆôÁ÷²ã²É¼¯ + m_objStreamPtr->StartGrab(); + AddToLog("StartSequenceAcquisition"); + } + catch (const CGalaxyException& e) + { + string a = e.what(); + AddToLog(e.what()); + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); + //¹Ø±ÕÁ÷²ã²É¼¯ + m_objStreamPtr->StopGrab(); + return DEVICE_ERR; + } + catch (const std::exception& e) + { + AddToLog(e.what()); + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); + //¹Ø±ÕÁ÷²ã²É¼¯ + m_objStreamPtr->StopGrab(); + return DEVICE_ERR; + } + return DEVICE_OK; +} +int ClassGalaxy::StopSequenceAcquisition() +{ + + + if (m_objStreamFeatureControlPtr->GetBoolFeature("StreamIsGrabbing")->GetValue()) + { + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); + m_objStreamPtr->StopGrab(); + GetCoreCallback()->AcqFinished(this, 0); + //camera_->DeregisterImageEventHandler(ImageHandler_); + m_objStreamPtr->UnregisterCaptureCallback(); + } + AddToLog("StopSequenceAcquisition"); + return DEVICE_OK; +} + +int ClassGalaxy::PrepareSequenceAcqusition() +{ + AddToLog("PrepareSequenceAcqusition"); + // nothing to prepare + return DEVICE_OK; +} + +void ClassGalaxy::ResizeSnapBuffer() { + + free(imgBuffer_); + GetImageSize(); + imageBufferSize_ = Width_ * Height_ * GetImageBytesPerPixel();//Ô­ÏÈÊÇbuffersize + imgBuffer_ = malloc(imageBufferSize_); +} + +bool ClassGalaxy::__IsPixelFormat8(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry) +{ + bool bIsPixelFormat8 = false; + const unsigned PIXEL_FORMATE_BIT = 0x00FF0000; ///<ÓÃÓÚÓ뵱ǰµÄÊý¾Ý¸ñʽ½øÐÐÓëÔËËãµÃµ½µ±Ç°µÄÊý¾ÝλÊý + unsigned uiPixelFormatEntry = (unsigned)emPixelFormatEntry; + if ((uiPixelFormatEntry & PIXEL_FORMATE_BIT) == GX_PIXEL_8BIT) + { + bIsPixelFormat8 = true; + } + return bIsPixelFormat8; +} + + +unsigned char* ClassGalaxy::GetImageBufferFromCallBack(CImageDataPointer& objImageDataPointer) +{ + + INT64 Width_ = m_objFeatureControlPtr->GetIntFeature("Width")->GetValue(); + + INT64 Height_ = m_objFeatureControlPtr->GetIntFeature("Height")->GetValue(); + //Ïà»úÀàÐÍ-Ã÷È·Ïà»úµÄÊä³öÐÎʽ--´ýÈ·ÈÏ + GX_VALID_BIT_LIST emValidBits = GX_BIT_0_7; + //Ã÷È·Ïà»úµÄ²Éͼ¸ñʽ + emValidBits = GetBestValudBit(objImageDataPointer->GetPixelFormat()); + + if (colorCamera_) + { + imgBuffer_2 = (unsigned char*)objImageDataPointer->ConvertToRGB24(emValidBits, GX_RAW2RGB_NEIGHBOUR, true); + } + else + { + if (__IsPixelFormat8(objImageDataPointer->GetPixelFormat())) + { + imgBuffer_2 = (BYTE*)objImageDataPointer->GetBuffer(); + } + else + { + imgBuffer_2 = (BYTE*)objImageDataPointer->ConvertToRaw8(emValidBits); + } + + // ºÚ°×Ïà»úÐèÒª·­×ªÊý¾ÝºóÏÔʾ + for (int i = 0; i < Height_; i++) + { + //º¬Òå + memcpy(m_pImageBuffer + i * Width_, imgBuffer_2 + (Height_ - i - 1) * Width_, (size_t)Width_); + return (unsigned char*)imgBuffer_; + } + } + //»ñȡͼÏñbuffer + return (unsigned char*)imgBuffer_; + +} + +const unsigned char* ClassGalaxy::GetImageBuffer() +{ + //°´ÕÕºÚ°×ÏÔʾ + return (unsigned char*)imgBuffer_; + +} + +void ClassGalaxy::GetImageSize() +{ + Width_= (unsigned int) m_objFeatureControlPtr->GetIntFeature("Width")->GetValue(); + Height_ = (unsigned int) m_objFeatureControlPtr->GetIntFeature("Height")->GetValue(); +} + +unsigned ClassGalaxy::GetNumberOfComponents() const +{ + return nComponents_; +} + +unsigned ClassGalaxy::GetImageWidth() const +{ + //mutable unsigned Width_ = m_objFeatureControlPtr->GetIntFeature("Width")->GetValue(); + + return Width_; +} + +unsigned ClassGalaxy::GetImageHeight() const +{ + return Height_; +} + +long ClassGalaxy::GetImageBufferSize()const +{ + return imageBufferSize_; + + //return GetImageWidth() * GetImageHeight() * GetImageBytesPerPixel(); +} + +long ClassGalaxy::GetImageSizeLarge()const +{ + return Width_ * Height_; + + //return GetImageWidth() * GetImageHeight() * GetImageBytesPerPixel(); +} + +int ClassGalaxy::OnBinning(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + CIntFeaturePointer BinningHorizontal = m_objFeatureControlPtr->GetIntFeature("BinningHorizontal"); + + CIntFeaturePointer BinningVertical = m_objFeatureControlPtr->GetIntFeature("BinningVertical"); + //CIntegerPtr BinningHorizontal(nodeMap_->GetNode("BinningHorizontal")); + //CIntegerPtr BinningVertical(nodeMap_->GetNode("BinningVertical")); + + if (eAct == MM::AfterSet) + { + bool Isgrabbing = m_objStreamFeatureControlPtr->GetBoolFeature("StreamIsGrabbing")->GetValue(); + + try + { + if (Isgrabbing) + { + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); + //¹Ø±ÕÁ÷²ã²É¼¯ + m_objStreamPtr->StopGrab(); + } + pProp->Get(binningFactor_); + int64_t val = std::atoi(binningFactor_.c_str()); + BinningHorizontal->SetValue(val); + BinningVertical->SetValue(val); + if (Isgrabbing) + { + //ÖØ¿ª + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute(); + m_objStreamPtr->StartGrab(); + + } + pProp->Set(binningFactor_.c_str()); + } + catch (CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + } + else if (eAct == MM::BeforeGet) { + + try { + binningFactor_ = CDeviceUtils::ConvertToString((long)BinningHorizontal->GetValue()); + pProp->Set((long)BinningHorizontal->GetValue()); + } + catch (CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + } + return DEVICE_OK; +} + +int ClassGalaxy::OnDeviceLinkThroughputLimit(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + return 0; +} + +int ClassGalaxy::OnExposure(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + if (eAct == MM::AfterSet) + { + try + { + pProp->Get(exposure_us_); + m_objFeatureControlPtr->GetFloatFeature("ExposureTime")->SetValue(exposure_us_); + } + catch (CGalaxyException& e) + { + AddToLog(e.what()); + } + } + else if (eAct == MM::BeforeGet) + { + try + { + exposure_us_ = m_objFeatureControlPtr->GetFloatFeature("ExposureTime")->GetValue(); + pProp->Set(exposure_us_); + } + catch (CGalaxyException& e) + { + AddToLog(e.what()); + } + } + return DEVICE_OK; +} + +int ClassGalaxy::OnGain(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + try + { + //CFloatPtr gain(nodeMap_->GetNode("Gain")); + //CIntegerPtr GainRaw(nodeMap_->GetNode("GainRaw")); + CFloatFeaturePointer gain = m_objFeatureControlPtr->GetFloatFeature("Gain"); + if (eAct == MM::AfterSet) { + pProp->Get(gain_); + if (gain_ > gain->GetMax()) { + gain_ = gain->GetMax(); + } + if (gain_ < gain->GetMin()) { + gain_ = gain->GetMin(); + } + if (1) + { + // the range gain depends on Pixel format sometimes. + if (gain->GetMin() <= gain_ && gain->GetMax() >= gain_) + { + gain->SetValue(gain_); + } + else + { + AddToLog("gain value out of range"); + gainMax_ = gain->GetMax(); + gainMin_ = gain->GetMin(); + gain_ = gain->GetValue(); + SetPropertyLimits(MM::g_Keyword_Gain, gainMin_, gainMax_); + pProp->Set(gain_); + } + } + } + else if (eAct == MM::BeforeGet) { + + if (1) + { + gain_ = gain->GetValue(); + pProp->Set(gain_); + } + } + } + catch (const CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + return DEVICE_ERR; + } + return DEVICE_OK; +} + +int ClassGalaxy::OnHeight(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + CIntFeaturePointer Height = m_objFeatureControlPtr->GetIntFeature("Height"); + + std::string strval; + if (eAct == MM::AfterSet) + { + bool Isgrabbing = m_objStreamFeatureControlPtr->GetBoolFeature("StreamIsGrabbing")->GetValue();; + if (Height.getUse()) + { + try + { + if (Isgrabbing) + { + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); + //¹Ø±ÕÁ÷²ã²É¼¯ + m_objStreamPtr->StopGrab(); + //camera_->StopGrabbing(); + } + pProp->Get(strval); + int64_t val = std::atoi(strval.c_str()); + int64_t inc = Height->GetInc(); + Height->SetValue(val - (val % inc)); + + if (Isgrabbing) + { + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute(); + m_objStreamPtr->StartGrab(); + } + pProp->Set((long)Height->GetValue()); + + } + catch (CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + } + } + else if (eAct == MM::BeforeGet) { + + try { + if (Height.getUse()) + { + pProp->Set((long)Height->GetValue()); + } + } + catch (CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + } + + AddToLog(to_string((long)Height->GetValue())); + GetImageSize(); + return DEVICE_OK; +} + +int ClassGalaxy::OnInterPacketDelay(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + return 0; +} + +int ClassGalaxy::OnPixelType(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + if (m_objStreamFeatureControlPtr->GetBoolFeature("StreamIsGrabbing")->GetValue()) + { + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); + //¹Ø±ÕÁ÷²ã²É¼¯ + m_objStreamPtr->StopGrab(); + } + //CEnumerationPtr pixelFormat(nodeMap_->GetNode("PixelFormat")); + + CEnumFeaturePointer pixelFormat_ = m_objFeatureControlPtr->GetEnumFeature("PixelFormat"); + + if (eAct == MM::AfterSet) { + pProp->Get(pixelType_); + try + { + //´úÂ뱨´í + + //ÉèÖÃÐÂÖµ + pixelFormat_->SetValue(pixelType_.c_str()); + const char* subject("Bayer"); + std::size_t found = pixelType_.find(subject); + if (pixelType_.compare("Mono8") == 0) + { + nComponents_ = 1; + bitDepth_ = 8; + bytesPerPixel_ = 1; + SetProperty(MM::g_Keyword_PixelType, g_PixelType_8bit); + } + else if (pixelType_.compare("Mono10") == 0) + { + nComponents_ = 1; + bitDepth_ = 10; + bytesPerPixel_ = 2; + SetProperty(MM::g_Keyword_PixelType, g_PixelType_10bit); + } + else if (pixelType_.compare("Mono12") == 0) + { + nComponents_ = 2; + bitDepth_ = 12; + bytesPerPixel_ = 1; + SetProperty(MM::g_Keyword_PixelType, g_PixelType_12bit); + } + else if (pixelType_.compare("Mono16") == 0) + { + nComponents_ = 1; + bitDepth_ = 16; + bytesPerPixel_ = 2; + SetProperty(MM::g_Keyword_PixelType, g_PixelType_16bit); + } + else if (found == 0 && pixelType_.size() == 8) + { + nComponents_ = 4; + bitDepth_ = 8; + bytesPerPixel_ = 1; + SetProperty(MM::g_Keyword_PixelType, g_PixelType_8bitRGBA); + } + else if (found == 0 && pixelType_.size() == 9) + { + //nComponents_ = 4 * sizeof(unsigned short int); + nComponents_ = 4; + bitDepth_ = 8; + bytesPerPixel_ = 1; + SetProperty(MM::g_Keyword_PixelType, g_PixelType_8bitRGBA); + } + /* + m_objFeatureControlPtr->GetEnumFeature("BlackLevelSelector")->SetValue("All"); + CFloatFeaturePointer offset = m_objFeatureControlPtr->GetFloatFeature("BlackLevel"); + offsetMax_ = offset->GetMax(); + offsetMin_ = offset->GetMin(); + SetPropertyLimits(MM::g_Keyword_Offset, offsetMin_, offsetMax_); + */ + } + catch (CGalaxyException& e) + { + AddToLog(e.what()); + } + } + else if (eAct == MM::BeforeGet) { + pProp->Set(pixelType_.c_str()); + } + if (1) + { + + if (m_objStreamFeatureControlPtr->GetBoolFeature("StreamIsGrabbing")->GetValue()) + { + //ÖØ¿ª + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute(); + m_objStreamPtr->StartGrab(); + } + } + + return DEVICE_OK; +} + +int ClassGalaxy::OnTriggerSource(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + CEnumFeaturePointer TriggerSource = m_objFeatureControlPtr->GetEnumFeature("TriggerSource"); + + string TriggerSource_; + if (eAct == MM::AfterSet) { + pProp->Get(TriggerSource_); + TriggerSource->SetValue(TriggerSource_.c_str()); + } + else if (eAct == MM::BeforeGet) { + //CEnumerationPtr TriggerSource(nodeMap_->GetNode("TriggerSource")); + pProp->Set(TriggerSource->GetValue().c_str()); + } + return DEVICE_OK; +} + +int ClassGalaxy::OnTriggerMode(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + try + { + CEnumFeaturePointer TriggerMode = m_objFeatureControlPtr->GetEnumFeature("TriggerMode"); + + if (!TriggerMode.IsNull()) + { + if (eAct == MM::AfterSet) { + pProp->Get(TriggerMode_); + + pProp->Set(TriggerMode_.c_str()); + TriggerMode->SetValue(TriggerMode_.c_str()); + } + else if (eAct == MM::BeforeGet) { + pProp->Set(TriggerMode->GetValue().c_str()); + + } + } + } + catch (CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + return DEVICE_OK; +} + +int ClassGalaxy::OnTriggerActivation(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + try + { + CEnumFeaturePointer TriggerActivation = m_objFeatureControlPtr->GetEnumFeature("TriggerActivation"); + + if (!TriggerActivation.IsNull()) + { + if (eAct == MM::AfterSet) { + pProp->Get(TriggerActivation_); + pProp->Set(TriggerActivation_.c_str()); + TriggerActivation->SetValue(TriggerActivation_.c_str()); + } + else if (eAct == MM::BeforeGet) { + pProp->Set(TriggerActivation->GetValue().c_str()); + + } + } + } + catch (CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + return DEVICE_OK; +} + + +//AdjFrameRateMode +int ClassGalaxy::OnAdjFrameRateMode(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + try + { + CEnumFeaturePointer AcquisitionFrameRateMode = m_objFeatureControlPtr->GetEnumFeature("AcquisitionFrameRateMode"); + + if (eAct == MM::AfterSet) { + pProp->Get(AcquisitionFrameRateMode_); + + pProp->Set(AcquisitionFrameRateMode_.c_str()); + AcquisitionFrameRateMode->SetValue(AcquisitionFrameRateMode_.c_str()); + } + else if (eAct == MM::BeforeGet) { + pProp->Set(AcquisitionFrameRateMode->GetValue().c_str()); + } + } + catch (CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + return DEVICE_OK; +} +//OnAcquisitionFrameRate +int ClassGalaxy::OnAcquisitionFrameRate(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + try + { + CFloatFeaturePointer AcquisitionFrameRate = m_objFeatureControlPtr->GetFloatFeature("AcquisitionFrameRate"); + + if (eAct == MM::AfterSet) { + pProp->Get(AcquisitionFrameRate_); + pProp->Set(AcquisitionFrameRate_.c_str()); + AcquisitionFrameRate->SetValue(atoi(AcquisitionFrameRate_.c_str())); + } + else if (eAct == MM::BeforeGet) { + pProp->Set(AcquisitionFrameRate->GetValue()); + } + } + catch (CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + return DEVICE_OK; +} + + +int ClassGalaxy::OnWidth(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + CIntFeaturePointer Width = m_objFeatureControlPtr->GetIntFeature("Width"); + std::string strval; + if (eAct == MM::AfterSet) + { + if (Width.getUse()) + { + try + { + if (m_objStreamFeatureControlPtr->GetBoolFeature("StreamIsGrabbing")->GetValue()) + { + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute(); + //¹Ø±ÕÁ÷²ã²É¼¯ + m_objStreamPtr->StopGrab(); + //camera_->StopGrabbing(); + } + pProp->Get(strval); + int64_t val = std::atoi(strval.c_str()); + int64_t inc = Width->GetInc(); + int64_t a = val - (val % inc); + Width->SetValue(val - (val % inc)); + pProp->Set((long)Width->GetValue()); + if (m_objStreamFeatureControlPtr->GetBoolFeature("StreamIsGrabbing")->GetValue()) + { + m_objFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute(); + m_objStreamPtr->StartGrab(); + } + } + catch (CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + } + } + else if (eAct == MM::BeforeGet) { + try + { + if (Width.getUse()) + { + pProp->Set((long)Width->GetValue()); + } + } + catch (CGalaxyException& e) + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + } + GetImageSize(); + return DEVICE_OK; +} + +int ClassGalaxy::OnTriggerDelay(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + CFloatFeaturePointer TriggerDelay = m_objFeatureControlPtr->GetFloatFeature("TriggerDelay"); + try + { + if (eAct == MM::AfterSet) { + pProp->Get(TriggerDelay_); + pProp->Set(TriggerDelay_.c_str()); + TriggerDelay->SetValue(atoi(TriggerDelay_.c_str())); + } + else if (eAct == MM::BeforeGet) { + pProp->Set(TriggerDelay->GetValue()); + } + } + catch (CGalaxyException& e) + { + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + } + return DEVICE_OK; +} +//OnTriggerFilterRaisingEdge +int ClassGalaxy::OnTriggerFilterRaisingEdge(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + CFloatFeaturePointer TriggerFilterRaisingEdge = m_objFeatureControlPtr->GetFloatFeature("TriggerFilterRaisingEdge"); + try + { + if (eAct == MM::AfterSet) { + pProp->Get(TriggerFilterRaisingEdge_); + pProp->Set(TriggerFilterRaisingEdge_.c_str()); + TriggerFilterRaisingEdge->SetValue(atoi(TriggerFilterRaisingEdge_.c_str())); + } + else if (eAct == MM::BeforeGet) { + pProp->Set(TriggerFilterRaisingEdge->GetValue()); + } + } + catch (CGalaxyException& e) + { + { + // Error handling. + AddToLog(e.what()); + cerr << "An exception occurred." << endl + << e.what() << endl; + } + } + return DEVICE_OK; +} + + + + +unsigned ClassGalaxy::GetImageBytesPerPixel() const +{ + return nComponents_ * bytesPerPixel_; +} + +unsigned ClassGalaxy::GetBitDepth() const +{ + + const char* subject("Bayer"); + std::size_t found = pixelType_.find(subject); + + if (pixelType_ == "Mono8") { + return 8; + } + else if (pixelType_ == "Mono10") { + return 10; + } + else if (pixelType_ == "Mono12") { + return 12; + } + else if (pixelType_ == "Mono16") { + return 16; + } + else if (found != std::string::npos || pixelType_ == "BGR8" || pixelType_ == "RGB8") { + return 8; + } + assert(0); //should not happen + return 0; +} + + + +double ClassGalaxy::GetExposure() const +{ + return exposure_us_ / 1000.0; +} + +void ClassGalaxy::SetExposure(double exp) +{ + // Micro-Manager gives exposure in ms, Galaxy sets it in micro-seconds + try + { + m_objFeatureControlPtr->GetFloatFeature("ExposureTime")->SetValue(exp * 1000.0); + // will this update immediately? + exposure_us_ = m_objFeatureControlPtr->GetFloatFeature("ExposureTime")->GetValue(); + } catch (CGalaxyException& e) + { + AddToLog(e.what()); + } +} + +int ClassGalaxy::SetROI(unsigned x, unsigned y, unsigned xSize, unsigned ySize) +{ + m_objFeatureControlPtr->GetEnumFeature("RegionSelector")->SetValue("Region0"); + + int64_t width = m_objFeatureControlPtr->GetIntFeature("Width")->GetValue(); + int64_t height = m_objFeatureControlPtr->GetIntFeature("Height")->GetValue(); + + m_objFeatureControlPtr->GetIntFeature("Height")->SetValue(width); + m_objFeatureControlPtr->GetIntFeature("Width")->SetValue(height); + + m_objFeatureControlPtr->GetIntFeature("OffsetY")->SetValue(0); + m_objFeatureControlPtr->GetIntFeature("OffsetX")->SetValue(0); + + + + int64_t offsetX = m_objFeatureControlPtr->GetIntFeature("OffsetX")->GetValue(); + + int64_t offsetY = m_objFeatureControlPtr->GetIntFeature("OffsetY")->GetValue(); + + + x -= (x % (unsigned int)m_objFeatureControlPtr->GetFloatFeature("OffsetX")->GetInc()); + y -= (y % (unsigned int)m_objFeatureControlPtr->GetFloatFeature("OffsetY")->GetInc()); + xSize -= (xSize % (unsigned int)m_objFeatureControlPtr->GetFloatFeature("Width")->GetInc()); + ySize -= (ySize % (unsigned int)m_objFeatureControlPtr->GetFloatFeature("Height")->GetInc()); + + if (xSize < (unsigned int)m_objFeatureControlPtr->GetFloatFeature("Width")->GetMin()) { + xSize = (unsigned int)m_objFeatureControlPtr->GetFloatFeature("Width")->GetMin(); + } + if (ySize < (unsigned int)m_objFeatureControlPtr->GetFloatFeature("Height")->GetMin()) { + ySize = (unsigned int)m_objFeatureControlPtr->GetFloatFeature("Height")->GetMin(); + } + if (x < (unsigned int)m_objFeatureControlPtr->GetFloatFeature("offsetX")->GetMin()) { + x = (unsigned int)m_objFeatureControlPtr->GetFloatFeature("offsetX")->GetMin(); + } + if (y < (unsigned int)m_objFeatureControlPtr->GetFloatFeature("offsetY")->GetMin()) { + y = (unsigned int)m_objFeatureControlPtr->GetFloatFeature("offsetY")->GetMin(); + } + + m_objFeatureControlPtr->GetIntFeature("Height")->SetValue(xSize); + m_objFeatureControlPtr->GetIntFeature("Width")->SetValue(ySize); + m_objFeatureControlPtr->GetIntFeature("OffsetY")->SetValue(x); + m_objFeatureControlPtr->GetIntFeature("OffsetX")->SetValue(y); + + //width->SetValue(xSize); + //height->SetValue(ySize); + //offsetX->SetValue(x); + //offsetY->SetValue(y); + + return DEVICE_OK; + +} + +int ClassGalaxy::GetROI(unsigned& x, unsigned& y, unsigned& xSize, unsigned& ySize) +{ + xSize = (unsigned int) m_objFeatureControlPtr->GetIntFeature("Width")->GetValue(); + ySize = (unsigned int) m_objFeatureControlPtr->GetIntFeature("Height")->GetValue(); + + x = (unsigned int) m_objFeatureControlPtr->GetIntFeature("OffsetX")->GetValue(); + y = (unsigned int) m_objFeatureControlPtr->GetIntFeature("OffsetY")->GetValue(); + return DEVICE_OK; +} + +int ClassGalaxy::ClearROI() +{ + int64_t width = m_objFeatureControlPtr->GetIntFeature("Width")->GetMax(); + int64_t height = m_objFeatureControlPtr->GetIntFeature("Height")->GetMax(); + + m_objFeatureControlPtr->GetIntFeature("Height")->SetValue(width); + m_objFeatureControlPtr->GetIntFeature("Width")->SetValue(height); + + m_objFeatureControlPtr->GetIntFeature("OffsetY")->SetValue(0); + m_objFeatureControlPtr->GetIntFeature("OffsetX")->SetValue(0); + return 0; +} + +void ClassGalaxy::ReduceImageSize(int64_t Width, int64_t Height) +{ + //´ý¶¨ + + return ; +} + +int ClassGalaxy::GetBinning() const +{ + return std::atoi(binningFactor_.c_str()); +} + +int ClassGalaxy::SetBinning(int binSize) +{ + cout << "SetBinning called\n"; + if (binSize > 1 && binSize < 4) { + return DEVICE_OK; + } + return DEVICE_UNSUPPORTED_COMMAND; + +} +void ClassGalaxy::RGB24PackedToRGBA(void* destbuffer, void* srcbuffer, CImageDataPointer& objImageDataPointer) +{ + unsigned int srcOffset = 0; + unsigned int dstOffset = 0; + GX_VALID_BIT_LIST emValidBits = GX_BIT_0_7; + uint64_t Payloadsize=objImageDataPointer->GetPayloadSize(); + //Ã÷È·Ïà»úµÄ²Éͼ¸ñʽ + emValidBits = GetBestValudBit(objImageDataPointer->GetPixelFormat()); + if (emValidBits!= GX_BIT_0_7) + { + Payloadsize = Payloadsize / 2; + } + for (size_t i = 0; i < Payloadsize; ++i) + { + try + { // 4 3 + memcpy((BYTE*)destbuffer + dstOffset, (BYTE*)srcbuffer + srcOffset, 3); + srcOffset += 3; + dstOffset += 4; + } + catch (const std::exception& e) + { + AddToLog(e.what()); + } + } +} + +void ClassGalaxy::RG8ToRGB24Packed(void* destbuffer,CImageDataPointer& objImageDataPointer) +{ + //modify by LXM in 20240306 + /*CoverToRGB(GX_PIXEL_FORMAT_RGBA8, imgBuffer_, objImageDataPointer); + return;*/ + //end modify + + //RG8תRGB24 + try + { + GX_VALID_BIT_LIST emValidBits = GX_BIT_0_7; + //Ã÷È·Ïà»úµÄ²Éͼ¸ñʽ + emValidBits = GetBestValudBit(objImageDataPointer->GetPixelFormat()); + + //ΪÁËÏÔʾ£¬ÐèÒª¶¼×ª³ÉRaw8λ + if (emValidBits!= GX_BIT_0_7) + { + return; + } + //RGB24Packed-´óС³ËÒÔ3 + void* buffer = objImageDataPointer->ConvertToRGB24(emValidBits, GX_RAW2RGB_NEIGHBOUR, false); + RGB24PackedToRGBA(destbuffer, buffer, objImageDataPointer); + AddToLog("RG8ToRGB24Packed"); + } + catch (const std::exception e) + { + AddToLog(e.what()); + } +} + +void ClassGalaxy::CoverRGB16ToRGBA16(unsigned short int* Desbuffer, unsigned short int* Srcbuffer) +{ + unsigned int srcOffset = 0; + unsigned int dstOffset = 0; + for (size_t i = 0; i < GetImageSizeLarge(); ++i) + { + try + { // 4 3 + memcpy(Desbuffer + dstOffset, Srcbuffer + srcOffset, 3*sizeof(unsigned short int)); + Desbuffer[i*4+4] = 255; + srcOffset += 3; + dstOffset += 4; + } + catch (const std::exception& e) + { + AddToLog(e.what()); + } + } +} +void ClassGalaxy::RG10ToRGB24Packed(void* pRGB24Bufdest, CImageDataPointer& objImageDataPointer) +{ + if (0) + { + //ת³ÉRGB8*2£¬ÔÚת³ÉRGBA8*2*4 + size_t BufferSize = GetImageSizeLarge() * 3 * sizeof(unsigned short int); + void* RGB16 = malloc(BufferSize); + + CoverToRGB(GX_PIXEL_FORMAT_RGB16, RGB16, objImageDataPointer); + unsigned short int* Src = new unsigned short int[BufferSize](); + memset(Src, 0, BufferSize); + if (RGB16!=nullptr) + { + memcpy(Src, RGB16, BufferSize); + } + BufferSize= GetImageSizeLarge() * 4 * sizeof(unsigned short int); + unsigned short int* Dst = new unsigned short int[BufferSize](); + CoverRGB16ToRGBA16(Dst, Src); + + memcpy(pRGB24Bufdest, Dst, BufferSize); + return; + } + + + GX_VALID_BIT_LIST emValidBits = GX_BIT_0_7; + //Ã÷È·Ïà»úµÄ²Éͼ¸ñʽ + emValidBits = GetBestValudBit(objImageDataPointer->GetPixelFormat()); + + BYTE* pRGB24Buf2 = (BYTE*)objImageDataPointer->ConvertToRGB24(emValidBits, GX_RAW2RGB_NEIGHBOUR, false); + + RGB24PackedToRGBA(pRGB24Bufdest, pRGB24Buf2, objImageDataPointer); + +} +void ClassGalaxy::AddToLog(std::string msg) +{ + LogMessage(msg, false); +} + +GX_VALID_BIT_LIST ClassGalaxy::GetBestValudBit(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry) +{ + GX_VALID_BIT_LIST emValidBits = GX_BIT_0_7; + switch (emPixelFormatEntry) + { + case GX_PIXEL_FORMAT_MONO8: + case GX_PIXEL_FORMAT_BAYER_GR8: + case GX_PIXEL_FORMAT_BAYER_RG8: + case GX_PIXEL_FORMAT_BAYER_GB8: + case GX_PIXEL_FORMAT_BAYER_BG8: + { + emValidBits = GX_BIT_0_7; + if (emPixelFormatEntry!= GX_PIXEL_FORMAT_MONO8) + { + IsByerFormat = true; + } + break; + } + case GX_PIXEL_FORMAT_MONO10: + case GX_PIXEL_FORMAT_BAYER_GR10: + case GX_PIXEL_FORMAT_BAYER_RG10: + case GX_PIXEL_FORMAT_BAYER_GB10: + case GX_PIXEL_FORMAT_BAYER_BG10: + { + emValidBits = GX_BIT_2_9; + if (emPixelFormatEntry != GX_PIXEL_FORMAT_MONO10) + { + IsByerFormat = true; + } + break; + } + case GX_PIXEL_FORMAT_MONO12: + case GX_PIXEL_FORMAT_BAYER_GR12: + case GX_PIXEL_FORMAT_BAYER_RG12: + case GX_PIXEL_FORMAT_BAYER_GB12: + case GX_PIXEL_FORMAT_BAYER_BG12: + { + emValidBits = GX_BIT_4_11; + if (emPixelFormatEntry != GX_PIXEL_FORMAT_MONO12) + { + IsByerFormat = true; + } + break; + } + case GX_PIXEL_FORMAT_MONO14: + { + //ÔÝʱûÓÐÕâÑùµÄÊý¾Ý¸ñʽ´ýÉý¼¶ + break; + } + case GX_PIXEL_FORMAT_MONO16: + case GX_PIXEL_FORMAT_BAYER_GR16: + case GX_PIXEL_FORMAT_BAYER_RG16: + case GX_PIXEL_FORMAT_BAYER_GB16: + case GX_PIXEL_FORMAT_BAYER_BG16: + { + //ÔÝʱûÓÐÕâÑùµÄÊý¾Ý¸ñʽ´ýÉý¼¶ + if (emPixelFormatEntry != GX_PIXEL_FORMAT_MONO16) + { + IsByerFormat = true; + } + break; + } + default: + break; + } + return emValidBits; +} + +CircularBufferInserter::CircularBufferInserter(ClassGalaxy* dev) : + dev_(dev) +{} + //--------------------------------------------------------------------------------- + /** + \brief ²É¼¯»Øµ÷º¯Êý + \param objImageDataPointer ͼÏñ´¦Àí²ÎÊý + \param pFrame Óû§²ÎÊý + \return ÎÞ + */ + //---------------------------------------------------------------------------------- +void CircularBufferInserter::DoOnImageCaptured(CImageDataPointer& objImageDataPointer, void* pUserParam) +{ + // char label[MM::MaxStrLength]; + //dev_->AddToLog("OnImageGrabbed"); + // Important: meta data about the image are generated here: + Metadata md; + md.put("Camera", ""); + md.put(MM::g_Keyword_Metadata_ROI_X, CDeviceUtils::ConvertToString((long)objImageDataPointer->GetWidth())); + md.put(MM::g_Keyword_Metadata_ROI_Y, CDeviceUtils::ConvertToString((long)objImageDataPointer->GetHeight())); + md.put(MM::g_Keyword_Metadata_ImageNumber, CDeviceUtils::ConvertToString((long)objImageDataPointer->GetFrameID())); + md.put(MM::g_Keyword_Meatdata_Exposure, dev_->GetExposure()); + // Image grabbed successfully ? + if (objImageDataPointer->GetStatus()== GX_FRAME_STATUS_SUCCESS) + { + //²éѯͼÏñ¸ñʽ + GX_PIXEL_FORMAT_ENTRY pixelFormat_gx = objImageDataPointer->GetPixelFormat(); + + dev_->ResizeSnapBuffer(); + //ºÚ°× + if (!dev_->colorCamera_) + { + //copy to intermediate buffer + int ret = dev_->GetCoreCallback()->InsertImage(dev_, (const unsigned char*)objImageDataPointer->GetBuffer(), + (unsigned)objImageDataPointer->GetWidth(), (unsigned)objImageDataPointer->GetHeight(), + (unsigned)dev_->GetImageBytesPerPixel(), 1, md.Serialize().c_str(), FALSE); + if (ret == DEVICE_BUFFER_OVERFLOW) { + //if circular buffer overflows, just clear it and keep putting stuff in so live mode can continue + dev_->GetCoreCallback()->ClearImageBuffer(dev_); + } + } + else if (dev_->colorCamera_) + { + //²ÊÉ«£¬×¢ÒâÕâÀïÈ«²¿×ª³É8λRGB + if (dev_->__IsPixelFormat8(pixelFormat_gx)) + { + dev_->RG8ToRGB24Packed(dev_->imgBuffer_, objImageDataPointer); + } + else { + dev_->RG10ToRGB24Packed(dev_->imgBuffer_, objImageDataPointer); + } + //copy to intermediate buffer + int ret = dev_->GetCoreCallback()->InsertImage(dev_, (const unsigned char*)dev_->imgBuffer_, + (unsigned)dev_->GetImageWidth(), (unsigned)dev_->GetImageHeight(), + (unsigned)dev_->GetImageBytesPerPixel(), 1, md.Serialize().c_str(), FALSE); + if (ret == DEVICE_BUFFER_OVERFLOW) { + //if circular buffer overflows, just clear it and keep putting stuff in so live mode can continue + dev_->GetCoreCallback()->ClearImageBuffer(dev_); + } + } + } + else + { + dev_->AddToLog("²ÐÖ¡"); + } + + + + + +} +int64_t ClassGalaxy::__GetStride(int64_t nWidth, bool bIsColor) +{ + return bIsColor ? nWidth * 3 : nWidth; +} + +bool ClassGalaxy::__IsCompatible(BITMAPINFO* pBmpInfo, uint64_t nWidth, uint64_t nHeight) +{ + if (pBmpInfo == NULL + || pBmpInfo->bmiHeader.biHeight != nHeight + || pBmpInfo->bmiHeader.biWidth != nWidth + ) + { + return false; + } + return true; +} +void ClassGalaxy::__ColorPrepareForShowImg() +{ + //-------------------------------------------------------------------- + //---------------------------³õʼ»¯bitmapÍ·--------------------------- + m_pBmpInfo = (BITMAPINFO*)m_chBmpBuf; + m_pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + m_pBmpInfo->bmiHeader.biWidth = (LONG)Width_; + m_pBmpInfo->bmiHeader.biHeight = (LONG)Height_; + + m_pBmpInfo->bmiHeader.biPlanes = 1; + m_pBmpInfo->bmiHeader.biBitCount = 24; + m_pBmpInfo->bmiHeader.biCompression = BI_RGB; + m_pBmpInfo->bmiHeader.biSizeImage = 0; + m_pBmpInfo->bmiHeader.biXPelsPerMeter = 0; + m_pBmpInfo->bmiHeader.biYPelsPerMeter = 0; + m_pBmpInfo->bmiHeader.biClrUsed = 0; + m_pBmpInfo->bmiHeader.biClrImportant = 0; +} +void ClassGalaxy::__UpdateBitmap(CImageDataPointer& objCImageDataPointer) +{ + if (!__IsCompatible(m_pBmpInfo, objCImageDataPointer->GetWidth(), objCImageDataPointer->GetHeight())) + { + + if (colorCamera_) + { + __ColorPrepareForShowImg(); + } + else + { + //__MonoPrepareForShowImg(); + } + } +} +void ClassGalaxy::SaveBmp(CImageDataPointer& objCImageDataPointer, const std::string& strFilePath) +{ + GX_VALID_BIT_LIST emValidBits = GX_BIT_0_7; + BYTE* pBuffer = NULL; + + if ((objCImageDataPointer.IsNull()) || (strFilePath == "")) + { + throw std::runtime_error("Argument is error"); + } + + //¼ì²éͼÏñÊÇ·ñ¸Ä±ä²¢¸üÐÂBuffer + __UpdateBitmap(objCImageDataPointer); + + emValidBits = GetBestValudBit(objCImageDataPointer->GetPixelFormat()); + + if (colorCamera_) + { + //BYTE* pBuffer = (BYTE*)objCImageDataPointer->ImageProcess(objCfg); + + pBuffer = (BYTE*)objCImageDataPointer->ConvertToRGB24(emValidBits, GX_RAW2RGB_NEIGHBOUR, true); + } + else + { + if (__IsPixelFormat8(objCImageDataPointer->GetPixelFormat())) + { + pBuffer = (BYTE*)objCImageDataPointer->GetBuffer(); + } + else + { + pBuffer = (BYTE*)objCImageDataPointer->ConvertToRaw8(emValidBits); + } + // ºÚ°×Ïà»úÐèÒª·­×ªÊý¾ÝºóÏÔʾ + for (unsigned int i = 0; i < Height_; i++) + { + memcpy(m_pImageBuffer + i * Width_, pBuffer + (Height_ - i - 1) * Width_, (size_t)Width_); + } + pBuffer = m_pImageBuffer; + } + + DWORD dwImageSize = (DWORD)(__GetStride(Width_, colorCamera_) * Height_); + BITMAPFILEHEADER stBfh = { 0 }; + DWORD dwBytesRead = 0; + + stBfh.bfType = (WORD)'M' << 8 | 'B'; //¶¨ÒåÎļþÀàÐÍ + stBfh.bfOffBits = colorCamera_ ? sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + : sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (256 * 4); //¶¨ÒåÎļþÍ·´óСtrueΪ²ÊÉ«,falseΪºÚ°× + stBfh.bfSize = stBfh.bfOffBits + dwImageSize; //Îļþ´óС + + DWORD dwBitmapInfoHeader = colorCamera_ ? sizeof(BITMAPINFOHEADER) + : sizeof(BITMAPINFOHEADER) + (256 * 4); //¶¨ÒåBitmapInfoHeader´óСtrueΪ²ÊÉ«,falseΪºÚ°× + const char* strEn = strFilePath.c_str(); + + //½«const char*ת»¯ÎªLPCTSTR + size_t length = sizeof(TCHAR) * (strlen(strEn) + 1); + LPTSTR tcBuffer = new TCHAR[length]; + memset(tcBuffer, 0, length); + MultiByteToWideChar(CP_ACP, 0, strEn, (int) strlen(strEn), tcBuffer, (int) length); + LPCTSTR pDest = (LPCTSTR)tcBuffer; + + //´´½¨Îļþ + HANDLE hFile = ::CreateFile(pDest, + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + throw std::runtime_error("Handle is invalid"); + } + ::WriteFile(hFile, &stBfh, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL); + ::WriteFile(hFile, m_pBmpInfo, dwBitmapInfoHeader, &dwBytesRead, NULL); //ºÚ°×ºÍ²ÊÉ«×ÔÊÊÓ¦ + ::WriteFile(hFile, pBuffer, dwImageSize, &dwBytesRead, NULL); + CloseHandle(hFile); +} +void ClassGalaxy::SaveBmp(CImageDataPointer& objCImageDataPointer,void* buffer,const std::string& strFilePath) +{ + GX_VALID_BIT_LIST emValidBits = GX_BIT_0_7; + BYTE* pBuffer = NULL; + + if ((strFilePath == "")) + { + throw std::runtime_error("Argument is error"); + } + + //¼ì²éͼÏñÊÇ·ñ¸Ä±ä²¢¸üÐÂBuffer + __UpdateBitmap(objCImageDataPointer); + + emValidBits = GetBestValudBit(objCImageDataPointer->GetPixelFormat()); + + if (colorCamera_) + { + //BYTE* pBuffer = (BYTE*)objCImageDataPointer->ImageProcess(objCfg); + + pBuffer = (BYTE*)objCImageDataPointer->ConvertToRGB24(emValidBits, GX_RAW2RGB_NEIGHBOUR, true); + } + else + { + if (__IsPixelFormat8(objCImageDataPointer->GetPixelFormat())) + { + pBuffer = (BYTE*)objCImageDataPointer->GetBuffer(); + } + else + { + pBuffer = (BYTE*)objCImageDataPointer->ConvertToRaw8(emValidBits); + } + // ºÚ°×Ïà»úÐèÒª·­×ªÊý¾ÝºóÏÔʾ + for (unsigned int i = 0; i < Height_; i++) + { + memcpy(m_pImageBuffer + i * Width_, pBuffer + (Height_ - i - 1) * Width_, (size_t)Width_); + } + pBuffer = m_pImageBuffer; + } + + DWORD dwImageSize = (DWORD)(__GetStride(Width_, colorCamera_) * Height_); + BITMAPFILEHEADER stBfh = { 0 }; + DWORD dwBytesRead = 0; + + stBfh.bfType = (WORD)'M' << 8 | 'B'; //¶¨ÒåÎļþÀàÐÍ + stBfh.bfOffBits = colorCamera_ ? sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + : sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (256 * 4); //¶¨ÒåÎļþÍ·´óСtrueΪ²ÊÉ«,falseΪºÚ°× + stBfh.bfSize = stBfh.bfOffBits + dwImageSize; //Îļþ´óС + + DWORD dwBitmapInfoHeader = colorCamera_ ? sizeof(BITMAPINFOHEADER) + : sizeof(BITMAPINFOHEADER) + (256 * 4); //¶¨ÒåBitmapInfoHeader´óСtrueΪ²ÊÉ«,falseΪºÚ°× + const char* strEn = strFilePath.c_str(); + + //½«const char*ת»¯ÎªLPCTSTR + size_t length = sizeof(TCHAR) * (strlen(strEn) + 1); + LPTSTR tcBuffer = new TCHAR[length]; + memset(tcBuffer, 0, length); + MultiByteToWideChar(CP_ACP, 0, strEn, (int) strlen(strEn), tcBuffer, (int) length); + LPCTSTR pDest = (LPCTSTR)tcBuffer; + + //´´½¨Îļþ + HANDLE hFile = ::CreateFile(pDest, + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + throw std::runtime_error("Handle is invalid"); + } + ::WriteFile(hFile, &stBfh, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL); + ::WriteFile(hFile, m_pBmpInfo, dwBitmapInfoHeader, &dwBytesRead, NULL); //ºÚ°×ºÍ²ÊÉ«×ÔÊÊÓ¦ + //::WriteFile(hFile, pBuffer, dwImageSize, &dwBytesRead, NULL); + + ::WriteFile(hFile, buffer, dwImageSize, &dwBytesRead, NULL); + CloseHandle(hFile); +} + +void ClassGalaxy::SaveRaw(CImageDataPointer& objCImageDataPointer, const std::string& strFilePath) +{ + if ((objCImageDataPointer.IsNull()) || (strFilePath == "")) + { + throw std::runtime_error("Argument is error"); + } + + //¼ì²éͼÏñÊÇ·ñ¸Ä±ä²¢¸üÐÂBuffer + __UpdateBitmap(objCImageDataPointer); + + DWORD dwImageSize = (DWORD)objCImageDataPointer->GetPayloadSize(); // дÈëÎļþµÄ³¤¶È + DWORD dwBytesRead = 0; // Îļþ¶ÁÈ¡µÄ³¤¶È + + BYTE* pbuffer = (BYTE*)objCImageDataPointer->GetBuffer(); + + const char* strEn = strFilePath.c_str(); + + //½«const char*ת»¯ÎªLPCTSTR + size_t length = sizeof(TCHAR) * (strlen(strEn) + 1); + LPTSTR tcBuffer = new TCHAR[length]; + memset(tcBuffer, 0, length); + MultiByteToWideChar(CP_ACP, 0, strEn, (int) strlen(strEn), tcBuffer, (int) length); + LPCTSTR pDest = (LPCTSTR)tcBuffer; + // ´´½¨Îļþ + HANDLE hFile = ::CreateFile(pDest, + GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hFile == INVALID_HANDLE_VALUE) // ´´½¨Ê§°ÜÔò·µ»Ø + { + throw std::runtime_error("Handle is invalid"); + } + else // ±£´æRawͼÏñ + { + ::WriteFile(hFile, pbuffer, dwImageSize, &dwBytesRead, NULL); + CloseHandle(hFile); + } +} \ No newline at end of file diff --git a/DeviceAdapters/DahengGalaxy/ClassGalaxy.h b/DeviceAdapters/DahengGalaxy/ClassGalaxy.h new file mode 100644 index 000000000..10510616c --- /dev/null +++ b/DeviceAdapters/DahengGalaxy/ClassGalaxy.h @@ -0,0 +1,232 @@ +#pragma once +#define _AFXDLL +//#include +//#include "stdafx.h" + +#include "GalaxyException.h" +#include "GalaxyIncludes.h" +//#include "GXBitmap.h" +//#include "FileVersion.h" +//#include "DxImageProc.h" + //--------------------------------------------------------------------------------- +/** +\brief Óû§¼Ì³Ð²É¼¯Ê¼þ´¦ÀíÀ࣬»Øµ÷º¯Êý£¬Öصã¹Ø×¢ ÀàÖÐÓлص÷À࣬¹©²É¼¯Í¼Ïñ +*/ +//---------------------------------------------------------------------------------- +#include +#include +#include "ModuleInterface.h" +#include "DeviceUtils.h" +#include +#include "DeviceBase.h" +#include "DeviceThreads.h" +#include +#include +#include +#include "ImageMetadata.h" +#include "ImgBuffer.h" +#include + + + +class CircularBufferInserter; + +class MODULE_API ClassGalaxy : public CCameraBase +{ + +public: + + ClassGalaxy(); + //º¯ÊýµÄÒâÒå-Îö¹¹º¯Êý deleteʱ£¬ÆôÓÃ; + ~ClassGalaxy(void); + + // MMDevice API + // ------------ + int Initialize(); + int Shutdown(); + + void GetName(char* name) const; + bool Busy() { return false; } + + + // MMCamera API + // ------------ + int SnapImage(); + + unsigned char* GetImageBufferFromCallBack(CImageDataPointer& objCImageDataPointer); + + const unsigned char* GetImageBuffer(); + + // void* Buffer4ContinuesShot; + + unsigned GetNumberOfComponents() const; + unsigned GetImageWidth() const; + unsigned GetImageHeight() const; + + unsigned GetImageBytesPerPixel() const; + long GetImageSizeLarge()const; + unsigned GetBitDepth() const; + + long GetImageBufferSize() const; + + double GetExposure() const; + void SetExposure(double exp); + int SetROI(unsigned x, unsigned y, unsigned xSize, unsigned ySize); + int GetROI(unsigned& x, unsigned& y, unsigned& xSize, unsigned& ySize); + int ClearROI(); + void ReduceImageSize(int64_t Width, int64_t Height); + int GetBinning() const; + int SetBinning(int binSize); + int IsExposureSequenceable(bool& seq) const { seq = false; return DEVICE_OK; } + + void CoverToRGB(GX_PIXEL_FORMAT_ENTRY emDstFormat,void* DstBuffer, CImageDataPointer pObjSrcImageData); + + ////int SetProperty(const char* name, const char* value); + int CheckForBinningMode(CPropertyAction* pAct); + void AddToLog(std::string msg); + + GX_VALID_BIT_LIST GetBestValudBit(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry); + void CopyToImageBuffer(CImageDataPointer& objImageDataPointer); + //CImageFormatConverter* converter; + CircularBufferInserter* ImageHandler_; + //std::string EnumToString(EDeviceAccessiblityInfo DeviceAccessiblityInfo); + //void UpdateTemperature(); + + /** + * Starts continuous acquisition. liveģʽ£¬µ«ÊÇÒÔϺ¯ÊýûÓÐдҲ»á¿ªÆôliveģʽ£¬¿ªÆô¸Ãº¯ÊýÖ®ºó£¬Èí¼þ»á¿¨ËÀ£¬ÄÚ²¿Óк¯Êý + */ + int StartSequenceAcquisition(long numImages, double interval_ms, bool stopOnOverflow) final ; + int StartSequenceAcquisition(double interval_ms) final; + int StopSequenceAcquisition() final; + int PrepareSequenceAcqusition() final; + + ///** + //* Flag to indicate whether Sequence Acquisition is currently running. + //* Return true when Sequence acquisition is active, false otherwise + //*/ + //bool IsCapturing(); + + ////Genicam Callback + ////void ResultingFramerateCallback(GenApi::INode* pNode); + + + //// action interface + //// ---------------- + //int OnAcqFramerate(MM::PropertyBase* pProp, MM::ActionType eAct); + //int OnAcqFramerateEnable(MM::PropertyBase* pProp, MM::ActionType eAct); + //int OnAutoExpore(MM::PropertyBase* pProp, MM::ActionType eAct); + //int OnAutoGain(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnBinning(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnBinningMode(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnDeviceLinkThroughputLimit(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnExposure(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnGain(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnHeight(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnInterPacketDelay(MM::PropertyBase* pProp, MM::ActionType eAct); + //int OnLightSourcePreset(MM::PropertyBase* pProp, MM::ActionType eAct); + //int OnOffset(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnPixelType(MM::PropertyBase* pProp, MM::ActionType eAct); + //int OnResultingFramerate(MM::PropertyBase* pProp, MM::ActionType eAct); + //int OnReverseX(MM::PropertyBase* pProp, MM::ActionType eAct); + //int OnReverseY(MM::PropertyBase* pProp, MM::ActionType eAct); + //int OnSensorReadoutMode(MM::PropertyBase* pProp, MM::ActionType eAct); + //int OnShutterMode(MM::PropertyBase* pProp, MM::ActionType eAct); + //int OnTemperature(MM::PropertyBase* pProp, MM::ActionType eAct); + //int OnTemperatureState(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnTriggerMode(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnTriggerActivation(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnAdjFrameRateMode(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnAcquisitionFrameRate(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnTriggerSource(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnWidth(MM::PropertyBase* pProp, MM::ActionType eAct); + + int OnTriggerDelay(MM::PropertyBase* pProp, MM::ActionType eAct); + + int OnTriggerFilterRaisingEdge(MM::PropertyBase* pProp, MM::ActionType eAct); + //ΪÁËʵÏÖÔڲɼ¯ÀàÖÐʹÓà + bool colorCamera_; + CGXFeatureControlPointer m_objFeatureControlPtr; ///< ÊôÐÔ¿ØÖÆÆ÷ + //¸ñʽת»»º¯Êý + void RG8ToRGB24Packed(void* destbuffer, CImageDataPointer& objImageDataPointer); + void CoverRGB16ToRGBA16(unsigned short int* Desbuffer, unsigned short int* Srcbuffer); + void RG10ToRGB24Packed(void* destbuffer, CImageDataPointer& objImageDataPointer); + void RGB24PackedToRGBA(void* destbuffer, void* srcbuffer, CImageDataPointer& objImageDataPointer); + void ResizeSnapBuffer(); + void* imgBuffer_; + bool __IsPixelFormat8(GX_PIXEL_FORMAT_ENTRY emPixelFormatEntry); + +private: + GxIAPICPP::gxdeviceinfo_vector vectorDeviceInfo; + int nComponents_; + unsigned bitDepth_; + unsigned bytesPerPixel_; + + bool IsByerFormat = false; + + /*mutable*/ unsigned Width_, Height_; + long imageBufferSize_; + void GetImageSize(); + + unsigned maxWidth_, maxHeight_; + int64_t DeviceLinkThroughputLimit_; + // double ResultingFrameRatePrevious; + // double acqFramerate_, acqFramerateMax_, acqFramerateMin_; + double exposure_us_, exposureMax_, exposureMin_; + double gain_, gainMax_, gainMin_; + double offset_, offsetMin_, offsetMax_; + + std::string binningFactor_; + std::string pixelType_; + std::string reverseX_, reverseY_; + std::string sensorReadoutMode_; + std::string setAcqFrm_; + std::string shutterMode_; + std::string temperature_; + std::string temperatureState_; + std::string TriggerMode_; + std::string AcquisitionFrameRateMode_; + std::string AcquisitionFrameRate_; + std::string TriggerActivation_; + std::string TriggerDelay_; + std::string TriggerFilterRaisingEdge_; + + BITMAPINFO* m_pBmpInfo; /// + + + + Debug + x64 + + + Release + x64 + + + + + {b8c95f39-54bf-40a9-807b-598df2821d55} + + + + + + + + + + Win32Proj + {dd3a2820-f54c-42f3-aa0e-dc95d57481b7} + DahengGalaxy + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + true + + + false + + + + Level3 + true + _DEBUG;DAHENGGALAXY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + + + + $(MM_3RDPARTYPUBLIC)\DahengGalaxy\inc;%(AdditionalIncludeDirectories) + + + Windows + true + false + $(OutDir)$(TargetName)$(TargetExt) + $(MM_3RDPARTYPUBLIC)\DahengGalaxy\lib\x64;%(AdditionalLibraryDirectories) + + + + + Level3 + true + true + true + NDEBUG;DAHENGGALAXY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + + + + $(MM_3RDPARTYPUBLIC)\DahengGalaxy\inc;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + false + %(AdditionalDependencies) + $(MM_3RDPARTYPUBLIC)\DahengGalaxy\lib\x64;%(AdditionalLibraryDirectories) + + + + + + diff --git a/DeviceAdapters/DahengGalaxy/DahengGalaxy.vcxproj.filters b/DeviceAdapters/DahengGalaxy/DahengGalaxy.vcxproj.filters new file mode 100644 index 000000000..e7fd97f49 --- /dev/null +++ b/DeviceAdapters/DahengGalaxy/DahengGalaxy.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + diff --git a/DeviceAdapters/DahengGalaxy/GalaxySDK.props b/DeviceAdapters/DahengGalaxy/GalaxySDK.props new file mode 100644 index 000000000..9db4c0884 --- /dev/null +++ b/DeviceAdapters/DahengGalaxy/GalaxySDK.props @@ -0,0 +1,16 @@ + + + + + + + + $(GALAXY_ROOT)\C++ SDK\src\Common;$(GALAXY_ROOT)\C++ SDK\inc;%(AdditionalIncludeDirectories) + + + J:\Program Files\Daheng Imaging\GalaxySDK\Samples\C++ SDK\lib\x64;$(GALAXY_ROOT)\C++ SDK\lib\x64;%(AdditionalLibraryDirectories) + GxIAPICPPEx.lib;%(AdditionalDependencies) + + + + \ No newline at end of file diff --git a/micromanager.sln b/micromanager.sln index 9106a1760..da0440ec5 100644 --- a/micromanager.sln +++ b/micromanager.sln @@ -485,6 +485,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QSI", "DeviceAdapters\QSI\Q EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NotificationTester", "DeviceAdapters\NotificationTester\NotificationTester.vcxproj", "{7C8C60FA-92E3-4102-80AB-A4468C4FCD2F}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DahengGalaxy", "DeviceAdapters\DahengGalaxy\DahengGalaxy.vcxproj", "{DD3A2820-F54C-42F3-AA0E-DC95D57481B7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -1459,6 +1461,10 @@ Global {7C8C60FA-92E3-4102-80AB-A4468C4FCD2F}.Debug|x64.Build.0 = Debug|x64 {7C8C60FA-92E3-4102-80AB-A4468C4FCD2F}.Release|x64.ActiveCfg = Release|x64 {7C8C60FA-92E3-4102-80AB-A4468C4FCD2F}.Release|x64.Build.0 = Release|x64 + {DD3A2820-F54C-42F3-AA0E-DC95D57481B7}.Debug|x64.ActiveCfg = Debug|x64 + {DD3A2820-F54C-42F3-AA0E-DC95D57481B7}.Debug|x64.Build.0 = Debug|x64 + {DD3A2820-F54C-42F3-AA0E-DC95D57481B7}.Release|x64.ActiveCfg = Release|x64 + {DD3A2820-F54C-42F3-AA0E-DC95D57481B7}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From c8b81eb36dc5ccb0ab2ea7e8dbe675cab5025c8b Mon Sep 17 00:00:00 2001 From: Nico Stuurman Date: Tue, 2 Apr 2024 12:07:36 -0700 Subject: [PATCH 89/91] NIDAQ: Adding pre-post exposure transition property for AO sequences. --- DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp | 23 +++++++++++++++++++++ DeviceAdapters/NIDAQ/NIDAQ.cpp | 3 ++- DeviceAdapters/NIDAQ/NIDAQ.h | 6 +++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp b/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp index 4e612010e..11db0f8ca 100644 --- a/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp +++ b/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp @@ -36,6 +36,7 @@ NIAnalogOutputPort::NIAnalogOutputPort(const std::string& port) : minVolts_(0.0), maxVolts_(5.0), neverSequenceable_(false), + transitionPostExposure_(false), task_(0) { InitializeDefaultErrorMessages(); @@ -88,6 +89,13 @@ int NIAnalogOutputPort::Initialize() if (err != DEVICE_OK) return err; + pAct = new CPropertyAction(this, &NIAnalogOutputPort::OnSequenceTransition); + err = CreateStringProperty("Sequence Transition Pre-Post Exposure", g_Pre, false, pAct); + if (err != DEVICE_OK) + return err; + AddAllowedValue("Sequence Transition Pre-Post Exposure", g_Pre); + AddAllowedValue("Sequence Transition Pre-Post Exposure", g_Post); + err = StartOnDemandTask(gateOpen_ ? gatedVoltage_ : 0.0); if (err != DEVICE_OK) return err; @@ -292,6 +300,21 @@ int NIAnalogOutputPort::OnSequenceable(MM::PropertyBase* pProp, MM::ActionType e return DEVICE_OK; } +int NIAnalogOutputPort::OnSequenceTransition(MM::PropertyBase* pProp, MM::ActionType eAct) +{ + if (eAct == MM::BeforeGet) + { + pProp->Set(transitionPostExposure_ ? g_Post : g_Pre); + } + else if (eAct == MM::AfterSet) + { + std::string s; + pProp->Get(s); + transitionPostExposure_ = (s == g_Post); + } + return DEVICE_OK; +} + int NIAnalogOutputPort::OnVoltage(MM::PropertyBase* pProp, MM::ActionType eAct) { diff --git a/DeviceAdapters/NIDAQ/NIDAQ.cpp b/DeviceAdapters/NIDAQ/NIDAQ.cpp index f813c4822..67ed339f8 100644 --- a/DeviceAdapters/NIDAQ/NIDAQ.cpp +++ b/DeviceAdapters/NIDAQ/NIDAQ.cpp @@ -37,9 +37,10 @@ const char* g_On = "On"; const char* g_Off = "Off"; const char* g_Low = "Low"; const char* g_High = "High"; - const char* g_Never = "Never"; const char* g_UseHubSetting = "Use hub setting"; +const char* g_Post = "Post"; +const char* g_Pre = "Pre"; const int ERR_SEQUENCE_RUNNING = 2001; const int ERR_SEQUENCE_TOO_LONG = 2002; diff --git a/DeviceAdapters/NIDAQ/NIDAQ.h b/DeviceAdapters/NIDAQ/NIDAQ.h index 098000ffe..1e31d96fe 100644 --- a/DeviceAdapters/NIDAQ/NIDAQ.h +++ b/DeviceAdapters/NIDAQ/NIDAQ.h @@ -39,8 +39,9 @@ extern const char* g_On; extern const char* g_Off; extern const char* g_Low; extern const char* g_High; - extern const char* g_Never; +extern const char* g_Pre; +extern const char* g_Post; extern const char* g_UseHubSetting; extern const int ERR_SEQUENCE_RUNNING; @@ -286,6 +287,7 @@ class NIAnalogOutputPort : public CSignalIOBase, int OnMinVolts(MM::PropertyBase* pProp, MM::ActionType eAct); int OnMaxVolts(MM::PropertyBase* pProp, MM::ActionType eAct); int OnSequenceable(MM::PropertyBase* pProp, MM::ActionType eAct); + int OnSequenceTransition(MM::PropertyBase* pProp, MM::ActionType eAct); // Post-init property action handlers int OnVoltage(MM::PropertyBase* pProp, MM::ActionType eAct); @@ -309,6 +311,8 @@ class NIAnalogOutputPort : public CSignalIOBase, double minVolts_; // User-selected for this port double maxVolts_; // User-selected for this port bool neverSequenceable_; + bool transitionPostExposure_; // when to transition in a sequence, not that we always transition on a rising flank + // it can be advantaguous to transition post exposure, in which case we have to modify our sequence TaskHandle task_; From 542180b679c00ba4f53b983d689b0a22b557bcf9 Mon Sep 17 00:00:00 2001 From: Nico Stuurman Date: Tue, 2 Apr 2024 13:49:05 -0700 Subject: [PATCH 90/91] NIDAQ: added property to allow pre or post exposure transitions in sequences. --- DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp b/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp index 11db0f8ca..fec0c8d64 100644 --- a/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp +++ b/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp @@ -199,6 +199,16 @@ int NIAnalogOutputPort::StartDASequence() if (task_) StopTask(); + // probably beneficial in all cases to move to the first position, + // essential if we are transitioning post-exposure + double volt0 = sentSequence_[0]; + SetSignal(volt0); + + if (transitionPostExposure_) { + for (int i = 0; i < sentSequence_.size() - 1; i++) { + sentSequence_[i] = sentSequence_[i + 1]; + } + } sequenceRunning_ = true; int err = GetHub()->StartAOSequenceForPort(niPort_, sentSequence_); From 673c06aaee5d0dfe87303ad26f4b45013b6550dd Mon Sep 17 00:00:00 2001 From: edhirata Date: Wed, 10 Apr 2024 09:02:02 -0700 Subject: [PATCH 91/91] this exposes the mirroring functions(X,Y) for the flir cameras as a property. --- DeviceAdapters/Spinnaker/SpinnakerCamera.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DeviceAdapters/Spinnaker/SpinnakerCamera.cpp b/DeviceAdapters/Spinnaker/SpinnakerCamera.cpp index bd44d57bc..1386a89c2 100644 --- a/DeviceAdapters/Spinnaker/SpinnakerCamera.cpp +++ b/DeviceAdapters/Spinnaker/SpinnakerCamera.cpp @@ -403,6 +403,8 @@ int SpinnakerCamera::Initialize() CreatePropertyFromFloat("Gamma", m_cam->Gamma, &SpinnakerCamera::OnGamma); CreatePropertyFromFloat("Black Level", m_cam->BlackLevel, &SpinnakerCamera::OnBlackLevel); CreatePropertyFromEnum("Black Level Auto", m_cam->BlackLevelAuto, &SpinnakerCamera::OnBlackLevelAuto); + CreatePropertyFromBool("Reverse X", m_cam->ReverseX, &SpinnakerCamera::OnReverseX); + CreatePropertyFromBool("Reverse Y", m_cam->ReverseY, &SpinnakerCamera::OnReverseY); try {