diff --git a/Builds/Linux/Makefile b/Builds/Linux/Makefile index 49487a2e12f1b1f8aa86b328e10f4667f117ad66..1ae639259f1f18b1eb130ca3d6080c81bb120444 100644 --- a/Builds/Linux/Makefile +++ b/Builds/Linux/Makefile @@ -18,12 +18,12 @@ ifeq ($(CONFIG),Debug) TARGET_ARCH := -march=native endif - CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.4.1" -D "JUCE_APP_VERSION_HEX=0x401" -I /usr/include -I /usr/include/freetype2 -I ~/SDKs/VST3\ SDK -I ../../JuceLibraryCode -I ../../JuceLibraryCode/modules -I JuceLibraryCode/ + CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.4.2" -D "JUCE_APP_VERSION_HEX=0x402" -I /usr/include -I /usr/include/freetype2 -I ~/SDKs/VST3\ SDK -I ../../JuceLibraryCode -I ../../JuceLibraryCode/modules -I JuceLibraryCode/ CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O3 -rdynamic -fvisibility=hidden CXXFLAGS += $(CFLAGS) -std=c++11 LDFLAGS += $(TARGET_ARCH) -L$(BINDIR) -L$(LIBDIR) -L/usr/X11R6/lib/ -L/usr/local/include -lGL -lX11 -lXext -lXinerama -lasound -ldl -lfreetype -lpthread -lrt -ldl -lXext -lGLU -rdynamic -fPIC - TARGET := open-ephys.so + TARGET := open-ephys BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH) CLEANCMD = rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR) endif @@ -38,12 +38,12 @@ ifeq ($(CONFIG),Release) TARGET_ARCH := -march=native endif - CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.4.1" -D "JUCE_APP_VERSION_HEX=0x401" -I /usr/include -I /usr/include/freetype2 -I ~/SDKs/VST3\ SDK -I ../../JuceLibraryCode -I ../../JuceLibraryCode/modules -I JuceLibraryCode/ + CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.4.2" -D "JUCE_APP_VERSION_HEX=0x402" -I /usr/include -I /usr/include/freetype2 -I ~/SDKs/VST3\ SDK -I ../../JuceLibraryCode -I ../../JuceLibraryCode/modules -I JuceLibraryCode/ CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -O3 -rdynamic -fvisibility=hidden CXXFLAGS += $(CFLAGS) -std=c++11 LDFLAGS += $(TARGET_ARCH) -L$(BINDIR) -L$(LIBDIR) -fvisibility=hidden -L/usr/X11R6/lib/ -lGL -lX11 -lXext -lXinerama -lasound -ldl -lfreetype -lpthread -lrt -ldl -lXext -lGLU -rdynamic -fPIC - TARGET := open-ephys-release.so + TARGET := open-ephys-release BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH) CLEANCMD = rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR) endif diff --git a/Builds/Linux/Makefile.plugins b/Builds/Linux/Makefile.plugins index 49c67171856132e4830c7feb7634325147b54b6d..a07d4975ad69a6d736768fb4c75b0e28bef43606 100644 --- a/Builds/Linux/Makefile.plugins +++ b/Builds/Linux/Makefile.plugins @@ -21,12 +21,12 @@ ifeq ($(CONFIG),Debug) TARGET_ARCH := -march=native endif - CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.3.5" -D "JUCE_APP_VERSION_HEX=0x305" -I /usr/include -I /usr/include/freetype2 -I $(CURDIR)/../../JuceLibraryCode -I $(CURDIR)/../../JuceLibraryCode/modules -I $(CURDIR)/../../Source/Plugins/Headers + CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.4.2" -D "JUCE_APP_VERSION_HEX=0x402" -I /usr/include -I /usr/include/freetype2 -I $(CURDIR)/../../JuceLibraryCode -I $(CURDIR)/../../JuceLibraryCode/modules -I $(CURDIR)/../../Source/Plugins/Headers CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O3 -std=c++11 -fPIC -rdynamic CXXFLAGS += $(CFLAGS) LDFLAGS += $(TARGET_ARCH) -L$(BINDIR) -L$(LIBDIR) -L/usr/X11R6/lib/ -L/usr/local/include -lGL -lX11 -lXext -lXinerama -lasound -ldl -lfreetype -lpthread -lrt -pg -ldl -lXext -lGLU -fPIC -rdynamic LDDEPS := - RESFLAGS := -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.3.5" -D "JUCE_APP_VERSION_HEX=0x305" -I /usr/include -I /usr/include/freetype2 -I $(CURDIR)/../../Source/Plugins/Headers + RESFLAGS := -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.4.2" -D "JUCE_APP_VERSION_HEX=0x402" -I /usr/include -I /usr/include/freetype2 -I $(CURDIR)/../../Source/Plugins/Headers CLEANCMD = rm -rf $(OUTDIR)/* $(OBJDIR) $(BINDIR)/$(addsuffix .so,$(notdir $(COMMONDIRS))) endif @@ -41,12 +41,12 @@ ifeq ($(CONFIG),Release) TARGET_ARCH := -march=native endif - CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.3.5" -D "JUCE_APP_VERSION_HEX=0x305" -I /usr/include -I /usr/include/freetype2 -I $(CURDIR)/../../JuceLibraryCode -I $(CURDIR)/../../JuceLibraryCode/modules -I $(CURDIR)/../../Source/Plugins/Headers + CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.4.2" -D "JUCE_APP_VERSION_HEX=0x402" -I /usr/include -I /usr/include/freetype2 -I $(CURDIR)/../../JuceLibraryCode -I $(CURDIR)/../../JuceLibraryCode/modules -I $(CURDIR)/../../Source/Plugins/Headers CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -O3 -std=c++11 -fPIC -rdynamic CXXFLAGS += $(CFLAGS) LDFLAGS += $(TARGET_ARCH) -L$(BINDIR) -L$(LIBDIR) -fvisibility=hidden -L/usr/X11R6/lib/ -lGL -lX11 -lXext -lXinerama -lasound -ldl -lfreetype -lpthread -lrt -pg -ldl -lXext -lGLU -fPIC -rdynamic LDDEPS1 := - RESFLAGS := -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.3.5" -D "JUCE_APP_VERSION_HEX=0x305" -I /usr/include -I /usr/include/freetype2 -I $(CURDIR)/../../Source/Plugins/Headers + RESFLAGS := -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.4.2" -D "JUCE_APP_VERSION_HEX=0x402" -I /usr/include -I /usr/include/freetype2 -I $(CURDIR)/../../Source/Plugins/Headers CLEANCMD = rm -rf $(OUTDIR)/* $(OBJDIR) $(BINDIR)/$(addsuffix .so,$(notdir $(COMMONDIRS))) endif diff --git a/Builds/Linux/setup.sh b/Builds/Linux/setup.sh index 537ac63c02ca20ffc4e78ec24007595b7a18e2b6..d28f4fd34459e0273e509a6c936258c29e01d9fd 100755 --- a/Builds/Linux/setup.sh +++ b/Builds/Linux/setup.sh @@ -31,7 +31,7 @@ PROC_DIR=${BUILD_HOME%/*/*} make -j4 if [ $? -eq 0 ]; then - sudo ln -s -f $BUILD_HOME/build/open-ephys /usr/bin/. + sudo ln -s -f $BUILD_HOME/build/open-ephys /usr/bin/open-ephys echo "-----> GUI compile successful." else echo "-----> GUI compile failed." @@ -39,23 +39,7 @@ else fi # Step 2: Compile plugins -PLUGIN_SRC_DIR="${PROC_DIR}/Source/Processors" -PLUGINS=`ls -d ${PLUGIN_SRC_DIR}/*` - -cd $PLUGIN_SRC_DIR -for PLUGIN in ${PLUGINS} -do - if [ -f $PLUGIN/Makefile ]; then - cd $PLUGIN - make clean - make - if [ $? -ne 0 ]; then - echo "-----> Plugin compile failed." - exit - fi - cd .. - fi -done +make -j4 -f Makefile.plugins if [ $? -eq 0 ]; then echo "-----> Plugin installation sucessful." diff --git a/Builds/MacOSX/Info-App.plist b/Builds/MacOSX/Info-App.plist index b89a4f4194af99b7ce3ee617d1413dfa6e27e3ea..d6c7290d7f5f5fa579e83afc7e663d3ffbc1358d 100644 --- a/Builds/MacOSX/Info-App.plist +++ b/Builds/MacOSX/Info-App.plist @@ -18,9 +18,9 @@ <key>CFBundleSignature</key> <string>????</string> <key>CFBundleShortVersionString</key> - <string>0.4.1</string> + <string>0.4.2</string> <key>CFBundleVersion</key> - <string>0.4.1</string> + <string>0.4.2</string> <key>NSHumanReadableCopyright</key> <string>Open Ephys</string> <key>NSHighResolutionCapable</key> diff --git a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj index b84af84525271fe3130be3d9874657b6bf49c72e..c7ec046745c24e7a999f8886f5951ad00c83c2d5 100644 --- a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj @@ -3358,8 +3358,8 @@ "_DEBUG=1", "DEBUG=1", "JUCER_XCODE_MAC_F6D2F4CF=1", - "JUCE_APP_VERSION=0.4.1", - "JUCE_APP_VERSION_HEX=0x401", ); + "JUCE_APP_VERSION=0.4.2", + "JUCE_APP_VERSION_HEX=0x402", ); GCC_VERSION = com.apple.compilers.llvm.clang.1_0; HEADER_SEARCH_PATHS = ("~/SDKs/vstsdk2.4", "../../JuceLibraryCode", "../../JuceLibraryCode/modules", "JuceLibraryCode/", "$(inherited)"); INFOPLIST_FILE = Info-App.plist; @@ -3382,8 +3382,8 @@ "_NDEBUG=1", "NDEBUG=1", "JUCER_XCODE_MAC_F6D2F4CF=1", - "JUCE_APP_VERSION=0.4.1", - "JUCE_APP_VERSION_HEX=0x401", ); + "JUCE_APP_VERSION=0.4.2", + "JUCE_APP_VERSION_HEX=0x402", ); GCC_SYMBOLS_PRIVATE_EXTERN = YES; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; HEADER_SEARCH_PATHS = ("~/SDKs/vstsdk2.4", "../../JuceLibraryCode", "../../JuceLibraryCode/modules", "JuceLibraryCode/", "$(inherited)"); diff --git a/Builds/VisualStudio2012/open-ephys.vcxproj b/Builds/VisualStudio2012/open-ephys.vcxproj index f844ced2dcea543b5b4f026743fdccc8af97c84b..4ca750dc9a351b7f3e778e67c666f874fa10fc3c 100644 --- a/Builds/VisualStudio2012/open-ephys.vcxproj +++ b/Builds/VisualStudio2012/open-ephys.vcxproj @@ -85,7 +85,7 @@ <Optimization>Disabled</Optimization> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> <AdditionalIncludeDirectories>~\SDKs\VST3 SDK;..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;JuceLibraryCode/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.4.1;JUCE_APP_VERSION_HEX=0x401;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.4.2;JUCE_APP_VERSION_HEX=0x402;%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeTypeInfo>true</RuntimeTypeInfo> <PrecompiledHeader/> @@ -130,7 +130,7 @@ <ClCompile> <Optimization>Full</Optimization> <AdditionalIncludeDirectories>~\SDKs\VST3 SDK;..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;JuceLibraryCode/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.4.1;JUCE_APP_VERSION_HEX=0x401;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.4.2;JUCE_APP_VERSION_HEX=0x402;%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeTypeInfo>true</RuntimeTypeInfo> <PrecompiledHeader/> @@ -177,7 +177,7 @@ <Optimization>Disabled</Optimization> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <AdditionalIncludeDirectories>~\SDKs\VST3 SDK;..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;JuceLibraryCode/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.4.1;JUCE_APP_VERSION_HEX=0x401;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.4.2;JUCE_APP_VERSION_HEX=0x402;%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeTypeInfo>true</RuntimeTypeInfo> <PrecompiledHeader/> @@ -220,7 +220,7 @@ <ClCompile> <Optimization>Full</Optimization> <AdditionalIncludeDirectories>~\SDKs\VST3 SDK;..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;JuceLibraryCode/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.4.1;JUCE_APP_VERSION_HEX=0x401;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCER_VS2012_78A501F=1;JUCE_APP_VERSION=0.4.2;JUCE_APP_VERSION_HEX=0x402;%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeTypeInfo>true</RuntimeTypeInfo> <PrecompiledHeader/> diff --git a/Builds/VisualStudio2012/resources.rc b/Builds/VisualStudio2012/resources.rc index 4a4d8f58e6c85219e251895ef82cafa648a1207d..13bfc913a492ab1a9b507be55871002f2d99aaa7 100644 --- a/Builds/VisualStudio2012/resources.rc +++ b/Builds/VisualStudio2012/resources.rc @@ -7,7 +7,7 @@ #include <windows.h> VS_VERSION_INFO VERSIONINFO -FILEVERSION 0,4,1,0 +FILEVERSION 0,4,2,0 BEGIN BLOCK "StringFileInfo" BEGIN @@ -15,9 +15,9 @@ BEGIN BEGIN VALUE "CompanyName", "Open Ephys\0" VALUE "FileDescription", "open-ephys\0" - VALUE "FileVersion", "0.4.1\0" + VALUE "FileVersion", "0.4.2\0" VALUE "ProductName", "open-ephys\0" - VALUE "ProductVersion", "0.4.1\0" + VALUE "ProductVersion", "0.4.2\0" END END diff --git a/Builds/VisualStudio2013/Plugins/PCIeRhythm/PCIeRhythm.vcxproj b/Builds/VisualStudio2013/Plugins/PCIeRhythm/PCIeRhythm.vcxproj deleted file mode 100644 index 25632071bf364ffd640f660e22e39f93a7b102da..0000000000000000000000000000000000000000 --- a/Builds/VisualStudio2013/Plugins/PCIeRhythm/PCIeRhythm.vcxproj +++ /dev/null @@ -1,138 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{8F019559-89D4-4C33-BA0F-FF330C57BA2B}</ProjectGuid> - <RootNamespace>PCIeRhythm</RootNamespace> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <PlatformToolset>v120</PlatformToolset> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <PlatformToolset>v120</PlatformToolset> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <PlatformToolset>v120</PlatformToolset> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <PlatformToolset>v120</PlatformToolset> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - <Import Project="..\Plugin_Debug32.props" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - <Import Project="..\Plugin_Debug64.props" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - <Import Project="..\Plugin_Release32.props" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - <Import Project="..\Plugin_Release64.props" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <PropertyGroup /> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <Optimization>Disabled</Optimization> - <SDLCheck>true</SDLCheck> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <Optimization>Disabled</Optimization> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <SDLCheck>true</SDLCheck> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <SDLCheck>true</SDLCheck> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClCompile Include="..\..\..\..\Source\Plugins\PCIeRhythm\OpenEphysLib.cpp" /> - <ClCompile Include="..\..\..\..\Source\Plugins\PCIeRhythm\RHD2000Editor.cpp" /> - <ClCompile Include="..\..\..\..\Source\Plugins\PCIeRhythm\RHD2000Thread.cpp" /> - <ClCompile Include="..\..\..\..\Source\Plugins\PCIeRhythm\rhythm-api\rhd2000datablock.cpp" /> - <ClCompile Include="..\..\..\..\Source\Plugins\PCIeRhythm\rhythm-api\rhd2000PCIe.cpp" /> - <ClCompile Include="..\..\..\..\Source\Plugins\PCIeRhythm\rhythm-api\rhd2000registers.cpp" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="..\..\..\..\Source\Plugins\PCIeRhythm\RHD2000Editor.h" /> - <ClInclude Include="..\..\..\..\Source\Plugins\PCIeRhythm\RHD2000Thread.h" /> - <ClInclude Include="..\..\..\..\Source\Plugins\PCIeRhythm\rhythm-api\rhd2000datablock.h" /> - <ClInclude Include="..\..\..\..\Source\Plugins\PCIeRhythm\rhythm-api\rhd2000PCIe.h" /> - <ClInclude Include="..\..\..\..\Source\Plugins\PCIeRhythm\rhythm-api\rhd2000registers.h" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> -</Project> \ No newline at end of file diff --git a/Builds/VisualStudio2013/Plugins/PCIeRhythm/PCIeRhythm.vcxproj.filters b/Builds/VisualStudio2013/Plugins/PCIeRhythm/PCIeRhythm.vcxproj.filters deleted file mode 100644 index c907b4318d918e6278f87cfa185936df52b88cd2..0000000000000000000000000000000000000000 --- a/Builds/VisualStudio2013/Plugins/PCIeRhythm/PCIeRhythm.vcxproj.filters +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="Source Files"> - <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> - </Filter> - <Filter Include="Header Files"> - <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> - <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> - </Filter> - <Filter Include="Resource Files"> - <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> - <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> - </Filter> - <Filter Include="Source Files\rhythm-api"> - <UniqueIdentifier>{8ec4462a-3223-46ca-a2f1-cf88ba3c80f6}</UniqueIdentifier> - </Filter> - </ItemGroup> - <ItemGroup> - <ClCompile Include="..\..\..\..\Source\Plugins\PCIeRhythm\RHD2000Editor.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\..\..\..\Source\Plugins\PCIeRhythm\RHD2000Thread.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - <ClCompile Include="..\..\..\..\Source\Plugins\PCIeRhythm\rhythm-api\rhd2000datablock.cpp"> - <Filter>Source Files\rhythm-api</Filter> - </ClCompile> - <ClCompile Include="..\..\..\..\Source\Plugins\PCIeRhythm\rhythm-api\rhd2000registers.cpp"> - <Filter>Source Files\rhythm-api</Filter> - </ClCompile> - <ClCompile Include="..\..\..\..\Source\Plugins\PCIeRhythm\rhythm-api\rhd2000PCIe.cpp"> - <Filter>Source Files\rhythm-api</Filter> - </ClCompile> - <ClCompile Include="..\..\..\..\Source\Plugins\PCIeRhythm\OpenEphysLib.cpp"> - <Filter>Source Files</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <ClInclude Include="..\..\..\..\Source\Plugins\PCIeRhythm\RHD2000Editor.h"> - <Filter>Source Files</Filter> - </ClInclude> - <ClInclude Include="..\..\..\..\Source\Plugins\PCIeRhythm\RHD2000Thread.h"> - <Filter>Source Files</Filter> - </ClInclude> - <ClInclude Include="..\..\..\..\Source\Plugins\PCIeRhythm\rhythm-api\rhd2000datablock.h"> - <Filter>Source Files\rhythm-api</Filter> - </ClInclude> - <ClInclude Include="..\..\..\..\Source\Plugins\PCIeRhythm\rhythm-api\rhd2000registers.h"> - <Filter>Source Files\rhythm-api</Filter> - </ClInclude> - <ClInclude Include="..\..\..\..\Source\Plugins\PCIeRhythm\rhythm-api\rhd2000PCIe.h"> - <Filter>Source Files\rhythm-api</Filter> - </ClInclude> - </ItemGroup> -</Project> \ No newline at end of file diff --git a/Builds/VisualStudio2013/Plugins/Plugin_Debug32.props b/Builds/VisualStudio2013/Plugins/Plugin_Debug32.props index 1e53d8e451fea9998f181d7efe669a425ce62230..1dc4da6f46615c97c3570d726164b04b12417568 100644 --- a/Builds/VisualStudio2013/Plugins/Plugin_Debug32.props +++ b/Builds/VisualStudio2013/Plugins/Plugin_Debug32.props @@ -11,7 +11,7 @@ <ItemDefinitionGroup> <ClCompile> <AdditionalIncludeDirectories>..\..\..\..\JuceLibraryCode;..\..\..\..\JuceLibraryCode\modules;..\..\..\..\Source\Plugins\Headers;..\..\..\..\Source\Plugins\CommonLibs;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>OEPLUGIN;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_API=__declspec(dllimport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.3.5;JUCE_APP_VERSION_HEX=0x305;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>OEPLUGIN;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_API=__declspec(dllimport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.4.2;JUCE_APP_VERSION_HEX=0x402;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <SDLCheck>false</SDLCheck> </ClCompile> <Link> diff --git a/Builds/VisualStudio2013/Plugins/Plugin_Debug64.props b/Builds/VisualStudio2013/Plugins/Plugin_Debug64.props index 26eef7c94718636afd9cf5016f942a957f116aa4..e7eebcf9dcee15ca6bde65ece1e2459b67784d2d 100644 --- a/Builds/VisualStudio2013/Plugins/Plugin_Debug64.props +++ b/Builds/VisualStudio2013/Plugins/Plugin_Debug64.props @@ -11,7 +11,7 @@ <ItemDefinitionGroup> <ClCompile> <AdditionalIncludeDirectories>..\..\..\..\JuceLibraryCode;..\..\..\..\JuceLibraryCode\modules;JuceLibraryCode/;..\..\..\..\Source\Plugins\Headers;..\..\..\..\Source\Plugins\CommonLibs;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>OEPLUGIN;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_API=__declspec(dllimport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.3.5;JUCE_APP_VERSION_HEX=0x305;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>OEPLUGIN;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_API=__declspec(dllimport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.4.2;JUCE_APP_VERSION_HEX=0x402;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <SDLCheck>false</SDLCheck> </ClCompile> <Link> diff --git a/Builds/VisualStudio2013/Plugins/Plugin_Release32.props b/Builds/VisualStudio2013/Plugins/Plugin_Release32.props index 731014bc880afaa73cf404ca91487b3aac762963..0c3f0e2bdeb38c0aecccb0414713be9e1c4b55ac 100644 --- a/Builds/VisualStudio2013/Plugins/Plugin_Release32.props +++ b/Builds/VisualStudio2013/Plugins/Plugin_Release32.props @@ -11,7 +11,7 @@ <ItemDefinitionGroup> <ClCompile> <AdditionalIncludeDirectories>..\..\..\..\JuceLibraryCode;..\..\..\..\JuceLibraryCode\modules;..\..\..\..\Source\Plugins\Headers;..\..\..\..\Source\Plugins\CommonLibs;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>OEPLUGIN;WIN32;_WINDOWS;NDEBUG;JUCE_API=__declspec(dllimport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.3.5;JUCE_APP_VERSION_HEX=0x305;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>OEPLUGIN;WIN32;_WINDOWS;NDEBUG;JUCE_API=__declspec(dllimport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.4.2;JUCE_APP_VERSION_HEX=0x402;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <SDLCheck>false</SDLCheck> </ClCompile> <Link> diff --git a/Builds/VisualStudio2013/Plugins/Plugin_Release64.props b/Builds/VisualStudio2013/Plugins/Plugin_Release64.props index 33363000e19fd045044588cf9a3799f9d05fcfb3..851672beab8034c47576e5c5c3e3c33d393a637f 100644 --- a/Builds/VisualStudio2013/Plugins/Plugin_Release64.props +++ b/Builds/VisualStudio2013/Plugins/Plugin_Release64.props @@ -11,7 +11,7 @@ <ItemDefinitionGroup> <ClCompile> <AdditionalIncludeDirectories>..\..\..\..\JuceLibraryCode;..\..\..\..\JuceLibraryCode\modules;..\..\..\..\Source\Plugins\Headers;..\..\..\..\Source\Plugins\CommonLibs;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>OEPLUGIN;WIN32;_WINDOWS;NDEBUG;JUCE_API=__declspec(dllimport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.3.5;JUCE_APP_VERSION_HEX=0x305;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>OEPLUGIN;WIN32;_WINDOWS;NDEBUG;JUCE_API=__declspec(dllimport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.4.2;JUCE_APP_VERSION_HEX=0x402;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <SDLCheck>false</SDLCheck> </ClCompile> <Link> diff --git a/Builds/VisualStudio2013/open-ephys.sln b/Builds/VisualStudio2013/open-ephys.sln index 8387e176d9e8917b8d6ef6c803d976565310eab1..59a9d10ba28a4b47817570df74b1433044daefbb 100644 --- a/Builds/VisualStudio2013/open-ephys.sln +++ b/Builds/VisualStudio2013/open-ephys.sln @@ -1,31 +1,21 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 +Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.40629.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "open-ephys", "open-ephys.vcxproj", "{9C924D66-7DEC-1AEF-B375-DB8666BFB909}" +Project("{5A05F353-1D63-394C-DFB0-981BB2309002}") = "open-ephys", "open-ephys.vcxproj", "{9C924D66-7DEC-1AEF-B375-DB8666BFB909}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Debug64|Win32 = Debug64|Win32 - Debug64|x64 = Debug64|x64 Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - Release64|Win32 = Release64|Win32 + Debug64|x64 = Debug64|x64 Release64|x64 = Release64|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug|Win32.ActiveCfg = Debug|Win32 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug|Win32.Build.0 = Debug|Win32 - {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug|x64.ActiveCfg = Debug|Win32 - {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|Win32.ActiveCfg = Debug64|x64 - {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.ActiveCfg = Debug64|x64 - {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.Build.0 = Debug64|x64 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release|Win32.ActiveCfg = Release|Win32 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release|Win32.Build.0 = Release|Win32 - {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release|x64.ActiveCfg = Release|Win32 - {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release64|Win32.ActiveCfg = Release64|x64 + {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.ActiveCfg = Debug64|x64 + {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Debug64|x64.Build.0 = Debug64|x64 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release64|x64.ActiveCfg = Release64|x64 {9C924D66-7DEC-1AEF-B375-DB8666BFB909}.Release64|x64.Build.0 = Release64|x64 EndGlobalSection diff --git a/Builds/VisualStudio2013/open-ephys.vcxproj b/Builds/VisualStudio2013/open-ephys.vcxproj index 043c61d7aadfbd8da720215f806026558ddb2116..28b9e28dcbd726afc970f1f7173dd5ddcb9bfda6 100644 --- a/Builds/VisualStudio2013/open-ephys.vcxproj +++ b/Builds/VisualStudio2013/open-ephys.vcxproj @@ -85,7 +85,7 @@ <Optimization>Disabled</Optimization> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> <AdditionalIncludeDirectories>~\SDKs\VST3 SDK;..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;JuceLibraryCode/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCE_API=__declspec(dllexport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.4.1;JUCE_APP_VERSION_HEX=0x401;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCE_API=__declspec(dllexport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.4.2;JUCE_APP_VERSION_HEX=0x402;%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeTypeInfo>true</RuntimeTypeInfo> <PrecompiledHeader/> @@ -131,7 +131,7 @@ <ClCompile> <Optimization>Full</Optimization> <AdditionalIncludeDirectories>~\SDKs\VST3 SDK;..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;JuceLibraryCode/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCE_API=__declspec(dllexport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.4.1;JUCE_APP_VERSION_HEX=0x401;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCE_API=__declspec(dllexport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.4.2;JUCE_APP_VERSION_HEX=0x402;%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> <RuntimeTypeInfo>true</RuntimeTypeInfo> <PrecompiledHeader/> @@ -179,7 +179,7 @@ <Optimization>Disabled</Optimization> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <AdditionalIncludeDirectories>~\SDKs\VST3 SDK;..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;JuceLibraryCode/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCE_API=__declspec(dllexport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.4.1;JUCE_APP_VERSION_HEX=0x401;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;NOMINMAX;JUCE_API=__declspec(dllexport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.4.2;JUCE_APP_VERSION_HEX=0x402;%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeTypeInfo>true</RuntimeTypeInfo> <PrecompiledHeader/> @@ -223,7 +223,7 @@ <ClCompile> <Optimization>Full</Optimization> <AdditionalIncludeDirectories>~\SDKs\VST3 SDK;..\..\JuceLibraryCode;..\..\JuceLibraryCode\modules;JuceLibraryCode/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCE_API=__declspec(dllexport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.4.1;JUCE_APP_VERSION_HEX=0x401;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;NOMINMAX;JUCE_API=__declspec(dllexport);JUCER_VS2013_78A5020=1;JUCE_APP_VERSION=0.4.2;JUCE_APP_VERSION_HEX=0x402;%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> <RuntimeTypeInfo>true</RuntimeTypeInfo> <PrecompiledHeader/> diff --git a/Builds/VisualStudio2013/resources.rc b/Builds/VisualStudio2013/resources.rc index 4a4d8f58e6c85219e251895ef82cafa648a1207d..13bfc913a492ab1a9b507be55871002f2d99aaa7 100644 --- a/Builds/VisualStudio2013/resources.rc +++ b/Builds/VisualStudio2013/resources.rc @@ -7,7 +7,7 @@ #include <windows.h> VS_VERSION_INFO VERSIONINFO -FILEVERSION 0,4,1,0 +FILEVERSION 0,4,2,0 BEGIN BLOCK "StringFileInfo" BEGIN @@ -15,9 +15,9 @@ BEGIN BEGIN VALUE "CompanyName", "Open Ephys\0" VALUE "FileDescription", "open-ephys\0" - VALUE "FileVersion", "0.4.1\0" + VALUE "FileVersion", "0.4.2\0" VALUE "ProductName", "open-ephys\0" - VALUE "ProductVersion", "0.4.1\0" + VALUE "ProductVersion", "0.4.2\0" END END diff --git a/JuceLibraryCode/JuceHeader.h b/JuceLibraryCode/JuceHeader.h index 68e83b7bf213d71c4fba40350b7382f5fad8ed20..1cf20a1c5c7d43aeeabb48a43dc74f8f3c13823c 100644 --- a/JuceLibraryCode/JuceHeader.h +++ b/JuceLibraryCode/JuceHeader.h @@ -42,8 +42,8 @@ namespace ProjectInfo { const char* const projectName = "open-ephys"; - const char* const versionString = "0.4.1"; - const int versionNumber = 0x401; + const char* const versionString = "0.4.2"; + const int versionNumber = 0x402; } #endif diff --git a/Source/Plugins/PCIeRhythm/Makefile b/Source/Plugins/PCIeRhythm/Makefile deleted file mode 100644 index 7ea147feb7214c68e4ac0b8d490b5a6d7705ef7e..0000000000000000000000000000000000000000 --- a/Source/Plugins/PCIeRhythm/Makefile +++ /dev/null @@ -1,39 +0,0 @@ - -LIBNAME := $(notdir $(CURDIR)) -OBJDIR := $(OBJDIR)/$(LIBNAME) -TARGET := $(LIBNAME).so - - -SRC_DIR := ${shell find ./ -type d -print} -VPATH := $(SOURCE_DIRS) - -SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.cpp)) -OBJ := $(addprefix $(OBJDIR)/,$(notdir $(SRC:.cpp=.o))) - -BLDCMD := $(CXX) -shared -o $(OUTDIR)/$(TARGET) $(OBJ) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH) - -VPATH = $(SRC_DIR) - -.PHONY: objdir - -$(OUTDIR)/$(TARGET): objdir $(OBJ) - -@mkdir -p $(BINDIR) - -@mkdir -p $(LIBDIR) - -@mkdir -p $(OUTDIR) - @echo "Building $(TARGET)" - @$(BLDCMD) - -$(OBJDIR)/%.o : %.cpp - @echo "Compiling $<" - @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" - - -objdir: - -@mkdir -p $(OBJDIR) - -clean: - @echo "Cleaning $(LIBNAME)" - -@rm -rf $(OBJDIR) - -@rm -f $(OUTDIR)/$(TARGET) - --include $(OBJ:%.o=%.d) diff --git a/Source/Plugins/PCIeRhythm/OpenEphysLib.cpp b/Source/Plugins/PCIeRhythm/OpenEphysLib.cpp deleted file mode 100644 index 8e932252c35eeeb8435074f41c92127939c97b1d..0000000000000000000000000000000000000000 --- a/Source/Plugins/PCIeRhythm/OpenEphysLib.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* ------------------------------------------------------------------- - -This file is part of the Open Ephys GUI -Copyright (C) 2013 Open Ephys - ------------------------------------------------------------------- - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program 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. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -*/ - -#include <PluginInfo.h> -#include "RHD2000Thread.h" -#include <string> -#ifdef WIN32 -#include <Windows.h> -#define EXPORT __declspec(dllexport) -#else -#define EXPORT __attribute__((visibility("default"))) -#endif - -using namespace Plugin; -#define NUM_PLUGINS 1 - -extern "C" EXPORT void getLibInfo(Plugin::LibraryInfo* info) -{ - info->apiVersion = PLUGIN_API_VER; - info->name = "PCIe Rhythm interface"; - info->libVersion = 1; - info->numPlugins = NUM_PLUGINS; -} - -extern "C" EXPORT int getPluginInfo(int index, Plugin::PluginInfo* info) -{ - switch (index) - { - case 0: - info->type = Plugin::PLUGIN_TYPE_DATA_THREAD; - info->dataThread.name = "PCIe Rhythm"; - info->dataThread.creator = &createDataThread<PCIeRhythm::RHD2000Thread>; - break; - default: - return -1; - break; - } - return 0; -} - -#ifdef WIN32 -BOOL WINAPI DllMain(IN HINSTANCE hDllHandle, - IN DWORD nReason, - IN LPVOID Reserved) -{ - return TRUE; -} - -#endif diff --git a/Source/Plugins/PCIeRhythm/RHD2000Editor.cpp b/Source/Plugins/PCIeRhythm/RHD2000Editor.cpp deleted file mode 100644 index dabcc6b45b8f5fbabff2228888f20b91875cdd36..0000000000000000000000000000000000000000 --- a/Source/Plugins/PCIeRhythm/RHD2000Editor.cpp +++ /dev/null @@ -1,1558 +0,0 @@ -/* - ------------------------------------------------------------------ - - This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys - - ------------------------------------------------------------------ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program 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. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "RHD2000Editor.h" -#include <cmath> -#include "RHD2000Thread.h" -using namespace PCIeRhythm; - -#ifdef WIN32 -#if (_MSC_VER < 1800) //round doesn't exist on MSVC prior to 2013 version -inline double round(double x) -{ - return floor(x+0.5); -} -#endif -#endif - -FPGAchannelList::FPGAchannelList(GenericProcessor* proc_, Viewport* p, FPGAcanvas* c) : chainUpdate(false), viewport(p), canvas(c) -{ - proc = (SourceNode*)proc_; - channelComponents.clear(); - - numberingSchemeLabel = new Label("Numbering scheme:","Numbering scheme:"); - numberingSchemeLabel->setEditable(false); - numberingSchemeLabel->setBounds(10,10,150, 25); - numberingSchemeLabel->setColour(Label::textColourId,juce::Colours::white); - addAndMakeVisible(numberingSchemeLabel); - - numberingScheme = new ComboBox("numberingScheme"); - numberingScheme->addItem("Continuous",1); - numberingScheme->addItem("Per Stream",2); - numberingScheme->setBounds(160,10,100,25); - numberingScheme->addListener(this); - numberingScheme->setSelectedId(1, dontSendNotification); - addAndMakeVisible(numberingScheme); - - impedanceButton = new UtilityButton("Measure Impedance", Font("Default", 13, Font::plain)); - impedanceButton->setRadius(3); - impedanceButton->setBounds(280,10,140,25); - impedanceButton->addListener(this); - addAndMakeVisible(impedanceButton); - - RHD2000Editor* e = static_cast<RHD2000Editor*>(proc->getEditor()); - saveImpedanceButton = new ToggleButton("Save impedance measurements"); - saveImpedanceButton->setBounds(430,10,110,25); - saveImpedanceButton->setToggleState(e->getSaveImpedance(),dontSendNotification); - saveImpedanceButton->addListener(this); - addAndMakeVisible(saveImpedanceButton); - - autoMeasureButton = new ToggleButton("Measure impedance at acquisition start"); - autoMeasureButton->setBounds(550,10,150,25); - autoMeasureButton->setToggleState(e->getAutoMeasureImpedance(),dontSendNotification); - autoMeasureButton->addListener(this); - addAndMakeVisible(autoMeasureButton); - - gains.clear(); - gains.add(0.01); - gains.add(0.1); - gains.add(1); - gains.add(2); - gains.add(5); - gains.add(10); - gains.add(20); - gains.add(50); - gains.add(100); - gains.add(500); - gains.add(1000); - - - update(); -} - -FPGAchannelList::~FPGAchannelList() -{ - -} - -void FPGAchannelList::paint(Graphics& g) -{ -} - -void FPGAchannelList::buttonClicked(Button* btn) -{ - RHD2000Editor* p = (RHD2000Editor*)proc->getEditor(); - if (btn == impedanceButton) - { - p->measureImpedance(); - } - else if (btn == saveImpedanceButton) - { - p->setSaveImpedance(btn->getToggleState()); - } - else if (btn == autoMeasureButton) - { - p->setAutoMeasureImpedance(btn->getToggleState()); - } -} - -void FPGAchannelList::update() -{ - // const int columnWidth = 330; - const int columnWidth = 250; - // Query processor for number of channels, types, gains, etc... and update the UI - channelComponents.clear(); - staticLabels.clear(); - - RHD2000Thread* thread = (RHD2000Thread*)proc->getThread(); - ChannelType type; - - // find out which streams are active. - bool hsActive[MAX_NUM_HEADSTAGES+1]; - //bool adcActive = false; - int numActiveHeadstages = 0; - int hsColumn[MAX_NUM_HEADSTAGES + 1]; - int numChannelsPerHeadstage[MAX_NUM_HEADSTAGES + 1]; - chainUpdate = false; - - for (int k = 0; k<MAX_NUM_HEADSTAGES; k++) - { - if (thread->isHeadstageEnabled(k)) - { - numChannelsPerHeadstage[k] = thread->getActiveChannelsInHeadstage(k); - hsActive[k] = true; - hsColumn[k] = numActiveHeadstages*columnWidth; - numActiveHeadstages++; - } - else - { - numChannelsPerHeadstage[k] = 0; - hsActive[k] = false; - hsColumn[k] = 0; - } - } - - if (thread->getNumAdcOutputs() > 0) - { - numChannelsPerHeadstage[MAX_NUM_HEADSTAGES] = thread->getNumAdcOutputs(); - hsActive[MAX_NUM_HEADSTAGES] = true; - hsColumn[MAX_NUM_HEADSTAGES] = numActiveHeadstages*columnWidth; - numActiveHeadstages++; - } - else - { - numChannelsPerHeadstage[MAX_NUM_HEADSTAGES] = 0; - hsActive[MAX_NUM_HEADSTAGES] = false; - hsColumn[MAX_NUM_HEADSTAGES] = 0; - } - - StringArray streamNames; - streamNames.add("Port A1"); - streamNames.add("Port A2"); - streamNames.add("Port B1"); - streamNames.add("Port B2"); - streamNames.add("Port C1"); - streamNames.add("Port C2"); - streamNames.add("Port D1"); - streamNames.add("Port D2"); - streamNames.add("ADC"); - - for (int k = 0; k < MAX_NUM_HEADSTAGES + 1; k++) - { - if (hsActive[k]) - { - Label* lbl = new Label(streamNames[k],streamNames[k]); - lbl->setEditable(false); - lbl->setBounds(10+hsColumn[k],40,columnWidth, 25); - lbl->setJustificationType(juce::Justification::centred); - lbl->setColour(Label::textColourId,juce::Colours::white); - staticLabels.add(lbl); - addAndMakeVisible(lbl); - - } - - } - - for (int k = 0; k < MAX_NUM_HEADSTAGES + 1; k++) - { - if (hsActive[k]) - { - for (int ch = 0; ch < numChannelsPerHeadstage[k]+ (k < MAX_NUM_HEADSTAGES ? 3 : 0); ch++) - { - int channelGainIndex = 1; - int realChan = thread->getChannelFromHeadstage(k, ch); - float ch_gain = proc->channels[realChan]->getBitVolts() / proc->getBitVolts(proc->channels[realChan]); - for (int j = 0; j < gains.size(); j++) - { - if (fabs(gains[j] - ch_gain) < 1e-3) - { - channelGainIndex = j; - break; - } - } - if (k < MAX_NUM_HEADSTAGES) - type = ch < numChannelsPerHeadstage[k] ? HEADSTAGE_CHANNEL : AUX_CHANNEL; - else - type = ADC_CHANNEL; - - FPGAchannelComponent* comp = new FPGAchannelComponent(this, realChan, channelGainIndex + 1, thread->getChannelName(realChan), gains,type); - comp->setBounds(10 + hsColumn[k], 70 + ch * 22, columnWidth, 22); - comp->setUserDefinedData(k); - addAndMakeVisible(comp); - channelComponents.add(comp); - } - } - } - - - StringArray ttlNames; - proc->getEventChannelNames(ttlNames); - // add buttons for TTL channels - for (int k=0; k<ttlNames.size(); k++) - { - FPGAchannelComponent* comp = new FPGAchannelComponent(this,k, -1, ttlNames[k],gains,EVENT_CHANNEL); - comp->setBounds(10+numActiveHeadstages*columnWidth,70+k*22,columnWidth,22); - comp->setUserDefinedData(k); - addAndMakeVisible(comp); - channelComponents.add(comp); - } - - Label* lbl = new Label("TTL Events","TTL Events"); - lbl->setEditable(false); - lbl->setBounds(numActiveHeadstages*columnWidth,40,columnWidth, 25); - lbl->setJustificationType(juce::Justification::centred); - lbl->setColour(Label::textColourId,juce::Colours::white); - staticLabels.add(lbl); - addAndMakeVisible(lbl); - - chainUpdate = true; -} - -void FPGAchannelList::disableAll() -{ - for (int k=0; k<channelComponents.size(); k++) - { - channelComponents[k]->disableEdit(); - } - impedanceButton->setEnabled(false); - saveImpedanceButton->setEnabled(false); - autoMeasureButton->setEnabled(false); - numberingScheme->setEnabled(false); -} - -void FPGAchannelList::enableAll() -{ - for (int k=0; k<channelComponents.size(); k++) - { - channelComponents[k]->enableEdit(); - } - impedanceButton->setEnabled(true); - saveImpedanceButton->setEnabled(true); - autoMeasureButton->setEnabled(true); - numberingScheme->setEnabled(true); -} - -void FPGAchannelList::setNewGain(int channel, float gain) -{ - RHD2000Thread* thread = (RHD2000Thread*)proc->getThread(); - thread->modifyChannelGain(channel, gain); - if (chainUpdate) - proc->requestChainUpdate(); -} - -void FPGAchannelList::setNewName(int channel, String newName) -{ - RHD2000Thread* thread = (RHD2000Thread*)proc->getThread(); - thread->modifyChannelName(channel, newName); - if (chainUpdate) - proc->requestChainUpdate(); -} - -void FPGAchannelList::updateButtons() -{ -} - -int FPGAchannelList::getNumChannels() -{ - return 0; -} - -void FPGAchannelList::comboBoxChanged(ComboBox* b) -{ - if (b == numberingScheme) - { - SourceNode* p = (SourceNode*)proc; - RHD2000Thread* thread = (RHD2000Thread*)p->getThread(); - int scheme = numberingScheme->getSelectedId(); - thread->setDefaultNamingScheme(scheme); - update(); - p->requestChainUpdate(); - } -} - -void FPGAchannelList::updateImpedance(Array<int> streams, Array<int> channels, Array<float> magnitude, Array<float> phase) -{ - int i = 0; - for (int k = 0; k < streams.size(); k++) - { - if (i >= channelComponents.size()) - break; //little safety - - if (channelComponents[i]->type != HEADSTAGE_CHANNEL) - { - k--; - } - else - { - channelComponents[i]->setImpedanceValues(magnitude[k], phase[k]); - } - i++; - } - -} - - -/****************************************************/ -FPGAchannelComponent::FPGAchannelComponent(FPGAchannelList* cl, int ch, int gainIndex_, String N, Array<float> gains_, ChannelType type_) : -type(type_), gains(gains_), channelList(cl), channel(ch), name(N), gainIndex(gainIndex_) -{ - Font f = Font("Small Text", 13, Font::plain); - - staticLabel = new Label("Channel","Channel"); - staticLabel->setFont(f); - staticLabel->setEditable(false); - addAndMakeVisible(staticLabel); - - editName = new Label(name,name); - editName->setFont(f); - editName->setEditable(true); - editName->setColour(Label::backgroundColourId,juce::Colours::lightgrey); - editName->addListener(this); - addAndMakeVisible(editName); -/* if (gainIndex > 0) - { - - gainComboBox = new ComboBox("Gains"); - for (int k=0; k<gains.size(); k++) - { - if (gains[k] < 1) - { - gainComboBox->addItem("x"+String(gains[k],2),k+1); - } - else - { - gainComboBox->addItem("x"+String((int)gains[k]),k+1); - } - } - gainComboBox->setSelectedId(gainIndex, sendNotificationSync); - gainComboBox->addListener(this); - addAndMakeVisible(gainComboBox); - } - else - {*/ - gainComboBox = nullptr; - //} - - if (type == HEADSTAGE_CHANNEL) - { - impedance = new Label("Impedance","? Ohm"); - impedance->setFont(Font("Default", 13, Font::plain)); - impedance->setEditable(false); - addAndMakeVisible(impedance); - } - else - { - impedance = nullptr; - } -} -FPGAchannelComponent::~FPGAchannelComponent() -{ - -} - -void FPGAchannelComponent::setImpedanceValues(float mag, float phase) -{ - if (impedance != nullptr) - { - if (mag > 10000) - impedance->setText(String(mag/1e6,2)+" mOhm, "+String((int)phase) + " deg",juce::NotificationType::dontSendNotification); - else if (mag > 1000) - impedance->setText(String(mag/1e3,0)+" kOhm, "+String((int)phase) + " deg" ,juce::NotificationType::dontSendNotification); - else - impedance->setText(String(mag,0)+" Ohm, "+String((int)phase) + " deg" ,juce::NotificationType::dontSendNotification); - } - else - { - - } -} - -void FPGAchannelComponent::comboBoxChanged(ComboBox* comboBox) -{ - if (comboBox == gainComboBox) - { - int newGainIndex = gainComboBox->getSelectedId(); - float mult = gains[newGainIndex-1]; - float bitvolts = channelList->proc->getBitVolts(channelList->proc->channels[channel]); - channelList->setNewGain(channel, mult*bitvolts); - } -} -void FPGAchannelComponent::labelTextChanged(Label* lbl) -{ - // channel name change - String newName = lbl->getText(); - channelList->setNewName(channel, newName); -} - -void FPGAchannelComponent::disableEdit() -{ - editName->setEnabled(false); -} - -void FPGAchannelComponent::enableEdit() -{ - editName->setEnabled(true); -} - -void FPGAchannelComponent::buttonClicked(Button* btn) -{ -} - -void FPGAchannelComponent::setUserDefinedData(int d) -{ -} - -int FPGAchannelComponent::getUserDefinedData() -{ - return 0; -} - -void FPGAchannelComponent::resized() -{ - editName->setBounds(0,0,90,20); - if (gainComboBox != nullptr) - { - gainComboBox->setBounds(100,0,70,20); - } - if (impedance != nullptr) - { - // impedance->setBounds(180,0,130,20); - impedance->setBounds(100, 0, 130, 20); - } - -} - - - -/**********************************************/ - -FPGAcanvas::FPGAcanvas(GenericProcessor* n) -{ - processor = (SourceNode*)n; - channelsViewport = new Viewport(); - channelList = new FPGAchannelList(processor, channelsViewport, this); - channelsViewport->setViewedComponent(channelList, false); - channelsViewport->setScrollBarsShown(true, true); - addAndMakeVisible(channelsViewport); - - resized(); - update(); -} - -FPGAcanvas::~FPGAcanvas() -{ -} - -void FPGAcanvas::setParameter(int x, float f) -{ - -} - -void FPGAcanvas::setParameter(int a, int b, int c, float d) -{ -} - -void FPGAcanvas::paint(Graphics& g) -{ - g.fillAll(Colours::grey); - -} - -void FPGAcanvas::refresh() -{ - repaint(); -} - -void FPGAcanvas::refreshState() -{ - resized(); -} - - -void FPGAcanvas::beginAnimation() -{ -} - -void FPGAcanvas::endAnimation() -{ -} - -void FPGAcanvas::update() -{ - // create channel buttons (name, gain, recording, impedance, ... ?) - channelList->update(); - if (static_cast<RHD2000Thread*>(processor->getThread())->isAcquisitionActive()) - { - channelList->disableAll(); - } -} - -void FPGAcanvas::resized() -{ - //int screenWidth = getWidth(); - //int screenHeight = getHeight(); - - int scrollBarThickness = channelsViewport->getScrollBarThickness(); - int numChannels = 35; // max channels per stream? (32+3)*2 - - channelsViewport->setBounds(0,0,getWidth(),getHeight()); - channelList->setBounds(0,0,getWidth()-scrollBarThickness, 200+22*numChannels); -} - -void FPGAcanvas::buttonClicked(Button* button) -{ -} - -void FPGAcanvas::updateImpedance(Array<int> streams, Array<int> channels, Array<float> magnitude, Array<float> phase) -{ - channelList->updateImpedance(streams, channels, magnitude, phase); -} - -/***********************************************************************/ - -RHD2000Editor::RHD2000Editor(GenericProcessor* parentNode, - RHD2000Thread* board_, - bool useDefaultParameterEditors - ) - : VisualizerEditor(parentNode, useDefaultParameterEditors), board(board_) -{ - canvas = nullptr; - desiredWidth = 340; - tabText = "FPGA"; - measureWhenRecording = false; - saveImpedances = false; - - impedanceData = new ImpedanceData(); - impedanceData->valid = false; - - // add headstage-specific controls (currently just an enable/disable button) - for (int i = 0; i < 4; i++) - { - HeadstageOptionsInterface* hsOptions = new HeadstageOptionsInterface(board, this, i); - headstageOptionsInterfaces.add(hsOptions); - addAndMakeVisible(hsOptions); - hsOptions->setBounds(3, 28+i*20, 70, 18); - } - - // add sample rate selection - sampleRateInterface = new SampleRateInterface(board, this); - addAndMakeVisible(sampleRateInterface); - sampleRateInterface->setBounds(80, 25, 110, 50); - - // add Bandwidth selection - bandwidthInterface = new BandwidthInterface(board, this); - addAndMakeVisible(bandwidthInterface); - bandwidthInterface->setBounds(80, 58, 80, 50); - - // add DSP selection - // dspInterface = new DSPInterface(board, this); - // addAndMakeVisible(dspInterface); - // dspInterface->setBounds(80, 58, 80, 50); - - // add rescan button - rescanButton = new UtilityButton("RESCAN", Font("Small Text", 13, Font::plain)); - rescanButton->setRadius(3.0f); - rescanButton->setBounds(6, 108,65,18); - rescanButton->addListener(this); - rescanButton->setTooltip("Check for connected headstages"); - addAndMakeVisible(rescanButton); - - for (int i = 0; i < 2; i++) - { - ElectrodeButton* button = new ElectrodeButton(-1); - electrodeButtons.add(button); - - button->setBounds(200+i*25, 40, 25, 15); - button->setChannelNum(-1); - button->setToggleState(false, dontSendNotification); - button->setRadioGroupId(999); - - addAndMakeVisible(button); - button->addListener(this); - - if (i == 0) - { - button->setTooltip("Audio monitor left channel"); - } - else - { - button->setTooltip("Audio monitor right channel"); - } - } - - audioLabel = new Label("audio label", "Audio out"); - audioLabel->setBounds(190,25,75,15); - audioLabel->setFont(Font("Small Text", 10, Font::plain)); - audioLabel->setColour(Label::textColourId, Colours::darkgrey); - addAndMakeVisible(audioLabel); - - // add HW audio parameter selection - audioInterface = new AudioInterface(board, this); - addAndMakeVisible(audioInterface); - audioInterface->setBounds(179, 58, 70, 50); - - clockInterface = new ClockDivideInterface(board, this); - addAndMakeVisible(clockInterface); - clockInterface->setBounds(179, 82, 70, 50); - - adcButton = new UtilityButton("ADC 1-8", Font("Small Text", 13, Font::plain)); - adcButton->setRadius(3.0f); - adcButton->setBounds(179,108,70,18); - adcButton->addListener(this); - adcButton->setClickingTogglesState(true); - adcButton->setTooltip("Enable/disable ADC channels"); - addAndMakeVisible(adcButton); - - ledButton = new UtilityButton("LED", Font("Very Small Text", 13, Font::plain)); - ledButton->setRadius(3.0f); - ledButton->setBounds(140, 108, 30, 18); - ledButton->addListener(this); - ledButton->setClickingTogglesState(true); - ledButton->setTooltip("Enable/disable board LEDs"); - addAndMakeVisible(ledButton); - ledButton->setToggleState(true, dontSendNotification); - - // add DSP Offset Button - dspoffsetButton = new UtilityButton("DSP", Font("Very Small Text", 13, Font::plain)); - dspoffsetButton->setRadius(3.0f); // sets the radius of the button's corners - dspoffsetButton->setBounds(80, 108,30,18); // sets the x position, y position, width, and height of the button - dspoffsetButton->addListener(this); - dspoffsetButton->setClickingTogglesState(true); // makes the button toggle its state when clicked - dspoffsetButton->setTooltip("Enable/disable DSP offset removal"); - addAndMakeVisible(dspoffsetButton); // makes the button a child component of the editor and makes it visible - dspoffsetButton->setToggleState(true, dontSendNotification); - - // add DSP Frequency Selection field - dspInterface = new DSPInterface(board, this); - addAndMakeVisible(dspInterface); - dspInterface->setBounds(110, 108, 30, 50); - - ttlSettleLabel = new Label("TTL Settle","TTL Settle"); - ttlSettleLabel->setFont(Font("Small Text", 11, Font::plain)); - ttlSettleLabel->setBounds(255,80,100,20); - ttlSettleLabel->setColour(Label::textColourId, Colours::darkgrey); - addAndMakeVisible(ttlSettleLabel); - - - ttlSettleCombo = new ComboBox("FastSettleComboBox"); - ttlSettleCombo->setBounds(260,100,60,18); - ttlSettleCombo->addListener(this); - ttlSettleCombo->addItem("-",1); - for (int k=0; k<8; k++) - { - ttlSettleCombo->addItem("TTL"+String(1+k),2+k); - } - ttlSettleCombo->setSelectedId(1, sendNotification); - addAndMakeVisible(ttlSettleCombo); - - dacTTLButton = new UtilityButton("DAC TTL", Font("Small Text", 13, Font::plain)); - dacTTLButton->setRadius(3.0f); - dacTTLButton->setBounds(260,25,65,18); - dacTTLButton->addListener(this); - dacTTLButton->setClickingTogglesState(true); - dacTTLButton->setTooltip("Enable/disable DAC Threshold TTL Output"); - addAndMakeVisible(dacTTLButton); - - dacHPFlabel = new Label("DAC HPF","DAC HPF"); - dacHPFlabel->setFont(Font("Small Text", 11, Font::plain)); - dacHPFlabel->setBounds(260,42,100,20); - dacHPFlabel->setColour(Label::textColourId, Colours::darkgrey); - addAndMakeVisible(dacHPFlabel); - - dacHPFcombo = new ComboBox("dacHPFCombo"); - dacHPFcombo->setBounds(260,60,60,18); - dacHPFcombo->addListener(this); - dacHPFcombo->addItem("OFF",1); - int HPFvalues[10] = {50,100,200,300,400,500,600,700,800,900}; - for (int k=0; k<10; k++) - { - dacHPFcombo->addItem(String(HPFvalues[k])+" Hz",2+k); - } - dacHPFcombo->setSelectedId(1, sendNotification); - addAndMakeVisible(dacHPFcombo); - -} - -RHD2000Editor::~RHD2000Editor() -{ - -} - -void RHD2000Editor::scanPorts() -{ - rescanButton->triggerClick(); -} - -void RHD2000Editor::measureImpedance() -{ - impedanceData->valid = false; - board->runImpedanceTest(impedanceData); -} - -void RHD2000Editor::handleAsyncUpdate() -{ - if (!impedanceData->valid) - return; - if (canvas == nullptr) - VisualizerEditor::canvas = createNewCanvas(); - // update components... - canvas->updateImpedance(impedanceData->streams, impedanceData->channels, impedanceData->magnitudes, impedanceData->phases); - if (saveImpedances) - { - CoreServices::RecordNode::createNewrecordingDir(); - - String path(CoreServices::RecordNode::getRecordingPath().getFullPathName() - + File::separatorString + "impedance_measurement.xml"); - std::cout << "Saving impedance measurements in " << path << "\n"; - File file(path); - - if (!file.getParentDirectory().exists()) - file.getParentDirectory().createDirectory(); - - XmlDocument doc(file); - ScopedPointer<XmlElement> xml = new XmlElement("CHANNEL_IMPEDANCES"); - for (int i = 0; i < impedanceData->channels.size(); i++) - { - XmlElement* chan = new XmlElement("CHANNEL"); - chan->setAttribute("name",board->getChannelName(i)); - chan->setAttribute("stream", impedanceData->streams[i]); - chan->setAttribute("channel_number", impedanceData->channels[i]); - chan->setAttribute("magnitude", impedanceData->magnitudes[i]); - chan->setAttribute("phase", impedanceData->phases[i]); - xml->addChildElement(chan); - } - xml->writeToFile(file,String::empty); - } - -} - -void RHD2000Editor::setSaveImpedance(bool en) -{ - saveImpedances = en; -} - -void RHD2000Editor::setAutoMeasureImpedance(bool en) -{ - measureWhenRecording = en; -} - -bool RHD2000Editor::getSaveImpedance() -{ - return saveImpedances; -} - -bool RHD2000Editor::getAutoMeasureImpedance() -{ - return measureWhenRecording; -} - -void RHD2000Editor::comboBoxChanged(ComboBox* comboBox) -{ - if (comboBox == ttlSettleCombo) - { - int selectedChannel = ttlSettleCombo->getSelectedId(); - if (selectedChannel == 1) - { - board->setFastTTLSettle(false,0); - } - else - { - board->setFastTTLSettle(true,selectedChannel-2); - } - } - else if (comboBox == dacHPFcombo) - { - int selection = dacHPFcombo->getSelectedId(); - if (selection == 1) - { - board->setDAChpf(100,false); - } - else - { - int HPFvalues[10] = {50,100,200,300,400,500,600,700,800,900}; - board->setDAChpf(HPFvalues[selection-2],true); - } - } -} - - -void RHD2000Editor::buttonEvent(Button* button) -{ - if (button == rescanButton && !acquisitionIsActive) - { - board->scanPorts(); - - for (int i = 0; i < 4; i++) - { - headstageOptionsInterfaces[i]->checkEnabledState(); - } - // board->updateChannelNames(); - CoreServices::updateSignalChain(this); - } - else if (button == electrodeButtons[0]) - { - channelSelector->setRadioStatus(true); - } - else if (button == electrodeButtons[1]) - { - channelSelector->setRadioStatus(true); - } - else if (button == adcButton && !acquisitionIsActive) - { - board->enableAdcs(button->getToggleState()); - // board->updateChannelNames(); - std::cout << "ADC Button toggled" << "\n"; - CoreServices::updateSignalChain(this); - std::cout << "Editor visible." << "\n"; - } - else if (button == dacTTLButton) - { - board->setTTLoutputMode(dacTTLButton->getToggleState()); - } - else if (button == dspoffsetButton && !acquisitionIsActive) - { - std::cout << "DSP offset " << button->getToggleState() << "\n"; - board->setDSPOffset(button->getToggleState()); - } - else if (button == ledButton) - { - board->enableBoardLeds(button->getToggleState()); - } - -} - -void RHD2000Editor::channelChanged (int channel, bool /*newState*/) -{ - for (int i = 0; i < 2; i++) - { - if (electrodeButtons[i]->getToggleState()) - { - electrodeButtons[i]->setChannelNum (channel); - electrodeButtons[i]->repaint(); - board->setDACchannel (i, channel); - } - } -} - -void RHD2000Editor::startAcquisition() -{ - if (measureWhenRecording) - measureImpedance(); - - channelSelector->startAcquisition(); - - rescanButton->setEnabledState(false); - adcButton->setEnabledState(false); - dspoffsetButton-> setEnabledState(false); - acquisitionIsActive = true; - if (canvas != nullptr) - canvas->channelList->disableAll(); - //canvas->channelList->setEnabled(false); -} - -void RHD2000Editor::stopAcquisition() -{ - - channelSelector->stopAcquisition(); - - rescanButton->setEnabledState(true); - adcButton->setEnabledState(true); - dspoffsetButton-> setEnabledState(true); - - acquisitionIsActive = false; - if (canvas != nullptr) - canvas->channelList->enableAll(); - // canvas->channelList->setEnabled(true); -} - -void RHD2000Editor::saveCustomParameters(XmlElement* xml) -{ - xml->setAttribute("SampleRate", sampleRateInterface->getSelectedId()); - xml->setAttribute("LowCut", bandwidthInterface->getLowerBandwidth()); - xml->setAttribute("HighCut", bandwidthInterface->getUpperBandwidth()); - xml->setAttribute("ADCsOn", adcButton->getToggleState()); - xml->setAttribute("SampleRate", sampleRateInterface->getSelectedId()); - xml->setAttribute("LowCut", bandwidthInterface->getLowerBandwidth()); - xml->setAttribute("HighCut", bandwidthInterface->getUpperBandwidth()); - xml->setAttribute("ADCsOn", adcButton->getToggleState()); - xml->setAttribute("AudioOutputL", electrodeButtons[0]->getChannelNum()); - xml->setAttribute("AudioOutputR", electrodeButtons[1]->getChannelNum()); - xml->setAttribute("NoiseSlicer", audioInterface->getNoiseSlicerLevel()); - xml->setAttribute("TTLFastSettle", ttlSettleCombo->getSelectedId()); - xml->setAttribute("DAC_TTL", dacTTLButton->getToggleState()); - xml->setAttribute("DAC_HPF", dacHPFcombo->getSelectedId()); - xml->setAttribute("DSPOffset", dspoffsetButton->getToggleState()); - xml->setAttribute("DSPCutoffFreq", dspInterface->getDspCutoffFreq()); - xml->setAttribute("save_impedance_measurements",saveImpedances); - xml->setAttribute("auto_measure_impedances",measureWhenRecording); - xml->setAttribute("LEDs", ledButton->getToggleState()); - xml->setAttribute("ClockDivideRatio", clockInterface->getClockDivideRatio()); -} - -void RHD2000Editor::loadCustomParameters(XmlElement* xml) -{ - - sampleRateInterface->setSelectedId(xml->getIntAttribute("SampleRate")); - bandwidthInterface->setLowerBandwidth(xml->getDoubleAttribute("LowCut")); - bandwidthInterface->setUpperBandwidth(xml->getDoubleAttribute("HighCut")); - adcButton->setToggleState(xml->getBoolAttribute("ADCsOn"), sendNotification); - //electrodeButtons[0]->setChannelNum(xml->getIntAttribute("AudioOutputL")); - //board->assignAudioOut(0, xml->getIntAttribute("AudioOutputL")); - //electrodeButtons[1]->setChannelNum(xml->getIntAttribute("AudioOutputR")); - //board->assignAudioOut(1, xml->getIntAttribute("AudioOutputR")); - audioInterface->setNoiseSlicerLevel(xml->getIntAttribute("NoiseSlicer")); - ttlSettleCombo->setSelectedId(xml->getIntAttribute("TTLFastSettle")); - dacTTLButton->setToggleState(xml->getBoolAttribute("DAC_TTL"), sendNotification); - dacHPFcombo->setSelectedId(xml->getIntAttribute("DAC_HPF")); - dspoffsetButton->setToggleState(xml->getBoolAttribute("DSPOffset"), sendNotification); - dspInterface->setDspCutoffFreq(xml->getDoubleAttribute("DSPCutoffFreq")); - saveImpedances = xml->getBoolAttribute("save_impedance_measurements"); - measureWhenRecording = xml->getBoolAttribute("auto_measure_impedances"); - ledButton->setToggleState(xml->getBoolAttribute("LEDs", true),sendNotification); - clockInterface->setClockDivideRatio(xml->getIntAttribute("ClockDivideRatio")); -} - - -Visualizer* RHD2000Editor::createNewCanvas() -{ - GenericProcessor* processor = (GenericProcessor*) getProcessor(); - canvas= new FPGAcanvas(processor); - //ActionListener* listener = (ActionListener*) canvas; - //getUIComponent()->registerAnimatedComponent(listener); - return canvas; -} - -// Bandwidth Options -------------------------------------------------------------------- - -BandwidthInterface::BandwidthInterface(RHD2000Thread* board_, - RHD2000Editor* editor_) : - board(board_), editor(editor_) -{ - - name = "Bandwidth"; - - lastHighCutString = "7500"; - lastLowCutString = "1"; - - actualUpperBandwidth = 7500.0f; - actualLowerBandwidth = 1.0f; - - upperBandwidthSelection = new Label("UpperBandwidth",lastHighCutString); // this is currently set in RHD2000Thread, the cleaner would be to set it here again - upperBandwidthSelection->setEditable(true,false,false); - upperBandwidthSelection->addListener(this); - upperBandwidthSelection->setBounds(30,30,60,20); - upperBandwidthSelection->setColour(Label::textColourId, Colours::darkgrey); - addAndMakeVisible(upperBandwidthSelection); - - - lowerBandwidthSelection = new Label("LowerBandwidth",lastLowCutString); - lowerBandwidthSelection->setEditable(true,false,false); - lowerBandwidthSelection->addListener(this); - lowerBandwidthSelection->setBounds(25,10,60,20); - lowerBandwidthSelection->setColour(Label::textColourId, Colours::darkgrey); - - addAndMakeVisible(lowerBandwidthSelection); - - - -} - -BandwidthInterface::~BandwidthInterface() -{ - -} - - -void BandwidthInterface::labelTextChanged(Label* label) -{ - - if (!(editor->acquisitionIsActive) && board->foundInputSource()) - { - if (label == upperBandwidthSelection) - { - - Value val = label->getTextValue(); - double requestedValue = double(val.getValue()); - - if (requestedValue < 100.0 || requestedValue > 20000.0 || requestedValue < lastLowCutString.getFloatValue()) - { - CoreServices::sendStatusMessage("Value out of range."); - - label->setText(lastHighCutString, dontSendNotification); - - return; - } - - actualUpperBandwidth = board->setUpperBandwidth(requestedValue); - - std::cout << "Setting Upper Bandwidth to " << requestedValue << "\n"; - std::cout << "Actual Upper Bandwidth: " << actualUpperBandwidth << "\n"; - label->setText(String(round(actualUpperBandwidth*10.f)/10.f), dontSendNotification); - - } - else - { - - Value val = label->getTextValue(); - double requestedValue = double(val.getValue()); - - if (requestedValue < 0.1 || requestedValue > 500.0 || requestedValue > lastHighCutString.getFloatValue()) - { - CoreServices::sendStatusMessage("Value out of range."); - - label->setText(lastLowCutString, dontSendNotification); - - return; - } - - actualLowerBandwidth = board->setLowerBandwidth(requestedValue); - - std::cout << "Setting Lower Bandwidth to " << requestedValue << "\n"; - std::cout << "Actual Lower Bandwidth: " << actualLowerBandwidth << "\n"; - - label->setText(String(round(actualLowerBandwidth*10.f)/10.f), dontSendNotification); - } - } - else if (editor->acquisitionIsActive) - { - CoreServices::sendStatusMessage("Can't change bandwidth while acquisition is active!"); - if (label == upperBandwidthSelection) - label->setText(lastHighCutString, dontSendNotification); - else - label->setText(lastLowCutString, dontSendNotification); - return; - } - -} - -void BandwidthInterface::setLowerBandwidth(double value) -{ - actualLowerBandwidth = board->setLowerBandwidth(value); - lowerBandwidthSelection->setText(String(round(actualLowerBandwidth*10.f)/10.f), dontSendNotification); -} - -void BandwidthInterface::setUpperBandwidth(double value) -{ - actualUpperBandwidth = board->setUpperBandwidth(value); - upperBandwidthSelection->setText(String(round(actualUpperBandwidth*10.f)/10.f), dontSendNotification); -} - -double BandwidthInterface::getLowerBandwidth() -{ - return actualLowerBandwidth; -} - -double BandwidthInterface::getUpperBandwidth() -{ - return actualUpperBandwidth; -} - - -void BandwidthInterface::paint(Graphics& g) -{ - - g.setColour(Colours::darkgrey); - - g.setFont(Font("Small Text",10,Font::plain)); - - g.drawText(name, 0, 0, 200, 15, Justification::left, false); - - g.drawText("Low: ", 0, 10, 200, 20, Justification::left, false); - - g.drawText("High: ", 0, 30, 200, 20, Justification::left, false); - -} - -// Sample rate Options -------------------------------------------------------------------- - -SampleRateInterface::SampleRateInterface(RHD2000Thread* board_, - RHD2000Editor* editor_) : - board(board_), editor(editor_) -{ - - name = "Sample Rate"; - - sampleRateOptions.add("1.00 kS/s"); - sampleRateOptions.add("1.25 kS/s"); - sampleRateOptions.add("1.50 kS/s"); - sampleRateOptions.add("2.00 kS/s"); - sampleRateOptions.add("2.50 kS/s"); - sampleRateOptions.add("3.00 kS/s"); - sampleRateOptions.add("3.33 kS/s"); - sampleRateOptions.add("4.00 kS/s"); - sampleRateOptions.add("5.00 kS/s"); - sampleRateOptions.add("6.25 kS/s"); - sampleRateOptions.add("8.00 kS/s"); - sampleRateOptions.add("10.0 kS/s"); - sampleRateOptions.add("12.5 kS/s"); - sampleRateOptions.add("15.0 kS/s"); - sampleRateOptions.add("20.0 kS/s"); - sampleRateOptions.add("25.0 kS/s"); - sampleRateOptions.add("30.0 kS/s"); - - - rateSelection = new ComboBox("Sample Rate"); - rateSelection->addItemList(sampleRateOptions, 1); - rateSelection->setSelectedId(17, dontSendNotification); - rateSelection->addListener(this); - - rateSelection->setBounds(0,15,300,20); - addAndMakeVisible(rateSelection); - - -} - -SampleRateInterface::~SampleRateInterface() -{ - -} - -void SampleRateInterface::comboBoxChanged(ComboBox* cb) -{ - if (!(editor->acquisitionIsActive) && board->foundInputSource()) - { - if (cb == rateSelection) - { - board->setSampleRate(cb->getSelectedId()-1); - - std::cout << "Setting sample rate to index " << cb->getSelectedId()-1 << "\n"; - - CoreServices::updateSignalChain(editor); - } - } -} - -int SampleRateInterface::getSelectedId() -{ - return rateSelection->getSelectedId(); -} - -void SampleRateInterface::setSelectedId(int id) -{ - rateSelection->setSelectedId(id); -} - - -void SampleRateInterface::paint(Graphics& g) -{ - - g.setColour(Colours::darkgrey); - - g.setFont(Font("Small Text",10,Font::plain)); - - g.drawText(name, 0, 0, 200, 15, Justification::left, false); - -} - - -// Headstage Options -------------------------------------------------------------------- - -HeadstageOptionsInterface::HeadstageOptionsInterface(RHD2000Thread* board_, - RHD2000Editor* editor_, - int hsNum) : - isEnabled(false), board(board_), editor(editor_) -{ - - switch (hsNum) - { - case 0 : - name = "A"; - break; - case 1: - name = "B"; - break; - case 2: - name = "C"; - break; - case 3: - name = "D"; - break; - default: - name = "X"; - } - - hsNumber1 = hsNum*2; // data stream 1 - hsNumber2 = hsNumber1+1; // data stream 2 - - channelsOnHs1 = 0; - channelsOnHs2 = 0; - - - - hsButton1 = new UtilityButton(" ", Font("Small Text", 13, Font::plain)); - hsButton1->setRadius(3.0f); - hsButton1->setBounds(23,1,20,17); - hsButton1->setEnabledState(false); - hsButton1->setCorners(true, false, true, false); - hsButton1->addListener(this); - addAndMakeVisible(hsButton1); - - hsButton2 = new UtilityButton(" ", Font("Small Text", 13, Font::plain)); - hsButton2->setRadius(3.0f); - hsButton2->setBounds(43,1,20,17); - hsButton2->setEnabledState(false); - hsButton2->setCorners(false, true, false, true); - hsButton2->addListener(this); - addAndMakeVisible(hsButton2); - - checkEnabledState(); -} - -HeadstageOptionsInterface::~HeadstageOptionsInterface() -{ - -} - -void HeadstageOptionsInterface::checkEnabledState() -{ - isEnabled = (board->isHeadstageEnabled(hsNumber1) || - board->isHeadstageEnabled(hsNumber2)); - - if (board->isHeadstageEnabled(hsNumber1)) - { - channelsOnHs1 = board->getActiveChannelsInHeadstage(hsNumber1); - hsButton1->setLabel(String(channelsOnHs1)); - hsButton1->setEnabledState(true); - } - else - { - channelsOnHs1 = 0; - hsButton1->setLabel(" "); - hsButton1->setEnabledState(false); - } - - if (board->isHeadstageEnabled(hsNumber2)) - { - channelsOnHs2 = board->getActiveChannelsInHeadstage(hsNumber2); - hsButton2->setLabel(String(channelsOnHs2)); - hsButton2->setEnabledState(true); - } - else - { - channelsOnHs2 = 0; - hsButton2->setLabel(" "); - hsButton2->setEnabledState(false); - } - - repaint(); - -} - -void HeadstageOptionsInterface::buttonClicked(Button* button) -{ - - if (!(editor->acquisitionIsActive) && board->foundInputSource()) - { - - //std::cout << "Acquisition is not active" << "\n"; - if ((button == hsButton1) && (board->getChannelsInHeadstage(hsNumber1) == 32)) - { - if (channelsOnHs1 == 32) - channelsOnHs1 = 16; - else - channelsOnHs1 = 32; - - //std::cout << "HS1 has " << channelsOnHs1 << " channels." << "\n"; - - hsButton1->setLabel(String(channelsOnHs1)); - board->setNumChannels(hsNumber1, channelsOnHs1); - - //board->updateChannels(); - editor->updateSettings(); - - } - else if ((button == hsButton2) && (board->getChannelsInHeadstage(hsNumber2) == 32)) - { - if (channelsOnHs2 == 32) - channelsOnHs2 = 16; - else - channelsOnHs2 = 32; - - hsButton2->setLabel(String(channelsOnHs2)); - board->setNumChannels(hsNumber2, channelsOnHs2); - //board->updateChannels(); - editor->updateSettings(); - } - - CoreServices::updateSignalChain(editor); - } - -} - - -void HeadstageOptionsInterface::paint(Graphics& g) -{ - g.setColour(Colours::lightgrey); - - g.fillRoundedRectangle(5,0,getWidth()-10,getHeight(),4.0f); - - if (isEnabled) - g.setColour(Colours::black); - else - g.setColour(Colours::grey); - - g.setFont(Font("Small Text",15,Font::plain)); - - g.drawText(name, 8, 2, 200, 15, Justification::left, false); - -} - - -// (Direct OpalKelly) Audio Options -------------------------------------------------------------------- - -AudioInterface::AudioInterface(RHD2000Thread* board_, - RHD2000Editor* editor_) : - board(board_), editor(editor_) -{ - - name = "Noise Slicer"; - - lastNoiseSlicerString = "0"; - - actualNoiseSlicerLevel = 0.0f; - - noiseSlicerLevelSelection = new Label("Noise Slicer",lastNoiseSlicerString); // this is currently set in RHD2000Thread, the cleaner would be to set it here again - noiseSlicerLevelSelection->setEditable(true,false,false); - noiseSlicerLevelSelection->addListener(this); - noiseSlicerLevelSelection->setBounds(30,10,30,20); - noiseSlicerLevelSelection->setColour(Label::textColourId, Colours::darkgrey); - addAndMakeVisible(noiseSlicerLevelSelection); - - -} - -AudioInterface::~AudioInterface() -{ - -} - - -void AudioInterface::labelTextChanged(Label* label) -{ - if (board->foundInputSource()) - { - if (label == noiseSlicerLevelSelection) - { - - Value val = label->getTextValue(); - int requestedValue = int(val.getValue()); // Note that it might be nice to translate to actual uV levels (16*value) - - if (requestedValue < 0 || requestedValue > 127) - { - CoreServices::sendStatusMessage("Value out of range."); - - label->setText(lastNoiseSlicerString, dontSendNotification); - - return; - } - - actualNoiseSlicerLevel = board->setNoiseSlicerLevel(requestedValue); - - std::cout << "Setting Noise Slicer Level to " << requestedValue << "\n"; - label->setText(String((roundFloatToInt)(actualNoiseSlicerLevel)), dontSendNotification); - - } - } - else - { - Value val = label->getTextValue(); - int requestedValue = int(val.getValue()); // Note that it might be nice to translate to actual uV levels (16*value) - if (requestedValue < 0 || requestedValue > 127) - { - CoreServices::sendStatusMessage("Value out of range."); - label->setText(lastNoiseSlicerString, dontSendNotification); - return; - } - } -} - -void AudioInterface::setNoiseSlicerLevel(int value) -{ - actualNoiseSlicerLevel = board->setNoiseSlicerLevel(value); - noiseSlicerLevelSelection->setText(String(roundFloatToInt(actualNoiseSlicerLevel)), dontSendNotification); -} - -int AudioInterface::getNoiseSlicerLevel() -{ - return actualNoiseSlicerLevel; -} - - -void AudioInterface::paint(Graphics& g) -{ - - g.setColour(Colours::darkgrey); - g.setFont(Font("Small Text",9,Font::plain)); - g.drawText(name, 0, 0, 200, 15, Justification::left, false); - g.drawText("Level: ", 0, 10, 200, 20, Justification::left, false); -} - - -// Clock Divider options -ClockDivideInterface::ClockDivideInterface(RHD2000Thread* board_, - RHD2000Editor* editor_) : - name("Clock Divider") - , lastDivideRatioString("1") - , board(board_) - , editor(editor_) - , actualDivideRatio(1) - -{ - divideRatioSelection = new Label("Clock Divide", lastDivideRatioString); - divideRatioSelection->setEditable(true,false,false); - divideRatioSelection->addListener(this); - divideRatioSelection->setBounds(30,10,30,20); - divideRatioSelection->setColour(Label::textColourId, Colours::darkgrey); - addAndMakeVisible(divideRatioSelection); -} - -void ClockDivideInterface::labelTextChanged(Label* label) -{ - if (board->foundInputSource()) - { - if (label == divideRatioSelection) - { - Value val = label->getTextValue(); - int requestedValue = int(val.getValue()); - - if (requestedValue < 1 || requestedValue > 65534) - { - CoreServices::sendStatusMessage("Value must be between 1 and 65534."); - label->setText(lastDivideRatioString, dontSendNotification); - return; - } - - actualDivideRatio = board->setClockDivider(requestedValue); - lastDivideRatioString = String(actualDivideRatio); - - std::cout << "Setting clock divide ratio to " << actualDivideRatio << "\n"; - label->setText(lastDivideRatioString, dontSendNotification); - } - } -} - -void ClockDivideInterface::setClockDivideRatio(int value) -{ - actualDivideRatio = board->setClockDivider(value); - divideRatioSelection->setText(String(actualDivideRatio), dontSendNotification); -} - -void ClockDivideInterface::paint(Graphics& g) -{ - - g.setColour(Colours::darkgrey); - g.setFont(Font("Small Text",9,Font::plain)); - g.drawText(name, 0, 0, 200, 15, Justification::left, false); - g.drawText("Ratio: ", 0, 10, 200, 20, Justification::left, false); -} - -// DSP Options -------------------------------------------------------------------- - -DSPInterface::DSPInterface(RHD2000Thread* board_, - RHD2000Editor* editor_) : - board(board_), editor(editor_) -{ - name = "DSP"; - - dspOffsetSelection = new Label("DspOffsetSelection",String(round(board->getDspCutoffFreq()*10.f)/10.f)); - dspOffsetSelection->setEditable(true,false,false); - dspOffsetSelection->addListener(this); - dspOffsetSelection->setBounds(0,0,30,20); - dspOffsetSelection->setColour(Label::textColourId, Colours::darkgrey); - - addAndMakeVisible(dspOffsetSelection); - -} - -DSPInterface::~DSPInterface() -{ - -} - - -void DSPInterface::labelTextChanged(Label* label) -{ - - if (!(editor->acquisitionIsActive) && board->foundInputSource()) - { - if (label == dspOffsetSelection) - { - - Value val = label->getTextValue(); - double requestedValue = double(val.getValue()); - - actualDspCutoffFreq = board->setDspCutoffFreq(requestedValue); - - std::cout << "Setting DSP Cutoff Freq to " << requestedValue << "\n"; - std::cout << "Actual DSP Cutoff Freq: " << actualDspCutoffFreq << "\n"; - label->setText(String(round(actualDspCutoffFreq*10.f)/10.f), dontSendNotification); - - } - } - else if (editor->acquisitionIsActive) - { - CoreServices::sendStatusMessage("Can't change DSP cutoff while acquisition is active!"); - } - -} - -void DSPInterface::setDspCutoffFreq(double value) -{ - actualDspCutoffFreq = board->setDspCutoffFreq(value); - dspOffsetSelection->setText(String(round(actualDspCutoffFreq*10.f)/10.f), dontSendNotification); -} - - -double DSPInterface::getDspCutoffFreq() -{ - return actualDspCutoffFreq; -} - -void DSPInterface::paint(Graphics& g) -{ - - g.setColour(Colours::darkgrey); - - g.setFont(Font("Small Text",10,Font::plain)); - -} diff --git a/Source/Plugins/PCIeRhythm/RHD2000Editor.h b/Source/Plugins/PCIeRhythm/RHD2000Editor.h deleted file mode 100644 index 9f4ef4f5d1c715bcddf4027f9dc33dca8acaf722..0000000000000000000000000000000000000000 --- a/Source/Plugins/PCIeRhythm/RHD2000Editor.h +++ /dev/null @@ -1,399 +0,0 @@ -/* - ------------------------------------------------------------------ - - This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys - - ------------------------------------------------------------------ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program 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. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - -*/ - -#ifndef __RHD2000EDITOR_H_2AD3C591__ -#define __RHD2000EDITOR_H_2AD3C591__ - -#include <VisualizerEditorHeaders.h> - -class UtilityButton; -/** - -User interface for the RHD2000 source module. - -@see SourceNode - -*/ -class SourceNode; - -namespace PCIeRhythm { - class HeadstageOptionsInterface; - class SampleRateInterface; - class BandwidthInterface; - class DSPInterface; - class AudioInterface; - class ClockDivideInterface; - class RHD2000Thread; - struct ImpedanceData; - - - - class FPGAchannelComponent; - class RHD2000Editor; - class FPGAcanvas; - - class FPGAchannelList : public Component, - Button::Listener, ComboBox::Listener - { - public: - - FPGAchannelList(GenericProcessor* proc, Viewport* p, FPGAcanvas* c); - ~FPGAchannelList(); - void setNewName(int channelIndex, String newName); - void setNewGain(int channel, float gain); - void disableAll(); - void enableAll(); - void paint(Graphics& g); - void buttonClicked(Button* btn); - void update(); - void updateButtons(); - int getNumChannels(); - void comboBoxChanged(ComboBox* b); - void updateImpedance(Array<int> streams, Array<int> channels, Array<float> magnitude, Array<float> phase); - SourceNode* proc; - - private: - Array<float> gains; - Array<ChannelType> types; - - bool chainUpdate; - - Viewport* viewport; - FPGAcanvas* canvas; - ScopedPointer<UtilityButton> impedanceButton; - ScopedPointer<ToggleButton> saveImpedanceButton; - ScopedPointer<ToggleButton> autoMeasureButton; - ScopedPointer<ComboBox> numberingScheme; - ScopedPointer<Label> numberingSchemeLabel; - OwnedArray<Label> staticLabels; - OwnedArray<FPGAchannelComponent> channelComponents; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FPGAchannelList); - }; - - - class FPGAchannelComponent : public Component, Button::Listener, public ComboBox::Listener, public Label::Listener - { - public: - FPGAchannelComponent(FPGAchannelList* cl, int ch, int gainIndex_, String name_, Array<float> gains_, ChannelType type_); - ~FPGAchannelComponent(); - Colour getDefaultColor(int ID); - void setImpedanceValues(float mag, float phase); - void disableEdit(); - void enableEdit(); - - - void setEnabledState(bool); - bool getEnabledState() - { - return isEnabled; - } - void buttonClicked(Button* btn); - void setUserDefinedData(int d); - int getUserDefinedData(); - void comboBoxChanged(ComboBox* comboBox); - void labelTextChanged(Label* lbl); - - void resized(); - - const ChannelType type; - private: - Array<float> gains; - FPGAchannelList* channelList; - ScopedPointer<Label> staticLabel, editName, impedance; - ScopedPointer<ComboBox> gainComboBox; - int channel; - String name; - int gainIndex; - int userDefinedData; - Font font; - bool isEnabled; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FPGAchannelComponent); - }; - - - class FPGAcanvas : public Visualizer, public Button::Listener - { - public: - FPGAcanvas(GenericProcessor* n); - ~FPGAcanvas(); - - void paint(Graphics& g); - - void refresh(); - - void beginAnimation(); - void endAnimation(); - - void refreshState(); - void update(); - - void setParameter(int, float); - void setParameter(int, int, int, float); - - void updateImpedance(Array<int> streams, Array<int> channels, Array<float> magnitude, Array<float> phase); - - void resized(); - void buttonClicked(Button* button); - ScopedPointer<Viewport> channelsViewport; - SourceNode* processor; - ScopedPointer<FPGAchannelList> channelList; - }; - - class RHD2000Editor : public VisualizerEditor, public ComboBox::Listener, public AsyncUpdater - - { - public: - RHD2000Editor(GenericProcessor* parentNode, RHD2000Thread*, bool useDefaultParameterEditors); - ~RHD2000Editor(); - - void buttonEvent(Button* button); - - void scanPorts(); - void comboBoxChanged(ComboBox* comboBox); - - void startAcquisition(); - void stopAcquisition(); - - void channelChanged(int channel, bool newState) override; - - void saveCustomParameters(XmlElement* xml); - void loadCustomParameters(XmlElement* xml); - Visualizer* createNewCanvas(void); - void measureImpedance(); - - void setSaveImpedance(bool en); - void setAutoMeasureImpedance(bool en); - bool getSaveImpedance(); - bool getAutoMeasureImpedance(); - - void handleAsyncUpdate(); - - private: - - OwnedArray<HeadstageOptionsInterface> headstageOptionsInterfaces; - OwnedArray<ElectrodeButton> electrodeButtons; - - ScopedPointer<SampleRateInterface> sampleRateInterface; - ScopedPointer<BandwidthInterface> bandwidthInterface; - ScopedPointer<DSPInterface> dspInterface; - - ScopedPointer<AudioInterface> audioInterface; - ScopedPointer<ClockDivideInterface> clockInterface; - - ScopedPointer<UtilityButton> rescanButton, dacTTLButton; - ScopedPointer<UtilityButton> adcButton; - ScopedPointer<UtilityButton> ledButton; - - ScopedPointer<UtilityButton> dspoffsetButton; - ScopedPointer<ComboBox> ttlSettleCombo, dacHPFcombo; - - - ScopedPointer<Label> audioLabel, ttlSettleLabel, dacHPFlabel; - - bool saveImpedances, measureWhenRecording; - - RHD2000Thread* board; - FPGAcanvas* canvas; - - ScopedPointer<ImpedanceData> impedanceData; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RHD2000Editor); - - }; - - - class HeadstageOptionsInterface : public Component, - public Button::Listener - { - public: - HeadstageOptionsInterface(RHD2000Thread*, RHD2000Editor*, int hsNum); - ~HeadstageOptionsInterface(); - - void paint(Graphics& g); - - void buttonClicked(Button* button); - - void checkEnabledState(); - - private: - - int hsNumber1, hsNumber2; - int channelsOnHs1, channelsOnHs2; - String name; - - bool isEnabled; - - RHD2000Thread* board; - RHD2000Editor* editor; - - ScopedPointer<UtilityButton> hsButton1; - ScopedPointer<UtilityButton> hsButton2; - - }; - - - class BandwidthInterface : public Component, - public Label::Listener - { - public: - BandwidthInterface(RHD2000Thread*, RHD2000Editor*); - ~BandwidthInterface(); - - void paint(Graphics& g); - void labelTextChanged(Label* te); - - void setLowerBandwidth(double value); - void setUpperBandwidth(double value); - double getLowerBandwidth(); - double getUpperBandwidth(); - - private: - - String name; - - String lastLowCutString, lastHighCutString; - - RHD2000Thread* board; - RHD2000Editor* editor; - - ScopedPointer<Label> upperBandwidthSelection; - ScopedPointer<Label> lowerBandwidthSelection; - - double actualUpperBandwidth; - double actualLowerBandwidth; - - }; - - class DSPInterface : public Component, - public Label::Listener - { - public: - DSPInterface(RHD2000Thread*, RHD2000Editor*); - ~DSPInterface(); - - void paint(Graphics& g); - void labelTextChanged(Label* te); - - void setDspCutoffFreq(double value); - double getDspCutoffFreq(); - - private: - - String name; - - RHD2000Thread* board; - RHD2000Editor* editor; - - ScopedPointer<Label> dspOffsetSelection; - - double actualDspCutoffFreq; - - }; - - - - class SampleRateInterface : public Component, - public ComboBox::Listener - { - public: - SampleRateInterface(RHD2000Thread*, RHD2000Editor*); - ~SampleRateInterface(); - - int getSelectedId(); - void setSelectedId(int); - - void paint(Graphics& g); - void comboBoxChanged(ComboBox* cb); - - private: - - int sampleRate; - String name; - - RHD2000Thread* board; - RHD2000Editor* editor; - - ScopedPointer<ComboBox> rateSelection; - StringArray sampleRateOptions; - - }; - - class AudioInterface : public Component, - public Label::Listener - { - public: - AudioInterface(RHD2000Thread*, RHD2000Editor*); - ~AudioInterface(); - - void paint(Graphics& g); - void labelTextChanged(Label* te); - - void setNoiseSlicerLevel(int value); - int getNoiseSlicerLevel(); - //void setGain(double value); - //double getGain(); - - private: - - String name; - - String lastNoiseSlicerString; - String lastGainString; - - RHD2000Thread* board; - RHD2000Editor* editor; - - ScopedPointer<Label> noiseSlicerLevelSelection; - //ScopedPointer<Label> gainSelection; - - int actualNoiseSlicerLevel; - //double actualGain; - - }; - - class ClockDivideInterface : public Component, - public Label::Listener - { - public: - ClockDivideInterface(RHD2000Thread*, RHD2000Editor*); - - void paint(Graphics& g); - void labelTextChanged(Label* te); - - void setClockDivideRatio(int value); - int getClockDivideRatio() const { return actualDivideRatio; }; - - private: - - String name; - String lastDivideRatioString; - - RHD2000Thread * board; - RHD2000Editor * editor; - - ScopedPointer<Label> divideRatioSelection; - int actualDivideRatio; - - }; -}; -#endif // __RHD2000EDITOR_H_2AD3C591__ diff --git a/Source/Plugins/PCIeRhythm/RHD2000Thread.cpp b/Source/Plugins/PCIeRhythm/RHD2000Thread.cpp deleted file mode 100644 index 1e50f139b725124df19795eb2821803a48973bdd..0000000000000000000000000000000000000000 --- a/Source/Plugins/PCIeRhythm/RHD2000Thread.cpp +++ /dev/null @@ -1,2397 +0,0 @@ -/* - ------------------------------------------------------------------ - - This file is part of the Open Ephys GUI - Copyright (C) 2014 Open Ephys - - ------------------------------------------------------------------ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program 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. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "RHD2000Thread.h" -#include "RHD2000Editor.h" - - -#if defined(_WIN32) - #define okLIB_NAME "okFrontPanel.dll" - #define okLIB_EXTENSION "*.dll" -#elif defined(__APPLE__) - #define okLIB_NAME "libokFrontPanel.dylib" - #define okLIB_EXTENSION "*.dylib" -#elif defined(__linux__) - #define okLIB_NAME "./libokFrontPanel.so" - #define okLIB_EXTENSION "*.so" -#endif - -#define CHIP_ID_RHD2132 1 -#define CHIP_ID_RHD2216 2 -#define CHIP_ID_RHD2164 4 -#define CHIP_ID_RHD2164_B 1000 -#define REGISTER_59_MISO_A 53 -#define REGISTER_59_MISO_B 58 -#define RHD2132_16CH_OFFSET 8 - -#define THRESHOLD_CHECK 1.0f - -//#define DEBUG_EMULATE_HEADSTAGES 8 -//#define DEBUG_EMULATE_64CH -//#define DEBUG_REAL_HEADSTAGE 5 - -#define INIT_STEP 256 - -using namespace PCIeRhythm; - -// Allocates memory for a 3-D array of doubles. -void allocateDoubleArray3D(std::vector<std::vector<std::vector<double> > >& array3D, - int xSize, int ySize, int zSize) -{ - int i, j; - - if (xSize == 0) return; - array3D.resize(xSize); - for (i = 0; i < xSize; ++i) - { - array3D[i].resize(ySize); - for (j = 0; j < ySize; ++j) - { - array3D[i][j].resize(zSize); - } - } -} - -DataThread* RHD2000Thread::createDataThread(SourceNode *sn) -{ - return new RHD2000Thread(sn); -} - -RHD2000Thread::RHD2000Thread(SourceNode* sn) : DataThread(sn), - chipRegisters(30000.0f), - numChannels(0), - deviceFound(false), - isTransmitting(false), - dacOutputShouldChange(false), - acquireAdcChannels(false), - acquireAuxChannels(true), - fastSettleEnabled(false), - fastTTLSettleEnabled(false), - fastSettleTTLChannel(-1), - ttlMode(false), - dspEnabled(true), - desiredDspCutoffFreq(0.5f), - desiredUpperBandwidth(7500.0f), - desiredLowerBandwidth(1.0f), - boardSampleRate(30000.0f), - savedSampleRateIndex(16), - cableLengthPortA(0.914f), cableLengthPortB(0.914f), cableLengthPortC(0.914f), cableLengthPortD(0.914f), // default is 3 feet (0.914 m), - audioOutputL(-1), audioOutputR(-1) ,numberingScheme(1), - newScan(true), ledsEnabled(true) -{ - impedanceThread = new RHDImpedanceMeasure(this); - memset(auxBuffer, 0, sizeof(auxBuffer)); - memset(auxSamples, 0, sizeof(auxSamples)); - - for (int i=0; i < MAX_NUM_HEADSTAGES; i++) - headstagesArray.add(new RHDHeadstage(static_cast<rhd2000PCIe::BoardDataSource>(i))); - - evalBoard = new rhd2000PCIe; - dataBuffer = new DataBuffer(2, 10000); // start with 2 channels and automatically resize - - // Open Opal Kelly XEM6010 board. - // Returns 1 if successful, -1 if FrontPanel cannot be loaded, and -2 if XEM6010 can't be found. - -#if defined(__APPLE__) - File appBundle = File::getSpecialLocation(File::currentApplicationFile); - const String executableDirectory = appBundle.getChildFile("Contents/Resources").getFullPathName(); -#else - File executable = File::getSpecialLocation(File::currentExecutableFile); - const String executableDirectory = executable.getParentDirectory().getFullPathName(); -#endif - - std::cout << executableDirectory << std::endl; - - - String dirName = executableDirectory; - libraryFilePath = dirName; - libraryFilePath += File::separatorString; - libraryFilePath += okLIB_NAME; - - dacStream = nullptr; - dacChannels = nullptr; - dacThresholds = nullptr; - dacChannelsToUpdate = nullptr; - if (openBoard()) - { - dataBlock = new Rhd2000DataBlock(1); - // upload bitfile and restore default settings - initializeBoard(); - - // automatically find connected headstages - scanPorts(); // things would appear to run more smoothly if this were done after the editor has been created - - // probably better to do this with a thread, but a timer works for now: - // startTimer(10); // initialize the board in the background - dacStream = new int[8]; - dacChannels = new int[8]; - dacThresholds = new float[8]; - dacChannelsToUpdate = new bool[8]; - for (int k = 0; k < 8; k++) - { - dacChannelsToUpdate[k] = true; - dacStream[k] = 0; - setDACthreshold(k, 65534); - dacChannels[k] = 0; - dacThresholds[k] = 0; - } - - // evalBoard->getDacInformation(dacChannels,dacThresholds); - - // setDefaultNamingScheme(numberingScheme); - //setDefaultChannelNamesAndType(); - } -} - -GenericEditor* RHD2000Thread::createEditor (SourceNode* sn) -{ - return new RHD2000Editor(sn, this, true); -} - -void RHD2000Thread::timerCallback() -{ - stopTimer(); -} - -RHD2000Thread::~RHD2000Thread() -{ - std::cout << "RHD2000 interface destroyed." << std::endl; - -/* if (deviceFound) - { - int ledArray[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - evalBoard->setLedDisplay(ledArray); - } - - if (deviceFound) - evalBoard->resetFpga();*/ - - //deleteAndZero(dataBlock); - - delete[] dacStream; - delete[] dacChannels; - delete[] dacThresholds; - delete[] dacChannelsToUpdate; -} - -bool RHD2000Thread::usesCustomNames() const -{ - return true; -} - -void RHD2000Thread::setDACthreshold(int dacOutput, float threshold) -{ - dacThresholds[dacOutput]= threshold; - dacChannelsToUpdate[dacOutput] = true; - dacOutputShouldChange = true; - - // evalBoard->setDacThresholdVoltage(dacOutput,threshold); -} - -void RHD2000Thread::setDACchannel(int dacOutput, int channel) -{ - if (channel < getNumHeadstageOutputs()) - { - int channelCount = 0; - for (int i = 0; i < enabledStreams.size(); i++) - { - if (channel < channelCount + numChannelsPerDataStream[i]) - { - dacChannels[dacOutput] = channel - channelCount; - dacStream[dacOutput] = i; - break; - } - else - { - channelCount += numChannelsPerDataStream[i]; - } - } - dacChannelsToUpdate[dacOutput] = true; - dacOutputShouldChange = true; - } -} - -Array<int> RHD2000Thread::getDACchannels() const -{ - Array<int> dacChannelsArray; - //dacChannelsArray.addArray(dacChannels,8); - for (int k=0; k<8; k++) - { - dacChannelsArray.add(dacChannels[k]); - } - return dacChannelsArray; - -} -bool RHD2000Thread::openBoard() -{ - if (evalBoard->openBoard()) - { - deviceFound = true; - } - else // board could not be opened - { - bool response = AlertWindow::showOkCancelBox(AlertWindow::NoIcon, - "Acquisition board not found.", - "An acquisition board could not be found. Please connect one now.", - "OK", "Cancel", 0, 0); - - if (response) - { - openBoard(); // call recursively - } - else - { - deviceFound = false; - } - - } - - return deviceFound; - -} - - -void RHD2000Thread::initializeBoard() -{ - // Initialize the board - std::cout << "Initializing acquisition board." << std::endl; - evalBoard->openPipe(); - evalBoard->initialize(); - // This applies the following settings: - // - sample rate to 30 kHz - // - aux command banks to zero - // - aux command lengths to zero - // - continuous run mode to 'true' - // - maxTimeStep to 2^32 - 1 - // - all cable lengths to 3 feet - // - dspSettle to 'false' - // - data source mapping as 0->PortA1, 1->PortB1, 2->PortC1, 3->PortD1, etc. - // - enables all data streams - // - clears the ttlOut - // - disables all DACs and sets gain to 0 - - setSampleRate(rhd2000PCIe::SampleRate30000Hz); - evalBoard->setCableLengthMeters(rhd2000PCIe::PortA, cableLengthPortA); - evalBoard->setCableLengthMeters(rhd2000PCIe::PortB, cableLengthPortB); - evalBoard->setCableLengthMeters(rhd2000PCIe::PortC, cableLengthPortC); - evalBoard->setCableLengthMeters(rhd2000PCIe::PortD, cableLengthPortD); - - // Select RAM Bank 0 for AuxCmd3 initially, so the ADC is calibrated. - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortA, rhd2000PCIe::AuxCmd3, 0); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortB, rhd2000PCIe::AuxCmd3, 0); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortC, rhd2000PCIe::AuxCmd3, 0); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortD, rhd2000PCIe::AuxCmd3, 0); - - // Since our longest command sequence is 60 commands, run the SPI interface for - // 60 samples (64 for usb3 power-of two needs) - evalBoard->setMaxTimeStep(INIT_STEP); - evalBoard->setContinuousRunMode(false); - - // Start SPI interface - evalBoard->run(); - - // Wait for the 60-sample run to complete - while (evalBoard->isRunning()) - { - ; - } - - // Read the resulting single data block from the USB interface. We don't - // need to do anything with this, since it was only used for ADC calibration - ScopedPointer<Rhd2000DataBlock> dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams(), INIT_STEP); - - evalBoard->readDataBlock(dataBlock, INIT_STEP); - // Now that ADC calibration has been performed, we switch to the command sequence - // that does not execute ADC calibration. - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortA, rhd2000PCIe::AuxCmd3, - fastSettleEnabled ? 2 : 1); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortB, rhd2000PCIe::AuxCmd3, - fastSettleEnabled ? 2 : 1); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortC, rhd2000PCIe::AuxCmd3, - fastSettleEnabled ? 2 : 1); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortD, rhd2000PCIe::AuxCmd3, - fastSettleEnabled ? 2 : 1); - - evalBoard->closePipe(); - -} - -void RHD2000Thread::scanPorts() -{ - if (!deviceFound) //Safety to avoid crashes if board not present - { - return; - } - - impedanceThread->stopThreadSafely(); - //Clear previous known streams - enabledStreams.clear(); - evalBoard->openPipe(); - // Scan SPI ports - - int delay, hs, id; - int register59Value; - //int numChannelsOnPort[4] = {0, 0, 0, 0}; - rhd2000PCIe::BoardDataSource initStreamPorts[8] = - { - rhd2000PCIe::PortA1, - rhd2000PCIe::PortA2, - rhd2000PCIe::PortB1, - rhd2000PCIe::PortB2, - rhd2000PCIe::PortC1, - rhd2000PCIe::PortC2, - rhd2000PCIe::PortD1, - rhd2000PCIe::PortD2 - }; - - /* - Rhd2000EvalBoard::BoardDataSource initStreamDdrPorts[8] = - { - Rhd2000EvalBoard::PortA1Ddr, - Rhd2000EvalBoard::PortA2Ddr, - Rhd2000EvalBoard::PortB1Ddr, - Rhd2000EvalBoard::PortB2Ddr, - Rhd2000EvalBoard::PortC1Ddr, - Rhd2000EvalBoard::PortC2Ddr, - Rhd2000EvalBoard::PortD1Ddr, - Rhd2000EvalBoard::PortD2Ddr - }; - */ - - chipId.insertMultiple(0, -1, 8); - Array<int> tmpChipId(chipId); - - setSampleRate(rhd2000PCIe::SampleRate30000Hz, true); // set to 30 kHz temporarily - - // Enable all data streams, and set sources to cover one or two chips - // on Ports A-D. - evalBoard->setDataSource(0, initStreamPorts[0]); - evalBoard->setDataSource(1, initStreamPorts[1]); - evalBoard->setDataSource(2, initStreamPorts[2]); - evalBoard->setDataSource(3, initStreamPorts[3]); - evalBoard->setDataSource(4, initStreamPorts[4]); - evalBoard->setDataSource(5, initStreamPorts[5]); - evalBoard->setDataSource(6, initStreamPorts[6]); - evalBoard->setDataSource(7, initStreamPorts[7]); - - evalBoard->enableDataStream(0, true); - evalBoard->enableDataStream(1, true); - evalBoard->enableDataStream(2, true); - evalBoard->enableDataStream(3, true); - evalBoard->enableDataStream(4, true); - evalBoard->enableDataStream(5, true); - evalBoard->enableDataStream(6, true); - evalBoard->enableDataStream(7, true); - - std::cout << "Number of enabled data streams: " << evalBoard->getNumEnabledDataStreams() << std::endl; - - - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortA, - rhd2000PCIe::AuxCmd3, 0); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortB, - rhd2000PCIe::AuxCmd3, 0); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortC, - rhd2000PCIe::AuxCmd3, 0); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortD, - rhd2000PCIe::AuxCmd3, 0); - - // Since our longest command sequence is 60 commands, we run the SPI - // interface for 60 samples. (64 for usb3 power-of two needs) - evalBoard->setMaxTimeStep(INIT_STEP); - evalBoard->setContinuousRunMode(false); - - ScopedPointer<Rhd2000DataBlock> dataBlock = - new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams(), INIT_STEP); - - Array<int> sumGoodDelays; - sumGoodDelays.insertMultiple(0, 0, 8); - - Array<int> indexFirstGoodDelay; - indexFirstGoodDelay.insertMultiple(0, -1, 8); - - Array<int> indexSecondGoodDelay; - indexSecondGoodDelay.insertMultiple(0, -1, 8); - - - // Run SPI command sequence at all 16 possible FPGA MISO delay settings - // to find optimum delay for each SPI interface cable. - - std::cout << "Checking for connected amplifier chips..." << std::endl; - - for (delay = 0; delay < 16; delay++)//(delay = 0; delay < 16; ++delay) - { - evalBoard->setCableDelay(rhd2000PCIe::PortA, delay); - evalBoard->setCableDelay(rhd2000PCIe::PortB, delay); - evalBoard->setCableDelay(rhd2000PCIe::PortC, delay); - evalBoard->setCableDelay(rhd2000PCIe::PortD, delay); - - // Start SPI interface. - evalBoard->run(); - - // Wait for the 60-sample run to complete. - while (evalBoard->isRunning()) - { - ; - } - // Read the resulting single data block from the USB interface. - evalBoard->readDataBlock(dataBlock, INIT_STEP); - - // Read the Intan chip ID number from each RHD2000 chip found. - // Record delay settings that yield good communication with the chip. - for (hs = 0; hs < MAX_NUM_HEADSTAGES; ++hs)//MAX_NUM_DATA_STREAMS; ++stream) - { - // std::cout << "Stream number " << stream << ", delay = " << delay << std::endl; - - id = deviceId(dataBlock, hs, register59Value); - - if (id == CHIP_ID_RHD2132 || id == CHIP_ID_RHD2216 || - (id == CHIP_ID_RHD2164 && register59Value == REGISTER_59_MISO_A)) - { - // std::cout << "Device ID found: " << id << std::endl; - - sumGoodDelays.set(hs, sumGoodDelays[hs] + 1); - - if (indexFirstGoodDelay[hs] == -1) - { - indexFirstGoodDelay.set(hs, delay); - tmpChipId.set(hs, id); - } - else if (indexSecondGoodDelay[hs] == -1) - { - indexSecondGoodDelay.set(hs, delay); - tmpChipId.set(hs, id); - } - } - } - } - - // std::cout << "Chip IDs found: "; - // for (int i = 0; i < MAX_NUM_DATA_STREAMS; ++i) - // { - // std::cout << chipId[i] << " "; - // } - //std::cout << std::endl; - -#if DEBUG_EMULATE_HEADSTAGES > 0 - if (tmpChipId[DEBUG_REAL_HEADSTAGE] > 0) - { - int chipIdx = 0; - for (int hs = 0; hs < DEBUG_EMULATE_HEADSTAGES && hs < MAX_NUM_HEADSTAGES ; ++hs) - { - if (enabledStreams.size() < MAX_NUM_DATA_STREAMS) - { -#ifdef DEBUG_EMULATE_64CH - chipId.set(chipIdx++,CHIP_ID_RHD2164); - chipId.set(chipIdx++,CHIP_ID_RHD2164_B); - enableHeadstage(hs, true, 2, 32); -#else - chipId.set(chipIdx++,CHIP_ID_RHD2132); - enableHeadstage(hs, true, 1, 32); -#endif - } - } - for (int i = 0; i < enabledStreams.size(); i++) - { - enabledStreams.set(i,(rhd2000PCIe::BoardDataSource)DEBUG_REAL_HEADSTAGE); - } - } - -#else - // Now, disable data streams where we did not find chips present. - int chipIdx = 0; - for (hs = 0; hs < MAX_NUM_HEADSTAGES; ++hs) - { - if ((tmpChipId[hs] > 0) && (enabledStreams.size() < MAX_NUM_DATA_STREAMS)) - { - chipId.set(chipIdx++,tmpChipId[hs]); - //std::cout << "Enabling headstage on stream " << stream << std::endl; - if (tmpChipId[hs] == CHIP_ID_RHD2164) //RHD2164 - { - if (enabledStreams.size() < MAX_NUM_DATA_STREAMS - 1) - { - enableHeadstage(hs,true,2,32); - chipId.set(chipIdx++,CHIP_ID_RHD2164_B); - } - else //just one stream left - { - enableHeadstage(hs,true,1,32); - } - } - else - { - enableHeadstage(hs, true,1,tmpChipId[hs] == 1 ? 32:16); - } - } - else - { - enableHeadstage(hs, false); - } - } -#endif - updateBoardStreams(); - - - std::cout << "Number of enabled data streams: " << evalBoard->getNumEnabledDataStreams() << std::endl; - - - // Set cable delay settings that yield good communication with each - // RHD2000 chip. - Array<int> optimumDelay; - optimumDelay.insertMultiple(0,0,8); - - for (hs = 0; hs < MAX_NUM_HEADSTAGES; ++hs) - { - if (sumGoodDelays[hs] == 1 || sumGoodDelays[hs] == 2) - { - optimumDelay.set(hs,indexFirstGoodDelay[hs]); - } - else if (sumGoodDelays[hs] > 2) - { - optimumDelay.set(hs,indexSecondGoodDelay[hs]); - } - } - - evalBoard->setCableDelay(rhd2000PCIe::PortA, - max(optimumDelay[0],optimumDelay[1])); - evalBoard->setCableDelay(rhd2000PCIe::PortB, - max(optimumDelay[2],optimumDelay[3])); - evalBoard->setCableDelay(rhd2000PCIe::PortC, - max(optimumDelay[4],optimumDelay[5])); - evalBoard->setCableDelay(rhd2000PCIe::PortD, - max(optimumDelay[6],optimumDelay[7])); - - cableLengthPortA = - evalBoard->estimateCableLengthMeters(max(optimumDelay[0],optimumDelay[1])); - cableLengthPortB = - evalBoard->estimateCableLengthMeters(max(optimumDelay[2],optimumDelay[3])); - cableLengthPortC = - evalBoard->estimateCableLengthMeters(max(optimumDelay[4],optimumDelay[5])); - cableLengthPortD = - evalBoard->estimateCableLengthMeters(max(optimumDelay[6],optimumDelay[7])); - - setSampleRate(savedSampleRateIndex); // restore saved sample rate - evalBoard->closePipe(); - //updateRegisters(); - newScan = true; -} - -int RHD2000Thread::deviceId(Rhd2000DataBlock* dataBlock, int stream, int& register59Value) -{ - bool intanChipPresent; - - // First, check ROM registers 32-36 to verify that they hold 'INTAN', and - // the initial chip name ROM registers 24-26 that hold 'RHD'. - // This is just used to verify that we are getting good data over the SPI - // communication channel. - intanChipPresent = ((char) dataBlock->auxiliaryData[stream][2][32] == 'I' && - (char) dataBlock->auxiliaryData[stream][2][33] == 'N' && - (char) dataBlock->auxiliaryData[stream][2][34] == 'T' && - (char) dataBlock->auxiliaryData[stream][2][35] == 'A' && - (char) dataBlock->auxiliaryData[stream][2][36] == 'N' && - (char) dataBlock->auxiliaryData[stream][2][24] == 'R' && - (char) dataBlock->auxiliaryData[stream][2][25] == 'H' && - (char) dataBlock->auxiliaryData[stream][2][26] == 'D'); - - // If the SPI communication is bad, return -1. Otherwise, return the Intan - // chip ID number stored in ROM regstier 63. - if (!intanChipPresent) - { - register59Value = -1; - return -1; - } - else - { - register59Value = dataBlock->auxiliaryData[stream][2][23]; // Register 59 - return dataBlock->auxiliaryData[stream][2][19]; // chip ID (Register 63) - } -} - - -bool RHD2000Thread::isAcquisitionActive() const -{ - return isTransmitting; -} - -void RHD2000Thread::setNumChannels (int hsNum, int numChannels) -{ - if (headstagesArray[hsNum]->getNumChannels() == 32) - { - if (numChannels < headstagesArray[hsNum]->getNumChannels()) - headstagesArray[hsNum]->setHalfChannels(true); - else - headstagesArray[hsNum]->setHalfChannels(false); - numChannelsPerDataStream.set(headstagesArray[hsNum]->getStreamIndex(0), numChannels); - } -} - -int RHD2000Thread::getHeadstageChannels (int hsNum) const -{ - return headstagesArray[hsNum]->getNumChannels(); -} - - -void RHD2000Thread::getEventChannelNames (StringArray& Names) const -{ - Names.clear(); - for (int k = 0; k < 8; k++) - { - Names.add("TTL"+String(k+1)); - } -} - - -/* go over the old names and tests whether this particular channel name was changed. -if so, return the old name */ - - -int RHD2000Thread::modifyChannelName(int channel, String newName) -{ - ChannelCustomInfo i = channelInfo[channel]; - i.name = newName; - i.modified = true; - channelInfo.set(channel, i); - return 0; -} - -String RHD2000Thread::getChannelName (int ch) const -{ - return channelInfo[ch].name; -} - -int RHD2000Thread::modifyChannelGain (int channel, float gain) -{ - ChannelCustomInfo i = channelInfo[channel]; - i.gain = gain; - i.modified = true; - channelInfo.set(channel, i); - return 0; -} - -void RHD2000Thread::setDefaultNamingScheme (int scheme) -{ - numberingScheme = scheme; - newScan = true; //if the scheme is changed, reset all names - setDefaultChannelNames(); -} - -/* This will give default names & gains to channels, unless they were manually modified by the user - In that case, the query channelModified, will return the values that need to be put */ -void RHD2000Thread::setDefaultChannelNames() -{ - int aux_counter = 1; - int channelNumber = 1; - String oldName; - //int dummy; - //float oldGain; - StringArray stream_prefix; - stream_prefix.add("A1"); - stream_prefix.add("A2"); - stream_prefix.add("B1"); - stream_prefix.add("B2"); - stream_prefix.add("C1"); - stream_prefix.add("C2"); - stream_prefix.add("D1"); - stream_prefix.add("D2"); - - for (int i = 0; i < MAX_NUM_HEADSTAGES; i++) - { - if (headstagesArray[i]->isPlugged()) - { - for (int k = 0; k < headstagesArray[i]->getNumActiveChannels(); k++) - { - if (newScan || !channelInfo[k].modified) - { - ChannelCustomInfo in; - if (numberingScheme == 1) - in.name = "CH" + String(channelNumber); - else - in.name = "CH_" + stream_prefix[i] + "_" + String(1 + k); - in.gain = getBitVolts(sn->channels[k]); - channelInfo.set(channelNumber-1, in); - - } - channelNumber++; - } - } - } - //Aux channels - for (int i = 0; i < MAX_NUM_HEADSTAGES; i++) - { - if (headstagesArray[i]->isPlugged()) - { - for (int k = 0; k < 3; k++) - { - int chn = channelNumber - 1; - - if (newScan || !channelInfo[chn].modified) - { - ChannelCustomInfo in; - if (numberingScheme == 1) - in.name = "AUX" + String(aux_counter); - else - in.name = "AUX_" + stream_prefix[i] + "_" + String(1 + k); - in.gain = getBitVolts(sn->channels[chn]); - channelInfo.set(chn, in); - - } - channelNumber++; - aux_counter++; - } - } - } - //ADC channels - if (acquireAdcChannels) - { - for (int k = 0; k < 8; k++) - { - int chn = channelNumber - 1; - if (newScan || !channelInfo[chn].modified) - { - ChannelCustomInfo in; - in.name = "ADC" + String(k + 1); - in.gain = getAdcBitVolts(k); - channelInfo.set(chn, in); - } - channelNumber++; - } - } - newScan = false; -} - -int RHD2000Thread::getNumChannels() const -{ - return getNumHeadstageOutputs() + getNumAdcOutputs() + getNumAuxOutputs(); -} - -int RHD2000Thread::getNumHeadstageOutputs() const -{ - int newNumChannels = 0; - for (int i = 0; i < MAX_NUM_HEADSTAGES; i++) - { - if (headstagesArray[i]->isPlugged()) - { - newNumChannels += headstagesArray[i]->getNumActiveChannels(); - } - } - - return newNumChannels; -} - -int RHD2000Thread::getNumAuxOutputs() const -{ - int numAuxOutputs = 0; - - for (int i = 0; i < MAX_NUM_HEADSTAGES; i++) - { - if (headstagesArray[i]->isPlugged() > 0) - { - numAuxOutputs += 3; - } - } - - return numAuxOutputs; - -} - -int RHD2000Thread::getNumAdcOutputs() const -{ - if (acquireAdcChannels) - { - return 8; - } - else - { - return 0; - } -} - -int RHD2000Thread::getNumEventChannels() const -{ - return 16; // 8 inputs, 8 outputs -} - -float RHD2000Thread::getSampleRate() const -{ - return evalBoard->getSampleRate(); -} - -float RHD2000Thread::getBitVolts (Channel* ch) const -{ - if (ch->type == ADC_CHANNEL) - return getAdcBitVolts(ch->index); - else if (ch->type == AUX_CHANNEL) - return 0.0000374; - else - return 0.195f; -} - -float RHD2000Thread::getAdcBitVolts (int chan) const -{ - if (chan < adcBitVolts.size()) - return adcBitVolts[chan]; - else - return 0.00015258789; -} - -double RHD2000Thread::setUpperBandwidth(double upper) -{ - impedanceThread->stopThreadSafely(); - desiredUpperBandwidth = upper; - - updateRegisters(); - - return actualUpperBandwidth; -} - - -double RHD2000Thread::setLowerBandwidth(double lower) -{ - impedanceThread->stopThreadSafely(); - desiredLowerBandwidth = lower; - - updateRegisters(); - - return actualLowerBandwidth; -} - -double RHD2000Thread::setDspCutoffFreq(double freq) -{ - impedanceThread->stopThreadSafely(); - desiredDspCutoffFreq = freq; - - updateRegisters(); - - return actualDspCutoffFreq; -} - -double RHD2000Thread::getDspCutoffFreq() const -{ - return actualDspCutoffFreq; -} - -void RHD2000Thread::setDSPOffset(bool state) -{ - impedanceThread->stopThreadSafely(); - dspEnabled = state; - updateRegisters(); -} - -void RHD2000Thread::setTTLoutputMode(bool state) -{ - ttlMode = state; - dacOutputShouldChange = true; - -} - -void RHD2000Thread::setDAChpf(float cutoff, bool enabled) -{ - dacOutputShouldChange = true; - desiredDAChpf = cutoff; - desiredDAChpfState = enabled; -} - -void RHD2000Thread::setFastTTLSettle(bool state, int channel) -{ - fastTTLSettleEnabled = state; - fastSettleTTLChannel = channel; - dacOutputShouldChange = true; -} - -int RHD2000Thread::setNoiseSlicerLevel(int level) -{ - desiredNoiseSlicerLevel = level; - /* if (deviceFound) - evalBoard->setAudioNoiseSuppress(desiredNoiseSlicerLevel);*/ - - // Level has been checked once before this and then is checked again in setAudioNoiseSuppress. - // This may be overkill - maybe API should change so that the final function returns the value? - actualNoiseSlicerLevel = level; - - return actualNoiseSlicerLevel; -} - - -bool RHD2000Thread::foundInputSource() -{ - return deviceFound; -} - -bool RHD2000Thread::enableHeadstage(int hsNum, bool enabled, int nStr, int strChans) -{ - /* evalBoard->enableDataStream(hsNum, enabled);*/ - - if (enabled) - { - headstagesArray[hsNum]->setNumStreams(nStr); - headstagesArray[hsNum]->setChannelsPerStream(strChans,enabledStreams.size()); - enabledStreams.add(headstagesArray[hsNum]->getDataStream(0)); - numChannelsPerDataStream.add(strChans); - if (nStr > 1) - { - enabledStreams.add(headstagesArray[hsNum]->getDataStream(1)); - numChannelsPerDataStream.add(strChans); - } - } - else - { - int idx = enabledStreams.indexOf(headstagesArray[hsNum]->getDataStream(0)); - if (idx >= 0) - { - enabledStreams.remove(idx); - numChannelsPerDataStream.remove(idx); - } - if (headstagesArray[hsNum]->getNumStreams() > 1) - { - idx = enabledStreams.indexOf(headstagesArray[hsNum]->getDataStream(1)); - if (idx >= 0) - { - enabledStreams.remove(idx); - numChannelsPerDataStream.remove(idx); - } - } - headstagesArray[hsNum]->setNumStreams(0); - } - - /* - std::cout << "Enabled channels: "; - - for (int i = 0; i < MAX_NUM_DATA_STREAMS; i++) - { - std::cout << numChannelsPerDataStream[i] << " "; - }*/ - - dataBuffer->resize(getNumChannels(), 10000); - - return true; -} - -void RHD2000Thread::updateBoardStreams() -{ - for (int i=0; i < MAX_NUM_DATA_STREAMS; i++) - { - if (i < enabledStreams.size()) - { - evalBoard->enableDataStream(i,true); - evalBoard->setDataSource(i,enabledStreams[i]); - } - else - { - evalBoard->enableDataStream(i,false); - } - } -} - -bool RHD2000Thread::isHeadstageEnabled (int hsNum) const -{ - return headstagesArray[hsNum]->isPlugged(); -} - -bool RHD2000Thread::isReady() -{ - return deviceFound && (getNumChannels() > 0); -} - -int RHD2000Thread::getActiveChannelsInHeadstage (int hsNum) const -{ - return headstagesArray[hsNum]->getNumActiveChannels(); -} - -int RHD2000Thread::getChannelsInHeadstage (int hsNum) const -{ - return headstagesArray[hsNum]->getNumChannels(); -} - -/*void RHD2000Thread::assignAudioOut(int dacChannel, int dataChannel) -{ - if (deviceFound) - { - if (dacChannel == 0) - { - audioOutputR = dataChannel; - dacChannels[0] = dataChannel; - } - else if (dacChannel == 1) - { - audioOutputL = dataChannel; - dacChannels[1] = dataChannel; - } - - dacOutputShouldChange = true; // set a flag and take care of setting wires - // during the updateBuffer() method - // to avoid problems - } - -}*/ - -void RHD2000Thread::enableAdcs(bool t) -{ - acquireAdcChannels = t; - - dataBuffer->resize(getNumChannels(), 10000); -} - - -void RHD2000Thread::setSampleRate(int sampleRateIndex, bool isTemporary) -{ - impedanceThread->stopThreadSafely(); - if (!isTemporary) - { - savedSampleRateIndex = sampleRateIndex; - } - - int numUsbBlocksToRead = 0; // placeholder - make this change the number of blocks that are read in RHD2000Thread::updateBuffer() - - rhd2000PCIe::AmplifierSampleRate sampleRate; // just for local use - - switch (sampleRateIndex) - { - case 0: - sampleRate = rhd2000PCIe::SampleRate1000Hz; - numUsbBlocksToRead = 1; - boardSampleRate = 1000.0f; - break; - case 1: - sampleRate = rhd2000PCIe::SampleRate1250Hz; - numUsbBlocksToRead = 1; - boardSampleRate = 1250.0f; - break; - case 2: - sampleRate = rhd2000PCIe::SampleRate1500Hz; - numUsbBlocksToRead = 1; - boardSampleRate = 1500.0f; - break; - case 3: - sampleRate = rhd2000PCIe::SampleRate2000Hz; - numUsbBlocksToRead = 1; - boardSampleRate = 2000.0f; - break; - case 4: - sampleRate = rhd2000PCIe::SampleRate2500Hz; - numUsbBlocksToRead = 1; - boardSampleRate = 2500.0f; - break; - case 5: - sampleRate = rhd2000PCIe::SampleRate3000Hz; - numUsbBlocksToRead = 2; - boardSampleRate = 3000.0f; - break; - case 6: - sampleRate = rhd2000PCIe::SampleRate3333Hz; - numUsbBlocksToRead = 2; - boardSampleRate = 3333.0f; - break; - case 7: - sampleRate = rhd2000PCIe::SampleRate4000Hz; - numUsbBlocksToRead = 2; - boardSampleRate = 4000.0f; - break; - case 8: - sampleRate = rhd2000PCIe::SampleRate5000Hz; - numUsbBlocksToRead = 3; - boardSampleRate = 5000.0f; - break; - case 9: - sampleRate = rhd2000PCIe::SampleRate6250Hz; - numUsbBlocksToRead = 3; - boardSampleRate = 6250.0f; - break; - case 10: - sampleRate = rhd2000PCIe::SampleRate8000Hz; - numUsbBlocksToRead = 4; - boardSampleRate = 8000.0f; - break; - case 11: - sampleRate = rhd2000PCIe::SampleRate10000Hz; - numUsbBlocksToRead = 6; - boardSampleRate = 10000.0f; - break; - case 12: - sampleRate = rhd2000PCIe::SampleRate12500Hz; - numUsbBlocksToRead = 7; - boardSampleRate = 12500.0f; - break; - case 13: - sampleRate = rhd2000PCIe::SampleRate15000Hz; - numUsbBlocksToRead = 8; - boardSampleRate = 15000.0f; - break; - case 14: - sampleRate = rhd2000PCIe::SampleRate20000Hz; - numUsbBlocksToRead = 12; - boardSampleRate = 20000.0f; - break; - case 15: - sampleRate = rhd2000PCIe::SampleRate25000Hz; - numUsbBlocksToRead = 14; - boardSampleRate = 25000.0f; - break; - case 16: - sampleRate = rhd2000PCIe::SampleRate30000Hz; - numUsbBlocksToRead = 16; - boardSampleRate = 30000.0f; - break; - default: - sampleRate = rhd2000PCIe::SampleRate10000Hz; - numUsbBlocksToRead = 6; - boardSampleRate = 10000.0f; - } - - - // Select per-channel amplifier sampling rate. - evalBoard->setSampleRate(sampleRate); - - std::cout << "Sample rate set to " << evalBoard->getSampleRate() << std::endl; - - // Now that we have set our sampling rate, we can set the MISO sampling delay - // which is dependent on the sample rate. - evalBoard->setCableLengthMeters(rhd2000PCIe::PortA, cableLengthPortA); - evalBoard->setCableLengthMeters(rhd2000PCIe::PortB, cableLengthPortB); - evalBoard->setCableLengthMeters(rhd2000PCIe::PortC, cableLengthPortC); - evalBoard->setCableLengthMeters(rhd2000PCIe::PortD, cableLengthPortD); - - updateRegisters(); - -} - -void RHD2000Thread::updateRegisters() -{ - if (!deviceFound) //Safety to avoid crashes loading a chain with Rythm node withouth a board - { - return; - } - // Set up an RHD2000 register object using this sample rate to - // optimize MUX-related register settings. - chipRegisters.defineSampleRate(boardSampleRate); - - - int commandSequenceLength; - vector<int> commandList; - - // Create a command list for the AuxCmd1 slot. This command sequence will continuously - // update Register 3, which controls the auxiliary digital output pin on each RHD2000 chip. - // In concert with the v1.4 Rhythm FPGA code, this permits real-time control of the digital - // output pin on chips on each SPI port. - chipRegisters.setDigOutLow(); // Take auxiliary output out of HiZ mode. - commandSequenceLength = chipRegisters.createCommandListUpdateDigOut(commandList); - evalBoard->uploadCommandList(commandList, rhd2000PCIe::AuxCmd1, 0); - evalBoard->selectAuxCommandLength(rhd2000PCIe::AuxCmd1, 0, commandSequenceLength - 1); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortA, rhd2000PCIe::AuxCmd1, 0); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortB, rhd2000PCIe::AuxCmd1, 0); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortC, rhd2000PCIe::AuxCmd1, 0); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortD, rhd2000PCIe::AuxCmd1, 0); - - // // Next, we'll create a command list for the AuxCmd2 slot. This command sequence - // // will sample the temperature sensor and other auxiliary ADC inputs. - commandSequenceLength = chipRegisters.createCommandListTempSensor(commandList); - evalBoard->uploadCommandList(commandList, rhd2000PCIe::AuxCmd2, 0); - evalBoard->selectAuxCommandLength(rhd2000PCIe::AuxCmd2, 0, commandSequenceLength - 1); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortA, rhd2000PCIe::AuxCmd2, 0); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortB, rhd2000PCIe::AuxCmd2, 0); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortC, rhd2000PCIe::AuxCmd2, 0); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortD, rhd2000PCIe::AuxCmd2, 0); - - // Before generating register configuration command sequences, set amplifier - // bandwidth paramters. - actualDspCutoffFreq = chipRegisters.setDspCutoffFreq(desiredDspCutoffFreq); - //std::cout << "DSP Cutoff Frequency " << actualDspCutoffFreq << std::endl; - actualLowerBandwidth = chipRegisters.setLowerBandwidth(desiredLowerBandwidth); - actualUpperBandwidth = chipRegisters.setUpperBandwidth(desiredUpperBandwidth); - chipRegisters.enableDsp(dspEnabled); - //std::cout << "DSP Offset Status " << dspEnabled << std::endl; - - // turn on aux inputs - chipRegisters.enableAux1(true); - chipRegisters.enableAux2(true); - chipRegisters.enableAux3(true); - - chipRegisters.createCommandListRegisterConfig(commandList, true); - // Upload version with ADC calibration to AuxCmd3 RAM Bank 0. - evalBoard->uploadCommandList(commandList, rhd2000PCIe::AuxCmd3, 0); - evalBoard->selectAuxCommandLength(rhd2000PCIe::AuxCmd3, 0, - commandSequenceLength - 1); - - commandSequenceLength = chipRegisters.createCommandListRegisterConfig(commandList, false); - // Upload version with no ADC calibration to AuxCmd3 RAM Bank 1. - evalBoard->uploadCommandList(commandList, rhd2000PCIe::AuxCmd3, 1); - evalBoard->selectAuxCommandLength(rhd2000PCIe::AuxCmd3, 0, - commandSequenceLength - 1); - - - chipRegisters.setFastSettle(true); - - commandSequenceLength = chipRegisters.createCommandListRegisterConfig(commandList, false); - // Upload version with fast settle enabled to AuxCmd3 RAM Bank 2. - evalBoard->uploadCommandList(commandList, rhd2000PCIe::AuxCmd3, 2); - evalBoard->selectAuxCommandLength(rhd2000PCIe::AuxCmd3, 0, - commandSequenceLength - 1); - - chipRegisters.setFastSettle(false); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortA, rhd2000PCIe::AuxCmd3, - fastSettleEnabled ? 2 : 1); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortB, rhd2000PCIe::AuxCmd3, - fastSettleEnabled ? 2 : 1); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortC, rhd2000PCIe::AuxCmd3, - fastSettleEnabled ? 2 : 1); - evalBoard->selectAuxCommandBank(rhd2000PCIe::PortD, rhd2000PCIe::AuxCmd3, - fastSettleEnabled ? 2 : 1); -} - -void RHD2000Thread::setCableLength(int hsNum, float length) -{ - // Set the MISO sampling delay, which is dependent on the sample rate. - - switch (hsNum) - { - case 0: - evalBoard->setCableLengthFeet(rhd2000PCIe::PortA, length); - break; - case 1: - evalBoard->setCableLengthFeet(rhd2000PCIe::PortB, length); - break; - case 2: - evalBoard->setCableLengthFeet(rhd2000PCIe::PortC, length); - break; - case 3: - evalBoard->setCableLengthFeet(rhd2000PCIe::PortD, length); - break; - default: - break; - } - -} - -bool RHD2000Thread::startAcquisition() -{ - impedanceThread->waitSafely(); - dataBlock = new Rhd2000DataBlock(evalBoard->getNumEnabledDataStreams()); - - std::cout << "Expecting " << getNumChannels() << " channels." << std::endl; - lastThreshold = false; - auxSamp = 0; - //memset(filter_states,0,256*sizeof(double)); - - /*int ledArray[8] = {1, 1, 0, 0, 0, 0, 0, 0}; - evalBoard->setLedDisplay(ledArray); - - cout << "Number of 16-bit words in FIFO: " << evalBoard->numWordsInFifo() << endl; - cout << "Is eval board running: " << evalBoard->isRunning() << endl;*/ - - - //std::cout << "Setting max timestep." << std::endl; - //evalBoard->setMaxTimeStep(100); - - - std::cout << "Starting acquisition." << std::endl; - if (1) - { - // evalBoard->setContinuousRunMode(false); - // evalBoard->setMaxTimeStep(0); - std::cout << "Flushing FIFO." << std::endl; - evalBoard->openPipe(); - evalBoard->setContinuousRunMode(true); - //evalBoard->printFIFOmetrics(); - evalBoard->run(); - //evalBoard->printFIFOmetrics(); - } - - blockSize = dataBlock->calculateDataBlockSizeInWords(evalBoard->getNumEnabledDataStreams()); - std::cout << "Expecting blocksize of " << blockSize << " for " << evalBoard->getNumEnabledDataStreams() << " streams" << std::endl; - //evalBoard->printFIFOmetrics(); - startThread(); - - - isTransmitting = true; - - return true; -} - -bool RHD2000Thread::stopAcquisition() -{ - // isTransmitting = false; - std::cout << "RHD2000 data thread stopping acquisition." << std::endl; - - if (isThreadRunning()) - { - signalThreadShouldExit(); - - } - - if (getThreadId() != getCurrentThreadId()) - { - if (waitForThreadToExit(500)) - { - std::cout << "Thread exited." << std::endl; - } - else - { - std::cout << "Thread failed to exit, continuing anyway..." << std::endl; - } - } - - if (deviceFound) - { - evalBoard->setContinuousRunMode(false); - evalBoard->setMaxTimeStep(0); - std::cout << "Flushing FIFO." << std::endl; - evalBoard->closePipe(); - // evalBoard->setContinuousRunMode(true); - // evalBoard->run(); - - } - - dataBuffer->clear(); - - /*if (deviceFound) - { - cout << "Number of 16-bit words in FIFO: " << evalBoard->numWordsInFifo() << endl; - - // std::cout << "Stopped eval board." << std::endl; - - - int ledArray[8] = {1, 0, 0, 0, 0, 0, 0, 0}; - evalBoard->setLedDisplay(ledArray); - }*/ - - isTransmitting = false; - dacOutputShouldChange = false; - - return true; -} - -bool RHD2000Thread::updateBuffer() -{ - //int chOffset; - unsigned char* bufferPtr; - //cout << "Number of 16-bit words in FIFO: " << evalBoard->numWordsInFifo() << endl; - //cout << "Block size: " << blockSize << endl; - - //std::cout << "Current number of words: " << evalBoard->numWordsInFifo() << " for " << blockSize << std::endl; - if (true)//evalBoard->isUSB3() || evalBoard->numWordsInFifo() >= blockSize) - { - bool return_code; - - return_code = evalBoard->readRawDataBlock(&bufferPtr); - if (!return_code) - { - MessageManagerLock lockM; - CoreServices::setAcquisitionStatus(false); - return true; - } - - int index = 0; - int auxIndex, chanIndex; - int numStreams = enabledStreams.size(); - int nSamps = Rhd2000DataBlock::getSamplesPerDataBlock(); - - //evalBoard->printFIFOmetrics(); - for (int samp = 0; samp < nSamps; samp++) - { - int channel = -1; - - if (!Rhd2000DataBlock::checkUsbHeader(bufferPtr, index)) - { - cerr << "Error in Rhd2000EvalBoard::readDataBlock: Incorrect header." << endl; - break; - } - - index += 8; - timestamp = Rhd2000DataBlock::convertUsbTimeStamp(bufferPtr,index); - index += 4; - auxIndex = index; - //skip the aux channels - index += numStreams * 6; - // do the neural data channels first - for (int dataStream = 0; dataStream < numStreams; dataStream++) - { - int nChans = numChannelsPerDataStream[dataStream]; - chanIndex = index + 2*dataStream; - if ((chipId[dataStream] == CHIP_ID_RHD2132) && (nChans == 16)) //RHD2132 16ch. headstage - { - chanIndex += 2 * RHD2132_16CH_OFFSET*numStreams; - } - for (int chan = 0; chan < nChans; chan++) - { - channel++; - thisSample[channel] = float(*(uint16*)(bufferPtr + chanIndex) - 32768)*0.195f; - chanIndex += 2*numStreams; - if (dataStream == 0 && chan == 0) //First channel of the first enabled stream - checkThreshold(thisSample[channel]); - } - } - index += 64 * numStreams; - //now we can do the aux channels - auxIndex += 2*numStreams; - for (int dataStream = 0; dataStream < numStreams; dataStream++) - { - if (chipId[dataStream] != CHIP_ID_RHD2164_B) - { - int auxNum = (auxSamp+3) % 4; - auxSamp = (++auxSamp) % 4; - if (auxNum < 3) - { - auxSamples[dataStream][auxNum] = float(*(uint16*)(bufferPtr + auxIndex) - 32768)*0.0000374; - } - for (int chan = 0; chan < 3; chan++) - { - channel++; - if (auxNum == 3) - { - auxBuffer[channel] = auxSamples[dataStream][chan]; - } - thisSample[channel] = auxBuffer[channel]; - } - } - auxIndex += 2; - - } - index += 2 * numStreams; - if (acquireAdcChannels) - { - for (int adcChan = 0; adcChan < 8; ++adcChan) - { - - channel++; - // ADC waveform units = volts - thisSample[channel] = - //0.000050354 * float(dataBlock->boardAdcData[adcChan][samp]); - 0.00015258789 * float(*(uint16*)(bufferPtr + index)) - 5 - 0.4096; // account for +/-5V input range and DC offset - index += 2; - } - } - else - { - index += 16; - } - eventCode = *(uint16*)(bufferPtr + index); - index += 4; - dataBuffer->addToBuffer(thisSample, ×tamp, &eventCode, 1); -#if 0 - // do the neural data channels first - for (int dataStream = 0; dataStream < enabledStreams.size(); dataStream++) - { - if ((chipId[dataStream] == CHIP_ID_RHD2132) && (numChannelsPerDataStream[dataStream] == 16)) //RHD2132 16ch. headstage - chOffset = RHD2132_16CH_OFFSET; - else - chOffset = 0; - for (int chan = 0; chan < numChannelsPerDataStream[dataStream]; chan++) - { - - // std::cout << "reading sample stream " << streamNumber << " chan " << chan << " sample "<< samp << std::endl; - - channel++; - - int value = dataBlock->amplifierData[dataStream][chan+chOffset][samp]; - - thisSample[channel] = float(value-32768)*0.195f; - } - - - } - - - // then do the Intan AUX channels - for (int dataStream = 0; dataStream < enabledStreams.size(); dataStream++) - { - if (chipId[dataStream] != CHIP_ID_RHD2164_B) //Channel B of 2164 shouldn't be copied - { - if (samp % 4 == 1) // every 4th sample should have auxiliary input data - { - - // std::cout << "reading sample stream " << streamNumber << " aux ADCs " << std::endl; - - channel++; - thisSample[channel] = 0.0000374 * - float(dataBlock->auxiliaryData[dataStream][1][samp + 0] - 32768); - // constant offset keeps the values visible in the LFP Viewer - - auxBuffer[channel] = thisSample[channel]; - - channel++; - thisSample[channel] = 0.0000374 * - float(dataBlock->auxiliaryData[dataStream][1][samp + 1] - 32768); - // constant offset keeps the values visible in the LFP Viewer - - auxBuffer[channel] = thisSample[channel]; - - - channel++; - thisSample[channel] = 0.0000374 * - float(dataBlock->auxiliaryData[dataStream][1][samp + 2] - 32768); - // constant offset keeps the values visible in the LFP Viewer - - auxBuffer[channel] = thisSample[channel]; - - } - else // repeat last values from buffer - { - - //std::cout << "reading sample stream " << streamNumber << " aux ADCs " << std::endl; - - channel++; - thisSample[channel] = auxBuffer[channel]; - channel++; - thisSample[channel] = auxBuffer[channel]; - channel++; - thisSample[channel] = auxBuffer[channel]; - } - } - - } - - // finally, loop through acquisition board ADC channels if necessary - if (acquireAdcChannels) - { - for (int adcChan = 0; adcChan < 8; ++adcChan) - { - - channel++; - // ADC waveform units = volts - thisSample[channel] = - //0.000050354 * float(dataBlock->boardAdcData[adcChan][samp]); - 0.00015258789 * float(dataBlock->boardAdcData[adcChan][samp]) - 5 - 0.4096; // account for +/-5V input range and DC offset - } - } - // std::cout << channel << std::endl; - - timestamp = dataBlock->timeStamp[samp]; - //timestamp = timestamp; - eventCode = dataBlock->ttlIn[samp]; - dataBuffer->addToBuffer(thisSample, ×tamp, &eventCode, 1); -#endif - } - - } - - - if (dacOutputShouldChange) - { - std::cout << "DAC" << std::endl; - for (int k=0; k<8; k++) - { - if (dacChannelsToUpdate[k]) - { - dacChannelsToUpdate[k] = false; - if (dacChannels[k] >= 0) - { - /* evalBoard->enableDac(k, true); - evalBoard->selectDacDataStream(k, dacStream[k]); - evalBoard->selectDacDataChannel(k, dacChannels[k]); - evalBoard->setDacThreshold(k, (int)abs((dacThresholds[k]/0.195) + 32768),dacThresholds[k] >= 0); - // evalBoard->setDacThresholdVoltage(k, (int) dacThresholds[k]);*/ - } - else - { - // evalBoard->enableDac(k, false); - } - } - } - - /* evalBoard->setTtlMode(ttlMode ? 1 : 0); - evalBoard->enableExternalFastSettle(fastTTLSettleEnabled); - evalBoard->setExternalFastSettleChannel(fastSettleTTLChannel); - evalBoard->setDacHighpassFilter(desiredDAChpf); - evalBoard->enableDacHighpassFilter(desiredDAChpfState); - evalBoard->enableBoardLeds(ledsEnabled); - evalBoard->setClockDivider(clockDivideFactor);*/ - - dacOutputShouldChange = false; - } - - return true; - -} - -void RHD2000Thread::checkThreshold(float s) -{ - bool check = (s > THRESHOLD_CHECK); - if (!check != !lastThreshold) - { - //std::cout << "SIG" << std::endl; - lastThreshold = check; - evalBoard->setOuputSigs(check ? 0x0001 : 0x0000); - } -} - -int RHD2000Thread::getChannelFromHeadstage (int hs, int ch) const -{ - int channelCount = 0; - int hsCount = 0; - if (hs < 0 || hs >= MAX_NUM_HEADSTAGES+1) - return -1; - if (hs == MAX_NUM_HEADSTAGES) //let's consider this the ADC channels - { - if (getNumAdcOutputs() > 0) - { - return getNumHeadstageOutputs() + getNumAuxOutputs() + ch; - } - else - return -1; - } - if (headstagesArray[hs]->isPlugged()) - { - if (ch < 0) - return -1; - if (ch < headstagesArray[hs]->getNumActiveChannels()) - { - for (int i = 0; i < hs; i++) - { - channelCount += headstagesArray[i]->getNumActiveChannels(); - } - return channelCount + ch; - } - else if (ch < headstagesArray[hs]->getNumActiveChannels() + 3) - { - for (int i = 0; i < MAX_NUM_HEADSTAGES; i++) - { - if (headstagesArray[i]->isPlugged()) - { - channelCount += headstagesArray[i]->getNumActiveChannels(); - if (i < hs) - hsCount++; - } - } - return channelCount + hsCount * 3 + ch-headstagesArray[hs]->getNumActiveChannels(); - } - else - { - return -1; - } - - } - else - { - return -1; - } -} - -int RHD2000Thread::getHeadstageChannel (int& hs, int ch) const -{ - int channelCount = 0; - int hsCount = 0; - - if (ch < 0) - return -1; - - for (int i = 0; i < MAX_NUM_HEADSTAGES; i++) - { - if (headstagesArray[i]->isPlugged()) - { - int chans = headstagesArray[hs]->getNumActiveChannels(); - if (ch >= channelCount && ch < channelCount + chans) - { - hs = i; - return ch - channelCount; - } - channelCount += chans; - hsCount++; - } - } - if (ch < (channelCount + hsCount * 3)) //AUX - { - hsCount = (ch - channelCount) / 3; - for (int i = 0; i < MAX_NUM_HEADSTAGES; i++) - { - if (headstagesArray[i]->isPlugged()) - { - if (hsCount == 0) - { - hs = i; - return ch - channelCount; - } - hsCount--; - channelCount++; - } - } - } - return -1; -} - -void RHD2000Thread::enableBoardLeds(bool enable) -{ -#if 0 - ledsEnabled = enable; - if (isAcquisitionActive()) - dacOutputShouldChange = true; - else - evalBoard->enableBoardLeds(enable); -#endif -} - -int RHD2000Thread::setClockDivider(int divide_ratio) -{ -#if 0 - // Divide ratio should be 1 or an even number - if (divide_ratio != 1 && divide_ratio % 2) - divide_ratio--; - - // Format the divide ratio from its true value to the - // format required by the firmware - // Ratio N - // 1 0 - // >=2 Ratio/2 - if (divide_ratio == 1) - clockDivideFactor = 0; - else - clockDivideFactor = static_cast<uint16>(divide_ratio/2); - - if (isAcquisitionActive()) - dacOutputShouldChange = true; - else - evalBoard->setClockDivider(clockDivideFactor); -#endif - return divide_ratio; - -} - -void RHD2000Thread::runImpedanceTest(ImpedanceData* data) -{ - impedanceThread->stopThreadSafely(); - impedanceThread->prepareData(data); - impedanceThread->startThread(); -} - - -RHDHeadstage::RHDHeadstage(rhd2000PCIe::BoardDataSource stream) : - dataStream(stream), numStreams(0), channelsPerStream(32), halfChannels(false) -{ - streamIndex = -1; -} - -RHDHeadstage::~RHDHeadstage() -{ -} - -void RHDHeadstage::setNumStreams(int num) -{ - numStreams = num; -} - -void RHDHeadstage::setChannelsPerStream(int nchan, int index) -{ - channelsPerStream = nchan; - streamIndex = index; -} - -int RHDHeadstage::getStreamIndex (int index) const -{ - return streamIndex + index; -} - -int RHDHeadstage::getNumChannels() const -{ - return channelsPerStream*numStreams; -} - -int RHDHeadstage::getNumStreams() const -{ - return numStreams; -} - -void RHDHeadstage::setHalfChannels(bool half) -{ - halfChannels = half; -} - -int RHDHeadstage::getNumActiveChannels() const -{ - return (int)(getNumChannels() / (halfChannels ? 2 : 1)); -} - -rhd2000PCIe::BoardDataSource RHDHeadstage::getDataStream (int index) const -{ - if (index < 0 || index > 1) - index = 0; - - return static_cast<rhd2000PCIe::BoardDataSource>(dataStream + MAX_NUM_HEADSTAGES * index); -} - -bool RHDHeadstage::isPlugged() const -{ - return (numStreams > 0); -} - -/***********************************/ -/* Below is code for impedance measurements */ - -RHDImpedanceMeasure::RHDImpedanceMeasure(RHD2000Thread* b) : Thread(""), data(nullptr), board(b) -{ - // to perform electrode impedance measurements at very low frequencies. - const int maxNumBlocks = 120; - int numStreams = 8; - allocateDoubleArray3D(amplifierPreFilter, numStreams, 32, SAMPLES_PER_DATA_BLOCK_PCIE * maxNumBlocks); -} - -RHDImpedanceMeasure::~RHDImpedanceMeasure() -{ - stopThreadSafely(); -} - -void RHDImpedanceMeasure::stopThreadSafely() -{ - if (isThreadRunning()) - { - CoreServices::sendStatusMessage("Impedance measure in progress. Stopping it."); - if (!stopThread(3000)) //wait three seconds max for it to exit gracefully - { - std::cerr << "ERROR: Impedance measurement thread did not exit. Force killed it. This might led to crashes." << std::endl; - } - } -} - -void RHDImpedanceMeasure::waitSafely() -{ - if (!waitForThreadToExit(120000)) //two minutes should be enough for completing a scan - { - CoreServices::sendStatusMessage("Impedance measurement took too much. Aborting."); - if (!stopThread(3000)) //wait three seconds max for it to exit gracefully - { - std::cerr << "ERROR: Impedance measurement thread did not exit. Force killed it. This might led to crashes." << std::endl; - } - } -} - -void RHDImpedanceMeasure::prepareData(ImpedanceData* d) -{ - data = d; -} - - -// Update electrode impedance measurement frequency, after checking that -// requested test frequency lies within acceptable ranges based on the -// amplifier bandwidth and the sampling rate. See impedancefreqdialog.cpp -// for more information. -float RHDImpedanceMeasure::updateImpedanceFrequency(float desiredImpedanceFreq, bool& impedanceFreqValid) -{ - int impedancePeriod; - double lowerBandwidthLimit, upperBandwidthLimit; - float actualImpedanceFreq; - - upperBandwidthLimit = board->actualUpperBandwidth / 1.5; - lowerBandwidthLimit = board->actualLowerBandwidth * 1.5; - if (board->dspEnabled) - { - if (board->actualDspCutoffFreq > board->actualLowerBandwidth) - { - lowerBandwidthLimit = board->actualDspCutoffFreq * 1.5; - } - } - - if (desiredImpedanceFreq > 0.0) - { - impedancePeriod = (board->boardSampleRate / desiredImpedanceFreq); - if (impedancePeriod >= 4 && impedancePeriod <= 1024 && - desiredImpedanceFreq >= lowerBandwidthLimit && - desiredImpedanceFreq <= upperBandwidthLimit) - { - actualImpedanceFreq = board->boardSampleRate / impedancePeriod; - impedanceFreqValid = true; - } - else - { - actualImpedanceFreq = 0.0; - impedanceFreqValid = false; - } - } - else - { - actualImpedanceFreq = 0.0; - impedanceFreqValid = false; - } - - return actualImpedanceFreq; -} - - -// Reads numBlocks blocks of raw USB data stored in a queue of Rhd2000DataBlock -// objects, loads this data into this SignalProcessor object, scaling the raw -// data to generate waveforms with units of volts or microvolts. -int RHDImpedanceMeasure::loadAmplifierData (queue<Rhd2000DataBlock>& dataQueue, - int numBlocks, int numDataStreams) -{ - - int block, t, channel, stream; - int indexAmp = 0; - /* - int indexAux = 0; - int indexSupply = 0; - int indexAdc = 0; - int indexDig = 0; - int numWordsWritten = 0; - - int bufferIndex; - int16 tempQint16; - uint16 tempQuint16; - int32 tempQint32; - - bool triggerFound = false; - const double AnalogTriggerThreshold = 1.65; - */ - - - for (block = 0; block < numBlocks; ++block) - { - - // Load and scale RHD2000 amplifier waveforms - // (sampled at amplifier sampling rate) - for (t = 0; t < SAMPLES_PER_DATA_BLOCK_PCIE; ++t) - { - for (channel = 0; channel < 32; ++channel) - { - for (stream = 0; stream < numDataStreams; ++stream) - { - // Amplifier waveform units = microvolts - amplifierPreFilter[stream][channel][indexAmp] = 0.195 * - (dataQueue.front().amplifierData[stream][channel][t] - 32768); - } - } - ++indexAmp; - } - // We are done with this Rhd2000DataBlock object; remove it from dataQueue - dataQueue.pop(); - } - - return 0; -} - -#define PI 3.14159265359 -#define TWO_PI 6.28318530718 -#define DEGREES_TO_RADIANS 0.0174532925199 -#define RADIANS_TO_DEGREES 57.2957795132 - -// Return the magnitude and phase (in degrees) of a selected frequency component (in Hz) -// for a selected amplifier channel on the selected USB data stream. -void RHDImpedanceMeasure::measureComplexAmplitude(std::vector<std::vector<std::vector<double>>>& measuredMagnitude, - std::vector<std::vector<std::vector<double>>>& measuredPhase, - int capIndex, int stream, int chipChannel, int numBlocks, - double sampleRate, double frequency, int numPeriods) -{ - int period = (sampleRate / frequency); - int startIndex = 0; - int endIndex = startIndex + numPeriods * period - 1; - - // Move the measurement window to the end of the waveform to ignore start-up transient. - while (endIndex < SAMPLES_PER_DATA_BLOCK_PCIE * numBlocks - period) - { - startIndex += period; - endIndex += period; - } - - double iComponent, qComponent; - - // Measure real (iComponent) and imaginary (qComponent) amplitude of frequency component. - amplitudeOfFreqComponent(iComponent, qComponent, amplifierPreFilter[stream][chipChannel], - startIndex, endIndex, sampleRate, frequency); - // Calculate magnitude and phase from real (I) and imaginary (Q) components. - measuredMagnitude[stream][chipChannel][capIndex] = - sqrt(iComponent * iComponent + qComponent * qComponent); - measuredPhase[stream][chipChannel][capIndex] = - RADIANS_TO_DEGREES *atan2(qComponent, iComponent); -} - -// Returns the real and imaginary amplitudes of a selected frequency component in the vector -// data, between a start index and end index. -void RHDImpedanceMeasure::amplitudeOfFreqComponent(double& realComponent, double& imagComponent, - const std::vector<double>& data, int startIndex, - int endIndex, double sampleRate, double frequency) -{ - int length = endIndex - startIndex + 1; - const double k = TWO_PI * frequency / sampleRate; // precalculate for speed - - // Perform correlation with sine and cosine waveforms. - double meanI = 0.0; - double meanQ = 0.0; - for (int t = startIndex; t <= endIndex; ++t) - { - meanI += data.at(t) * cos(k * t); - meanQ += data.at(t) * -1.0 * sin(k * t); - } - meanI /= (double)length; - meanQ /= (double)length; - - realComponent = 2.0 * meanI; - imagComponent = 2.0 * meanQ; -} - - - -// Given a measured complex impedance that is the result of an electrode impedance in parallel -// with a parasitic capacitance (i.e., due to the amplifier input capacitance and other -// capacitances associated with the chip bondpads), this function factors out the effect of the -// parasitic capacitance to return the acutal electrode impedance. -void RHDImpedanceMeasure::factorOutParallelCapacitance(double& impedanceMagnitude, double& impedancePhase, - double frequency, double parasiticCapacitance) -{ - // First, convert from polar coordinates to rectangular coordinates. - double measuredR = impedanceMagnitude * cos(DEGREES_TO_RADIANS * impedancePhase); - double measuredX = impedanceMagnitude * sin(DEGREES_TO_RADIANS * impedancePhase); - - double capTerm = TWO_PI * frequency * parasiticCapacitance; - double xTerm = capTerm * (measuredR * measuredR + measuredX * measuredX); - double denominator = capTerm * xTerm + 2 * capTerm * measuredX + 1; - double trueR = measuredR / denominator; - double trueX = (measuredX + xTerm) / denominator; - - // Now, convert from rectangular coordinates back to polar coordinates. - impedanceMagnitude = sqrt(trueR * trueR + trueX * trueX); - impedancePhase = RADIANS_TO_DEGREES * atan2(trueX, trueR); -} - -// This is a purely empirical function to correct observed errors in the real component -// of measured electrode impedances at sampling rates below 15 kS/s. At low sampling rates, -// it is difficult to approximate a smooth sine wave with the on-chip voltage DAC and 10 kHz -// 2-pole lowpass filter. This function attempts to somewhat correct for this, but a better -// solution is to always run impedance measurements at 20 kS/s, where they seem to be most -// accurate. -void RHDImpedanceMeasure::empiricalResistanceCorrection(double& impedanceMagnitude, double& impedancePhase, - double boardSampleRate) -{ - // First, convert from polar coordinates to rectangular coordinates. - double impedanceR = impedanceMagnitude * cos(DEGREES_TO_RADIANS * impedancePhase); - double impedanceX = impedanceMagnitude * sin(DEGREES_TO_RADIANS * impedancePhase); - - // Emprically derived correction factor (i.e., no physical basis for this equation). - impedanceR /= 10.0 * exp(-boardSampleRate / 2500.0) * cos(TWO_PI * boardSampleRate / 15000.0) + 1.0; - - // Now, convert from rectangular coordinates back to polar coordinates. - impedanceMagnitude = sqrt(impedanceR * impedanceR + impedanceX * impedanceX); - impedancePhase = RADIANS_TO_DEGREES * atan2(impedanceX, impedanceR); -} - -void RHDImpedanceMeasure::run() -{ - RHD2000Editor* ed; - ed = (RHD2000Editor*)board->sn->editor.get(); - if (data == nullptr) - return; - board->evalBoard->openPipe(); - runImpedanceMeasurement(); - restoreFPGA(); - ed->triggerAsyncUpdate(); - data = nullptr; -} - -#define CHECK_EXIT if (threadShouldExit()) return - -void RHDImpedanceMeasure::runImpedanceMeasurement() -{ - int commandSequenceLength, stream, channel, capRange; - double cSeries; - vector<int> commandList; - //int triggerIndex; // dummy reference variable; not used - queue<Rhd2000DataBlock> bufferQueue; // dummy reference variable; not used - int numdataStreams = board->evalBoard->getNumEnabledDataStreams(); - - bool rhd2164ChipPresent = false; - int chOffset; - - Array<int> enabledStreams; - for (stream = 0; stream < MAX_NUM_DATA_STREAMS; ++stream) - { - CHECK_EXIT; - if (board->evalBoard->isStreamEnabled(stream)) - { - enabledStreams.add(stream); - } - - if (board->chipId[stream] == CHIP_ID_RHD2164_B) - { - rhd2164ChipPresent = true; - } - } - - bool validImpedanceFreq; - float actualImpedanceFreq = updateImpedanceFrequency(1000.0, validImpedanceFreq); - if (!validImpedanceFreq) - { - return; - } - // Create a command list for the AuxCmd1 slot. - commandSequenceLength = board->chipRegisters.createCommandListZcheckDac(commandList, actualImpedanceFreq, 128.0); - CHECK_EXIT; - board->evalBoard->uploadCommandList(commandList, rhd2000PCIe::AuxCmd1, 1); - board->evalBoard->selectAuxCommandLength(rhd2000PCIe::AuxCmd1, - 0, commandSequenceLength - 1); - /*if (board->fastTTLSettleEnabled) - { - board->evalBoard->enableExternalFastSettle(false); - }*/ - CHECK_EXIT; - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortA, - rhd2000PCIe::AuxCmd1, 1); - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortB, - rhd2000PCIe::AuxCmd1, 1); - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortC, - rhd2000PCIe::AuxCmd1, 1); - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortD, - rhd2000PCIe::AuxCmd1, 1); - - // Select number of periods to measure impedance over - int numPeriods = (0.020 * actualImpedanceFreq); // Test each channel for at least 20 msec... - if (numPeriods < 5) numPeriods = 5; // ...but always measure across no fewer than 5 complete periods - double period = board->boardSampleRate / actualImpedanceFreq; - int numBlocks = ceil((numPeriods + 2.0) * period / 60.0); // + 2 periods to give time to settle initially - if (numBlocks < 2) numBlocks = 2; // need first block for command to switch channels to take effect. - - CHECK_EXIT; - board->actualDspCutoffFreq = board->chipRegisters.setDspCutoffFreq(board->desiredDspCutoffFreq); - board->actualLowerBandwidth = board->chipRegisters.setLowerBandwidth(board->desiredLowerBandwidth); - board->actualUpperBandwidth = board->chipRegisters.setUpperBandwidth(board->desiredUpperBandwidth); - board->chipRegisters.enableDsp(board->dspEnabled); - board->chipRegisters.enableZcheck(true); - commandSequenceLength = board->chipRegisters.createCommandListRegisterConfig(commandList, false); - CHECK_EXIT; - // Upload version with no ADC calibration to AuxCmd3 RAM Bank 1. - board->evalBoard->uploadCommandList(commandList, rhd2000PCIe::AuxCmd3, 3); - board->evalBoard->selectAuxCommandLength(rhd2000PCIe::AuxCmd3, 0, commandSequenceLength - 1); - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortA, rhd2000PCIe::AuxCmd3, 3); - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortB, rhd2000PCIe::AuxCmd3, 3); - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortC, rhd2000PCIe::AuxCmd3, 3); - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortD, rhd2000PCIe::AuxCmd3, 3); - - CHECK_EXIT; - board->evalBoard->setContinuousRunMode(false); - board->evalBoard->setMaxTimeStep(INIT_STEP * numBlocks); - - // Create matrices of doubles of size (numStreams x 32 x 3) to store complex amplitudes - // of all amplifier channels (32 on each data stream) at three different Cseries values. - std::vector<std::vector<std::vector<double>>> measuredMagnitude; - std::vector<std::vector<std::vector<double>>> measuredPhase; - - measuredMagnitude.resize(board->evalBoard->getNumEnabledDataStreams()); - measuredPhase.resize(board->evalBoard->getNumEnabledDataStreams()); - for (int i = 0; i < board->evalBoard->getNumEnabledDataStreams(); ++i) - { - measuredMagnitude[i].resize(32); - measuredPhase[i].resize(32); - for (int j = 0; j < 32; ++j) - { - measuredMagnitude[i][j].resize(3); - measuredPhase[i][j].resize(3); - } - } - - - - double distance, minDistance, current, Cseries; - double impedanceMagnitude, impedancePhase; - - const double bestAmplitude = 250.0; // we favor voltage readings that are closest to 250 uV: not too large, - // and not too small. - const double dacVoltageAmplitude = 128 * (1.225 / 256); // this assumes the DAC amplitude was set to 128 - const double parasiticCapacitance = 14.0e-12; // 14 pF: an estimate of on-chip parasitic capacitance, - // including 10 pF of amplifier input capacitance. - double relativeFreq = actualImpedanceFreq / board->boardSampleRate; - - int bestAmplitudeIndex; - - // We execute three complete electrode impedance measurements: one each with - // Cseries set to 0.1 pF, 1 pF, and 10 pF. Then we select the best measurement - // for each channel so that we achieve a wide impedance measurement range. - for (capRange = 0; capRange < 3; ++capRange) - { - - switch (capRange) - { - case 0: - board->chipRegisters.setZcheckScale(Rhd2000Registers::ZcheckCs100fF); - cSeries = 0.1e-12; - cout << "setting capacitance to 0.1pF" << endl; - break; - case 1: - board->chipRegisters.setZcheckScale(Rhd2000Registers::ZcheckCs1pF); - cSeries = 1.0e-12; - cout << "setting capacitance to 1pF" << endl; - break; - case 2: - board->chipRegisters.setZcheckScale(Rhd2000Registers::ZcheckCs10pF); - cSeries = 10.0e-12; - cout << "setting capacitance to 10pF" << endl; - break; - } - - // Check all 32 channels across all active data streams. - for (channel = 0; channel < 32; ++channel) - { - CHECK_EXIT; - cout << "running impedance on channel " << channel << endl; - - board->chipRegisters.setZcheckChannel(channel); - commandSequenceLength = - board->chipRegisters.createCommandListRegisterConfig(commandList, false); - // Upload version with no ADC calibration to AuxCmd3 RAM Bank 1. - board->evalBoard->uploadCommandList(commandList, rhd2000PCIe::AuxCmd3, 3); - - board->evalBoard->run(); - while (board->evalBoard->isRunning()) - { - - } - queue<Rhd2000DataBlock> dataQueue; - board->evalBoard->readDataBlocks(numBlocks, dataQueue); - loadAmplifierData(dataQueue, numBlocks, numdataStreams); - for (stream = 0; stream < numdataStreams; ++stream) - { - if (board->chipId[stream] != CHIP_ID_RHD2164_B) - { - measureComplexAmplitude(measuredMagnitude, measuredPhase, - capRange, stream, channel, numBlocks, board->boardSampleRate, - actualImpedanceFreq, numPeriods); - } - } - - // If an RHD2164 chip is plugged in, we have to set the Zcheck select register to channels 32-63 - // and repeat the previous steps. - if (rhd2164ChipPresent) - { - CHECK_EXIT; - board->chipRegisters.setZcheckChannel(channel + 32); // address channels 32-63 - commandSequenceLength = - board->chipRegisters.createCommandListRegisterConfig(commandList, false); - // Upload version with no ADC calibration to AuxCmd3 RAM Bank 1. - board->evalBoard->uploadCommandList(commandList, rhd2000PCIe::AuxCmd3, 3); - - board->evalBoard->run(); - while (board->evalBoard->isRunning()) - { - - } - board->evalBoard->readDataBlocks(numBlocks, dataQueue); - loadAmplifierData(dataQueue, numBlocks, numdataStreams); - - for (stream = 0; stream < board->evalBoard->getNumEnabledDataStreams(); ++stream) - { - if (board->chipId[stream] == CHIP_ID_RHD2164_B) - { - measureComplexAmplitude(measuredMagnitude, measuredPhase, - capRange, stream, channel, numBlocks, board->boardSampleRate, - actualImpedanceFreq, numPeriods); - } - } - } - } - } - - data->streams.clear(); - data->channels.clear(); - data->magnitudes.clear(); - data->phases.clear(); - - for (stream = 0; stream < board->evalBoard->getNumEnabledDataStreams(); ++stream) - { - if ((board->chipId[stream] == CHIP_ID_RHD2132) && (board->numChannelsPerDataStream[stream] == 16)) - chOffset = RHD2132_16CH_OFFSET; - else - chOffset = 0; - - for (channel = 0; channel < board->numChannelsPerDataStream[stream]; ++channel) - { - if (1) - { - minDistance = 9.9e99; // ridiculously large number - for (capRange = 0; capRange < 3; ++capRange) - { - // Find the measured amplitude that is closest to bestAmplitude on a logarithmic scale - distance = abs(log(measuredMagnitude[stream][channel+chOffset][capRange] / bestAmplitude)); - if (distance < minDistance) - { - bestAmplitudeIndex = capRange; - minDistance = distance; - } - } - switch (bestAmplitudeIndex) - { - case 0: - Cseries = 0.1e-12; - break; - case 1: - Cseries = 1.0e-12; - break; - case 2: - Cseries = 10.0e-12; - break; - } - - // Calculate current amplitude produced by on-chip voltage DAC - current = TWO_PI * actualImpedanceFreq * dacVoltageAmplitude * Cseries; - - // Calculate impedance magnitude from calculated current and measured voltage. - impedanceMagnitude = 1.0e-6 * (measuredMagnitude[stream][channel + chOffset][bestAmplitudeIndex] / current) * - (18.0 * relativeFreq * relativeFreq + 1.0); - - // Calculate impedance phase, with small correction factor accounting for the - // 3-command SPI pipeline delay. - impedancePhase = measuredPhase[stream][channel + chOffset][bestAmplitudeIndex] + (360.0 * (3.0 / period)); - - // Factor out on-chip parasitic capacitance from impedance measurement. - factorOutParallelCapacitance(impedanceMagnitude, impedancePhase, actualImpedanceFreq, - parasiticCapacitance); - - // Perform empirical resistance correction to improve accuarcy at sample rates below - // 15 kS/s. - empiricalResistanceCorrection(impedanceMagnitude, impedancePhase, - board->boardSampleRate); - - data->streams.add(enabledStreams[stream]); - data->channels.add(channel + chOffset); - data->magnitudes.add(impedanceMagnitude); - data->phases.add(impedancePhase); - - if (impedanceMagnitude > 1000000) - cout << "stream " << stream << " channel " << 1 + channel << " magnitude: " << String(impedanceMagnitude / 1e6, 2) << " MOhm , phase : " << impedancePhase << endl; - else - cout << "stream " << stream << " channel " << 1 + channel << " magnitude: " << String(impedanceMagnitude / 1e3, 2) << " kOhm , phase : " << impedancePhase << endl; - - } - } - } - data->valid = true; - -} - -void RHDImpedanceMeasure::restoreFPGA() -{ - board->evalBoard->setContinuousRunMode(false); - board->evalBoard->setMaxTimeStep(0); - board->evalBoard->closePipe(); - - // Switch back to flatline - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortA, rhd2000PCIe::AuxCmd1, 0); - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortB, rhd2000PCIe::AuxCmd1, 0); - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortC, rhd2000PCIe::AuxCmd1, 0); - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortD, rhd2000PCIe::AuxCmd1, 0); - board->evalBoard->selectAuxCommandLength(rhd2000PCIe::AuxCmd1, 0, 1); - - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortA, rhd2000PCIe::AuxCmd3, - board->fastSettleEnabled ? 2 : 1); - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortB, rhd2000PCIe::AuxCmd3, - board->fastSettleEnabled ? 2 : 1); - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortC, rhd2000PCIe::AuxCmd3, - board->fastSettleEnabled ? 2 : 1); - board->evalBoard->selectAuxCommandBank(rhd2000PCIe::PortD, rhd2000PCIe::AuxCmd3, - board->fastSettleEnabled ? 2 : 1); - - /*if (board->fastTTLSettleEnabled) - { - board->evalBoard->enableExternalFastSettle(true); - }*/ -} diff --git a/Source/Plugins/PCIeRhythm/RHD2000Thread.h b/Source/Plugins/PCIeRhythm/RHD2000Thread.h deleted file mode 100644 index e18d81992897d4f74c89ce154e02c518e4e3a589..0000000000000000000000000000000000000000 --- a/Source/Plugins/PCIeRhythm/RHD2000Thread.h +++ /dev/null @@ -1,300 +0,0 @@ -/* - ------------------------------------------------------------------ - - This file is part of the Open Ephys GUI - Copyright (C) 2016 Open Ephys - - ------------------------------------------------------------------ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program 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. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - -*/ - - -#ifndef __RHD2000THREAD_H_2C4CBD67__ -#define __RHD2000THREAD_H_2C4CBD67__ - -#include <DataThreadHeaders.h> -#include <stdio.h> -#include <string.h> - -#include "rhythm-api/rhd2000PCIe.h" -#include "rhythm-api/rhd2000registers.h" -#include "rhythm-api/rhd2000datablock.h" - - -#define MAX_NUM_DATA_STREAMS_PCIE 16 -#define MAX_NUM_HEADSTAGES 8 - -#define MAX_NUM_CHANNELS MAX_NUM_DATA_STREAMS_PCIE*35 - -class SourceNode; - -namespace PCIeRhythm -{ -class RHDHeadstage; -class RHDImpedanceMeasure; - -struct ImpedanceData -{ - Array<int> streams; - Array<int> channels; - Array<float> magnitudes; - Array<float> phases; - bool valid; -}; - - /** - Communicates with the RHD2000 Evaluation Board from Intan Technologies - - @see DataThread, SourceNode - */ - -class RHD2000Thread : public DataThread - , public Timer -{ - friend class RHDImpedanceMeasure; -public: - RHD2000Thread (SourceNode* sn); - ~RHD2000Thread(); - - int getNumChannels() const; - - // for communication with SourceNode processors: - bool foundInputSource() override; - - int getNumEventChannels() const override; - int getNumHeadstageOutputs() const override; - int getNumAuxOutputs() const override; - int getNumAdcOutputs() const override; - - bool usesCustomNames() const; - - float getSampleRate() const override; - float getBitVolts (Channel* chan) const override; - - float getAdcBitVolts (int channelNum) const; - - bool isHeadstageEnabled (int hsNum) const; - int getChannelsInHeadstage (int hsNum) const; - - void setSampleRate (int index, bool temporary = false); - - double setUpperBandwidth (double upper); // set desired BW, returns actual BW - double setLowerBandwidth (double lower); - - double setDspCutoffFreq (double freq); - double getDspCutoffFreq() const; - - void setDSPOffset (bool state); - - int setNoiseSlicerLevel (int level); - void setFastTTLSettle (bool state, int channel); - void setTTLoutputMode (bool state); - void setDAChpf (float cutoff, bool enabled); - - void scanPorts(); - void enableAdcs (bool); - - bool isReady() override; - bool isAcquisitionActive() const; - - int modifyChannelGain (int channel, float gain) override; - int modifyChannelName (int channel, String newName) override; - - void getEventChannelNames (StringArray& Names) const override; - - Array<int> getDACchannels() const; - - void setDACchannel (int dacOutput, int channel); - void setDACthreshold (int dacOutput, float threshold); - void setDefaultNamingScheme (int scheme); - - String getChannelName (int ch) const; - void setNumChannels (int hsNum, int nChannels); - - int getHeadstageChannels (int hsNum) const; - int getActiveChannelsInHeadstage (int hsNum) const; - - /* Gets the absolute channel index from the headstage channel index*/ - int getChannelFromHeadstage (int hs, int ch) const; - /*Gets the headstage relative channel index from the absolute channel index*/ - int getHeadstageChannel (int& hs, int ch) const; - - void runImpedanceTest (ImpedanceData* data); - void enableBoardLeds (bool enable); - int setClockDivider (int divide_ratio); - - GenericEditor* createEditor (SourceNode* sn) override; - static DataThread* createDataThread (SourceNode* sn); - - -private: - bool enableHeadstage (int hsNum, bool enabled, int nStr = 1, int strChans = 32); - void updateBoardStreams(); - void setCableLength (int hsNum, float length); - - bool updateBuffer() override; - - void timerCallback() override; - - bool startAcquisition() override; - bool stopAcquisition() override; - - bool openBoard(); - void initializeBoard(); - - void updateRegisters(); - - int deviceId (Rhd2000DataBlock* dataBlock, int stream, int& register59Value); - - void checkThreshold (float s); - - void setDefaultChannelNames(); - - ScopedPointer<rhd2000PCIe> evalBoard; - Rhd2000Registers chipRegisters; - ScopedPointer<Rhd2000DataBlock> dataBlock; - - int numChannels; - bool deviceFound; - - float thisSample[MAX_NUM_CHANNELS]; - float auxBuffer[MAX_NUM_CHANNELS]; // aux inputs are only sampled every 4th sample, so use this to buffer the samples so they can be handles just like the regular neural channels later - float auxSamples[MAX_NUM_DATA_STREAMS_PCIE][3]; - - unsigned int blockSize; - - bool isTransmitting; - - bool dacOutputShouldChange; - bool acquireAdcChannels; - bool acquireAuxChannels; - - bool fastSettleEnabled; - bool fastTTLSettleEnabled; - bool fastSettleTTLChannel; - bool ttlMode; - bool desiredDAChpfState; - double desiredDAChpf; - - bool dspEnabled; - double actualDspCutoffFreq, desiredDspCutoffFreq; - double actualUpperBandwidth, desiredUpperBandwidth; - double actualLowerBandwidth, desiredLowerBandwidth; - int actualNoiseSlicerLevel, desiredNoiseSlicerLevel; - double boardSampleRate; - int savedSampleRateIndex; - - String libraryFilePath; - - double cableLengthPortA, cableLengthPortB, cableLengthPortC, cableLengthPortD; - - int audioOutputL, audioOutputR; - int* dacChannels, *dacStream; - float* dacThresholds; - bool* dacChannelsToUpdate; - Array<int> chipId; - OwnedArray<RHDHeadstage> headstagesArray; - Array<rhd2000PCIe::BoardDataSource> enabledStreams; - Array<int> numChannelsPerDataStream; - - // used for data stream names... - int numberingScheme; - Array<float> adcBitVolts; - bool newScan; - ScopedPointer<RHDImpedanceMeasure> impedanceThread; - bool ledsEnabled; - - bool lastThreshold; - - - int auxSamp; - - // Sync ouput divide factor - uint16 clockDivideFactor; - - // ======================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RHD2000Thread); -}; - - -class RHDHeadstage -{ -public: - RHDHeadstage (rhd2000PCIe::BoardDataSource stream); - ~RHDHeadstage(); - - bool isPlugged() const; - - int getStreamIndex (int index) const; - int getNumActiveChannels() const; - int getNumChannels() const; - int getNumStreams() const; - - rhd2000PCIe::BoardDataSource getDataStream (int index) const; - - void setNumStreams (int num); - void setChannelsPerStream (int nchan, int index); - void setHalfChannels (bool half); //mainly used for de 16ch rhd2132 board - - -private: - rhd2000PCIe::BoardDataSource dataStream; - - int streamIndex; - int numStreams; - int channelsPerStream; - bool halfChannels; - - // ======================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RHDHeadstage); -}; - -class RHDImpedanceMeasure : public Thread -{ -public: - RHDImpedanceMeasure(RHD2000Thread* b); - ~RHDImpedanceMeasure(); - void prepareData(ImpedanceData* d); - void stopThreadSafely(); - void waitSafely(); - void run(); -private: - void runImpedanceMeasurement(); - void restoreFPGA(); - void measureComplexAmplitude(std::vector<std::vector<std::vector<double>>>& measuredMagnitude, - std::vector<std::vector<std::vector<double>>>& measuredPhase, - int capIndex, int stream, int chipChannel, int numBlocks, - double sampleRate, double frequency, int numPeriods); - void amplitudeOfFreqComponent(double& realComponent, double& imagComponent, - const std::vector<double>& data, int startIndex, - int endIndex, double sampleRate, double frequency); - float updateImpedanceFrequency(float desiredImpedanceFreq, bool& impedanceFreqValid); - void factorOutParallelCapacitance(double& impedanceMagnitude, double& impedancePhase, - double frequency, double parasiticCapacitance); - void empiricalResistanceCorrection(double& impedanceMagnitude, double& impedancePhase, - double boardSampleRate); - int loadAmplifierData (queue<Rhd2000DataBlock>& dataQueue, - int numBlocks, int numDataStreams); - - std::vector<std::vector<std::vector<double>>> amplifierPreFilter; - - ImpedanceData* data; - RHD2000Thread* board; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RHDImpedanceMeasure); -}; -}; -#endif // __RHD2000THREAD_H_2C4CBD67__ diff --git a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000PCIe.cpp b/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000PCIe.cpp deleted file mode 100644 index 6e2a7e9f83adc06d58357facafe505e0d9a2d354..0000000000000000000000000000000000000000 --- a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000PCIe.cpp +++ /dev/null @@ -1,1044 +0,0 @@ -#include "rhd2000PCIe.h" -#include <iostream> -#include <iomanip> -#include <fstream> -#include <queue> -#include <cmath> - -#ifdef _WIN32 -#include <io.h> -#define Open _open -#define Seek _lseek -#define Read _read -#define Write _write -#define Close _close -#define CONTROL_FILE "\\\\.\\xillybus_control_regs_16" -#define STATUS_FILE "\\\\.\\xillybus_status_regs_16" -#define FIFO_FILE "\\\\.\\xillybus_neural_data_32" -#define AUXCMD1_FILE "\\\\.\\xillybus_auxcmd1_membank_16" -#define AUXCMD2_FILE "\\\\.\\xillybus_auxcmd2_membank_16" -#define AUXCMD3_FILE "\\\\.\\xillybus_auxcmd3_membank_16" -#else -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#define Open open -#define Seek lseek -#define Read read -#define Write write -#define Close close -#define CONTROL_FILE "/dev/xillybus_control_regs_16" -#define STATUS_FILE "/dev/xillybus_status_regs_16" -#define FIFO_FILE "/dev/xillybus_neural_data_32" -#define AUXCMD1_FILE "/dev/xillybus_auxcmd1_membank_16" -#define AUXCMD2_FILE "/dev/xillybus_auxcmd2_membank_16" -#define AUXCMD3_FILE "/dev/xillybus_auxcmd3_membank_16" -#ifndef O_BINARY -#define O_BINARY 0 -#endif -#endif -#include <fcntl.h> - -#include "rhd2000datablock.h" -using namespace PCIeRhythm; - -rhd2000PCIe::rhd2000PCIe() -{ - int i; - sampleRate = SampleRate30000Hz; // Rhythm FPGA boots up with 30.0 kS/s/channel sampling rate - numDataStreams = 0; - fidControl = -1; - fidStatus = -1; - fidFIFO = -1; - - for (i = 0; i < MAX_NUM_DATA_STREAMS; ++i) { - dataStreamEnabled[i] = 0; - } - - cableDelay.resize(4, -1); -} - - -rhd2000PCIe::~rhd2000PCIe() -{ - if (fidControl >= 0) - Close(fidControl); - if (fidStatus >= 0) - Close(fidStatus); - if (fidFIFO >= 0) - Close(fidFIFO); -} - -void rhd2000PCIe::writeRegister(controlAddr reg, uint16_t value, uint16_t mask) -{ - int regAddr = static_cast<int>(reg); - - if (Seek(fidControl, regAddr, SEEK_SET) < 0) - { - std::cerr << "Error seeking control to addr " << regAddr << std::endl; - return; - } - - uint16_t writeVal; - uint16_t curVal = 0x1010; //an easily recognizable value, to distinguish it from an actual read value of zero in debug strings - if ((mask & 0xFFFF) != 0xFFFF) - { - - int rd = Read(fidControl, &curVal, 2); - if (rd < 2) - { - std::cerr << "Unsuccesful read to control addr " << regAddr << " code: " << rd << std::endl; - return; - } - if (Seek(fidControl, regAddr, SEEK_SET) < 0) - { - std::cerr << "Error re-seeking control to addr " << regAddr << std::endl; - return; - } - writeVal = (curVal & ~mask) | (value & mask); - } - else - writeVal = value; - - int wd = Write(fidControl, &writeVal, 2); - if (wd < 2) - { - std::cerr << "Unsuccesful write to control addr " << regAddr << " code: " << wd << std::endl; - return; - } -// printf("Written registry %X val: %X mask: %X\n original: %X written: %X\n", reg, value, -// mask, curVal, writeVal); //Debug line -} - -uint16_t rhd2000PCIe::readRegister(statusAddr reg) const -{ - int16_t value = -1; - int regAddr = static_cast<int>(reg); - if (Seek(fidStatus, regAddr, SEEK_SET) < 0) - { - std::cerr << "Error seeking status to addr " << regAddr << std::endl; - return value; - } - int rd = Read(fidStatus, &value, 2); - if (rd < 2) - { - std::cerr << "Unsuccesful read to status addr " << regAddr << " code: " << rd << std::endl; - return value; - } - return value; -} - -bool rhd2000PCIe::openBoard() -{ - fidControl = Open(CONTROL_FILE, O_RDWR | O_BINARY); - if (fidControl < 0) - { - std::cerr << "Error opening control file " << std::endl; - return false; - } - - fidStatus = Open(STATUS_FILE, O_RDONLY | O_BINARY); - if (fidStatus < 0) - { - std::cerr << "Error opening status file" << std::endl; - Close(fidControl); - fidControl = -1; - return false; - } - - std::cout << "Device files opened" << std::endl; - return true; -} - -bool rhd2000PCIe::openPipe() -{ - fidFIFO = Open(FIFO_FILE, O_RDONLY | O_BINARY); - if (fidFIFO < 0) - { - std:cerr << "Error opening data FIFO" << std::endl; - return false; - } - std::cout << "Pipe opened" << std::endl; - return true; -} - -void rhd2000PCIe::closePipe() -{ - if (fidFIFO >= 0) - { - Close(fidFIFO); - fidFIFO = -1; - std::cout << "Pipe closed" << std::endl; - } - else - std::cerr << "ERROR: pipe already closed" << std::endl; -} - -// Initialize Rhythm FPGA to default starting values. -void rhd2000PCIe::initialize() -{ - int i; - - //resetBoard(); - setSampleRate(SampleRate30000Hz); - selectAuxCommandBank(PortA, AuxCmd1, 0); - selectAuxCommandBank(PortB, AuxCmd1, 0); - selectAuxCommandBank(PortC, AuxCmd1, 0); - selectAuxCommandBank(PortD, AuxCmd1, 0); - selectAuxCommandBank(PortA, AuxCmd2, 0); - selectAuxCommandBank(PortB, AuxCmd2, 0); - selectAuxCommandBank(PortC, AuxCmd2, 0); - selectAuxCommandBank(PortD, AuxCmd2, 0); - selectAuxCommandBank(PortA, AuxCmd3, 0); - selectAuxCommandBank(PortB, AuxCmd3, 0); - selectAuxCommandBank(PortC, AuxCmd3, 0); - selectAuxCommandBank(PortD, AuxCmd3, 0); - selectAuxCommandLength(AuxCmd1, 0, 0); - selectAuxCommandLength(AuxCmd2, 0, 0); - selectAuxCommandLength(AuxCmd3, 0, 0); - setContinuousRunMode(true); - setMaxTimeStep(4294967295); // 4294967295 == (2^32 - 1) - - setCableLengthFeet(PortA, 3.0); // assume 3 ft cables - setCableLengthFeet(PortB, 3.0); - setCableLengthFeet(PortC, 3.0); - setCableLengthFeet(PortD, 3.0); - - setDspSettle(false); - - setDataSource(0, PortA1); - setDataSource(1, PortB1); - setDataSource(2, PortC1); - setDataSource(3, PortD1); - setDataSource(4, PortA2); - setDataSource(5, PortB2); - setDataSource(6, PortC2); - setDataSource(7, PortD2); - setDataSource(8, PortA1); - setDataSource(9, PortB1); - setDataSource(10, PortC1); - setDataSource(11, PortD1); - setDataSource(12, PortA2); - setDataSource(13, PortB2); - setDataSource(14, PortC2); - setDataSource(15, PortD2); - - enableDataStream(0, true); // start with only one data stream enabled - for (i = 1; i < MAX_NUM_DATA_STREAMS; i++) { - enableDataStream(i, false); - } -} - -void rhd2000PCIe::resetBoard() -{ - writeRegister(ResetRun, 0x1, 0x1); - writeRegister(ResetRun, 0x0, 0x1); -} - -// Set the per-channel sampling rate of the RHD2000 chips connected to the FPGA. -bool rhd2000PCIe::setSampleRate(AmplifierSampleRate newSampleRate) -{ - // Assuming a 100 MHz reference clock is provided to the FPGA, the programmable FPGA clock frequency - // is given by: - // - // FPGA internal clock frequency = 100 MHz * (M/D) / 2 - // - // M and D are "multiply" and "divide" integers used in the FPGA's digital clock manager (DCM) phase- - // locked loop (PLL) frequency synthesizer, and are subject to the following restrictions: - // - // M must have a value in the range of 2 - 256 - // D must have a value in the range of 1 - 256 - // M/D must fall in the range of 0.05 - 3.33 - // - // (See pages 85-86 of Xilinx document UG382 "Spartan-6 FPGA Clocking Resources" for more details.) - // - // This variable-frequency clock drives the state machine that controls all SPI communication - // with the RHD2000 chips. A complete SPI cycle (consisting of one CS pulse and 16 SCLK pulses) - // takes 80 clock cycles. The SCLK period is 4 clock cycles; the CS pulse is high for 14 clock - // cycles between commands. - // - // Rhythm samples all 32 channels and then executes 3 "auxiliary" commands that can be used to read - // and write from other registers on the chip, or to sample from the temperature sensor or auxiliary ADC - // inputs, for example. Therefore, a complete cycle that samples from each amplifier channel takes - // 80 * (32 + 3) = 80 * 35 = 2800 clock cycles. - // - // So the per-channel sampling rate of each amplifier is 2800 times slower than the clock frequency. - // - // Based on these design choices, we can use the following values of M and D to generate the following - // useful amplifier sampling rates for electrophsyiological applications: - // - // M D clkout frequency per-channel sample rate per-channel sample period - // --- --- ---------------- ----------------------- ------------------------- - // 7 125 2.80 MHz 1.00 kS/s 1000.0 usec = 1.0 msec - // 7 100 3.50 MHz 1.25 kS/s 800.0 usec - // 21 250 4.20 MHz 1.50 kS/s 666.7 usec - // 14 125 5.60 MHz 2.00 kS/s 500.0 usec - // 35 250 7.00 MHz 2.50 kS/s 400.0 usec - // 21 125 8.40 MHz 3.00 kS/s 333.3 usec - // 14 75 9.33 MHz 3.33 kS/s 300.0 usec - // 28 125 11.20 MHz 4.00 kS/s 250.0 usec - // 7 25 14.00 MHz 5.00 kS/s 200.0 usec - // 7 20 17.50 MHz 6.25 kS/s 160.0 usec - // 112 250 22.40 MHz 8.00 kS/s 125.0 usec - // 14 25 28.00 MHz 10.00 kS/s 100.0 usec - // 7 10 35.00 MHz 12.50 kS/s 80.0 usec - // 21 25 42.00 MHz 15.00 kS/s 66.7 usec - // 28 25 56.00 MHz 20.00 kS/s 50.0 usec - // 35 25 70.00 MHz 25.00 kS/s 40.0 usec - // 42 25 84.00 MHz 30.00 kS/s 33.3 usec - // - // To set a new clock frequency, assert new values for M and D (e.g., using okWireIn modules) and - // pulse DCM_prog_trigger high (e.g., using an okTriggerIn module). If this module is reset, it - // reverts to a per-channel sampling rate of 30.0 kS/s. - - unsigned long M, O, D; - D = 0; - switch (newSampleRate) { - case SampleRate1000Hz: - M = 7; - O = 125; - break; - case SampleRate1250Hz: - M = 7; - O = 100; - break; - case SampleRate1500Hz: - M = 21; - O = 125; - D = 0x8000; - break; - case SampleRate2000Hz: - M = 14; - O = 125; - break; - case SampleRate2500Hz: - M = 35; - O = 125; - D = 0x8000; - break; - case SampleRate3000Hz: - M = 21; - O = 125; - break; - case SampleRate3333Hz: - M = 14; - O = 75; - break; - case SampleRate4000Hz: - M = 28; - O = 125; - break; - case SampleRate5000Hz: - M = 7; - O = 25; - break; - case SampleRate6250Hz: - M = 7; - O = 20; - break; - case SampleRate8000Hz: - M = 56; - O = 125; - break; - case SampleRate10000Hz: - M = 14; - O = 25; - break; - case SampleRate12500Hz: - M = 7; - O = 10; - break; - case SampleRate15000Hz: - M = 21; - O = 25; - break; - case SampleRate20000Hz: - M = 28; - O = 25; - break; - case SampleRate25000Hz: - M = 35; - O = 25; - break; - case SampleRate30000Hz: - M = 42; - O = 25; - break; - default: - return(false); - } - - sampleRate = newSampleRate; - - // Wait for DcmProgDone = 1 before reprogramming clock synthesizer - while (isDcmProgDone() == false) {} - - // Reprogram clock synthesizer - writeRegister(DataFreqPll, D + ((M << 8) & 0x7F00) + (O & 0x00FF)); - - // Wait for DataClkLocked = 1 before allowing data acquisition to continue - while (isDataClockLocked() == false) {} - - return(true); -} - -double rhd2000PCIe::getSampleRate() const -{ - switch (sampleRate) { - case SampleRate1000Hz: - return 1000.0; - break; - case SampleRate1250Hz: - return 1250.0; - break; - case SampleRate1500Hz: - return 1500.0; - break; - case SampleRate2000Hz: - return 2000.0; - break; - case SampleRate2500Hz: - return 2500.0; - break; - case SampleRate3000Hz: - return 3000.0; - break; - case SampleRate3333Hz: - return (10000.0 / 3.0); - break; - case SampleRate4000Hz: - return 4000.0; - break; - case SampleRate5000Hz: - return 5000.0; - break; - case SampleRate6250Hz: - return 6250.0; - break; - case SampleRate8000Hz: - return 8000.0; - break; - case SampleRate10000Hz: - return 10000.0; - break; - case SampleRate12500Hz: - return 12500.0; - break; - case SampleRate15000Hz: - return 15000.0; - break; - case SampleRate20000Hz: - return 20000.0; - break; - case SampleRate25000Hz: - return 25000.0; - break; - case SampleRate30000Hz: - return 30000.0; - break; - default: - return -1.0; - } -} - -rhd2000PCIe::AmplifierSampleRate rhd2000PCIe::getSampleRateEnum() const -{ - return sampleRate; -} - -// Upload an auxiliary command list to a particular command slot (AuxCmd1, AuxCmd2, or AuxCmd3) and RAM bank (0-15) -// on the FPGA. -void rhd2000PCIe::uploadCommandList(const vector<int> &commandList, AuxCmdSlot auxCommandSlot, int bank) -{ - unsigned int i; - const char* devFile; - int bankPos; - - if (auxCommandSlot != AuxCmd1 && auxCommandSlot != AuxCmd2 && auxCommandSlot != AuxCmd3) { - cerr << "Error in Rhd2000EvalBoard::uploadCommandList: auxCommandSlot out of range." << endl; - return; - } - - if (bank < 0 || bank > 15) { - cerr << "Error in Rhd2000EvalBoard::uploadCommandList: bank out of range." << endl; - return; - } - - switch (auxCommandSlot) - { - case AuxCmd1: - devFile = AUXCMD1_FILE; - break; - case AuxCmd2: - devFile = AUXCMD2_FILE; - break; - case AuxCmd3: - devFile = AUXCMD3_FILE; - break; - default: - devFile = ""; - } - bankPos = 2048 * bank; - int fidMem = Open(devFile, O_WRONLY | O_BINARY); - if (fidMem < 0) - { - std::cerr << "Error opening auxcmd device " << auxCommandSlot << std::endl; - return; - } - if (Seek(fidMem, bankPos, SEEK_SET) < 0) - { - std::cerr << "Error seeking auxcmd " << auxCommandSlot << " to addr " << bankPos << std::endl; - Close(fidMem); - return; - } - - for (i = 0; i < commandList.size(); ++i) { - int16_t value = commandList[i]; - int wd = Write(fidMem, &value, 2); - if (wd < 2) - { - std::cerr << "Error writing auxcmd " << auxCommandSlot << " index " << i << std::endl; - } - } - Close(fidMem); -} - -// Select an auxiliary command slot (AuxCmd1, AuxCmd2, or AuxCmd3) and bank (0-15) for a particular SPI port -// (PortA, PortB, PortC, or PortD) on the FPGA. -void rhd2000PCIe::selectAuxCommandBank(BoardPort port, AuxCmdSlot auxCommandSlot, int bank) -{ - int bitShift; - - if (auxCommandSlot != AuxCmd1 && auxCommandSlot != AuxCmd2 && auxCommandSlot != AuxCmd3) { - cerr << "Error in Rhd2000EvalBoard::selectAuxCommandBank: auxCommandSlot out of range." << endl; - return; - } - if (bank < 0 || bank > 15) { - cerr << "Error in Rhd2000EvalBoard::selectAuxCommandBank: bank out of range." << endl; - return; - } - - switch (port) { - case PortA: - bitShift = 0; - break; - case PortB: - bitShift = 4; - break; - case PortC: - bitShift = 8; - break; - case PortD: - bitShift = 12; - break; - } - - switch (auxCommandSlot) { - case AuxCmd1: - writeRegister(AuxCmdBank1, bank << bitShift, 0x000f << bitShift); - break; - case AuxCmd2: - writeRegister(AuxCmdBank2, bank << bitShift, 0x000f << bitShift); - break; - case AuxCmd3: - writeRegister(AuxCmdBank3, bank << bitShift, 0x000f << bitShift); - break; - } -} - -// Specify a command sequence length (endIndex = 0-1023) and command loop index (0-1023) for a particular -// auxiliary command slot (AuxCmd1, AuxCmd2, or AuxCmd3). -void rhd2000PCIe::selectAuxCommandLength(AuxCmdSlot auxCommandSlot, int loopIndex, int endIndex) -{ - if (auxCommandSlot != AuxCmd1 && auxCommandSlot != AuxCmd2 && auxCommandSlot != AuxCmd3) { - cerr << "Error in Rhd2000EvalBoard::selectAuxCommandLength: auxCommandSlot out of range." << endl; - return; - } - - if (loopIndex < 0 || loopIndex > 1023) { - cerr << "Error in Rhd2000EvalBoard::selectAuxCommandLength: loopIndex out of range." << endl; - return; - } - - if (endIndex < 0 || endIndex > 1023) { - cerr << "Error in Rhd2000EvalBoard::selectAuxCommandLength: endIndex out of range." << endl; - return; - } - - switch (auxCommandSlot) { - case AuxCmd1: - writeRegister(AuxCmdLoop1, loopIndex); - writeRegister(AuxCmdLength1, endIndex); - break; - case AuxCmd2: - writeRegister(AuxCmdLoop2, loopIndex); - writeRegister(AuxCmdLength2, endIndex); - break; - case AuxCmd3: - writeRegister(AuxCmdLoop3, loopIndex); - writeRegister(AuxCmdLength3, endIndex); - break; - } -} - -// Set the FPGA to run continuously once started (if continuousMode == true) or to run until -// maxTimeStep is reached (if continuousMode == false). -void rhd2000PCIe::setContinuousRunMode(bool continuousMode) -{ - if (continuousMode) { - writeRegister(ResetRun, 0x02, 0x2); - } - else { - writeRegister(ResetRun, 0x00, 0x2); - } -} - -void rhd2000PCIe::setMaxTimeStep(unsigned int maxTimeStep) -{ - unsigned int maxTimeStepLsb, maxTimeStepMsb; - - maxTimeStepLsb = maxTimeStep & 0x0000ffff; - maxTimeStepMsb = maxTimeStep & 0xffff0000; - - writeRegister(MaxTimeStepLsb, maxTimeStepLsb); - writeRegister(MaxTimeStepMsb, maxTimeStepMsb >> 16); -} - -// Initiate SPI data acquisition. -void rhd2000PCIe::run() -{ - writeRegister(StartTrigger, 0x1); -} - -// Is the FPGA currently running? -bool rhd2000PCIe::isRunning() const -{ - int value; - - value = readRegister(SpiRunning); - - if ((value & 0x01) == 0) { - return false; - } - else { - return true; - } -} - -// Set the delay for sampling the MISO line on a particular SPI port (PortA - PortD), in integer clock -// steps, where each clock step is 1/2800 of a per-channel sampling period. -// Note: Cable delay must be updated after sampleRate is changed, since cable delay calculations are -// based on the clock frequency! -void rhd2000PCIe::setCableDelay(BoardPort port, int delay) -{ - int bitShift; - - if (delay < 0 || delay > 15) { - cerr << "Warning in Rhd2000EvalBoard::setCableDelay: delay out of range: " << delay << endl; - } - - if (delay < 0) delay = 0; - if (delay > 15) delay = 15; - - switch (port) { - case PortA: - bitShift = 0; - cableDelay[0] = delay; - break; - case PortB: - bitShift = 4; - cableDelay[1] = delay; - break; - case PortC: - bitShift = 8; - cableDelay[2] = delay; - break; - case PortD: - bitShift = 12; - cableDelay[3] = delay; - break; - default: - cerr << "Error in RHD2000EvalBoard::setCableDelay: unknown port." << endl; - } - - writeRegister(MisoDelay, delay << bitShift, 0x000f << bitShift); -} - -// Set the delay for sampling the MISO line on a particular SPI port (PortA - PortD) based on the length -// of the cable between the FPGA and the RHD2000 chip (in meters). -// Note: Cable delay must be updated after sampleRate is changed, since cable delay calculations are -// based on the clock frequency! -void rhd2000PCIe::setCableLengthMeters(BoardPort port, double lengthInMeters) -{ - int delay; - double tStep, cableVelocity, distance, timeDelay; - const double speedOfLight = 299792458.0; // units = meters per second - const double xilinxLvdsOutputDelay = 1.9e-9; // 1.9 ns Xilinx LVDS output pin delay - const double xilinxLvdsInputDelay = 1.4e-9; // 1.4 ns Xilinx LVDS input pin delay - const double rhd2000Delay = 9.0e-9; // 9.0 ns RHD2000 SCLK-to-MISO delay - const double misoSettleTime = 6.7e-9; // 6.7 ns delay after MISO changes, before we sample it - - tStep = 1.0 / (2800.0 * getSampleRate()); // data clock that samples MISO has a rate 35 x 80 = 2800x higher than the sampling rate - // cableVelocity = 0.67 * speedOfLight; // propogation velocity on cable: version 1.3 and earlier - cableVelocity = 0.555 * speedOfLight; // propogation velocity on cable: version 1.4 improvement based on cable measurements - distance = 2.0 * lengthInMeters; // round trip distance data must travel on cable - timeDelay = (distance / cableVelocity) + xilinxLvdsOutputDelay + rhd2000Delay + xilinxLvdsInputDelay + misoSettleTime; - - delay = (int)floor(((timeDelay / tStep) + 1.0) + 0.5); - - if (delay < 1) delay = 1; // delay of zero is too short (due to I/O delays), even for zero-length cables - - setCableDelay(port, delay); -} - -// Same function as above, but accepts lengths in feet instead of meters -void rhd2000PCIe::setCableLengthFeet(BoardPort port, double lengthInFeet) -{ - setCableLengthMeters(port, 0.3048 * lengthInFeet); // convert feet to meters -} - -// Estimate cable length based on a particular delay used in setCableDelay. -// (Note: Depends on sample rate.) -double rhd2000PCIe::estimateCableLengthMeters(int delay) const -{ - double tStep, cableVelocity, distance; - const double speedOfLight = 299792458.0; // units = meters per second - const double xilinxLvdsOutputDelay = 1.9e-9; // 1.9 ns Xilinx LVDS output pin delay - const double xilinxLvdsInputDelay = 1.4e-9; // 1.4 ns Xilinx LVDS input pin delay - const double rhd2000Delay = 9.0e-9; // 9.0 ns RHD2000 SCLK-to-MISO delay - const double misoSettleTime = 6.7e-9; // 6.7 ns delay after MISO changes, before we sample it - - tStep = 1.0 / (2800.0 * getSampleRate()); // data clock that samples MISO has a rate 35 x 80 = 2800x higher than the sampling rate - // cableVelocity = 0.67 * speedOfLight; // propogation velocity on cable: version 1.3 and earlier - cableVelocity = 0.555 * speedOfLight; // propogation velocity on cable: version 1.4 improvement based on cable measurements - - // distance = cableVelocity * (delay * tStep - (xilinxLvdsOutputDelay + rhd2000Delay + xilinxLvdsInputDelay)); // version 1.3 and earlier - distance = cableVelocity * ((((double)delay) - 1.0) * tStep - (xilinxLvdsOutputDelay + rhd2000Delay + xilinxLvdsInputDelay + misoSettleTime)); // version 1.4 improvement - if (distance < 0.0) distance = 0.0; - - return (distance / 2.0); -} - -// Same function as above, but returns length in feet instead of meters -double rhd2000PCIe::estimateCableLengthFeet(int delay) const -{ - return 3.2808 * estimateCableLengthMeters(delay); -} - -// Turn on or off DSP settle function in the FPGA. (Only executes when CONVERT commands are sent.) -void rhd2000PCIe::setDspSettle(bool enabled) -{ - writeRegister(ResetRun, (enabled ? 0x04 : 0x00), 0x04); -} - -// Assign a particular data source (e.g., PortA1, PortA2, PortB1,...) to one of the eight -// available USB data streams (0-7). -void rhd2000PCIe::setDataSource(int stream, BoardDataSource dataSource) -{ - int bitShift; - controlAddr endPoint; - - if (stream < 0 || stream >(MAX_NUM_DATA_STREAMS - 1)) { - cerr << "Error in Rhd2000EvalBoard::setDataSource: stream out of range." << endl; - return; - } - - switch (stream) { - case 0: - endPoint = DataStreamSel1234; - bitShift = 0; - break; - case 1: - endPoint = DataStreamSel1234; - bitShift = 4; - break; - case 2: - endPoint = DataStreamSel1234; - bitShift = 8; - break; - case 3: - endPoint = DataStreamSel1234; - bitShift = 12; - break; - case 4: - endPoint = DataStreamSel5678; - bitShift = 0; - break; - case 5: - endPoint = DataStreamSel5678; - bitShift = 4; - break; - case 6: - endPoint = DataStreamSel5678; - bitShift = 8; - break; - case 7: - endPoint = DataStreamSel5678; - bitShift = 12; - break; - case 8: - endPoint = DataStreamSel9ABC; - bitShift = 0; - break; - case 9: - endPoint = DataStreamSel9ABC; - bitShift = 4; - break; - case 10: - endPoint = DataStreamSel9ABC; - bitShift = 8; - break; - case 11: - endPoint = DataStreamSel9ABC; - bitShift = 12; - break; - case 12: - endPoint = DataStreamSelDEF10; - bitShift = 0; - break; - case 13: - endPoint = DataStreamSelDEF10; - bitShift = 4; - break; - case 14: - endPoint = DataStreamSelDEF10; - bitShift = 8; - break; - case 15: - endPoint = DataStreamSelDEF10; - bitShift = 12; - break; - } - - writeRegister(endPoint, dataSource << bitShift, 0x000f << bitShift); -} - -// Enable or disable one of the eight available USB data streams (0-7). -void rhd2000PCIe::enableDataStream(int stream, bool enabled) -{ - if (stream < 0 || stream >(MAX_NUM_DATA_STREAMS - 1)) { - cerr << "Error in Rhd2000EvalBoard::setDataSource: stream out of range." << endl; - return; - } - - if (enabled) { - if (dataStreamEnabled[stream] == 0) { - writeRegister(DataStreamEn, 0x0001 << stream, 0x0001 << stream); - dataStreamEnabled[stream] = 1; - ++numDataStreams; - } - } - else { - if (dataStreamEnabled[stream] == 1) { - writeRegister(DataStreamEn, 0x0000 << stream, 0x0001 << stream); - dataStreamEnabled[stream] = 0; - numDataStreams--; - } - } -} - -// Returns the number of enabled data streams. -int rhd2000PCIe::getNumEnabledDataStreams() const -{ - return numDataStreams; -} - -// Is variable-frequency clock DCM programming done? -bool rhd2000PCIe::isDcmProgDone() const -{ - int value; - - value = readRegister(DataClkLocked); - - return ((value & 0x0002) > 1); -} - -// Is variable-frequency clock PLL locked? -bool rhd2000PCIe::isDataClockLocked() const -{ - int value; - - value = readRegister(DataClkLocked); - - return ((value & 0x0001) > 0); -} - -// Return FPGA cable delay for selected SPI port. -int rhd2000PCIe::getCableDelay(BoardPort port) const -{ - switch (port) { - case PortA: - return cableDelay[0]; - case PortB: - return cableDelay[1]; - case PortC: - return cableDelay[2]; - case PortD: - return cableDelay[3]; - default: - cerr << "Error in RHD2000EvalBoard::getCableDelay: unknown port." << endl; - return -1; - } -} - -// Return FPGA cable delays for all SPI ports. -void rhd2000PCIe::getCableDelay(vector<int> &delays) const -{ - if (delays.size() != 4) { - delays.resize(4); - } - for (int i = 0; i < 4; ++i) { - delays[i] = cableDelay[i]; - } -} - -bool rhd2000PCIe::isStreamEnabled(int streamIndex) -{ - if (streamIndex < 0 || streamIndex >(MAX_NUM_DATA_STREAMS - 1)) - return false; - - return dataStreamEnabled[streamIndex]; -} - -bool rhd2000PCIe::readRawDataBlock(unsigned char** bufferPtr, int nSamples) -{ - unsigned int numBytesToRead; - unsigned int numread = 0; - - numBytesToRead = 2 * Rhd2000DataBlock::calculateDataBlockSizeInWords(numDataStreams, nSamples); - - if (numBytesToRead > DATA_BUFFER_SIZE) { - cerr << "Error in rhd2000PCIe::readRawDataBlock: Data buffer size exceeded. " << - "Increase value of DATA_BUFFER_SIZE." << endl; - *bufferPtr = nullptr; - return false; - } - - do { - int nr = Read(fidFIFO, dataBuffer + numread, numBytesToRead - numread); - - - if (nr == 0) - { - std::cout << "DMA buffer overflow. Stop acquisition" << std::endl; - return false; - } - else if (nr < 0) - { - std::cerr << "Error reading from pipe" << std::endl; - return false; - } - numread += nr; - } while (numread < numBytesToRead); - - *bufferPtr = dataBuffer; - return true; -} -/* -void rhd2000PCIe::flush() -{ -int nr = 0; -do -{ -nr = Read(fidFIFO, &dataBuffer, DATA_BUFFER_SIZE); - -} while (nr > 0); - -}*/ - -// Read data block from the USB interface, if one is available. Returns true if data block -// was available. -bool rhd2000PCIe::readDataBlock(Rhd2000DataBlock *dataBlock, int nSamples) -{ - unsigned int numBytesToRead; - long res; - unsigned int numread = 0; - - numBytesToRead = 2 * dataBlock->calculateDataBlockSizeInWords(numDataStreams, nSamples); - //std::cout << "To read: " << numBytesToRead << std::endl; - - if (numBytesToRead > DATA_BUFFER_SIZE) { - cerr << "Error in rhd2000PCIe::readDataBlock: Data buffer size exceeded. " << - "Increase value of DATA_BUFFER_SIZE." << endl; - return false; - } - - do { - int nr = Read(fidFIFO, dataBuffer + numread, numBytesToRead - numread); - - if (nr == 0) - { - std::cout << "DMA buffer overflow. Stop acquisition" << std::endl; - return false; - } - else if (nr < 0) - { - std::cerr << "Error reading from pipe" << std::endl; - return false; - } - numread += nr; - //std::cout << "Read: " << nr << " total: " << numread << " left: " << numBytesToRead - numread << std::endl; - } while (numread < numBytesToRead); - - - dataBlock->fillFromUsbBuffer(dataBuffer, 0, numDataStreams, nSamples); - - return true; -} - -// Reads a certain number of USB data blocks, if the specified number is available, and appends them -// to queue. Returns true if data blocks were available. -bool rhd2000PCIe::readDataBlocks(int numBlocks, queue<Rhd2000DataBlock> &dataQueue, int nSamples) -{ - unsigned int numWordsToRead, numBytesToRead; - int i; - unsigned int numread = 0; - Rhd2000DataBlock *dataBlock; - - if (nSamples < 1) nSamples = SAMPLES_PER_DATA_BLOCK_PCIE; - - numWordsToRead = numBlocks * dataBlock->calculateDataBlockSizeInWords(numDataStreams, nSamples); - - - numBytesToRead = 2 * numWordsToRead; - - if (numBytesToRead > DATA_BUFFER_SIZE) { - cerr << "Error in rhd2000PCIe::readDataBlocks: Data buffer size exceeded. " << - "Increase value of DATA_BUFFER_SIZE." << endl; - return false; - } - - do { - int nr = Read(fidFIFO, dataBuffer + numread, numBytesToRead - numread); - - if (nr == 0) - { - std::cout << "DMA buffer overflow. Stop acquisition" << std::endl; - return false; - - } - else if (nr < 0) - { - std::cerr << "Error reading from pipe" << std::endl; - return false; - } - numread += nr; - } while (numread < numBytesToRead); - - dataBlock = new Rhd2000DataBlock(numDataStreams, nSamples); - for (i = 0; i < numBlocks; ++i) { - dataBlock->fillFromUsbBuffer(dataBuffer, i, numDataStreams); - dataQueue.push(*dataBlock); - } - delete dataBlock; - - return true; -} - -void rhd2000PCIe::setOuputSigs(int sigs) -{ - writeRegister(AuxOutputs, sigs); -} diff --git a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000PCIe.h b/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000PCIe.h deleted file mode 100644 index 4de6ac73ecd23215f0e529d0d01615ce39c15e7f..0000000000000000000000000000000000000000 --- a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000PCIe.h +++ /dev/null @@ -1,170 +0,0 @@ -#ifndef RHD2000PCIE_H -#define RHD2000PCIE_H - -#include <vector> -#include <cstdint> -#include <queue> - -#define MAX_NUM_DATA_STREAMS 16 -#define DATA_BUFFER_SIZE 2560000 - -using namespace std; - -namespace PCIeRhythm { - class Rhd2000DataBlock; - - class rhd2000PCIe - { - public: - rhd2000PCIe(); - ~rhd2000PCIe(); - - enum AmplifierSampleRate { - SampleRate1000Hz, - SampleRate1250Hz, - SampleRate1500Hz, - SampleRate2000Hz, - SampleRate2500Hz, - SampleRate3000Hz, - SampleRate3333Hz, - SampleRate4000Hz, - SampleRate5000Hz, - SampleRate6250Hz, - SampleRate8000Hz, - SampleRate10000Hz, - SampleRate12500Hz, - SampleRate15000Hz, - SampleRate20000Hz, - SampleRate25000Hz, - SampleRate30000Hz - }; - - enum BoardDataSource { - PortA1 = 0, - PortA2 = 1, - PortB1 = 2, - PortB2 = 3, - PortC1 = 4, - PortC2 = 5, - PortD1 = 6, - PortD2 = 7, - PortA1Ddr = 8, - PortA2Ddr = 9, - PortB1Ddr = 10, - PortB2Ddr = 11, - PortC1Ddr = 12, - PortC2Ddr = 13, - PortD1Ddr = 14, - PortD2Ddr = 15 - }; - - enum AuxCmdSlot { - AuxCmd1, - AuxCmd2, - AuxCmd3 - }; - - enum BoardPort { - PortA, - PortB, - PortC, - PortD - }; - - bool openBoard(); - void initialize(); - void resetBoard(); - - bool setSampleRate(AmplifierSampleRate newSampleRate); - double getSampleRate() const; - AmplifierSampleRate getSampleRateEnum() const; - - void uploadCommandList(const vector<int> &commandList, AuxCmdSlot auxCommandSlot, int bank); - void selectAuxCommandBank(BoardPort port, AuxCmdSlot auxCommandSlot, int bank); - void selectAuxCommandLength(AuxCmdSlot auxCommandSlot, int loopIndex, int endIndex); - - void setContinuousRunMode(bool continuousMode); - void setMaxTimeStep(unsigned int maxTimeStep); - - void run(); - bool isRunning() const; - - void setCableDelay(BoardPort port, int delay); - void setCableLengthMeters(BoardPort port, double lengthInMeters); - void setCableLengthFeet(BoardPort port, double lengthInFeet); - double estimateCableLengthMeters(int delay) const; - double estimateCableLengthFeet(int delay) const; - - void setDspSettle(bool enabled); - - void setDataSource(int stream, BoardDataSource dataSource); - void enableDataStream(int stream, bool enabled); - int getNumEnabledDataStreams() const; - - int getCableDelay(BoardPort port) const; - void getCableDelay(vector<int> &delays) const; - bool isStreamEnabled(int streamIndex); - - bool readRawDataBlock(unsigned char** bufferPtr, int nSamples = -1); - bool readDataBlock(Rhd2000DataBlock *dataBlock, int nSamples = -1); - bool readDataBlocks(int numBlocks, queue<Rhd2000DataBlock> &dataQueue, int nSamples = -1); - - bool openPipe(); - void closePipe(); - - void setOuputSigs(int sigs); - - //void flush(); - - - private: - int fidControl, fidStatus, fidFIFO; - - enum controlAddr { - ResetRun = 0x00, - MaxTimeStepLsb = 0x02, - MaxTimeStepMsb = 0x04, - DataFreqPll = 0x06, - MisoDelay = 0x08, - AuxCmdBank1 = 0x10, - AuxCmdBank2 = 0x12, - AuxCmdBank3 = 0x14, - AuxCmdLength1 = 0x16, - AuxCmdLength2 = 0x18, - AuxCmdLength3 = 0x1A, - AuxCmdLoop1 = 0x1C, - AuxCmdLoop2 = 0x1E, - AuxCmdLoop3 = 0x20, - DataStreamSel1234 = 0x24, - DataStreamSel5678 = 0x26, - DataStreamSel9ABC = 0x28, - DataStreamSelDEF10 = 0x2A, - DataStreamEn = 0x2C, - AuxOutputs = 0x2E, - StartTrigger = 0x3E - }; - enum statusAddr { - NumWordsLsb = 0x00, - NumWordsMsb = 0x02, - SpiRunning = 0x04, - DataClkLocked = 0x08, - BoardId = 0x0A, - BoardVersion = 0x0C - }; - - AmplifierSampleRate sampleRate; - int numDataStreams; // total number of data streams currently enabled - int dataStreamEnabled[MAX_NUM_DATA_STREAMS]; // 0 (disabled) or 1 (enabled), set for maximum stream number - vector<int> cableDelay; - - void writeRegister(controlAddr reg, uint16_t value, uint16_t mask = 0xFFFF); - uint16_t readRegister(statusAddr reg) const; - - bool isDcmProgDone() const; - bool isDataClockLocked() const; - - unsigned char dataBuffer[DATA_BUFFER_SIZE]; - - }; -}; -#endif // !RHD2000PCIE_H \ No newline at end of file diff --git a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000datablock.cpp b/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000datablock.cpp deleted file mode 100644 index 6d52e8b78ef80bd50f9a5f914f9bbfe102fc8054..0000000000000000000000000000000000000000 --- a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000datablock.cpp +++ /dev/null @@ -1,390 +0,0 @@ -//---------------------------------------------------------------------------------- -// rhd2000datablock.cpp -// -// Intan Technoloies RHD2000 Rhythm Interface API -// Rhd2000DataBlock Class -// Version 1.4 (26 February 2014) -// -// Copyright (c) 2013-2014 Intan Technologies LLC -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the -// use of this software. -// -// Permission is granted to anyone to use this software for any applications that -// use Intan Technologies integrated circuits, and to alter it and redistribute it -// freely. -// -// See http://www.intantech.com for documentation and product information. -//---------------------------------------------------------------------------------- - -#include <iostream> -#include <fstream> -#include <iomanip> -#include <vector> - -#include "rhd2000datablock.h" - -using namespace std; -using namespace PCIeRhythm; - -// This class creates a data structure storing SAMPLES_PER_DATA_BLOCK data frames -// from a Rhythm FPGA interface controlling up to eight RHD2000 chips. - -// Constructor. Allocates memory for data block. -Rhd2000DataBlock::Rhd2000DataBlock(int numDataStreams, int nSamples) : samplesPerBlock(nSamples) -{ - allocateUIntArray1D(timeStamp, samplesPerBlock); - allocateIntArray3D(amplifierData, numDataStreams, 32, samplesPerBlock); - allocateIntArray3D(auxiliaryData, numDataStreams, 3, samplesPerBlock); - allocateIntArray2D(boardAdcData, 8, samplesPerBlock); - allocateIntArray1D(ttlIn, samplesPerBlock); - allocateIntArray1D(ttlOut, samplesPerBlock); -} - -// Allocates memory for a 1-D array of integers. -void Rhd2000DataBlock::allocateIntArray1D(vector<int> &array1D, int xSize) -{ - array1D.resize(xSize); -} - -// Allocates memory for a 1-D array of unsigned integers. -void Rhd2000DataBlock::allocateUIntArray1D(vector<unsigned int> &array1D, int xSize) -{ - array1D.resize(xSize); -} - -// Allocates memory for a 2-D array of integers. -void Rhd2000DataBlock::allocateIntArray2D(vector<vector<int> > & array2D, int xSize, int ySize) -{ - int i; - - array2D.resize(xSize); - for (i = 0; i < xSize; ++i) - array2D[i].resize(ySize); -} - -// Allocates memory for a 3-D array of integers. -void Rhd2000DataBlock::allocateIntArray3D(vector<vector<vector<int> > > &array3D, int xSize, int ySize, int zSize) -{ - int i, j; - - array3D.resize(xSize); - for (i = 0; i < xSize; ++i) { - array3D[i].resize(ySize); - - for (j = 0; j < ySize; ++j) { - array3D[i][j].resize(zSize); - } - } -} - -// Returns the number of samples in a USB data block. -unsigned int Rhd2000DataBlock::getSamplesPerDataBlock() -{ - return SAMPLES_PER_DATA_BLOCK_PCIE; -} - -// Returns the number of 16-bit words in a USB data block with numDataStreams data streams enabled. -unsigned int Rhd2000DataBlock::calculateDataBlockSizeInWords(int numDataStreams, int nSamples) -{ - unsigned int samps = nSamples <= 0 ? SAMPLES_PER_DATA_BLOCK_PCIE : nSamples; - return samps * (4 + 2 + numDataStreams * 36 + 8 + 2); - // 4 = magic number; 2 = time stamp; 36 = (32 amp channels + 3 aux commands + 1 filler word); 8 = ADCs; 2 = TTL in/out -} - -// Check first 64 bits of USB header against the fixed Rhythm "magic number" to verify data sync. -bool Rhd2000DataBlock::checkUsbHeader(unsigned char usbBuffer[], int index) -{ - unsigned long long x1, x2, x3, x4, x5, x6, x7, x8; - unsigned long long header; - - x1 = usbBuffer[index]; - x2 = usbBuffer[index + 1]; - x3 = usbBuffer[index + 2]; - x4 = usbBuffer[index + 3]; - x5 = usbBuffer[index + 4]; - x6 = usbBuffer[index + 5]; - x7 = usbBuffer[index + 6]; - x8 = usbBuffer[index + 7]; - - header = (x8 << 56) + (x7 << 48) + (x6 << 40) + (x5 << 32) + (x4 << 24) + (x3 << 16) + (x2 << 8) + (x1 << 0); - - return (header == RHD2000_HEADER_MAGIC_NUMBER); -} - -// Read 32-bit time stamp from USB data frame. -unsigned int Rhd2000DataBlock::convertUsbTimeStamp(unsigned char usbBuffer[], int index) -{ - unsigned int x1, x2, x3, x4; - x1 = usbBuffer[index]; - x2 = usbBuffer[index + 1]; - x3 = usbBuffer[index + 2]; - x4 = usbBuffer[index + 3]; - - return (x4 << 24) + (x3 << 16) + (x2 << 8) + (x1 << 0); -} - -// Convert two USB bytes into 16-bit word. -int Rhd2000DataBlock::convertUsbWord(unsigned char usbBuffer[], int index) -{ - unsigned int x1, x2, result; - - x1 = (unsigned int) usbBuffer[index]; - x2 = (unsigned int) usbBuffer[index + 1]; - - result = (x2 << 8) | (x1 << 0); - - return (int) result; -} - -// Fill data block with raw data from USB input buffer. -void Rhd2000DataBlock::fillFromUsbBuffer(unsigned char usbBuffer[], int blockIndex, int numDataStreams, int nSamples) -{ - int index, t, channel, stream, i; - int samplesToRead = nSamples <= 0 ? samplesPerBlock : nSamples; - int num = 0; - - index = blockIndex * 2 * calculateDataBlockSizeInWords(numDataStreams, usb3); - for (t = 0; t < samplesToRead; ++t) { - if (!checkUsbHeader(usbBuffer, index)) { - cerr << "Error in Rhd2000EvalBoard::readDataBlock: Incorrect header." << endl; - break; - } - else - num++; - //else cerr << "Block ok" << endl; - index += 8; - timeStamp[t] = convertUsbTimeStamp(usbBuffer, index); - index += 4; - - // Read auxiliary results - for (channel = 0; channel < 3; ++channel) { - for (stream = 0; stream < numDataStreams; ++stream) { - auxiliaryData[stream][channel][t] = convertUsbWord(usbBuffer, index); - index += 2; - } - } - - // Read amplifier channels - for (channel = 0; channel < 32; ++channel) { - for (stream = 0; stream < numDataStreams; ++stream) { - amplifierData[stream][channel][t] = convertUsbWord(usbBuffer, index); - index += 2; - } - } - - // skip 36th filler word in each data stream - index += 2 * numDataStreams; - - // Read from AD5662 ADCs - for (i = 0; i < 8; ++i) { - boardAdcData[i][t] = convertUsbWord(usbBuffer, index); - index += 2; - } - - // Read TTL input and output values - ttlIn[t] = convertUsbWord(usbBuffer, index); - index += 2; - - ttlOut[t] = convertUsbWord(usbBuffer, index); - index += 2; - } - //cout << "Read " << num << " valid samples with " << numDataStreams << " streams. Usb mode status: " << usb3 << endl; -} - -// Print the contents of RHD2000 registers from a selected USB data stream (0-7) -// to the console. -void Rhd2000DataBlock::print(int stream) const -{ - const int RamOffset = 37; - - cout << endl; - cout << "RHD 2000 Data Block contents:" << endl; - cout << " ROM contents:" << endl; - cout << " Chip Name: " << - (char) auxiliaryData[stream][2][24] << - (char) auxiliaryData[stream][2][25] << - (char) auxiliaryData[stream][2][26] << - (char) auxiliaryData[stream][2][27] << - (char) auxiliaryData[stream][2][28] << - (char) auxiliaryData[stream][2][29] << - (char) auxiliaryData[stream][2][30] << - (char) auxiliaryData[stream][2][31] << endl; - cout << " Company Name:" << - (char) auxiliaryData[stream][2][32] << - (char) auxiliaryData[stream][2][33] << - (char) auxiliaryData[stream][2][34] << - (char) auxiliaryData[stream][2][35] << - (char) auxiliaryData[stream][2][36] << endl; - cout << " Intan Chip ID: " << auxiliaryData[stream][2][19] << endl; - cout << " Number of Amps: " << auxiliaryData[stream][2][20] << endl; - cout << " Unipolar/Bipolar Amps: "; - switch (auxiliaryData[stream][2][21]) { - case 0: - cout << "bipolar"; - break; - case 1: - cout << "unipolar"; - break; - default: - cout << "UNKNOWN"; - } - cout << endl; - cout << " Die Revision: " << auxiliaryData[stream][2][22] << endl; - cout << " Future Expansion Register: " << auxiliaryData[stream][2][23] << endl; - - cout << " RAM contents:" << endl; - cout << " ADC reference BW: " << ((auxiliaryData[stream][2][RamOffset + 0] & 0xc0) >> 6) << endl; - cout << " amp fast settle: " << ((auxiliaryData[stream][2][RamOffset + 0] & 0x20) >> 5) << endl; - cout << " amp Vref enable: " << ((auxiliaryData[stream][2][RamOffset + 0] & 0x10) >> 4) << endl; - cout << " ADC comparator bias: " << ((auxiliaryData[stream][2][RamOffset + 0] & 0x0c) >> 2) << endl; - cout << " ADC comparator select: " << ((auxiliaryData[stream][2][RamOffset + 0] & 0x03) >> 0) << endl; - cout << " VDD sense enable: " << ((auxiliaryData[stream][2][RamOffset + 1] & 0x40) >> 6) << endl; - cout << " ADC buffer bias: " << ((auxiliaryData[stream][2][RamOffset + 1] & 0x3f) >> 0) << endl; - cout << " MUX bias: " << ((auxiliaryData[stream][2][RamOffset + 2] & 0x3f) >> 0) << endl; - cout << " MUX load: " << ((auxiliaryData[stream][2][RamOffset + 3] & 0xe0) >> 5) << endl; - cout << " tempS2, tempS1: " << ((auxiliaryData[stream][2][RamOffset + 3] & 0x10) >> 4) << "," << - ((auxiliaryData[stream][2][RamOffset + 3] & 0x08) >> 3) << endl; - cout << " tempen: " << ((auxiliaryData[stream][2][RamOffset + 3] & 0x04) >> 2) << endl; - cout << " digout HiZ: " << ((auxiliaryData[stream][2][RamOffset + 3] & 0x02) >> 1) << endl; - cout << " digout: " << ((auxiliaryData[stream][2][RamOffset + 3] & 0x01) >> 0) << endl; - cout << " weak MISO: " << ((auxiliaryData[stream][2][RamOffset + 4] & 0x80) >> 7) << endl; - cout << " twoscomp: " << ((auxiliaryData[stream][2][RamOffset + 4] & 0x40) >> 6) << endl; - cout << " absmode: " << ((auxiliaryData[stream][2][RamOffset + 4] & 0x20) >> 5) << endl; - cout << " DSPen: " << ((auxiliaryData[stream][2][RamOffset + 4] & 0x10) >> 4) << endl; - cout << " DSP cutoff freq: " << ((auxiliaryData[stream][2][RamOffset + 4] & 0x0f) >> 0) << endl; - cout << " Zcheck DAC power: " << ((auxiliaryData[stream][2][RamOffset + 5] & 0x40) >> 6) << endl; - cout << " Zcheck load: " << ((auxiliaryData[stream][2][RamOffset + 5] & 0x20) >> 5) << endl; - cout << " Zcheck scale: " << ((auxiliaryData[stream][2][RamOffset + 5] & 0x18) >> 3) << endl; - cout << " Zcheck conn all: " << ((auxiliaryData[stream][2][RamOffset + 5] & 0x04) >> 2) << endl; - cout << " Zcheck sel pol: " << ((auxiliaryData[stream][2][RamOffset + 5] & 0x02) >> 1) << endl; - cout << " Zcheck en: " << ((auxiliaryData[stream][2][RamOffset + 5] & 0x01) >> 0) << endl; - cout << " Zcheck DAC: " << ((auxiliaryData[stream][2][RamOffset + 6] & 0xff) >> 0) << endl; - cout << " Zcheck select: " << ((auxiliaryData[stream][2][RamOffset + 7] & 0x3f) >> 0) << endl; - cout << " ADC aux1 en: " << ((auxiliaryData[stream][2][RamOffset + 9] & 0x80) >> 7) << endl; - cout << " ADC aux2 en: " << ((auxiliaryData[stream][2][RamOffset + 11] & 0x80) >> 7) << endl; - cout << " ADC aux3 en: " << ((auxiliaryData[stream][2][RamOffset + 13] & 0x80) >> 7) << endl; - cout << " offchip RH1: " << ((auxiliaryData[stream][2][RamOffset + 8] & 0x80) >> 7) << endl; - cout << " offchip RH2: " << ((auxiliaryData[stream][2][RamOffset + 10] & 0x80) >> 7) << endl; - cout << " offchip RL: " << ((auxiliaryData[stream][2][RamOffset + 12] & 0x80) >> 7) << endl; - - int rH1Dac1 = auxiliaryData[stream][2][RamOffset + 8] & 0x3f; - int rH1Dac2 = auxiliaryData[stream][2][RamOffset + 9] & 0x1f; - int rH2Dac1 = auxiliaryData[stream][2][RamOffset + 10] & 0x3f; - int rH2Dac2 = auxiliaryData[stream][2][RamOffset + 11] & 0x1f; - int rLDac1 = auxiliaryData[stream][2][RamOffset + 12] & 0x7f; - int rLDac2 = auxiliaryData[stream][2][RamOffset + 13] & 0x3f; - int rLDac3 = auxiliaryData[stream][2][RamOffset + 13] & 0x40 >> 6; - - double rH1 = 2630.0 + rH1Dac2 * 30800.0 + rH1Dac1 * 590.0; - double rH2 = 8200.0 + rH2Dac2 * 38400.0 + rH2Dac1 * 730.0; - double rL = 3300.0 + rLDac3 * 3000000.0 + rLDac2 * 15400.0 + rLDac1 * 190.0; - - cout << fixed << setprecision(2); - - cout << " RH1 DAC1, DAC2: " << rH1Dac1 << " " << rH1Dac2 << " = " << (rH1 / 1000) << - " kOhm" << endl; - cout << " RH2 DAC1, DAC2: " << rH2Dac1 << " " << rH2Dac2 << " = " << (rH2 / 1000) << - " kOhm" << endl; - cout << " RL DAC1, DAC2, DAC3: " << rLDac1 << " " << rLDac2 << " " << rLDac3 << " = " << - (rL / 1000) << " kOhm" << endl; - - cout << " amp power[31:0]: " << - ((auxiliaryData[stream][2][RamOffset + 17] & 0x80) >> 7) << - ((auxiliaryData[stream][2][RamOffset + 17] & 0x40) >> 6) << - ((auxiliaryData[stream][2][RamOffset + 17] & 0x20) >> 5) << - ((auxiliaryData[stream][2][RamOffset + 17] & 0x10) >> 4) << - ((auxiliaryData[stream][2][RamOffset + 17] & 0x08) >> 3) << - ((auxiliaryData[stream][2][RamOffset + 17] & 0x04) >> 2) << - ((auxiliaryData[stream][2][RamOffset + 17] & 0x02) >> 1) << - ((auxiliaryData[stream][2][RamOffset + 17] & 0x01) >> 0) << " " << - ((auxiliaryData[stream][2][RamOffset + 16] & 0x80) >> 7) << - ((auxiliaryData[stream][2][RamOffset + 16] & 0x40) >> 6) << - ((auxiliaryData[stream][2][RamOffset + 16] & 0x20) >> 5) << - ((auxiliaryData[stream][2][RamOffset + 16] & 0x10) >> 4) << - ((auxiliaryData[stream][2][RamOffset + 16] & 0x08) >> 3) << - ((auxiliaryData[stream][2][RamOffset + 16] & 0x04) >> 2) << - ((auxiliaryData[stream][2][RamOffset + 16] & 0x02) >> 1) << - ((auxiliaryData[stream][2][RamOffset + 16] & 0x01) >> 0) << " " << - ((auxiliaryData[stream][2][RamOffset + 15] & 0x80) >> 7) << - ((auxiliaryData[stream][2][RamOffset + 15] & 0x40) >> 6) << - ((auxiliaryData[stream][2][RamOffset + 15] & 0x20) >> 5) << - ((auxiliaryData[stream][2][RamOffset + 15] & 0x10) >> 4) << - ((auxiliaryData[stream][2][RamOffset + 15] & 0x08) >> 3) << - ((auxiliaryData[stream][2][RamOffset + 15] & 0x04) >> 2) << - ((auxiliaryData[stream][2][RamOffset + 15] & 0x02) >> 1) << - ((auxiliaryData[stream][2][RamOffset + 15] & 0x01) >> 0) << " " << - ((auxiliaryData[stream][2][RamOffset + 14] & 0x80) >> 7) << - ((auxiliaryData[stream][2][RamOffset + 14] & 0x40) >> 6) << - ((auxiliaryData[stream][2][RamOffset + 14] & 0x20) >> 5) << - ((auxiliaryData[stream][2][RamOffset + 14] & 0x10) >> 4) << - ((auxiliaryData[stream][2][RamOffset + 14] & 0x08) >> 3) << - ((auxiliaryData[stream][2][RamOffset + 14] & 0x04) >> 2) << - ((auxiliaryData[stream][2][RamOffset + 14] & 0x02) >> 1) << - ((auxiliaryData[stream][2][RamOffset + 14] & 0x01) >> 0) << endl; - - cout << endl; - - int tempA = auxiliaryData[stream][1][12]; - int tempB = auxiliaryData[stream][1][20]; - int vddSample = auxiliaryData[stream][1][28]; - - double tempUnitsC = ((double)(tempB - tempA)) / 98.9 - 273.15; - double tempUnitsF = (9.0/5.0) * tempUnitsC + 32.0; - - double vddSense = 0.0000748 * ((double) vddSample); - - cout << setprecision(1); - cout << " Temperature sensor (only one reading): " << tempUnitsC << " C (" << - tempUnitsF << " F)" << endl; - - cout << setprecision(2); - cout << " Supply voltage sensor : " << vddSense << " V" << endl; - - cout << setprecision(6); - cout.unsetf(ios::floatfield); - cout << endl; -} - -// Write a 16-bit dataWord to an outputStream in "little endian" format (i.e., least significant -// byte first). We must do this explicitly for cross-platform consistency. For example, Windows -// is a little-endian OS, while Mac OS X and Linux can be little-endian or big-endian depending on -// the processor running the operating system. -// -// (See "Endianness" article in Wikipedia for more information.) -void Rhd2000DataBlock::writeWordLittleEndian(ofstream &outputStream, int dataWord) const -{ - unsigned short msb, lsb; - - lsb = ((unsigned short) dataWord) & 0x00ff; - msb = (((unsigned short) dataWord) & 0xff00) >> 8; - - outputStream << (unsigned char) lsb; - outputStream << (unsigned char) msb; -} - -// Write contents of data block to a binary output stream (saveOut) in little endian format. -void Rhd2000DataBlock::write(ofstream &saveOut, int numDataStreams) const -{ - int t, channel, stream, i; - - for (t = 0; t < samplesPerBlock; ++t) { - writeWordLittleEndian(saveOut, timeStamp[t]); - for (channel = 0; channel < 32; ++channel) { - for (stream = 0; stream < numDataStreams; ++stream) { - writeWordLittleEndian(saveOut, amplifierData[stream][channel][t]); - } - } - for (channel = 0; channel < 3; ++channel) { - for (stream = 0; stream < numDataStreams; ++stream) { - writeWordLittleEndian(saveOut, auxiliaryData[stream][channel][t]); - } - } - for (i = 0; i < 8; ++i) { - writeWordLittleEndian(saveOut, boardAdcData[i][t]); - } - writeWordLittleEndian(saveOut, ttlIn[t]); - writeWordLittleEndian(saveOut, ttlOut[t]); - } -} diff --git a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000datablock.h b/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000datablock.h deleted file mode 100644 index 67ab197359d030cdaf847be5ba495be8bf62d2f0..0000000000000000000000000000000000000000 --- a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000datablock.h +++ /dev/null @@ -1,68 +0,0 @@ -//---------------------------------------------------------------------------------- -// rhd2000datablock.h -// -// Intan Technoloies RHD2000 Rhythm Interface API -// Rhd2000DataBlock Class Header File -// Version 1.4 (26 February 2014) -// -// Copyright (c) 2013-2014 Intan Technologies LLC -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the -// use of this software. -// -// Permission is granted to anyone to use this software for any applications that -// use Intan Technologies integrated circuits, and to alter it and redistribute it -// freely. -// -// See http://www.intantech.com for documentation and product information. -//---------------------------------------------------------------------------------- - -#ifndef RHD2000DATABLOCK_H -#define RHD2000DATABLOCK_H - -#define SAMPLES_PER_DATA_BLOCK_PCIE 1 -#define RHD2000_HEADER_MAGIC_NUMBER 0xc691199927021942 - -using namespace std; - -namespace PCIeRhythm { - - class Rhd2000EvalBoard; - - class Rhd2000DataBlock - { - public: - Rhd2000DataBlock(int numDataStreams, int nSamples = SAMPLES_PER_DATA_BLOCK_PCIE); - - vector<unsigned int> timeStamp; - vector<vector<vector<int> > > amplifierData; - vector<vector<vector<int> > > auxiliaryData; - vector<vector<int> > boardAdcData; - vector<int> ttlIn; - vector<int> ttlOut; - - static unsigned int calculateDataBlockSizeInWords(int numDataStreams, int nSamples = -1); - static unsigned int getSamplesPerDataBlock(); - void fillFromUsbBuffer(unsigned char usbBuffer[], int blockIndex, int numDataStreams, int nSamples = -1); - void print(int stream) const; - void write(ofstream &saveOut, int numDataStreams) const; - - static bool checkUsbHeader(unsigned char usbBuffer[], int index); - static unsigned int convertUsbTimeStamp(unsigned char usbBuffer[], int index); - static int convertUsbWord(unsigned char usbBuffer[], int index); - - private: - void allocateIntArray3D(vector<vector<vector<int> > > &array3D, int xSize, int ySize, int zSize); - void allocateIntArray2D(vector<vector<int> > &array2D, int xSize, int ySize); - void allocateIntArray1D(vector<int> &array1D, int xSize); - void allocateUIntArray1D(vector<unsigned int> &array1D, int xSize); - - void writeWordLittleEndian(ofstream &outputStream, int dataWord) const; - - - const unsigned int samplesPerBlock; - bool usb3; - }; -}; -#endif // RHD2000DATABLOCK_H diff --git a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000registers.cpp b/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000registers.cpp deleted file mode 100644 index 8fc819c5d8a7537dcfbb5b60251620dcf15e64cc..0000000000000000000000000000000000000000 --- a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000registers.cpp +++ /dev/null @@ -1,1025 +0,0 @@ -//---------------------------------------------------------------------------------- -// rhd2000registers.cpp -// -// Intan Technoloies RHD2000 Rhythm Interface API -// Rhd2000Registers Class -// Version 1.4 (26 February 2014) -// -// Copyright (c) 2013-2014 Intan Technologies LLC -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the -// use of this software. -// -// Permission is granted to anyone to use this software for any applications that -// use Intan Technologies integrated circuits, and to alter it and redistribute it -// freely. -// -// See http://www.intantech.com for documentation and product information. -//---------------------------------------------------------------------------------- - -#include <iostream> -#include <iomanip> -#include <cmath> -#include <vector> -#include <queue> - -#include "rhd2000registers.h" - -using namespace std; -using namespace PCIeRhythm; - -// This class creates and manages a data structure representing the internal RAM registers on -// a RHD2000 chip, and generates command lists to configure the chip and perform other functions. -// Changing the value of variables within an instance of this class does not directly affect a -// RHD2000 chip connected to the FPGA; rather, a command list must be generated from this class -// and then downloaded to the FPGA board using Rhd2000EvalBoard::uploadCommandList. - -// Constructor. Set RHD2000 register variables to default values. -Rhd2000Registers::Rhd2000Registers(double sampleRate) -{ - aPwr.resize(64); - - defineSampleRate(sampleRate); - - // Set default values for all register settings - adcReferenceBw = 3; // ADC reference generator bandwidth (0 [highest BW] - 3 [lowest BW]); - // always set to 3 - setFastSettle(false); // amplifier fast settle (off = normal operation) - ampVrefEnable = 1; // enable amplifier voltage references (0 = power down; 1 = enable); - // 1 = normal operation - adcComparatorBias = 3; // ADC comparator preamp bias current (0 [lowest] - 3 [highest], only - // valid for comparator select = 2,3); always set to 3 - adcComparatorSelect = 2; // ADC comparator select; always set to 2 - - vddSenseEnable = 1; // supply voltage sensor enable (0 = disable; 1 = enable) - // adcBufferBias = 32; // ADC reference buffer bias current (0 [highest current] - 63 [lowest current]); - // This value should be set according to ADC sampling rate; set in setSampleRate() - - // muxBias = 40; // ADC input MUX bias current (0 [highest current] - 63 [lowest current]); - // This value should be set according to ADC sampling rate; set in setSampleRate() - - // muxLoad = 0; // MUX capacitance load at ADC input (0 [min CL] - 7 [max CL]); LSB = 3 pF - // Set in setSampleRate() - - tempS1 = 0; // temperature sensor S1 (0-1); 0 = power saving mode when temperature sensor is - // not in use - tempS2 = 0; // temperature sensor S2 (0-1); 0 = power saving mode when temperature sensor is - // not in use - tempEn = 0; // temperature sensor enable (0 = disable; 1 = enable) - setDigOutHiZ(); // auxiliary digital output state - - weakMiso = 1; // weak MISO (0 = MISO line is HiZ when CS is inactive; 1 = MISO line is weakly - // driven when CS is inactive) - twosComp = 0; // two's complement ADC results (0 = unsigned offset representation; 1 = signed - // representation) - absMode = 0; // absolute value mode (0 = normal output; 1 = output passed through abs(x) function) - enableDsp(true); // DSP offset removal enable/disable - setDspCutoffFreq(1.0); // DSP offset removal HPF cutoff freqeuncy - - zcheckDacPower = 1; // impedance testing DAC power-up (0 = power down; 1 = power up) - zcheckLoad = 0; // impedance testing dummy load (0 = normal operation; 1 = insert 60 pF to ground) - setZcheckScale(ZcheckCs100fF); // impedance testing scale factor (100 fF, 1.0 pF, or 10.0 pF) - zcheckConnAll = 0; // impedance testing connect all (0 = normal operation; 1 = connect all electrodes together) - setZcheckPolarity(ZcheckPositiveInput); // impedance testing polarity select (RHD2216 only) (0 = test positive inputs; - // 1 = test negative inputs) - enableZcheck(false); // impedance testing enable/disable - - setZcheckChannel(0); // impedance testing amplifier select (0-63) - - offChipRH1 = 0; // bandwidth resistor RH1 on/off chip (0 = on chip; 1 = off chip) - offChipRH2 = 0; // bandwidth resistor RH2 on/off chip (0 = on chip; 1 = off chip) - offChipRL = 0; // bandwidth resistor RL on/off chip (0 = on chip; 1 = off chip) - adcAux1En = 1; // enable ADC aux1 input (when RH1 is on chip) (0 = disable; 1 = enable) - adcAux2En = 1; // enable ADC aux2 input (when RH2 is on chip) (0 = disable; 1 = enable) - adcAux3En = 1; // enable ADC aux3 input (when RL is on chip) (0 = disable; 1 = enable) - - setUpperBandwidth(10000.0); // set upper bandwidth of amplifiers - setLowerBandwidth(1.0); // set lower bandwidth of amplifiers - - powerUpAllAmps(); // turn on all amplifiers -} - -// Define RHD2000 per-channel sampling rate so that certain sampling-rate-dependent registers are set correctly -// (This function does not change the sampling rate of the FPGA; for this, use Rhd2000EvalBoard::setSampleRate.) -void Rhd2000Registers::defineSampleRate(double newSampleRate) -{ - sampleRate = newSampleRate; - - muxLoad = 0; - - if (sampleRate < 3334.0) { - muxBias = 40; - adcBufferBias = 32; - } else if (sampleRate < 4001.0) { - muxBias = 40; - adcBufferBias = 16; - } else if (sampleRate < 5001.0) { - muxBias = 40; - adcBufferBias = 8; - } else if (sampleRate < 6251.0) { - muxBias = 32; - adcBufferBias = 8; - } else if (sampleRate < 8001.0) { - muxBias = 26; - adcBufferBias = 8; - } else if (sampleRate < 10001.0) { - muxBias = 18; - adcBufferBias = 4; - } else if (sampleRate < 12501.0) { - muxBias = 16; - adcBufferBias = 3; - } else if (sampleRate < 15001.0) { - muxBias = 7; - adcBufferBias = 3; - } else { - muxBias = 4; - adcBufferBias = 2; - } -} - -// Enable or disable amplifier fast settle function; drive amplifiers to baseline -// if enabled. -void Rhd2000Registers::setFastSettle(bool enabled) -{ - ampFastSettle = (enabled ? 1 : 0); -} - -// Drive auxiliary digital output low -void Rhd2000Registers::setDigOutLow() -{ - digOut = 0; - digOutHiZ = 0; -} - -// Drive auxiliary digital output high -void Rhd2000Registers::setDigOutHigh() -{ - digOut = 1; - digOutHiZ = 0; -} - -// Set auxiliary digital output to high-impedance (HiZ) state -void Rhd2000Registers::setDigOutHiZ() -{ - digOut = 0; - digOutHiZ = 1; -} - -// Enable or disable ADC auxiliary input 1 -void Rhd2000Registers::enableAux1(bool enabled) -{ - adcAux1En = (enabled ? 1 : 0); -} - -// Enable or disable ADC auxiliary input 2 -void Rhd2000Registers::enableAux2(bool enabled) -{ - adcAux2En = (enabled ? 1 : 0); -} - -// Enable or disable ADC auxiliary input 3 -void Rhd2000Registers::enableAux3(bool enabled) -{ - adcAux3En = (enabled ? 1 : 0); -} - -// Enable or disable DSP offset removal filter -void Rhd2000Registers::enableDsp(bool enabled) -{ - dspEn = (enabled ? 1 : 0); -} - -// Set the DSP offset removal filter cutoff frequency as closely to the requested -// newDspCutoffFreq (in Hz) as possible; returns the actual cutoff frequency (in Hz). -double Rhd2000Registers::setDspCutoffFreq(double newDspCutoffFreq) -{ - int n; - double x, fCutoff[16], logNewDspCutoffFreq, logFCutoff[16], minLogDiff; - const double Pi = 2*acos(0.0); - - fCutoff[0] = 0.0; // We will not be using fCutoff[0], but we initialize it to be safe - - logNewDspCutoffFreq = log10(newDspCutoffFreq); - - // Generate table of all possible DSP cutoff frequencies - for (n = 1; n < 16; ++n) { - x = pow(2.0, (double) n); - fCutoff[n] = sampleRate * log(x / (x - 1.0)) / (2*Pi); - logFCutoff[n] = log10(fCutoff[n]); - // cout << " fCutoff[" << n << "] = " << fCutoff[n] << " Hz" << endl; - } - - // Now find the closest value to the requested cutoff frequency (on a logarithmic scale) - if (newDspCutoffFreq > fCutoff[1]) { - dspCutoffFreq = 1; - } else if (newDspCutoffFreq < fCutoff[15]) { - dspCutoffFreq = 15; - } else { - minLogDiff = 10000000.0; - for (n = 1; n < 16; ++n) { - if (abs(logNewDspCutoffFreq - logFCutoff[n]) < minLogDiff) { - minLogDiff = abs(logNewDspCutoffFreq - logFCutoff[n]); - dspCutoffFreq = n; - } - } - } - - return fCutoff[dspCutoffFreq]; -} - -// Returns the current value of the DSP offset removal cutoff frequency (in Hz). -double Rhd2000Registers::getDspCutoffFreq() const -{ - double x; - const double Pi = 2*acos(0.0); - - x = pow(2.0, (double) dspCutoffFreq); - - return sampleRate * log(x / (x - 1.0)) / (2*Pi); -} - -// Enable or disable impedance checking mode -void Rhd2000Registers::enableZcheck(bool enabled) -{ - zcheckEn = (enabled ? 1: 0); -} - -// Power up or down impedance checking DAC -void Rhd2000Registers::setZcheckDacPower(bool enabled) -{ - zcheckDacPower = (enabled ? 1 : 0); -} - -// Select the series capacitor used to convert the voltage waveform generated by the on-chip -// DAC into an AC current waveform that stimulates a selected electrode for impedance testing -// (ZcheckCs100fF, ZcheckCs1pF, or Zcheck10pF). -void Rhd2000Registers::setZcheckScale(ZcheckCs scale) -{ - switch (scale) { - case ZcheckCs100fF: - zcheckScale = 0x00; // Cs = 0.1 pF - break; - case ZcheckCs1pF: - zcheckScale = 0x01; // Cs = 1.0 pF - break; - case ZcheckCs10pF: - zcheckScale = 0x03; // Cs = 10.0 pF - break; - } -} - -// Select impedance testing of positive or negative amplifier inputs (RHD2216 only), based -// on the variable polarity (ZcheckPositiveInput or ZcheckNegativeInput) -void Rhd2000Registers::setZcheckPolarity(ZcheckPolarity polarity) -{ - switch (polarity) { - case ZcheckPositiveInput: - zcheckSelPol = 0; - break; - case ZcheckNegativeInput: - zcheckSelPol = 1; - break; - } -} - -// Select the amplifier channel (0-63) for impedance testing. -int Rhd2000Registers::setZcheckChannel(int channel) -{ - if (channel < 0 || channel > 63) { - return -1; - } else { - zcheckSelect = channel; - return zcheckSelect; - } -} - -// Power up or down selected amplifier on chip -void Rhd2000Registers::setAmpPowered(int channel, bool powered) -{ - if (channel >= 0 && channel <= 63) { - aPwr[channel] = (powered ? 1 : 0); - } -} - -// Power up all amplifiers on chip -void Rhd2000Registers::powerUpAllAmps() -{ - for (int channel = 0; channel < 64; ++channel) { - aPwr[channel] = 1; - } -} - -// Power down all amplifiers on chip -void Rhd2000Registers::powerDownAllAmps() -{ - for (int channel = 0; channel < 64; ++channel) { - aPwr[channel] = 0; - } -} - -// Returns the value of a selected RAM register (0-17) on the RHD2000 chip, based -// on the current register variables in the class instance. -int Rhd2000Registers::getRegisterValue(int reg) const -{ - int regout; - const int zcheckDac = 128; // midrange - - switch (reg) { - case 0: - regout = (adcReferenceBw << 6) + (ampFastSettle << 5) + (ampVrefEnable << 4) + - (adcComparatorBias << 2) + adcComparatorSelect; - break; - case 1: - regout = (vddSenseEnable << 6) + adcBufferBias; - break; - case 2: - regout = muxBias; - break; - case 3: - regout = (muxLoad << 5) + (tempS2 << 4) + (tempS1 << 3) + (tempEn << 2) + - (digOutHiZ << 1) + digOut; - break; - case 4: - regout = (weakMiso << 7) + (twosComp << 6) + (absMode << 5) + (dspEn << 4) + - dspCutoffFreq; - break; - case 5: - regout = (zcheckDacPower << 6) + (zcheckLoad << 5) + (zcheckScale << 3) + - (zcheckConnAll << 2) + (zcheckSelPol << 1) + zcheckEn; - break; - case 6: - regout = zcheckDac; - break; - case 7: - regout = zcheckSelect; - break; - case 8: - regout = (offChipRH1 << 7) + rH1Dac1; - break; - case 9: - regout = (adcAux1En << 7) + rH1Dac2; - break; - case 10: - regout = (offChipRH2 << 7) + rH2Dac1; - break; - case 11: - regout = (adcAux2En << 7) + rH2Dac2; - break; - case 12: - regout = (offChipRL << 7) + rLDac1; - break; - case 13: - regout = (adcAux3En << 7) + (rLDac3 << 6) + rLDac2; - break; - case 14: - regout = (aPwr[7] << 7) + (aPwr[6] << 6) + (aPwr[5] << 5) + (aPwr[4] << 4) + - (aPwr[3] << 3) + (aPwr[2] << 2) + (aPwr[1] << 1) + aPwr[0]; - break; - case 15: - regout = (aPwr[15] << 7) + (aPwr[14] << 6) + (aPwr[13] << 5) + (aPwr[12] << 4) + - (aPwr[11] << 3) + (aPwr[10] << 2) + (aPwr[9] << 1) + aPwr[0]; - break; - case 16: - regout = (aPwr[23] << 7) + (aPwr[22] << 6) + (aPwr[21] << 5) + (aPwr[20] << 4) + - (aPwr[19] << 3) + (aPwr[18] << 2) + (aPwr[17] << 1) + aPwr[16]; - break; - case 17: - regout = (aPwr[31] << 7) + (aPwr[30] << 6) + (aPwr[29] << 5) + (aPwr[28] << 4) + - (aPwr[27] << 3) + (aPwr[26] << 2) + (aPwr[25] << 1) + aPwr[24]; - break; - case 18: - regout = (aPwr[39] << 7) + (aPwr[38] << 6) + (aPwr[37] << 5) + (aPwr[36] << 4) + - (aPwr[35] << 3) + (aPwr[34] << 2) + (aPwr[33] << 1) + aPwr[32]; - break; - case 19: - regout = (aPwr[47] << 7) + (aPwr[46] << 6) + (aPwr[45] << 5) + (aPwr[44] << 4) + - (aPwr[43] << 3) + (aPwr[42] << 2) + (aPwr[41] << 1) + aPwr[40]; - break; - case 20: - regout = (aPwr[55] << 7) + (aPwr[54] << 6) + (aPwr[53] << 5) + (aPwr[52] << 4) + - (aPwr[51] << 3) + (aPwr[50] << 2) + (aPwr[49] << 1) + aPwr[48]; - break; - case 21: - regout = (aPwr[63] << 7) + (aPwr[62] << 6) + (aPwr[61] << 5) + (aPwr[60] << 4) + - (aPwr[59] << 3) + (aPwr[58] << 2) + (aPwr[57] << 1) + aPwr[56]; - break; - default: - regout = -1; - } - return regout; -} - -// Returns the value of the RH1 resistor (in ohms) corresponding to a particular upper -// bandwidth value (in Hz). -double Rhd2000Registers::rH1FromUpperBandwidth(double upperBandwidth) const -{ - double log10f = log10(upperBandwidth); - - return 0.9730 * pow(10.0, (8.0968 - 1.1892 * log10f + 0.04767 * log10f * log10f)); -} - -// Returns the value of the RH2 resistor (in ohms) corresponding to a particular upper -// bandwidth value (in Hz). -double Rhd2000Registers::rH2FromUpperBandwidth(double upperBandwidth) const -{ - double log10f = log10(upperBandwidth); - - return 1.0191 * pow(10.0, (8.1009 - 1.0821 * log10f + 0.03383 * log10f * log10f)); -} - -// Returns the value of the RL resistor (in ohms) corresponding to a particular lower -// bandwidth value (in Hz). -double Rhd2000Registers::rLFromLowerBandwidth(double lowerBandwidth) const -{ - double log10f = log10(lowerBandwidth); - - if (lowerBandwidth < 4.0) { - return 1.0061 * pow(10.0, (4.9391 - 1.2088 * log10f + 0.5698 * log10f * log10f + - 0.1442 * log10f * log10f * log10f)); - } else { - return 1.0061 * pow(10.0, (4.7351 - 0.5916 * log10f + 0.08482 * log10f * log10f)); - } -} - -// Returns the amplifier upper bandwidth (in Hz) corresponding to a particular value -// of the resistor RH1 (in ohms). -double Rhd2000Registers::upperBandwidthFromRH1(double rH1) const -{ - double a, b, c; - - a = 0.04767; - b = -1.1892; - c = 8.0968 - log10(rH1/0.9730); - - return pow(10.0, ((-b - sqrt(b * b - 4 * a * c))/(2 * a))); -} - -// Returns the amplifier upper bandwidth (in Hz) corresponding to a particular value -// of the resistor RH2 (in ohms). -double Rhd2000Registers::upperBandwidthFromRH2(double rH2) const -{ - double a, b, c; - - a = 0.03383; - b = -1.0821; - c = 8.1009 - log10(rH2/1.0191); - - return pow(10.0, ((-b - sqrt(b * b - 4 * a * c))/(2 * a))); -} - -// Returns the amplifier lower bandwidth (in Hz) corresponding to a particular value -// of the resistor RL (in ohms). -double Rhd2000Registers::lowerBandwidthFromRL(double rL) const -{ - double a, b, c; - - // Quadratic fit below is invalid for values of RL less than 5.1 kOhm - if (rL < 5100.0) { - rL = 5100.0; - } - - if (rL < 30000.0) { - a = 0.08482; - b = -0.5916; - c = 4.7351 - log10(rL/1.0061); - } else { - a = 0.3303; - b = -1.2100; - c = 4.9873 - log10(rL/1.0061); - } - - return pow(10.0, ((-b - sqrt(b * b - 4 * a * c))/(2 * a))); -} - -// Sets the on-chip RH1 and RH2 DAC values appropriately to set a particular amplifier -// upper bandwidth (in Hz). Returns an estimate of the actual upper bandwidth achieved. -double Rhd2000Registers::setUpperBandwidth(double upperBandwidth) -{ - const double RH1Base = 2200.0; - const double RH1Dac1Unit = 600.0; - const double RH1Dac2Unit = 29400.0; - const int RH1Dac1Steps = 63; - const int RH1Dac2Steps = 31; - - const double RH2Base = 8700.0; - const double RH2Dac1Unit = 763.0; - const double RH2Dac2Unit = 38400.0; - const int RH2Dac1Steps = 63; - const int RH2Dac2Steps = 31; - - double actualUpperBandwidth; - double rH1Target, rH2Target; - double rH1Actual, rH2Actual; - int i; - - // Upper bandwidths higher than 30 kHz don't work well with the RHD2000 amplifiers - if (upperBandwidth > 30000.0) { - upperBandwidth = 30000.0; - } - - rH1Target = rH1FromUpperBandwidth(upperBandwidth); - - rH1Dac1 = 0; - rH1Dac2 = 0; - rH1Actual = RH1Base; - - for (i = 0; i < RH1Dac2Steps; ++i) { - if (rH1Actual < rH1Target - (RH1Dac2Unit - RH1Dac1Unit / 2)) { - rH1Actual += RH1Dac2Unit; - ++rH1Dac2; - } - } - - for (i = 0; i < RH1Dac1Steps; ++i) { - if (rH1Actual < rH1Target - (RH1Dac1Unit / 2)) { - rH1Actual += RH1Dac1Unit; - ++rH1Dac1; - } - } - - rH2Target = rH2FromUpperBandwidth(upperBandwidth); - - rH2Dac1 = 0; - rH2Dac2 = 0; - rH2Actual = RH2Base; - - for (i = 0; i < RH2Dac2Steps; ++i) { - if (rH2Actual < rH2Target - (RH2Dac2Unit - RH2Dac1Unit / 2)) { - rH2Actual += RH2Dac2Unit; - ++rH2Dac2; - } - } - - for (i = 0; i < RH2Dac1Steps; ++i) { - if (rH2Actual < rH2Target - (RH2Dac1Unit / 2)) { - rH2Actual += RH2Dac1Unit; - ++rH2Dac1; - } - } - - double actualUpperBandwidth1, actualUpperBandwidth2; - - actualUpperBandwidth1 = upperBandwidthFromRH1(rH1Actual); - actualUpperBandwidth2 = upperBandwidthFromRH2(rH2Actual); - - // Upper bandwidth estimates calculated from actual RH1 value and acutal RH2 value - // should be very close; we will take their geometric mean to get a single - // number. - actualUpperBandwidth = sqrt(actualUpperBandwidth1 * actualUpperBandwidth2); - - /* - cout << endl; - cout << "Rhd2000Registers::setUpperBandwidth" << endl; - cout << fixed << setprecision(1); - - cout << "RH1 DAC2 = " << rH1Dac2 << ", DAC1 = " << rH1Dac1 << endl; - cout << "RH1 target: " << rH1Target << " Ohms" << endl; - cout << "RH1 actual: " << rH1Actual << " Ohms" << endl; - - cout << "RH2 DAC2 = " << rH2Dac2 << ", DAC1 = " << rH2Dac1 << endl; - cout << "RH2 target: " << rH2Target << " Ohms" << endl; - cout << "RH2 actual: " << rH2Actual << " Ohms" << endl; - - cout << "Upper bandwidth target: " << upperBandwidth << " Hz" << endl; - cout << "Upper bandwidth actual: " << actualUpperBandwidth << " Hz" << endl; - - cout << endl; - cout << setprecision(6); - cout.unsetf(ios::floatfield); - */ - - return actualUpperBandwidth; -} - -// Sets the on-chip RL DAC values appropriately to set a particular amplifier -// lower bandwidth (in Hz). Returns an estimate of the actual lower bandwidth achieved. -double Rhd2000Registers::setLowerBandwidth(double lowerBandwidth) -{ - const double RLBase = 3500.0; - const double RLDac1Unit = 175.0; - const double RLDac2Unit = 12700.0; - const double RLDac3Unit = 3000000.0; - const int RLDac1Steps = 127; - const int RLDac2Steps = 63; - - double actualLowerBandwidth; - double rLTarget; - double rLActual; - int i; - - // Lower bandwidths higher than 1.5 kHz don't work well with the RHD2000 amplifiers - if (lowerBandwidth > 1500.0) { - lowerBandwidth = 1500.0; - } - - rLTarget = rLFromLowerBandwidth(lowerBandwidth); - - rLDac1 = 0; - rLDac2 = 0; - rLDac3 = 0; - rLActual = RLBase; - - if (lowerBandwidth < 0.15) { - rLActual += RLDac3Unit; - ++rLDac3; - } - - for (i = 0; i < RLDac2Steps; ++i) { - if (rLActual < rLTarget - (RLDac2Unit - RLDac1Unit / 2)) { - rLActual += RLDac2Unit; - ++rLDac2; - } - } - - for (i = 0; i < RLDac1Steps; ++i) { - if (rLActual < rLTarget - (RLDac1Unit / 2)) { - rLActual += RLDac1Unit; - ++rLDac1; - } - } - - actualLowerBandwidth = lowerBandwidthFromRL(rLActual); - - /* - cout << endl; - cout << fixed << setprecision(1); - cout << "Rhd2000Registers::setLowerBandwidth" << endl; - - cout << "RL DAC3 = " << rLDac3 << ", DAC2 = " << rLDac2 << ", DAC1 = " << rLDac1 << endl; - cout << "RL target: " << rLTarget << " Ohms" << endl; - cout << "RL actual: " << rLActual << " Ohms" << endl; - - cout << setprecision(3); - - cout << "Lower bandwidth target: " << lowerBandwidth << " Hz" << endl; - cout << "Lower bandwidth actual: " << actualLowerBandwidth << " Hz" << endl; - - cout << endl; - cout << setprecision(6); - cout.unsetf(ios::floatfield); - */ - - return actualLowerBandwidth; -} - -// Return a 16-bit MOSI command (CALIBRATE or CLEAR) -int Rhd2000Registers::createRhd2000Command(Rhd2000CommandType commandType) -{ - switch (commandType) { - case Rhd2000CommandCalibrate: - return 0x5500; // 0101010100000000 - break; - case Rhd2000CommandCalClear: - return 0x6a00; // 0110101000000000 - break; - default: - cerr << "Error in Rhd2000Registers::createRhd2000Command: " << - "Only 'Calibrate' or 'Clear Calibration' commands take zero arguments." << endl; - return -1; - } -} - -// Return a 16-bit MOSI command (CONVERT or READ) -int Rhd2000Registers::createRhd2000Command(Rhd2000CommandType commandType, int arg1) -{ - switch (commandType) { - case Rhd2000CommandConvert: - if (arg1 < 0 || arg1 > 63) { - cerr << "Error in Rhd2000Registers::createRhd2000Command: " << - "Channel number out of range." << endl; - return -1; - } - return 0x0000 + (arg1 << 8); // 00cccccc0000000h; if the command is 'Convert', - // arg1 is the channel number - case Rhd2000CommandRegRead: - if (arg1 < 0 || arg1 > 63) { - cerr << "Error in Rhd2000Registers::createRhd2000Command: " << - "Register address out of range." << endl; - return -1; - } - return 0xc000 + (arg1 << 8); // 11rrrrrr00000000; if the command is 'Register Read', - // arg1 is the register address - break; - default: - cerr << "Error in Rhd2000Registers::createRhd2000Command: " << - "Only 'Convert' and 'Register Read' commands take one argument." << endl; - return -1; - } -} - -// Return a 16-bit MOSI command (WRITE) -int Rhd2000Registers::createRhd2000Command(Rhd2000CommandType commandType, int arg1, int arg2) -{ - switch (commandType) { - case Rhd2000CommandRegWrite: - if (arg1 < 0 || arg1 > 63) { - cerr << "Error in Rhd2000Registers::createRhd2000Command: " << - "Register address out of range." << endl; - return -1; - } - if (arg2 < 0 || arg2 > 255) { - cerr << "Error in Rhd2000Registers::createRhd2000Command: " << - "Register data out of range." << endl; - return -1; - } - return 0x8000 + (arg1 << 8) + arg2; // 10rrrrrrdddddddd; if the command is 'Register Write', - // arg1 is the register address and arg1 is the data - break; - default: - cerr << "Error in Rhd2000Registers::createRhd2000Command: " << - "Only 'Register Write' commands take two arguments." << endl; - return -1; - } -} - - -// Create a list of 60 commands to program most RAM registers on a RHD2000 chip, read those values -// back to confirm programming, read ROM registers, and (if calibrate == true) run ADC calibration. -// Returns the length of the command list. -int Rhd2000Registers::createCommandListRegisterConfig(vector<int> &commandList, bool calibrate) -{ - commandList.clear(); // if command list already exists, erase it and start a new one - - // Start with a few dummy commands in case chip is still powering up - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 63)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 63)); - - // Program RAM registers - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 0, getRegisterValue( 0))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 1, getRegisterValue( 1))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 2, getRegisterValue( 2))); - // Don't program Register 3 (MUX Load, Temperature Sensor, and Auxiliary Digital Output); - // control temperature sensor in another command stream - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 4, getRegisterValue( 4))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 5, getRegisterValue( 5))); - // Don't program Register 6 (Impedance Check DAC) here; create DAC waveform in another command stream - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 7, getRegisterValue( 7))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 8, getRegisterValue( 8))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 9, getRegisterValue( 9))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 10, getRegisterValue(10))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 11, getRegisterValue(11))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 12, getRegisterValue(12))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 13, getRegisterValue(13))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 14, getRegisterValue(14))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 15, getRegisterValue(15))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 16, getRegisterValue(16))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 17, getRegisterValue(17))); - - // Read ROM registers - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 63)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 62)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 61)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 60)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 59)); - - // Read chip name from ROM - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 48)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 49)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 50)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 51)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 52)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 53)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 54)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 55)); - - // Read Intan name from ROM - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 40)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 41)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 42)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 43)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 44)); - - // Read back RAM registers to confirm programming - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 0)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 1)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 2)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 3)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 4)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 5)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 6)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 7)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 8)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 9)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 10)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 11)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 12)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 13)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 14)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 15)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 16)); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 17)); - - // Optionally, run ADC calibration (should only be run once after board is plugged in) - if (calibrate) { - commandList.push_back(createRhd2000Command(Rhd2000CommandCalibrate)); - } else { - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 63)); - } - - // Added in Version 1.2: - // Program amplifier 31-63 power up/down registers in case a RHD2164 is connected - // Note: We don't read these registers back, since they are only 'visible' on MISO B. - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 18, getRegisterValue(18))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 19, getRegisterValue(19))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 20, getRegisterValue(20))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 21, getRegisterValue(21))); - - // End with a dummy command - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 63)); - - - return commandList.size(); -} - -// Create a list of 60 commands to sample auxiliary ADC inputs, temperature sensor, and supply -// voltage sensor. One temperature reading (one sample of ResultA and one sample of ResultB) -// is taken during this 60-command sequence. One supply voltage sample is taken. Auxiliary -// ADC inputs are continuously sampled at 1/4 the amplifier sampling rate. -// -// Since this command list consists of writing to Register 3, it also sets the state of the -// auxiliary digital output. If the digital output value needs to be changed dynamically, -// then variations of this command list need to be generated for each state and programmed into -// different RAM banks, and the appropriate command list selected at the right time. -// -// Returns the length of the command list. -int Rhd2000Registers::createCommandListTempSensor(vector<int> &commandList) -{ - int i; - - commandList.clear(); // if command list already exists, erase it and start a new one - - tempEn = 1; - - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 32)); // sample AuxIn1 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 33)); // sample AuxIn2 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 34)); // sample AuxIn3 - tempS1 = tempEn; - tempS2 = 0; - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 32)); // sample AuxIn1 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 33)); // sample AuxIn2 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 34)); // sample AuxIn3 - tempS1 = tempEn; - tempS2 = tempEn; - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 32)); // sample AuxIn1 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 33)); // sample AuxIn2 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 34)); // sample AuxIn3 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 49)); // sample Temperature Sensor - - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 32)); // sample AuxIn1 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 33)); // sample AuxIn2 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 34)); // sample AuxIn3 - tempS1 = 0; - tempS2 = tempEn; - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 32)); // sample AuxIn1 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 33)); // sample AuxIn2 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 34)); // sample AuxIn3 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 49)); // sample Temperature Sensor - - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 32)); // sample AuxIn1 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 33)); // sample AuxIn2 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 34)); // sample AuxIn3 - tempS1 = 0; - tempS2 = 0; - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 32)); // sample AuxIn1 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 33)); // sample AuxIn2 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 34)); // sample AuxIn3 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 48)); // sample Supply Voltage Sensor - - for (i = 0; i < 8; ++i) { - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 32)); // sample AuxIn1 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 33)); // sample AuxIn2 - commandList.push_back(createRhd2000Command(Rhd2000CommandConvert, 34)); // sample AuxIn3 - commandList.push_back(createRhd2000Command(Rhd2000CommandRegRead, 63)); // dummy command - } - - return commandList.size(); -} - -// Create a list of 60 commands to update Register 3 (controlling the auxiliary digital ouput -// pin) every sampling period. -// -// Since this command list consists of writing to Register 3, it also sets the state of the -// on-chip temperature sensor. The temperature sensor settings are therefore changed throughout -// this command list to coordinate with the 60-command list generated by createCommandListTempSensor(). -// -// Returns the length of the command list. -int Rhd2000Registers::createCommandListUpdateDigOut(vector<int> &commandList) -{ - int i; - - commandList.clear(); // if command list already exists, erase it and start a new one - - tempEn = 1; - - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - tempS1 = tempEn; - tempS2 = 0; - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - tempS1 = tempEn; - tempS2 = tempEn; - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - tempS1 = 0; - tempS2 = tempEn; - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - tempS1 = 0; - tempS2 = 0; - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - - for (i = 0; i < 8; ++i) { - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 3, getRegisterValue(3))); - } - - return commandList.size(); -} - -// Create a list of up to 1024 commands to generate a sine wave of particular frequency (in Hz) and -// amplitude (in DAC steps, 0-128) using the on-chip impedance testing voltage DAC. If frequency is set to zero, -// a DC baseline waveform is created. -// Returns the length of the command list. -int Rhd2000Registers::createCommandListZcheckDac(vector<int> &commandList, double frequency, double amplitude) -{ - int i, period, value; - double t; - const double Pi = 2*acos(0.0); - - commandList.clear(); // if command list already exists, erase it and start a new one - - if (amplitude < 0.0 || amplitude > 128.0) { - cerr << "Error in Rhd2000Registers::createCommandListZcheckDac: Amplitude out of range." << endl; - return -1; - } - if (frequency < 0.0) { - cerr << "Error in Rhd2000Registers::createCommandListZcheckDac: Negative frequency not allowed." << endl; - return -1; - } else if (frequency > sampleRate / 4.0) { - cerr << "Error in Rhd2000Registers::createCommandListZcheckDac: " << - "Frequency too high relative to sampling rate." << endl; - return -1; - } - if (frequency == 0.0) { - for (i = 0; i < MaxCommandLength; ++i) { - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 6, 128)); - } - } else { - period = (int) floor(sampleRate / frequency + 0.5); - if (period > MaxCommandLength) { - cerr << "Error in Rhd2000Registers::createCommandListZcheckDac: Frequency too low." << endl; - return -1; - } else { - t = 0.0; - for (i = 0; i < period; ++i) { - value = (int) floor(amplitude * sin(2 * Pi * frequency * t) + 128.0 + 0.5); - if (value < 0) { - value = 0; - } else if (value > 255) { - value = 255; - } - commandList.push_back(createRhd2000Command(Rhd2000CommandRegWrite, 6, value)); - t += 1.0 / sampleRate; - } - } - } - - return commandList.size(); -} diff --git a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000registers.h b/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000registers.h deleted file mode 100644 index 6c47449456cd0a1877a2d8ee819f7a970012bbca..0000000000000000000000000000000000000000 --- a/Source/Plugins/PCIeRhythm/rhythm-api/rhd2000registers.h +++ /dev/null @@ -1,170 +0,0 @@ -//---------------------------------------------------------------------------------- -// rhd2000registers.h -// -// Intan Technoloies RHD2000 Rhythm Interface API -// Rhd2000Registers Class Header File -// Version 1.4 (26 February 2014) -// -// Copyright (c) 2013-2014 Intan Technologies LLC -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the -// use of this software. -// -// Permission is granted to anyone to use this software for any applications that -// use Intan Technologies integrated circuits, and to alter it and redistribute it -// freely. -// -// See http://www.intantech.com for documentation and product information. -//---------------------------------------------------------------------------------- - -#ifndef RHD2000REGISTERS_H -#define RHD2000REGISTERS_H - -using namespace std; - -namespace PCIeRhythm { - class Rhd2000Registers - { - - public: - Rhd2000Registers(double sampleRate); - - void defineSampleRate(double newSampleRate); - - void setFastSettle(bool enabled); - - void setDigOutLow(); - void setDigOutHigh(); - void setDigOutHiZ(); - - void enableAux1(bool enabled); - void enableAux2(bool enabled); - void enableAux3(bool enabled); - - void enableDsp(bool enabled); - void disableDsp(); - double setDspCutoffFreq(double newDspCutoffFreq); - double getDspCutoffFreq() const; - - void enableZcheck(bool enabled); - void setZcheckDacPower(bool enabled); - - enum ZcheckCs { - ZcheckCs100fF, - ZcheckCs1pF, - ZcheckCs10pF - }; - - enum ZcheckPolarity { - ZcheckPositiveInput, - ZcheckNegativeInput - }; - - void setZcheckScale(ZcheckCs scale); - void setZcheckPolarity(ZcheckPolarity polarity); - int setZcheckChannel(int channel); - - void setAmpPowered(int channel, bool powered); - void powerUpAllAmps(); - void powerDownAllAmps(); - - int getRegisterValue(int reg) const; - - double setUpperBandwidth(double upperBandwidth); - double setLowerBandwidth(double lowerBandwidth); - - int createCommandListRegisterConfig(vector<int> &commandList, bool calibrate); - int createCommandListTempSensor(vector<int> &commandList); - int createCommandListUpdateDigOut(vector<int> &commandList); - int createCommandListZcheckDac(vector<int> &commandList, double frequency, double amplitude); - - enum Rhd2000CommandType { - Rhd2000CommandConvert, - Rhd2000CommandCalibrate, - Rhd2000CommandCalClear, - Rhd2000CommandRegWrite, - Rhd2000CommandRegRead - }; - - int createRhd2000Command(Rhd2000CommandType commandType); - int createRhd2000Command(Rhd2000CommandType commandType, int arg1); - int createRhd2000Command(Rhd2000CommandType commandType, int arg1, int arg2); - - private: - double sampleRate; - - // RHD2000 Register 0 variables - int adcReferenceBw; - int ampFastSettle; - int ampVrefEnable; - int adcComparatorBias; - int adcComparatorSelect; - - // RHD2000 Register 1 variables - int vddSenseEnable; - int adcBufferBias; - - // RHD2000 Register 2 variables - int muxBias; - - // RHD2000 Register 3 variables - int muxLoad; - int tempS1; - int tempS2; - int tempEn; - int digOutHiZ; - int digOut; - - // RHD2000 Register 4 variables - int weakMiso; - int twosComp; - int absMode; - int dspEn; - int dspCutoffFreq; - - // RHD2000 Register 5 variables - int zcheckDacPower; - int zcheckLoad; - int zcheckScale; - int zcheckConnAll; - int zcheckSelPol; - int zcheckEn; - - // RHD2000 Register 6 variables - //int zcheckDac; // handle Zcheck DAC waveform elsewhere - - // RHD2000 Register 7 variables - int zcheckSelect; - - // RHD2000 Register 8-13 variables - int offChipRH1; - int offChipRH2; - int offChipRL; - int adcAux1En; - int adcAux2En; - int adcAux3En; - int rH1Dac1; - int rH1Dac2; - int rH2Dac1; - int rH2Dac2; - int rLDac1; - int rLDac2; - int rLDac3; - - // RHD2000 Register 14-17 variables - vector<int> aPwr; - - double rH1FromUpperBandwidth(double upperBandwidth) const; - double rH2FromUpperBandwidth(double upperBandwidth) const; - double rLFromLowerBandwidth(double lowerBandwidth) const; - double upperBandwidthFromRH1(double rH1) const; - double upperBandwidthFromRH2(double rH2) const; - double lowerBandwidthFromRL(double rL) const; - - static const int MaxCommandLength = 1024; // size of on-FPGA auxiliary command RAM banks - - }; -}; - -#endif // RHD2000REGISTERS_H diff --git a/Source/Plugins/PulsePalOutput/serial/PulsePal.cpp b/Source/Plugins/PulsePalOutput/serial/PulsePal.cpp index 70e3f03ca407fe7968a6c79a4e1ab2ec4cddbd98..9b686101228799bdfe085495bb2e638893350991 100644 --- a/Source/Plugins/PulsePalOutput/serial/PulsePal.cpp +++ b/Source/Plugins/PulsePalOutput/serial/PulsePal.cpp @@ -176,7 +176,7 @@ void PulsePal::setInterPulseInterval(uint8_t channel, float timeInSeconds) uint32_t timeInCycles = (uint32_t)(timeInSeconds * CycleFreq); constrain(&timeInCycles, 1, MAX_Cycles); program(channel, 7, timeInCycles); - PulsePal::currentOutputParams[channel].interPhaseInterval = timeInSeconds; + PulsePal::currentOutputParams[channel].interPulseInterval = timeInSeconds; } void PulsePal::setBurstDuration(uint8_t channel, float timeInSeconds) @@ -519,4 +519,4 @@ void PulsePal::syncAllParams() { messageBytes[pos] = (uint8_t)currentInputParams[2].triggerMode; pos++; serial.writeBytes(messageBytes, 168); -} \ No newline at end of file +} diff --git a/Source/Processors/Merger/Merger.cpp b/Source/Processors/Merger/Merger.cpp index 9732a34ef7e2bbe00a9fadeb9642d144572ddbcc..04e1a33c7101eff120ff27966c9ea9958ddf7f09 100755 --- a/Source/Processors/Merger/Merger.cpp +++ b/Source/Processors/Merger/Merger.cpp @@ -34,6 +34,7 @@ Merger::Merger() mergeEventsB(true), mergeContinuousB(true), sourceNodeA(0), sourceNodeB(0), activePath(0) { + setProcessorType(PROCESSOR_TYPE_MERGER); sendSampleCount = false; } diff --git a/Source/Processors/Splitter/Splitter.cpp b/Source/Processors/Splitter/Splitter.cpp index cb1fcdabf0cf805a22cff00afcb71682bce8a2c0..0c9bd25703bd178b4a97f2b284d2dd5a0fa5711a 100755 --- a/Source/Processors/Splitter/Splitter.cpp +++ b/Source/Processors/Splitter/Splitter.cpp @@ -30,6 +30,7 @@ Splitter::Splitter() : GenericProcessor("Splitter"), destNodeA(0), destNodeB(0), activePath(0) { + setProcessorType(PROCESSOR_TYPE_SPLITTER); sendSampleCount = false; } diff --git a/open-ephys.jucer b/open-ephys.jucer index eba47afc7ae7099e9bbc97800cc1cccf451d696a..3c996776dbf473a246555534a308e89edb04460b 100644 --- a/open-ephys.jucer +++ b/open-ephys.jucer @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<JUCERPROJECT id="ynSYIrr" name="open-ephys" projectType="guiapp" version="0.4.1" +<JUCERPROJECT id="ynSYIrr" name="open-ephys" projectType="guiapp" version="0.4.2" juceLinkage="amalg_multi" buildVST="1" buildRTAS="0" buildAU="1" pluginName="Juce Project" pluginDesc="Juce Project" pluginManufacturer="yourcompany" pluginManufacturerCode="Manu" pluginCode="Plug" pluginChannelConfigs="{1, 1}, {2, 2}"