Commit 98a05dfb authored by kaltenbe's avatar kaltenbe

deleted unnecessary files and added lmsSDR, lms7002m directories

parent 051a4e2a
# This is the CMakeCache file.
# For build in directory: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build
# It was generated by CMake: /usr/bin/cmake
# You can edit this file to change values found and used by cmake.
# If you do not want to change any of the values, simply exit the editor.
# If you do want to change a value, simply edit, save, and exit the editor.
# The syntax for the file is as follows:
# KEY:TYPE=VALUE
# KEY is the name of a variable in the cache.
# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
# VALUE is the current value for the KEY.
########################
# EXTERNAL cache entries
########################
//Path to a program.
CMAKE_AR:FILEPATH=/usr/bin/ar
//For backwards compatibility, what version of CMake commands and
// syntax should this version of CMake try to support.
CMAKE_BACKWARDS_COMPATIBILITY:STRING=2.4
//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or
// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.
CMAKE_BUILD_TYPE:STRING=
//Enable/Disable color output during build.
CMAKE_COLOR_MAKEFILE:BOOL=ON
//CXX compiler.
CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++
//Flags used by the compiler during all build types.
CMAKE_CXX_FLAGS:STRING=
//Flags used by the compiler during debug builds.
CMAKE_CXX_FLAGS_DEBUG:STRING=-g
//Flags used by the compiler during release minsize builds.
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
//Flags used by the compiler during release builds (/MD /Ob1 /Oi
// /Ot /Oy /Gs will produce slightly less optimized but smaller
// files).
CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
//Flags used by the compiler during Release with Debug Info builds.
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
//C compiler.
CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc
//Flags used by the compiler during all build types.
CMAKE_C_FLAGS:STRING=
//Flags used by the compiler during debug builds.
CMAKE_C_FLAGS_DEBUG:STRING=-g
//Flags used by the compiler during release minsize builds.
CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
//Flags used by the compiler during release builds (/MD /Ob1 /Oi
// /Ot /Oy /Gs will produce slightly less optimized but smaller
// files).
CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
//Flags used by the compiler during Release with Debug Info builds.
CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
//Flags used by the linker.
CMAKE_EXE_LINKER_FLAGS:STRING=' '
//Flags used by the linker during debug builds.
CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=
//Flags used by the linker during release minsize builds.
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=
//Flags used by the linker during release builds.
CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=
//Flags used by the linker during Release with Debug Info builds.
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
//Enable/Disable output of compile commands during generation.
CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=OFF
//Install path prefix, prepended onto install directories.
CMAKE_INSTALL_PREFIX:PATH=/usr/local
//Path to a program.
CMAKE_LINKER:FILEPATH=/usr/bin/ld
//Path to a program.
CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make
//Flags used by the linker during the creation of modules.
CMAKE_MODULE_LINKER_FLAGS:STRING=' '
//Flags used by the linker during debug builds.
CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=
//Flags used by the linker during release minsize builds.
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=
//Flags used by the linker during release builds.
CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=
//Flags used by the linker during Release with Debug Info builds.
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
//Path to a program.
CMAKE_NM:FILEPATH=/usr/bin/nm
//Path to a program.
CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy
//Path to a program.
CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump
//Value Computed by CMake
CMAKE_PROJECT_NAME:STATIC=Project
//Path to a program.
CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib
//Flags used by the linker during the creation of dll's.
CMAKE_SHARED_LINKER_FLAGS:STRING=' '
//Flags used by the linker during debug builds.
CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=
//Flags used by the linker during release minsize builds.
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=
//Flags used by the linker during release builds.
CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=
//Flags used by the linker during Release with Debug Info builds.
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=
//If set, runtime paths are not added when installing shared libraries,
// but are added when building.
CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
//If set, runtime paths are not added when using shared libraries.
CMAKE_SKIP_RPATH:BOOL=NO
//Flags used by the linker during the creation of static libraries.
CMAKE_STATIC_LINKER_FLAGS:STRING=
//Flags used by the linker during debug builds.
CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
//Flags used by the linker during release minsize builds.
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
//Flags used by the linker during release builds.
CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
//Flags used by the linker during Release with Debug Info builds.
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
//Path to a program.
CMAKE_STRIP:FILEPATH=/usr/bin/strip
//If true, cmake will use relative paths in makefiles and projects.
CMAKE_USE_RELATIVE_PATHS:BOOL=OFF
//If this value is on, makefiles will be generated without the
// .SILENT directive, and all commands will be echoed to the console
// during the make. This is useful for debugging only. With Visual
// Studio IDE projects all commands are done without /nologo.
CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE
//Single output directory for building all executables.
EXECUTABLE_OUTPUT_PATH:PATH=
//Single output directory for building all libraries.
LIBRARY_OUTPUT_PATH:PATH=
//Value Computed by CMake
Project_BINARY_DIR:STATIC=/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build
//Value Computed by CMake
Project_SOURCE_DIR:STATIC=/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C
//Dependencies for the target
Si5351C_LIB_DEPENDS:STATIC=general;LMS7002M;
########################
# INTERNAL cache entries
########################
//ADVANCED property for variable: CMAKE_AR
CMAKE_AR-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_BUILD_TOOL
CMAKE_BUILD_TOOL-ADVANCED:INTERNAL=1
//What is the target build tool cmake is generating for.
CMAKE_BUILD_TOOL:INTERNAL=/usr/bin/make
//This is the directory where this CMakeCache.txt was created
CMAKE_CACHEFILE_DIR:INTERNAL=/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build
//Major version of cmake used to create the current loaded cache
CMAKE_CACHE_MAJOR_VERSION:INTERNAL=2
//Minor version of cmake used to create the current loaded cache
CMAKE_CACHE_MINOR_VERSION:INTERNAL=8
//Patch version of cmake used to create the current loaded cache
CMAKE_CACHE_PATCH_VERSION:INTERNAL=12
//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE
CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1
//Path to CMake executable.
CMAKE_COMMAND:INTERNAL=/usr/bin/cmake
//Path to cpack program executable.
CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack
//Path to ctest program executable.
CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest
//ADVANCED property for variable: CMAKE_CXX_COMPILER
CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_COMPILER
CMAKE_C_COMPILER-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS
CMAKE_C_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//Path to cache edit program executable.
CMAKE_EDIT_COMMAND:INTERNAL=/usr/bin/ccmake
//Executable file format
CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS
CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG
CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE
CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS
CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1
//Name of generator.
CMAKE_GENERATOR:INTERNAL=Unix Makefiles
//Name of generator toolset.
CMAKE_GENERATOR_TOOLSET:INTERNAL=
//Start directory with the top level CMakeLists.txt file for this
// project
CMAKE_HOME_DIRECTORY:INTERNAL=/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C
//Install .so files without execute permission.
CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1
//ADVANCED property for variable: CMAKE_LINKER
CMAKE_LINKER-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MAKE_PROGRAM
CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS
CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG
CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE
CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_NM
CMAKE_NM-ADVANCED:INTERNAL=1
//number of local generators
CMAKE_NUMBER_OF_LOCAL_GENERATORS:INTERNAL=1
//ADVANCED property for variable: CMAKE_OBJCOPY
CMAKE_OBJCOPY-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_OBJDUMP
CMAKE_OBJDUMP-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_RANLIB
CMAKE_RANLIB-ADVANCED:INTERNAL=1
//Path to CMake installation.
CMAKE_ROOT:INTERNAL=/usr/share/cmake-2.8
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG
CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE
CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH
CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SKIP_RPATH
CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS
CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG
CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE
CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STRIP
CMAKE_STRIP-ADVANCED:INTERNAL=1
//uname command
CMAKE_UNAME:INTERNAL=/bin/uname
//ADVANCED property for variable: CMAKE_USE_RELATIVE_PATHS
CMAKE_USE_RELATIVE_PATHS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE
CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1
set(CMAKE_C_COMPILER "/usr/bin/cc")
set(CMAKE_C_COMPILER_ARG1 "")
set(CMAKE_C_COMPILER_ID "GNU")
set(CMAKE_C_COMPILER_VERSION "4.8.4")
set(CMAKE_C_PLATFORM_ID "Linux")
set(CMAKE_AR "/usr/bin/ar")
set(CMAKE_RANLIB "/usr/bin/ranlib")
set(CMAKE_LINKER "/usr/bin/ld")
set(CMAKE_COMPILER_IS_GNUCC 1)
set(CMAKE_C_COMPILER_LOADED 1)
set(CMAKE_C_COMPILER_WORKS TRUE)
set(CMAKE_C_ABI_COMPILED TRUE)
set(CMAKE_COMPILER_IS_MINGW )
set(CMAKE_COMPILER_IS_CYGWIN )
if(CMAKE_COMPILER_IS_CYGWIN)
set(CYGWIN 1)
set(UNIX 1)
endif()
set(CMAKE_C_COMPILER_ENV_VAR "CC")
if(CMAKE_COMPILER_IS_MINGW)
set(MINGW 1)
endif()
set(CMAKE_C_COMPILER_ID_RUN 1)
set(CMAKE_C_SOURCE_FILE_EXTENSIONS c)
set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
set(CMAKE_C_LINKER_PREFERENCE 10)
# Save compiler ABI information.
set(CMAKE_C_SIZEOF_DATA_PTR "8")
set(CMAKE_C_COMPILER_ABI "ELF")
set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
if(CMAKE_C_SIZEOF_DATA_PTR)
set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}")
endif()
if(CMAKE_C_COMPILER_ABI)
set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}")
endif()
if(CMAKE_C_LIBRARY_ARCHITECTURE)
set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
endif()
set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "c")
set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib")
set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
set(CMAKE_CXX_COMPILER "/usr/bin/c++")
set(CMAKE_CXX_COMPILER_ARG1 "")
set(CMAKE_CXX_COMPILER_ID "GNU")
set(CMAKE_CXX_COMPILER_VERSION "4.8.4")
set(CMAKE_CXX_PLATFORM_ID "Linux")
set(CMAKE_AR "/usr/bin/ar")
set(CMAKE_RANLIB "/usr/bin/ranlib")
set(CMAKE_LINKER "/usr/bin/ld")
set(CMAKE_COMPILER_IS_GNUCXX 1)
set(CMAKE_CXX_COMPILER_LOADED 1)
set(CMAKE_CXX_COMPILER_WORKS TRUE)
set(CMAKE_CXX_ABI_COMPILED TRUE)
set(CMAKE_COMPILER_IS_MINGW )
set(CMAKE_COMPILER_IS_CYGWIN )
if(CMAKE_COMPILER_IS_CYGWIN)
set(CYGWIN 1)
set(UNIX 1)
endif()
set(CMAKE_CXX_COMPILER_ENV_VAR "CXX")
if(CMAKE_COMPILER_IS_MINGW)
set(MINGW 1)
endif()
set(CMAKE_CXX_COMPILER_ID_RUN 1)
set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP)
set(CMAKE_CXX_LINKER_PREFERENCE 30)
set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1)
# Save compiler ABI information.
set(CMAKE_CXX_SIZEOF_DATA_PTR "8")
set(CMAKE_CXX_COMPILER_ABI "ELF")
set(CMAKE_CXX_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
if(CMAKE_CXX_SIZEOF_DATA_PTR)
set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}")
endif()
if(CMAKE_CXX_COMPILER_ABI)
set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}")
endif()
if(CMAKE_CXX_LIBRARY_ARCHITECTURE)
set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu")
endif()
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;c")
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib")
set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
set(CMAKE_HOST_SYSTEM "Linux-3.17.0-031700-lowlatency")
set(CMAKE_HOST_SYSTEM_NAME "Linux")
set(CMAKE_HOST_SYSTEM_VERSION "3.17.0-031700-lowlatency")
set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64")
set(CMAKE_SYSTEM "Linux-3.17.0-031700-lowlatency")
set(CMAKE_SYSTEM_NAME "Linux")
set(CMAKE_SYSTEM_VERSION "3.17.0-031700-lowlatency")
set(CMAKE_SYSTEM_PROCESSOR "x86_64")
set(CMAKE_CROSSCOMPILING "FALSE")
set(CMAKE_SYSTEM_LOADED 1)
#ifdef __cplusplus
# error "A C++ compiler has been selected for C."
#endif
/* Version number components: V=Version, R=Revision, P=Patch
Version date components: YYYY=Year, MM=Month, DD=Day */
#if defined(__18CXX)
# define ID_VOID_MAIN
#endif
#if defined(__INTEL_COMPILER) || defined(__ICC)
# define COMPILER_ID "Intel"
/* __INTEL_COMPILER = VRP */
# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
# if defined(__INTEL_COMPILER_BUILD_DATE)
/* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
# endif
#elif defined(__PATHCC__)
# define COMPILER_ID "PathScale"
# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
# if defined(__PATHCC_PATCHLEVEL__)
# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
# endif
#elif defined(__clang__)
# define COMPILER_ID "Clang"
# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
# define COMPILER_ID "Embarcadero"
# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
# define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__ & 0xFFFF)
#elif defined(__BORLANDC__)
# define COMPILER_ID "Borland"
/* __BORLANDC__ = 0xVRR */
# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
#elif defined(__WATCOMC__)
# define COMPILER_ID "Watcom"
/* __WATCOMC__ = VVRR */
# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
# define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100)
#elif defined(__SUNPRO_C)
# define COMPILER_ID "SunPro"
# if __SUNPRO_C >= 0x5100
/* __SUNPRO_C = 0xVRRP */
# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12)
# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF)
# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF)
# else
/* __SUNPRO_C = 0xVRP */
# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8)
# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF)
# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF)
# endif
#elif defined(__HP_cc)
# define COMPILER_ID "HP"
/* __HP_cc = VVRRPP */
# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000)
# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100)
# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100)
#elif defined(__DECC)
# define COMPILER_ID "Compaq"
/* __DECC_VER = VVRRTPPPP */
# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000)
# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100)
# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000)
#elif defined(__IBMC__)
# if defined(__COMPILER_VER__)
# define COMPILER_ID "zOS"
# else
# if __IBMC__ >= 800
# define COMPILER_ID "XL"
# else
# define COMPILER_ID "VisualAge"
# endif
/* __IBMC__ = VRP */
# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
# endif
#elif defined(__PGI)
# define COMPILER_ID "PGI"
# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
# if defined(__PGIC_PATCHLEVEL__)
# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
# endif
#elif defined(_CRAYC)
# define COMPILER_ID "Cray"
# define COMPILER_VERSION_MAJOR DEC(_RELEASE)
# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
#elif defined(__TI_COMPILER_VERSION__)
# define COMPILER_ID "TI"
/* __TI_COMPILER_VERSION__ = VVVRRRPPP */
# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
#elif defined(__TINYC__)
# define COMPILER_ID "TinyCC"
#elif defined(__SCO_VERSION__)
# define COMPILER_ID "SCO"
#elif defined(__GNUC__)
# define COMPILER_ID "GNU"
# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
# if defined(__GNUC_PATCHLEVEL__)
# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
# endif
#elif defined(_MSC_VER)
# define COMPILER_ID "MSVC"
/* _MSC_VER = VVRR */
# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
# if defined(_MSC_FULL_VER)
# if _MSC_VER >= 1400
/* _MSC_FULL_VER = VVRRPPPPP */
# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
# else
/* _MSC_FULL_VER = VVRRPPPP */
# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
# endif
# endif
# if defined(_MSC_BUILD)
# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
# endif
/* Analog VisualDSP++ >= 4.5.6 */
#elif defined(__VISUALDSPVERSION__)
# define COMPILER_ID "ADSP"
/* __VISUALDSPVERSION__ = 0xVVRRPP00 */
# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF)
/* Analog VisualDSP++ < 4.5.6 */
#elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
# define COMPILER_ID "ADSP"
/* IAR Systems compiler for embedded systems.
http://www.iar.com */
#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC)
# define COMPILER_ID "IAR"
/* sdcc, the small devices C compiler for embedded systems,
http://sdcc.sourceforge.net */
#elif defined(SDCC)
# define COMPILER_ID "SDCC"
/* SDCC = VRP */
# define COMPILER_VERSION_MAJOR DEC(SDCC/100)
# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10)
# define COMPILER_VERSION_PATCH DEC(SDCC % 10)
#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION)
# define COMPILER_ID "MIPSpro"
# if defined(_SGI_COMPILER_VERSION)
/* _SGI_COMPILER_VERSION = VRP */
# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100)
# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10)
# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10)
# else
/* _COMPILER_VERSION = VRP */
# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100)
# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10)
# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10)
# endif
/* This compiler is either not known or is too old to define an
identification macro. Try to identify the platform and guess that
it is the native compiler. */
#elif defined(__sgi)
# define COMPILER_ID "MIPSpro"
#elif defined(__hpux) || defined(__hpua)
# define COMPILER_ID "HP"
#else /* unknown compiler */
# define COMPILER_ID ""
#endif
/* Construct the string literal in pieces to prevent the source from
getting matched. Store it in a pointer rather than an array
because some compilers will just produce instructions to fill the
array rather than assigning a pointer to a static array. */
char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
/* Identify known platforms by name. */
#if defined(__linux) || defined(__linux__) || defined(linux)
# define PLATFORM_ID "Linux"
#elif defined(__CYGWIN__)
# define PLATFORM_ID "Cygwin"
#elif defined(__MINGW32__)
# define PLATFORM_ID "MinGW"
#elif defined(__APPLE__)
# define PLATFORM_ID "Darwin"
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
# define PLATFORM_ID "Windows"
#elif defined(__FreeBSD__) || defined(__FreeBSD)
# define PLATFORM_ID "FreeBSD"
#elif defined(__NetBSD__) || defined(__NetBSD)
# define PLATFORM_ID "NetBSD"
#elif defined(__OpenBSD__) || defined(__OPENBSD)
# define PLATFORM_ID "OpenBSD"
#elif defined(__sun) || defined(sun)
# define PLATFORM_ID "SunOS"
#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
# define PLATFORM_ID "AIX"
#elif defined(__sgi) || defined(__sgi__) || defined(_SGI)
# define PLATFORM_ID "IRIX"
#elif defined(__hpux) || defined(__hpux__)
# define PLATFORM_ID "HP-UX"
#elif defined(__HAIKU__)
# define PLATFORM_ID "Haiku"
#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
# define PLATFORM_ID "BeOS"
#elif defined(__QNX__) || defined(__QNXNTO__)
# define PLATFORM_ID "QNX"
#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
# define PLATFORM_ID "Tru64"
#elif defined(__riscos) || defined(__riscos__)
# define PLATFORM_ID "RISCos"
#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
# define PLATFORM_ID "SINIX"
#elif defined(__UNIX_SV__)
# define PLATFORM_ID "UNIX_SV"
#elif defined(__bsdos__)
# define PLATFORM_ID "BSDOS"
#elif defined(_MPRAS) || defined(MPRAS)
# define PLATFORM_ID "MP-RAS"
#elif defined(__osf) || defined(__osf__)
# define PLATFORM_ID "OSF1"
#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
# define PLATFORM_ID "SCO_SV"
#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
# define PLATFORM_ID "ULTRIX"
#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
# define PLATFORM_ID "Xenix"
#else /* unknown platform */
# define PLATFORM_ID ""
#endif
/* For windows compilers MSVC and Intel we can determine
the architecture of the compiler being used. This is because
the compilers do not have flags that can change the architecture,
but rather depend on which compiler is being used
*/
#if defined(_WIN32) && defined(_MSC_VER)
# if defined(_M_IA64)
# define ARCHITECTURE_ID "IA64"
# elif defined(_M_X64) || defined(_M_AMD64)
# define ARCHITECTURE_ID "x64"
# elif defined(_M_IX86)
# define ARCHITECTURE_ID "X86"
# elif defined(_M_ARM)
# define ARCHITECTURE_ID "ARM"
# elif defined(_M_MIPS)
# define ARCHITECTURE_ID "MIPS"
# elif defined(_M_SH)
# define ARCHITECTURE_ID "SHx"
# else /* unknown architecture */
# define ARCHITECTURE_ID ""
# endif
#else
# define ARCHITECTURE_ID ""
#endif
/* Convert integer to decimal digit literals. */
#define DEC(n) \
('0' + (((n) / 10000000)%10)), \
('0' + (((n) / 1000000)%10)), \
('0' + (((n) / 100000)%10)), \
('0' + (((n) / 10000)%10)), \
('0' + (((n) / 1000)%10)), \
('0' + (((n) / 100)%10)), \
('0' + (((n) / 10)%10)), \
('0' + ((n) % 10))
/* Convert integer to hex digit literals. */
#define HEX(n) \
('0' + ((n)>>28 & 0xF)), \
('0' + ((n)>>24 & 0xF)), \
('0' + ((n)>>20 & 0xF)), \
('0' + ((n)>>16 & 0xF)), \
('0' + ((n)>>12 & 0xF)), \
('0' + ((n)>>8 & 0xF)), \
('0' + ((n)>>4 & 0xF)), \
('0' + ((n) & 0xF))
/* Construct a string literal encoding the version number components. */
#ifdef COMPILER_VERSION_MAJOR
char const info_version[] = {
'I', 'N', 'F', 'O', ':',
'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
COMPILER_VERSION_MAJOR,
# ifdef COMPILER_VERSION_MINOR
'.', COMPILER_VERSION_MINOR,
# ifdef COMPILER_VERSION_PATCH
'.', COMPILER_VERSION_PATCH,
# ifdef COMPILER_VERSION_TWEAK
'.', COMPILER_VERSION_TWEAK,
# endif
# endif
# endif
']','\0'};
#endif
/* Construct the string literal in pieces to prevent the source from
getting matched. Store it in a pointer rather than an array
because some compilers will just produce instructions to fill the
array rather than assigning a pointer to a static array. */
char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
/*--------------------------------------------------------------------------*/
#ifdef ID_VOID_MAIN
void main() {}
#else
int main(int argc, char* argv[])
{
int require = 0;
require += info_compiler[argc];
require += info_platform[argc];
require += info_arch[argc];
#ifdef COMPILER_VERSION_MAJOR
require += info_version[argc];
#endif
(void)argv;
return require;
}
#endif
/* This source file must have a .cpp extension so that all C++ compilers
recognize the extension without flags. Borland does not know .cxx for
example. */
#ifndef __cplusplus
# error "A C compiler has been selected for C++."
#endif
/* Version number components: V=Version, R=Revision, P=Patch
Version date components: YYYY=Year, MM=Month, DD=Day */
#if defined(__COMO__)
# define COMPILER_ID "Comeau"
/* __COMO_VERSION__ = VRR */
# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100)
# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100)
#elif defined(__INTEL_COMPILER) || defined(__ICC)
# define COMPILER_ID "Intel"
/* __INTEL_COMPILER = VRP */
# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
# if defined(__INTEL_COMPILER_BUILD_DATE)
/* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
# endif
#elif defined(__PATHCC__)
# define COMPILER_ID "PathScale"
# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
# if defined(__PATHCC_PATCHLEVEL__)
# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
# endif
#elif defined(__clang__)
# define COMPILER_ID "Clang"
# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
# define COMPILER_ID "Embarcadero"
# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
# define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__ & 0xFFFF)
#elif defined(__BORLANDC__)
# define COMPILER_ID "Borland"
/* __BORLANDC__ = 0xVRR */
# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
#elif defined(__WATCOMC__)
# define COMPILER_ID "Watcom"
/* __WATCOMC__ = VVRR */
# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
# define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100)
#elif defined(__SUNPRO_CC)
# define COMPILER_ID "SunPro"
# if __SUNPRO_CC >= 0x5100
/* __SUNPRO_CC = 0xVRRP */
# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12)
# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF)
# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
# else
/* __SUNPRO_CC = 0xVRP */
# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8)
# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF)
# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
# endif
#elif defined(__HP_aCC)
# define COMPILER_ID "HP"
/* __HP_aCC = VVRRPP */
# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000)
# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100)
# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100)
#elif defined(__DECCXX)
# define COMPILER_ID "Compaq"
/* __DECCXX_VER = VVRRTPPPP */
# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000)
# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100)
# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000)
#elif defined(__IBMCPP__)
# if defined(__COMPILER_VER__)
# define COMPILER_ID "zOS"
# else
# if __IBMCPP__ >= 800
# define COMPILER_ID "XL"
# else
# define COMPILER_ID "VisualAge"
# endif
/* __IBMCPP__ = VRP */
# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
# endif
#elif defined(__PGI)
# define COMPILER_ID "PGI"
# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
# if defined(__PGIC_PATCHLEVEL__)
# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
# endif
#elif defined(_CRAYC)
# define COMPILER_ID "Cray"
# define COMPILER_VERSION_MAJOR DEC(_RELEASE)
# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
#elif defined(__TI_COMPILER_VERSION__)
# define COMPILER_ID "TI"
/* __TI_COMPILER_VERSION__ = VVVRRRPPP */
# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
#elif defined(__SCO_VERSION__)
# define COMPILER_ID "SCO"
#elif defined(__GNUC__)
# define COMPILER_ID "GNU"
# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
# if defined(__GNUC_PATCHLEVEL__)
# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
# endif
#elif defined(_MSC_VER)
# define COMPILER_ID "MSVC"
/* _MSC_VER = VVRR */
# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
# if defined(_MSC_FULL_VER)
# if _MSC_VER >= 1400
/* _MSC_FULL_VER = VVRRPPPPP */
# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
# else
/* _MSC_FULL_VER = VVRRPPPP */
# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
# endif
# endif
# if defined(_MSC_BUILD)
# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
# endif
/* Analog VisualDSP++ >= 4.5.6 */
#elif defined(__VISUALDSPVERSION__)
# define COMPILER_ID "ADSP"
/* __VISUALDSPVERSION__ = 0xVVRRPP00 */
# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF)
/* Analog VisualDSP++ < 4.5.6 */
#elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
# define COMPILER_ID "ADSP"
/* IAR Systems compiler for embedded systems.
http://www.iar.com */
#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC)
# define COMPILER_ID "IAR"
#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION)
# define COMPILER_ID "MIPSpro"
# if defined(_SGI_COMPILER_VERSION)
/* _SGI_COMPILER_VERSION = VRP */
# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100)
# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10)
# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10)
# else
/* _COMPILER_VERSION = VRP */
# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100)
# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10)
# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10)
# endif
/* This compiler is either not known or is too old to define an
identification macro. Try to identify the platform and guess that
it is the native compiler. */
#elif defined(__sgi)
# define COMPILER_ID "MIPSpro"
#elif defined(__hpux) || defined(__hpua)
# define COMPILER_ID "HP"
#else /* unknown compiler */
# define COMPILER_ID ""
#endif
/* Construct the string literal in pieces to prevent the source from
getting matched. Store it in a pointer rather than an array
because some compilers will just produce instructions to fill the
array rather than assigning a pointer to a static array. */
char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
/* Identify known platforms by name. */
#if defined(__linux) || defined(__linux__) || defined(linux)
# define PLATFORM_ID "Linux"
#elif defined(__CYGWIN__)
# define PLATFORM_ID "Cygwin"
#elif defined(__MINGW32__)
# define PLATFORM_ID "MinGW"
#elif defined(__APPLE__)
# define PLATFORM_ID "Darwin"
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
# define PLATFORM_ID "Windows"
#elif defined(__FreeBSD__) || defined(__FreeBSD)
# define PLATFORM_ID "FreeBSD"
#elif defined(__NetBSD__) || defined(__NetBSD)
# define PLATFORM_ID "NetBSD"
#elif defined(__OpenBSD__) || defined(__OPENBSD)
# define PLATFORM_ID "OpenBSD"
#elif defined(__sun) || defined(sun)
# define PLATFORM_ID "SunOS"
#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
# define PLATFORM_ID "AIX"
#elif defined(__sgi) || defined(__sgi__) || defined(_SGI)
# define PLATFORM_ID "IRIX"
#elif defined(__hpux) || defined(__hpux__)
# define PLATFORM_ID "HP-UX"
#elif defined(__HAIKU__)
# define PLATFORM_ID "Haiku"
#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
# define PLATFORM_ID "BeOS"
#elif defined(__QNX__) || defined(__QNXNTO__)
# define PLATFORM_ID "QNX"
#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
# define PLATFORM_ID "Tru64"
#elif defined(__riscos) || defined(__riscos__)
# define PLATFORM_ID "RISCos"
#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
# define PLATFORM_ID "SINIX"
#elif defined(__UNIX_SV__)
# define PLATFORM_ID "UNIX_SV"
#elif defined(__bsdos__)
# define PLATFORM_ID "BSDOS"
#elif defined(_MPRAS) || defined(MPRAS)
# define PLATFORM_ID "MP-RAS"
#elif defined(__osf) || defined(__osf__)
# define PLATFORM_ID "OSF1"
#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
# define PLATFORM_ID "SCO_SV"
#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
# define PLATFORM_ID "ULTRIX"
#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
# define PLATFORM_ID "Xenix"
#else /* unknown platform */
# define PLATFORM_ID ""
#endif
/* For windows compilers MSVC and Intel we can determine
the architecture of the compiler being used. This is because
the compilers do not have flags that can change the architecture,
but rather depend on which compiler is being used
*/
#if defined(_WIN32) && defined(_MSC_VER)
# if defined(_M_IA64)
# define ARCHITECTURE_ID "IA64"
# elif defined(_M_X64) || defined(_M_AMD64)
# define ARCHITECTURE_ID "x64"
# elif defined(_M_IX86)
# define ARCHITECTURE_ID "X86"
# elif defined(_M_ARM)
# define ARCHITECTURE_ID "ARM"
# elif defined(_M_MIPS)
# define ARCHITECTURE_ID "MIPS"
# elif defined(_M_SH)
# define ARCHITECTURE_ID "SHx"
# else /* unknown architecture */
# define ARCHITECTURE_ID ""
# endif
#else
# define ARCHITECTURE_ID ""
#endif
/* Convert integer to decimal digit literals. */
#define DEC(n) \
('0' + (((n) / 10000000)%10)), \
('0' + (((n) / 1000000)%10)), \
('0' + (((n) / 100000)%10)), \
('0' + (((n) / 10000)%10)), \
('0' + (((n) / 1000)%10)), \
('0' + (((n) / 100)%10)), \
('0' + (((n) / 10)%10)), \
('0' + ((n) % 10))
/* Convert integer to hex digit literals. */
#define HEX(n) \
('0' + ((n)>>28 & 0xF)), \
('0' + ((n)>>24 & 0xF)), \
('0' + ((n)>>20 & 0xF)), \
('0' + ((n)>>16 & 0xF)), \
('0' + ((n)>>12 & 0xF)), \
('0' + ((n)>>8 & 0xF)), \
('0' + ((n)>>4 & 0xF)), \
('0' + ((n) & 0xF))
/* Construct a string literal encoding the version number components. */
#ifdef COMPILER_VERSION_MAJOR
char const info_version[] = {
'I', 'N', 'F', 'O', ':',
'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
COMPILER_VERSION_MAJOR,
# ifdef COMPILER_VERSION_MINOR
'.', COMPILER_VERSION_MINOR,
# ifdef COMPILER_VERSION_PATCH
'.', COMPILER_VERSION_PATCH,
# ifdef COMPILER_VERSION_TWEAK
'.', COMPILER_VERSION_TWEAK,
# endif
# endif
# endif
']','\0'};
#endif
/* Construct the string literal in pieces to prevent the source from
getting matched. Store it in a pointer rather than an array
because some compilers will just produce instructions to fill the
array rather than assigning a pointer to a static array. */
char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
/*--------------------------------------------------------------------------*/
int main(int argc, char* argv[])
{
int require = 0;
require += info_compiler[argc];
require += info_platform[argc];
#ifdef COMPILER_VERSION_MAJOR
require += info_version[argc];
#endif
(void)argv;
return require;
}
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8
# Relative path conversion top directories.
SET(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C")
SET(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build")
# Force unix paths in dependencies.
SET(CMAKE_FORCE_UNIX_PATHS 1)
# The C and CXX include file regular expressions for this directory.
SET(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$")
SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$")
SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN})
SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN})
The system is: Linux - 3.17.0-031700-lowlatency - x86_64
Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded.
Compiler: /usr/bin/cc
Build flags:
Id flags:
The output was:
0
Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out"
The C compiler identification is GNU, found in "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/a.out"
Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded.
Compiler: /usr/bin/c++
Build flags:
Id flags:
The output was:
0
Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out"
The CXX compiler identification is GNU, found in "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdCXX/a.out"
Determining if the C compiler works passed with the following output:
Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp
Run Build Command:/usr/bin/make "cmTryCompileExec4097118404/fast"
/usr/bin/make -f CMakeFiles/cmTryCompileExec4097118404.dir/build.make CMakeFiles/cmTryCompileExec4097118404.dir/build
make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp'
/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1
Building C object CMakeFiles/cmTryCompileExec4097118404.dir/testCCompiler.c.o
/usr/bin/cc -o CMakeFiles/cmTryCompileExec4097118404.dir/testCCompiler.c.o -c /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/testCCompiler.c
Linking C executable cmTryCompileExec4097118404
/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec4097118404.dir/link.txt --verbose=1
/usr/bin/cc CMakeFiles/cmTryCompileExec4097118404.dir/testCCompiler.c.o -o cmTryCompileExec4097118404 -rdynamic
make[1]: Leaving directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp'
Detecting C compiler ABI info compiled with the following output:
Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp
Run Build Command:/usr/bin/make "cmTryCompileExec3603593924/fast"
/usr/bin/make -f CMakeFiles/cmTryCompileExec3603593924.dir/build.make CMakeFiles/cmTryCompileExec3603593924.dir/build
make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp'
/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1
Building C object CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o
/usr/bin/cc -o CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-2.8/Modules/CMakeCCompilerABI.c
Linking C executable cmTryCompileExec3603593924
/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec3603593924.dir/link.txt --verbose=1
/usr/bin/cc -v CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -o cmTryCompileExec3603593924 -rdynamic
Using built-in specs.
COLLECT_GCC=/usr/bin/cc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec3603593924' '-rdynamic' '-mtune=generic' '-march=x86-64'
/usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec3603593924 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o
make[1]: Leaving directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp'
Parsed C implicit link information from above output:
link line regex: [^( *|.*[/\])(ld|([^/\]+-)?ld|collect2)[^/\]*( |$)]
ignore line: [Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp]
ignore line: []
ignore line: [Run Build Command:/usr/bin/make "cmTryCompileExec3603593924/fast"]
ignore line: [/usr/bin/make -f CMakeFiles/cmTryCompileExec3603593924.dir/build.make CMakeFiles/cmTryCompileExec3603593924.dir/build]
ignore line: [make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp']
ignore line: [/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1]
ignore line: [Building C object CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o]
ignore line: [/usr/bin/cc -o CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-2.8/Modules/CMakeCCompilerABI.c]
ignore line: [Linking C executable cmTryCompileExec3603593924]
ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec3603593924.dir/link.txt --verbose=1]
ignore line: [/usr/bin/cc -v CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -o cmTryCompileExec3603593924 -rdynamic ]
ignore line: [Using built-in specs.]
ignore line: [COLLECT_GCC=/usr/bin/cc]
ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper]
ignore line: [Target: x86_64-linux-gnu]
ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu]
ignore line: [Thread model: posix]
ignore line: [gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) ]
ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/]
ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/]
ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec3603593924' '-rdynamic' '-mtune=generic' '-march=x86-64']
link line: [ /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec3603593924 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o]
arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/collect2] ==> ignore
arg [--sysroot=/] ==> ignore
arg [--build-id] ==> ignore
arg [--eh-frame-hdr] ==> ignore
arg [-m] ==> ignore
arg [elf_x86_64] ==> ignore
arg [--hash-style=gnu] ==> ignore
arg [--as-needed] ==> ignore
arg [-export-dynamic] ==> ignore
arg [-dynamic-linker] ==> ignore
arg [/lib64/ld-linux-x86-64.so.2] ==> ignore
arg [-zrelro] ==> ignore
arg [-o] ==> ignore
arg [cmTryCompileExec3603593924] ==> ignore
arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o] ==> ignore
arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o] ==> ignore
arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o] ==> ignore
arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8]
arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu]
arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib]
arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu]
arg [-L/lib/../lib] ==> dir [/lib/../lib]
arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu]
arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib]
arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..]
arg [CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o] ==> ignore
arg [-lgcc] ==> lib [gcc]
arg [--as-needed] ==> ignore
arg [-lgcc_s] ==> lib [gcc_s]
arg [--no-as-needed] ==> ignore
arg [-lc] ==> lib [c]
arg [-lgcc] ==> lib [gcc]
arg [--as-needed] ==> ignore
arg [-lgcc_s] ==> lib [gcc_s]
arg [--no-as-needed] ==> ignore
arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o] ==> ignore
arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o] ==> ignore
remove lib [gcc]
remove lib [gcc_s]
remove lib [gcc]
remove lib [gcc_s]
collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> [/usr/lib/gcc/x86_64-linux-gnu/4.8]
collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> [/usr/lib]
collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu]
collapse library dir [/lib/../lib] ==> [/lib]
collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
collapse library dir [/usr/lib/../lib] ==> [/usr/lib]
collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> [/usr/lib]
implicit libs: [c]
implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib]
implicit fwks: []
Determining if the CXX compiler works passed with the following output:
Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp
Run Build Command:/usr/bin/make "cmTryCompileExec997608794/fast"
/usr/bin/make -f CMakeFiles/cmTryCompileExec997608794.dir/build.make CMakeFiles/cmTryCompileExec997608794.dir/build
make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp'
/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1
Building CXX object CMakeFiles/cmTryCompileExec997608794.dir/testCXXCompiler.cxx.o
/usr/bin/c++ -o CMakeFiles/cmTryCompileExec997608794.dir/testCXXCompiler.cxx.o -c /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/testCXXCompiler.cxx
Linking CXX executable cmTryCompileExec997608794
/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec997608794.dir/link.txt --verbose=1
/usr/bin/c++ CMakeFiles/cmTryCompileExec997608794.dir/testCXXCompiler.cxx.o -o cmTryCompileExec997608794 -rdynamic
make[1]: Leaving directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp'
Detecting CXX compiler ABI info compiled with the following output:
Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp
Run Build Command:/usr/bin/make "cmTryCompileExec2573420878/fast"
/usr/bin/make -f CMakeFiles/cmTryCompileExec2573420878.dir/build.make CMakeFiles/cmTryCompileExec2573420878.dir/build
make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp'
/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1
Building CXX object CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o
/usr/bin/c++ -o CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-2.8/Modules/CMakeCXXCompilerABI.cpp
Linking CXX executable cmTryCompileExec2573420878
/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec2573420878.dir/link.txt --verbose=1
/usr/bin/c++ -v CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -o cmTryCompileExec2573420878 -rdynamic
Using built-in specs.
COLLECT_GCC=/usr/bin/c++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec2573420878' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
/usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec2573420878 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o
make[1]: Leaving directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp'
Parsed CXX implicit link information from above output:
link line regex: [^( *|.*[/\])(ld|([^/\]+-)?ld|collect2)[^/\]*( |$)]
ignore line: [Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp]
ignore line: []
ignore line: [Run Build Command:/usr/bin/make "cmTryCompileExec2573420878/fast"]
ignore line: [/usr/bin/make -f CMakeFiles/cmTryCompileExec2573420878.dir/build.make CMakeFiles/cmTryCompileExec2573420878.dir/build]
ignore line: [make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp']
ignore line: [/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1]
ignore line: [Building CXX object CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o]
ignore line: [/usr/bin/c++ -o CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-2.8/Modules/CMakeCXXCompilerABI.cpp]
ignore line: [Linking CXX executable cmTryCompileExec2573420878]
ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec2573420878.dir/link.txt --verbose=1]
ignore line: [/usr/bin/c++ -v CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -o cmTryCompileExec2573420878 -rdynamic ]
ignore line: [Using built-in specs.]
ignore line: [COLLECT_GCC=/usr/bin/c++]
ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper]
ignore line: [Target: x86_64-linux-gnu]
ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu]
ignore line: [Thread model: posix]
ignore line: [gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) ]
ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/]
ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/]
ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec2573420878' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64']
link line: [ /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec2573420878 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o]
arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/collect2] ==> ignore
arg [--sysroot=/] ==> ignore
arg [--build-id] ==> ignore
arg [--eh-frame-hdr] ==> ignore
arg [-m] ==> ignore
arg [elf_x86_64] ==> ignore
arg [--hash-style=gnu] ==> ignore
arg [--as-needed] ==> ignore
arg [-export-dynamic] ==> ignore
arg [-dynamic-linker] ==> ignore
arg [/lib64/ld-linux-x86-64.so.2] ==> ignore
arg [-zrelro] ==> ignore
arg [-o] ==> ignore
arg [cmTryCompileExec2573420878] ==> ignore
arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o] ==> ignore
arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o] ==> ignore
arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o] ==> ignore
arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8]
arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu]
arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib]
arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu]
arg [-L/lib/../lib] ==> dir [/lib/../lib]
arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu]
arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib]
arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..]
arg [CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore
arg [-lstdc++] ==> lib [stdc++]
arg [-lm] ==> lib [m]
arg [-lgcc_s] ==> lib [gcc_s]
arg [-lgcc] ==> lib [gcc]
arg [-lc] ==> lib [c]
arg [-lgcc_s] ==> lib [gcc_s]
arg [-lgcc] ==> lib [gcc]
arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o] ==> ignore
arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o] ==> ignore
remove lib [gcc_s]
remove lib [gcc]
remove lib [gcc_s]
remove lib [gcc]
collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> [/usr/lib/gcc/x86_64-linux-gnu/4.8]
collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> [/usr/lib]
collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu]
collapse library dir [/lib/../lib] ==> [/lib]
collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu]
collapse library dir [/usr/lib/../lib] ==> [/usr/lib]
collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> [/usr/lib]
implicit libs: [stdc++;m;c]
implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib]
implicit fwks: []
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8
# The generator used is:
SET(CMAKE_DEPENDS_GENERATOR "Unix Makefiles")
# The top level Makefile was generated from the following files:
SET(CMAKE_MAKEFILE_DEPENDS
"CMakeCache.txt"
"../CMakeLists.txt"
"CMakeFiles/2.8.12.2/CMakeCCompiler.cmake"
"CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake"
"CMakeFiles/2.8.12.2/CMakeSystem.cmake"
"/usr/share/cmake-2.8/Modules/CMakeCInformation.cmake"
"/usr/share/cmake-2.8/Modules/CMakeCXXInformation.cmake"
"/usr/share/cmake-2.8/Modules/CMakeCommonLanguageInclude.cmake"
"/usr/share/cmake-2.8/Modules/CMakeGenericSystem.cmake"
"/usr/share/cmake-2.8/Modules/CMakeSystemSpecificInformation.cmake"
"/usr/share/cmake-2.8/Modules/Compiler/GNU-C.cmake"
"/usr/share/cmake-2.8/Modules/Compiler/GNU-CXX.cmake"
"/usr/share/cmake-2.8/Modules/Compiler/GNU.cmake"
"/usr/share/cmake-2.8/Modules/Platform/Linux-GNU-C.cmake"
"/usr/share/cmake-2.8/Modules/Platform/Linux-GNU-CXX.cmake"
"/usr/share/cmake-2.8/Modules/Platform/Linux-GNU.cmake"
"/usr/share/cmake-2.8/Modules/Platform/Linux.cmake"
"/usr/share/cmake-2.8/Modules/Platform/UnixPaths.cmake"
)
# The corresponding makefile is:
SET(CMAKE_MAKEFILE_OUTPUTS
"Makefile"
"CMakeFiles/cmake.check_cache"
)
# Byproducts of CMake generate step:
SET(CMAKE_MAKEFILE_PRODUCTS
"CMakeFiles/CMakeDirectoryInformation.cmake"
)
# Dependency information for all targets:
SET(CMAKE_DEPEND_INFO_FILES
"CMakeFiles/Si5351C.dir/DependInfo.cmake"
)
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
# The main recursive all target
all:
.PHONY : all
# The main recursive preinstall target
preinstall:
.PHONY : preinstall
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
# The shell in which to execute make rules.
SHELL = /bin/sh
# The CMake executable.
CMAKE_COMMAND = /usr/bin/cmake
# The command to remove a file.
RM = /usr/bin/cmake -E remove -f
# Escaping for special characters.
EQUALS = =
# The program to use to edit the cache.
CMAKE_EDIT_COMMAND = /usr/bin/ccmake
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build
#=============================================================================
# Target rules for target CMakeFiles/Si5351C.dir
# All Build rule for target.
CMakeFiles/Si5351C.dir/all:
$(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/depend
$(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/build
$(CMAKE_COMMAND) -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles 1
@echo "Built target Si5351C"
.PHONY : CMakeFiles/Si5351C.dir/all
# Include target in all.
all: CMakeFiles/Si5351C.dir/all
.PHONY : all
# Build rule for subdir invocation for target.
CMakeFiles/Si5351C.dir/rule: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles 1
$(MAKE) -f CMakeFiles/Makefile2 CMakeFiles/Si5351C.dir/all
$(CMAKE_COMMAND) -E cmake_progress_start /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles 0
.PHONY : CMakeFiles/Si5351C.dir/rule
# Convenience name for target.
Si5351C: CMakeFiles/Si5351C.dir/rule
.PHONY : Si5351C
# clean rule for target.
CMakeFiles/Si5351C.dir/clean:
$(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/clean
.PHONY : CMakeFiles/Si5351C.dir/clean
# clean rule for target.
clean: CMakeFiles/Si5351C.dir/clean
.PHONY : clean
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
.PHONY : cmake_check_build_system
#IncludeRegexLine: ^[ ]*#[ ]*(include|import)[ ]*[<"]([^">]+)([">])
#IncludeRegexScan: ^.*$
#IncludeRegexComplain: ^$
#IncludeRegexTransform:
# The set of languages for which implicit dependencies are needed:
SET(CMAKE_DEPENDS_LANGUAGES
"CXX"
)
# The set of files for implicit dependencies of each language:
SET(CMAKE_DEPENDS_CHECK_CXX
"/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp" "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/Si5351C.o"
)
SET(CMAKE_CXX_COMPILER_ID "GNU")
# Targets to which this target links.
SET(CMAKE_TARGET_LINKED_INFO_FILES
)
# The include file search paths:
SET(CMAKE_C_TARGET_INCLUDE_PATH
"../../lms7002m"
".."
)
SET(CMAKE_CXX_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH})
SET(CMAKE_Fortran_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH})
SET(CMAKE_ASM_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH})
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
# The shell in which to execute make rules.
SHELL = /bin/sh
# The CMake executable.
CMAKE_COMMAND = /usr/bin/cmake
# The command to remove a file.
RM = /usr/bin/cmake -E remove -f
# Escaping for special characters.
EQUALS = =
# The program to use to edit the cache.
CMAKE_EDIT_COMMAND = /usr/bin/ccmake
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build
# Include any dependencies generated for this target.
include CMakeFiles/Si5351C.dir/depend.make
# Include the progress variables for this target.
include CMakeFiles/Si5351C.dir/progress.make
# Include the compile flags for this target's objects.
include CMakeFiles/Si5351C.dir/flags.make
CMakeFiles/Si5351C.dir/Si5351C.o: CMakeFiles/Si5351C.dir/flags.make
CMakeFiles/Si5351C.dir/Si5351C.o: ../Si5351C.cpp
$(CMAKE_COMMAND) -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles $(CMAKE_PROGRESS_1)
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Building CXX object CMakeFiles/Si5351C.dir/Si5351C.o"
/usr/bin/c++ $(CXX_DEFINES) $(CXX_FLAGS) -o CMakeFiles/Si5351C.dir/Si5351C.o -c /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp
CMakeFiles/Si5351C.dir/Si5351C.i: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/Si5351C.dir/Si5351C.i"
/usr/bin/c++ $(CXX_DEFINES) $(CXX_FLAGS) -E /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp > CMakeFiles/Si5351C.dir/Si5351C.i
CMakeFiles/Si5351C.dir/Si5351C.s: cmake_force
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/Si5351C.dir/Si5351C.s"
/usr/bin/c++ $(CXX_DEFINES) $(CXX_FLAGS) -S /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp -o CMakeFiles/Si5351C.dir/Si5351C.s
CMakeFiles/Si5351C.dir/Si5351C.o.requires:
.PHONY : CMakeFiles/Si5351C.dir/Si5351C.o.requires
CMakeFiles/Si5351C.dir/Si5351C.o.provides: CMakeFiles/Si5351C.dir/Si5351C.o.requires
$(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/Si5351C.o.provides.build
.PHONY : CMakeFiles/Si5351C.dir/Si5351C.o.provides
CMakeFiles/Si5351C.dir/Si5351C.o.provides.build: CMakeFiles/Si5351C.dir/Si5351C.o
# Object files for target Si5351C
Si5351C_OBJECTS = \
"CMakeFiles/Si5351C.dir/Si5351C.o"
# External object files for target Si5351C
Si5351C_EXTERNAL_OBJECTS =
libSi5351C.a: CMakeFiles/Si5351C.dir/Si5351C.o
libSi5351C.a: CMakeFiles/Si5351C.dir/build.make
libSi5351C.a: CMakeFiles/Si5351C.dir/link.txt
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --red --bold "Linking CXX static library libSi5351C.a"
$(CMAKE_COMMAND) -P CMakeFiles/Si5351C.dir/cmake_clean_target.cmake
$(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/Si5351C.dir/link.txt --verbose=$(VERBOSE)
# Rule to build all files generated by this target.
CMakeFiles/Si5351C.dir/build: libSi5351C.a
.PHONY : CMakeFiles/Si5351C.dir/build
CMakeFiles/Si5351C.dir/requires: CMakeFiles/Si5351C.dir/Si5351C.o.requires
.PHONY : CMakeFiles/Si5351C.dir/requires
CMakeFiles/Si5351C.dir/clean:
$(CMAKE_COMMAND) -P CMakeFiles/Si5351C.dir/cmake_clean.cmake
.PHONY : CMakeFiles/Si5351C.dir/clean
CMakeFiles/Si5351C.dir/depend:
cd /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/DependInfo.cmake --color=$(COLOR)
.PHONY : CMakeFiles/Si5351C.dir/depend
FILE(REMOVE_RECURSE
"CMakeFiles/Si5351C.dir/Si5351C.o"
"libSi5351C.pdb"
"libSi5351C.a"
)
# Per-language clean rules from dependency scanning.
FOREACH(lang CXX)
INCLUDE(CMakeFiles/Si5351C.dir/cmake_clean_${lang}.cmake OPTIONAL)
ENDFOREACH(lang)
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8
CMakeFiles/Si5351C.dir/Si5351C.o
/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp
/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.h
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8
CMakeFiles/Si5351C.dir/Si5351C.o: ../Si5351C.cpp
CMakeFiles/Si5351C.dir/Si5351C.o: ../Si5351C.h
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8
# compile CXX with /usr/bin/c++
CXX_FLAGS = -std=c++11 -I/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/../lms7002m -I/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C
CXX_DEFINES =
/usr/bin/ar cr libSi5351C.a CMakeFiles/Si5351C.dir/Si5351C.o
/usr/bin/ranlib libSi5351C.a
/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir
# This file is generated by cmake for dependency checking of the CMakeCache.txt file
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
# The shell in which to execute make rules.
SHELL = /bin/sh
# The CMake executable.
CMAKE_COMMAND = /usr/bin/cmake
# The command to remove a file.
RM = /usr/bin/cmake -E remove -f
# Escaping for special characters.
EQUALS = =
# The program to use to edit the cache.
CMAKE_EDIT_COMMAND = /usr/bin/ccmake
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target edit_cache
edit_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
/usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# Special rule for the target rebuild_cache
rebuild_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
/usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# The main all target
all: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/progress.marks
$(MAKE) -f CMakeFiles/Makefile2 all
$(CMAKE_COMMAND) -E cmake_progress_start /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles 0
.PHONY : all
# The main clean target
clean:
$(MAKE) -f CMakeFiles/Makefile2 clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
$(MAKE) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall/fast
# clear depends
depend:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
.PHONY : depend
#=============================================================================
# Target rules for targets named Si5351C
# Build rule for target.
Si5351C: cmake_check_build_system
$(MAKE) -f CMakeFiles/Makefile2 Si5351C
.PHONY : Si5351C
# fast build rule for target.
Si5351C/fast:
$(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/build
.PHONY : Si5351C/fast
# target to build an object file
Si5351C.o:
$(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/Si5351C.o
.PHONY : Si5351C.o
# target to preprocess a source file
Si5351C.i:
$(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/Si5351C.i
.PHONY : Si5351C.i
# target to generate assembly for a file
Si5351C.s:
$(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/Si5351C.s
.PHONY : Si5351C.s
# Help Target
help:
@echo "The following are some of the valid targets for this Makefile:"
@echo "... all (the default if no target is provided)"
@echo "... clean"
@echo "... depend"
@echo "... Si5351C"
@echo "... edit_cache"
@echo "... rebuild_cache"
@echo "... Si5351C.o"
@echo "... Si5351C.i"
@echo "... Si5351C.s"
.PHONY : help
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
.PHONY : cmake_check_build_system
# Install script for directory: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C
# Set the install prefix
IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
SET(CMAKE_INSTALL_PREFIX "/usr/local")
ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX)
STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
IF(BUILD_TYPE)
STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
ELSE(BUILD_TYPE)
SET(CMAKE_INSTALL_CONFIG_NAME "")
ENDIF(BUILD_TYPE)
MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
# Set the component getting installed.
IF(NOT CMAKE_INSTALL_COMPONENT)
IF(COMPONENT)
MESSAGE(STATUS "Install component: \"${COMPONENT}\"")
SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
ELSE(COMPONENT)
SET(CMAKE_INSTALL_COMPONENT)
ENDIF(COMPONENT)
ENDIF(NOT CMAKE_INSTALL_COMPONENT)
# Install shared libraries without execute permission?
IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
SET(CMAKE_INSTALL_SO_NO_EXE "1")
ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
IF(CMAKE_INSTALL_COMPONENT)
SET(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt")
ELSE(CMAKE_INSTALL_COMPONENT)
SET(CMAKE_INSTALL_MANIFEST "install_manifest.txt")
ENDIF(CMAKE_INSTALL_COMPONENT)
FILE(WRITE "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/${CMAKE_INSTALL_MANIFEST}" "")
FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES})
FILE(APPEND "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/${CMAKE_INSTALL_MANIFEST}" "${file}\n")
ENDFOREACH(file)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE TYPE INTERNAL FORCE)
project("lms7api")
#include modules for finding FFTW and CyAPI
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
cmake_policy(SET CMP0015 OLD)
if(${CMAKE_MAJOR_VERSION} GREATER 2)
cmake_policy(SET CMP0043 NEW)
endif()
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
if(CMAKE_COMPILER_IS_GNUCXX)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
endif()
# set up include-directories
include_directories(
"${PROJECT_SOURCE_DIR}"
"${PROJECT_BINARY_DIR}"
cpp-feather-ini-parser
)
set(LMS7002M_src_files
LMS7002M.cpp
LMS7002M_parameters.cpp
LMS7002M_statuses.cpp
LMS7002M_filtersCalibration.cpp
lmsComms.cpp
LMS7002M_RegistersMap.cpp
)
set(ENABLE_USB_CONNECTION "YES" CACHE BOOL INTERNAL)
set(ENABLE_SPI_CONNECTION "NO" CACHE BOOL INTERNAL)
set(CONNECTION_MANAGER_DIR connectionManager)
set(connectionManager_src_files
${CONNECTION_MANAGER_DIR}/ConnectionManager.cpp
${CONNECTION_MANAGER_DIR}/ConnectionCOM.cpp
${CONNECTION_MANAGER_DIR}/ConnectionManager.h
${CONNECTION_MANAGER_DIR}/ConnectionCOM.h
)
if(ENABLE_USB_CONNECTION)
list(APPEND connectionManager_src_files ${CONNECTION_MANAGER_DIR}/ConnectionUSB.cpp ${CONNECTION_MANAGER_DIR}/ConnectionUSB.h)
add_definitions(-DENABLE_USB_CONNECTION)
endif()
if(ENABLE_SPI_CONNECTION)
list(APPEND connectionManager_src_files ${CONNECTION_MANAGER_DIR}/ConnectionSPI.cpp ${CONNECTION_MANAGER_DIR}/ConnectionSPI.h)
add_definitions(-DENABLE_SPI_CONNECTION)
endif()
add_library(LMS7002M STATIC ${LMS7002M_src_files} ${connectionManager_src_files})
target_include_directories(LMS7002M PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
if(WIN32 AND ENABLE_USB_CONNECTION)
find_package(CyAPI REQUIRED)
LINK_DIRECTORIES(${CYAPI_LIBRARIES})
include_directories(${CYAPI_INCLUDE_DIRS})
set(CONNECTION_MANAGER_LIBS ${CYAPI_LIBRARIES} SetupAPI)
target_link_libraries(LMS7002M ${CONNECTION_MANAGER_LIBS})
endif()
if(UNIX AND ENABLE_USB_CONNECTION)
set(CONNECTION_MANAGER_LIBS usb-1.0 -lpthread)
target_link_libraries(LMS7002M ${CONNECTION_MANAGER_LIBS})
endif()
/**
@file LMS7002M.cpp
@author Lime Microsystems (www.limemicro.com)
@brief Implementation of LMS7002M transceiver configuring
*/
#include "LMS7002M.h"
#include <stdio.h>
#include <set>
#include "lmsComms.h"
#include "INI.h"
#include <cmath>
#include <iostream>
#include <algorithm>
#include "LMS7002M_RegistersMap.h"
#include <chrono>
#include <thread>
float_type LMS7002M::gVCO_frequency_table[3][2] = { { 3800, 5222 }, { 4961, 6754 }, {6306, 7714} };
float_type LMS7002M::gCGEN_VCO_frequencies[2] = {2000, 2700};
///define for parameter enumeration if prefix might be needed
#define LMS7param(id) id
//module addresses needs to be sorted in ascending order
const uint16_t LMS7002M::readOnlyRegisters[] = { 0x002F, 0x008C, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x0123, 0x0209, 0x020A, 0x020B, 0x040E, 0x040F };
const uint16_t LMS7002M::readOnlyRegistersMasks[] = { 0x0000, 0x0FFF, 0x007F, 0x0000, 0x0000, 0x0000, 0x0000, 0x003F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };
/** @brief Simple logging function to print status messages
@param text message to print
@param type message type for filtering specific information
*/
void LMS7002M::Log(const char* text, LogType type)
{
switch(type)
{
case LOG_INFO:
printf("%s\n", text);
break;
case LOG_WARNING:
printf("Warning: %s\n", text);
break;
case LOG_ERROR:
printf("ERROR: %s\n", text);
break;
case LOG_DATA:
printf("DATA: %s\n", text);
break;
}
}
LMS7002M::LMS7002M() : controlPort(NULL), mRegistersMap(new LMS7002M_RegistersMap())
{
mRefClkSXR_MHz = 30.72;
mRefClkSXT_MHz = 30.72;
}
/** @brief Creates LMS7002M main control object, it requires LMScomms to communicate with chip
@param controlPort data connection for controlling LMS7002 chip registers
*/
LMS7002M::LMS7002M(LMScomms* controlPort) :
controlPort(controlPort), mRegistersMap(new LMS7002M_RegistersMap())
{
mRefClkSXR_MHz = 30.72;
mRefClkSXT_MHz = 30.72;
//memory intervals for registers tests and calibration algorithms
MemorySectionAddresses[LimeLight][0] = 0x0020;
MemorySectionAddresses[LimeLight][1] = 0x002F;
MemorySectionAddresses[EN_DIR][0] = 0x0081;
MemorySectionAddresses[EN_DIR][1] = 0x0081;
MemorySectionAddresses[AFE][0] = 0x0082;
MemorySectionAddresses[AFE][1] = 0x0082;
MemorySectionAddresses[BIAS][0] = 0x0084;
MemorySectionAddresses[BIAS][1] = 0x0084;
MemorySectionAddresses[XBUF][0] = 0x0085;
MemorySectionAddresses[XBUF][1] = 0x0085;
MemorySectionAddresses[CGEN][0] = 0x0086;
MemorySectionAddresses[CGEN][1] = 0x008C;
MemorySectionAddresses[LDO][0] = 0x0092;
MemorySectionAddresses[LDO][1] = 0x00A7;
MemorySectionAddresses[BIST][0] = 0x00A8;
MemorySectionAddresses[BIST][1] = 0x00AC;
MemorySectionAddresses[CDS][0] = 0x00AD;
MemorySectionAddresses[CDS][1] = 0x00AE;
MemorySectionAddresses[TRF][0] = 0x0100;
MemorySectionAddresses[TRF][1] = 0x0104;
MemorySectionAddresses[TBB][0] = 0x0105;
MemorySectionAddresses[TBB][1] = 0x010A;
MemorySectionAddresses[RFE][0] = 0x010C;
MemorySectionAddresses[RFE][1] = 0x0114;
MemorySectionAddresses[RBB][0] = 0x0115;
MemorySectionAddresses[RBB][1] = 0x011A;
MemorySectionAddresses[SX][0] = 0x011C;
MemorySectionAddresses[SX][1] = 0x0124;
MemorySectionAddresses[TxTSP][0] = 0x0200;
MemorySectionAddresses[TxTSP][1] = 0x020C;
MemorySectionAddresses[TxNCO][0] = 0x0240;
MemorySectionAddresses[TxNCO][1] = 0x0261;
MemorySectionAddresses[TxGFIR1][0] = 0x0280;
MemorySectionAddresses[TxGFIR1][1] = 0x02A7;
MemorySectionAddresses[TxGFIR2][0] = 0x02C0;
MemorySectionAddresses[TxGFIR2][1] = 0x02E7;
MemorySectionAddresses[TxGFIR3a][0] = 0x0300;
MemorySectionAddresses[TxGFIR3a][1] = 0x0327;
MemorySectionAddresses[TxGFIR3b][0] = 0x0340;
MemorySectionAddresses[TxGFIR3b][1] = 0x0367;
MemorySectionAddresses[TxGFIR3c][0] = 0x0380;
MemorySectionAddresses[TxGFIR3c][1] = 0x03A7;
MemorySectionAddresses[RxTSP][0] = 0x0400;
MemorySectionAddresses[RxTSP][1] = 0x040F;
MemorySectionAddresses[RxNCO][0] = 0x0440;
MemorySectionAddresses[RxNCO][1] = 0x0461;
MemorySectionAddresses[RxGFIR1][0] = 0x0480;
MemorySectionAddresses[RxGFIR1][1] = 0x04A7;
MemorySectionAddresses[RxGFIR2][0] = 0x04C0;
MemorySectionAddresses[RxGFIR2][1] = 0x04E7;
MemorySectionAddresses[RxGFIR3a][0] = 0x0500;
MemorySectionAddresses[RxGFIR3a][1] = 0x0527;
MemorySectionAddresses[RxGFIR3b][0] = 0x0540;
MemorySectionAddresses[RxGFIR3b][1] = 0x0567;
MemorySectionAddresses[RxGFIR3c][0] = 0x0580;
MemorySectionAddresses[RxGFIR3c][1] = 0x05A7;
mRegistersMap->InitializeDefaultValues(LMS7parameterList);
}
LMS7002M::~LMS7002M()
{
}
/** @brief Sends reset signal to chip, after reset enables B channel controls
@return 0-success, other-failure
*/
liblms7_status LMS7002M::ResetChip()
{
if (controlPort == NULL)
return LIBLMS7_NO_CONNECTION_MANAGER;
if (controlPort->IsOpen() == false)
return LIBLMS7_NOT_CONNECTED;
LMScomms::GenericPacket pkt;
pkt.cmd = CMD_LMS7002_RST;
pkt.outBuffer.push_back(LMS_RST_PULSE);
controlPort->TransferPacket(pkt);
if (pkt.status == STATUS_COMPLETED_CMD)
{
Modify_SPI_Reg_bits(LMS7param(MIMO_SISO), 0); //enable B channel after reset
return LIBLMS7_SUCCESS;
}
else
return LIBLMS7_FAILURE;
}
liblms7_status LMS7002M::LoadConfigLegacyFile(const char* filename)
{
ifstream f(filename);
if (f.good() == false) //file not found
{
f.close();
return LIBLMS7_FILE_NOT_FOUND;
}
f.close();
uint16_t addr = 0;
uint16_t value = 0;
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); //remember used channel
liblms7_status status;
typedef INI<string, string, string> ini_t;
ini_t parser(filename, true);
if (parser.select("FILE INFO") == false)
return LIBLMS7_FILE_INVALID_FORMAT;
string type = "";
type = parser.get("type", "undefined");
stringstream ss;
if (type.find("LMS7002 configuration") == string::npos)
{
ss << "File " << filename << " not recognized" << endl;
return LIBLMS7_FILE_INVALID_FORMAT;
}
int fileVersion = 0;
fileVersion = parser.get("version", 0);
vector<uint16_t> addrToWrite;
vector<uint16_t> dataToWrite;
if (fileVersion == 1)
{
if (parser.select("Reference clocks"))
{
mRefClkSXR_MHz = parser.get("SXR reference frequency MHz", 30.72);
mRefClkSXT_MHz = parser.get("SXT reference frequency MHz", 30.72);
}
if (parser.select("LMS7002 registers ch.A") == true)
{
ini_t::sectionsit_t section = parser.sections.find("LMS7002 registers ch.A");
uint16_t x0020_value = 0;
Modify_SPI_Reg_bits(LMS7param(MAC), 1); //select A channel
for (ini_t::keysit_t pairs = section->second->begin(); pairs != section->second->end(); pairs++)
{
sscanf(pairs->first.c_str(), "%hx", &addr);
sscanf(pairs->second.c_str(), "%hx", &value);
if (addr == LMS7param(MAC).address) //skip register containing channel selection
{
x0020_value = value;
continue;
}
addrToWrite.push_back(addr);
dataToWrite.push_back(value);
}
status = SPI_write_batch(&addrToWrite[0], &dataToWrite[0], addrToWrite.size());
if (status != LIBLMS7_SUCCESS && status != LIBLMS7_NOT_CONNECTED)
return status;
//parse FCW or PHO
if (parser.select("NCO Rx ch.A") == true)
{
char varname[64];
int mode = Get_SPI_Reg_bits(LMS7param(MODE_RX));
if (mode == 0) //FCW
{
for (int i = 0; i < 16; ++i)
{
sprintf(varname, "FCW%02i", i);
SetNCOFrequency(LMS7002M::Rx, i, parser.get(varname, 0.0));
}
}
else
{
for (int i = 0; i < 16; ++i)
{
sprintf(varname, "PHO%02i", i);
SetNCOPhaseOffset(LMS7002M::Rx, i, parser.get(varname, 0.0));
}
}
}
if (parser.select("NCO Tx ch.A") == true)
{
char varname[64];
int mode = Get_SPI_Reg_bits(LMS7param(MODE_TX));
if (mode == 0) //FCW
{
for (int i = 0; i < 16; ++i)
{
sprintf(varname, "FCW%02i", i);
SetNCOFrequency(LMS7002M::Tx, i, parser.get(varname, 0.0));
}
}
else
{
for (int i = 0; i < 16; ++i)
{
sprintf(varname, "PHO%02i", i);
SetNCOPhaseOffset(LMS7002M::Tx, i, parser.get(varname, 0.0));
}
}
}
status = SPI_write(0x0020, x0020_value);
if (status != LIBLMS7_SUCCESS && status != LIBLMS7_NOT_CONNECTED)
return status;
}
Modify_SPI_Reg_bits(LMS7param(MAC), 2);
if (parser.select("LMS7002 registers ch.B") == true)
{
addrToWrite.clear();
dataToWrite.clear();
ini_t::sectionsit_t section = parser.sections.find("LMS7002 registers ch.B");
for (ini_t::keysit_t pairs = section->second->begin(); pairs != section->second->end(); pairs++)
{
sscanf(pairs->first.c_str(), "%hx", &addr);
sscanf(pairs->second.c_str(), "%hx", &value);
addrToWrite.push_back(addr);
dataToWrite.push_back(value);
}
Modify_SPI_Reg_bits(LMS7param(MAC), 2); //select B channel
status = SPI_write_batch(&addrToWrite[0], &dataToWrite[0], addrToWrite.size());
if (status != LIBLMS7_SUCCESS && status != LIBLMS7_NOT_CONNECTED)
return status;
//parse FCW or PHO
if (parser.select("NCO Rx ch.B") == true)
{
char varname[64];
int mode = Get_SPI_Reg_bits(LMS7param(MODE_RX));
if (mode == 0) //FCW
{
for (int i = 0; i < 16; ++i)
{
sprintf(varname, "FCW%02i", i);
SetNCOFrequency(LMS7002M::Rx, i, parser.get(varname, 0.0));
}
}
else
{
for (int i = 0; i < 16; ++i)
{
sprintf(varname, "PHO%02i", i);
SetNCOPhaseOffset(LMS7002M::Rx, i, parser.get(varname, 0.0));
}
}
}
if (parser.select("NCO Tx ch.A") == true)
{
char varname[64];
int mode = Get_SPI_Reg_bits(LMS7param(MODE_TX));
if (mode == 0) //FCW
{
for (int i = 0; i < 16; ++i)
{
sprintf(varname, "FCW%02i", i);
SetNCOFrequency(LMS7002M::Tx, i, parser.get(varname, 0.0));
}
}
else
{
for (int i = 0; i < 16; ++i)
{
sprintf(varname, "PHO%02i", i);
SetNCOPhaseOffset(LMS7002M::Tx, i, parser.get(varname, 0.0));
}
}
}
}
Modify_SPI_Reg_bits(LMS7param(MAC), ch);
return LIBLMS7_SUCCESS;
}
else
return LIBLMS7_FILE_INVALID_FORMAT;
return LIBLMS7_FAILURE;
}
/** @brief Reads configuration file and uploads registers to chip
@param filename Configuration source file
@return 0-success, other-failure
*/
liblms7_status LMS7002M::LoadConfig(const char* filename)
{
ifstream f(filename);
if (f.good() == false) //file not found
{
f.close();
return LIBLMS7_FILE_NOT_FOUND;
}
f.close();
uint16_t addr = 0;
uint16_t value = 0;
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); //remember used channel
liblms7_status status;
typedef INI<string, string, string> ini_t;
ini_t parser(filename, true);
if (parser.select("file_info") == false)
{
//try loading as legacy format
status = LoadConfigLegacyFile(filename);
Modify_SPI_Reg_bits(MAC, 1);
return status;
}
string type = "";
type = parser.get("type", "undefined");
stringstream ss;
if (type.find("lms7002m_minimal_config") == string::npos)
{
ss << "File " << filename << " not recognized" << endl;
return LIBLMS7_FILE_INVALID_FORMAT;
}
int fileVersion = 0;
fileVersion = parser.get("version", 0);
vector<uint16_t> addrToWrite;
vector<uint16_t> dataToWrite;
if (fileVersion == 1)
{
if(parser.select("lms7002_registers_a") == true)
{
ini_t::sectionsit_t section = parser.sections.find("lms7002_registers_a");
uint16_t x0020_value = 0;
Modify_SPI_Reg_bits(LMS7param(MAC), 1); //select A channel
for (ini_t::keysit_t pairs = section->second->begin(); pairs != section->second->end(); pairs++)
{
sscanf(pairs->first.c_str(), "%hx", &addr);
sscanf(pairs->second.c_str(), "%hx", &value);
if (addr == LMS7param(MAC).address) //skip register containing channel selection
{
x0020_value = value;
continue;
}
addrToWrite.push_back(addr);
dataToWrite.push_back(value);
}
status = SPI_write_batch(&addrToWrite[0], &dataToWrite[0], addrToWrite.size());
if (status != LIBLMS7_SUCCESS && status != LIBLMS7_NOT_CONNECTED)
return status;
status = SPI_write(0x0020, x0020_value);
if (status != LIBLMS7_SUCCESS && status != LIBLMS7_NOT_CONNECTED)
return status;
Modify_SPI_Reg_bits(LMS7param(MAC), 2);
if (status != LIBLMS7_SUCCESS && status != LIBLMS7_NOT_CONNECTED)
return status;
}
if (parser.select("lms7002_registers_b") == true)
{
addrToWrite.clear();
dataToWrite.clear();
ini_t::sectionsit_t section = parser.sections.find("lms7002_registers_b");
for (ini_t::keysit_t pairs = section->second->begin(); pairs != section->second->end(); pairs++)
{
sscanf(pairs->first.c_str(), "%hx", &addr);
sscanf(pairs->second.c_str(), "%hx", &value);
addrToWrite.push_back(addr);
dataToWrite.push_back(value);
}
Modify_SPI_Reg_bits(LMS7param(MAC), 2); //select B channel
status = SPI_write_batch(&addrToWrite[0], &dataToWrite[0], addrToWrite.size());
if (status != LIBLMS7_SUCCESS && status != LIBLMS7_NOT_CONNECTED)
return status;
}
Modify_SPI_Reg_bits(LMS7param(MAC), ch);
parser.select("reference_clocks");
mRefClkSXR_MHz = parser.get("sxr_ref_clk_mhz", 30.72);
mRefClkSXT_MHz = parser.get("sxt_ref_clk_mhz", 30.72);
}
Modify_SPI_Reg_bits(MAC, 1);
if (controlPort == NULL)
return LIBLMS7_NO_CONNECTION_MANAGER;
if (controlPort->IsOpen() == false)
return LIBLMS7_NOT_CONNECTED;
return LIBLMS7_SUCCESS;
}
/** @brief Reads all registers from chip and saves to file
@param filename destination filename
@return 0-success, other failure
*/
liblms7_status LMS7002M::SaveConfig(const char* filename)
{
liblms7_status status;
typedef INI<> ini_t;
ini_t parser(filename, true);
parser.create("file_info");
parser.set("type", "lms7002m_minimal_config");
parser.set("version", 1);
char addr[80];
char value[80];
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC));
vector<uint16_t> addrToRead;
for (uint8_t i = 0; i < MEMORY_SECTIONS_COUNT; ++i)
for (uint16_t addr = MemorySectionAddresses[i][0]; addr <= MemorySectionAddresses[i][1]; ++addr)
addrToRead.push_back(addr);
vector<uint16_t> dataReceived;
dataReceived.resize(addrToRead.size(), 0);
parser.create("lms7002_registers_a");
Modify_SPI_Reg_bits(LMS7param(MAC), 1);
for (uint16_t i = 0; i < addrToRead.size(); ++i)
{
dataReceived[i] = Get_SPI_Reg_bits(addrToRead[i], 15, 0, false);
sprintf(addr, "0x%04X", addrToRead[i]);
sprintf(value, "0x%04X", dataReceived[i]);
parser.set(addr, value);
}
parser.create("lms7002_registers_b");
addrToRead.clear(); //add only B channel addresses
for (uint8_t i = 0; i < MEMORY_SECTIONS_COUNT; ++i)
for (uint16_t addr = MemorySectionAddresses[i][0]; addr <= MemorySectionAddresses[i][1]; ++addr)
if (addr >= 0x0100)
addrToRead.push_back(addr);
Modify_SPI_Reg_bits(LMS7param(MAC), 2);
for (uint16_t i = 0; i < addrToRead.size(); ++i)
{
dataReceived[i] = Get_SPI_Reg_bits(addrToRead[i], 15, 0, false);
sprintf(addr, "0x%04X", addrToRead[i]);
sprintf(value, "0x%04X", dataReceived[i]);
parser.set(addr, value);
}
Modify_SPI_Reg_bits(LMS7param(MAC), ch); //retore previously used channel
parser.create("reference_clocks");
parser.set("sxt_ref_clk_mhz", mRefClkSXT_MHz);
parser.set("sxr_ref_clk_mhz", mRefClkSXR_MHz);
parser.save(filename);
return LIBLMS7_SUCCESS;
}
/** @brief Returns reference clock in MHz used for SXT or SXR
@param Tx transmitter or receiver selection
*/
float_type LMS7002M::GetReferenceClk_SX(bool tx)
{
return tx ? mRefClkSXT_MHz : mRefClkSXR_MHz;
}
/** @return Current CLKGEN frequency in MHz
Returned frequency depends on reference clock used for Receiver
*/
float_type LMS7002M::GetFrequencyCGEN_MHz()
{
float_type dMul = (mRefClkSXR_MHz/2.0)/(Get_SPI_Reg_bits(LMS7param(DIV_OUTCH_CGEN))+1); //DIV_OUTCH_CGEN
uint16_t gINT = Get_SPI_Reg_bits(0x0088, 13, 0); //read whole register to reduce SPI transfers
uint32_t gFRAC = ((gINT & 0xF) * 65536) | Get_SPI_Reg_bits(0x0087, 15, 0);
return dMul * (((gINT>>4) + 1 + gFRAC/1048576.0));
}
/** @brief Returns TSP reference frequency
@param tx TxTSP or RxTSP selection
@return TSP reference frequency in MHz
*/
float_type LMS7002M::GetReferenceClk_TSP_MHz(bool tx)
{
float_type cgenFreq = GetFrequencyCGEN_MHz();
float_type clklfreq = cgenFreq/pow(2.0, Get_SPI_Reg_bits(LMS7param(CLKH_OV_CLKL_CGEN)));
if(Get_SPI_Reg_bits(LMS7param(EN_ADCCLKH_CLKGN)) == 0)
return tx ? clklfreq : cgenFreq/4.0;
else
return tx ? cgenFreq : clklfreq/4.0;
}
/** @brief Sets CLKGEN frequency, calculations use receiver'r reference clock
@param freq_MHz desired frequency in MHz
@return 0-succes, other-cannot deliver desired frequency
*/
liblms7_status LMS7002M::SetFrequencyCGEN(const float_type freq_MHz)
{
float_type dFvco;
float_type dFrac;
int16_t iHdiv;
//VCO frequency selection according to F_CLKH
iHdiv = (int16_t)((gCGEN_VCO_frequencies[1]/ 2) / freq_MHz) - 1;
dFvco = 2*(iHdiv+1) * freq_MHz;
//Integer division
uint16_t gINT = (uint16_t)(dFvco/mRefClkSXR_MHz - 1);
//Fractional division
dFrac = dFvco/mRefClkSXR_MHz - (uint32_t)(dFvco/mRefClkSXR_MHz);
uint32_t gFRAC = (uint32_t)(dFrac * 1048576);
Modify_SPI_Reg_bits(LMS7param(INT_SDM_CGEN), gINT); //INT_SDM_CGEN
Modify_SPI_Reg_bits(0x0087, 15, 0, gFRAC&0xFFFF); //INT_SDM_CGEN[15:0]
Modify_SPI_Reg_bits(0x0088, 3, 0, gFRAC>>16); //INT_SDM_CGEN[19:16]
Modify_SPI_Reg_bits(LMS7param(DIV_OUTCH_CGEN), iHdiv); //DIV_OUTCH_CGEN
return TuneVCO(VCO_CGEN);
}
/** @brief Performs VCO tuning operations for CLKGEN, SXR, SXT modules
@param module module selection for tuning 0-cgen, 1-SXR, 2-SXT
@return 0-success, other-failure
*/
liblms7_status LMS7002M::TuneVCO(VCO_Module module) // 0-cgen, 1-SXR, 2-SXT
{
if (controlPort == NULL)
return LIBLMS7_NO_CONNECTION_MANAGER;
if (controlPort->IsOpen() == false)
return LIBLMS7_NOT_CONNECTED;
int8_t i;
uint8_t cmphl; //comparators
int16_t csw_lowest = -1;
uint16_t addrVCOpd; // VCO power down address
uint16_t addrCSW_VCO;
uint16_t addrCMP; //comparator address
uint8_t lsb; //SWC lsb index
uint8_t msb; //SWC msb index
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); //remember used channel
if(module != VCO_CGEN) //set addresses to SX module
{
Modify_SPI_Reg_bits(LMS7param(MAC), module);
addrVCOpd = LMS7param(PD_VCO).address;
addrCSW_VCO = LMS7param(CSW_VCO).address;
lsb = LMS7param(CSW_VCO).lsb;
msb = LMS7param(CSW_VCO).msb;
addrCMP = LMS7param(VCO_CMPHO).address;
}
else //set addresses to CGEN module
{
addrVCOpd = LMS7param(PD_VCO_CGEN).address;
addrCSW_VCO = LMS7param(CSW_VCO_CGEN).address;
lsb = LMS7param(CSW_VCO_CGEN).lsb;
msb = LMS7param(CSW_VCO_CGEN).msb;
addrCMP = LMS7param(VCO_CMPHO_CGEN).address;
}
// Initialization
Modify_SPI_Reg_bits (addrVCOpd, 2, 1, 0); //activate VCO and comparator
if (Get_SPI_Reg_bits(addrVCOpd, 2, 1) != 0)
return LIBLMS7_VCO_IS_POWERED_DOWN;
if(module == VCO_CGEN)
Modify_SPI_Reg_bits(LMS7param(SPDUP_VCO_CGEN), 1); //SHORT_NOISEFIL=1 SPDUP_VCO_ Short the noise filter resistor to speed up the settling time
else
Modify_SPI_Reg_bits(LMS7param(SPDUP_VCO), 1); //SHORT_NOISEFIL=1 SPDUP_VCO_ Short the noise filter resistor to speed up the settling time
Modify_SPI_Reg_bits (addrCSW_VCO , msb, lsb , 0); //Set SWC_VCO<7:0>=<00000000>
i=7;
while(i>=0)
{
Modify_SPI_Reg_bits (addrCSW_VCO, lsb + i, lsb + i, 1); // CSW_VCO<i>=1
std::this_thread::sleep_for(std::chrono::milliseconds(5));
cmphl = (uint8_t)Get_SPI_Reg_bits(addrCMP, 13, 12);
if ( (cmphl&0x01) == 1) // reduce CSW
Modify_SPI_Reg_bits (addrCSW_VCO, lsb + i, lsb + i, 0); // CSW_VCO<i>=0
if( cmphl == 2 && csw_lowest < 0)
csw_lowest = Get_SPI_Reg_bits(addrCSW_VCO, msb, lsb);
--i;
}
if(csw_lowest >= 0)
{
uint16_t csw_highest = Get_SPI_Reg_bits(addrCSW_VCO, msb, lsb);
if(csw_lowest == csw_highest)
{
while(csw_lowest>=0)
{
Modify_SPI_Reg_bits(addrCSW_VCO, msb, lsb, csw_lowest);
std::this_thread::sleep_for(std::chrono::milliseconds(5));
if(Get_SPI_Reg_bits(addrCMP, 13, 12) == 0)
{
++csw_lowest;
break;
}
else
--csw_lowest;
}
}
Modify_SPI_Reg_bits(addrCSW_VCO, msb, lsb, csw_lowest+(csw_highest-csw_lowest)/2);
}
if (module == VCO_CGEN)
Modify_SPI_Reg_bits(LMS7param(SPDUP_VCO_CGEN), 0); //SHORT_NOISEFIL=1 SPDUP_VCO_ Short the noise filter resistor to speed up the settling time
else
Modify_SPI_Reg_bits(LMS7param(SPDUP_VCO), 0); //SHORT_NOISEFIL=1 SPDUP_VCO_ Short the noise filter resistor to speed up the settling time
cmphl = (uint8_t)Get_SPI_Reg_bits(addrCMP, 13, 12);
Modify_SPI_Reg_bits(LMS7param(MAC), ch); //restore previously used channel
if(cmphl == 2)
return LIBLMS7_SUCCESS;
else
return LIBLMS7_FAILURE;
}
/** @brief Returns given parameter value from chip register
@param param LMS7002M control parameter
@param fromChip read directly from chip
@return parameter value
*/
uint16_t LMS7002M::Get_SPI_Reg_bits(const LMS7Parameter &param, bool fromChip)
{
return Get_SPI_Reg_bits(param.address, param.msb, param.lsb, fromChip);
}
/** @brief Returns given parameter value from chip register
@param address register address
@param msb most significant bit index
@param lsb least significant bit index
@param fromChip read directly from chip
@return register bits from selected interval, shifted to right by lsb bits
*/
uint16_t LMS7002M::Get_SPI_Reg_bits(uint16_t address, uint8_t msb, uint8_t lsb, bool fromChip)
{
return (SPI_read(address, fromChip) & (~(~0<<(msb+1)))) >> lsb; //shift bits to LSB
}
/** @brief Change given parameter value
@param param LMS7002M control parameter
@param fromChip read initial value directly from chip
@param value new parameter value
*/
liblms7_status LMS7002M::Modify_SPI_Reg_bits(const LMS7Parameter &param, const uint16_t value, bool fromChip)
{
return Modify_SPI_Reg_bits(param.address, param.msb, param.lsb, value, fromChip);
}
/** @brief Change given parameter value
@param address register address
@param value new bits value, the value is shifted left by lsb bits
@param fromChip read initial value directly from chip
*/
liblms7_status LMS7002M::Modify_SPI_Reg_bits(const uint16_t address, const uint8_t msb, const uint8_t lsb, const uint16_t value, bool fromChip)
{
uint16_t spiDataReg = SPI_read(address, fromChip); //read current SPI reg data
uint16_t spiMask = (~(~0 << (msb - lsb + 1))) << (lsb); // creates bit mask
spiDataReg = (spiDataReg & (~spiMask)) | ((value << lsb) & spiMask);//clear bits
return SPI_write(address, spiDataReg); //write modified data back to SPI reg
}
/** @brief Modifies given registers with values applied using masks
@param addr array of register addresses
@param masks array of applied masks
@param values array of values to be written
@param start starting index of given arrays
@param stop end index of given arrays
*/
liblms7_status LMS7002M::Modify_SPI_Reg_mask(const uint16_t *addr, const uint16_t *masks, const uint16_t *values, uint8_t start, uint8_t stop)
{
liblms7_status status;
uint16_t reg_data;
vector<uint16_t> addresses;
vector<uint16_t> data;
while (start <= stop)
{
reg_data = SPI_read(addr[start], true, &status); //read current SPI reg data
reg_data &= ~masks[start];//clear bits
reg_data |= (values[start] & masks[start]);
addresses.push_back(addr[start]);
data.push_back(reg_data);
++start;
}
if (status != LIBLMS7_SUCCESS)
return status;
SPI_write_batch(&addresses[0], &data[0], addresses.size());
return status;
}
/** @brief Sets SX frequency
@param Tx Rx/Tx module selection
@param freq_MHz desired frequency in MHz
@param refClk_MHz reference clock in MHz
@return 0-success, other-cannot deliver requested frequency
*/
liblms7_status LMS7002M::SetFrequencySX(bool tx, float_type freq_MHz, float_type refClk_MHz)
{
if (controlPort == NULL)
return LIBLMS7_NO_CONNECTION_MANAGER;
if (controlPort->IsOpen() == false)
return LIBLMS7_NOT_CONNECTED;
const uint8_t sxVCO_N = 2; //number of entries in VCO frequencies
const float_type m_dThrF = 5500; //threshold to enable additional divider
uint8_t ch; //remember used channel
float_type VCOfreq;
int8_t div_loch;
int8_t sel_vco;
bool canDeliverFrequency = false;
uint16_t integerPart;
uint32_t fractionalPart;
int8_t i;
//find required VCO frequency
for (div_loch = 6; div_loch >= 0; --div_loch)
{
VCOfreq = (1 << (div_loch + 1)) * freq_MHz;
if ((VCOfreq >= gVCO_frequency_table[0][0]) && (VCOfreq <= gVCO_frequency_table[2][sxVCO_N - 1]))
{
canDeliverFrequency = true;
break;
}
}
if (canDeliverFrequency == false)
return LIBLMS7_CANNOT_DELIVER_FREQUENCY;
integerPart = (uint16_t)(VCOfreq / (refClk_MHz * (1 + (VCOfreq > m_dThrF))) - 4);
fractionalPart = (uint32_t)((VCOfreq / (refClk_MHz * (1 + (VCOfreq > m_dThrF))) - (uint32_t)(VCOfreq / (refClk_MHz * (1 + (VCOfreq > m_dThrF))))) * 1048576);
ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC));
Modify_SPI_Reg_bits(LMS7param(MAC), tx + 1);
Modify_SPI_Reg_bits(LMS7param(INT_SDM), integerPart); //INT_SDM
Modify_SPI_Reg_bits(0x011D, 15, 0, fractionalPart & 0xFFFF); //FRAC_SDM[15:0]
Modify_SPI_Reg_bits(0x011E, 3, 0, (fractionalPart >> 16)); //FRAC_SDM[19:16]
Modify_SPI_Reg_bits(LMS7param(DIV_LOCH), div_loch); //DIV_LOCH
Modify_SPI_Reg_bits(LMS7param(EN_DIV2_DIVPROG), (VCOfreq > m_dThrF)); //EN_DIV2_DIVPROG
//find which VCO supports required frequency
Modify_SPI_Reg_bits(LMS7param(PD_VCO), 0); //
Modify_SPI_Reg_bits(LMS7param(PD_VCO_COMP), 0); //
int cswBackup = Get_SPI_Reg_bits(LMS7param(CSW_VCO)); //remember to restore previous tune value
canDeliverFrequency = false;
int tuneScore[] = { -128, -128, -128 }; //best is closest to 0
for (sel_vco = 0; sel_vco < 3; ++sel_vco)
{
Modify_SPI_Reg_bits(LMS7param(SEL_VCO), sel_vco);
liblms7_status status = TuneVCO(tx ? VCO_SXT : VCO_SXR);
int csw = Get_SPI_Reg_bits(LMS7param(CSW_VCO), true);
tuneScore[sel_vco] = -128 + csw;
if (status == LIBLMS7_SUCCESS)
canDeliverFrequency = true;
}
if (abs(tuneScore[0]) < abs(tuneScore[1]))
{
if (abs(tuneScore[0]) < abs(tuneScore[2]))
sel_vco = 0;
else
sel_vco = 2;
}
else
{
if (abs(tuneScore[1]) < abs(tuneScore[2]))
sel_vco = 1;
else
sel_vco = 2;
}
Modify_SPI_Reg_bits(LMS7param(SEL_VCO), sel_vco);
Modify_SPI_Reg_bits(LMS7param(CSW_VCO), cswBackup);
Modify_SPI_Reg_bits(LMS7param(MAC), ch); //restore used channel
if (tx)
mRefClkSXT_MHz = refClk_MHz;
else
mRefClkSXR_MHz = refClk_MHz;
if (canDeliverFrequency == false)
return LIBLMS7_CANNOT_DELIVER_FREQUENCY;
return TuneVCO( tx ? VCO_SXT : VCO_SXR); //Rx-1, Tx-2
}
/** @brief Returns currently set SXR/SXT frequency
@return SX frequency MHz
*/
float_type LMS7002M::GetFrequencySX_MHz(bool Tx, float_type refClk_MHz)
{
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); //remember previously used channel
float_type dMul;
if(Tx)
Modify_SPI_Reg_bits(LMS7param(MAC), 2); // Rx mac = 1, Tx max = 2
else
Modify_SPI_Reg_bits(LMS7param(MAC), 1); // Rx mac = 1, Tx max = 2
uint16_t gINT = Get_SPI_Reg_bits(0x011E, 13, 0); // read whole register to reduce SPI transfers
uint32_t gFRAC = ((gINT&0xF) * 65536) | Get_SPI_Reg_bits(0x011D, 15, 0);
dMul = (float_type)refClk_MHz / (1 << (Get_SPI_Reg_bits(LMS7param(DIV_LOCH)) + 1));
//Calculate real frequency according to the calculated parameters
dMul = dMul * ((gINT >> 4) + 4 + (float_type)gFRAC / 1048576.0) * (Get_SPI_Reg_bits(LMS7param(EN_DIV2_DIVPROG)) + 1);
Modify_SPI_Reg_bits(LMS7param(MAC), ch); //restore used channel
return dMul;
}
/** @brief Loads given DC_REG values into registers
@param tx TxTSP or RxTSP selection
@param I DC_REG I value
@param Q DC_REG Q value
*/
liblms7_status LMS7002M::LoadDC_REG_IQ(bool tx, int16_t I, int16_t Q)
{
if(tx)
{
Modify_SPI_Reg_bits(LMS7param(DC_REG_TXTSP), I);
Modify_SPI_Reg_bits(LMS7param(TSGDCLDI_TXTSP), 0);
Modify_SPI_Reg_bits(LMS7param(TSGDCLDI_TXTSP), 1);
Modify_SPI_Reg_bits(LMS7param(TSGDCLDI_TXTSP), 0);
Modify_SPI_Reg_bits(LMS7param(DC_REG_TXTSP), Q);
Modify_SPI_Reg_bits(LMS7param(TSGDCLDQ_TXTSP), 0);
Modify_SPI_Reg_bits(LMS7param(TSGDCLDQ_TXTSP), 1);
Modify_SPI_Reg_bits(LMS7param(TSGDCLDQ_TXTSP), 0);
Modify_SPI_Reg_bits(LMS7param(DC_BYP_TXTSP), 0); //DC_BYP
}
else
{
Modify_SPI_Reg_bits(LMS7param(DC_REG_RXTSP), I);
Modify_SPI_Reg_bits(LMS7param(TSGDCLDI_RXTSP), 0);
Modify_SPI_Reg_bits(LMS7param(TSGDCLDI_RXTSP), 1);
Modify_SPI_Reg_bits(LMS7param(TSGDCLDI_RXTSP), 0);
Modify_SPI_Reg_bits(LMS7param(DC_REG_TXTSP), Q);
Modify_SPI_Reg_bits(LMS7param(TSGDCLDQ_RXTSP), 0);
Modify_SPI_Reg_bits(LMS7param(TSGDCLDQ_RXTSP), 1);
Modify_SPI_Reg_bits(LMS7param(TSGDCLDQ_RXTSP), 0);
Modify_SPI_Reg_bits(LMS7param(DC_BYP_RXTSP), 0); //DC_BYP
}
return LIBLMS7_SUCCESS;
}
/** @brief Sets chosen NCO's frequency
@param tx transmitter or receiver selection
@param index NCO index from 0 to 15
@param freq_MHz desired NCO frequency
@return 0-success, other-failure
*/
liblms7_status LMS7002M::SetNCOFrequency(bool tx, uint8_t index, float_type freq_MHz)
{
if(index > 15)
return LIBLMS7_INDEX_OUT_OF_RANGE;
float_type refClk_MHz = GetReferenceClk_TSP_MHz(tx);
uint16_t addr = tx ? 0x0240 : 0x0440;
uint32_t fcw = (uint32_t)((freq_MHz/refClk_MHz)*4294967296);
SPI_write(addr+2+index*2, (fcw >> 16)); //NCO frequency control word register MSB part.
SPI_write(addr+3+index*2, fcw); //NCO frequency control word register LSB part.
return LIBLMS7_SUCCESS;
}
/** @brief Returns chosen NCO's frequency in MHz
@param tx transmitter or receiver selection
@param index NCO index from 0 to 15
@param fromChip read frequency directly from chip or local registers
@return NCO frequency in MHz
*/
float_type LMS7002M::GetNCOFrequency_MHz(bool tx, uint8_t index, const float_type refClk_MHz, bool fromChip)
{
if(index > 15)
return LIBLMS7_INDEX_OUT_OF_RANGE;
uint16_t addr = tx ? 0x0240 : 0x0440;
uint32_t fcw = 0;
fcw |= SPI_read(addr + 2 + index * 2, fromChip) << 16; //NCO frequency control word register MSB part.
fcw |= SPI_read(addr + 3 + index * 2, fromChip); //NCO frequency control word register LSB part.
return refClk_MHz*(fcw/4294967296.0);
}
/** @brief Sets chosen NCO phase offset angle when memory table MODE is 0
@param tx transmitter or receiver selection
@param angle_deg phase offset angle in degrees
@return 0-success, other-failure
*/
liblms7_status LMS7002M::SetNCOPhaseOffsetForMode0(bool tx, float_type angle_deg)
{
uint16_t addr = tx ? 0x0241 : 0x0441;
uint16_t pho = (uint16_t)(65536 * (angle_deg / 360 ));
SPI_write(addr, pho);
return LIBLMS7_SUCCESS;
}
/** @brief Sets chosen NCO's phase offset angle
@param tx transmitter or receiver selection
@param index PHO index from 0 to 15
@param angle_deg phase offset angle in degrees
@return 0-success, other-failure
*/
liblms7_status LMS7002M::SetNCOPhaseOffset(bool tx, uint8_t index, float_type angle_deg)
{
if(index > 15)
return LIBLMS7_INDEX_OUT_OF_RANGE;
uint16_t addr = tx ? 0x0244 : 0x0444;
uint16_t pho = (uint16_t)(65536*(angle_deg / 360));
SPI_write(addr+index, pho);
return LIBLMS7_SUCCESS;
}
/** @brief Returns chosen NCO's phase offset angle in radians
@param tx transmitter or receiver selection
@param index PHO index from 0 to 15
@return phase offset angle in degrees
*/
float_type LMS7002M::GetNCOPhaseOffset_Deg(bool tx, uint8_t index)
{
uint16_t addr = tx ? 0x0244 : 0x0444;
uint16_t pho = SPI_read(addr+index);
float_type angle = 360*pho/65536.0;
return angle;
}
/** @brief Uploads given FIR coefficients to chip
@param tx Transmitter or receiver selection
@param GFIR_index GIR index from 0 to 2
@param coef array of coefficients
@param coefCount number of coefficients
@return 0-success, other-failure
This function does not change GFIR*_L or GFIR*_N parameters, they have to be set manually
*/
liblms7_status LMS7002M::SetGFIRCoefficients(bool tx, uint8_t GFIR_index, const int16_t *coef, uint8_t coefCount)
{
uint8_t index;
uint8_t coefLimit;
uint16_t startAddr;
if (GFIR_index == 0)
startAddr = 0x0280;
else if (GFIR_index == 1)
startAddr = 0x02C0;
else
startAddr = 0x0300;
if (tx == false)
startAddr += 0x0200;
if (GFIR_index < 2)
coefLimit = 40;
else
coefLimit = 120;
if (coefCount > coefLimit)
return LIBLMS7_TOO_MANY_VALUES;
vector<uint16_t> addresses;
for (index = 0; index < coefCount; ++index)
addresses.push_back(startAddr + index + 24 * (index / 40));
SPI_write_batch(&addresses[0], (uint16_t*)coef, coefCount);
return LIBLMS7_SUCCESS;
}
/** @brief Returns currently loaded FIR coefficients
@param tx Transmitter or receiver selection
@param GFIR_index GIR index from 0 to 2
@param coef array of returned coefficients
@param coefCount number of coefficients to read
@return 0-success, other-failure
*/
liblms7_status LMS7002M::GetGFIRCoefficients(bool tx, uint8_t GFIR_index, int16_t *coef, uint8_t coefCount)
{
liblms7_status status = LIBLMS7_FAILURE;
uint8_t index;
uint8_t coefLimit;
uint16_t startAddr;
if(GFIR_index == 0)
startAddr = 0x0280;
else if (GFIR_index == 1)
startAddr = 0x02C0;
else
startAddr = 0x0300;
if (tx == false)
startAddr += 0x0200;
if (GFIR_index < 2)
coefLimit = 40;
else
coefLimit = 120;
if (coefCount > coefLimit)
return LIBLMS7_TOO_MANY_VALUES;
std::vector<uint16_t> addresses;
for (index = 0; index < coefCount; ++index)
addresses.push_back(startAddr + index + 24 * (index / 40));
uint16_t spiData[120];
memset(spiData, 0, 120 * sizeof(uint16_t));
if (controlPort->IsOpen())
{
status = SPI_read_batch(&addresses[0], spiData, coefCount);
for (index = 0; index < coefCount; ++index)
coef[index] = spiData[index];
}
else
{
const int channel = Get_SPI_Reg_bits(LMS7param(MAC), false) > 1 ? 1 : 0;
for (index = 0; index < coefCount; ++index)
coef[index] = mRegistersMap->GetValue(channel, addresses[index]);
status = LIBLMS7_SUCCESS;
}
return status;
}
/** @brief Write given data value to whole register
@param address SPI address
@param data new register value
@return 0-succes, other-failure
*/
liblms7_status LMS7002M::SPI_write(uint16_t address, uint16_t data)
{
if (controlPort == NULL)
return LIBLMS7_NO_CONNECTION_MANAGER;
if ((mRegistersMap->GetValue(0, LMS7param(MAC).address) & 0x0003) > 1 && address >= 0x0100)
mRegistersMap->SetValue(1, address, data);
else
mRegistersMap->SetValue(0, address, data);
if (controlPort->IsOpen() == false)
return LIBLMS7_NOT_CONNECTED;
LMScomms::GenericPacket pkt;
pkt.cmd = CMD_LMS7002_WR;
pkt.outBuffer.push_back(address >> 8);
pkt.outBuffer.push_back(address & 0xFF);
pkt.outBuffer.push_back(data >> 8);
pkt.outBuffer.push_back(data & 0xFF);
controlPort->TransferPacket(pkt);
if (pkt.status == STATUS_COMPLETED_CMD)
return LIBLMS7_SUCCESS;
else
return LIBLMS7_FAILURE;
}
/** @brief Reads whole register value from given address
@param address SPI address
@param status operation status(optional)
@param fromChip read value directly from chip
@return register value
*/
uint16_t LMS7002M::SPI_read(uint16_t address, bool fromChip, liblms7_status *status)
{
if (controlPort == NULL)
{
if (status)
*status = LIBLMS7_NO_CONNECTION_MANAGER;
}
if (controlPort->IsOpen() == false || fromChip == false)
{
if ((mRegistersMap->GetValue(0, LMS7param(MAC).address) & 0x0003) > 1 && address >= 0x0100)
return mRegistersMap->GetValue(1, address);
else
return mRegistersMap->GetValue(0, address);
}
LMScomms::GenericPacket pkt;
pkt.cmd = CMD_LMS7002_RD;
pkt.outBuffer.push_back(address >> 8);
pkt.outBuffer.push_back(address & 0xFF);
if (controlPort->TransferPacket(pkt) == LMScomms::TRANSFER_SUCCESS)
{
if (status)
*status = (pkt.status == STATUS_COMPLETED_CMD ? LIBLMS7_SUCCESS : LIBLMS7_FAILURE);
return (pkt.inBuffer[2] << 8) | pkt.inBuffer[3];
}
else
return 0;
}
/** @brief Batches multiple register writes into least ammount of transactions
@param spiAddr spi register addresses to be written
@param spiData registers data to be written
@param cnt number of registers to write
@return 0-success, other-failure
*/
liblms7_status LMS7002M::SPI_write_batch(const uint16_t* spiAddr, const uint16_t* spiData, uint16_t cnt)
{
LMScomms::GenericPacket pkt;
pkt.cmd = CMD_LMS7002_WR;
uint32_t index = 0;
for (uint32_t i = 0; i < cnt; ++i)
{
pkt.outBuffer.push_back(spiAddr[i] >> 8);
pkt.outBuffer.push_back(spiAddr[i] & 0xFF);
pkt.outBuffer.push_back(spiData[i] >> 8);
pkt.outBuffer.push_back(spiData[i] & 0xFF);
if ((mRegistersMap->GetValue(0, LMS7param(MAC).address) & 0x0003) > 1)
mRegistersMap->SetValue(1, spiAddr[i], spiData[i]);
else
mRegistersMap->SetValue(0, spiAddr[i], spiData[i]);
}
if (controlPort == NULL)
return LIBLMS7_NO_CONNECTION_MANAGER;
if (controlPort->IsOpen() == false)
return LIBLMS7_NOT_CONNECTED;
controlPort->TransferPacket(pkt);
if (pkt.status == STATUS_COMPLETED_CMD)
return LIBLMS7_SUCCESS;
else
return LIBLMS7_FAILURE;
}
/** @brief Batches multiple register reads into least amount of transactions
@param spiAddr SPI addresses to read
@param spiData array for read data
@param cnt number of registers to read
@return 0-success, other-failure
*/
liblms7_status LMS7002M::SPI_read_batch(const uint16_t* spiAddr, uint16_t* spiData, uint16_t cnt)
{
LMScomms::GenericPacket pkt;
pkt.cmd = CMD_LMS7002_RD;
uint32_t index = 0;
for (uint32_t i = 0; i < cnt; ++i)
{
pkt.outBuffer.push_back(spiAddr[i] >> 8);
pkt.outBuffer.push_back(spiAddr[i] & 0xFF);
}
if (controlPort == NULL)
return LIBLMS7_NO_CONNECTION_MANAGER;
if (controlPort->IsOpen() == false)
return LIBLMS7_NOT_CONNECTED;
LMScomms::TransferStatus status = controlPort->TransferPacket(pkt);
if (status != LMScomms::TRANSFER_SUCCESS)
return LIBLMS7_FAILURE;
for (uint32_t i = 0; i < cnt; ++i)
{
spiData[i] = (pkt.inBuffer[2*sizeof(uint16_t)*i + 2] << 8) | pkt.inBuffer[2*sizeof(uint16_t)*i + 3];
if ((mRegistersMap->GetValue(0, LMS7param(MAC).address) & 0x0003) > 1)
mRegistersMap->SetValue(1, spiAddr[i], spiData[i]);
else
mRegistersMap->SetValue(0, spiAddr[i], spiData[i]);
}
return pkt.status == STATUS_COMPLETED_CMD ? LIBLMS7_SUCCESS : LIBLMS7_FAILURE;
/*
for(int i=0; i<cnt; ++i)
{
spiData[i] = Get_SPI_Reg_bits(spiAddr[i], 15, 0);
if ((mRegistersMap->GetValue(0, LMS7param(MAC).address) & 0x0003) > 1)
mRegistersMap->SetValue(1, spiAddr[i], spiData[i]);
else
mRegistersMap->SetValue(0, spiAddr[i], spiData[i]);
}
return LIBLMS7_SUCCESS;*/
}
/** @brief Performs registers test by writing known data and confirming readback data
@return 0-registers test passed, other-failure
*/
liblms7_status LMS7002M::RegistersTest()
{
char chex[16];
if (controlPort == NULL)
return LIBLMS7_NO_CONNECTION_MANAGER;
if (controlPort->IsOpen() == false)
return LIBLMS7_NOT_CONNECTED;
liblms7_status status;
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC));
//backup both channel data for restoration after test
vector<uint16_t> ch1Addresses;
for (uint8_t i = 0; i < MEMORY_SECTIONS_COUNT; ++i)
for (uint16_t addr = MemorySectionAddresses[i][0]; addr <= MemorySectionAddresses[i][1]; ++addr)
ch1Addresses.push_back(addr);
vector<uint16_t> ch1Data;
ch1Data.resize(ch1Addresses.size(), 0);
//backup A channel
Modify_SPI_Reg_bits(LMS7param(MAC), 1);
status = SPI_read_batch(&ch1Addresses[0], &ch1Data[0], ch1Addresses.size());
if (status != LIBLMS7_SUCCESS)
return status;
vector<uint16_t> ch2Addresses;
for (uint8_t i = 0; i < MEMORY_SECTIONS_COUNT; ++i)
for (uint16_t addr = MemorySectionAddresses[i][0]; addr <= MemorySectionAddresses[i][1]; ++addr)
if (addr >= 0x0100)
ch2Addresses.push_back(addr);
vector<uint16_t> ch2Data;
ch2Data.resize(ch2Addresses.size(), 0);
Modify_SPI_Reg_bits(LMS7param(MAC), 2);
status = SPI_read_batch(&ch2Addresses[0], &ch2Data[0], ch2Addresses.size());
if (status != LIBLMS7_SUCCESS)
return status;
//test registers
ResetChip();
Modify_SPI_Reg_bits(LMS7param(MIMO_SISO), 0);
Modify_SPI_Reg_bits(LMS7param(PD_RX_AFE2), 0);
Modify_SPI_Reg_bits(LMS7param(PD_TX_AFE2), 0);
Modify_SPI_Reg_bits(LMS7param(MAC), 1);
stringstream ss;
//check single channel memory sections
vector<MemorySection> modulesToCheck = { AFE, BIAS, XBUF, CGEN, LDO, BIST, CDS, TRF, TBB, RFE, RBB, SX,
TxTSP, TxNCO, TxGFIR1, TxGFIR2, TxGFIR3a, TxGFIR3b, TxGFIR3c,
RxTSP, RxNCO, RxGFIR1, RxGFIR2, RxGFIR3a, RxGFIR3b, RxGFIR3c, LimeLight };
const char* moduleNames[] = { "AFE", "BIAS", "XBUF", "CGEN", "LDO", "BIST", "CDS", "TRF", "TBB", "RFE", "RBB", "SX",
"TxTSP", "TxNCO", "TxGFIR1", "TxGFIR2", "TxGFIR3a", "TxGFIR3b", "TxGFIR3c",
"RxTSP", "RxNCO", "RxGFIR1", "RxGFIR2", "RxGFIR3a", "RxGFIR3b", "RxGFIR3c", "LimeLight" };
const uint16_t patterns[] = { 0xAAAA, 0x5555 };
const uint8_t patternsCount = 2;
bool allTestSuccess = true;
for (unsigned i = 0; i < modulesToCheck.size(); ++i)
{
bool moduleTestsSuccess = true;
uint16_t startAddr = MemorySectionAddresses[modulesToCheck[i]][0];
uint16_t endAddr = MemorySectionAddresses[modulesToCheck[i]][1];
uint8_t channelCount = startAddr >= 0x0100 ? 2 : 1;
for (int cc = 1; cc <= channelCount; ++cc)
{
Modify_SPI_Reg_bits(LMS7param(MAC), cc);
sprintf(chex, "0x%04X", startAddr);
ss << moduleNames[i] << " [" << chex << ":";
sprintf(chex, "0x%04X", endAddr);
ss << chex << "]";
if (startAddr >= 0x0100)
ss << " Ch." << (cc == 1 ? "A" : "B");
ss << endl;
for (uint8_t p = 0; p < patternsCount; ++p)
moduleTestsSuccess &= RegistersTestInterval(startAddr, endAddr, patterns[p], ss) == LIBLMS7_SUCCESS;
}
allTestSuccess &= moduleTestsSuccess;
}
//restore register values
Modify_SPI_Reg_bits(LMS7param(MAC), 1);
SPI_write_batch(&ch1Addresses[0], &ch1Data[0], ch1Addresses.size());
Modify_SPI_Reg_bits(LMS7param(MAC), 2);
SPI_write_batch(&ch2Addresses[0], &ch2Data[0], ch2Addresses.size());
Modify_SPI_Reg_bits(LMS7param(MAC), ch);
fstream fout;
fout.open("registersTest.txt", ios::out);
fout << ss.str() << endl;
fout.close();
return allTestSuccess ? LIBLMS7_SUCCESS : LIBLMS7_FAILURE;
}
/** @brief Performs registers test for given address interval by writing given pattern data
@param startAddr first register address
@param endAddr last reigster address
@param pattern data to be written into registers
@return 0-register test passed, other-failure
*/
liblms7_status LMS7002M::RegistersTestInterval(uint16_t startAddr, uint16_t endAddr, uint16_t pattern, stringstream &ss)
{
vector<uint16_t> addrToWrite;
vector<uint16_t> dataToWrite;
vector<uint16_t> dataReceived;
vector<uint16_t> dataMasks;
for (uint16_t addr = startAddr; addr <= endAddr; ++addr)
{
addrToWrite.push_back(addr);
}
dataMasks.resize(addrToWrite.size(), 0xFFFF);
for (uint16_t j = 0; j < sizeof(readOnlyRegisters)/sizeof(uint16_t); ++j)
for (uint16_t k = 0; k < addrToWrite.size(); ++k)
if (readOnlyRegisters[j] == addrToWrite[k])
{
dataMasks[k] = readOnlyRegistersMasks[j];
break;
}
dataToWrite.clear();
dataReceived.clear();
for (uint16_t j = 0; j < addrToWrite.size(); ++j)
{
if (addrToWrite[j] == 0x00A6)
dataToWrite.push_back(0x1 | pattern & ~0x2);
else if (addrToWrite[j] == 0x0084)
dataToWrite.push_back(pattern & ~0x19);
else
dataToWrite.push_back(pattern & dataMasks[j]);
}
dataReceived.resize(addrToWrite.size(), 0);
liblms7_status status;
status = SPI_write_batch(&addrToWrite[0], &dataToWrite[0], addrToWrite.size());
if (status != LIBLMS7_SUCCESS)
return status;
status = SPI_read_batch(&addrToWrite[0], &dataReceived[0], addrToWrite.size());
if (status != LIBLMS7_SUCCESS)
return status;
bool registersMatch = true;
char ctemp[16];
for (uint16_t j = 0; j < dataToWrite.size(); ++j)
{
if (dataToWrite[j] != (dataReceived[j] & dataMasks[j]))
{
registersMatch = false;
sprintf(ctemp, "0x%04X", addrToWrite[j]);
ss << "\t" << ctemp << "(wr/rd): ";
sprintf(ctemp, "0x%04X", dataToWrite[j]);
ss << ctemp << "/";
sprintf(ctemp, "0x%04X", dataReceived[j]);
ss << ctemp << endl;
}
}
if (registersMatch)
{
sprintf(ctemp, "0x%04X", pattern);
ss << "\tRegisters OK (" << ctemp << ")\n";
}
return registersMatch ? LIBLMS7_SUCCESS : LIBLMS7_FAILURE;
}
/** @brief Parameters setup instructions for Tx calibration
@return 0-success, other-failure
*/
liblms7_status LMS7002M::CalibrateTxSetup(float_type bandwidth_MHz)
{
//Stage 2
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC));
uint8_t sel_band1_trf = (uint8_t)Get_SPI_Reg_bits(LMS7param(SEL_BAND1_TRF));
uint8_t sel_band2_trf = (uint8_t)Get_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF));
//rfe
//reset RFE to defaults
SetDefaults(RFE);
if (sel_band1_trf == 1)
Modify_SPI_Reg_bits(LMS7param(SEL_PATH_RFE), 3); //SEL_PATH_RFE 3
else if (sel_band2_trf == 1)
Modify_SPI_Reg_bits(LMS7param(SEL_PATH_RFE), 2);
else
return LIBLMS7_BAND_NOT_SELECTED;
if (ch == 2)
Modify_SPI_Reg_bits(LMS7param(EN_NEXTRX_RFE), 1); // EN_NEXTTX_RFE 1
Modify_SPI_Reg_bits(LMS7param(G_RXLOOPB_RFE), 8); //G_RXLOOPB_RFE 8
Modify_SPI_Reg_bits(0x010C, 4, 3, 0); //PD_MXLOBUF_RFE 0, PD_QGEN_RFE 0
Modify_SPI_Reg_bits(LMS7param(CCOMP_TIA_RFE), 10); //CCOMP_TIA_RFE 10
Modify_SPI_Reg_bits(LMS7param(CFB_TIA_RFE), 2600); //CFB_TIA_RFE 2600
Modify_SPI_Reg_bits(LMS7param(ICT_LODC_RFE), 31); //ICT_LODC_RFE 31
Modify_SPI_Reg_bits(LMS7param(PD_LNA_RFE), 1);
//RBB
//reset RBB to defaults
SetDefaults(RBB);
Modify_SPI_Reg_bits(LMS7param(PD_LPFL_RBB), 0); //PD_LPFL_RBB 0
Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), 0); //RCC_CTL_LPFL_RBB 0
Modify_SPI_Reg_bits(LMS7param(C_CTL_LPFL_RBB), 1500); //C_CTL_LPFL_RBB 1500
Modify_SPI_Reg_bits(LMS7param(G_PGA_RBB), 22); //G_PGA_RBB 22
//TRF
//reset TRF to defaults
//SetDefaults(TRF);
Modify_SPI_Reg_bits(LMS7param(L_LOOPB_TXPAD_TRF), 0); //L_LOOPB_TXPAD_TRF 0
Modify_SPI_Reg_bits(LMS7param(EN_LOOPB_TXPAD_TRF), 1); //EN_LOOPB_TXPAD_TRF 1
Modify_SPI_Reg_bits(LMS7param(EN_G_TRF), 0); //EN_G_TRF 0
if (ch == 2)
Modify_SPI_Reg_bits(LMS7param(EN_NEXTTX_TRF), 1); //EN_NEXTTX_TRF 1
Modify_SPI_Reg_bits(LMS7param(LOSS_LIN_TXPAD_TRF), 0); //LOSS_LIN_TXPAD_TRF 5
Modify_SPI_Reg_bits(LMS7param(LOSS_MAIN_TXPAD_TRF), 0); //LOSS_MAIN_TXPAD_TRF 5
//TBB
//reset TBB to defaults
/*SetDefaults(TBB);
Modify_SPI_Reg_bits(LMS7param(CG_IAMP_TBB), 9); //CG_IAMP_TBB 9
Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_FRP_TBB), 1); //ICT_IAMP_FRP_TBB 1
Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_GG_FRP_TBB), 6); //ICT_IAMP_GG_FRP_TBB 6
Modify_SPI_Reg_bits(LMS7param(RCAL_LPFH_TBB), 125); //RCAL_LPFH_TBB 0
*/
//AFE
//reset AFE to defaults
uint8_t isel_dac_afe =(uint8_t) Get_SPI_Reg_bits(LMS7param(ISEL_DAC_AFE));
SetDefaults(AFE);
Modify_SPI_Reg_bits(LMS7param(PD_RX_AFE2), 0); //PD_RX_AFE2 0
Modify_SPI_Reg_bits(LMS7param(ISEL_DAC_AFE), isel_dac_afe);
if (ch == 2)
Modify_SPI_Reg_bits(LMS7param(PD_TX_AFE2), 0);
//BIAS
uint16_t backup = Get_SPI_Reg_bits(LMS7param(RP_CALIB_BIAS));
SetDefaults(BIAS);
Modify_SPI_Reg_bits(LMS7param(RP_CALIB_BIAS), backup); //RP_CALIB_BIAS
//XBUF
Modify_SPI_Reg_bits(0x0085, 2, 0, 1); //PD_XBUF_RX 0, PD_XBUF_TX 0, EN_G_XBUF 1
//CGEN
//reset CGEN to defaults
SetDefaults(CGEN);
//power up VCO
Modify_SPI_Reg_bits(LMS7param(PD_VCO_CGEN), 0);
if (SetFrequencyCGEN(122.88) != LIBLMS7_SUCCESS)
return LIBLMS7_FAILURE;
if (TuneVCO(VCO_CGEN) != LIBLMS7_SUCCESS)
return LIBLMS7_FAILURE;
//SXR
Modify_SPI_Reg_bits(LMS7param(MAC), 1);
SetDefaults(SX);
float_type SXTfreqMHz = GetFrequencySX_MHz(Tx, mRefClkSXT_MHz);
float_type SXRfreqMHz = SXTfreqMHz - bandwidth_MHz / 4 - 1;
if (SetFrequencySX(Rx, SXRfreqMHz, mRefClkSXR_MHz) != LIBLMS7_SUCCESS)
return LIBLMS7_FAILURE;
if (TuneVCO(VCO_SXR) != LIBLMS7_SUCCESS)
return LIBLMS7_FAILURE;
//SXT
Modify_SPI_Reg_bits(LMS7param(MAC), 2);
Modify_SPI_Reg_bits(LMS7param(PD_LOCH_T2RBUF), 1); //PD_LOCH_T2RBUF 1
if (SetFrequencySX(Tx, SXTfreqMHz, mRefClkSXT_MHz) != LIBLMS7_SUCCESS)
return LIBLMS7_FAILURE;
if (TuneVCO(VCO_SXT) != LIBLMS7_SUCCESS)
return LIBLMS7_FAILURE;
Modify_SPI_Reg_bits(LMS7param(MAC), ch);
//TXTSP
SetDefaults(TxTSP);
Modify_SPI_Reg_bits(0x0200, 3, 2, 0x3); //TSGMODE 1, INSEL 1
Modify_SPI_Reg_bits(0x0208, 6, 4, 0x7); //GFIR3_BYP 1, GFIR2_BYP 1, GFIR1_BYP 1
LoadDC_REG_IQ(Tx, (int16_t)0x7FFF, (int16_t)0x8000);
Modify_SPI_Reg_bits(LMS7param(MAC), ch);
Modify_SPI_Reg_bits(0x0440, 4, 0, 0); //TX SEL[3:0] = 0 & MODE = 0
float_type offset = 0.2;
if (bandwidth_MHz == 8)
{
//SXR
Modify_SPI_Reg_bits(LMS7param(MAC), 1);
SetDefaults(SX);
float_type SXTfreqMHz = GetFrequencySX_MHz(Tx, mRefClkSXT_MHz);
float_type sxrFreq = SXTfreqMHz - bandwidth_MHz / 4 - 1 - offset;
if (SetFrequencySX(Rx, sxrFreq, mRefClkSXR_MHz) != LIBLMS7_SUCCESS)
return LIBLMS7_FAILURE;
SetNCOFrequency(Tx, 0, bandwidth_MHz / 4 + offset);
}
else
SetNCOFrequency(Tx, 0, bandwidth_MHz / 4);
//RXTSP
SetDefaults(RxTSP);
Modify_SPI_Reg_bits(LMS7param(AGC_MODE_RXTSP), 1); //AGC_MODE 1
Modify_SPI_Reg_bits(0x040C, 7, 0, 0xBF);
Modify_SPI_Reg_bits(LMS7param(CAPSEL), 0);
Modify_SPI_Reg_bits(LMS7param(HBD_OVR_RXTSP), 0); //Decimation HBD ratio
Modify_SPI_Reg_bits(LMS7param(AGC_AVG_RXTSP), 0x7); //agc_avg iq corr
return LIBLMS7_SUCCESS;
}
/** @brief Flips the CAPTURE bit and returns digital RSSI value
*/
uint32_t LMS7002M::GetRSSI()
{
Modify_SPI_Reg_bits(LMS7param(CAPTURE), 0);
Modify_SPI_Reg_bits(LMS7param(CAPTURE), 1);
return (Get_SPI_Reg_bits(0x040F, 15, 0) << 2) | Get_SPI_Reg_bits(0x040E, 1, 0);
}
/** @brief Sets Rx Dc offsets by converting two's complementary numbers to sign and magnitude
*/
void LMS7002M::SetRxDCOFF(int8_t offsetI, int8_t offsetQ)
{
uint16_t valToSend = 0;
if (offsetI < 0)
valToSend |= 0x40;
valToSend |= labs(offsetI);
valToSend = valToSend << 7;
if (offsetQ < 0)
valToSend |= 0x40;
valToSend |= labs(offsetQ);
SPI_write(0x010E, valToSend);
}
/** @brief Calibrates Transmitter. DC correction, IQ gains, IQ phase correction
@return 0-success, other-failure
*/
liblms7_status LMS7002M::CalibrateTx(float_type bandwidth_MHz)
{
liblms7_status status;
Log("Tx calibration started", LOG_INFO);
BackupAllRegisters();
int16_t iqcorr = 0;
uint16_t gcorrq = 0;
uint16_t gcorri = 0;
uint16_t dccorri;
uint16_t dccorrq;
int16_t corrI = 0;
int16_t corrQ = 0;
uint32_t minRSSI_i;
uint32_t minRSSI_q;
uint32_t minRSSI_iq;
int16_t i;
int16_t offsetI = 0;
int16_t offsetQ = 0;
const short firCoefs[] =
{
-2531,
-517,
2708,
188,
-3059,
216,
3569,
-770,
-4199,
1541,
4886,
-2577,
-5552,
3909,
6108,
-5537,
-6457,
7440,
6507,
-9566,
-6174,
11845,
5391,
-14179,
-4110,
16457,
2310,
-18561,
0,
20369,
-2780,
-21752,
5963,
22610,
-9456,
-22859,
13127,
22444,
-16854,
-21319,
20489,
19492,
-23883,
-17002,
26881,
13902,
-29372,
-10313,
31226,
6345,
-32380,
-2141,
32767,
-2141,
-32380,
6345,
31226,
-10313,
-29372,
13902,
26881,
-17002,
-23883,
19492,
20489,
-21319,
-16854,
22444,
13127,
-22859,
-9456,
22610,
5963,
-21752,
-2780,
20369,
0,
-18561,
2310,
16457,
-4110,
-14179,
5391,
11845,
-6174,
-9566,
6507,
7440,
-6457,
-5537,
6108,
3909,
-5552,
-2577,
4886,
1541,
-4199,
-770,
3569,
216,
-3059,
188,
2708,
-517,
-2531
};
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC));
//Stage 1
uint8_t sel_band1_trf = (uint8_t)Get_SPI_Reg_bits(LMS7param(SEL_BAND1_TRF));
uint8_t sel_band2_trf = (uint8_t)Get_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF));
Log("Setup stage", LOG_INFO);
status = CalibrateTxSetup(bandwidth_MHz);
if (status != LIBLMS7_SUCCESS)
goto TxCalibrationEnd; //go to ending stage to restore registers
//Stage 3
//Calibrate Rx DC
Log("Rx DC calibration", LOG_INFO);
{
uint16_t requiredRegs[] = { 0x0400, 0x040A, 0x010D, 0x040C };
uint16_t requiredMask[] = { 0x6000, 0x3007, 0x0040, 0x00FF }; //CAPSEL, AGC_MODE, AGC_AVG, EN_DCOFF, Bypasses
uint16_t requiredValue[] = { 0x0000, 0x1007, 0x0040, 0x00BD };
Modify_SPI_Reg_mask(requiredRegs, requiredMask, requiredValue, 0, 3);
}
for (i = 0; i<6; ++i)
{
FindMinRSSI(LMS7param(DCOFFI_RFE), offsetI, &offsetI, 3, 2, 32 >> i);
FindMinRSSI(LMS7param(DCOFFQ_RFE), offsetQ, &offsetQ, 3, 2, 32 >> i);
}
SetRxDCOFF((int8_t)offsetI, (int8_t)offsetQ);
Modify_SPI_Reg_bits(LMS7param(DC_BYP_RXTSP), 0); // DC_BYP 0
sel_band1_trf = (uint8_t)Get_SPI_Reg_bits(LMS7param(SEL_BAND1_TRF));
sel_band2_trf = (uint8_t)Get_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF));
//B
Modify_SPI_Reg_bits(0x0100, 0, 0, 1); //EN_G_TRF 1
if (sel_band1_trf == 1)
{
Modify_SPI_Reg_bits(LMS7param(PD_RLOOPB_1_RFE), 0); //PD_RLOOPB_1_RFE 0
Modify_SPI_Reg_bits(LMS7param(EN_INSHSW_LB1_RFE), 0); //EN_INSHSW_LB1 0
}
if (sel_band2_trf == 1)
{
Modify_SPI_Reg_bits(LMS7param(PD_RLOOPB_2_RFE), 0); //PD_RLOOPB_2_RFE 0
Modify_SPI_Reg_bits(LMS7param(EN_INSHSW_LB2_RFE), 0); // EN_INSHSW_LB2 0
}
FixRXSaturation();
Modify_SPI_Reg_bits(LMS7param(GFIR3_BYP_RXTSP), 0); //GFIR3_BYP 0
Modify_SPI_Reg_bits(LMS7param(HBD_OVR_RXTSP), 2);
Modify_SPI_Reg_bits(LMS7param(GFIR3_L_RXTSP), 7);
Modify_SPI_Reg_bits(LMS7param(GFIR3_N_RXTSP), 7);
SetGFIRCoefficients(Rx, 2, firCoefs, sizeof(firCoefs) / sizeof(int16_t));
Log("IQ correction stage", LOG_INFO);
Modify_SPI_Reg_bits(LMS7param(GCORRI_TXTSP), 2047);
Modify_SPI_Reg_bits(LMS7param(GCORRQ_TXTSP), 2047);
Modify_SPI_Reg_bits(LMS7param(IQCORR_TXTSP), 0);
Log("I gain", LOG_INFO);
minRSSI_i = FindMinRSSI_Gain(LMS7param(GCORRI_TXTSP), &gcorri);
Modify_SPI_Reg_bits(LMS7param(GCORRI_TXTSP), 2047);
Modify_SPI_Reg_bits(LMS7param(GCORRQ_TXTSP), 2047);
Log("Q gain", LOG_INFO);
minRSSI_q = FindMinRSSI_Gain(LMS7param(GCORRQ_TXTSP), &gcorrq);
if (minRSSI_i < minRSSI_q)
gcorrq = 2047;
else
gcorri = 2047;
Modify_SPI_Reg_bits(LMS7param(GCORRI_TXTSP), gcorri);
Modify_SPI_Reg_bits(LMS7param(GCORRQ_TXTSP), gcorrq);
Log("Phase", LOG_INFO);
iqcorr = 0;
for (uint8_t i = 0; i<9; ++i)
minRSSI_iq = FindMinRSSI(LMS7param(IQCORR_TXTSP), iqcorr, &iqcorr, 3, 1, 256 >> i);
Modify_SPI_Reg_bits(LMS7param(GCORRI_TXTSP), gcorri);
Modify_SPI_Reg_bits(LMS7param(GCORRQ_TXTSP), gcorrq);
Modify_SPI_Reg_bits(LMS7param(IQCORR_TXTSP), iqcorr);
Modify_SPI_Reg_bits(LMS7param(MAC), 1);
status = SetFrequencySX(Rx, GetFrequencySX_MHz(Tx, mRefClkSXT_MHz)-1, mRefClkSXR_MHz);
if (status != LIBLMS7_SUCCESS)
goto TxCalibrationEnd; //go to ending stage to restore registers
//C
Modify_SPI_Reg_bits(LMS7param(MAC), ch);
Modify_SPI_Reg_bits(LMS7param(AGC_MODE_RXTSP), 1);
Modify_SPI_Reg_bits(LMS7param(CAPSEL), 0);
Log("TX LO calibration", LOG_INFO);
//Calibrate Tx DC
for (uint8_t i = 0; i<7; ++i)
{
FindMinRSSI(LMS7param(DCCORRI_TXTSP), corrI, &corrI, 3, 1, 64 >> i);
FindMinRSSI(LMS7param(DCCORRQ_TXTSP), corrQ, &corrQ, 3, 1, 64 >> i);
}
dccorri = Get_SPI_Reg_bits(LMS7param(DCCORRI_TXTSP));
dccorrq = Get_SPI_Reg_bits(LMS7param(DCCORRQ_TXTSP));
// Stage 4
TxCalibrationEnd:
Log("Restoring registers state", LOG_INFO);
Modify_SPI_Reg_bits(LMS7param(MAC), ch);
RestoreAllRegisters();
if (status != LIBLMS7_SUCCESS)
{
Log("Tx calibration failed", LOG_WARNING);
return status;
}
Modify_SPI_Reg_bits(LMS7param(MAC), ch);
Modify_SPI_Reg_bits(LMS7param(DCCORRI_TXTSP), dccorri);
Modify_SPI_Reg_bits(LMS7param(DCCORRQ_TXTSP), dccorrq);
Modify_SPI_Reg_bits(LMS7param(GCORRI_TXTSP), gcorri);
Modify_SPI_Reg_bits(LMS7param(GCORRQ_TXTSP), gcorrq);
Modify_SPI_Reg_bits(LMS7param(IQCORR_TXTSP), iqcorr);
Modify_SPI_Reg_bits(LMS7param(DC_BYP_TXTSP), 0); //DC_BYP
Modify_SPI_Reg_bits(0x0208, 1, 0, 0); //GC_BYP PH_BYP
Log("Tx calibration finished", LOG_INFO);
return LIBLMS7_SUCCESS;
}
/** @brief Performs Rx DC offsets calibration
*/
void LMS7002M::CalibrateRxDC_RSSI()
{
int16_t i;
int16_t offsetI = 0;
int16_t offsetQ = 0;
uint16_t requiredRegs[] = { 0x0400, 0x040A, 0x010D, 0x040C };
uint16_t requiredMask[] = { 0x6000, 0x3007, 0x0040, 0x00FF }; //CAPSEL, AGC_MODE, AGC_AVG, EN_DCOFF, Bypasses
uint16_t requiredValue[] = { 0x0000, 0x1007, 0x0040, 0x00BD };
Modify_SPI_Reg_mask(requiredRegs, requiredMask, requiredValue, 0, 3);
for (i = 0; i<6; ++i)
{
FindMinRSSI(LMS7param(DCOFFI_RFE), offsetI, &offsetI, 3, 2, 32 >> i);
FindMinRSSI(LMS7param(DCOFFQ_RFE), offsetQ, &offsetQ, 3, 2, 32 >> i);
}
Modify_SPI_Reg_bits(LMS7param(EN_DCOFF_RXFE_RFE), 1);
SetRxDCOFF((int8_t)offsetI, (int8_t)offsetQ);
Modify_SPI_Reg_bits(LMS7param(DC_BYP_RXTSP), 0); // DC_BYP 0
}
/** @brief Tries to detect and fix gains if Rx is saturated
@return 0-success, other-failure
*/
liblms7_status LMS7002M::FixRXSaturation()
{
uint8_t g_rxloopb = 0;
Modify_SPI_Reg_bits(LMS7param(G_RXLOOPB_RFE), g_rxloopb);
Modify_SPI_Reg_bits(LMS7param(L_LOOPB_TXPAD_TRF), 3);
int8_t lLoopb = 3;
const uint32_t rssi_saturation_level = 0xD000;
while (g_rxloopb < 15)
{
g_rxloopb += 1;
Modify_SPI_Reg_bits(LMS7param(G_RXLOOPB_RFE), g_rxloopb);
Modify_SPI_Reg_bits(LMS7param(L_LOOPB_TXPAD_TRF), 3);
if (GetRSSI() < rssi_saturation_level)
{
for (lLoopb = 3; lLoopb >= 0; --lLoopb)
{
Modify_SPI_Reg_bits(LMS7param(L_LOOPB_TXPAD_TRF), lLoopb);
if (GetRSSI() > rssi_saturation_level)
{
++lLoopb;
Modify_SPI_Reg_bits(LMS7param(L_LOOPB_TXPAD_TRF), lLoopb);
goto finished;
}
}
}
else
{
g_rxloopb -= 1;
Modify_SPI_Reg_bits(LMS7param(G_RXLOOPB_RFE), g_rxloopb);
break;
}
}
finished:
return GetRSSI() < rssi_saturation_level ? LIBLMS7_SUCCESS : LIBLMS7_FAILURE;
}
uint32_t LMS7002M::FindMinRSSI(const LMS7Parameter &param, const int16_t startValue, int16_t *result, const uint8_t scanWidth, const uint8_t twoCompl, int8_t stepMult)
{
return FindMinRSSI(param.address, param.msb, param.lsb, startValue, result, scanWidth, twoCompl, stepMult);
}
/** @brief Searches for minimal RSSI value while changing given address bits
@param addr address of parameter being changed
@param msb most significant bit index
@param lsb least significant bit index
@param startValue initial value where to start search
@param result found minimal parameter value will be set here
@param twoCompl varying parameter value is treated as two's complement
@return found minimal RSSI value
*/
uint32_t LMS7002M::FindMinRSSI(const uint16_t addr, const uint8_t msb, const uint8_t lsb, const int16_t startValue, int16_t *result, const uint8_t scanWidth, const uint8_t twoCompl, int8_t stepMult)
{
if (scanWidth < 1)
return ~0;
int minI;
int min = startValue;
int globMin = 0;
uint32_t minRSSI = ~0;
unsigned int *rssiField = new unsigned int[scanWidth];
int minRSSIindex;
int i;
int maxVal;
int minVal = 0;
if (twoCompl)
{
maxVal = (~(~0x0 << (msb - lsb + 1))) / 2;
minVal = -(~(~0x0 << (msb - lsb + 1))) / 2 - 1;
}
else
maxVal = (~(~0x0 << (msb - lsb + 1)));
Modify_SPI_Reg_bits(addr, msb, lsb, startValue);
Modify_SPI_Reg_bits(LMS7param(AGC_MODE_RXTSP), 1);
Modify_SPI_Reg_bits(LMS7param(CAPSEL), 0);
minRSSIindex = 0;
for (i = 0; i<scanWidth; ++i)
{
short currentValue = min + (i - scanWidth / 2)*stepMult;
if (currentValue < minVal)
currentValue = minVal;
else if (currentValue > maxVal)
currentValue = maxVal;
if (twoCompl == 2)
{
uint16_t valToSend = 0;
if (currentValue < 0)
valToSend |= 0x40;
valToSend |= labs(currentValue);
Modify_SPI_Reg_bits(addr, msb, lsb, valToSend);
}
else
Modify_SPI_Reg_bits(addr, msb, lsb, currentValue);
rssiField[i] = GetRSSI();
}
minI = min;
minRSSIindex = 0;
for (i = 0; i<scanWidth; ++i)
if (rssiField[i] < minRSSI)
{
minRSSI = rssiField[i];
minRSSIindex = i;
minI = min + (i - scanWidth / 2)*stepMult;
if (minI > maxVal)
minI = maxVal;
else if (minI < minVal)
minI = minVal;
globMin = minI;
}
min = minI;
Modify_SPI_Reg_bits(addr, msb, lsb, min);
*result = min;
return minRSSI;
}
/** @brief Sets given module registers to default values
@return 0-success, other-failure
*/
liblms7_status LMS7002M::SetDefaults(MemorySection module)
{
liblms7_status status = LIBLMS7_SUCCESS;
vector<uint16_t> addrs;
vector<uint16_t> values;
for(uint32_t address = MemorySectionAddresses[module][0]; address <= MemorySectionAddresses[module][1]; ++address)
{
addrs.push_back(address);
values.push_back(mRegistersMap->GetDefaultValue(address));
}
status = SPI_write_batch(&addrs[0], &values[0], addrs.size());
return status;
}
/** @brief Parameters setup instructions for Rx calibration
@param bandwidth_MHz filter bandwidth in MHz
@return 0-success, other-failure
*/
liblms7_status LMS7002M::CalibrateRxSetup(float_type bandwidth_MHz)
{
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC));
//rfe
if (ch == 2)
Modify_SPI_Reg_bits(LMS7param(EN_NEXTTX_TRF), 1); // EN_NEXTTX_TRF 0
Modify_SPI_Reg_bits(LMS7param(G_RXLOOPB_RFE), 15); //G_RXLOOPB_RFE 15
Modify_SPI_Reg_bits(0x010C, 4, 3, 0); //PD_MXLOBUF_RFE 0, PD_QGEN_RFE 0
Modify_SPI_Reg_bits(0x010C, 1, 1, 0); //PD_TIA 0
Modify_SPI_Reg_bits(0x010C, 7, 7, 1); //PD_LNA 1
Modify_SPI_Reg_bits(0x0110, 4, 0, 31); //ICT_LO_RFE 31
Modify_SPI_Reg_bits(0x010D, 4, 1, 0xFF); // all short switches are enabled
//RBB
Modify_SPI_Reg_bits(0x0115, 15, 14, 0); //Loopback switches disable
Modify_SPI_Reg_bits(0x0119, 15, 15, 0); //OSW_PGA 0
//TRF
//reset TRF to defaults
SetDefaults(TRF);
Modify_SPI_Reg_bits(LMS7param(L_LOOPB_TXPAD_TRF), 0); //L_LOOPB_TXPAD_TRF 0
Modify_SPI_Reg_bits(LMS7param(EN_LOOPB_TXPAD_TRF), 1); //EN_LOOPB_TXPAD_TRF 1
Modify_SPI_Reg_bits(LMS7param(EN_G_TRF), 0); //EN_G_TRF 0
if (ch == 2)
Modify_SPI_Reg_bits(LMS7param(EN_NEXTTX_TRF), 1); //EN_NEXTTX_TRF 1
Modify_SPI_Reg_bits(LMS7param(LOSS_LIN_TXPAD_TRF), 0); //LOSS_LIN_TXPAD_TRF 5
Modify_SPI_Reg_bits(LMS7param(LOSS_MAIN_TXPAD_TRF), 0); //LOSS_MAIN_TXPAD_TRF 5
//TBB
//reset TBB to defaults
SetDefaults(TBB);
Modify_SPI_Reg_bits(LMS7param(CG_IAMP_TBB), 9); //CG_IAMP_TBB 9
Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_FRP_TBB), 1); //ICT_IAMP_FRP_TBB 1
Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_GG_FRP_TBB), 6); //ICT_IAMP_GG_FRP_TBB 6
//AFE
//reset AFE to defaults
SetDefaults(AFE);
Modify_SPI_Reg_bits(LMS7param(PD_RX_AFE2), 0); //PD_RX_AFE2
if (ch == 2)
{
Modify_SPI_Reg_bits(LMS7param(PD_TX_AFE2), 0); //PD_TX_AFE2
}
//BIAS
uint16_t backup = Get_SPI_Reg_bits(0x0084, 10, 6);
SetDefaults(BIAS);
Modify_SPI_Reg_bits(0x0084, 10, 6, backup); //RP_CALIB_BIAS
//XBUF
Modify_SPI_Reg_bits(0x0085, 2, 0, 1); //PD_XBUF_RX 0, PD_XBUF_TX 0, EN_G_XBUF 1
//CGEN
//reset CGEN to defaults
SetDefaults(CGEN);
//power up VCO
Modify_SPI_Reg_bits(0x0086, 2, 2, 0);
liblms7_status status = SetFrequencyCGEN(122.88);
if (status != LIBLMS7_SUCCESS)
return status;
// //SXR
Modify_SPI_Reg_bits(LMS7param(MAC), 1);
float_type SXRfreqMHz = GetFrequencySX_MHz(Rx, mRefClkSXR_MHz);
//SXT
Modify_SPI_Reg_bits(LMS7param(MAC), 2);
Modify_SPI_Reg_bits(LMS7param(PD_LOCH_T2RBUF), 1); //PD_LOCH_t2RBUF 1
status = SetFrequencySX(Tx, SXRfreqMHz + bandwidth_MHz / 4, mRefClkSXT_MHz);
if ( status != LIBLMS7_SUCCESS)
return status;
Modify_SPI_Reg_bits(LMS7param(MAC), ch);
//TXTSP
SetDefaults(TxTSP);
Modify_SPI_Reg_bits(0x0200, 3, 2, 0x3); //TSGMODE 1, INSEL 1
//Modify_SPI_Reg_bits(0x0208, 6, 4, 0xFFFF); //GFIR3_BYP 1, GFIR2_BYP 1, GFIR1_BYP 1
Modify_SPI_Reg_bits(0x0208, 6, 6, 1); //GFIR3_BYP 1, GFIR2_BYP 1, GFIR1_BYP 1
Modify_SPI_Reg_bits(0x0208, 5, 5, 1); //GFIR3_BYP 1, GFIR2_BYP 1, GFIR1_BYP 1
Modify_SPI_Reg_bits(0x0208, 4, 4, 1); //GFIR3_BYP 1, GFIR2_BYP 1, GFIR1_BYP 1
LoadDC_REG_IQ(Tx, (int16_t)0x7FFF, (int16_t)0x8000);
SetNCOFrequency(Tx, 0, 0);
//RXTSP
SetDefaults(RxTSP);
Modify_SPI_Reg_bits(LMS7param(AGC_MODE_RXTSP), 1); //AGC_MODE 1
Modify_SPI_Reg_bits(0x040C, 7, 7, 0x1); //CMIX_BYP 1
Modify_SPI_Reg_bits(0x040C, 6, 6, 0x0); //AGC_BYP 0
Modify_SPI_Reg_bits(0x040C, 5, 5, 1); //
Modify_SPI_Reg_bits(0x040C, 4, 4, 1); //
Modify_SPI_Reg_bits(0x040C, 3, 3, 1); //
Modify_SPI_Reg_bits(0x040C, 2, 2, 1); // DC_BYP
Modify_SPI_Reg_bits(0x040C, 1, 1, 1); //
Modify_SPI_Reg_bits(0x040C, 0, 0, 1); //
Modify_SPI_Reg_bits(LMS7param(CAPSEL), 0);
Modify_SPI_Reg_bits(LMS7param(HBD_OVR_RXTSP), 2);
Modify_SPI_Reg_bits(LMS7param(AGC_AVG_RXTSP), 0x7); //agc_avg iq corr
return LIBLMS7_SUCCESS;
}
/** @brief Calibrates Receiver. DC offset, IQ gains, IQ phase correction
@return 0-success, other-failure
*/
liblms7_status LMS7002M::CalibrateRx(float_type bandwidth_MHz)
{
liblms7_status status;
uint32_t minRSSI_i;
uint32_t minRSSI_q;
int16_t iqcorr_rx = 0;
uint32_t minRSSI_iq;
int16_t dcoffi;
int16_t dcoffq;
const int16_t firCoefs[] =
{
-2531,
-517,
2708,
188,
-3059,
216,
3569,
-770,
-4199,
1541,
4886,
-2577,
-5552,
3909,
6108,
-5537,
-6457,
7440,
6507,
-9566,
-6174,
11845,
5391,
-14179,
-4110,
16457,
2310,
-18561,
0,
20369,
-2780,
-21752,
5963,
22610,
-9456,
-22859,
13127,
22444,
-16854,
-21319,
20489,
19492,
-23883,
-17002,
26881,
13902,
-29372,
-10313,
31226,
6345,
-32380,
-2141,
32767,
-2141,
-32380,
6345,
31226,
-10313,
-29372,
13902,
26881,
-17002,
-23883,
19492,
20489,
-21319,
-16854,
22444,
13127,
-22859,
-9456,
22610,
5963,
-21752,
-2780,
20369,
0,
-18561,
2310,
16457,
-4110,
-14179,
5391,
11845,
-6174,
-9566,
6507,
7440,
-6457,
-5537,
6108,
3909,
-5552,
-2577,
4886,
1541,
-4199,
-770,
3569,
216,
-3059,
188,
2708,
-517,
-2531
};
Log("Rx calibration started", LOG_INFO);
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC));
Log("Saving registers state", LOG_INFO);
BackupAllRegisters();
uint8_t sel_path_rfe = (uint8_t)Get_SPI_Reg_bits(LMS7param(SEL_PATH_RFE));
if (sel_path_rfe == 1 || sel_path_rfe == 0)
return LIBLMS7_BAD_SEL_PATH;
Log("Setup stage", LOG_INFO);
status = CalibrateRxSetup(bandwidth_MHz);
if (status != LIBLMS7_SUCCESS)
goto RxCalibrationEndStage;
Log("Rx DC calibration", LOG_INFO);
CalibrateRxDC_RSSI();
dcoffi = Get_SPI_Reg_bits(LMS7param(DCOFFI_RFE));
dcoffq = Get_SPI_Reg_bits(LMS7param(DCOFFQ_RFE));
Modify_SPI_Reg_bits(LMS7param(EN_G_TRF), 1);
if (sel_path_rfe == 2)
{
Modify_SPI_Reg_bits(LMS7param(PD_RLOOPB_2_RFE), 0);
Modify_SPI_Reg_bits(0x0103, 10, 10, 1);
Modify_SPI_Reg_bits(0x0103, 11, 11, 0);
Modify_SPI_Reg_bits(LMS7param(EN_INSHSW_LB2_RFE), 0);
}
if (sel_path_rfe == 3)
{
Modify_SPI_Reg_bits(LMS7param(PD_RLOOPB_1_RFE), 0);
Modify_SPI_Reg_bits(0x0103, 11, 11, 1);
Modify_SPI_Reg_bits(0x0103, 10, 10, 0);
Modify_SPI_Reg_bits(LMS7param(EN_INSHSW_LB1_RFE), 0);
}
Modify_SPI_Reg_bits(0x040C, 7, 7, 0); //CMIX_BYP 0
Modify_SPI_Reg_bits(0x040C, 2, 0, 0); //DC_BYP 0, GC_BYP 0, PH_BYP 0
Modify_SPI_Reg_bits(LMS7param(CMIX_GAIN_RXTSP), 1); //CMIX_GAIN 1 +6 db
Modify_SPI_Reg_bits(0x040C, 13, 13, 1); //CMIX_SC 1
FixRXSaturation();
Modify_SPI_Reg_bits(0x040C, 5, 5, 0); //GFIR3_BYP 0
Modify_SPI_Reg_bits(LMS7param(HBD_OVR_RXTSP), 2);
Modify_SPI_Reg_bits(LMS7param(GFIR3_L_RXTSP), 7);
Modify_SPI_Reg_bits(LMS7param(GFIR3_N_RXTSP), 7);
SetGFIRCoefficients(Rx, 2, firCoefs, sizeof(firCoefs) / sizeof(int16_t));
SetNCOFrequency(Rx, 0, bandwidth_MHz / 4 + 1);
Modify_SPI_Reg_bits(LMS7param(GCORRI_RXTSP), 2047);
Modify_SPI_Reg_bits(LMS7param(GCORRQ_RXTSP), 2047);
Log("IQ correction stage", LOG_INFO);
iqcorr_rx = 0;
for (int i = 0; i<9; ++i)
minRSSI_iq = FindMinRSSI(LMS7param(IQCORR_RXTSP), iqcorr_rx, &iqcorr_rx, 3, 1, 256 >> i);
Modify_SPI_Reg_bits(LMS7param(IQCORR_RXTSP), iqcorr_rx);
uint16_t mingcorri;
Log("I gain", LOG_INFO);
minRSSI_i = FindMinRSSI_Gain(LMS7param(GCORRI_RXTSP), &mingcorri);
Modify_SPI_Reg_bits(LMS7param(GCORRI_RXTSP), 2047);
Modify_SPI_Reg_bits(LMS7param(GCORRQ_RXTSP), 2047);
Log("Q gain", LOG_INFO);
uint16_t mingcorrq;
minRSSI_q = FindMinRSSI_Gain(LMS7param(GCORRQ_RXTSP), &mingcorrq);
if (minRSSI_i < minRSSI_q)
mingcorrq = 2047;
else
mingcorri = 2047;
Modify_SPI_Reg_bits(LMS7param(GCORRI_RXTSP), mingcorri);
Modify_SPI_Reg_bits(LMS7param(GCORRQ_RXTSP), mingcorrq);
Log("Phase", LOG_INFO);
for (int i = 0; i<9; ++i)
minRSSI_iq = FindMinRSSI(LMS7param(IQCORR_RXTSP), iqcorr_rx, &iqcorr_rx, 3, 1, 256 >> i);
RxCalibrationEndStage:
Log("Restoring registers state", LOG_INFO);
RestoreAllRegisters();
if (status != LIBLMS7_SUCCESS)
{
Log("Rx calibration failed", LOG_WARNING);
return status;
}
Modify_SPI_Reg_bits(LMS7param(MAC), ch);
SetRxDCOFF((int8_t)dcoffi, (int8_t)dcoffq);
Modify_SPI_Reg_bits(LMS7param(EN_DCOFF_RXFE_RFE), 1);
Modify_SPI_Reg_bits(LMS7param(GCORRI_RXTSP), mingcorri);
Modify_SPI_Reg_bits(LMS7param(GCORRQ_RXTSP), mingcorrq);
Modify_SPI_Reg_bits(LMS7param(IQCORR_RXTSP), iqcorr_rx);
Modify_SPI_Reg_bits(0x040C, 2, 0, 0); //DC_BYP 0, GC_BYP 0, PH_BYP 0
Modify_SPI_Reg_bits(0x0110, 4, 0, 31); //ICT_LO_RFE 31
Log("Rx calibration finished", LOG_INFO);
return LIBLMS7_SUCCESS;
}
const uint16_t backupAddrs[] = {
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028,
0x0029, 0x002A, 0x002B, 0x002C, 0x002E, 0x0081, 0x0082, 0x0084, 0x0085,
0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x0092, 0x0093, 0x0094,
0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E,
0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8,
0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0100, 0x0101, 0x0102, 0x0103,
0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010A, 0x010C, 0x010D, 0x010E,
0x010F, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117, 0x0118,
0x0119, 0x011A, 0x011C, 0x011D, 0x011E, 0x011F, 0x0120, 0x0121, 0x0122, 0x0123,
0x0124, 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208,
0x0240, 0x0242, 0x0243, 0x0400, 0x0401, 0x0402,
0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, 0x040C,
0x0440, 0x0442, 0x0443 };
uint16_t backupRegs[sizeof(backupAddrs) / 2];
const uint16_t backupSXAddr[] = { 0x011C, 0x011D, 0x011E, 0x011F, 0x01200, 0x0121, 0x0122, 0x0123, 0x0124 };
uint16_t backupRegsSXR[sizeof(backupSXAddr) / 2];
uint16_t backupRegsSXT[sizeof(backupSXAddr) / 2];
/** @brief Stores chip current registers state into memory for later restoration
*/
void LMS7002M::BackupAllRegisters()
{
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC));
SPI_read_batch(backupAddrs, backupRegs, sizeof(backupAddrs) / sizeof(uint16_t));
Modify_SPI_Reg_bits(LMS7param(MAC), 1); // channel A
SPI_read_batch(backupSXAddr, backupRegsSXR, sizeof(backupRegsSXR) / sizeof(uint16_t));
Modify_SPI_Reg_bits(LMS7param(MAC), 2); // channel B
SPI_read_batch(backupSXAddr, backupRegsSXT, sizeof(backupRegsSXR) / sizeof(uint16_t));
Modify_SPI_Reg_bits(LMS7param(MAC), ch);
}
/** @brief Sets chip registers to state that was stored in memory using BackupAllRegisters()
*/
void LMS7002M::RestoreAllRegisters()
{
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC));
SPI_write_batch(backupAddrs, backupRegs, sizeof(backupAddrs) / sizeof(uint16_t));
Modify_SPI_Reg_bits(LMS7param(MAC), 1); // channel A
SPI_write_batch(backupSXAddr, backupRegsSXR, sizeof(backupRegsSXR) / sizeof(uint16_t));
Modify_SPI_Reg_bits(LMS7param(MAC), 2); // channel B
SPI_write_batch(backupSXAddr, backupRegsSXT, sizeof(backupRegsSXR) / sizeof(uint16_t));
Modify_SPI_Reg_bits(LMS7param(MAC), ch);
}
/** @brief Searches for minimal digital RSSI value by changing given gain parameter
@param param LMS7002M gain correction parameter
@param foundValue returns value which achieved minimal RSSI
@return minimal found RSSI value
*/
uint32_t LMS7002M::FindMinRSSI_Gain(const LMS7Parameter &param, uint16_t *foundValue)
{
uint32_t RSSI = ~0 - 2;
uint32_t prevRSSI = RSSI + 1;
uint8_t decrement = 2;
uint16_t gcorr = 2047;
while (gcorr > 1024)
{
Modify_SPI_Reg_bits(param, gcorr);
RSSI = GetRSSI();
if (RSSI < prevRSSI)
{
prevRSSI = RSSI;
*foundValue = gcorr;
gcorr -= decrement;
decrement *= 2;
}
else
{
if (decrement == 2)
break;
gcorr -= decrement;
decrement = 2;
}
}
return prevRSSI;
}
/** @brief Reads all chip configuration and checks if it matches with local registers copy
*/
bool LMS7002M::IsSynced()
{
if (controlPort->IsOpen() == false)
return false;
bool isSynced = true;
liblms7_status status;
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC));
vector<uint16_t> addrToRead = mRegistersMap->GetUsedAddresses(0);
vector<uint16_t> dataReceived;
dataReceived.resize(addrToRead.size(), 0);
Modify_SPI_Reg_bits(LMS7param(MAC), 1);
status = SPI_read_batch(&addrToRead[0], &dataReceived[0], addrToRead.size());
if (status != LIBLMS7_SUCCESS)
{
isSynced = false;
goto isSyncedEnding;
}
//mask out readonly bits
for (uint16_t j = 0; j < sizeof(readOnlyRegisters) / sizeof(uint16_t); ++j)
for (uint16_t k = 0; k < addrToRead.size(); ++k)
if (readOnlyRegisters[j] == addrToRead[k])
{
dataReceived[k] &= readOnlyRegistersMasks[j];
break;
}
//check if local copy matches chip
for (uint16_t i = 0; i < addrToRead.size(); ++i)
{
if (dataReceived[i] != mRegistersMap->GetValue(0, addrToRead[i]))
{
isSynced = false;
goto isSyncedEnding;
}
}
addrToRead.clear(); //add only B channel addresses
addrToRead = mRegistersMap->GetUsedAddresses(1);
//mask out readonly bits
for (uint16_t j = 0; j < sizeof(readOnlyRegisters) / sizeof(uint16_t); ++j)
for (uint16_t k = 0; k < addrToRead.size(); ++k)
if (readOnlyRegisters[j] == addrToRead[k])
{
dataReceived[k] &= readOnlyRegistersMasks[j];
break;
}
Modify_SPI_Reg_bits(LMS7param(MAC), 2);
status = SPI_read_batch(&addrToRead[0], &dataReceived[0], addrToRead.size());
if (status != LIBLMS7_SUCCESS)
return false;
//check if local copy matches chip
for (uint16_t i = 0; i < addrToRead.size(); ++i)
if (dataReceived[i] != mRegistersMap->GetValue(1, addrToRead[i]))
{
isSynced = false;
break;
}
isSyncedEnding:
Modify_SPI_Reg_bits(LMS7param(MAC), ch); //restore previously used channel
return isSynced;
}
/** @brief Writes all registers from host to chip
When used on Novena board, also changes gpios to match rx path and tx band selections
*/
liblms7_status LMS7002M::UploadAll()
{
if (controlPort == NULL)
return LIBLMS7_NO_CONNECTION_MANAGER;
if (controlPort->IsOpen() == false)
return LIBLMS7_NOT_CONNECTED;
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); //remember used channel
liblms7_status status;
vector<uint16_t> addrToWrite;
vector<uint16_t> dataToWrite;
uint16_t x0020_value = mRegistersMap->GetValue(0, 0x0020);
Modify_SPI_Reg_bits(LMS7param(MAC), 1); //select A channel
addrToWrite = mRegistersMap->GetUsedAddresses(0);
//remove 0x0020 register from list, to not change MAC
addrToWrite.erase( find(addrToWrite.begin(), addrToWrite.end(), 0x0020) );
for (auto address : addrToWrite)
dataToWrite.push_back(mRegistersMap->GetValue(0, address));
status = SPI_write_batch(&addrToWrite[0], &dataToWrite[0], addrToWrite.size());
status = LIBLMS7_SUCCESS;
if (status != LIBLMS7_SUCCESS)
return status;
//after all channel A registers have been written, update 0x0020 register value
status = SPI_write(0x0020, x0020_value);
if (status != LIBLMS7_SUCCESS)
return status;
Modify_SPI_Reg_bits(LMS7param(MAC), 2);
if (status != LIBLMS7_SUCCESS)
return status;
addrToWrite = mRegistersMap->GetUsedAddresses(1);
dataToWrite.clear();
for (auto address : addrToWrite)
{
dataToWrite.push_back(mRegistersMap->GetValue(1, address));
}
Modify_SPI_Reg_bits(LMS7param(MAC), 2); //select B channel
status = SPI_write_batch(&addrToWrite[0], &dataToWrite[0], addrToWrite.size());
if (status != LIBLMS7_SUCCESS)
return status;
Modify_SPI_Reg_bits(LMS7param(MAC), ch); //restore last used channel
//in case of Novena board, need to update GPIO
if(controlPort->GetInfo().device == LMS_DEV_NOVENA)
{
uint16_t regValue = SPI_read(0x0706) & 0xFFF8;
//lms_gpio2 - tx output selection:
// 0 - TX1_A and TX1_B (Band 1),
// 1 - TX2_A and TX2_B (Band 2)
regValue |= Get_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF)) << 2; //gpio2
//RX active paths
//lms_gpio0 | lms_gpio1 RX_A RX_B
// 0 0 => no active path
// 1 0 => LNAW_A LNAW_B
// 0 1 => LNAH_A LNAH_B
// 1 1 => LNAL_A LNAL_B
switch(Get_SPI_Reg_bits(LMS7param(SEL_PATH_RFE)))
{
//set gpio1:gpio0
case 0: regValue |= 0x0; break;
case 1: regValue |= 0x2; break;
case 2: regValue |= 0x3; break;
case 3: regValue |= 0x1; break;
}
SPI_write(0x0706, regValue);
}
return LIBLMS7_SUCCESS;
}
/** @brief Reads all registers from the chip to host
When used on Novena board, also updates gpios to match rx path and tx band selections
*/
liblms7_status LMS7002M::DownloadAll()
{
if (controlPort == nullptr)
return LIBLMS7_NO_CONNECTION_MANAGER;
if (controlPort->IsOpen() == false)
return LIBLMS7_NOT_CONNECTED;
liblms7_status status;
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC), false);
vector<uint16_t> addrToRead = mRegistersMap->GetUsedAddresses(0);
vector<uint16_t> dataReceived;
dataReceived.resize(addrToRead.size(), 0);
Modify_SPI_Reg_bits(LMS7param(MAC), 1);
status = SPI_read_batch(&addrToRead[0], &dataReceived[0], addrToRead.size());
if (status != LIBLMS7_SUCCESS)
return status;
for (uint16_t i = 0; i < addrToRead.size(); ++i)
{
uint16_t adr = addrToRead[i];
uint16_t val = dataReceived[i];
mRegistersMap->SetValue(0, addrToRead[i], dataReceived[i]);
}
addrToRead.clear(); //add only B channel addresses
addrToRead = mRegistersMap->GetUsedAddresses(1);
dataReceived.resize(addrToRead.size(), 0);
Modify_SPI_Reg_bits(LMS7param(MAC), 2);
status = SPI_read_batch(&addrToRead[0], &dataReceived[0], addrToRead.size());
if (status != LIBLMS7_SUCCESS)
return status;
for (uint16_t i = 0; i < addrToRead.size(); ++i)
mRegistersMap->SetValue(1, addrToRead[i], dataReceived[i]);
Modify_SPI_Reg_bits(LMS7param(MAC), ch); //retore previously used channel
//in case of Novena board, update GPIO
if(controlPort->GetInfo().device == LMS_DEV_NOVENA)
{
uint16_t regValue = SPI_read(0x0706) & 0xFFF8;
//lms_gpio2 - tx output selection:
// 0 - TX1_A and TX1_B (Band 1),
// 1 - TX2_A and TX2_B (Band 2)
regValue |= Get_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF)) << 2; //gpio2
//RX active paths
//lms_gpio0 | lms_gpio1 RX_A RX_B
// 0 0 => no active path
// 1 0 => LNAW_A LNAW_B
// 0 1 => LNAH_A LNAH_B
// 1 1 => LNAL_A LNAL_B
switch(Get_SPI_Reg_bits(LMS7param(SEL_PATH_RFE)))
{
//set gpio1:gpio0
case 0: regValue |= 0x0; break;
case 1: regValue |= 0x2; break;
case 2: regValue |= 0x3; break;
case 3: regValue |= 0x1; break;
}
SPI_write(0x0706, regValue);
}
return LIBLMS7_SUCCESS;
}
/** @brief Configures interfaces for desired frequency
Sets interpolation and decimation, changes MCLK sources and TSP clock dividers accordingly to selected interpolation and decimation
*/
liblms7_status LMS7002M::SetInterfaceFrequency(float_type cgen_freq_MHz, const uint8_t interpolation, const uint8_t decimation)
{
Modify_SPI_Reg_bits(LMS7param(HBD_OVR_RXTSP), decimation);
Modify_SPI_Reg_bits(LMS7param(HBI_OVR_TXTSP), interpolation);
liblms7_status status = SetFrequencyCGEN(cgen_freq_MHz);
if (status != LIBLMS7_SUCCESS)
return status;
if (decimation == 7 || decimation == 0) //bypass
{
Modify_SPI_Reg_bits(LMS7param(RXTSPCLKA_DIV), 0);
Modify_SPI_Reg_bits(LMS7param(RXDIVEN), false);
Modify_SPI_Reg_bits(LMS7param(MCLK2SRC), 3);
}
else
{
uint8_t divider = (uint8_t)pow(2.0, decimation);
if (divider > 1)
Modify_SPI_Reg_bits(LMS7param(RXTSPCLKA_DIV), (divider / 2) - 1);
else
Modify_SPI_Reg_bits(LMS7param(RXTSPCLKA_DIV), 0);
Modify_SPI_Reg_bits(LMS7param(RXDIVEN), true);
Modify_SPI_Reg_bits(LMS7param(MCLK2SRC), 1);
}
if (interpolation == 7 || interpolation == 0) //bypass
{
Modify_SPI_Reg_bits(LMS7param(TXTSPCLKA_DIV), 0);
Modify_SPI_Reg_bits(LMS7param(TXDIVEN), false);
Modify_SPI_Reg_bits(LMS7param(MCLK1SRC), 2);
}
else
{
uint8_t divider = (uint8_t)pow(2.0, interpolation);
if (divider > 1)
Modify_SPI_Reg_bits(LMS7param(TXTSPCLKA_DIV), (divider / 2) - 1);
else
Modify_SPI_Reg_bits(LMS7param(TXTSPCLKA_DIV), 0);
Modify_SPI_Reg_bits(LMS7param(TXDIVEN), true);
Modify_SPI_Reg_bits(LMS7param(MCLK1SRC), 0);
}
return status;
}
/**
@file LMS7002M.h
@author Lime Microsystems (www.limemicro.com)
@brief LMS7002M transceiver configuration interface
*/
#ifndef LMS7API_H
#define LMS7API_H
#include "LMS7002M_statuses.h"
#include "LMS7002M_parameters.h"
#include "typedefs.h"
#include <sstream>
class LMScomms;
class LMS7002M_RegistersMap;
class LMS7002M
{
public:
enum
{
Rx, Tx
};
LMS7002M();
LMS7002M(LMScomms* controlPort);
virtual ~LMS7002M();
///@name Registers writing and reading
liblms7_status UploadAll();
liblms7_status DownloadAll();
bool IsSynced();
liblms7_status ResetChip();
liblms7_status LoadConfig(const char* filename);
liblms7_status SaveConfig(const char* filename);
///@}
///@name Registers writing and reading
uint16_t Get_SPI_Reg_bits(const LMS7Parameter &param, bool fromChip = true);
uint16_t Get_SPI_Reg_bits(uint16_t address, uint8_t msb, uint8_t lsb, bool fromChip = true);
liblms7_status Modify_SPI_Reg_bits(const LMS7Parameter &param, const uint16_t value, bool fromChip = true);
liblms7_status Modify_SPI_Reg_bits(uint16_t address, uint8_t msb, uint8_t lsb, uint16_t value, bool fromChip = true);
liblms7_status SPI_write(uint16_t address, uint16_t data);
uint16_t SPI_read(uint16_t address, bool fromChip = true, liblms7_status *status = 0);
liblms7_status RegistersTest();
///@}
///@name Transmitter, Receiver calibrations
liblms7_status CalibrateRx(float_type bandwidth_MHz);
liblms7_status CalibrateTx(float_type bandwidth_MHz);
///@}
///@name Filters tuning
enum TxFilter
{
TX_LADDER, TX_REALPOLE, TX_HIGHBAND
};
enum RxFilter
{
RX_TIA, RX_LPF_LOWBAND, RX_LPF_HIGHBAND
};
liblms7_status TuneTxFilter(TxFilter filterType, float_type bandwidth_MHz);
liblms7_status TuneTxFilterLowBandChain(float_type ladder_bw_MHz, float_type realpole_bw_MHz);
liblms7_status TuneRxFilter(RxFilter filterType, float_type bandwidth_MHz);
///@}
///@name CGEN and PLL
float_type GetReferenceClk_SX(bool tx);
float_type GetFrequencyCGEN_MHz();
liblms7_status SetFrequencyCGEN(float_type freq_MHz);
float_type GetFrequencySX_MHz(bool tx, float_type refClk_MHz);
liblms7_status SetFrequencySX(bool tx, float_type freq_MHz, float_type refClk_MHz);
///VCO modules available for tuning
enum VCO_Module
{
VCO_CGEN, VCO_SXR, VCO_SXT
};
liblms7_status TuneVCO(VCO_Module module);
///@}
///@name TSP
liblms7_status LoadDC_REG_IQ(bool tx, int16_t I, int16_t Q);
liblms7_status SetNCOFrequency(bool tx, uint8_t index, float_type freq_MHz);
float_type GetNCOFrequency_MHz(bool tx, uint8_t index, float_type refClk_MHz, bool fromChip = true);
liblms7_status SetNCOPhaseOffsetForMode0(bool tx, float_type angle_Deg);
liblms7_status SetNCOPhaseOffset(bool tx, uint8_t index, float_type angle_Deg);
float_type GetNCOPhaseOffset_Deg(bool tx, uint8_t index);
liblms7_status SetGFIRCoefficients(bool tx, uint8_t GFIR_index, const int16_t *coef, uint8_t coefCount);
liblms7_status GetGFIRCoefficients(bool tx, uint8_t GFIR_index, int16_t *coef, uint8_t coefCount);
float_type GetReferenceClk_TSP_MHz(bool tx);
///@}
liblms7_status SetInterfaceFrequency(float_type cgen_freq_MHz, const uint8_t interpolation, const uint8_t decimation);
///enumeration to indicate module registers intervals
enum MemorySection
{
LimeLight = 0, EN_DIR, AFE, BIAS, XBUF, CGEN, LDO, BIST, CDS,
TRF, TBB, RFE, RBB, SX, TxTSP,
TxNCO, TxGFIR1, TxGFIR2, TxGFIR3a, TxGFIR3b, TxGFIR3c,
RxTSP, RxNCO, RxGFIR1, RxGFIR2, RxGFIR3a, RxGFIR3b, RxGFIR3c,
MEMORY_SECTIONS_COUNT
};
virtual liblms7_status SetDefaults(MemorySection module);
LMScomms* GetControlPort() const { return controlPort;};
static const float_type gLadder_lower_limit;
static const float_type gLadder_higher_limit;
static const float_type gRealpole_lower_limit;
static const float_type gRealpole_higher_limit;
static const float_type gHighband_lower_limit;
static const float_type gHighband_higher_limit;
static const float_type gRxTIA_higher_limit;
static const float_type gRxTIA_lower_limit_g1;
static const float_type gRxTIA_lower_limit_g23;
static const float_type gRxLPF_low_lower_limit;
static const float_type gRxLPF_low_higher_limit;
static const float_type gRxLPF_high_lower_limit;
static const float_type gRxLPF_high_higher_limit;
static float_type gVCO_frequency_table[3][2];
static float_type gCGEN_VCO_frequencies[2];
//protected:
LMS7002M_RegistersMap *mRegistersMap;
static const uint16_t readOnlyRegisters[];
static const uint16_t readOnlyRegistersMasks[];
uint16_t MemorySectionAddresses[MEMORY_SECTIONS_COUNT][2];
///@name Algorithms functions
void BackupAllRegisters();
void RestoreAllRegisters();
uint32_t GetRSSI();
void SetRxDCOFF(int8_t offsetI, int8_t offsetQ);
uint32_t FindMinRSSI_Gain(const LMS7Parameter &param, uint16_t *foundValue);
uint32_t FindMinRSSI(const LMS7Parameter &param, const int16_t startValue, int16_t *result, const uint8_t scanWidth, const uint8_t twoCompl, int8_t stepMult = 1);
uint32_t FindMinRSSI(const uint16_t addr, const uint8_t msb, const uint8_t lsb, const int16_t startValue, int16_t *result, const uint8_t scanWidth, const uint8_t twoCompl, int8_t stepMult = 1);
void CalibrateRxDC_RSSI();
liblms7_status CalibrateTxSetup(float_type bandwidth_MHz);
liblms7_status CalibrateRxSetup(float_type bandwidth_MHz);
liblms7_status FixRXSaturation();
void FilterTuning_AdjustGains();
liblms7_status TuneTxFilterSetup(TxFilter type, float_type cutoff_MHz);
liblms7_status TuneRxFilterSetup(RxFilter type, float_type cutoff_MHz);
liblms7_status RFE_TIA_Calibration(float_type TIA_freq_MHz);
liblms7_status RxLPFLow_Calibration(float_type RxLPFL_freq_MHz);
liblms7_status RxLPFHigh_Calibration(float_type RxLPFH_freq_MHz);
liblms7_status RegistersTestInterval(uint16_t startAddr, uint16_t endAddr, uint16_t pattern, std::stringstream &ss);
liblms7_status SPI_write_batch(const uint16_t* spiAddr, const uint16_t* spiData, uint16_t cnt);
liblms7_status SPI_read_batch(const uint16_t* spiAddr, uint16_t* spiData, uint16_t cnt);
liblms7_status Modify_SPI_Reg_mask(const uint16_t *addr, const uint16_t *masks, const uint16_t *values, uint8_t start, uint8_t stop);
///@}
///Reference clock used for Receiver frequency calculations
float_type mRefClkSXR_MHz;
///Reference clock used for Transmitter frequency calculations
float_type mRefClkSXT_MHz;
enum LogType
{
LOG_INFO,
LOG_WARNING,
LOG_ERROR,
LOG_DATA
};
virtual void Log(const char* text, LogType type);
///port used for communicating with LMS7002M
LMScomms* controlPort;
liblms7_status LoadConfigLegacyFile(const char* filename);
};
#endif
#include "LMS7002M_RegistersMap.h"
#include "LMS7002M_parameters.h"
LMS7002M_RegistersMap::LMS7002M_RegistersMap()
{
}
LMS7002M_RegistersMap::~LMS7002M_RegistersMap()
{
}
uint16_t LMS7002M_RegistersMap::GetDefaultValue(uint16_t address) const
{
std::map<uint16_t, Register>::const_iterator iter = mChannelA.find(address);
if( iter != mChannelA.end())
return iter->second.defaultValue;
else
return 0;
}
void LMS7002M_RegistersMap::InitializeDefaultValues(const std::vector<const LMS7Parameter*> parameterList)
{
for(auto parameter : parameterList)
{
uint16_t regValue = mChannelA[parameter->address].defaultValue;
mChannelA[parameter->address].defaultValue = regValue | (parameter->defaultValue << parameter->lsb);
mChannelA[parameter->address].value = mChannelA[parameter->address].defaultValue;
if(parameter->address >= 0x0100)
mChannelB[parameter->address].value = mChannelA[parameter->address].value;
}
}
void LMS7002M_RegistersMap::SetValue(uint8_t channel, const uint16_t address, const uint16_t value)
{
if(channel == 0)
mChannelA[address].value = value;
else if(channel == 1)
mChannelB[address].value = value;
}
uint16_t LMS7002M_RegistersMap::GetValue(uint8_t channel, uint16_t address) const
{
const std::map<const uint16_t, Register> *regMap;
if(channel == 0)
regMap = &mChannelA;
else if(channel == 1)
regMap = &mChannelB;
std::map<const uint16_t, Register>::const_iterator iter;
iter = regMap->find(address);
if (iter != regMap->end())
return iter->second.value;
else
return 0;
}
std::vector<uint16_t> LMS7002M_RegistersMap::GetUsedAddresses(const uint8_t channel) const
{
std::vector<uint16_t> addresses;
if(channel == 0)
for(auto iter : mChannelA)
addresses.push_back(iter.first);
else if(channel == 1)
for(auto iter : mChannelB)
addresses.push_back(iter.first);
return addresses;
}
#ifndef LMS7002M_REGISTERS_MAP_H
#define LMS7002M_REGISTERS_MAP_H
#include <vector>
#include <map>
#include <typedefs.h>
struct LMS7Parameter;
class LMS7002M_RegistersMap
{
public:
struct Register
{
uint16_t value;
uint16_t defaultValue;
uint16_t mask;
};
LMS7002M_RegistersMap();
~LMS7002M_RegistersMap();
uint16_t GetValue(uint8_t channel, uint16_t address) const;
void SetValue(uint8_t channel, const uint16_t address, const uint16_t value);
void InitializeDefaultValues(const std::vector<const LMS7Parameter*> parameterList);
uint16_t GetDefaultValue(uint16_t address) const;
std::vector<uint16_t> GetUsedAddresses(const uint8_t channel) const;
protected:
std::map<const uint16_t, Register> mChannelA;
std::map<const uint16_t, Register> mChannelB;
};
#endif
/**
@file LMS7002M_filtersCalibration.cpp
@author Lime Microsystems (www.limemicro.com)
@brief Implementation of LMS7002M transceiver filters calibration algorithms
*/
#include "LMS7002M.h"
#include <cmath>
///define for parameter enumeration if prefix might be needed
#define LMS7param(id) id
const float_type LMS7002M::gLadder_lower_limit = 2;
const float_type LMS7002M::gLadder_higher_limit = 16;
const float_type LMS7002M::gRealpole_lower_limit = 0.8;
const float_type LMS7002M::gRealpole_higher_limit = 3.2;
const float_type LMS7002M::gHighband_lower_limit = 28;
const float_type LMS7002M::gHighband_higher_limit = 70;
const float_type LMS7002M::gRxTIA_higher_limit = 60;
const float_type LMS7002M::gRxTIA_lower_limit_g1 = 1.5;
const float_type LMS7002M::gRxTIA_lower_limit_g23 = 0.5;
const float_type LMS7002M::gRxLPF_low_lower_limit = 1;
const float_type LMS7002M::gRxLPF_low_higher_limit = 20;
const float_type LMS7002M::gRxLPF_high_lower_limit = 20;
const float_type LMS7002M::gRxLPF_high_higher_limit = 70;
liblms7_status LMS7002M::TuneTxFilterSetup(LMS7002M::TxFilter type, float_type cutoff_MHz)
{
Modify_SPI_Reg_bits(LMS7param(EN_G_RFE), 0);
Modify_SPI_Reg_bits(LMS7param(EN_G_TRF), 0);
//RBB
SetDefaults(RBB);
Modify_SPI_Reg_bits(LMS7param(PD_LPFL_RBB), 1);
Modify_SPI_Reg_bits(LMS7param(INPUT_CTL_PGA_RBB), 3);
Modify_SPI_Reg_bits(LMS7param(ICT_PGA_OUT_RBB), 20);
Modify_SPI_Reg_bits(LMS7param(ICT_PGA_IN_RBB), 20);
Modify_SPI_Reg_bits(LMS7param(C_CTL_PGA_RBB), 3);
//TBB
SetDefaults(TBB);
Modify_SPI_Reg_bits(LMS7param(CG_IAMP_TBB), 1);
Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_FRP_TBB), 1);
Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_GG_FRP_TBB), 6);
//AFE
uint8_t isel_dac_afe = (uint8_t)Get_SPI_Reg_bits(0x0082, 15, 13);
SetDefaults(AFE);
if (Get_SPI_Reg_bits(LMS7param(MAC)) == 2)
{
Modify_SPI_Reg_bits(LMS7param(PD_TX_AFE2), 0); //PD_RX_AFE2 0
Modify_SPI_Reg_bits(LMS7param(PD_RX_AFE2), 0); //PD_RX_AFE2 0
}
Modify_SPI_Reg_bits(0x0082, 15, 13, isel_dac_afe);
//BIAS
uint8_t rpcalib_bias = (uint8_t)Get_SPI_Reg_bits(LMS7param(RP_CALIB_BIAS));
SetDefaults(BIAS);
Modify_SPI_Reg_bits(LMS7param(RP_CALIB_BIAS), rpcalib_bias);
//XBUF
Modify_SPI_Reg_bits(LMS7param(PD_XBUF_RX), 0);
Modify_SPI_Reg_bits(LMS7param(PD_XBUF_TX), 0);
Modify_SPI_Reg_bits(LMS7param(EN_G_XBUF), 1);
//CGEN
SetDefaults(CGEN);
//txtsp
SetDefaults(TxTSP);
Modify_SPI_Reg_bits(LMS7param(TSGMODE_TXTSP), 1);
Modify_SPI_Reg_bits(LMS7param(INSEL_TXTSP), 1);
Modify_SPI_Reg_bits(0x0208, 6, 4, 7);
LoadDC_REG_IQ(Tx, (int16_t)0x7FFF, (int16_t)0x8000);
float_type txNCOfreq = 0.05;
SetNCOFrequency(Tx, 0, txNCOfreq);
//rxtsp
SetDefaults(RxTSP);
SetNCOFrequency(Rx, 0, txNCOfreq - 1);
Modify_SPI_Reg_bits(LMS7param(AGC_MODE_RXTSP), 1);
Modify_SPI_Reg_bits(0x040C, 6, 3, 0x07);
Modify_SPI_Reg_bits(LMS7param(AGC_AVG_RXTSP), 7);
Modify_SPI_Reg_bits(LMS7param(CMIX_GAIN_RXTSP), 1);
return LIBLMS7_SUCCESS;
}
liblms7_status LMS7002M::TuneTxFilter(LMS7002M::TxFilter type, float_type cutoff_MHz)
{
liblms7_status status;
float_type lowLimit = 0;
float_type highLimit = 1000;
uint32_t rssi = 0;
int8_t dir;
uint8_t ccal_lpflad_tbb;
uint32_t rssi_value_100k;
int16_t rcal;
float_type ncoFreq = 0.05;
float_type cgenFreq;
uint8_t loopb_tbb;
uint8_t cg_iamp_tbb = 1;
uint8_t bypladder_tbb;
uint8_t pd_lpfh_tbb;
uint8_t pd_lpflad_tbb;
uint8_t pd_lpfs5;
uint8_t en_g_tbb = 1;
uint8_t pd_iamp_tbb = 0;
uint8_t tstin_tbb = 0;
BackupAllRegisters();
//float_type userCLKGENfreq = GetFrequencyCGEN_MHz();
status = TuneTxFilterSetup(type, cutoff_MHz);
if (status != LIBLMS7_SUCCESS)
goto TxFilterTuneEnd;
cgenFreq = cutoff_MHz * 20;
if (cgenFreq < 60)
cgenFreq = 60;
if (cgenFreq > 640)
cgenFreq = 640;
if (type == TX_LADDER)
{
loopb_tbb = 2;
bypladder_tbb = 0;
pd_lpfh_tbb = 1;
pd_lpflad_tbb = 0;
pd_lpfs5 = 1;
lowLimit = gLadder_lower_limit;
highLimit = gLadder_higher_limit;
}
else if (type == TX_REALPOLE)
{
loopb_tbb = 3;
bypladder_tbb = 1;
pd_lpfh_tbb = 1;
pd_lpflad_tbb = 1;
pd_lpfs5 = 0;
lowLimit = gRealpole_lower_limit;
highLimit = gRealpole_higher_limit;
}
else if (type == TX_HIGHBAND)
{
loopb_tbb = 3;
bypladder_tbb = 0;
pd_lpfh_tbb = 0;
pd_lpflad_tbb = 1;
pd_lpfs5 = 1;
lowLimit = gHighband_lower_limit;
highLimit = gHighband_higher_limit;
}
if (cutoff_MHz == cgenFreq / 16)
cgenFreq -= 10;
if (cutoff_MHz < lowLimit || cutoff_MHz > highLimit)
{
status = LIBLMS7_FREQUENCY_OUT_OF_RANGE;
goto TxFilterTuneEnd;
}
status = SetFrequencyCGEN(cgenFreq);
if (status != LIBLMS7_SUCCESS)
goto TxFilterTuneEnd;
Modify_SPI_Reg_bits(LMS7param(LOOPB_TBB), loopb_tbb);
Modify_SPI_Reg_bits(LMS7param(CG_IAMP_TBB), cg_iamp_tbb);
Modify_SPI_Reg_bits(LMS7param(BYPLADDER_TBB), bypladder_tbb);
Modify_SPI_Reg_bits(LMS7param(TSTIN_TBB), tstin_tbb);
Modify_SPI_Reg_bits(LMS7param(PD_LPFH_TBB), pd_lpfh_tbb);
Modify_SPI_Reg_bits(LMS7param(PD_LPFIAMP_TBB), pd_iamp_tbb);
Modify_SPI_Reg_bits(LMS7param(PD_LPFLAD_TBB), pd_lpflad_tbb);
Modify_SPI_Reg_bits(LMS7param(PD_LPFS5_TBB), pd_lpfs5);
Modify_SPI_Reg_bits(LMS7param(EN_G_TBB), en_g_tbb);
//B
//LADDER coefficients
float_type p1, p2, p3, p4, p5;
switch (type)
{
case TX_LADDER:
p1 = 1.29858903647958E-16;
p2 = -0.000110746929967704;
p3 = 0.00277593485991029;
p4 = 21.0384293169607;
p5 = -48.4092606238297;
break;
case TX_REALPOLE:
p1 = 1.93821841029921E-15;
p2 = -0.0429694461214244;
p3 = 0.253501254059498;
p4 = 88.9545445989649;
p5 = -48.0847491316861;
break;
case TX_HIGHBAND:
p1 = 1.10383E-06;
p2 = -0.0002108;
p3 = 0.019049487;
p4 = 1.433174459;
p5 = -47.69507793;
break;
}
rcal = (int16_t)(pow(cutoff_MHz, 4)*p1 + pow(cutoff_MHz, 3)*p2 + pow(cutoff_MHz, 2)*p3 + cutoff_MHz * p4 + p5);
if (rcal < 0)
rcal = 0;
if (rcal > 255)
rcal = 255;
if (type == TX_REALPOLE)
Modify_SPI_Reg_bits(LMS7param(RCAL_LPFS5_TBB), rcal);
else if (type == TX_LADDER)
Modify_SPI_Reg_bits(LMS7param(RCAL_LPFLAD_TBB), rcal);
else if (type == TX_HIGHBAND)
Modify_SPI_Reg_bits(LMS7param(RCAL_LPFH_TBB), rcal);
FilterTuning_AdjustGains();
rssi_value_100k = (uint32_t)( GetRSSI()*0.707 );
SetNCOFrequency(Tx, 0, cutoff_MHz);
SetNCOFrequency(Rx, 0, cutoff_MHz - 1);
for (ccal_lpflad_tbb = 31; ccal_lpflad_tbb > 0; --ccal_lpflad_tbb)
{
Modify_SPI_Reg_bits(LMS7param(CCAL_LPFLAD_TBB), ccal_lpflad_tbb);
rssi = GetRSSI();
if (rssi > rssi_value_100k && ccal_lpflad_tbb == 31)
break; //skip this search, continue to advanced search
if (rssi > rssi_value_100k)
{
status = LIBLMS7_SUCCESS;
goto TxFilterTuneEnd; //found correct value
}
}
//advanced search for c and r values
status = LIBLMS7_FAILURE;
dir = ccal_lpflad_tbb == 31 ? -1 : 1;
while (rcal > 0 && rcal < 255)
{
rcal += 5 * dir;
if (rcal < 0 && rcal > 255)
break;
if (type == TX_REALPOLE)
Modify_SPI_Reg_bits(LMS7param(RCAL_LPFS5_TBB), rcal);
else if (type == TX_LADDER)
Modify_SPI_Reg_bits(LMS7param(RCAL_LPFLAD_TBB), rcal);
else if (type == TX_HIGHBAND)
Modify_SPI_Reg_bits(LMS7param(RCAL_LPFH_TBB), rcal);
SetNCOFrequency(Tx, 0, ncoFreq);
SetNCOFrequency(Rx, 0, ncoFreq - 1);
Modify_SPI_Reg_bits(LMS7param(CCAL_LPFLAD_TBB), 16);
rssi_value_100k = GetRSSI();
SetNCOFrequency(Tx, 0, cutoff_MHz);
SetNCOFrequency(Rx, 0, cutoff_MHz - 1);
for (ccal_lpflad_tbb = 31; ccal_lpflad_tbb > 0; --ccal_lpflad_tbb)
{
Modify_SPI_Reg_bits(LMS7param(CCAL_LPFLAD_TBB), ccal_lpflad_tbb);
rssi = GetRSSI();
if (rssi > rssi_value_100k*0.707 && ccal_lpflad_tbb == 31)
break; //skip c search, need to change r value
if (rssi > rssi_value_100k*0.707)
{
status = LIBLMS7_SUCCESS;
goto TxFilterTuneEnd;
}
}
}
//end
TxFilterTuneEnd:
RestoreAllRegisters();
if (status != LIBLMS7_SUCCESS)
return status;
Modify_SPI_Reg_bits(LMS7param(CCAL_LPFLAD_TBB), ccal_lpflad_tbb);
Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_FRP_TBB), 1);
Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_GG_FRP_TBB), 6);
if (type == TX_REALPOLE)
Modify_SPI_Reg_bits(LMS7param(RCAL_LPFS5_TBB), rcal);
else if (type == TX_LADDER)
Modify_SPI_Reg_bits(LMS7param(RCAL_LPFLAD_TBB), rcal);
else if (type == TX_HIGHBAND)
{
Modify_SPI_Reg_bits(LMS7param(RCAL_LPFH_TBB), rcal);
Modify_SPI_Reg_bits(0x0105, 4, 0, 0x7); //set powerdowns
}
return LIBLMS7_SUCCESS;
}
void LMS7002M::FilterTuning_AdjustGains()
{
uint8_t cg_iamp_tbb;
uint32_t rssi = 0;
const uint32_t rssi_required = 0x8400;
uint8_t g_pga_rbb = (uint8_t)Get_SPI_Reg_bits(LMS7param(G_PGA_RBB));
while (g_pga_rbb < 31)
{
cg_iamp_tbb = 0;
while (cg_iamp_tbb < 63 && rssi < rssi_required)
{
Modify_SPI_Reg_bits(LMS7param(CG_IAMP_TBB), cg_iamp_tbb);
rssi = GetRSSI();
if (rssi > rssi_required)
return;
++cg_iamp_tbb;
}
g_pga_rbb += 6;
if (g_pga_rbb > 31)
g_pga_rbb = 31;
Modify_SPI_Reg_bits(LMS7param(G_PGA_RBB), g_pga_rbb);
}
}
liblms7_status LMS7002M::TuneTxFilterLowBandChain(float_type bandwidth, float_type realpole_MHz)
{
uint32_t rssi;
uint32_t rssi_value_10k;
bool prevRSSIbigger;
int16_t rcal;
float_type p1,p2,p3,p4,p5;
float_type ncoFreq = 0.05;
float_type cgenFreq;
BackupAllRegisters();
liblms7_status status = TuneTxFilter(TX_LADDER, bandwidth);
uint8_t ladder_c_value = (uint8_t)Get_SPI_Reg_bits(LMS7param(CCAL_LPFLAD_TBB));
uint8_t ladder_r_value = (uint8_t)Get_SPI_Reg_bits(LMS7param(RCAL_LPFLAD_TBB));
status = TuneTxFilterSetup(TX_LADDER, bandwidth);
if (bandwidth < gLadder_lower_limit || bandwidth > gLadder_higher_limit)
{
status = LIBLMS7_FREQUENCY_OUT_OF_RANGE;
goto TxFilterLowBandChainEnd;
}
//realpole calibration
//float userCLKGENfreq = GetFrequencyCGEN();
cgenFreq = realpole_MHz * 20;
if (cgenFreq < 60)
cgenFreq = 60;
if (cgenFreq > 640)
cgenFreq = 640;
if (realpole_MHz < gRealpole_lower_limit || realpole_MHz > gRealpole_higher_limit)
{
status = LIBLMS7_FREQUENCY_OUT_OF_RANGE;
goto TxFilterLowBandChainEnd;
}
status = SetFrequencyCGEN(cgenFreq);
if (status != LIBLMS7_SUCCESS)
goto TxFilterLowBandChainEnd;
Modify_SPI_Reg_bits(LMS7param(LOOPB_TBB), 3);
Modify_SPI_Reg_bits(LMS7param(CG_IAMP_TBB), 1);
Modify_SPI_Reg_bits(LMS7param(BYPLADDER_TBB), 1);
Modify_SPI_Reg_bits(LMS7param(TSTIN_TBB), 0);
Modify_SPI_Reg_bits(LMS7param(PD_LPFH_TBB), 1);
Modify_SPI_Reg_bits(LMS7param(PD_LPFIAMP_TBB), 0);
Modify_SPI_Reg_bits(LMS7param(PD_LPFLAD_TBB), 1);
Modify_SPI_Reg_bits(LMS7param(PD_LPFS5_TBB), 0);
Modify_SPI_Reg_bits(LMS7param(EN_G_TBB), 1);
//B
p1 = 1.93821841029921E-15;
p2 = -0.0429694461214244;
p3 = 0.253501254059498;
p4 = 88.9545445989649;
p5 = -48.0847491316861;
rcal = (int16_t)(pow(realpole_MHz, 4)*p1 + pow(realpole_MHz, 3)*p2 + pow(realpole_MHz, 2)*p3 + realpole_MHz * p4 + p5);
if (rcal < 0)
rcal = 0;
if (rcal > 255)
rcal = 255;
Modify_SPI_Reg_bits(LMS7param(RCAL_LPFS5_TBB), rcal);
FilterTuning_AdjustGains();
rssi_value_10k = GetRSSI();
SetNCOFrequency(Tx, 0, realpole_MHz);
SetNCOFrequency(Rx, 0, realpole_MHz - 1);
prevRSSIbigger = GetRSSI() > rssi_value_10k*0.707;
status = LIBLMS7_FAILURE; //assuming r value is not found
while (rcal >= 0 && rcal < 256)
{
Modify_SPI_Reg_bits(LMS7param(RCAL_LPFS5_TBB), rcal);
SetNCOFrequency(Tx, 0, ncoFreq);
SetNCOFrequency(Rx, 0, ncoFreq - 1);
rssi_value_10k = (uint32_t)( GetRSSI()*0.707 );
SetNCOFrequency(Tx, 0, realpole_MHz);
SetNCOFrequency(Rx, 0, realpole_MHz - 1);
rssi = GetRSSI();
if (rssi > rssi_value_10k)
--rcal;
else
{
if (prevRSSIbigger)
{
--rcal;
status = LIBLMS7_SUCCESS;
goto TxFilterLowBandChainEnd;
}
++rcal;
}
prevRSSIbigger = rssi > rssi_value_10k;
}
//end
TxFilterLowBandChainEnd:
RestoreAllRegisters();
if (status != LIBLMS7_SUCCESS)
return status;
Modify_SPI_Reg_bits(LMS7param(CCAL_LPFLAD_TBB), ladder_c_value);
Modify_SPI_Reg_bits(LMS7param(RCAL_LPFLAD_TBB), ladder_r_value);
Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_FRP_TBB), 1);
Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_GG_FRP_TBB), 6);
Modify_SPI_Reg_bits(LMS7param(RCAL_LPFS5_TBB), rcal);
Modify_SPI_Reg_bits(0x0105, 4, 0, 0x11); //set powerdowns
return LIBLMS7_SUCCESS;
}
liblms7_status LMS7002M::TuneRxFilter(RxFilter filter, float_type bandwidth_MHz)
{
liblms7_status status;
uint16_t cfb_tia_rfe;
uint16_t c_ctl_lpfl_rbb;
uint8_t ccomp_tia_rfe;
uint8_t rcomp_tia_rfe;
uint8_t c_ctl_lpfh_rbb;
uint8_t ict_pga_out;
uint8_t ict_pga_in;
uint8_t r_ctl_lpf_rbb;
uint8_t c_ctl_pga_rbb;
uint8_t rcc_ctl_lpfl_rbb;
uint8_t rcc_ctl_lpfh_rbb;
float_type lowerLimit;
float_type higherLimit;
if (filter == RX_TIA)
{
lowerLimit = Get_SPI_Reg_bits(LMS7param(G_TIA_RFE)) == 1 ? gRxTIA_lower_limit_g1 : gRxTIA_lower_limit_g23;
higherLimit = gRxTIA_higher_limit;
}
else if (filter == RX_LPF_LOWBAND)
{
lowerLimit = gRxLPF_low_lower_limit;
higherLimit = gRxLPF_low_higher_limit;
}
else if (filter == RX_LPF_HIGHBAND)
{
lowerLimit = gRxLPF_high_lower_limit;
higherLimit = gRxLPF_high_higher_limit;
}
if (bandwidth_MHz < lowerLimit || bandwidth_MHz > higherLimit)
return LIBLMS7_FREQUENCY_OUT_OF_RANGE;
BackupAllRegisters();
status = TuneRxFilterSetup(filter, bandwidth_MHz);
if (status != LIBLMS7_SUCCESS)
goto RxFilterTuneEnd;
if (filter == RX_TIA)
status = RFE_TIA_Calibration(bandwidth_MHz);
else if (filter == RX_LPF_LOWBAND)
status = RxLPFLow_Calibration(bandwidth_MHz);
else if (filter == RX_LPF_HIGHBAND)
status = RxLPFHigh_Calibration(bandwidth_MHz);
cfb_tia_rfe = Get_SPI_Reg_bits(LMS7param(CFB_TIA_RFE));
c_ctl_lpfl_rbb = Get_SPI_Reg_bits(LMS7param(C_CTL_LPFL_RBB));
ccomp_tia_rfe = (int8_t)Get_SPI_Reg_bits(LMS7param(CCOMP_TIA_RFE));
rcomp_tia_rfe = (int8_t)Get_SPI_Reg_bits(LMS7param(RCOMP_TIA_RFE));
c_ctl_lpfh_rbb = (int8_t)Get_SPI_Reg_bits(LMS7param(C_CTL_LPFH_RBB));
ict_pga_out = (int8_t)Get_SPI_Reg_bits(LMS7param(ICT_PGA_OUT_RBB));
ict_pga_in = (int8_t)Get_SPI_Reg_bits(LMS7param(ICT_PGA_IN_RBB));
r_ctl_lpf_rbb = (int8_t)Get_SPI_Reg_bits(LMS7param(R_CTL_LPF_RBB));
c_ctl_pga_rbb = (int8_t)Get_SPI_Reg_bits(LMS7param(C_CTL_PGA_RBB));
rcc_ctl_lpfl_rbb = (int8_t)Get_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB));
rcc_ctl_lpfh_rbb = (int8_t)Get_SPI_Reg_bits(LMS7param(RCC_CTL_LPFH_RBB));
RxFilterTuneEnd:
RestoreAllRegisters();
if (status != LIBLMS7_SUCCESS)
return status;
if (filter == RX_TIA)
{
Modify_SPI_Reg_bits(LMS7param(ICT_TIAMAIN_RFE), 2);
Modify_SPI_Reg_bits(LMS7param(ICT_TIAOUT_RFE), 2);
Modify_SPI_Reg_bits(LMS7param(RFB_TIA_RFE), 16);
Modify_SPI_Reg_bits(LMS7param(CFB_TIA_RFE), cfb_tia_rfe);
Modify_SPI_Reg_bits(LMS7param(CCOMP_TIA_RFE), ccomp_tia_rfe);
Modify_SPI_Reg_bits(LMS7param(RCOMP_TIA_RFE), rcomp_tia_rfe);
Modify_SPI_Reg_bits(0x010c, 1, 0, 0x1);
}
else if (filter == RX_LPF_LOWBAND)
{
Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), rcc_ctl_lpfl_rbb);
Modify_SPI_Reg_bits(LMS7param(C_CTL_LPFL_RBB), c_ctl_lpfl_rbb);
Modify_SPI_Reg_bits(LMS7param(ICT_PGA_OUT_RBB), ict_pga_out);
Modify_SPI_Reg_bits(LMS7param(ICT_PGA_IN_RBB), ict_pga_in);
Modify_SPI_Reg_bits(LMS7param(R_CTL_LPF_RBB), r_ctl_lpf_rbb);
Modify_SPI_Reg_bits(LMS7param(C_CTL_PGA_RBB), c_ctl_pga_rbb);
Modify_SPI_Reg_bits(0x0115, 3, 0, 0x9);
Modify_SPI_Reg_bits(0x0118, 15, 13, 0x1);
}
else if (filter == RX_LPF_HIGHBAND)
{
Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFH_RBB), rcc_ctl_lpfh_rbb);
Modify_SPI_Reg_bits(LMS7param(C_CTL_LPFH_RBB), c_ctl_lpfh_rbb);
Modify_SPI_Reg_bits(LMS7param(ICT_PGA_OUT_RBB), ict_pga_out);
Modify_SPI_Reg_bits(LMS7param(ICT_PGA_IN_RBB), ict_pga_in);
Modify_SPI_Reg_bits(LMS7param(R_CTL_LPF_RBB), r_ctl_lpf_rbb);
Modify_SPI_Reg_bits(LMS7param(C_CTL_PGA_RBB), c_ctl_pga_rbb);
Modify_SPI_Reg_bits(0x0115, 3, 0, 0x5);
Modify_SPI_Reg_bits(0x0118, 15, 13, 0x0);
}
return LIBLMS7_SUCCESS;
}
liblms7_status LMS7002M::TuneRxFilterSetup(RxFilter type, float_type cutoff_MHz)
{
liblms7_status status;
uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC));
//RFE
uint8_t g_tia_rfe = (uint8_t)Get_SPI_Reg_bits(LMS7param(G_TIA_RFE));
SetDefaults(RFE);
Modify_SPI_Reg_bits(LMS7param(SEL_PATH_RFE), 2);
if (ch == 2)
Modify_SPI_Reg_bits(LMS7param(EN_NEXTRX_RFE), 1);
else
Modify_SPI_Reg_bits(LMS7param(EN_NEXTRX_RFE), 0);
Modify_SPI_Reg_bits(LMS7param(G_RXLOOPB_RFE), 8);
Modify_SPI_Reg_bits(LMS7param(PD_RLOOPB_2_RFE), 0);
Modify_SPI_Reg_bits(LMS7param(EN_INSHSW_LB2_RFE), 0);
Modify_SPI_Reg_bits(LMS7param(PD_MXLOBUF_RFE), 0);
Modify_SPI_Reg_bits(LMS7param(PD_QGEN_RFE), 0);
Modify_SPI_Reg_bits(LMS7param(ICT_TIAMAIN_RFE), 2);
Modify_SPI_Reg_bits(LMS7param(ICT_TIAOUT_RFE), 2);
Modify_SPI_Reg_bits(LMS7param(RFB_TIA_RFE), 16);
Modify_SPI_Reg_bits(LMS7param(G_TIA_RFE), g_tia_rfe);
//RBB
SetDefaults(RBB);
Modify_SPI_Reg_bits(LMS7param(ICT_PGA_OUT_RBB), 20);
Modify_SPI_Reg_bits(LMS7param(ICT_PGA_IN_RBB), 20);
Modify_SPI_Reg_bits(LMS7param(C_CTL_PGA_RBB), 3);
//TRF
SetDefaults(TRF);
Modify_SPI_Reg_bits(LMS7param(L_LOOPB_TXPAD_TRF), 0);
Modify_SPI_Reg_bits(LMS7param(EN_LOOPB_TXPAD_TRF), 1);
if (ch == 2)
Modify_SPI_Reg_bits(LMS7param(EN_NEXTTX_TRF), 1);
else
Modify_SPI_Reg_bits(LMS7param(EN_NEXTTX_TRF), 0);
Modify_SPI_Reg_bits(LMS7param(SEL_BAND1_TRF), 0);
Modify_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF), 1);
//TBB
SetDefaults(TBB);
Modify_SPI_Reg_bits(LMS7param(CG_IAMP_TBB), 1);
Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_FRP_TBB), 1);
Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_GG_FRP_TBB), 6);
//AFE
SetDefaults(AFE);
if (ch == 2)
{
Modify_SPI_Reg_bits(LMS7param(PD_TX_AFE2), 0);
Modify_SPI_Reg_bits(LMS7param(PD_RX_AFE2), 0);
}
//BIAS
uint8_t rp_calib_bias = (uint8_t)Get_SPI_Reg_bits(LMS7param(RP_CALIB_BIAS));
SetDefaults(BIAS);
Modify_SPI_Reg_bits(LMS7param(RP_CALIB_BIAS), rp_calib_bias);
//XBUF
Modify_SPI_Reg_bits(LMS7param(PD_XBUF_RX), 0);
Modify_SPI_Reg_bits(LMS7param(PD_XBUF_TX), 0);
Modify_SPI_Reg_bits(LMS7param(EN_G_TRF), 1);
//CLKGEN
SetDefaults(CGEN);
//SXR
Modify_SPI_Reg_bits(LMS7param(MAC), 1);
SetDefaults(SX);
status = SetFrequencySX(Rx, 499.95, mRefClkSXR_MHz);
if (status != LIBLMS7_SUCCESS)
return status;
Modify_SPI_Reg_bits(LMS7param(PD_VCO), 0);
//SXT
Modify_SPI_Reg_bits(LMS7param(MAC), 2);
SetDefaults(SX);
status = SetFrequencySX(Tx, 500, mRefClkSXT_MHz);
if (status != LIBLMS7_SUCCESS)
return status;
Modify_SPI_Reg_bits(LMS7param(PD_VCO), 0);
Modify_SPI_Reg_bits(LMS7param(MAC), ch);
//TxTSP
SetDefaults(TxTSP);
Modify_SPI_Reg_bits(LMS7param(TSGMODE_TXTSP), 1);
Modify_SPI_Reg_bits(LMS7param(INSEL_TXTSP), 1);
Modify_SPI_Reg_bits(0x0208, 8, 8, 1);
Modify_SPI_Reg_bits(0x0208, 6, 4, 0x7);
LoadDC_REG_IQ(Tx, (int16_t)0x7FFF, (int16_t)0x8000);
SetNCOFrequency(Tx, 0, 0);
//RxTSP
SetDefaults(RxTSP);
Modify_SPI_Reg_bits(LMS7param(AGC_MODE_RXTSP), 1);
Modify_SPI_Reg_bits(0x040C, 5, 3, 0x7);
Modify_SPI_Reg_bits(LMS7param(AGC_AVG_RXTSP), 7);
Modify_SPI_Reg_bits(LMS7param(CMIX_GAIN_RXTSP), 1);
float_type sxtfreq = GetFrequencySX_MHz(Tx, mRefClkSXT_MHz);
float_type sxrfreq = GetFrequencySX_MHz(Rx, mRefClkSXR_MHz);
SetNCOFrequency(Rx, 0, sxtfreq - sxrfreq - 1);
return LIBLMS7_SUCCESS;
}
liblms7_status LMS7002M::RFE_TIA_Calibration(float_type TIA_freq_MHz)
{
liblms7_status status;
bool prevRSSIbigger;
uint8_t ccomp_tia_rfe_value;
int16_t rcomp_tia_rfe;
float_type cgenFreq = TIA_freq_MHz * 20;
uint32_t rssi;
uint32_t rssi_value_50k;
//RFE
uint8_t g_tia_rfe = (uint8_t)Get_SPI_Reg_bits(LMS7param(G_TIA_RFE));
int16_t cfb_tia_rfe_value;
if (g_tia_rfe == 1)
cfb_tia_rfe_value = (uint16_t)(5400 / TIA_freq_MHz - 15);
else if (g_tia_rfe > 1)
cfb_tia_rfe_value = (uint16_t)(1680 / TIA_freq_MHz - 10);
else
return LIBLMS7_FAILURE;
Modify_SPI_Reg_bits(LMS7param(CFB_TIA_RFE), cfb_tia_rfe_value);
if (g_tia_rfe == 1)
ccomp_tia_rfe_value = (uint8_t)(cfb_tia_rfe_value / 100 + 1);
else if (g_tia_rfe > 1)
ccomp_tia_rfe_value = (uint8_t)(cfb_tia_rfe_value / 100);
else
return LIBLMS7_FAILURE;
if (ccomp_tia_rfe_value > 15)
ccomp_tia_rfe_value = 15;
Modify_SPI_Reg_bits(LMS7param(CCOMP_TIA_RFE), ccomp_tia_rfe_value);
rcomp_tia_rfe = (int16_t)(15 - cfb_tia_rfe_value * 2 / 100);
if (rcomp_tia_rfe < 0)
rcomp_tia_rfe = 0;
Modify_SPI_Reg_bits(LMS7param(RCOMP_TIA_RFE), rcomp_tia_rfe);
//RBB
Modify_SPI_Reg_bits(LMS7param(INPUT_CTL_PGA_RBB), 2);
Modify_SPI_Reg_bits(LMS7param(PD_LPFL_RBB), 1);
//CLKGEN
if (cgenFreq < 60)
cgenFreq = 60;
if (cgenFreq > 640)
cgenFreq = 640;
if (cgenFreq / 16 == TIA_freq_MHz)
status = SetFrequencyCGEN(cgenFreq - 10);
else
status = SetFrequencyCGEN(cgenFreq);
if (status != LIBLMS7_SUCCESS)
return status;
FilterTuning_AdjustGains();
rssi_value_50k = (uint32_t)( GetRSSI() * 0.707 );
status = SetFrequencySX(Rx, GetFrequencySX_MHz(Tx, mRefClkSXT_MHz) - TIA_freq_MHz, mRefClkSXR_MHz);
if (status != LIBLMS7_SUCCESS)
return status;
SetNCOFrequency(Rx, 0, GetFrequencySX_MHz(Tx, mRefClkSXT_MHz) - GetFrequencySX_MHz(Rx, mRefClkSXR_MHz) - 1);
prevRSSIbigger = GetRSSI() > rssi_value_50k;
while (cfb_tia_rfe_value >= 0 && cfb_tia_rfe_value < 4096)
{
Modify_SPI_Reg_bits(LMS7param(CFB_TIA_RFE), cfb_tia_rfe_value);
rssi = GetRSSI();
if (rssi > rssi_value_50k)
++cfb_tia_rfe_value;
else
{
--cfb_tia_rfe_value;
if (prevRSSIbigger)
return LIBLMS7_SUCCESS; //found correct value
}
prevRSSIbigger = rssi > rssi_value_50k;
}
return LIBLMS7_FAILURE;
}
liblms7_status LMS7002M::RxLPFLow_Calibration(float_type RxLPFL_freq_MHz)
{
liblms7_status status;
uint32_t rssi;
uint32_t rssi_value_50k;
int32_t c_ctl_lpfl_rbb;
bool prevRSSIbigger;
float_type cgenFreq_MHz = RxLPFL_freq_MHz * 20;
//RFE
Modify_SPI_Reg_bits(LMS7param(CFB_TIA_RFE), 15);
Modify_SPI_Reg_bits(LMS7param(CCOMP_TIA_RFE), 1);
Modify_SPI_Reg_bits(LMS7param(RCOMP_TIA_RFE), 15);
Modify_SPI_Reg_bits(LMS7param(G_TIA_RFE), 1);
//RBB
c_ctl_lpfl_rbb = (int32_t)(2160 / RxLPFL_freq_MHz - 103);
if (c_ctl_lpfl_rbb < 0)
c_ctl_lpfl_rbb = 0;
if (c_ctl_lpfl_rbb > 2047)
c_ctl_lpfl_rbb = 2047;
Modify_SPI_Reg_bits(LMS7param(C_CTL_LPFL_RBB), c_ctl_lpfl_rbb);
if (RxLPFL_freq_MHz >= 15)
Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), 5);
else if (RxLPFL_freq_MHz >= 10)
Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), 4);
else if (RxLPFL_freq_MHz >= 5)
Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), 3);
else if (RxLPFL_freq_MHz >= 3)
Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), 2);
else if (RxLPFL_freq_MHz >= 1.4)
Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), 1);
else
Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), 0);
//CLKGEN
if (cgenFreq_MHz < 60)
cgenFreq_MHz = 60;
if (cgenFreq_MHz > 640)
cgenFreq_MHz = 640;
if (cgenFreq_MHz / 16 == RxLPFL_freq_MHz)
status = SetFrequencyCGEN(cgenFreq_MHz - 10);
else
status = SetFrequencyCGEN(cgenFreq_MHz);
if (status != LIBLMS7_SUCCESS)
return status;
FilterTuning_AdjustGains();
rssi_value_50k = (uint32_t)( GetRSSI() * 0.707 );
status = SetFrequencySX(Rx, GetFrequencySX_MHz(Tx, mRefClkSXT_MHz) - RxLPFL_freq_MHz, mRefClkSXR_MHz);
if (status != LIBLMS7_SUCCESS)
return status;
SetNCOFrequency(Rx, 0, GetFrequencySX_MHz(Tx, mRefClkSXT_MHz) - GetFrequencySX_MHz(Rx, mRefClkSXR_MHz) - 1);
prevRSSIbigger = GetRSSI() > rssi_value_50k;
while (c_ctl_lpfl_rbb >= 0 && c_ctl_lpfl_rbb < 2048)
{
Modify_SPI_Reg_bits(LMS7param(C_CTL_LPFL_RBB), c_ctl_lpfl_rbb);
rssi = GetRSSI();
if (rssi > rssi_value_50k)
++c_ctl_lpfl_rbb;
else
{
--c_ctl_lpfl_rbb;
if (prevRSSIbigger)
return LIBLMS7_SUCCESS; //found correct value
}
prevRSSIbigger = rssi > rssi_value_50k;
}
return LIBLMS7_FAILURE;
}
liblms7_status LMS7002M::RxLPFHigh_Calibration(float_type RxLPFH_freq_MHz)
{
liblms7_status status;
int16_t c_ctl_lpfh_rbb;
int16_t rcc_ctl_lpfh_rbb;
float_type cgenFreq = RxLPFH_freq_MHz * 20;
uint32_t rssi;
uint32_t rssi_value_50k;
bool prevRSSIbigger;
//RFE
Modify_SPI_Reg_bits(LMS7param(CFB_TIA_RFE), 15);
Modify_SPI_Reg_bits(LMS7param(CCOMP_TIA_RFE), 1);
Modify_SPI_Reg_bits(LMS7param(RCOMP_TIA_RFE), 15);
Modify_SPI_Reg_bits(LMS7param(G_TIA_RFE), 1);
//RBB
c_ctl_lpfh_rbb = (int16_t)(6000 / RxLPFH_freq_MHz - 50);
if (c_ctl_lpfh_rbb < 0)
c_ctl_lpfh_rbb = 0;
if (c_ctl_lpfh_rbb > 255)
c_ctl_lpfh_rbb = 255;
Modify_SPI_Reg_bits(LMS7param(C_CTL_LPFH_RBB), c_ctl_lpfh_rbb);
rcc_ctl_lpfh_rbb = (int16_t)(RxLPFH_freq_MHz / 10 - 3);
if (rcc_ctl_lpfh_rbb < 0)
rcc_ctl_lpfh_rbb = 0;
Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFH_RBB), rcc_ctl_lpfh_rbb);
Modify_SPI_Reg_bits(LMS7param(INPUT_CTL_PGA_RBB), 1);
Modify_SPI_Reg_bits(LMS7param(PD_LPFL_RBB), 1);
Modify_SPI_Reg_bits(LMS7param(PD_LPFH_RBB), 0);
//CLKGEN
if (cgenFreq < 60)
cgenFreq = 60;
if (cgenFreq > 640)
cgenFreq = 640;
if (cgenFreq / 16 == RxLPFH_freq_MHz)
status = SetFrequencyCGEN(cgenFreq - 10);
else
status = SetFrequencyCGEN(cgenFreq);
if (status != LIBLMS7_SUCCESS)
return status;
FilterTuning_AdjustGains();
rssi_value_50k = (uint32_t)( GetRSSI() * 0.707);
status = SetFrequencySX(Rx, GetFrequencySX_MHz(Tx, mRefClkSXT_MHz) - RxLPFH_freq_MHz, mRefClkSXR_MHz);
if (status != LIBLMS7_SUCCESS)
return status;
SetNCOFrequency(Rx, 0, GetFrequencySX_MHz(Tx, mRefClkSXT_MHz) - GetFrequencySX_MHz(Rx, mRefClkSXR_MHz) - 1);
prevRSSIbigger = GetRSSI() > rssi_value_50k;
while (c_ctl_lpfh_rbb >= 0 && c_ctl_lpfh_rbb < 256)
{
Modify_SPI_Reg_bits(LMS7param(C_CTL_LPFH_RBB), c_ctl_lpfh_rbb);
rssi = GetRSSI();
if (rssi > rssi_value_50k)
++c_ctl_lpfh_rbb;
else
{
--c_ctl_lpfh_rbb;
if (prevRSSIbigger)
return LIBLMS7_SUCCESS; //found correct value
}
prevRSSIbigger = rssi > rssi_value_50k;
}
return LIBLMS7_FAILURE;
}
/**
@file LMS7002M_parameters.cpp
@author Lime Microsystems (www.limemicro.com)
@brief Definition of LMS7002M transceiver control parameters registers
*/
#include "LMS7002M_parameters.h"
std::vector<const LMS7Parameter*> LMS7parameterList;
const struct LMS7Parameter LRST_TX_B = { 0x0020, 15, 15, 1, "LRST_TX_B", "Resets all the logic registers to the default state for Tx MIMO channel B" };
const struct LMS7Parameter MRST_TX_B = { 0x0020, 14, 14, 1, "MRST_TX_B", "Resets all the configuration memory to the default state for Tx MIMO channel B" };
const struct LMS7Parameter LRST_TX_A = { 0x0020, 13, 13, 1, "LRST_TX_A", "Resets all the logic registers to the default state for Tx MIMO channel A" };
const struct LMS7Parameter MRST_TX_A = { 0x0020, 12, 12, 1, "MRST_TX_A", "Resets all the configuration memory to the default state for Tx MIMO channel A" };
const struct LMS7Parameter LRST_RX_B = { 0x0020, 11, 11, 1, "LRST_RX_B", "Resets all the logic registers to the default state for Rx MIMO channel B" };
const struct LMS7Parameter MRST_RX_B = { 0x0020, 10, 10, 1, "MRST_RX_B", "Resets all the configuration memory to the default state for Rx MIMO channel B" };
const struct LMS7Parameter LRST_RX_A = { 0x0020, 9, 9, 1, "LRST_RX_A", "Resets all the logic registers to the default state for Rx MIMO channel A" };
const struct LMS7Parameter MRST_RX_A = { 0x0020, 8, 8, 1, "MRST_RX_A", "Resets all the configuration memory to the default state for Rx MIMO channel A" };
const struct LMS7Parameter SRST_RXFIFO = { 0x0020, 7, 7, 1, "SRST_RXFIFO", "RX FIFO soft reset (LimeLight Interface)" };
const struct LMS7Parameter SRST_TXFIFO = { 0x0020, 6, 6, 1, "SRST_TXFIFO", "TX FIFO soft reset (LimeLight Interface)" };
const struct LMS7Parameter RXEN_B = { 0x0020, 5, 5, 1, "RXEN_B", "Power control for Rx MIMO channel B" };
const struct LMS7Parameter RXEN_A = { 0x0020, 4, 4, 1, "RXEN_A", "Power control for Rx MIMO channel A" };
const struct LMS7Parameter TXEN_B = { 0x0020, 3, 3, 1, "TXEN_B", "Power control for Tx MIMO channel B" };
const struct LMS7Parameter TXEN_A = { 0x0020, 2, 2, 1, "TXEN_A", "Power control for Tx MIMO channel A" };
const struct LMS7Parameter MAC = { 0x0020, 1, 0, 3, "MAC", "Selects MIMO channel for communication" };
const struct LMS7Parameter TX_CLK_PE = { 0x0021, 11, 11, 1, "TX_CLK_PE", "Pull up control of TX_CLK pad" };
const struct LMS7Parameter RX_CLK_PE = { 0x0021, 10, 10, 1, "RX_CLK_PE", "Pull up control of RX_CLK pad" };
const struct LMS7Parameter SDA_PE = { 0x0021, 9, 9, 1, "SDA_PE", "Pull up control of SDA pad" };
const struct LMS7Parameter SDA_DS = { 0x0021, 8, 8, 0, "SDA_DS", "Driver strength of SDA pad" };
const struct LMS7Parameter SCL_PE = { 0x0021, 7, 7, 1, "SCL_PE", "Pull up control of SCL pad" };
const struct LMS7Parameter SCL_DS = { 0x0021, 6, 6, 0, "SCL_DS", "Driver strength of SCL pad" };
const struct LMS7Parameter SDIO_DS = { 0x0021, 5, 5, 0, "SDIO_DS", "Driver strength of SDIO pad" };
const struct LMS7Parameter SDIO_PE = { 0x0021, 4, 4, 1, "SDIO_PE", "Pull up control of SDIO pad" };
const struct LMS7Parameter SDO_PE = { 0x0021, 3, 3, 1, "SDO_PE", "Pull up control of SDO pad" };
const struct LMS7Parameter SCLK_PE = { 0x0021, 2, 2, 1, "SCLK_PE", "Pull up control of SCLK pad" };
const struct LMS7Parameter SEN_PE = { 0x0021, 1, 1, 1, "SEN_PE", "Pull up control of SEN pad" };
const struct LMS7Parameter SPIMODE = { 0x0021, 0, 0, 1, "SPIMODE", "SPI communication mode" };
const struct LMS7Parameter DIQ2_DS = { 0x0022, 11, 11, 0, "DIQ2_DS", "Driver strength of DIQ2 pad" };
const struct LMS7Parameter DIQ2_PE = { 0x0022, 10, 10, 1, "DIQ2_PE", "Pull up control of DIQ2 pad" };
const struct LMS7Parameter IQ_SEL_EN_2_PE = { 0x0022, 9, 9, 1, "IQ_SEL_EN_2_PE", "Pull up control of IQ_SEL_EN_2 pad" };
const struct LMS7Parameter TXNRX2_PE = { 0x0022, 8, 8, 1, "TXNRX2_PE", "Pull up control of TXNRX2 pad" };
const struct LMS7Parameter FCLK2_PE = { 0x0022, 7, 7, 1, "FCLK2_PE", "Pull up control of FCLK2 pad" };
const struct LMS7Parameter MCLK2_PE = { 0x0022, 6, 6, 1, "MCLK2_PE", "Pull up control of MCLK2 pad" };
const struct LMS7Parameter DIQ1_DS = { 0x0022, 5, 5, 0, "DIQ1_DS", "Pull up control of MCLK2 pad" };
const struct LMS7Parameter DIQ1_PE = { 0x0022, 4, 4, 1, "DIQ1_PE", "Pull up control of DIQ1 pad" };
const struct LMS7Parameter IQ_SEL_EN_1_PE = { 0x0022, 3, 3, 1, "IQ_SEL_EN_1_PE", "Pull up control of IQ_SEL_EN_1 pad" };
const struct LMS7Parameter TXNRX1_PE = { 0x0022, 2, 2, 1, "TXNRX1_PE", "Pull up control of TXNRX1 pad" };
const struct LMS7Parameter FCLK1_PE = { 0x0022, 1, 1, 1, "FCLK1_PE", "Pull up control of FCLK1 pad" };
const struct LMS7Parameter MCLK1_PE = { 0x0022, 0, 0, 1, "MCLK1_PE", "Pull up control of MCLK1 pad" };
const struct LMS7Parameter DIQDIRCTR2 = { 0x0023, 15, 15, 0, "DIQDIRCTR2", "DIQ2 direction control mode" };
const struct LMS7Parameter DIQDIR2 = { 0x0023, 14, 14, 1, "DIQDIR2", "DIQ2 direction" };
const struct LMS7Parameter DIQDIRCTR1 = { 0x0023, 13, 13, 0, "DIQDIRCTR1", "DIQ1 direction control mode" };
const struct LMS7Parameter DIQDIR1 = { 0x0023, 12, 12, 1, "DIQDIR1", "DIQ1 direction" };
const struct LMS7Parameter ENABLEDIRCTR2 = { 0x0023, 11, 11, 0, "ENABLEDIRCTR2", "ENABLE2 direction control mode" };
const struct LMS7Parameter ENABLEDIR2 = { 0x0023, 10, 10, 1, "ENABLEDIR2", "ENABLE2 direction" };
const struct LMS7Parameter ENABLEDIRCTR1 = { 0x0023, 9, 9, 0, "ENABLEDIRCTR1", "ENABLE1 direction control mode" };
const struct LMS7Parameter ENABLEDIR1 = { 0x0023, 8, 8, 1, "ENABLEDIR1", "ENABLE1 direction." };
const struct LMS7Parameter MOD_EN = { 0x0023, 6, 6, 1, "MOD_EN", "LimeLight interface enable" };
const struct LMS7Parameter LML2_FIDM = { 0x0023, 5, 5, 0, "LML2_FIDM", "Frame start ID selection for Port 2 when LML_MODE2 = 0" };
const struct LMS7Parameter LML2_TXNRXIQ = { 0x0023, 4, 4, 1, "LML2_TXNRXIQ", "TXIQ/RXIQ mode selection for Port 2 when LML_MODE2 = 0" };
const struct LMS7Parameter LML2_MODE = { 0x0023, 3, 3, 1, "LML2_MODE", "Mode of LimeLight Port 2" };
const struct LMS7Parameter LML1_FIDM = { 0x0023, 2, 2, 0, "LML1_FIDM", "Frame start ID selection for Port 1 when LML_MODE1 = 0" };
const struct LMS7Parameter LML1_TXNRXIQ = { 0x0023, 1, 1, 0, "LML1_TXNRXIQ", "TXIQ/RXIQ mode selection for Port 1 when LML_MODE1 = 0" };
const struct LMS7Parameter LML1_MODE = { 0x0023, 0, 0, 1, "LML1_MODE", "Mode of LimeLight Port 1" };
const struct LMS7Parameter LML1_S3S = { 0x0024, 15, 14, 3, "LML1_S3S", "Sample source in position 3, when Port 1 is RF2BB" };
const struct LMS7Parameter LML1_S2S = { 0x0024, 13, 12, 2, "LML1_S2S", "Sample source in position 2, when Port 1 is RF2BB" };
const struct LMS7Parameter LML1_S1S = { 0x0024, 11, 10, 1, "LML1_S1S", "Sample source in position 1, when Port 1 is RF2BB" };
const struct LMS7Parameter LML1_S0S = { 0x0024, 9, 8, 0, "LML1_S0S", "Sample source in position 0, when Port 1 is RF2BB" };
const struct LMS7Parameter LML1_BQP = { 0x0024, 7, 6, 3, "LML1_BQP", "BQ sample position in frame, when Port 1 is BB2RF" };
const struct LMS7Parameter LML1_BIP = { 0x0024, 5, 4, 2, "LML1_BIP", "BI sample position in frame, when Port 1 is BB2RF" };
const struct LMS7Parameter LML1_AQP = { 0x0024, 3, 2, 1, "LML1_AQP", "AQ sample position in frame, when Port 1 is BB2RF" };
const struct LMS7Parameter LML1_AIP = { 0x0024, 1, 0, 0, "LML1_AIP", "AI sample position in frame, when Port 1 is BB2RF" };
const struct LMS7Parameter LML1_BB2RF_PST = { 0x0025, 15, 8, 1, "LML1_BB2RF_PST", "Number of clock cycles to wait before data drive stop after burst stop is detected in JESD207 mode on Port 1 and Port 1 BB2RF" };
const struct LMS7Parameter LML1_BB2RF_PRE = { 0x0025, 7, 0, 1, "LML1_BB2RF_PRE", "Number of clock cycles to wait before data drive start after burst start is detected in JESD207 mode on Port 1 and Port 1 BB2RF" };
const struct LMS7Parameter LML1_RF2BB_PST = { 0x0026, 15, 8, 1, "LML1_RF2BB_PST", "Number of clock cycles to wait before data capture stop after burst stop is detected in JESD207 mode on Port 1 and Port 1 is RF2BB" };
const struct LMS7Parameter LML1_RF2BB_PRE = { 0x0026, 7, 0, 1, "LML1_RF2BB_PRE", "Number of clock cycles to wait before data capture start after burst start is detected in JESD207 mode on Port 1 and Port 1 RF2BB" };
const struct LMS7Parameter LML2_S3S = { 0x0027, 15, 14, 3, "LML2_S3S", "Sample source in position 3, when Port 2 is RF2BB" };
const struct LMS7Parameter LML2_S2S = { 0x0027, 13, 12, 2, "LML2_S2S", "Sample source in position 2, when Port 2 is RF2BB" };
const struct LMS7Parameter LML2_S1S = { 0x0027, 11, 10, 1, "LML2_S1S", "Sample source in position 1, when Port 2 is RF2BB" };
const struct LMS7Parameter LML2_S0S = { 0x0027, 9, 8, 0, "LML2_S0S", "Sample source in position 0, when Port 2 is RF2BB" };
const struct LMS7Parameter LML2_BQP = { 0x0027, 7, 6, 3, "LML2_BQP", "BQ sample position in frame, when Port 2 is BB2RF" };
const struct LMS7Parameter LML2_BIP = { 0x0027, 5, 4, 2, "LML2_BIP", "BI sample position in frame, when Port 2 is BB2RF" };
const struct LMS7Parameter LML2_AQP = { 0x0027, 3, 2, 1, "LML2_AQP", "AQ sample position in frame, when Port 2 is BB2RF" };
const struct LMS7Parameter LML2_AIP = { 0x0027, 1, 0, 0, "LML2_AIP", "AI sample position in frame, when Port 2 is BB2RF" };
const struct LMS7Parameter LML2_BB2RF_PST = { 0x0028, 15, 8, 1, "LML2_BB2RF_PST", "Number of clock cycles to wait before data drive stop after burst stop is detected in JESD207 mode on Port 2 and Port 2 BB2RF" };
const struct LMS7Parameter LML2_BB2RF_PRE = { 0x0028, 7, 0, 1, "LML2_BB2RF_PRE", "Number of clock cycles to wait before data drive start after burst start is detected in JESD207 mode on Port 2 and Port 2 BB2RF" };
const struct LMS7Parameter LML2_RF2BB_PST = { 0x0029, 15, 8, 1, "LML2_RF2BB_PST", "Number of clock cycles to wait before data capture stop after burst stop is detected in JESD207 mode on Port 2 and Port 2 RF2BB" };
const struct LMS7Parameter LML2_RF2BB_PRE = { 0x0029, 7, 0, 1, "LML2_RF2BB_PRE", "Number of clock cycles to wait before data capture start after burst start is detected in JESD207 mode on Port 2 and Port 2 RF2BB" };
const struct LMS7Parameter FCLK2_DLY = { 0x002A, 15, 14, 0, "FCLK2_DLY", "" };
const struct LMS7Parameter FCLK1_DLY = { 0x002A, 13, 12, 0, "FCLK1_DLY", "" };
const struct LMS7Parameter RX_MUX = { 0x002A, 11, 10, 0, "RX_MUX", "RxFIFO data source selection" };
const struct LMS7Parameter TX_MUX = { 0x002A, 9, 8, 0, "TX_MUX", "Port selection for data transmit to TSP" };
const struct LMS7Parameter TXRDCLK_MUX = { 0x002A, 7, 6, 2, "TXRDCLK_MUX", "TX FIFO read clock selection" };
const struct LMS7Parameter TXWRCLK_MUX = { 0x002A, 5, 4, 0, "TXWRCLK_MUX", "TX FIFO write clock selection" };
const struct LMS7Parameter RXRDCLK_MUX = { 0x002A, 3, 2, 1, "RXRDCLK_MUX", "RX FIFO read clock selection" };
const struct LMS7Parameter RXWRCLK_MUX = { 0x002A, 1, 0, 2, "RXWRCLK_MUX", "RX FIFO write clock selection" };
const struct LMS7Parameter FCLK2_INV = { 0x002B, 15, 15, 0, "FCLK2_INV", "FCLK2 clock inversion" };
const struct LMS7Parameter FCLK1_INV = { 0x002B, 14, 14, 0, "FCLK1_INV", "FCLK1 clock inversion" };
const struct LMS7Parameter MCLK2DLY = { 0x002B, 13, 12, 0, "MCLK2DLY", "MCLK2 clock internal delay" };
const struct LMS7Parameter MCLK1DLY = { 0x002B, 11, 10, 0, "MCLK1DLY", "MCLK1 clock internal delay" };
const struct LMS7Parameter MCLK2SRC = { 0x002B, 5, 4, 1, "MCLK2SRC", "MCLK2 clock source" };
const struct LMS7Parameter MCLK1SRC = { 0x002B, 3, 2, 0, "MCLK1SRC", "MCLK1 clock source" };
const struct LMS7Parameter TXDIVEN = { 0x002B, 1, 1, 0, "TXDIVEN", "TX clock divider enable" };
const struct LMS7Parameter RXDIVEN = { 0x002B, 0, 0, 0, "RXDIVEN", "RX clock divider enable" };
const struct LMS7Parameter TXTSPCLKA_DIV = { 0x002C, 15, 8, 255, "TXTSPCLKA_DIV", "TxTSP clock divider, used to produce MCLK(1/2). Clock division ratio is 2(TXTSPCLKA_DIV + 1)"};
const struct LMS7Parameter RXTSPCLKA_DIV = { 0x002C, 7, 0, 255, "RXTSPCLKA_DIV", "RxTSP clock divider, used to produce MCLK(1/2). Clock division ratio is 2(RXTSPCLKA_DIV + 1)"};
const struct LMS7Parameter MIMO_SISO = { 0x002E, 15, 15, 0, "MIMO_SISO", "MIMO channel B enable control" };
const struct LMS7Parameter VER = { 0x002F, 15, 11, 7, "VER", "" };
const struct LMS7Parameter REV = { 0x002F, 10, 6, 1, "REV", "" };
const struct LMS7Parameter MASK = { 0x002F, 5, 0, 0, "MASK", "" };
const struct LMS7Parameter EN_DIR_LDO = { 0x0081, 3, 3, 0, "EN_DIR_LDO", "" };
const struct LMS7Parameter EN_DIR_CGEN = { 0x0081, 2, 2, 0, "EN_DIR_CGEN", "" };
const struct LMS7Parameter EN_DIR_XBUF = { 0x0081, 1, 1, 0, "EN_DIR_XBUF", "" };
const struct LMS7Parameter EN_DIR_AFE = { 0x0081, 0, 0, 0, "EN_DIR_AFE", "" };
const struct LMS7Parameter ISEL_DAC_AFE = { 0x0082, 15, 13, 4, "ISEL_DAC_AFE", "Controls the peak current of the DAC output current" };
const struct LMS7Parameter MODE_INTERLEAVE_AFE = { 0x0082, 12, 12, 0, "MODE_INTERLEAVE_AFE", "time interleaves the two ADCs into one ADC" };
const struct LMS7Parameter MUX_AFE_1 = { 0x0082, 11, 10, 0, "MUX_AFE_1", "Controls the MUX at the input of the ADC channel 1" };
const struct LMS7Parameter MUX_AFE_2 = { 0x0082, 9, 8, 0, "MUX_AFE_2", "Controls the MUX at the input of the ADC channel 2" };
const struct LMS7Parameter PD_AFE = { 0x0082, 5, 5, 0, "PD_AFE", "Power down control for the AFE current mirror in BIAS_TOP" };
const struct LMS7Parameter PD_RX_AFE1 = { 0x0082, 4, 4, 0, "PD_RX_AFE1", "Power down control for the ADC of channel 1" };
const struct LMS7Parameter PD_RX_AFE2 = { 0x0082, 3, 3, 1, "PD_RX_AFE2", "Power down control for the ADC of channel 2" };
const struct LMS7Parameter PD_TX_AFE1 = { 0x0082, 2, 2, 0, "PD_TX_AFE1", "Power down control for the DAC of channel 1" };
const struct LMS7Parameter PD_TX_AFE2 = { 0x0082, 1, 1, 1, "PD_TX_AFE2", "Power down control for the DAC of channel 2" };
const struct LMS7Parameter EN_G_AFE = { 0x0082, 0, 0, 1, "EN_G_AFE", "Enable control for all the AFE power downs" };
const struct LMS7Parameter MUX_BIAS_OUT = { 0x0084, 12, 11, 0, "MUX_BIAS_OUT", "Test mode of the BIAS_TOP" };
const struct LMS7Parameter RP_CALIB_BIAS = { 0x0084, 10, 6, 16, "RP_CALIB_BIAS", "Calibration code for rppolywo. This code is set by the calibration algorithm: BIAS_RPPOLY_calibration" };
const struct LMS7Parameter PD_FRP_BIAS = { 0x0084, 4, 4, 0, "PD_FRP_BIAS", "Power down signal for Fix/RP block" };
const struct LMS7Parameter PD_F_BIAS = { 0x0084, 3, 3, 0, "PD_F_BIAS", "Power down signal for Fix" };
const struct LMS7Parameter PD_PTRP_BIAS = { 0x0084, 2, 2, 0, "PD_PTRP_BIAS", "Power down signal for PTAT/RP block" };
const struct LMS7Parameter PD_PT_BIAS = { 0x0084, 1, 1, 0, "PD_PT_BIAS", "Power down signal for PTAT block" };
const struct LMS7Parameter PD_BIAS_MASTER = { 0x0084, 0, 0, 0, "PD_BIAS_MASTER", "Enable signal for central bias block" };
const struct LMS7Parameter SLFB_XBUF_RX = { 0x0085, 8, 8, 0, "SLFB_XBUF_RX", "Self biasing digital contol SLFB_XBUF_RX" };
const struct LMS7Parameter SLFB_XBUF_TX = { 0x0085, 7, 7, 0, "SLFB_XBUF_TX", "Self biasing digital contol SLFB_XBUF_TX" };
const struct LMS7Parameter BYP_XBUF_RX = { 0x0085, 6, 6, 0, "BYP_XBUF_RX", "Shorts the Input 3.3V buffer in XBUF" };
const struct LMS7Parameter BYP_XBUF_TX = { 0x0085, 5, 5, 0, "BYP_XBUF_TX", "Shorts the Input 3.3V buffer in XBUF" };
const struct LMS7Parameter EN_OUT2_XBUF_TX = { 0x0085, 4, 4, 0, "EN_OUT2_XBUF_TX", "Enables the 2nd output of TX XBUF. This 2nd buffer goes to XBUF_RX. This should be active when only 1 XBUF is to be used" };
const struct LMS7Parameter EN_TBUFIN_XBUF_RX = { 0x0085, 3, 3, 0, "EN_TBUFIN_XBUF_RX", "Disables the input from the external XOSC and buffers the 2nd input signal (from TX XBUF 2nd output) to the RX. This should be active when only 1 XBUF is to be used" };
const struct LMS7Parameter PD_XBUF_RX = { 0x0085, 2, 2, 0, "PD_XBUF_RX", "Power down signal PD_XBUF_RX" };
const struct LMS7Parameter PD_XBUF_TX = { 0x0085, 1, 1, 0, "PD_XBUF_TX", "Power down signal PD_XBUF_TX" };
const struct LMS7Parameter EN_G_XBUF = { 0x0085, 0, 0, 1, "EN_G_XBUF", "Enable control for all the XBUF power downs" };
const struct LMS7Parameter SPDUP_VCO_CGEN = { 0x0086, 15, 15, 0, "SPDUP_VCO_CGEN", "Bypasses the noise filter resistor for fast setlling time. It should be connected to a 1us pulse" };
const struct LMS7Parameter RESET_N_CGEN = { 0x0086, 14, 14, 1, "RESET_N_CGEN", "A pulse should be used in the start-up to reset ( 1-normal operation)" };
const struct LMS7Parameter EN_ADCCLKH_CLKGN = { 0x0086, 11, 11, 1, "EN_ADCCLKH_CLKGN", "Selects if F_CLKH or F_CLKL is connected to FCLK_ADC" };
const struct LMS7Parameter EN_COARSE_CKLGEN = { 0x0086, 10, 10, 0, "EN_COARSE_CKLGEN", "Enable signal for coarse tuning block" };
const struct LMS7Parameter EN_INTONLY_SDM_CGEN = { 0x0086, 9, 9, 0, "EN_INTONLY_SDM_CGEN", "Enables INTEGER-N mode of the SX " };
const struct LMS7Parameter EN_SDM_CLK_CGEN = { 0x0086, 8, 8, 1, "EN_SDM_CLK_CGEN", "Enables/Disables SDM clock. In INT-N mode or for noise testing, SDM clock can be disabled" };
const struct LMS7Parameter PD_CP_CGEN = { 0x0086, 6, 6, 0, "PD_CP_CGEN", "Power down for Charge Pump" };
const struct LMS7Parameter PD_FDIV_FB_CGEN = { 0x0086, 5, 5, 0, "PD_FDIV_FB_CGEN", "Power down for feedback frequency divider" };
const struct LMS7Parameter PD_FDIV_O_CGEN = { 0x0086, 4, 4, 0, "PD_FDIV_O_CGEN", "Power down for forward frequency divider of the CGEN block" };
const struct LMS7Parameter PD_SDM_CGEN = { 0x0086, 3, 3, 0, "PD_SDM_CGEN", "Power down for SDM" };
const struct LMS7Parameter PD_VCO_CGEN = { 0x0086, 2, 2, 0, "PD_VCO_CGEN", "Power down for VCO" };
const struct LMS7Parameter PD_VCO_COMP_CGEN = { 0x0086, 1, 1, 0, "PD_VCO_COMP_CGEN", "Power down for VCO comparator" };
const struct LMS7Parameter EN_G_CGEN = { 0x0086, 0, 0, 1, "EN_G_CGEN", "Enable control for all the CGEN power downs" };
const struct LMS7Parameter FRAC_SDM_CGEN_LSB = { 0x0087, 15, 0, 0x0400, "FRAC_SDM_CGEN_LSB", "" };
const struct LMS7Parameter INT_SDM_CGEN = { 0x0088, 13, 4, 120, "INT_SDM_CGEN", "" };
const struct LMS7Parameter FRAC_SDM_CGEN_MSB = { 0x0088, 3, 0, 0, "FRAC_SDM_CGEN_MSB", "" };
const struct LMS7Parameter REV_SDMCLK_CGEN = { 0x0089, 15, 15, 0, "REV_SDMCLK_CGEN", "Reverses the SDM clock" };
const struct LMS7Parameter SEL_SDMCLK_CGEN = { 0x0089, 14, 14, 0, "SEL_SDMCLK_CGEN", "Selects between the feedback divider output and Fref for SDM" };
const struct LMS7Parameter SX_DITHER_EN_CGEN = { 0x0089, 13, 13, 0, "SX_DITHER_EN_CGEN", "Enabled dithering in SDM" };
const struct LMS7Parameter CLKH_OV_CLKL_CGEN = { 0x0089, 12, 11, 0, "CLKH_OV_CLKL_CGEN", "FCLKL here is ADC clock. FCLKH is the clock to the DAC and if no division is added to the ADC as well" };
const struct LMS7Parameter DIV_OUTCH_CGEN = { 0x0089, 10, 3, 4, "DIV_OUTCH_CGEN", "" };
const struct LMS7Parameter TST_CGEN = { 0x0089, 2, 0, 0, "TST_CGEN",
"Controls the test mode of the SX\n\
0 - TST disabled; RSSI analog outputs enabled if RSSI blocks active and when all PLL test signals are off\n\
1 - tstdo[0] = ADC clock; tstdo[1] = DAC clock; tstao = High impedance;\n\
2 - tstdo[0] = SDM clock; tstdo[1] = feedback divider output; tstao = VCO tune through a 60kOhm resistor;\n\
3 - tstdo[0] = Reference clock; tstdo[1] = feedback divider output; tstao = VCO tune through a 10kOhm resistor;\n\
4 - tstdo[0] = High impedance; tstdo[1] = High impedance; tstao = High impedance;\n\
5 - tstdo[0] = Charge pump Down signal; tstdo[1] = Charge pump Up signal; tstao = High impedance;\n\
6 - tstdo[0] = High impedance; tstdo[1] = High impedance; tstao = VCO tune through a 60kOhm resistor;\n\
7 - tstdo[0] = High impedance; tstdo[1] = High impedance; tstao = VCO tune through a 10kOhm resistor;\n\
if TST_SX[2] = 1 --> VCO_TSTBUF active generating VCO_TST_DIV20 and VCO_TST_DIV40"};
const struct LMS7Parameter REV_CLKDAC_CGEN = { 0x008A, 14, 14, 0, "REV_CLKDAC_CGEN", "Inverts the clock F_CLKL" };
const struct LMS7Parameter CMPLO_CTRL_CGEN = { 0x008A, 27, 14, 0, "CMPLO_CTRL_CGEN", "" };
const struct LMS7Parameter REV_CLKADC_CGEN = { 0x008A, 13, 13, 0, "REV_CLKADC_CGEN", "Inverts the clock F_CLKL" };
const struct LMS7Parameter REVPH_PFD_CGEN = { 0x008A, 12, 12, 0, "REVPH_PFD_CGEN", "Reverse the pulses of PFD. It can be used to reverse the polarity of the PLL loop (positive feedback to negative feedback)" };
const struct LMS7Parameter IOFFSET_CP_CGEN = { 0x008A, 11, 6, 20, "IOFFSET_CP_CGEN", "Scales the offset current of the charge pump, 0-->63. This current is used in Fran-N mode to create an offset in the CP response and avoide the non-linear section" };
const struct LMS7Parameter IPULSE_CP_CGEN = { 0x008A, 5, 0, 20, "IPULSE_CP_CGEN", "Scales the pulse current of the charge pump" };
const struct LMS7Parameter ICT_VCO_CGEN = { 0x008B, 13, 9, 16, "ICT_VCO_CGEN", "Scales the VCO bias current from 0 to 2.5xInom" };
const struct LMS7Parameter CSW_VCO_CGEN = { 0x008B, 8, 1, 128, "CSW_VCO_CGEN", "" };
const struct LMS7Parameter COARSE_START_CGEN = { 0x008B, 0, 0, 0, "COARSE_START_CGEN", "Control signal for coarse tuning algorithm (SX_SWC_calibration)" };
const struct LMS7Parameter COARSE_STEPDONE_CGEN = { 0x008C, 15, 15, 0, "COARSE_STEPDONE_CGEN", "" };
const struct LMS7Parameter COARSEPLL_COMPO_CGEN = { 0x008C, 14, 14, 0, "COARSEPLL_COMPO_CGEN", "" };
const struct LMS7Parameter VCO_CMPHO_CGEN = { 0x008C, 13, 13, 0, "VCO_CMPHO_CGEN", "" };
const struct LMS7Parameter VCO_CMPLO_CGEN = { 0x008C, 12, 12, 0, "VCO_CMPLO_CGEN", "" };
const struct LMS7Parameter CP2_CGEN = { 0x008C, 11, 8, 6, "CP2_CGEN", "Controls the value of CP2 (cap from CP output to GND) in the PLL filter" };
const struct LMS7Parameter CP3_CGEN = { 0x008C, 7, 4, 7, "CP3_CGEN", "Controls the value of CP3 (cap from VCO Vtune input to GND) in the PLL filter" };
const struct LMS7Parameter CZ_CGEN = { 0x008C, 3, 0, 11, "CZ_CGEN", "Controls the value of CZ (Zero capacitor) in the PLL filter" };
const struct LMS7Parameter EN_LDO_DIG = { 0x0092, 15, 15, 0, "EN_LDO_DIG", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_DIGGN = { 0x0092, 14, 14, 0, "EN_LDO_DIGGN", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_DIGSXR = { 0x0092, 13, 13, 0, "EN_LDO_DIGSXR", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_DIGSXT = { 0x0092, 12, 12, 0, "EN_LDO_DIGSXT", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_DIVGN = { 0x0092, 11, 11, 0, "EN_LDO_DIVGN", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_DIVSXR = { 0x0092, 10, 10, 0, "EN_LDO_DIVSXR", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_DIVSXT = { 0x0092, 9, 9, 0, "EN_LDO_DIVSXT", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_LNA12 = { 0x0092, 8, 8, 0, "EN_LDO_LNA12", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_LNA14 = { 0x0092, 7, 7, 0, "EN_LDO_LNA14", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_MXRFE = { 0x0092, 6, 6, 0, "EN_LDO_MXRFE", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_RBB = { 0x0092, 5, 5, 0, "EN_LDO_RBB", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_RXBUF = { 0x0092, 4, 4, 0, "EN_LDO_RXBUF", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_TBB = { 0x0092, 3, 3, 0, "EN_LDO_TBB", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_TIA12 = { 0x0092, 2, 2, 0, "EN_LDO_TIA12", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_TIA14 = { 0x0092, 1, 1, 0, "EN_LDO_TIA14", "Enables the LDO" };
const struct LMS7Parameter EN_G_LDO = { 0x0092, 0, 0, 1, "EN_G_LDO", "Enable control for all the LDO power downs" };
const struct LMS7Parameter EN_LOADIMP_LDO_TLOB = { 0x0093, 15, 15, 0, "EN_LOADIMP_LDO_TLOB", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_TPAD = { 0x0093, 14, 14, 0, "EN_LOADIMP_LDO_TPAD", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_TXBUF = { 0x0093, 13, 13, 0, "EN_LOADIMP_LDO_TXBUF", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_VCOGN = { 0x0093, 12, 12, 0, "EN_LOADIMP_LDO_VCOGN", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_VCOSXR = { 0x0093, 11, 11, 0, "EN_LOADIMP_LDO_VCOSXR", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_VCOSXT = { 0x0093, 10, 10, 0, "EN_LOADIMP_LDO_VCOSXT", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LDO_AFE = { 0x0093, 9, 9, 0, "EN_LDO_AFE", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_CPGN = { 0x0093, 8, 8, 0, "EN_LDO_CPGN", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_CPSXR = { 0x0093, 7, 7, 0, "EN_LDO_CPSXR", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_TLOB = { 0x0093, 6, 6, 0, "EN_LDO_TLOB", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_TPAD = { 0x0093, 5, 5, 0, "EN_LDO_TPAD", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_TXBUF = { 0x0093, 4, 4, 0, "EN_LDO_TXBUF", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_VCOGN = { 0x0093, 3, 3, 0, "EN_LDO_VCOGN", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_VCOSXR = { 0x0093, 2, 2, 0, "EN_LDO_VCOSXR", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_VCOSXT = { 0x0093, 1, 1, 0, "EN_LDO_VCOSXT", "Enables the LDO" };
const struct LMS7Parameter EN_LDO_CPSXT = { 0x0093, 0, 0, 0, "EN_LDO_CPSXT", "Enables the LDO" };
const struct LMS7Parameter EN_LOADIMP_LDO_CPSXT = { 0x0094, 15, 15, 0, "EN_LOADIMP_LDO_CPSXT", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_DIG = { 0x0094, 14, 14, 0, "EN_LOADIMP_LDO_DIG", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_DIGGN = { 0x0094, 13, 13, 0, "EN_LOADIMP_LDO_DIGGN", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_DIGSXR = { 0x0094, 12, 12, 0, "EN_LOADIMP_LDO_DIGSXR", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_DIGSXT = { 0x0094, 11, 11, 0, "EN_LOADIMP_LDO_DIGSXT", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_DIVGN = { 0x0094, 10, 10, 0, "EN_LOADIMP_LDO_DIVGN", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_DIVSXR = { 0x0094, 9, 9, 0, "EN_LOADIMP_LDO_DIVSXR", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_DIVSXT = { 0x0094, 8, 8, 0, "EN_LOADIMP_LDO_DIVSXT", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_LNA12 = { 0x0094, 7, 7, 0, "EN_LOADIMP_LDO_LNA12", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_LNA14 = { 0x0094, 6, 6, 0, "EN_LOADIMP_LDO_LNA14", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_MXRFE = { 0x0094, 5, 5, 0, "EN_LOADIMP_LDO_MXRFE", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_RBB = { 0x0094, 4, 4, 0, "EN_LOADIMP_LDO_RBB", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_RXBUF = { 0x0094, 3, 3, 0, "EN_LOADIMP_LDO_RXBUF", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_TBB = { 0x0094, 2, 2, 0, "EN_LOADIMP_LDO_TBB", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_TIA12 = { 0x0094, 1, 1, 0, "EN_LOADIMP_LDO_TIA12", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_TIA14 = { 0x0094, 0, 0, 0, "EN_LOADIMP_LDO_TIA14", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter BYP_LDO_TBB = { 0x0095, 15, 15, 0, "BYP_LDO_TBB", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_TIA12 = { 0x0095, 14, 14, 0, "BYP_LDO_TIA12", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_TIA14 = { 0x0095, 13, 13, 0, "BYP_LDO_TIA14", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_TLOB = { 0x0095, 12, 12, 0, "BYP_LDO_TLOB", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_TPAD = { 0x0095, 11, 11, 0, "BYP_LDO_TPAD", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_TXBUF = { 0x0095, 10, 10, 0, "BYP_LDO_TXBUF", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_VCOGN = { 0x0095, 9, 9, 0, "BYP_LDO_VCOGN", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_VCOSXR = { 0x0095, 8, 8, 0, "BYP_LDO_VCOSXR", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_VCOSXT = { 0x0095, 7, 7, 0, "BYP_LDO_VCOSXT", "Bypass signal for the LDO" };
const struct LMS7Parameter EN_LOADIMP_LDO_AFE = { 0x0095, 2, 2, 0, "EN_LOADIMP_LDO_AFE", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_CPGN = { 0x0095, 1, 1, 0, "EN_LOADIMP_LDO_CPGN", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_CPSXR = { 0x0095, 0, 0, 0, "EN_LOADIMP_LDO_CPSXR", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter BYP_LDO_AFE = { 0x0096, 15, 15, 0, "BYP_LDO_AFE", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_CPGN = { 0x0096, 14, 14, 0, "BYP_LDO_CPGN", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_CPSXR = { 0x0096, 13, 13, 0, "BYP_LDO_CPSXR", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_CPSXT = { 0x0096, 12, 12, 0, "BYP_LDO_CPSXT", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_DIG = { 0x0096, 11, 11, 0, "BYP_LDO_DIG", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_DIGGN = { 0x0096, 10, 10, 0, "BYP_LDO_DIGGN", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_DIGSXR = { 0x0096, 9, 9, 0, "BYP_LDO_DIGSXR", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_DIGSXT = { 0x0096, 8, 8, 0, "BYP_LDO_DIGSXT", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_DIVGN = { 0x0096, 7, 7, 0, "BYP_LDO_DIVGN", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_DIVSXR = { 0x0096, 6, 6, 0, "BYP_LDO_DIVSXR", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_DIVSXT = { 0x0096, 5, 5, 0, "BYP_LDO_DIVSXT", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_LNA12 = { 0x0096, 4, 4, 0, "BYP_LDO_LNA12", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_LNA14 = { 0x0096, 3, 3, 0, "BYP_LDO_LNA14", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_MXRFE = { 0x0096, 2, 2, 0, "BYP_LDO_MXRFE", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_RBB = { 0x0096, 1, 1, 0, "BYP_LDO_RBB", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_RXBUF = { 0x0096, 0, 0, 0, "BYP_LDO_RXBUF", "Bypass signal for the LDO" };
const struct LMS7Parameter SPDUP_LDO_DIVSXR = { 0x0097, 15, 15, 0, "SPDUP_LDO_DIVSXR", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_DIVSXT = { 0x0097, 14, 14, 0, "SPDUP_LDO_DIVSXT", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_LNA12 = { 0x0097, 13, 13, 0, "SPDUP_LDO_LNA12", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_LNA14 = { 0x0097, 12, 12, 0, "SPDUP_LDO_LNA14", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_MXRFE = { 0x0097, 11, 11, 0, "SPDUP_LDO_MXRFE", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_RBB = { 0x0097, 10, 10, 0, "SPDUP_LDO_RBB", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_RXBUF = { 0x0097, 9, 9, 0, "SPDUP_LDO_RXBUF", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_TBB = { 0x0097, 8, 8, 0, "SPDUP_LDO_TBB", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_TIA12 = { 0x0097, 7, 7, 0, "SPDUP_LDO_TIA12", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_TIA14 = { 0x0097, 6, 6, 0, "SPDUP_LDO_TIA14", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_TLOB = { 0x0097, 5, 5, 0, "SPDUP_LDO_TLOB", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_TPAD = { 0x0097, 4, 4, 0, "SPDUP_LDO_TPAD", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_TXBUF = { 0x0097, 3, 3, 0, "SPDUP_LDO_TXBUF", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_VCOGN = { 0x0097, 2, 2, 0, "SPDUP_LDO_VCOGN", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_VCOSXR = { 0x0097, 1, 1, 0, "SPDUP_LDO_VCOSXR", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_VCOSXT = { 0x0097, 0, 0, 0, "SPDUP_LDO_VCOSXT", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_AFE = { 0x0098, 8, 8, 0, "SPDUP_LDO_AFE", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_CPGN = { 0x0098, 7, 7, 0, "SPDUP_LDO_CPGN", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_CPSXR = { 0x0098, 6, 6, 0, "SPDUP_LDO_CPSXR", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_CPSXT = { 0x0098, 5, 5, 0, "SPDUP_LDO_CPSXT", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_DIG = { 0x0098, 4, 4, 0, "SPDUP_LDO_DIG", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_DIGGN = { 0x0098, 3, 3, 0, "SPDUP_LDO_DIGGN", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_DIGSXR = { 0x0098, 2, 2, 0, "SPDUP_LDO_DIGSXR", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_DIGSXT = { 0x0098, 1, 1, 0, "SPDUP_LDO_DIGSXT", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_DIVGN = { 0x0098, 0, 0, 0, "SPDUP_LDO_DIVGN", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter RDIV_VCOSXR = { 0x0099, 15, 8, 101, "RDIV_VCOSXR", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_VCOSXT = { 0x0099, 7, 0, 101, "RDIV_VCOSXT", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_TXBUF = { 0x009A, 15, 8, 101, "RDIV_TXBUF", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_VCOGN = { 0x009A, 7, 0, 140, "RDIV_VCOGN", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_TLOB = { 0x009B, 15, 8, 101, "RDIV_TLOB", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_TPAD = { 0x009B, 7, 0, 101, "RDIV_TPAD", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_TIA12 = { 0x009C, 15, 8, 101, "RDIV_TIA12", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_TIA14 = { 0x009C, 7, 0, 140, "RDIV_TIA14", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_RXBUF = { 0x009D, 15, 8, 101, "RDIV_RXBUF", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_TBB = { 0x009D, 7, 0, 101, "RDIV_TBB", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_MXRFE = { 0x009E, 15, 8, 101, "RDIV_MXRFE", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_RBB = { 0x009E, 7, 0, 140, "RDIV_RBB", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_LNA12 = { 0x009F, 15, 8, 101, "RDIV_LNA12", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_LNA14 = { 0x009F, 7, 0, 140, "RDIV_LNA14", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_DIVSXR = { 0x00A0, 15, 8, 101, "RDIV_DIVSXR", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_DIVSXT = { 0x00A0, 7, 0, 101, "RDIV_DIVSXT", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_DIGSXT = { 0x00A1, 15, 8, 101, "RDIV_DIGSXT", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_DIVGN = { 0x00A1, 7, 0, 101, "RDIV_DIVGN", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_DIGGN = { 0x00A2, 15, 8, 101, "RDIV_DIGGN", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_DIGSXR = { 0x00A2, 7, 0, 101, "RDIV_DIGSXR", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_CPSXT = { 0x00A3, 15, 8, 101, "RDIV_CPSXT", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_DIG = { 0x00A3, 7, 0, 101, "RDIV_DIG", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_CPGN = { 0x00A4, 15, 8, 101, "RDIV_CPGN", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_CPSXR = { 0x00A4, 7, 0, 101, "RDIV_CPSXR", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_SPIBUF = { 0x00A5, 15, 8, 101, "RDIV_SPIBUF", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_AFE = { 0x00A5, 7, 0, 101, "RDIV_AFE", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter SPDUP_LDO_SPIBUF = { 0x00A6, 12, 12, 0, "SPDUP_LDO_SPIBUF", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_DIGIp2 = { 0x00A6, 11, 11, 0, "SPDUP_LDO_DIGIp2", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter SPDUP_LDO_DIGIp1 = { 0x00A6, 10, 10, 0, "SPDUP_LDO_DIGIp1", "Short the noise filter resistor to speed up the settling time" };
const struct LMS7Parameter BYP_LDO_SPIBUF = { 0x00A6, 9, 9, 0, "BYP_LDO_SPIBUF", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_DIGIp2 = { 0x00A6, 8, 8, 0, "BYP_LDO_DIGIp2", "Bypass signal for the LDO" };
const struct LMS7Parameter BYP_LDO_DIGIp1 = { 0x00A6, 7, 7, 0, "BYP_LDO_DIGIp1", "Bypass signal for the LDO" };
const struct LMS7Parameter EN_LOADIMP_LDO_SPIBUF = { 0x00A6, 6, 6, 0, "EN_LOADIMP_LDO_SPIBUF", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_DIGIp2 = { 0x00A6, 5, 5, 0, "EN_LOADIMP_LDO_DIGIp2", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter EN_LOADIMP_LDO_DIGIp1 = { 0x00A6, 4, 4, 0, "EN_LOADIMP_LDO_DIGIp1", "Enables the load dependent bias to optimize the load regulation" };
const struct LMS7Parameter PD_LDO_SPIBUF = { 0x00A6, 3, 3, 1, "PD_LDO_SPIBUF", "Enables the LDO" };
const struct LMS7Parameter PD_LDO_DIGIp2 = { 0x00A6, 2, 2, 1, "PD_LDO_DIGIp2", "Enables the LDO" };
const struct LMS7Parameter PD_LDO_DIGIp1 = { 0x00A6, 1, 1, 1, "PD_LDO_DIGIp1", "Enables the LDO" };
const struct LMS7Parameter EN_G_LDOP = { 0x00A6, 0, 0, 1, "EN_G_LDOP", "Enable control for all the LDO power downs" };
const struct LMS7Parameter RDIV_DIGIp2 = { 0x00A7, 15, 8, 101, "RDIV_DIGIp2", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter RDIV_DIGIp1 = { 0x00A7, 7, 0, 101, "RDIV_DIGIp1", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" };
const struct LMS7Parameter BSIGT = { 0x00A8, 31, 9, 0, "BSIGT", "" };
const struct LMS7Parameter BSTATE = { 0x00A8, 8, 8, 0, "BSTATE", "" };
const struct LMS7Parameter EN_SDM_TSTO_SXT = { 0x00A8, 6, 6, 0, "EN_SDM_TSTO_SXT", "Enables the SDM_TSTO_SXT" };
const struct LMS7Parameter EN_SDM_TSTO_SXR = { 0x00A8, 5, 5, 0, "EN_SDM_TSTO_SXR", "Enables the SDM_TSTO_SXR" };
const struct LMS7Parameter EN_SDM_TSTO_CGEN = { 0x00A8, 4, 4, 0, "EN_SDM_TSTO_CGEN", "Enables the SDM_TSTO_CGEN" };
const struct LMS7Parameter BENC = { 0x00A8, 3, 3, 0, "BENC", "enables CGEN BIST" };
const struct LMS7Parameter BENR = { 0x00A8, 2, 2, 0, "BENR", "enables SXR BIST" };
const struct LMS7Parameter BENT = { 0x00A8, 1, 1, 0, "BENT", "enables SXT BIST" };
const struct LMS7Parameter BSTART = { 0x00A8, 0, 0, 0, "BSTART", "Starts delta sigma built in self test. Keep it at 1 one at least three clock cycles" };
const struct LMS7Parameter BSIGR = { 0x00AA, 22, 0, 0, "BSIGR", "" };
const struct LMS7Parameter BSIGC = { 0x00AB, 29, 7, 0, "BSIGC", "" };
const struct LMS7Parameter CDS_MCLK2 = { 0x00AD, 15, 14, 0, "CDS_MCLK2", "MCLK2 clock delay" };
const struct LMS7Parameter CDS_MCLK1 = { 0x00AD, 13, 12, 0, "CDS_MCLK1", "MCLK1 clock delay" };
const struct LMS7Parameter CDSN_TXBTSP = { 0x00AD, 9, 9, 1, "CDSN_TXBTSP", "TX TSPB clock inversion control" };
const struct LMS7Parameter CDSN_TXATSP = { 0x00AD, 8, 8, 1, "CDSN_TXATSP", "TX TSPA clock inversion control" };
const struct LMS7Parameter CDSN_RXBTSP = { 0x00AD, 7, 7, 1, "CDSN_RXBTSP", "RX TSPB clock inversion control" };
const struct LMS7Parameter CDSN_RXATSP = { 0x00AD, 6, 6, 1, "CDSN_RXATSP", "RX TSPA clock inversion control" };
const struct LMS7Parameter CDSN_TXBLML = { 0x00AD, 5, 5, 1, "CDSN_TXBLML", "TX LMLB clock inversion control" };
const struct LMS7Parameter CDSN_TXALML = { 0x00AD, 4, 4, 1, "CDSN_TXALML", "TX LMLA clock inversion control" };
const struct LMS7Parameter CDSN_RXBLML = { 0x00AD, 3, 3, 1, "CDSN_RXBLML", "RX LMLB clock inversion control" };
const struct LMS7Parameter CDSN_RXALML = { 0x00AD, 2, 2, 1, "CDSN_RXALML", "RX LMLA clock inversion control" };
const struct LMS7Parameter CDSN_MCLK2 = { 0x00AD, 1, 1, 1, "CDSN_MCLK2", "MCLK2 clock inversion control" };
const struct LMS7Parameter CDSN_MCLK1 = { 0x00AD, 0, 0, 1, "CDSN_MCLK1", "MCLK1 clock inversion control" };
const struct LMS7Parameter CDS_TXBTSP = { 0x00AE, 15, 14, 0, "CDS_TXBTSP", "TX TSP B clock delay" };
const struct LMS7Parameter CDS_TXATSP = { 0x00AE, 13, 12, 0, "CDS_TXATSP", "TX TSP A clock delay" };
const struct LMS7Parameter CDS_RXBTSP = { 0x00AE, 11, 10, 0, "CDS_RXBTSP", "RX TSP B clock delay" };
const struct LMS7Parameter CDS_RXATSP = { 0x00AE, 9, 8, 0, "CDS_RXATSP", "RX TSP A clock delay" };
const struct LMS7Parameter CDS_TXBLML = { 0x00AE, 7, 6, 0, "CDS_TXBLML", "TX LML B clock delay" };
const struct LMS7Parameter CDS_TXALML = { 0x00AE, 5, 4, 0, "CDS_TXALML", "TX LML A clock delay" };
const struct LMS7Parameter CDS_RXBLML = { 0x00AE, 3, 2, 0, "CDS_RXBLML", "RX LML B clock delay" };
const struct LMS7Parameter CDS_RXALML = { 0x00AE, 1, 0, 0, "CDS_RXALML", "RX LML A clock delay" };
const struct LMS7Parameter EN_LOWBWLOMX_TMX_TRF = { 0x0100, 15, 15, 0, "EN_LOWBWLOMX_TMX_TRF", "Controls the high pass pole frequency of the RC biasing the gate of the mixer switches" };
const struct LMS7Parameter EN_NEXTTX_TRF = { 0x0100, 14, 14, 0, "EN_NEXTTX_TRF", "Enables the daisy change LO buffer going from TRF_1 to TRF2" };
const struct LMS7Parameter EN_AMPHF_PDET_TRF = { 0x0100, 13, 12, 3, "EN_AMPHF_PDET_TRF", "Enables the TXPAD power detector preamplifier" };
const struct LMS7Parameter LOADR_PDET_TRF = { 0x0100, 11, 10, 1, "LOADR_PDET_TRF", "Controls the resistive load of the Power detector" };
const struct LMS7Parameter PD_PDET_TRF = { 0x0100, 3, 3, 1, "PD_PDET_TRF", "Powerdown signal for Power Detector" };
const struct LMS7Parameter PD_TLOBUF_TRF = { 0x0100, 2, 2, 0, "PD_TLOBUF_TRF", "Powerdown signal for TX LO buffer" };
const struct LMS7Parameter PD_TXPAD_TRF = { 0x0100, 1, 1, 0, "PD_TXPAD_TRF", "Powerdown signal for TXPAD" };
const struct LMS7Parameter EN_G_TRF = { 0x0100, 0, 0, 1, "EN_G_TRF", "Enable control for all the TRF_1 power downs" };
const struct LMS7Parameter F_TXPAD_TRF = { 0x0101, 15, 13, 3, "F_TXPAD_TRF", "Controls the switched capacitor at the TXPAD output. Is used for fine tuning of the TXPAD output" };
const struct LMS7Parameter L_LOOPB_TXPAD_TRF = { 0x0101, 12, 11, 3, "L_LOOPB_TXPAD_TRF", "Controls the loss of the of the loopback path at the TX side" };
const struct LMS7Parameter LOSS_LIN_TXPAD_TRF = { 0x0101, 10, 6, 0, "LOSS_LIN_TXPAD_TRF", "Controls the gain of the linearizing part of of the TXPAD" };
const struct LMS7Parameter LOSS_MAIN_TXPAD_TRF = { 0x0101, 5, 1, 0, "LOSS_MAIN_TXPAD_TRF", "Controls the gain output power of the TXPAD" };
const struct LMS7Parameter EN_LOOPB_TXPAD_TRF = { 0x0101, 0, 0, 0, "EN_LOOPB_TXPAD_TRF", "Enables the TXPAD loopback path" };
const struct LMS7Parameter GCAS_GNDREF_TXPAD_TRF = { 0x0102, 15, 15, 0, "GCAS_GNDREF_TXPAD_TRF", "Controls if the TXPAD cascode transistor gate bias is referred to VDD or GND" };
const struct LMS7Parameter ICT_LIN_TXPAD_TRF = { 0x0102, 14, 10, 12, "ICT_LIN_TXPAD_TRF", "Control the bias current of the linearization section of the TXPAD" };
const struct LMS7Parameter ICT_MAIN_TXPAD_TRF = { 0x0102, 9, 5, 12, "ICT_MAIN_TXPAD_TRF", "Control the bias current of the main gm section of the TXPAD" };
const struct LMS7Parameter VGCAS_TXPAD_TRF = { 0x0102, 4, 0, 0, "VGCAS_TXPAD_TRF", "Controls the bias voltage at the gate of TXPAD cascade" };
const struct LMS7Parameter SEL_BAND1_TRF = { 0x0103, 11, 11, 1, "SEL_BAND1_TRF", "" };
const struct LMS7Parameter SEL_BAND2_TRF = { 0x0103, 10, 10, 0, "SEL_BAND2_TRF", "" };
const struct LMS7Parameter LOBIASN_TXM_TRF = { 0x0103, 9, 5, 16, "LOBIASN_TXM_TRF", "Controls the bias at the gate of the mixer NMOS" };
const struct LMS7Parameter LOBIASP_TXX_TRF = { 0x0103, 4, 0, 18, "LOBIASP_TXX_TRF", "Controls the bias at the gate of the mixer PMOS" };
const struct LMS7Parameter CDC_I_TRF = { 0x0104, 7, 4, 8, "CDC_I_TRF", "" };
const struct LMS7Parameter CDC_Q_TRF = { 0x0104, 3, 0, 8, "CDC_Q_TRF", "" };
const struct LMS7Parameter STATPULSE_TBB = { 0x0105, 15, 15, 0, "STATPULSE_TBB", "" };
const struct LMS7Parameter LOOPB_TBB = { 0x0105, 14, 12, 0, "LOOPB_TBB", "This controls which signal is connected to the loopback output pins. Note: when both the lowpass ladder and real pole are powered down, the output of the active highband biquad is routed to the loopb output" };
const struct LMS7Parameter PD_LPFH_TBB = { 0x0105, 4, 4, 0, "PD_LPFH_TBB", "This selectively powers down the LPFH_TBB biquad" };
const struct LMS7Parameter PD_LPFIAMP_TBB = { 0x0105, 3, 3, 0, "PD_LPFIAMP_TBB", "selectively powers down the LPFIAMP_TBB front-end current amp of the transmitter baseband" };
const struct LMS7Parameter PD_LPFLAD_TBB = { 0x0105, 2, 2, 1, "PD_LPFLAD_TBB", "This selectively powers down the LPFLAD_TBB low pass ladder filter of the transmitter baseband" };
const struct LMS7Parameter PD_LPFS5_TBB = { 0x0105, 1, 1, 1, "PD_LPFS5_TBB", "This selectively powers down the LPFS5_TBB low pass real-pole filter of the transmitter baseband" };
const struct LMS7Parameter EN_G_TBB = { 0x0105, 0, 0, 1, "EN_G_TBB", "Enable control for all the TBB_TOP power downs" };
const struct LMS7Parameter ICT_LPFS5_F_TBB = { 0x0106, 14, 10, 12, "ICT_LPFS5_F_TBB", "This controls the operational amplifier's output stage bias current of the low band real pole filter of the transmitter's baseband" };
const struct LMS7Parameter ICT_LPFS5_PT_TBB = { 0x0106, 9, 5, 12, "ICT_LPFS5_PT_TBB", "This controls the operational amplifier's input stage bias current of the low band real pole filter of the transmitter's baseband" };
const struct LMS7Parameter ICT_LPF_H_PT_TBB = { 0x0106, 4, 0, 12, "ICT_LPF_H_PT_TBB", "This controls the operational amplifiers input stage bias reference current of the high band low pass filter of the transmitter's baseband " };
const struct LMS7Parameter ICT_LPFH_F_TBB = { 0x0107, 14, 10, 12, "ICT_LPFH_F_TBB", "controls the operational amplifiers output stage bias reference current of the high band low pass filter of the transmitter's baseband (LPFH_TBB)" };
const struct LMS7Parameter ICT_LPFLAD_F_TBB = { 0x0107, 9, 5, 12, "ICT_LPFLAD_F_TBB", "This controls the operational amplfiers' output stages bias referene current of the low band ladder filter of the transmisster's baseband" };
const struct LMS7Parameter ICT_LPFLAD_PT_TBB = { 0x0107, 4, 0, 12, "ICT_LPFLAD_PT_TBB", "This controls the operational amplifers' input stages bias reference current of the low band ladder filter of the transmitter's baseband" };
const struct LMS7Parameter CG_IAMP_TBB = { 0x0108, 15, 10, 37, "CG_IAMP_TBB", "This controls the frontend gain of the TBB. For a given gain value, this control value varies with the set TX mode. After resistance calibration, the following table gives the nominal values for each frequency setting. However, this table is to be updated and corrected after calibration" };
const struct LMS7Parameter ICT_IAMP_FRP_TBB = { 0x0108, 9, 5, 1, "ICT_IAMP_FRP_TBB", "This controls the reference bias current of the IAMP main bias current sources" };
const struct LMS7Parameter ICT_IAMP_GG_FRP_TBB = { 0x0108, 4, 0, 6, "ICT_IAMP_GG_FRP_TBB", "This controls the reference bias current of the IAMP's cascode transistors gate voltages that set the IAMP's input voltage level. The IAMP's input is connected to the DAC output" };
const struct LMS7Parameter RCAL_LPFH_TBB = { 0x0109, 15, 8, 97, "RCAL_LPFH_TBB", "This controls the value of the equivalent resistance of the resistor banks of the biquad filter stage (of the high band section) of the transmitter baseband(TBB)" };
const struct LMS7Parameter RCAL_LPFLAD_TBB = { 0x0109, 7, 0, 193, "RCAL_LPFLAD_TBB", "This controls the value of the equivalent resistance of the resistor banks of the low pass filter ladder (of the low band section) of the transmitter baseband(TBB)" };
const struct LMS7Parameter TSTIN_TBB = { 0x010A, 15, 14, 0, "TSTIN_TBB", "This control selects where the input test signal (vinp/n_aux_bbq/i) is routed to as well as disabling the route." };
const struct LMS7Parameter BYPLADDER_TBB = { 0x010A, 13, 13, 0, "BYPLADDER_TBB", "This signal bypasses the LPF ladder of TBB and directly connects the output of current amplifier to the null port of the real pole stage of TBB low pass filter" };
const struct LMS7Parameter CCAL_LPFLAD_TBB = { 0x010A, 12, 8, 16, "CCAL_LPFLAD_TBB", "A common control signal for all the capacitor banks of TBB filters (including the ladder, real pole, and the high band biquad). It is the calibrated value of the banks control that sets the value of the banks' equivalent capacitor to their respective nominal values" };
const struct LMS7Parameter RCAL_LPFS5_TBB = { 0x010A, 7, 0, 76, "RCAL_LPFS5_TBB", "This controls the value of the equivalent resistance of the resistor banks of the real pole filter stage (of the low band section) of the transmitter baseband (TBB). Following is a nominal values table that are corrected for any process variation after calibration" };
const struct LMS7Parameter CDC_I_RFE = { 0x010C, 15, 12, 8, "CDC_I_RFE", "" };
const struct LMS7Parameter CDC_Q_RFE = { 0x010C, 11, 8, 8, "CDC_Q_RFE", "" };
const struct LMS7Parameter PD_LNA_RFE = { 0x010C, 7, 7, 1, "PD_LNA_RFE", "Power control signal for LNA_RFE" };
const struct LMS7Parameter PD_RLOOPB_1_RFE = { 0x010C, 6, 6, 1, "PD_RLOOPB_1_RFE", "Power control signal for RXFE loopback 1" };
const struct LMS7Parameter PD_RLOOPB_2_RFE = { 0x010C, 5, 5, 1, "PD_RLOOPB_2_RFE", "Power control signal for RXFE loopback 2" };
const struct LMS7Parameter PD_MXLOBUF_RFE = { 0x010C, 4, 4, 1, "PD_MXLOBUF_RFE", "Power control signal for RXFE mixer lo buffer" };
const struct LMS7Parameter PD_QGEN_RFE = { 0x010C, 3, 3, 1, "PD_QGEN_RFE", "Power control signal for RXFE Quadrature LO generator" };
const struct LMS7Parameter PD_RSSI_RFE = { 0x010C, 2, 2, 1, "PD_RSSI_RFE", "Power control signal for RXFE RSSI" };
const struct LMS7Parameter PD_TIA_RFE = { 0x010C, 1, 1, 0, "PD_TIA_RFE", "Power control signal for RXFE TIA" };
const struct LMS7Parameter EN_G_RFE = { 0x010C, 0, 0, 1, "EN_G_RFE", "Enable control for all the RFE_1 power downs" };
const struct LMS7Parameter SEL_PATH_RFE = { 0x010D, 8, 7, 1, "SEL_PATH_RFE", "Selects the active path of the RXFE" };
const struct LMS7Parameter EN_DCOFF_RXFE_RFE = { 0x010D, 6, 6, 0, "EN_DCOFF_RXFE_RFE", "Enables the DCOFFSET block for the RXFE" };
const struct LMS7Parameter EN_INSHSW_LB1_RFE = { 0x010D, 4, 4, 1, "EN_INSHSW_LB1_RFE", "Enables the input shorting switch at the input of the loopback 1 (in parallel with LNAL mixer)" };
const struct LMS7Parameter EN_INSHSW_LB2_RFE = { 0x010D, 3, 3, 1, "EN_INSHSW_LB2_RFE", "Enables the input shorting switch at the input of the loopback 2 (in parallel with LNAW mixer)" };
const struct LMS7Parameter EN_INSHSW_L_RFE = { 0x010D, 2, 2, 1, "EN_INSHSW_L_RFE", "Enables the input shorting switch at the input of the LNAL" };
const struct LMS7Parameter EN_INSHSW_W_RFE = { 0x010D, 1, 1, 1, "EN_INSHSW_W_RFE", "Enables the input shorting switch at the input of the LNAW" };
const struct LMS7Parameter EN_NEXTRX_RFE = { 0x010D, 0, 0, 0, "EN_NEXTRX_RFE", "Enables the daisy chain LO buffer going from RXFE1 to RXFE2" };
const struct LMS7Parameter DCOFFI_RFE = { 0x010E, 13, 7, 64, "DCOFFI_RFE", "Controls DC offset at the output of the TIA by injecting current to the input of the TIA (I side)" };
const struct LMS7Parameter DCOFFQ_RFE = { 0x010E, 6, 0, 64, "DCOFFQ_RFE", "Controls DC offset at the output of the TIA by injecting current to the input of the TIA (Q side)" };
const struct LMS7Parameter ICT_LOOPB_RFE = { 0x010F, 14, 10, 12, "ICT_LOOPB_RFE", "Controls the reference current of the RXFE loopback amplifier" };
const struct LMS7Parameter ICT_TIAMAIN_RFE = { 0x010F, 9, 5, 2, "ICT_TIAMAIN_RFE", "Controls the reference current of the RXFE TIA first stage" };
const struct LMS7Parameter ICT_TIAOUT_RFE = { 0x010F, 4, 0, 2, "ICT_TIAOUT_RFE", "Controls the reference current of the RXFE TIA 2nd stage" };
const struct LMS7Parameter ICT_LNACMO_RFE = { 0x0110, 14, 10, 2, "ICT_LNACMO_RFE", "Controls the current generating LNA output common mode voltage" };
const struct LMS7Parameter ICT_LNA_RFE = { 0x0110, 9, 5, 31, "ICT_LNA_RFE", "Controls the current of the LNA core" };
const struct LMS7Parameter ICT_LODC_RFE = { 0x0110, 4, 0, 20, "ICT_LODC_RFE", "Controls the DC of the mixer LO signal at the gate of the mixer switches" };
const struct LMS7Parameter CAP_RXMXO_RFE = { 0x0111, 9, 5, 4, "CAP_RXMXO_RFE", "Control the decoupling cap at the output of the RX Mixer" };
const struct LMS7Parameter CGSIN_LNA_RFE = { 0x0111, 4, 0, 3, "CGSIN_LNA_RFE", "Controls the cap parallel with the LNA input input NMOS CGS to control the Q of the maching circuit and provides trade off between gain/NF and IIP. The higher the frequency, the lower CGSIN_LNA_RFE should be. Also, the higher CGSIN, the lower the Q, The lower the gain, the higher the NF, and the higher the IIP3" };
const struct LMS7Parameter CCOMP_TIA_RFE = { 0x0112, 15, 12, 12, "CCOMP_TIA_RFE", "Compensation capacitor for TIA" };
const struct LMS7Parameter CFB_TIA_RFE = { 0x0112, 11, 0, 230, "CFB_TIA_RFE", "Feeback capacitor for TIA. Controls the 3dB BW of the TIA. Should be set with calibration through digital baseband" };
const struct LMS7Parameter G_LNA_RFE = { 0x0113, 9, 6, 15, "G_LNA_RFE", "Controls the gain of the LNA" };
const struct LMS7Parameter G_RXLOOPB_RFE = { 0x0113, 5, 2, 0, "G_RXLOOPB_RFE", "Controls RXFE loopback gain" };
const struct LMS7Parameter G_TIA_RFE = { 0x0113, 1, 0, 3, "G_TIA_RFE", "Controls the Gain of the TIA" };
const struct LMS7Parameter RCOMP_TIA_RFE = { 0x0114, 8, 5, 4, "RCOMP_TIA_RFE", "Controls the compensation resistors of the TIA opamp" };
const struct LMS7Parameter RFB_TIA_RFE = { 0x0114, 4, 0, 13, "RFB_TIA_RFE", "Sets the feedback resistor to the nominal value" };
const struct LMS7Parameter EN_LB_LPFH_RBB = { 0x0115, 15, 15, 0, "EN_LB_LPFH_RBB", "" };
const struct LMS7Parameter EN_LB_LPFL_RBB = { 0x0115, 14, 14, 0, "EN_LB_LPFL_RBB", "" };
const struct LMS7Parameter PD_LPFH_RBB = { 0x0115, 3, 3, 1, "PD_LPFH_RBB", "Power down of the LPFH block" };
const struct LMS7Parameter PD_LPFL_RBB = { 0x0115, 2, 2, 0, "PD_LPFL_RBB", "Power down of the LPFL block" };
const struct LMS7Parameter PD_PGA_RBB = { 0x0115, 1, 1, 0, "PD_PGA_RBB", "Power down of the PGA block" };
const struct LMS7Parameter EN_G_RBB = { 0x0115, 0, 0, 1, "EN_G_RBB", "Enable control for all the RBB_1 power downs" };
const struct LMS7Parameter R_CTL_LPF_RBB = { 0x0116, 15, 11, 16, "R_CTL_LPF_RBB", "Controls the absolute value of the resistance of the RC time constant of the RBB_LPF blocks (both Low and High)" };
const struct LMS7Parameter RCC_CTL_LPFH_RBB = { 0x0116, 10, 8, 1, "RCC_CTL_LPFH_RBB", "Controls the stability passive compensation of the LPFH_RBB operational amplifier" };
const struct LMS7Parameter C_CTL_LPFH_RBB = { 0x0116, 7, 0, 128, "C_CTL_LPFH_RBB", "Controls the capacitance value of the RC time constant of RBB_LPFH and it varies with the respective rxMode from 37MHz to 108MHz" };
const struct LMS7Parameter RCC_CTL_LPFL_RBB = { 0x0117, 13, 11, 5, "RCC_CTL_LPFL_RBB", "Controls the stability passive compensation of the LPFL_RBB operational amplifier" };
const struct LMS7Parameter C_CTL_LPFL_RBB = { 0x0117, 10, 0, 12, "C_CTL_LPFL_RBB", "Controls the capacitance value of the RC time constant of RBB_LPFH and it varies with the respective rxMode from 1.4MHz to 20MHz." };
const struct LMS7Parameter INPUT_CTL_PGA_RBB = { 0x0118, 15, 13, 0, "INPUT_CTL_PGA_RBB", "There are a total of four different differential inputs to the PGA. Only one of them is active at a time" };
const struct LMS7Parameter ICT_LPF_IN_RBB = { 0x0118, 9, 5, 12, "ICT_LPF_IN_RBB", "Controls the reference bias current of the input stage of the operational amplifier used in RBB_LPF blocks (Low or High). " };
const struct LMS7Parameter ICT_LPF_OUT_RBB = { 0x0118, 4, 0, 12, "ICT_LPF_OUT_RBB", "The reference bias current of the output stage of the operational amplifier used in RBB_LPF blocks (low or High)" };
const struct LMS7Parameter OSW_PGA_RBB = { 0x0119, 15, 15, 0, "OSW_PGA_RBB", "There are two instances of the PGA circuit in the design. The output of the RBB_LPF blocks are connected the input of these PGA blocks (common). The output of one of them is connected to two pads pgaoutn and pgaoutp and the output of the other PGA is connected directly to the ADC input" };
const struct LMS7Parameter ICT_PGA_OUT_RBB = { 0x0119, 14, 10, 6, "ICT_PGA_OUT_RBB", "Controls the output stage reference bias current of the operational amplifier used in the PGA circuit" };
const struct LMS7Parameter ICT_PGA_IN_RBB = { 0x0119, 9, 5, 6, "ICT_PGA_IN_RBB", "Controls the input stage reference bias current of the operational amplifier used in the PGA circuit" };
const struct LMS7Parameter G_PGA_RBB = { 0x0119, 4, 0, 11, "G_PGA_RBB", "This is the gain of the PGA" };
const struct LMS7Parameter RCC_CTL_PGA_RBB = { 0x011A, 13, 9, 23, "RCC_CTL_PGA_RBB", "Controls the stability passive compensation of the PGA_RBB operational amplifier" };
const struct LMS7Parameter C_CTL_PGA_RBB = { 0x011A, 6, 0, 2, "C_CTL_PGA_RBB", "Control the value of the feedback capacitor of the PGA that is used to help against the parasitic cap at the virtual node for stability" };
const struct LMS7Parameter RESET_N = { 0x011C, 15, 15, 1, "RESET_N", "Resets SX. A pulse should be used in the start-up to reset" };
const struct LMS7Parameter SPDUP_VCO = { 0x011C, 14, 14, 0, "SPDUP_VCO", "Bypasses the noise filter resistor for fast settling time. It should be connected to a 1uS pulse" };
const struct LMS7Parameter BYPLDO_VCO = { 0x011C, 13, 13, 1, "BYPLDO_VCO", "Controls the bypass signal for the SX LDO" };
const struct LMS7Parameter EN_COARSEPLL = { 0x011C, 12, 12, 0, "EN_COARSEPLL", "Enable signal for coarse tuning block" };
const struct LMS7Parameter CURLIM_VCO = { 0x011C, 11, 11, 1, "CURLIM_VCO", "Enables the output current limitation in the VCO regulator" };
const struct LMS7Parameter EN_DIV2_DIVPROG = { 0x011C, 10, 10, 1, "EN_DIV2_DIVPROG", "" };
const struct LMS7Parameter EN_INTONLY_SDM = { 0x011C, 9, 9, 0, "EN_INTONLY_SDM", "Enables INTEGER-N mode of the SX " };
const struct LMS7Parameter EN_SDM_CLK = { 0x011C, 8, 8, 1, "EN_SDM_CLK", "Enables/Disables SDM clock. In INT-N mode or for noise testing, SDM clock can be disabled" };
const struct LMS7Parameter PD_FBDIV = { 0x011C, 7, 7, 0, "PD_FBDIV", "Power down the feedback divider block" };
const struct LMS7Parameter PD_LOCH_T2RBUF = { 0x011C, 6, 6, 1, "PD_LOCH_T2RBUF", "Power down for LO buffer from SXT to SXR. To be active only in the TDD mode" };
const struct LMS7Parameter PD_CP = { 0x011C, 5, 5, 0, "PD_CP", "Power down for Charge Pump" };
const struct LMS7Parameter PD_FDIV = { 0x011C, 4, 4, 0, "PD_FDIV", "Power down for feedback frequency and forward dividers" };
const struct LMS7Parameter PD_SDM = { 0x011C, 3, 3, 0, "PD_SDM", "Power down for SDM" };
const struct LMS7Parameter PD_VCO_COMP = { 0x011C, 2, 2, 0, "PD_VCO_COMP", "Power down for VCO comparator" };
const struct LMS7Parameter PD_VCO = { 0x011C, 1, 1, 1, "PD_VCO", "Power down for VCO" };
const struct LMS7Parameter EN_G = { 0x011C, 0, 0, 1, "EN_G", "Enable control for all the SXT power downs" };
const struct LMS7Parameter FRAC_SDM_LSB = { 0x011D, 15, 0, 0x0400, "FRAC_SDM_LSB", "" };
const struct LMS7Parameter INT_SDM = { 0x011E, 13, 4, 120, "INT_SDM", "" };
const struct LMS7Parameter FRAC_SDM_MSB = { 0x011E, 3, 0, 0, "FRAC_SDM_MSB", "" };
const struct LMS7Parameter PW_DIV2_LOCH = { 0x011F, 14, 12, 3, "PW_DIV2_LOCH", "trims the duty cycle of DIV2 LOCH. Only works when forward divider is dividing by at least 2 (excluding quadrature block division). If in bypass mode, this does not work" };
const struct LMS7Parameter PW_DIV4_LOCH = { 0x011F, 11, 9, 3, "PW_DIV4_LOCH", "trims the duty cycle of DIV4 LOCH. Only works when forward divider is dividing by at least 4 (excluding quadrature block division). If in bypass mode, this does not work" };
const struct LMS7Parameter DIV_LOCH = { 0x011F, 8, 6, 1, "DIV_LOCH", "Controls the division ratio in the LOCH_DIV" };
const struct LMS7Parameter TST_SX = { 0x011F, 5, 3, 0, "TST_SX",
"Controls the test mode of PLLs. TST signal lines are shared between all PLLs (CGEN, RX and TX). Only one TST signal of any PLL should be active at a given time.\n\
0 - TST disabled; RSSI analog outputs enabled if RSSI blocks active and when all PLL test signals are off(default)\n\
1 - tstdo[0] = VCO / 20 clock*; tstdo[1] = VCO / 40 clock*; tstao = High impedance;\n\
2 - tstdo[0] = SDM clock; tstdo[1] = feedback divider output; tstao = VCO tune through a 60kOhm resistor;\n\
3 - tstdo[0] = Reference clock; tstdo[1] = feedback divider output; tstao = VCO tune through a 10kOhm resistor;\n\
4 - tstdo[0] = High impedance; tstdo[1] = High impedance; tstao = High impedance;\n\
5 - tstdo[0] = Charge pump Down signal; tstdo[1] = Charge pump Up signal; tstao = High impedance;\n\
6 - tstdo[0] = High impedance; tstdo[1] = High impedance; tstao = VCO tune through a 60kOhm resistor;\n\
7 - tstdo[0] = High impedance; tstdo[1] = High impedance; tstao = VCO tune through a 10kOhm resistor;\n\
if TST_SX[2] = 1 --> VCO_TSTBUF active generating VCO_TST_DIV20 and VCO_TST_DIV40\n\
* When EN_DIV2_DIVPROG_(SXR, SXT) is active, the division ratio must be multiplied by 2 (40 / 80)"};
const struct LMS7Parameter SEL_SDMCLK = { 0x011F, 2, 2, 0, "SEL_SDMCLK", "Selects between the feedback divider output and Fref for SDM" };
const struct LMS7Parameter SX_DITHER_EN = { 0x011F, 1, 1, 0, "SX_DITHER_EN", "Enabled dithering in SDM" };
const struct LMS7Parameter REV_SDMCLK = { 0x011F, 0, 0, 0, "REV_SDMCLK", "Reverses the SDM clock" };
const struct LMS7Parameter VDIV_VCO = { 0x0120, 15, 8, 185, "VDIV_VCO", "Controls VCO LDO output voltage" };
const struct LMS7Parameter ICT_VCO = { 0x0120, 7, 0, 255, "ICT_VCO", "Scales the VCO bias current from 0 to 2.5xInom" };
const struct LMS7Parameter RSEL_LDO_VCO = { 0x0121, 15, 11, 6, "RSEL_LDO_VCO", "Set the reference voltage that supplies bias voltage of switch-cap array and varactor" };
const struct LMS7Parameter CSW_VCO = { 0x0121, 10, 3, 128, "CSW_VCO", "Coarse control of VCO frequency, 0 for lowest frequency and 255 for highest. This control is set by SX_SWC_calibration" };
const struct LMS7Parameter SEL_VCO = { 0x0121, 2, 1, 2, "SEL_VCO", "Selects the active VCO. It is set by SX_SWC_calibration" };
const struct LMS7Parameter COARSE_START = { 0x0121, 0, 0, 0, "COARSE_START", "" };
const struct LMS7Parameter REVPH_PFD = { 0x0122, 12, 12, 0, "REVPH_PFD", "Reverse the pulses of PFD. It can be used to reverse the polarity of the PLL loop (positive feedback to negative feedback)" };
const struct LMS7Parameter IOFFSET_CP = { 0x0122, 11, 6, 12, "IOFFSET_CP", "Scales the offset current of the charge pump, 0-->63. This current is used in Fran-N mode to create an offset in the CP response and avoid the non-linear section" };
const struct LMS7Parameter IPULSE_CP = { 0x0122, 5, 0, 63, "IPULSE_CP", "Scales the pulse current of the charge pump" };
const struct LMS7Parameter COARSE_STEPDONE = { 0x0123, 15, 15, 0, "COARSE_STEPDONE", "" };
const struct LMS7Parameter COARSEPLL_COMPO = { 0x0123, 14, 14, 0, "COARSEPLL_COMPO", "" };
const struct LMS7Parameter VCO_CMPHO = { 0x0123, 13, 13, 0, "VCO_CMPHO", "" };
const struct LMS7Parameter VCO_CMPLO = { 0x0123, 12, 12, 0, "VCO_CMPLO", "" };
const struct LMS7Parameter CP2_PLL = { 0x0123, 11, 8, 6, "CP2_PLL", "Controls the value of CP2 (cap from CP output to GND) in the PLL filter" };
const struct LMS7Parameter CP3_PLL = { 0x0123, 7, 4, 7, "CP3_PLL", "Controls the value of CP3 (cap from VCO Vtune input to GND) in the PLL filter" };
const struct LMS7Parameter CZ = { 0x0123, 3, 0, 11, "CZ", "Controls the value of CZ (Zero capacitor) in the PLL filter" };
const struct LMS7Parameter EN_DIR_SXRSXT = { 0x0124, 4, 4, 0, "EN_DIR_SXRSXT", "Enables direct control of PDs and ENs for SXR/SXT module" };
const struct LMS7Parameter EN_DIR_RBB = { 0x0124, 3, 3, 0, "EN_DIR_RBB", "Enables direct control of PDs and ENs for RBB module" };
const struct LMS7Parameter EN_DIR_RFE = { 0x0124, 2, 2, 0, "EN_DIR_RFE", "Enables direct control of PDs and ENs for RFE module" };
const struct LMS7Parameter EN_DIR_TBB = { 0x0124, 1, 1, 0, "EN_DIR_TBB", "Enables direct control of PDs and ENs for TBB module" };
const struct LMS7Parameter EN_DIR_TRF = { 0x0124, 0, 0, 0, "EN_DIR_TRF", "Enables direct control of PDs and ENs for TRF module" };
const struct LMS7Parameter TSGFC_TXTSP = { 0x0200, 9, 9, 0, "TSGFC_TXTSP", "TSG full scale control" };
const struct LMS7Parameter TSGFCW_TXTSP = { 0x0200, 8, 7, 1, "TSGFCW_TXTSP", "Set frequency of TSG's NCO" };
const struct LMS7Parameter TSGDCLDQ_TXTSP = { 0x0200, 6, 6, 0, "TSGDCLDQ_TXTSP", "" };
const struct LMS7Parameter TSGDCLDI_TXTSP = { 0x0200, 5, 5, 0, "TSGDCLDI_TXTSP", "" };
const struct LMS7Parameter TSGSWAPIQ_TXTSP = { 0x0200, 4, 4, 0, "TSGSWAPIQ_TXTSP", "Swap signals at test signal generator's output" };
const struct LMS7Parameter TSGMODE_TXTSP = { 0x0200, 3, 3, 0, "TSGMODE_TXTSP", "Test signal generator mode" };
const struct LMS7Parameter INSEL_TXTSP = { 0x0200, 2, 2, 0, "INSEL_TXTSP", "Input source of TxTSP" };
const struct LMS7Parameter BSTART_TXTSP = { 0x0200, 1, 1, 0, "BSTART_TXTSP", "Starts delta sigma built in self test. Keep it at 1 one at least three clock cycles" };
const struct LMS7Parameter EN_TXTSP = { 0x0200, 0, 0, 1, "EN_TXTSP", "TxTSP modules enable" };
const struct LMS7Parameter GCORRQ_TXTSP = { 0x0201, 10, 0, 2047, "GCORRQ_TXTSP", "corrector value, channel Q Unsigned integer" };
const struct LMS7Parameter GCORRI_TXTSP = { 0x0202, 10, 0, 2047, "GCORRI_TXTSP", "corrector value, channel I Unsigned integer" };
const struct LMS7Parameter HBI_OVR_TXTSP = { 0x0203, 14, 12, 0, "HBI_OVR_TXTSP", "HBI interpolation ratio" };
const struct LMS7Parameter IQCORR_TXTSP = { 0x0203, 11, 0, 0, "IQCORR_TXTSP", "Phase corrector value (tan(Alpha/2)). Integer, 2's complement" };
const struct LMS7Parameter DCCORRI_TXTSP = { 0x0204, 15, 8, 0, "DCCORRI_TXTSP", "DC corrector value, channel I. Integer, 2's complement" };
const struct LMS7Parameter DCCORRQ_TXTSP = { 0x0204, 7, 0, 0, "DCCORRQ_TXTSP", "DC corrector value, channel Q. Integer, 2's complement" };
const struct LMS7Parameter GFIR1_L_TXTSP = { 0x0205, 10, 8, 0, "GFIR1_L_TXTSP", "Parameter l of GFIR1 (l = roundUp(CoeffN/5)-1). Unsigned integer" };
const struct LMS7Parameter GFIR1_N_TXTSP = { 0x0205, 7, 0, 0, "GFIR1_N_TXTSP", "Clock division ratio of GFIR1 is GFIR1_N + 1. Unsigned integer" };
const struct LMS7Parameter GFIR2_L_TXTSP = { 0x0206, 10, 8, 0, "GFIR2_L_TXTSP", "Parameter l of GFIR2 (l = roundUp(CoeffN/5)-1). Unsigned integer" };
const struct LMS7Parameter GFIR2_N_TXTSP = { 0x0206, 7, 0, 0, "GFIR2_N_TXTSP", "Clock division ratio of GFIR2 is GFIR2_N + 1. Unsigned integer" };
const struct LMS7Parameter GFIR3_L_TXTSP = { 0x0207, 10, 8, 0, "GFIR3_L_TXTSP", "Parameter l of GFIR3 (l = roundUp(CoeffN/5)-1). Unsigned integer" };
const struct LMS7Parameter GFIR3_N_TXTSP = { 0x0207, 7, 0, 0, "GFIR3_N_TXTSP", "Clock division ratio of GFIR3 is GFIR3_N + 1. Unsigned integer" };
const struct LMS7Parameter CMIX_GAIN_TXTSP = { 0x0208, 15, 14, 0, "CMIX_GAIN_TXTSP", "Gain of CMIX output" };
const struct LMS7Parameter CMIX_SC_TXTSP = { 0x0208, 13, 13, 0, "CMIX_SC_TXTSP", "Spectrum control of CMIX" };
const struct LMS7Parameter CMIX_BYP_TXTSP = { 0x0208, 8, 8, 0, "CMIX_BYP_TXTSP", "CMIX bypass" };
const struct LMS7Parameter ISINC_BYP_TXTSP = { 0x0208, 7, 7, 0, "ISINC_BYP_TXTSP", "ISINC bypass" };
const struct LMS7Parameter GFIR3_BYP_TXTSP = { 0x0208, 6, 6, 0, "GFIR3_BYP_TXTSP", "GFIR3 bypass" };
const struct LMS7Parameter GFIR2_BYP_TXTSP = { 0x0208, 5, 5, 0, "GFIR2_BYP_TXTSP", "GFIR2 bypass" };
const struct LMS7Parameter GFIR1_BYP_TXTSP = { 0x0208, 4, 4, 0, "GFIR1_BYP_TXTSP", "GFIR1 bypass" };
const struct LMS7Parameter DC_BYP_TXTSP = { 0x0208, 3, 3, 0, "DC_BYP_TXTSP", "DC corrector bypass" };
const struct LMS7Parameter GC_BYP_TXTSP = { 0x0208, 1, 1, 0, "GC_BYP_TXTSP", "Gain corrector bypass" };
const struct LMS7Parameter PH_BYP_TXTSP = { 0x0208, 0, 0, 0, "PH_BYP_TXTSP", "Phase corrector bypass" };
const struct LMS7Parameter BSIGI_TXTSP = { 0x0209, 23, 1, 0, "BSIGI_TXTSP", "" };
const struct LMS7Parameter BSTATE_TXTSP = { 0x0209, 0, 0, 0, "BSTATE_TXTSP", "" };
const struct LMS7Parameter BSIGQ_TXTSP = { 0x020A, 30, 8, 0, "BSIGQ_TXTSP", "" };
const struct LMS7Parameter DC_REG_TXTSP = { 0x020C, 15, 0, 0, "DC_REG_TXTSP", "" };
const struct LMS7Parameter DTHBIT_TX = { 0x0240, 8, 5, 1, "DTHBIT_TX", "NCO bits to dither" };
const struct LMS7Parameter SEL_TX = { 0x0240, 4, 1, 0, "SEL_TX", "" };
const struct LMS7Parameter MODE_TX = { 0x0240, 0, 0, 0, "MODE_TX", "" };
const struct LMS7Parameter CAPTURE = { 0x0400, 15, 15, 0, "CAPTURE", "" };
const struct LMS7Parameter CAPSEL = { 0x0400, 14, 13, 0, "CAPSEL", "" };
const struct LMS7Parameter CAPSEL_ADC = { 0x0400, 12, 12, 0, "CAPSEL_ADC", "" };
const struct LMS7Parameter TSGFC_RXTSP = { 0x0400, 9, 9, 0, "TSGFC_RXTSP", "TSG full scale control" };
const struct LMS7Parameter TSGFCW_RXTSP = { 0x0400, 8, 7, 1, "TSGFCW_RXTSP", "Set frequency of TSG's NCO" };
const struct LMS7Parameter TSGDCLDQ_RXTSP = { 0x0400, 6, 6, 0, "TSGDCLDQ_RXTSP", "" };
const struct LMS7Parameter TSGDCLDI_RXTSP = { 0x0400, 5, 5, 0, "TSGDCLDI_RXTSP", "" };
const struct LMS7Parameter TSGSWAPIQ_RXTSP = { 0x0400, 4, 4, 0, "TSGSWAPIQ_RXTSP", "Swap signals at test signal generator's output" };
const struct LMS7Parameter TSGMODE_RXTSP = { 0x0400, 3, 3, 0, "TSGMODE_RXTSP", "Test signal generator mode" };
const struct LMS7Parameter INSEL_RXTSP = { 0x0400, 2, 2, 0, "INSEL_RXTSP", "Input source of RxTSP" };
const struct LMS7Parameter BSTART_RXTSP = { 0x0400, 1, 1, 0, "BSTART_RXTSP", "Starts delta sigma built in self test. Keep it at 1 one at least three clock cycles" };
const struct LMS7Parameter EN_RXTSP = { 0x0400, 0, 0, 1, "EN_RXTSP", "RxTSP modules enable" };
const struct LMS7Parameter GCORRQ_RXTSP = { 0x0401, 10, 0, 2047, "GCORRQ_RXTSP", "corrector value, channel Q Unsigned integer" };
const struct LMS7Parameter GCORRI_RXTSP = { 0x0402, 10, 0, 2047, "GCORRI_RXTSP", "corrector value, channel I Unsigned integer" };
const struct LMS7Parameter HBD_OVR_RXTSP = { 0x0403, 14, 12, 0, "HBD_OVR_RXTSP", "HBD interpolation ratio. Interpolation ratio is 2HBD_OVR+1" };
const struct LMS7Parameter IQCORR_RXTSP = { 0x0403, 11, 0, 0, "IQCORR_RXTSP", "Phase corrector value (tan(Alpha/2)). Integer, 2's complement" };
const struct LMS7Parameter HBD_DLY = { 0x0404, 15, 13, 0, "HBD_DLY", "" };
const struct LMS7Parameter DCLOOP_BYP = { 0x0404, 8, 8, 0, "DCLOOP_BYP", "" };
const struct LMS7Parameter DCCORR_AVG_RXTSP = { 0x0404, 2, 0, 0, "DCCORR_AVG_RXTSP", "Number of samples to average for Automatic DC corrector. Number of samples to average is 2DCCORR_AVG + 12" };
const struct LMS7Parameter GFIR1_L_RXTSP = { 0x0405, 10, 8, 0, "GFIR1_L_RXTSP", "Parameter l of GFIR1 (l = roundUp(CoeffN/5)-1). Unsigned integer" };
const struct LMS7Parameter GFIR1_N_RXTSP = { 0x0405, 7, 0, 0, "GFIR1_N_RXTSP", "Clock division ratio of GFIR1 is GFIR1_N + 1. Unsigned integer" };
const struct LMS7Parameter GFIR2_L_RXTSP = { 0x0406, 10, 8, 0, "GFIR2_L_RXTSP", "Parameter l of GFIR2 (l = roundUp(CoeffN/5)-1). Unsigned integer" };
const struct LMS7Parameter GFIR2_N_RXTSP = { 0x0406, 7, 0, 0, "GFIR2_N_RXTSP", "Clock division ratio of GFIR2 is GFIR2_N + 1. Unsigned integer" };
const struct LMS7Parameter GFIR3_L_RXTSP = { 0x0407, 10, 8, 0, "GFIR3_L_RXTSP", "Parameter l of GFIR3 (l = roundUp(CoeffN/5)-1). Unsigned integer" };
const struct LMS7Parameter GFIR3_N_RXTSP = { 0x0407, 7, 0, 0, "GFIR3_N_RXTSP", "Clock division ratio of GFIR3 is GFIR3_N + 1. Unsigned integer" };
const struct LMS7Parameter AGC_K_RXTSP = { 0x0408, 17, 0, 0, "AGC_K_RXTSP", "AGC loop gain" };
const struct LMS7Parameter AGC_ADESIRED_RXTSP = { 0x0409, 15, 4, 0, "AGC_ADESIRED_RXTSP", "AGC_ADESIRED" };
const struct LMS7Parameter RSSI_MODE = { 0x040A, 15, 14, 0, "RSSI_MODE", "" };
const struct LMS7Parameter AGC_MODE_RXTSP = { 0x040A, 13, 12, 0, "AGC_MODE_RXTSP", "" };
const struct LMS7Parameter AGC_AVG_RXTSP = { 0x040A, 2, 0, 0, "AGC_AVG_RXTSP", "AGC Averaging window size" };
const struct LMS7Parameter DC_REG_RXTSP = { 0x040B, 15, 0, 0, "DC_REG_RXTSP", "" };
const struct LMS7Parameter CMIX_GAIN_RXTSP = { 0x040C, 15, 14, 0, "CMIX_GAIN_RXTSP", "Gain of CMIX output" };
const struct LMS7Parameter CMIX_SC_RXTSP = { 0x040C, 13, 13, 0, "CMIX_SC_RXTSP", "Spectrum control of CMIX" };
const struct LMS7Parameter CMIX_BYP_RXTSP = { 0x040C, 7, 7, 0, "CMIX_BYP_RXTSP", "CMIX bypass" };
const struct LMS7Parameter AGC_BYP_RXTSP = { 0x040C, 6, 6, 0, "AGC_BYP_RXTSP", "AGC bypass" };
const struct LMS7Parameter GFIR3_BYP_RXTSP = { 0x040C, 5, 5, 0, "GFIR3_BYP_RXTSP", "GFIR3 bypass" };
const struct LMS7Parameter GFIR2_BYP_RXTSP = { 0x040C, 4, 4, 0, "GFIR2_BYP_RXTSP", "GFIR2 bypass" };
const struct LMS7Parameter GFIR1_BYP_RXTSP = { 0x040C, 3, 3, 0, "GFIR1_BYP_RXTSP", "GFIR1 bypass" };
const struct LMS7Parameter DC_BYP_RXTSP = { 0x040C, 2, 2, 0, "DC_BYP_RXTSP", "DC corrector bypass" };
const struct LMS7Parameter GC_BYP_RXTSP = { 0x040C, 1, 1, 0, "GC_BYP_RXTSP", "Gain corrector bypass" };
const struct LMS7Parameter PH_BYP_RXTSP = { 0x040C, 0, 0, 0, "PH_BYP_RXTSP", "Phase corrector bypass" };
const struct LMS7Parameter CAPD = { 0x040E, 31, 0, 0, "CAPD", "" };
const struct LMS7Parameter DTHBIT_RX = { 0x0440, 8, 5, 1, "DTHBIT_RX", "NCO bits to dither" };
const struct LMS7Parameter SEL_RX = { 0x0440, 4, 1, 0, "SEL_RX", "" };
const struct LMS7Parameter MODE_RX = { 0x0440, 0, 0, 0, "MODE_RX", "" };
/**
@file LMS7002M_parameters.h
@author Lime Microsystems (www.limemicro.com)
@brief List of LMS7002M transceiver control parameters
*/
#ifndef LMS7002M_PARAMETERS_H
#define LMS7002M_PARAMETERS_H
#include "typedefs.h"
#include <vector>
struct LMS7Parameter;
extern std::vector<const LMS7Parameter*> LMS7parameterList;
struct LMS7Parameter
{
LMS7Parameter() : address(0), msb(0), lsb(0), defaultValue(0), name(nullptr), tooltip(nullptr)
{
}
LMS7Parameter(uint16_t address, uint8_t msb, uint8_t lsb, uint16_t defaultValue, const char *name, const char* tooltip)
: address(address), msb(msb), lsb(lsb), defaultValue(defaultValue), name(name), tooltip(tooltip)
{
LMS7parameterList.push_back(this);
}
uint16_t address;
uint8_t msb;
uint8_t lsb;
uint16_t defaultValue;
const char* name;
const char* tooltip;
inline bool operator==(const LMS7Parameter& obj)
{
if (address == obj.address && msb == obj.msb && lsb == obj.lsb)
return true;
return false;
};
};
extern const struct LMS7Parameter LRST_TX_B;
extern const struct LMS7Parameter MRST_TX_B;
extern const struct LMS7Parameter LRST_TX_A;
extern const struct LMS7Parameter MRST_TX_A;
extern const struct LMS7Parameter LRST_RX_B;
extern const struct LMS7Parameter MRST_RX_B;
extern const struct LMS7Parameter LRST_RX_A;
extern const struct LMS7Parameter MRST_RX_A;
extern const struct LMS7Parameter SRST_RXFIFO;
extern const struct LMS7Parameter SRST_TXFIFO;
extern const struct LMS7Parameter RXEN_B;
extern const struct LMS7Parameter RXEN_A;
extern const struct LMS7Parameter TXEN_B;
extern const struct LMS7Parameter TXEN_A;
extern const struct LMS7Parameter MAC;
extern const struct LMS7Parameter TX_CLK_PE;
extern const struct LMS7Parameter RX_CLK_PE;
extern const struct LMS7Parameter SDA_PE;
extern const struct LMS7Parameter SDA_DS;
extern const struct LMS7Parameter SCL_PE;
extern const struct LMS7Parameter SCL_DS;
extern const struct LMS7Parameter SDIO_DS;
extern const struct LMS7Parameter SDIO_PE;
extern const struct LMS7Parameter SDO_PE;
extern const struct LMS7Parameter SCLK_PE;
extern const struct LMS7Parameter SEN_PE;
extern const struct LMS7Parameter SPIMODE;
extern const struct LMS7Parameter DIQ2_DS;
extern const struct LMS7Parameter DIQ2_PE;
extern const struct LMS7Parameter IQ_SEL_EN_2_PE;
extern const struct LMS7Parameter TXNRX2_PE;
extern const struct LMS7Parameter FCLK2_PE;
extern const struct LMS7Parameter MCLK2_PE;
extern const struct LMS7Parameter DIQ1_DS;
extern const struct LMS7Parameter DIQ1_PE;
extern const struct LMS7Parameter IQ_SEL_EN_1_PE;
extern const struct LMS7Parameter TXNRX1_PE;
extern const struct LMS7Parameter FCLK1_PE;
extern const struct LMS7Parameter MCLK1_PE;
extern const struct LMS7Parameter DIQDIRCTR2;
extern const struct LMS7Parameter DIQDIR2;
extern const struct LMS7Parameter DIQDIRCTR1;
extern const struct LMS7Parameter DIQDIR1;
extern const struct LMS7Parameter ENABLEDIRCTR2;
extern const struct LMS7Parameter ENABLEDIR2;
extern const struct LMS7Parameter ENABLEDIRCTR1;
extern const struct LMS7Parameter ENABLEDIR1;
extern const struct LMS7Parameter MOD_EN;
extern const struct LMS7Parameter LML2_FIDM;
extern const struct LMS7Parameter LML2_TXNRXIQ;
extern const struct LMS7Parameter LML2_MODE;
extern const struct LMS7Parameter LML1_FIDM;
extern const struct LMS7Parameter LML1_TXNRXIQ;
extern const struct LMS7Parameter LML1_MODE;
extern const struct LMS7Parameter LML1_S3S;
extern const struct LMS7Parameter LML1_S2S;
extern const struct LMS7Parameter LML1_S1S;
extern const struct LMS7Parameter LML1_S0S;
extern const struct LMS7Parameter LML1_BQP;
extern const struct LMS7Parameter LML1_BIP;
extern const struct LMS7Parameter LML1_AQP;
extern const struct LMS7Parameter LML1_AIP;
extern const struct LMS7Parameter LML1_BB2RF_PST;
extern const struct LMS7Parameter LML1_BB2RF_PRE;
extern const struct LMS7Parameter LML1_RF2BB_PST;
extern const struct LMS7Parameter LML1_RF2BB_PRE;
extern const struct LMS7Parameter LML2_S3S;
extern const struct LMS7Parameter LML2_S2S;
extern const struct LMS7Parameter LML2_S1S;
extern const struct LMS7Parameter LML2_S0S;
extern const struct LMS7Parameter LML2_BQP;
extern const struct LMS7Parameter LML2_BIP;
extern const struct LMS7Parameter LML2_AQP;
extern const struct LMS7Parameter LML2_AIP;
extern const struct LMS7Parameter LML2_BB2RF_PST;
extern const struct LMS7Parameter LML2_BB2RF_PRE;
extern const struct LMS7Parameter LML2_RF2BB_PST;
extern const struct LMS7Parameter LML2_RF2BB_PRE;
extern const struct LMS7Parameter FCLK2_DLY;
extern const struct LMS7Parameter FCLK1_DLY;
extern const struct LMS7Parameter RX_MUX;
extern const struct LMS7Parameter TX_MUX;
extern const struct LMS7Parameter TXRDCLK_MUX;
extern const struct LMS7Parameter TXWRCLK_MUX;
extern const struct LMS7Parameter RXRDCLK_MUX;
extern const struct LMS7Parameter RXWRCLK_MUX;
extern const struct LMS7Parameter FCLK2_INV;
extern const struct LMS7Parameter FCLK1_INV;
extern const struct LMS7Parameter MCLK2DLY;
extern const struct LMS7Parameter MCLK1DLY;
extern const struct LMS7Parameter MCLK2SRC;
extern const struct LMS7Parameter MCLK1SRC;
extern const struct LMS7Parameter TXDIVEN;
extern const struct LMS7Parameter RXDIVEN;
extern const struct LMS7Parameter TXTSPCLKA_DIV;
extern const struct LMS7Parameter RXTSPCLKA_DIV;
extern const struct LMS7Parameter MIMO_SISO;
extern const struct LMS7Parameter VER;
extern const struct LMS7Parameter REV;
extern const struct LMS7Parameter MASK;
extern const struct LMS7Parameter EN_DIR_LDO;
extern const struct LMS7Parameter EN_DIR_CGEN;
extern const struct LMS7Parameter EN_DIR_XBUF;
extern const struct LMS7Parameter EN_DIR_AFE;
extern const struct LMS7Parameter ISEL_DAC_AFE;
extern const struct LMS7Parameter MODE_INTERLEAVE_AFE;
extern const struct LMS7Parameter MUX_AFE_1;
extern const struct LMS7Parameter MUX_AFE_2;
extern const struct LMS7Parameter PD_AFE;
extern const struct LMS7Parameter PD_RX_AFE1;
extern const struct LMS7Parameter PD_RX_AFE2;
extern const struct LMS7Parameter PD_TX_AFE1;
extern const struct LMS7Parameter PD_TX_AFE2;
extern const struct LMS7Parameter EN_G_AFE;
extern const struct LMS7Parameter MUX_BIAS_OUT;
extern const struct LMS7Parameter RP_CALIB_BIAS;
extern const struct LMS7Parameter PD_FRP_BIAS;
extern const struct LMS7Parameter PD_F_BIAS;
extern const struct LMS7Parameter PD_PTRP_BIAS;
extern const struct LMS7Parameter PD_PT_BIAS;
extern const struct LMS7Parameter PD_BIAS_MASTER;
extern const struct LMS7Parameter SLFB_XBUF_RX;
extern const struct LMS7Parameter SLFB_XBUF_TX;
extern const struct LMS7Parameter BYP_XBUF_RX;
extern const struct LMS7Parameter BYP_XBUF_TX;
extern const struct LMS7Parameter EN_OUT2_XBUF_TX;
extern const struct LMS7Parameter EN_TBUFIN_XBUF_RX;
extern const struct LMS7Parameter PD_XBUF_RX;
extern const struct LMS7Parameter PD_XBUF_TX;
extern const struct LMS7Parameter EN_G_XBUF;
extern const struct LMS7Parameter SPDUP_VCO_CGEN;
extern const struct LMS7Parameter RESET_N_CGEN;
extern const struct LMS7Parameter EN_ADCCLKH_CLKGN;
extern const struct LMS7Parameter EN_COARSE_CKLGEN;
extern const struct LMS7Parameter EN_INTONLY_SDM_CGEN;
extern const struct LMS7Parameter EN_SDM_CLK_CGEN;
extern const struct LMS7Parameter PD_CP_CGEN;
extern const struct LMS7Parameter PD_FDIV_FB_CGEN;
extern const struct LMS7Parameter PD_FDIV_O_CGEN;
extern const struct LMS7Parameter PD_SDM_CGEN;
extern const struct LMS7Parameter PD_VCO_CGEN;
extern const struct LMS7Parameter PD_VCO_COMP_CGEN;
extern const struct LMS7Parameter EN_G_CGEN;
extern const struct LMS7Parameter FRAC_SDM_CGEN_LSB;
extern const struct LMS7Parameter INT_SDM_CGEN;
extern const struct LMS7Parameter FRAC_SDM_CGEN_MSB;
extern const struct LMS7Parameter REV_SDMCLK_CGEN;
extern const struct LMS7Parameter SEL_SDMCLK_CGEN;
extern const struct LMS7Parameter SX_DITHER_EN_CGEN;
extern const struct LMS7Parameter CLKH_OV_CLKL_CGEN;
extern const struct LMS7Parameter DIV_OUTCH_CGEN;
extern const struct LMS7Parameter TST_CGEN;
extern const struct LMS7Parameter REV_CLKDAC_CGEN;
extern const struct LMS7Parameter CMPLO_CTRL_CGEN;
extern const struct LMS7Parameter REV_CLKADC_CGEN;
extern const struct LMS7Parameter REVPH_PFD_CGEN;
extern const struct LMS7Parameter IOFFSET_CP_CGEN;
extern const struct LMS7Parameter IPULSE_CP_CGEN;
extern const struct LMS7Parameter ICT_VCO_CGEN;
extern const struct LMS7Parameter CSW_VCO_CGEN;
extern const struct LMS7Parameter COARSE_START_CGEN;
extern const struct LMS7Parameter COARSE_STEPDONE_CGEN;
extern const struct LMS7Parameter COARSEPLL_COMPO_CGEN;
extern const struct LMS7Parameter VCO_CMPHO_CGEN;
extern const struct LMS7Parameter VCO_CMPLO_CGEN;
extern const struct LMS7Parameter CP2_CGEN;
extern const struct LMS7Parameter CP3_CGEN;
extern const struct LMS7Parameter CZ_CGEN;
extern const struct LMS7Parameter EN_LDO_DIG;
extern const struct LMS7Parameter EN_LDO_DIGGN;
extern const struct LMS7Parameter EN_LDO_DIGSXR;
extern const struct LMS7Parameter EN_LDO_DIGSXT;
extern const struct LMS7Parameter EN_LDO_DIVGN;
extern const struct LMS7Parameter EN_LDO_DIVSXR;
extern const struct LMS7Parameter EN_LDO_DIVSXT;
extern const struct LMS7Parameter EN_LDO_LNA12;
extern const struct LMS7Parameter EN_LDO_LNA14;
extern const struct LMS7Parameter EN_LDO_MXRFE;
extern const struct LMS7Parameter EN_LDO_RBB;
extern const struct LMS7Parameter EN_LDO_RXBUF;
extern const struct LMS7Parameter EN_LDO_TBB;
extern const struct LMS7Parameter EN_LDO_TIA12;
extern const struct LMS7Parameter EN_LDO_TIA14;
extern const struct LMS7Parameter EN_G_LDO;
extern const struct LMS7Parameter EN_LOADIMP_LDO_TLOB;
extern const struct LMS7Parameter EN_LOADIMP_LDO_TPAD;
extern const struct LMS7Parameter EN_LOADIMP_LDO_TXBUF;
extern const struct LMS7Parameter EN_LOADIMP_LDO_VCOGN;
extern const struct LMS7Parameter EN_LOADIMP_LDO_VCOSXR;
extern const struct LMS7Parameter EN_LOADIMP_LDO_VCOSXT;
extern const struct LMS7Parameter EN_LDO_AFE;
extern const struct LMS7Parameter EN_LDO_CPGN;
extern const struct LMS7Parameter EN_LDO_CPSXR;
extern const struct LMS7Parameter EN_LDO_TLOB;
extern const struct LMS7Parameter EN_LDO_TPAD;
extern const struct LMS7Parameter EN_LDO_TXBUF;
extern const struct LMS7Parameter EN_LDO_VCOGN;
extern const struct LMS7Parameter EN_LDO_VCOSXR;
extern const struct LMS7Parameter EN_LDO_VCOSXT;
extern const struct LMS7Parameter EN_LDO_CPSXT;
extern const struct LMS7Parameter EN_LOADIMP_LDO_CPSXT;
extern const struct LMS7Parameter EN_LOADIMP_LDO_DIG;
extern const struct LMS7Parameter EN_LOADIMP_LDO_DIGGN;
extern const struct LMS7Parameter EN_LOADIMP_LDO_DIGSXR;
extern const struct LMS7Parameter EN_LOADIMP_LDO_DIGSXT;
extern const struct LMS7Parameter EN_LOADIMP_LDO_DIVGN;
extern const struct LMS7Parameter EN_LOADIMP_LDO_DIVSXR;
extern const struct LMS7Parameter EN_LOADIMP_LDO_DIVSXT;
extern const struct LMS7Parameter EN_LOADIMP_LDO_LNA12;
extern const struct LMS7Parameter EN_LOADIMP_LDO_LNA14;
extern const struct LMS7Parameter EN_LOADIMP_LDO_MXRFE;
extern const struct LMS7Parameter EN_LOADIMP_LDO_RBB;
extern const struct LMS7Parameter EN_LOADIMP_LDO_RXBUF;
extern const struct LMS7Parameter EN_LOADIMP_LDO_TBB;
extern const struct LMS7Parameter EN_LOADIMP_LDO_TIA12;
extern const struct LMS7Parameter EN_LOADIMP_LDO_TIA14;
extern const struct LMS7Parameter BYP_LDO_TBB;
extern const struct LMS7Parameter BYP_LDO_TIA12;
extern const struct LMS7Parameter BYP_LDO_TIA14;
extern const struct LMS7Parameter BYP_LDO_TLOB;
extern const struct LMS7Parameter BYP_LDO_TPAD;
extern const struct LMS7Parameter BYP_LDO_TXBUF;
extern const struct LMS7Parameter BYP_LDO_VCOGN;
extern const struct LMS7Parameter BYP_LDO_VCOSXR;
extern const struct LMS7Parameter BYP_LDO_VCOSXT;
extern const struct LMS7Parameter EN_LOADIMP_LDO_AFE;
extern const struct LMS7Parameter EN_LOADIMP_LDO_CPGN;
extern const struct LMS7Parameter EN_LOADIMP_LDO_CPSXR;
extern const struct LMS7Parameter BYP_LDO_AFE;
extern const struct LMS7Parameter BYP_LDO_CPGN;
extern const struct LMS7Parameter BYP_LDO_CPSXR;
extern const struct LMS7Parameter BYP_LDO_CPSXT;
extern const struct LMS7Parameter BYP_LDO_DIG;
extern const struct LMS7Parameter BYP_LDO_DIGGN;
extern const struct LMS7Parameter BYP_LDO_DIGSXR;
extern const struct LMS7Parameter BYP_LDO_DIGSXT;
extern const struct LMS7Parameter BYP_LDO_DIVGN;
extern const struct LMS7Parameter BYP_LDO_DIVSXR;
extern const struct LMS7Parameter BYP_LDO_DIVSXT;
extern const struct LMS7Parameter BYP_LDO_LNA12;
extern const struct LMS7Parameter BYP_LDO_LNA14;
extern const struct LMS7Parameter BYP_LDO_MXRFE;
extern const struct LMS7Parameter BYP_LDO_RBB;
extern const struct LMS7Parameter BYP_LDO_RXBUF;
extern const struct LMS7Parameter SPDUP_LDO_DIVSXR;
extern const struct LMS7Parameter SPDUP_LDO_DIVSXT;
extern const struct LMS7Parameter SPDUP_LDO_LNA12;
extern const struct LMS7Parameter SPDUP_LDO_LNA14;
extern const struct LMS7Parameter SPDUP_LDO_MXRFE;
extern const struct LMS7Parameter SPDUP_LDO_RBB;
extern const struct LMS7Parameter SPDUP_LDO_RXBUF;
extern const struct LMS7Parameter SPDUP_LDO_TBB;
extern const struct LMS7Parameter SPDUP_LDO_TIA12;
extern const struct LMS7Parameter SPDUP_LDO_TIA14;
extern const struct LMS7Parameter SPDUP_LDO_TLOB;
extern const struct LMS7Parameter SPDUP_LDO_TPAD;
extern const struct LMS7Parameter SPDUP_LDO_TXBUF;
extern const struct LMS7Parameter SPDUP_LDO_VCOGN;
extern const struct LMS7Parameter SPDUP_LDO_VCOSXR;
extern const struct LMS7Parameter SPDUP_LDO_VCOSXT;
extern const struct LMS7Parameter SPDUP_LDO_AFE;
extern const struct LMS7Parameter SPDUP_LDO_CPGN;
extern const struct LMS7Parameter SPDUP_LDO_CPSXR;
extern const struct LMS7Parameter SPDUP_LDO_CPSXT;
extern const struct LMS7Parameter SPDUP_LDO_DIG;
extern const struct LMS7Parameter SPDUP_LDO_DIGGN;
extern const struct LMS7Parameter SPDUP_LDO_DIGSXR;
extern const struct LMS7Parameter SPDUP_LDO_DIGSXT;
extern const struct LMS7Parameter SPDUP_LDO_DIVGN;
extern const struct LMS7Parameter RDIV_VCOSXR;
extern const struct LMS7Parameter RDIV_VCOSXT;
extern const struct LMS7Parameter RDIV_TXBUF;
extern const struct LMS7Parameter RDIV_VCOGN;
extern const struct LMS7Parameter RDIV_TLOB;
extern const struct LMS7Parameter RDIV_TPAD;
extern const struct LMS7Parameter RDIV_TIA12;
extern const struct LMS7Parameter RDIV_TIA14;
extern const struct LMS7Parameter RDIV_RXBUF;
extern const struct LMS7Parameter RDIV_TBB;
extern const struct LMS7Parameter RDIV_MXRFE;
extern const struct LMS7Parameter RDIV_RBB;
extern const struct LMS7Parameter RDIV_LNA12;
extern const struct LMS7Parameter RDIV_LNA14;
extern const struct LMS7Parameter RDIV_DIVSXR;
extern const struct LMS7Parameter RDIV_DIVSXT;
extern const struct LMS7Parameter RDIV_DIGSXT;
extern const struct LMS7Parameter RDIV_DIVGN;
extern const struct LMS7Parameter RDIV_DIGGN;
extern const struct LMS7Parameter RDIV_DIGSXR;
extern const struct LMS7Parameter RDIV_CPSXT;
extern const struct LMS7Parameter RDIV_DIG;
extern const struct LMS7Parameter RDIV_CPGN;
extern const struct LMS7Parameter RDIV_CPSXR;
extern const struct LMS7Parameter RDIV_SPIBUF;
extern const struct LMS7Parameter RDIV_AFE;
extern const struct LMS7Parameter SPDUP_LDO_SPIBUF;
extern const struct LMS7Parameter SPDUP_LDO_DIGIp2;
extern const struct LMS7Parameter SPDUP_LDO_DIGIp1;
extern const struct LMS7Parameter BYP_LDO_SPIBUF;
extern const struct LMS7Parameter BYP_LDO_DIGIp2;
extern const struct LMS7Parameter BYP_LDO_DIGIp1;
extern const struct LMS7Parameter EN_LOADIMP_LDO_SPIBUF;
extern const struct LMS7Parameter EN_LOADIMP_LDO_DIGIp2;
extern const struct LMS7Parameter EN_LOADIMP_LDO_DIGIp1;
extern const struct LMS7Parameter PD_LDO_SPIBUF;
extern const struct LMS7Parameter PD_LDO_DIGIp2;
extern const struct LMS7Parameter PD_LDO_DIGIp1;
extern const struct LMS7Parameter EN_G_LDOP;
extern const struct LMS7Parameter RDIV_DIGIp2;
extern const struct LMS7Parameter RDIV_DIGIp1;
extern const struct LMS7Parameter BSIGT;
extern const struct LMS7Parameter BSTATE;
extern const struct LMS7Parameter EN_SDM_TSTO_SXT;
extern const struct LMS7Parameter EN_SDM_TSTO_SXR;
extern const struct LMS7Parameter EN_SDM_TSTO_CGEN;
extern const struct LMS7Parameter BENC;
extern const struct LMS7Parameter BENR;
extern const struct LMS7Parameter BENT;
extern const struct LMS7Parameter BSTART;
extern const struct LMS7Parameter BSIGR;
extern const struct LMS7Parameter BSIGC;
extern const struct LMS7Parameter CDS_MCLK2;
extern const struct LMS7Parameter CDS_MCLK1;
extern const struct LMS7Parameter CDSN_TXBTSP;
extern const struct LMS7Parameter CDSN_TXATSP;
extern const struct LMS7Parameter CDSN_RXBTSP;
extern const struct LMS7Parameter CDSN_RXATSP;
extern const struct LMS7Parameter CDSN_TXBLML;
extern const struct LMS7Parameter CDSN_TXALML;
extern const struct LMS7Parameter CDSN_RXBLML;
extern const struct LMS7Parameter CDSN_RXALML;
extern const struct LMS7Parameter CDSN_MCLK2;
extern const struct LMS7Parameter CDSN_MCLK1;
extern const struct LMS7Parameter CDS_TXBTSP;
extern const struct LMS7Parameter CDS_TXATSP;
extern const struct LMS7Parameter CDS_RXBTSP;
extern const struct LMS7Parameter CDS_RXATSP;
extern const struct LMS7Parameter CDS_TXBLML;
extern const struct LMS7Parameter CDS_TXALML;
extern const struct LMS7Parameter CDS_RXBLML;
extern const struct LMS7Parameter CDS_RXALML;
extern const struct LMS7Parameter EN_LOWBWLOMX_TMX_TRF;
extern const struct LMS7Parameter EN_NEXTTX_TRF;
extern const struct LMS7Parameter EN_AMPHF_PDET_TRF;
extern const struct LMS7Parameter LOADR_PDET_TRF;
extern const struct LMS7Parameter PD_PDET_TRF;
extern const struct LMS7Parameter PD_TLOBUF_TRF;
extern const struct LMS7Parameter PD_TXPAD_TRF;
extern const struct LMS7Parameter EN_G_TRF;
extern const struct LMS7Parameter F_TXPAD_TRF;
extern const struct LMS7Parameter L_LOOPB_TXPAD_TRF;
extern const struct LMS7Parameter LOSS_LIN_TXPAD_TRF;
extern const struct LMS7Parameter LOSS_MAIN_TXPAD_TRF;
extern const struct LMS7Parameter EN_LOOPB_TXPAD_TRF;
extern const struct LMS7Parameter GCAS_GNDREF_TXPAD_TRF;
extern const struct LMS7Parameter ICT_LIN_TXPAD_TRF;
extern const struct LMS7Parameter ICT_MAIN_TXPAD_TRF;
extern const struct LMS7Parameter VGCAS_TXPAD_TRF;
extern const struct LMS7Parameter SEL_BAND1_TRF;
extern const struct LMS7Parameter SEL_BAND2_TRF;
extern const struct LMS7Parameter LOBIASN_TXM_TRF;
extern const struct LMS7Parameter LOBIASP_TXX_TRF;
extern const struct LMS7Parameter CDC_I_TRF;
extern const struct LMS7Parameter CDC_Q_TRF;
extern const struct LMS7Parameter STATPULSE_TBB;
extern const struct LMS7Parameter LOOPB_TBB;
extern const struct LMS7Parameter PD_LPFH_TBB;
extern const struct LMS7Parameter PD_LPFIAMP_TBB;
extern const struct LMS7Parameter PD_LPFLAD_TBB;
extern const struct LMS7Parameter PD_LPFS5_TBB;
extern const struct LMS7Parameter EN_G_TBB;
extern const struct LMS7Parameter ICT_LPFS5_F_TBB;
extern const struct LMS7Parameter ICT_LPFS5_PT_TBB;
extern const struct LMS7Parameter ICT_LPF_H_PT_TBB;
extern const struct LMS7Parameter ICT_LPFH_F_TBB;
extern const struct LMS7Parameter ICT_LPFLAD_F_TBB;
extern const struct LMS7Parameter ICT_LPFLAD_PT_TBB;
extern const struct LMS7Parameter CG_IAMP_TBB;
extern const struct LMS7Parameter ICT_IAMP_FRP_TBB;
extern const struct LMS7Parameter ICT_IAMP_GG_FRP_TBB;
extern const struct LMS7Parameter RCAL_LPFH_TBB;
extern const struct LMS7Parameter RCAL_LPFLAD_TBB;
extern const struct LMS7Parameter TSTIN_TBB;
extern const struct LMS7Parameter BYPLADDER_TBB;
extern const struct LMS7Parameter CCAL_LPFLAD_TBB;
extern const struct LMS7Parameter RCAL_LPFS5_TBB;
extern const struct LMS7Parameter CDC_I_RFE;
extern const struct LMS7Parameter CDC_Q_RFE;
extern const struct LMS7Parameter PD_LNA_RFE;
extern const struct LMS7Parameter PD_RLOOPB_1_RFE;
extern const struct LMS7Parameter PD_RLOOPB_2_RFE;
extern const struct LMS7Parameter PD_MXLOBUF_RFE;
extern const struct LMS7Parameter PD_QGEN_RFE;
extern const struct LMS7Parameter PD_RSSI_RFE;
extern const struct LMS7Parameter PD_TIA_RFE;
extern const struct LMS7Parameter EN_G_RFE;
extern const struct LMS7Parameter SEL_PATH_RFE;
extern const struct LMS7Parameter EN_DCOFF_RXFE_RFE;
extern const struct LMS7Parameter EN_INSHSW_LB1_RFE;
extern const struct LMS7Parameter EN_INSHSW_LB2_RFE;
extern const struct LMS7Parameter EN_INSHSW_L_RFE;
extern const struct LMS7Parameter EN_INSHSW_W_RFE;
extern const struct LMS7Parameter EN_NEXTRX_RFE;
extern const struct LMS7Parameter DCOFFI_RFE;
extern const struct LMS7Parameter DCOFFQ_RFE;
extern const struct LMS7Parameter ICT_LOOPB_RFE;
extern const struct LMS7Parameter ICT_TIAMAIN_RFE;
extern const struct LMS7Parameter ICT_TIAOUT_RFE;
extern const struct LMS7Parameter ICT_LNACMO_RFE;
extern const struct LMS7Parameter ICT_LNA_RFE;
extern const struct LMS7Parameter ICT_LODC_RFE;
extern const struct LMS7Parameter CAP_RXMXO_RFE;
extern const struct LMS7Parameter CGSIN_LNA_RFE;
extern const struct LMS7Parameter CCOMP_TIA_RFE;
extern const struct LMS7Parameter CFB_TIA_RFE;
extern const struct LMS7Parameter G_LNA_RFE;
extern const struct LMS7Parameter G_RXLOOPB_RFE;
extern const struct LMS7Parameter G_TIA_RFE;
extern const struct LMS7Parameter RCOMP_TIA_RFE;
extern const struct LMS7Parameter RFB_TIA_RFE;
extern const struct LMS7Parameter EN_LB_LPFH_RBB;
extern const struct LMS7Parameter EN_LB_LPFL_RBB;
extern const struct LMS7Parameter PD_LPFH_RBB;
extern const struct LMS7Parameter PD_LPFL_RBB;
extern const struct LMS7Parameter PD_PGA_RBB;
extern const struct LMS7Parameter EN_G_RBB;
extern const struct LMS7Parameter R_CTL_LPF_RBB;
extern const struct LMS7Parameter RCC_CTL_LPFH_RBB;
extern const struct LMS7Parameter C_CTL_LPFH_RBB;
extern const struct LMS7Parameter RCC_CTL_LPFL_RBB;
extern const struct LMS7Parameter C_CTL_LPFL_RBB;
extern const struct LMS7Parameter INPUT_CTL_PGA_RBB;
extern const struct LMS7Parameter ICT_LPF_IN_RBB;
extern const struct LMS7Parameter ICT_LPF_OUT_RBB;
extern const struct LMS7Parameter OSW_PGA_RBB;
extern const struct LMS7Parameter ICT_PGA_OUT_RBB;
extern const struct LMS7Parameter ICT_PGA_IN_RBB;
extern const struct LMS7Parameter G_PGA_RBB;
extern const struct LMS7Parameter RCC_CTL_PGA_RBB;
extern const struct LMS7Parameter C_CTL_PGA_RBB;
extern const struct LMS7Parameter RESET_N;
extern const struct LMS7Parameter SPDUP_VCO;
extern const struct LMS7Parameter BYPLDO_VCO;
extern const struct LMS7Parameter EN_COARSEPLL;
extern const struct LMS7Parameter CURLIM_VCO;
extern const struct LMS7Parameter EN_DIV2_DIVPROG;
extern const struct LMS7Parameter EN_INTONLY_SDM;
extern const struct LMS7Parameter EN_SDM_CLK;
extern const struct LMS7Parameter PD_FBDIV;
extern const struct LMS7Parameter PD_LOCH_T2RBUF;
extern const struct LMS7Parameter PD_CP;
extern const struct LMS7Parameter PD_FDIV;
extern const struct LMS7Parameter PD_SDM;
extern const struct LMS7Parameter PD_VCO_COMP;
extern const struct LMS7Parameter PD_VCO;
extern const struct LMS7Parameter EN_G;
extern const struct LMS7Parameter FRAC_SDM_LSB;
extern const struct LMS7Parameter INT_SDM;
extern const struct LMS7Parameter FRAC_SDM_MSB;
extern const struct LMS7Parameter PW_DIV2_LOCH;
extern const struct LMS7Parameter PW_DIV4_LOCH;
extern const struct LMS7Parameter DIV_LOCH;
extern const struct LMS7Parameter TST_SX;
extern const struct LMS7Parameter SEL_SDMCLK;
extern const struct LMS7Parameter SX_DITHER_EN;
extern const struct LMS7Parameter REV_SDMCLK;
extern const struct LMS7Parameter VDIV_VCO;
extern const struct LMS7Parameter ICT_VCO;
extern const struct LMS7Parameter RSEL_LDO_VCO;
extern const struct LMS7Parameter CSW_VCO;
extern const struct LMS7Parameter SEL_VCO;
extern const struct LMS7Parameter COARSE_START;
extern const struct LMS7Parameter REVPH_PFD;
extern const struct LMS7Parameter IOFFSET_CP;
extern const struct LMS7Parameter IPULSE_CP;
extern const struct LMS7Parameter COARSE_STEPDONE;
extern const struct LMS7Parameter COARSEPLL_COMPO;
extern const struct LMS7Parameter VCO_CMPHO;
extern const struct LMS7Parameter VCO_CMPLO;
extern const struct LMS7Parameter CP2_PLL;
extern const struct LMS7Parameter CP3_PLL;
extern const struct LMS7Parameter CZ;
extern const struct LMS7Parameter EN_DIR_SXRSXT;
extern const struct LMS7Parameter EN_DIR_RBB;
extern const struct LMS7Parameter EN_DIR_RFE;
extern const struct LMS7Parameter EN_DIR_TBB;
extern const struct LMS7Parameter EN_DIR_TRF;
extern const struct LMS7Parameter TSGFC_TXTSP;
extern const struct LMS7Parameter TSGFCW_TXTSP;
extern const struct LMS7Parameter TSGDCLDQ_TXTSP;
extern const struct LMS7Parameter TSGDCLDI_TXTSP;
extern const struct LMS7Parameter TSGSWAPIQ_TXTSP;
extern const struct LMS7Parameter TSGMODE_TXTSP;
extern const struct LMS7Parameter INSEL_TXTSP;
extern const struct LMS7Parameter BSTART_TXTSP;
extern const struct LMS7Parameter EN_TXTSP;
extern const struct LMS7Parameter GCORRQ_TXTSP;
extern const struct LMS7Parameter GCORRI_TXTSP;
extern const struct LMS7Parameter HBI_OVR_TXTSP;
extern const struct LMS7Parameter IQCORR_TXTSP;
extern const struct LMS7Parameter DCCORRI_TXTSP;
extern const struct LMS7Parameter DCCORRQ_TXTSP;
extern const struct LMS7Parameter GFIR1_L_TXTSP;
extern const struct LMS7Parameter GFIR1_N_TXTSP;
extern const struct LMS7Parameter GFIR2_L_TXTSP;
extern const struct LMS7Parameter GFIR2_N_TXTSP;
extern const struct LMS7Parameter GFIR3_L_TXTSP;
extern const struct LMS7Parameter GFIR3_N_TXTSP;
extern const struct LMS7Parameter CMIX_GAIN_TXTSP;
extern const struct LMS7Parameter CMIX_SC_TXTSP;
extern const struct LMS7Parameter CMIX_BYP_TXTSP;
extern const struct LMS7Parameter ISINC_BYP_TXTSP;
extern const struct LMS7Parameter GFIR3_BYP_TXTSP;
extern const struct LMS7Parameter GFIR2_BYP_TXTSP;
extern const struct LMS7Parameter GFIR1_BYP_TXTSP;
extern const struct LMS7Parameter DC_BYP_TXTSP;
extern const struct LMS7Parameter GC_BYP_TXTSP;
extern const struct LMS7Parameter PH_BYP_TXTSP;
extern const struct LMS7Parameter BSIGI_TXTSP;
extern const struct LMS7Parameter BSTATE_TXTSP;
extern const struct LMS7Parameter BSIGQ_TXTSP;
extern const struct LMS7Parameter DC_REG_TXTSP;
extern const struct LMS7Parameter DTHBIT_TX;
extern const struct LMS7Parameter SEL_TX;
extern const struct LMS7Parameter MODE_TX;
extern const struct LMS7Parameter CAPTURE;
extern const struct LMS7Parameter CAPSEL;
extern const struct LMS7Parameter CAPSEL_ADC;
extern const struct LMS7Parameter TSGFC_RXTSP;
extern const struct LMS7Parameter TSGFCW_RXTSP;
extern const struct LMS7Parameter TSGDCLDQ_RXTSP;
extern const struct LMS7Parameter TSGDCLDI_RXTSP;
extern const struct LMS7Parameter TSGSWAPIQ_RXTSP;
extern const struct LMS7Parameter TSGMODE_RXTSP;
extern const struct LMS7Parameter INSEL_RXTSP;
extern const struct LMS7Parameter BSTART_RXTSP;
extern const struct LMS7Parameter EN_RXTSP;
extern const struct LMS7Parameter GCORRQ_RXTSP;
extern const struct LMS7Parameter GCORRI_RXTSP;
extern const struct LMS7Parameter HBD_OVR_RXTSP;
extern const struct LMS7Parameter IQCORR_RXTSP;
extern const struct LMS7Parameter HBD_DLY;
extern const struct LMS7Parameter DCLOOP_BYP;
extern const struct LMS7Parameter DCCORR_AVG_RXTSP;
extern const struct LMS7Parameter GFIR1_L_RXTSP;
extern const struct LMS7Parameter GFIR1_N_RXTSP;
extern const struct LMS7Parameter GFIR2_L_RXTSP;
extern const struct LMS7Parameter GFIR2_N_RXTSP;
extern const struct LMS7Parameter GFIR3_L_RXTSP;
extern const struct LMS7Parameter GFIR3_N_RXTSP;
extern const struct LMS7Parameter AGC_K_RXTSP;
extern const struct LMS7Parameter AGC_ADESIRED_RXTSP;
extern const struct LMS7Parameter RSSI_MODE;
extern const struct LMS7Parameter AGC_MODE_RXTSP;
extern const struct LMS7Parameter AGC_AVG_RXTSP;
extern const struct LMS7Parameter DC_REG_RXTSP;
extern const struct LMS7Parameter CMIX_GAIN_RXTSP;
extern const struct LMS7Parameter CMIX_SC_RXTSP;
extern const struct LMS7Parameter CMIX_BYP_RXTSP;
extern const struct LMS7Parameter AGC_BYP_RXTSP;
extern const struct LMS7Parameter GFIR3_BYP_RXTSP;
extern const struct LMS7Parameter GFIR2_BYP_RXTSP;
extern const struct LMS7Parameter GFIR1_BYP_RXTSP;
extern const struct LMS7Parameter DC_BYP_RXTSP;
extern const struct LMS7Parameter GC_BYP_RXTSP;
extern const struct LMS7Parameter PH_BYP_RXTSP;
extern const struct LMS7Parameter CAPD;
extern const struct LMS7Parameter DTHBIT_RX;
extern const struct LMS7Parameter SEL_RX;
extern const struct LMS7Parameter MODE_RX;
#endif
/**
@file LMS7002M_statuses.cpp
@author Lime Microsystems (www.limemicro.com)
*/
#include "LMS7002M_statuses.h"
const char* undefinedStatusStr = "undefined status";
const char* liblms7_status2string(liblms7_status status)
{
if (status >= 0 && status < LIBLMS7_STATUS_COUNT)
return liblms7_status_strings[status];
else
return undefinedStatusStr;
}
/**
@file LMS7002M_statuses.h
@author Lime Microsystems (www.limemicro.com)
@brief LMS7002M control library statuses enumerations
*/
#ifndef LMS7API_STATUSES_H
#define LMS7API_STATUSES_H
const char liblms7_status_strings[][64] =
{
"success",
"failure",
"index out of range",
"too many values",
"connection manager is NULL",
"port not connected",
"frequency out of range",
"cannot deliver frequency",
"VCO is powered down",
"Bad SEL_PATH_RFE",
"Band not selected",
"file not found",
"file invalid format",
};
enum liblms7_status
{
LIBLMS7_SUCCESS = 0,
LIBLMS7_FAILURE,
LIBLMS7_INDEX_OUT_OF_RANGE,
LIBLMS7_TOO_MANY_VALUES,
LIBLMS7_NO_CONNECTION_MANAGER,
LIBLMS7_NOT_CONNECTED,
LIBLMS7_FREQUENCY_OUT_OF_RANGE,
LIBLMS7_CANNOT_DELIVER_FREQUENCY,
LIBLMS7_VCO_IS_POWERED_DOWN,
LIBLMS7_BAD_SEL_PATH,
LIBLMS7_BAND_NOT_SELECTED,
LIBLMS7_FILE_NOT_FOUND,
LIBLMS7_FILE_INVALID_FORMAT,
LIBLMS7_STATUS_COUNT
};
const char* liblms7_status2string(liblms7_status status);
#endif
/**
@file ConnectionCOM.cpp
@author Lime Microsystems (www.limemicro.com)
@brief Implementation of communications through COM port
*/
#include "ConnectionCOM.h"
#include "string.h"
#ifdef __unix__
#include <fstream>
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <iostream>
#include <stdio.h>
#endif // LINUX
const int COM_RETRY_INTERVAL = 20; //ms
const int COM_TOTAL_TIMEOUT = 300; //ms
/** @brief Initializes com port connection
*/
ConnectionCOM::ConnectionCOM()
{
currentDeviceIndex = -1;
connected = false;
comPortList.clear();
m_deviceNames.clear();
m_connectionType = COM_PORT;
#ifndef __unix__
hComm = INVALID_HANDLE_VALUE;
#else
hComm = -1;
#endif
comBaudrate = 9600;
}
/** @brief When object is destroyed it closes it's opened COM port
*/
ConnectionCOM::~ConnectionCOM()
{
Close();
}
/** @brief Opens connection to first found chip
@return 0-success
*/
IConnection::DeviceStatus ConnectionCOM::Open()
{
comPortList.clear();
if(comPortList.size() == 0)
FindAllComPorts();
m_deviceNames.clear();
if(m_deviceNames.size() == 0)
RefreshDeviceList();
for(unsigned int i=0; i<m_deviceNames.size(); i++)
{
if( Open(i) == SUCCESS)
{
currentDeviceIndex = i;
return SUCCESS;
}
}
return FAILURE;
}
/** @brief Opens connection to selected chip
@param index chip index in device list
@return 0-success
*/
IConnection::DeviceStatus ConnectionCOM::Open(unsigned index)
{
unsigned int toOpen = index;
Close();
if(toOpen < m_deviceNames.size() && m_deviceNames.size() > 0 )
{
comPortName = m_deviceNames[toOpen];
IConnection::DeviceStatus status = Open(comPortName.c_str(), comBaudrate);
if( status == SUCCESS )
currentDeviceIndex = toOpen;
return status;
}
return FAILURE;
}
/** @brief Closes connection to chip
*/
void ConnectionCOM::Close()
{
connected = false;
currentDeviceIndex = -1;
#ifndef __unix__
if (hComm != INVALID_HANDLE_VALUE)
{
SetCommTimeouts(hComm, &m_ctmoOld);
CloseHandle(hComm);
}
hComm = INVALID_HANDLE_VALUE;
#else
if( hComm >= 0)
{
close(hComm);
}
hComm = -1;
#endif
}
/** @brief Returns whether chip is connected
@return chip is connected
*/
bool ConnectionCOM::IsOpen()
{
#ifndef __unix__
if (hComm != INVALID_HANDLE_VALUE && TestConnectivity() )
return true;
#else
if( hComm != -1 && TestConnectivity() )
return true;
#endif
return false;
}
int ConnectionCOM::GetOpenedIndex()
{
return currentDeviceIndex;
}
/** @brief Sends data through COM port
@param buffer data buffer to send
@param length size of data buffer
@param timeout_ms timeout limit for operation in milliseconds
@return Number of bytes sent
*/
int ConnectionCOM::Write(const unsigned char *buffer, int length, int timeout_ms)
{
if(timeout_ms == 0)
{
timeout_ms = COM_TOTAL_TIMEOUT;
}
int retryCount = 0;
const int maxRetries = (timeout_ms/COM_RETRY_INTERVAL) > 1 ? (timeout_ms/COM_RETRY_INTERVAL) : 1;
bool status = false;
#ifndef __unix__
unsigned long bytesWriten = 0;
m_osWOverlap.InternalHigh = 0;
for(int i = 0; i<maxRetries && status == false; ++i)
{
if (!WriteFile(hComm, buffer, length , &bytesWriten, NULL))
{
status = false;
}
else
status = true;
++retryCount;
}
#else
long bytesWriten = 0;
for(int i = 0; i<maxRetries && bytesWriten == 0; ++i)
{
bytesWriten = write(hComm, buffer, length);
if(bytesWriten <= 0)
{
// if(bytesWriten < 0)
// MessageLog::getInstance()->write("COM PORT: error writing data\n", LOG_ERROR);
// if(bytesWriten == 0)
// MessageLog::getInstance()->write("COM PORT: data bytes sent 0\n", LOG_WARNING);
status = false;
}
else
status = true;
++retryCount;
}
#endif
if(bytesWriten == length)
status = true;
return bytesWriten;
}
/** @brief Reads data from COM port
@param buffer pointer to data buffer for receiving
@param length number of bytes to read
@param timeout_ms timeout limit for operation in milliseconds
@return Number of bytes received
*/
int ConnectionCOM::Read(unsigned char *buffer, int length, int timeout_ms)
{
if(timeout_ms == 0)
{
timeout_ms = COM_TOTAL_TIMEOUT;
}
int retryCount = 0;
const int maxRetries = (timeout_ms/COM_RETRY_INTERVAL) > 1 ? (timeout_ms/COM_RETRY_INTERVAL) : 1;
bool status = false;
memset(buffer, 0, length);
long bytesReaded = 0;
unsigned long totalBytesReaded = 0;
char cRawData[COM_BUFFER_LENGTH];
unsigned long bytesToRead = length;
memset(cRawData, '\0', sizeof(cRawData[0])*COM_BUFFER_LENGTH);
for(int i=0; i<maxRetries && status == false; ++i)
{
memset(cRawData, '\0', sizeof(cRawData[0])*COM_BUFFER_LENGTH);
#ifndef __unix__
DWORD bytesReceived = 0;
if ( !ReadFile(hComm, cRawData, bytesToRead, &bytesReceived, NULL) )
{
status = false;
}
bytesReaded = bytesReceived;
#else
bytesReaded = read(hComm, cRawData, bytesToRead);
if(bytesReaded <= 0)
{
// if(bytesReaded < 0)
// MessageLog::getInstance()->write("COM PORT: error reading data\n", LOG_ERROR);
// if(bytesReaded == 0)
// MessageLog::getInstance()->write("COM PORT: reading 0 bytes\n", LOG_WARNING);
status = false;
}
#endif
retryCount++;
for(int j=0; j<bytesReaded; ++j)
{
buffer[totalBytesReaded+j] = cRawData[j];
}
totalBytesReaded += bytesReaded;
if(totalBytesReaded == bytesToRead)
status = true;
}
// ss << " read(" << totalBytesReaded << "): ";
// for(unsigned int i=0; i<64; ++i)
// ss << int2hex(buffer[i], 1) << " ";
// ss << " - retries: " << retryCount-1 << endl;
//MessageLog::getInstance()->write(ss.str(), LOG_DATA);
// if(retryCount == maxRetries)
// MessageLog::getInstance()->write("COM PORT: read data timeout\n", LOG_WARNING);
//
// if(totalBytesReaded > length)
// MessageLog::getInstance()->write("COM PORT: read data corrupted, received length > requested length\n", LOG_ERROR);
return totalBytesReaded;
}
/** @brief Searches for available COM ports and adds them to list
*/
void ConnectionCOM::FindAllComPorts()
{
Close();
comPortList.clear();
#ifndef __unix__
HKEY hSERIALCOMM;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hSERIALCOMM) == ERROR_SUCCESS)
{
// Get the max value name and max value lengths
DWORD dwMaxValueNameLen;
DWORD dwMaxValueLen;
DWORD dwQueryInfo = RegQueryInfoKey(hSERIALCOMM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL);
if (dwQueryInfo == ERROR_SUCCESS)
{
DWORD dwMaxValueNameSizeInChars = dwMaxValueNameLen + 1;
// Include space for the NULL terminator
DWORD dwMaxValueNameSizeInBytes = dwMaxValueNameSizeInChars*sizeof(TCHAR);
DWORD dwMaxValueDataSizeInChars = dwMaxValueLen / sizeof(TCHAR) + 1;
// Include space for the NULL terminator
DWORD dwMaxValueDataSizeInBytes = dwMaxValueDataSizeInChars*sizeof(TCHAR);
// Allocate some space for the value name and value data
TCHAR* szValueName = new TCHAR[dwMaxValueNameSizeInChars];
TCHAR* byValue = new TCHAR[dwMaxValueDataSizeInBytes];
if (szValueName && byValue)
{
// Enumerate all the values underneath HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM
DWORD dwIndex = 0;
DWORD dwType;
DWORD dwValueNameSize = dwMaxValueNameSizeInChars;
DWORD dwDataSize = dwMaxValueDataSizeInBytes;
memset(szValueName, 0, dwMaxValueNameSizeInBytes);
memset(byValue, 0, dwMaxValueDataSizeInBytes);
LONG nEnum = RegEnumValue(hSERIALCOMM, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, (LPBYTE)byValue, &dwDataSize);
while (nEnum == ERROR_SUCCESS)
{
// If the value is of the correct type, then add it to the array
if (dwType == REG_SZ)
{
char portname[512];
TCHAR* szPort = byValue;
int nUserNameLenUnicode = lstrlen( szPort ); // Convert all UNICODE characters
int nUserNameLen = WideCharToMultiByte( CP_ACP, // ANSI Code Page
0, // No special handling of unmapped chars
(LPCWSTR)szPort, // wide-character string to be converted
nUserNameLenUnicode,
NULL, 0, // No output buffer since we are calculating length
NULL, NULL ); // Unrepresented char replacement - Use Default
TCHAR* pszUserName = new TCHAR[ nUserNameLen ]; // nUserNameLen includes the NULL character
WideCharToMultiByte( CP_ACP, // ANSI Code Page
0, // No special handling of unmapped chars
(LPCWSTR)szPort, // wide-character string to be converted
nUserNameLenUnicode,
portname,
nUserNameLen,
NULL, NULL ); // Unrepresented char replacement - Use Default
portname[nUserNameLen] = 0;
#ifdef UNICODE
comPortList.push_back(portname);
#else
comPortList.push_back(szPort);
#endif
}
// Prepare for the next time around
dwValueNameSize = dwMaxValueNameSizeInChars;
dwDataSize = dwMaxValueDataSizeInBytes;
memset(szValueName, 0, dwMaxValueNameSizeInBytes);
memset(byValue, 0, dwMaxValueDataSizeInBytes);
++dwIndex;
nEnum = RegEnumValue(hSERIALCOMM, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, (LPBYTE)byValue, &dwDataSize);
}
}
delete szValueName;
delete byValue;
}
// Close the registry key now that we are finished with it
RegCloseKey(hSERIALCOMM);
if (dwQueryInfo != ERROR_SUCCESS)
SetLastError(dwQueryInfo);
}
#else
char tempBuffer[256];
string result = "";
#warning Currently searching only for ACM connections
system( "ls /dev | grep ttyACM > /tmp/foundSerialPorts.txt");
fstream fin;
fin.open("/tmp/foundSerialPorts.txt", ios::in);
while(!fin.eof())
{
fin.getline(tempBuffer, 256);
result = "/dev/";
result.append(tempBuffer);
if( strlen(tempBuffer) > 3 ) //longer than tty
comPortList.push_back(result);
}
fin.close();
#endif
}
/** @brief Opens COM port
@param comName COM port name
@param baudrate COM port baudrate
@return 0 on success
*/
IConnection::DeviceStatus ConnectionCOM::Open(const char *comName, int baudrate)
{
Close();
if (strlen(comName) == 0)
return FAILURE;
DeviceStatus errorCode = SUCCESS;
#ifndef __unix__
// Initialize Overlap structures
m_osROverlap.Internal = 0;
m_osROverlap.InternalHigh = 0;
m_osROverlap.Offset = 0;
m_osROverlap.OffsetHigh = 0;
m_osROverlap.hEvent = CreateEvent(NULL, false, false, NULL);
m_osWOverlap.Internal = 0;
m_osWOverlap.InternalHigh = 0;
m_osWOverlap.Offset = 0;
m_osWOverlap.OffsetHigh = 0;
m_osWOverlap.hEvent = CreateEvent(NULL, false, false, NULL);
// Initialize DSB structure
memset(&m_dcbCommPort, 0, sizeof(m_dcbCommPort));
m_dcbCommPort.BaudRate = comBaudrate;
m_dcbCommPort.fBinary = 1;
m_dcbCommPort.fParity = 0;
m_dcbCommPort.fOutxCtsFlow = 0;
m_dcbCommPort.fOutxDsrFlow = 0;
m_dcbCommPort.fDtrControl = 0;
m_dcbCommPort.fDsrSensitivity = 0;
m_dcbCommPort.fTXContinueOnXoff = 0;
m_dcbCommPort.fOutX = 0;
m_dcbCommPort.fInX = 0;
m_dcbCommPort.fErrorChar = 0;
m_dcbCommPort.fNull = 0;
m_dcbCommPort.fRtsControl = 0;
m_dcbCommPort.fAbortOnError = 0;
m_dcbCommPort.fDummy2 = 0;
// m_dcbCommPort.wReserved = 0;
m_dcbCommPort.XonLim = 512;
m_dcbCommPort.XoffLim = 512;
m_dcbCommPort.ByteSize = 8;
m_dcbCommPort.Parity = 0;
m_dcbCommPort.StopBits = 0;
//m_dcbCommPort.StopBits = 1;
m_dcbCommPort.XonChar = 17;
m_dcbCommPort.XoffChar = 19;
m_dcbCommPort.ErrorChar = 0;
m_dcbCommPort.EofChar = 26;
m_dcbCommPort.EvtChar = 0;
m_dcbCommPort.wReserved1 = 0;
m_dcbCommPort.DCBlength = sizeof(DCB);
// Initialize Timeout's
m_ctmoNew.ReadIntervalTimeout = 50;
m_ctmoNew.ReadTotalTimeoutMultiplier = 0;
m_ctmoNew.ReadTotalTimeoutConstant = 100; // 1;
m_ctmoNew.WriteTotalTimeoutMultiplier = 0;
m_ctmoNew.WriteTotalTimeoutConstant = 100;
// Open COM port
string stmp;
stmp = "\\\\.\\";
stmp.append(comName);
hComm = CreateFileA(stmp.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hComm != INVALID_HANDLE_VALUE)
{
// Set Events
if (!SetCommMask(hComm, 0))
errorCode = FAILURE;
// Set Timeouts
GetCommTimeouts(hComm, &m_ctmoOld);
if (!SetCommTimeouts(hComm, &m_ctmoNew))
errorCode = FAILURE;
// Set DCB
if (!SetCommState(hComm, &m_dcbCommPort))
errorCode = FAILURE;
}
else
{
errorCode = FAILURE;
};
// Check the results
if (errorCode != 0)
{
//unsigned long err = GetLastError();
CloseHandle(hComm);
hComm = INVALID_HANDLE_VALUE;
return errorCode;
}
else
{
PurgeComm(hComm, PURGE_TXCLEAR | PURGE_RXCLEAR);
return SUCCESS;
}
#else
hComm = open(comName, O_RDWR | O_NOCTTY | O_SYNC);
if(hComm < 0)
{
// printf("%s",strerror(errno));
// MessageLog::getInstance()->write("Connection manager: failed opening COM port\n", LOG_ERROR);
return FAILURE;
}
struct termios tty;
memset(&tty, 0, sizeof(tty));
if( tcgetattr(hComm, &tty) != 0)
{
// MessageLog::getInstance()->write("Connection Manager: error from tcgetattr\n", LOG_ERROR);
return FAILURE;
}
int speed = B9600;
cfsetospeed(&tty, speed);
cfsetispeed(&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
tty.c_iflag &= ~IGNBRK;
tty.c_lflag = 0;
tty.c_oflag = 0;
tty.c_cc[VMIN] = 0; // read non blocking
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_cflag |= (CLOCAL | CREAD);
if(tcsetattr(hComm, TCSANOW, &tty) != 0)
{
// MessageLog::getInstance()->write("Connection manager: error from tcsetattr\n", LOG_ERROR);
return FAILURE;
}
#endif
return SUCCESS;
}
/** @brief Checks if chip is connected to currently open port
@return chip is connected
*/
bool ConnectionCOM::TestConnectivity()
{
//currently set to always return true to show all com ports
return true;
#ifndef __unix__
if (hComm != INVALID_HANDLE_VALUE)
#else
if( hComm >= 0)
#endif
{
// unsigned char out[64];
// unsigned char in[64];
// memset(in, 0, 64);
// out[0] = CMD_GET_INFO;
// SendData(out, 64);
// ReadData(in, 64);
// if(in[0] == CMD_GET_INFO && in[1] == 0x01)
// return true;
// else
// return false;
}
return false;
}
/** @brief Finds all chips connected to com ports
@return number of devices found
*/
int ConnectionCOM::RefreshDeviceList()
{
int wasOpen = -1;
string wasOpenName = "";
if(IsOpen())
{
wasOpen = GetOpenedIndex();
wasOpenName = comPortName;
}
Close();
comPortList.clear();
if(comPortList.size() == 0)
FindAllComPorts();
m_deviceNames.clear();
string comName;
for(unsigned int i=0; i<comPortList.size(); i++)
{
comName = comPortList[i];
#ifndef __unix__
if( Open(comName.c_str(), comBaudrate) == SUCCESS)
{
if( TestConnectivity() ) //if responds add it to device list
m_deviceNames.push_back(comName);
}
Close();
#else
m_deviceNames.push_back(comName);
#endif
}
if(wasOpen != -1)
{
for(unsigned i=0; i<m_deviceNames.size(); ++i)
if(m_deviceNames[i] == wasOpenName)
{
Open(i);
break;
}
}
return m_deviceNames.size();
}
/** @brief Returns found devices names
@return vector of device names
*/
vector<string> ConnectionCOM::GetDeviceNames()
{
return m_deviceNames;
}
/** @brief Purges communication buffers
*/
void ConnectionCOM::ClearComm()
{
#ifndef __unix__
PurgeComm(hComm, PURGE_TXCLEAR|PURGE_RXCLEAR);
#endif
}
/**
@file ConnectionCOM.h
@author Lime Microsystems (www.limemicro.com)
@brief Class for data communications through COM port
*/
#ifndef CONNECTION_COM_PORT_H
#define CONNECTION_COM_PORT_H
#ifndef __unix__
#include "windows.h"
#endif
#include "IConnection.h"
class ConnectionCOM : public IConnection
{
public:
static const int COM_BUFFER_LENGTH = 1024; //max buffer size for data
ConnectionCOM();
~ConnectionCOM();
DeviceStatus Open();
DeviceStatus Open(unsigned i);
void Close();
bool IsOpen();
int GetOpenedIndex();
int Write(const unsigned char *buffer, int length, int timeout_ms = 0);
int Read(unsigned char *buffer, int length, int timeout_ms = 0);
std::vector<std::string> GetDeviceNames();
int RefreshDeviceList();
void ClearComm();
private:
void FindAllComPorts();
DeviceStatus Open(const char *comName, int baudrate);
bool TestConnectivity();
std::string comPortName;
int comBaudrate;
bool connected;
int currentDeviceIndex;
std::vector<std::string> comPortList;
std::vector<std::string> m_deviceNames;
#ifndef __unix__
HANDLE hComm;
COMMTIMEOUTS m_ctmoNew;
COMMTIMEOUTS m_ctmoOld;
OVERLAPPED m_osROverlap;
OVERLAPPED m_osWOverlap;
DCB m_dcbCommPort;
#else
int hComm; //com port file descriptor
#endif
};
#endif
/**
@file ConnectionManager.cpp
@author Lime Microsystems (www.limemicro.com)
@brief Implementation of various connection types to devices
*/
#include "ConnectionManager.h"
#include "ConnectionCOM.h"
#ifdef ENABLE_USB_CONNECTION
#include "ConnectionUSB.h"
#endif
#ifdef ENABLE_SPI_CONNECTION
#include "ConnectionSPI.h"
#endif
#include <sstream>
#include <iomanip>
#include <iostream>
/** @brief Creates connection interfaces
*/
ConnectionManager::ConnectionManager() : activeControlPort(NULL)
{
mLogData = false;
mOpenedDevice = -1;
m_connections[IConnection::COM_PORT] = new ConnectionCOM();
#ifdef ENABLE_USB_CONNECTION
m_connections[IConnection::USB_PORT] = new ConnectionUSB();
#endif
#ifdef ENABLE_SPI_CONNECTION
m_connections[IConnection::SPI_PORT] = new ConnectionSPI();
#endif
}
/** @brief Destroys connection interfaces
*/
ConnectionManager::~ConnectionManager()
{
for (auto iter = m_connections.begin(); iter != m_connections.end(); ++iter)
{
delete iter->second;
}
}
/** @brief Checks if connection to device is opened
@return True if device is connected
*/
bool ConnectionManager::IsOpen()
{
return activeControlPort ? activeControlPort->IsOpen() : false;
}
/** @brief Opens connection to first available device
@return True if connected to device
*/
bool ConnectionManager::Open()
{
return Open(0);
}
/** @brief Connects to selected device
@param i device index from device list
@return 1:Success, 0:failure
*/
int ConnectionManager::Open(unsigned i)
{
if(i >= mDevices.size())
return 0;
if(activeControlPort)
activeControlPort->Close();
switch(mDevices[i].port)
{
case IConnection::COM_PORT:
activeControlPort = m_connections[IConnection::COM_PORT];
break;
case IConnection::USB_PORT:
activeControlPort = m_connections[IConnection::USB_PORT];
break;
case IConnection::SPI_PORT:
activeControlPort = m_connections[IConnection::SPI_PORT];
break;
default:
return 0;
}
mOpenedDevice = -1;
if( i < mDevices.size() )
{
if( activeControlPort->Open(mDevices[i].portIndex) )
{
mOpenedDevice = i;
return 1;
}
}
return 0;
}
/** @brief Closes connection to device
*/
void ConnectionManager::Close()
{
if(activeControlPort)
{
activeControlPort->Close();
//Notify(LMS_Message(MSG_BOARD_DISCONNECTED, "", 0, 0));
}
mOpenedDevice = -1;
}
/** @brief Finds all currently connected devices and forms device list
@return number of devices found
*/
int ConnectionManager::RefreshDeviceList()
{
mDeviceList.clear();
mDevices.clear();
DeviceInfo dev;
for (auto iter = m_connections.begin(); iter != m_connections.end(); ++iter)
{
vector<string> names;
IConnection *port = iter->second;
if(port->RefreshDeviceList() > 0)
{
names = port->GetDeviceNames();
for(unsigned i=0; i<names.size(); ++i)
{
dev.name = names[i];
dev.port = iter->first;
dev.portIndex = i;
mDevices.push_back(dev);
}
}
}
for(unsigned i=0; i<mDevices.size(); ++i)
mDeviceList.push_back(mDevices[i].name);
return mDevices.size();
}
/** @brief Returns currently opened connection index
*/
int ConnectionManager::GetOpenedIndex()
{
return mOpenedDevice;
}
/** @brief Writes given data to currently opened connection
@param buffer outcomming data buffer
@param length bytes to write
@param timeout_ms timeout in milliseconds
@return number of bytes written, on failure negative values
*/
int ConnectionManager::Write(const unsigned char *buffer, const int length, int timeout_ms)
{
if(activeControlPort)
{
int bytesTransferred = activeControlPort->Write(buffer, length, timeout_ms);
#ifndef NDEBUG
if(mLogData)
{
stringstream ss;
ss << "WR(" << (bytesTransferred>=0?bytesTransferred: 0) << "): ";
ss << std::hex << std::setfill('0');
int repeatedZeros = 0;
for(int i=length-1; i>=0; --i)
if(buffer[i] == 0)
++repeatedZeros;
else break;
if(repeatedZeros == 1)
repeatedZeros = 0;
repeatedZeros = repeatedZeros - (repeatedZeros & 0x1);
for(int i=0; i<length-repeatedZeros; ++i)
//casting to short to print as numbers
ss << " " << std::setw(2) << (unsigned short)buffer[i];
if(repeatedZeros > 1)
ss << " (00 x " << std::dec << repeatedZeros << " times)";
cout << ss.str() << endl;
}
#endif
return bytesTransferred;
}
return -1;
}
/** @brief Receives data from currently opened connection
@param buffer incomming data buffer, must be big enough for length bytes
@param length bytes to read
@param timeout_ms timeout in milliseconds
@return number of bytes received
*/
int ConnectionManager::Read(unsigned char *buffer, int length, int timeout_ms)
{
if(activeControlPort)
{
int bytesTransferred = activeControlPort->Read(buffer, length, timeout_ms);
#ifndef NDEBUG
if(mLogData)
{
stringstream ss;
ss << "RD(" << (bytesTransferred>=0?bytesTransferred: 0) << "): ";
ss << std::hex << std::setfill('0');
int repeatedZeros = 0;
for(int i=length-1; i>=0; --i)
if(buffer[i] == 0)
++repeatedZeros;
else break;
if(repeatedZeros == 2)
repeatedZeros = 0;
repeatedZeros = repeatedZeros - (repeatedZeros & 0x1);
for(int i=0; i<length-repeatedZeros; ++i)
//casting to short to print as numbers
ss << " " << std::setw(2) << (unsigned short)buffer[i];
if(repeatedZeros > 2)
ss << " (00 x " << std::dec << repeatedZeros << " times)";
cout << ss.str() << endl;
}
#endif
return bytesTransferred;
}
return -1;
}
int ConnectionManager::WriteStream(const char *buffer, int length)
{
return 0;
}
int ConnectionManager::ReadStream(char *buffer, int length, unsigned int timeout_ms)
{
/*int handle = activeControlPort->BeginDataReading(buffer, length);
activeControlPort->WaitForReading(handle, timeout_ms);
long received = length;
activeControlPort->FinishDataReading(buffer, received, handle);
return received;
*/
long len = length;
int status = activeControlPort->ReadDataBlocking(buffer, len, 0);
return len;
}
int ConnectionManager::BeginDataReading(char *buffer, long length)
{
return activeControlPort->BeginDataReading(buffer, length);
}
/**
@brief Blocks until data is received or set number of milliseconds have passed.
@param contextHandle handle returned by BeginDataReading()
@param timeout_ms number of milliseconds to wait
@return 1-data received, 0-data not received
*/
int ConnectionManager::WaitForReading(int contextHandle, unsigned int timeout_ms)
{
return activeControlPort->WaitForReading(contextHandle, timeout_ms);
}
/**
@brief Finished asynchronous data reading.
@param buffer where to put received data
@param length number of bytes to read, will be changed to actual number of bytes received
@param contextHandle context handle returned by BeginDataReading()
@return received data length
*/
int ConnectionManager::FinishDataReading(char *buffer, long &length, int contextHandle)
{
return activeControlPort->FinishDataReading(buffer, length, contextHandle);
}
/**
@brief Aborts reading operations
*/
void ConnectionManager::AbortReading()
{
activeControlPort->AbortReading();
}
/**
@brief Start asynchronous data sending.
@param buffer data buffer to be sent
@param length number of bytes to send.
@return context handle
*/
int ConnectionManager::BeginDataSending(const char *buffer, long length)
{
return activeControlPort->BeginDataSending(buffer, length);
}
/**
@brief Blocks until data is sent or set number of miliseconds have passed.
@param contextHandle handle returned by BeginDataReading()
@param timeout_ms number of miliseconds to wait
@return 1-data sent, 0-data not sent
*/
int ConnectionManager::WaitForSending(int contextHandle, unsigned int timeout_ms)
{
return activeControlPort->WaitForSending(contextHandle, timeout_ms);
}
/**
@brief Finished asynchronous data sending.
@param buffer where to put received data
@param length number of bytes to send, will be changed to actual number of bytes sent
@param contextHandle context handle returned by BeginDataReading()
@return sent data length
*/
int ConnectionManager::FinishDataSending(const char *buffer, long &length, int contextHandle)
{
return activeControlPort->FinishDataSending(buffer, length, contextHandle);
}
/**
@brief Aborts sending operations
*/
void ConnectionManager::AbortSending()
{
activeControlPort->AbortSending();
}
/**
@file ConnectionManager.h
@author Lime Microsystems (www.limemicro.com)
@brief Class for managing connection to devices
*/
#ifndef LMS_CONNECTION_MANAGER_H
#define LMS_CONNECTION_MANAGER_H
#include "IConnection.h"
#include <map>
class ConnectionManager
{
public:
struct DeviceInfo
{
std::string name;
IConnection::eConnectionType port;
int portIndex;
};
ConnectionManager();
~ConnectionManager();
bool IsOpen();
bool Open();
int Open(unsigned i);
void Close();
int RefreshDeviceList();
int GetOpenedIndex();
std::vector<std::string> GetDeviceList(){return mDeviceList;};
int Write(const unsigned char *buffer, int length, int timeout_ms = 0);
int Read(unsigned char *buffer, int length, int timeout_ms = 0);
int WriteStream(const char *buffer, int length);
int ReadStream(char *buffer, int length, unsigned int timeout_ms);
int BeginDataReading(char *buffer, long length);
int WaitForReading(int contextHandle, unsigned int timeout_ms);
int FinishDataReading(char *buffer, long &length, int contextHandle);
void AbortReading();
int BeginDataSending(const char *buffer, long length);
int WaitForSending(int contextHandle, unsigned int timeout_ms);
int FinishDataSending(const char *buffer, long &length, int contextHandle);
void AbortSending();
protected:
bool mLogData;
/// Port used for communication.
IConnection *activeControlPort;
std::vector<DeviceInfo> mDevices;
std::vector<std::string> mDeviceList;
int mOpenedDevice;
std::map<IConnection::eConnectionType, IConnection*> m_connections;
};
#endif // LMS_CONNECTION_MANAGER_H
/**
@file ConnectionSPI.cpp
@author Lime Microsystems (www.limemicro.com)
@brief Implementation of communications through SPI port
*/
#include "ConnectionSPI.h"
#include "string.h"
#ifdef __unix__
#include <fstream>
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <linux/i2c-dev.h>
#endif // LINUX
#include <iostream>
#include <sstream>
const int ConnectionSPI::cSPI_BUF_SIZE = 128;
const int ConnectionSPI::cSPI_SPEED_HZ = 2000000;
/** @brief Tries to read EEPROM for Novena board signature
@return true if Novena board
*/
bool IsNovenaBoard()
{
#ifdef __unix__
char data[8];
int count = 6;
memset(data, 0, 8);
int addr = 0;
struct i2c_rdwr_ioctl_data session;
struct i2c_msg messages[2];
char set_addr_buf[2];
memset(set_addr_buf, 0, sizeof(set_addr_buf));
memset(data, 0, count);
set_addr_buf[0] = addr>>8;
set_addr_buf[1] = addr;
messages[0].addr = 0xac>>1;
messages[0].flags = 0;
messages[0].len = sizeof(set_addr_buf);
messages[0].buf = set_addr_buf;
messages[1].addr = 0xac>>1;
messages[1].flags = I2C_M_RD;
messages[1].len = count;
messages[1].buf = data;
session.msgs = messages;
session.nmsgs = 2;
bool isNovena = false;
int fd = open("/dev/i2c-2", O_RDWR);
if(fd > 0)
{
if(ioctl(fd, I2C_RDWR, &session) < 0)
{
perror("Unable to communicate with i2c device");
isNovena = false;
}
if(strcmp("Novena", data) == 0)
isNovena = true;
}
close(fd);
return isNovena;
#else
return false;
#endif
}
/** @brief Initializes SPI port and exports needed GPIO
*/
ConnectionSPI::ConnectionSPI()
{
fd = -1;
m_connectionType = SPI_PORT;
std::fstream gpio;
//export SEN pin
gpio.open("/sys/class/gpio/export", ios::out);
if(gpio.good())
{
gpio << 122;
gpio.flush();
gpio.close();
gpio.open("/sys/class/gpio/gpio122/direction", ios::out);
gpio << "out";
gpio.flush();
gpio.close();
m_SEN.open("/sys/class/gpio/gpio122/value", ios::out);
m_SEN<< 1;
m_SEN.flush();
cout << "GPIO122: set to 1" << endl;
}
}
ConnectionSPI::~ConnectionSPI()
{
Close();
m_SEN.close();
}
/** @brief Opens connection to first found chip
@return 0-success
*/
IConnection::DeviceStatus ConnectionSPI::Open()
{
Close();
#ifdef __unix__
fd = open("/dev/spidev2.0", O_RDWR | O_SYNC);
if (fd < 0)
{
//MessageLog::getInstance()->write("SPI PORT: device not found\n", LOG_ERROR);
return IConnection::FAILURE;
}
int mode = SPI_MODE_0;
int ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
printf("can't set spi mode");
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
printf("can't get spi mode");
/*
* bits per word
*/
int bits = 8;
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
printf("can't set bits per word");
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
printf("can't get bits per word");
/*
* max speed hz
*/
int speed = cSPI_SPEED_HZ;
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
printf("can't set max speed hz");
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
printf("can't get max speed hz");
printf("spi mode: 0x%x\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
return IConnection::SUCCESS;
#else
return IConnection::FAILURE;
#endif
}
/** @brief Opens connection to selected chip
@param index chip index in device list
@return 0-success
*/
IConnection::DeviceStatus ConnectionSPI::Open(unsigned index)
{
return Open();
}
/** @brief Closes connection to chip
*/
void ConnectionSPI::Close()
{
#ifdef __unix__
close(fd);
fd = -1;
#endif
}
/** @brief Returns whether chip is connected
@return chip is connected
*/
bool ConnectionSPI::IsOpen()
{
return (fd >= 0);
}
/** @brief Sends data through SPI port
@param buffer data buffer to send
@param length size of data buffer
@param timeout_ms timeout limit for operation in milliseconds
@return Number of bytes sent
*/
int ConnectionSPI::Write(const unsigned char *buffer, int length, int timeout_ms)
{
#ifdef __unix__
if(fd < 0)
return 0;
m_SEN << 0;
m_SEN.flush();
unsigned long bytesWritten = 0;
rxbuf.clear();
int bytesReceived = 0;
char rxbytes[2];
while(bytesWritten < length)
{
int toWrite = length-bytesWritten > cSPI_BUF_SIZE ? cSPI_BUF_SIZE : length-bytesWritten;
for(int i=0; i<toWrite; i+=2)
{
if(buffer[i] < 0x80) //reading
{
write(fd, &buffer[i+bytesWritten], 2);
bytesReceived += read(fd, rxbytes, 2);
rxbuf.push_back(rxbytes[0]);
rxbuf.push_back(rxbytes[1]);
}
else //writing
{
write(fd, &buffer[i+bytesWritten], 4);
i+=2; //data bytes have been written
}
}
bytesWritten += toWrite;
}
m_SEN << 1;
m_SEN.flush();
return bytesWritten;
#else
return 0;
#endif
}
/** @brief Reads data from SPI port
@param buffer pointer to data buffer for receiving
@param length number of bytes to read
@param timeout_ms timeout limit for operation in milliseconds
@return Number of bytes received
*/
int ConnectionSPI::Read(unsigned char *buffer, int length, int timeout_ms)
{
#ifdef __unix__
if(fd < 0)
return 0;
//because transfer is done in full duplex, function returns data from last transfer
int tocpy = length > rxbuf.size() ? rxbuf.size() : length;
memcpy(buffer, &rxbuf[0], tocpy);
rxbuf.clear();
return tocpy;
#else
return 0;
#endif
}
/** @brief Finds SPI port
@return number of devices found
*/
int ConnectionSPI::RefreshDeviceList()
{
m_deviceNames.clear();
#ifdef __unix__
int spidev = open("/dev/spidev2.0", O_RDWR);
if (spidev >= 0)
{
if(IsNovenaBoard() == true)
m_deviceNames.push_back("SPI (Novena)");
else
m_deviceNames.push_back("SPI");
}
close(spidev);
#endif
return m_deviceNames.size();
}
/** @brief Returns found devices names
@return vector of device names
*/
vector<string> ConnectionSPI::GetDeviceNames()
{
return m_deviceNames;
}
int ConnectionSPI::GetOpenedIndex()
{
return 0;
}
/**
@file ConnectionSPI.h
@author Lime Microsystems (www.limemicro.com)
@brief Class for data communications through SPI port
*/
#ifndef CONNECTION_SPI_PORT_H
#define CONNECTION_SPI_PORT_H
#include "IConnection.h"
#include <fstream>
#include <string>
#include <vector>
class ConnectionSPI : public IConnection
{
public:
static const int cSPI_BUF_SIZE;
static const int cSPI_SPEED_HZ;
ConnectionSPI();
~ConnectionSPI();
DeviceStatus Open();
DeviceStatus Open(unsigned i);
void Close();
bool IsOpen();
int GetOpenedIndex();
int Write(const unsigned char *buffer, int length, int timeout_ms = 0);
int Read(unsigned char *buffer, int length, int timeout_ms = 0);
std::vector<std::string> GetDeviceNames();
int RefreshDeviceList();
protected:
std::vector<std::string> m_deviceNames;
std::vector<unsigned char> rxbuf;
int fd;
std::fstream m_SEN;
};
#endif
/**
@file ConnectionUSB.cpp
@author Lime Microsystems (www.limemicro.com)
@brief Data writing and reading through USB port
*/
#include "ConnectionUSB.h"
#include <string.h>
#ifdef __unix__
#include <thread>
#include <chrono>
#endif
#define USB_TIMEOUT 1000
#define HW_LDIGIRED L"DigiRed"
#define HW_LDIGIGREEN L"DigiGreen"
#define HW_LSTREAMER L"Stream"
#define HW_DIGIRED "DigiRed"
#define HW_DIGIGREEN "DigiGreen"
#define HW_STREAMER "Stream"
#define CTR_W_REQCODE 0xC1
#define CTR_W_VALUE 0x0000
#define CTR_W_INDEX 0x0000
#define CTR_R_REQCODE 0xC0
#define CTR_R_VALUE 0x0000
#define CTR_R_INDEX 0x0000
/** @brief Initializes port type and object necessary to communicate to usb device.
*/
ConnectionUSB::ConnectionUSB()
{
m_hardwareName = "";
isConnected = false;
m_connectionType = USB_PORT;
#ifndef __unix__
USBDevicePrimary = new CCyUSBDevice(NULL);
OutCtrEndPt = NULL;
InCtrEndPt = NULL;
InCtrlEndPt3 = NULL;
OutCtrlEndPt3 = NULL;
#else
dev_handle = 0;
devs = 0;
int r = libusb_init(&ctx); //initialize the library for the session we just declared
if(r < 0)
printf("Init Error %i\n", r); //there was an error
libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation
#endif
currentDeviceIndex = -1;
}
/** @brief Closes connection to chip and deallocates used memory.
*/
ConnectionUSB::~ConnectionUSB()
{
Close();
#ifndef __unix__
delete USBDevicePrimary;
#else
libusb_exit(ctx);
#endif
}
/** @brief Automatically open first available chip connected to usb port.
@return 0-success, other-failure
*/
IConnection::DeviceStatus ConnectionUSB::Open()
{
currentDeviceIndex = -1;
if(m_deviceNames.size() == 0)
RefreshDeviceList();
#ifndef __unix__
for(int i=0; i<USBDevicePrimary->DeviceCount(); ++i)
if( Open(i) == SUCCESS)
{
currentDeviceIndex = i;
return SUCCESS;
}
#else
if(Open(0) == SUCCESS)
return SUCCESS;
#endif
return FAILURE;
}
/** @brief Tries to open connected USB device and find communication endpoints.
@return Returns 1-Success, 0-EndPoints not found or device didn't connect.
*/
IConnection::DeviceStatus ConnectionUSB::Open(unsigned index)
{
#ifndef __unix__
wstring m_hardwareDesc = L"";
if( index < USBDevicePrimary->DeviceCount())
{
if(USBDevicePrimary->Open(index))
{
m_hardwareDesc = USBDevicePrimary->Product;
unsigned int pos;
//determine connected board type
pos = m_hardwareDesc.find(HW_LDIGIRED, 0);
if( pos != wstring::npos )
m_hardwareName = HW_DIGIRED;
else if (m_hardwareDesc.find(HW_LSTREAMER, 0) != wstring::npos)
m_hardwareName = HW_STREAMER;
else
m_hardwareName = HW_STREAMER;
if (InCtrlEndPt3)
{
delete InCtrlEndPt3;
InCtrlEndPt3 = NULL;
}
InCtrlEndPt3 = new CCyControlEndPoint(*USBDevicePrimary->ControlEndPt);
if (OutCtrlEndPt3)
{
delete OutCtrlEndPt3;
OutCtrlEndPt3 = NULL;
}
OutCtrlEndPt3 = new CCyControlEndPoint(*USBDevicePrimary->ControlEndPt);
InCtrlEndPt3->ReqCode = CTR_R_REQCODE;
InCtrlEndPt3->Value = CTR_R_VALUE;
InCtrlEndPt3->Index = CTR_R_INDEX;
OutCtrlEndPt3->ReqCode = CTR_W_REQCODE;
OutCtrlEndPt3->Value = CTR_W_VALUE;
OutCtrlEndPt3->Index = CTR_W_INDEX;
for (int i=0; i<USBDevicePrimary->EndPointCount(); i++)
if(USBDevicePrimary->EndPoints[i]->Address == 0x01)
{
OutEndPt = USBDevicePrimary->EndPoints[i];
long len = OutEndPt->MaxPktSize * 64;
OutEndPt->SetXferSize(len);
break;
}
for (int i=0; i<USBDevicePrimary->EndPointCount(); i++)
if(USBDevicePrimary->EndPoints[i]->Address == 0x81)
{
InEndPt = USBDevicePrimary->EndPoints[i];
long len = InEndPt->MaxPktSize * 64;
InEndPt->SetXferSize(len);
break;
}
isConnected = true;
return SUCCESS;
} //successfully opened device
} //if has devices
return FAILURE;
#else
if(index >= 0 && index < m_dev_pid_vid.size())
{
dev_handle = libusb_open_device_with_vid_pid(ctx, m_dev_pid_vid[index].second, m_dev_pid_vid[index].first);
if(dev_handle == 0)
return FAILURE;
if(libusb_kernel_driver_active(dev_handle, 0) == 1) //find out if kernel driver is attached
{
printf("Kernel Driver Active\n");
if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it
printf("Kernel Driver Detached!\n");
}
int r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the first) of device
if(r < 0)
{
printf("Cannot Claim Interface\n");
return CANNOT_CLAIM_INTERFACE;
}
printf("Claimed Interface\n");
isConnected = true;
return SUCCESS;
}
else
{
return FAILURE;
}
#endif
}
/** @brief Closes communication to device.
*/
void ConnectionUSB::Close()
{
#ifndef __unix__
USBDevicePrimary->Close();
InEndPt = NULL;
OutEndPt = NULL;
if (InCtrlEndPt3)
{
delete InCtrlEndPt3;
InCtrlEndPt3 = NULL;
}
if (OutCtrlEndPt3)
{
delete OutCtrlEndPt3;
OutCtrlEndPt3 = NULL;
}
#else
if(dev_handle != 0)
{
libusb_release_interface(dev_handle, 0);
libusb_close(dev_handle);
dev_handle = 0;
}
#endif
isConnected = false;
}
/** @brief Returns connection status
@return 1-connection open, 0-connection closed.
*/
bool ConnectionUSB::IsOpen()
{
#ifndef __unix__
return USBDevicePrimary->IsOpen() && isConnected;
#else
return isConnected;
#endif
}
/** @brief Sends given data buffer to chip through USB port.
@param buffer data buffer, must not be longer than 64 bytes.
@param length given buffer size.
@param timeout_ms timeout limit for operation in milliseconds
@return number of bytes sent.
*/
int ConnectionUSB::Write(const unsigned char *buffer, const int length, int timeout_ms)
{
long len = length;
if(IsOpen())
{
unsigned char* wbuffer = new unsigned char[length];
memcpy(wbuffer, buffer, length);
if(m_hardwareName == HW_DIGIRED || m_hardwareName == HW_STREAMER)
{
#ifndef __unix__
if(OutCtrlEndPt3)
OutCtrlEndPt3->Write(wbuffer, len);
else
len = 0;
#else
len = libusb_control_transfer(dev_handle, LIBUSB_REQUEST_TYPE_VENDOR,CTR_W_REQCODE ,CTR_W_VALUE, CTR_W_INDEX, wbuffer, length, USB_TIMEOUT);
#endif
}
else
{
#ifndef __unix__
if(OutCtrEndPt)
OutCtrEndPt->XferData(wbuffer, len);
else
len = 0;
#else
int actual = 0;
libusb_bulk_transfer(dev_handle, 0x01, wbuffer, len, &actual, USB_TIMEOUT);
len = actual;
#endif
}
delete wbuffer;
}
else
return 0;
return len;
}
/** @brief Reads data coming from the chip through USB port.
@param buffer pointer to array where received data will be copied, array must be
big enough to fit received data.
@param length number of bytes to read from chip.
@param timeout_ms timeout limit for operation in milliseconds
@return number of bytes received.
*/
int ConnectionUSB::Read(unsigned char *buffer, const int length, int timeout_ms)
{
long len = length;
if(IsOpen())
{
if(m_hardwareName == HW_DIGIRED || m_hardwareName == HW_STREAMER)
{
#ifndef __unix__
if(InCtrlEndPt3)
InCtrlEndPt3->Read(buffer, len);
else
len = 0;
#else
len = libusb_control_transfer(dev_handle, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN ,CTR_R_REQCODE ,CTR_R_VALUE, CTR_R_INDEX, buffer, len, USB_TIMEOUT);
#endif
}
else
{
#ifndef __unix__
if(InCtrEndPt)
InCtrEndPt->XferData(buffer, len);
else
len = 0;
#else
int actual = 0;
libusb_bulk_transfer(dev_handle, 0x81, buffer, len, &actual, USB_TIMEOUT);
len = actual;
#endif
}
}
return len;
}
#ifdef __unix__
/** @brief Function for handling libusb callbacks
*/
void callback_libusbtransfer(libusb_transfer *trans)
{
USBTransferContext *context = reinterpret_cast<USBTransferContext*>(trans->user_data);
switch(trans->status)
{
case LIBUSB_TRANSFER_CANCELLED:
printf("Transfer canceled\n" );
context->bytesXfered = trans->actual_length;
context->done = true;
context->used = false;
context->reset();
break;
case LIBUSB_TRANSFER_COMPLETED:
if(trans->actual_length == context->bytesExpected)
{
context->bytesXfered = trans->actual_length;
context->done = true;
}
//printf("Transfer complete %i\n", trans->actual_length);
break;
case LIBUSB_TRANSFER_ERROR:
printf("TRANSFER ERRRO\n");
break;
case LIBUSB_TRANSFER_TIMED_OUT:
printf("transfer timed out\n");
break;
case LIBUSB_TRANSFER_OVERFLOW:
printf("transfer overflow\n");
break;
case LIBUSB_TRANSFER_STALL:
printf("transfer stalled\n");
break;
}
context->mPacketProcessed.notify_one();
}
#endif
/** @brief Finds all chips connected to usb ports
@return number of devices found
*/
int ConnectionUSB::RefreshDeviceList()
{
#ifndef __unix__
USBDevicePrimary->Close();
currentDeviceIndex = -1;
m_deviceNames.clear();
string name;
if (USBDevicePrimary->DeviceCount())
{
for (int i=0; i<USBDevicePrimary->DeviceCount(); ++i)
{
Open(i);
name = DeviceName();
m_deviceNames.push_back(name);
}
currentDeviceIndex = -1;
}
#else
m_dev_pid_vid.clear();
m_deviceNames.clear();
int usbDeviceCount = libusb_get_device_list(ctx, &devs);
if(usbDeviceCount > 0)
{
libusb_device_descriptor desc;
for(int i=0; i<usbDeviceCount; ++i)
{
int r = libusb_get_device_descriptor(devs[i], &desc);
if(r<0)
printf("failed to get device description\n");
int pid = desc.idProduct;
int vid = desc.idVendor;
if( vid == 1204)
{
if(pid == 34323)
{
m_hardwareName = HW_DIGIGREEN;
m_deviceNames.push_back("DigiGreen");
m_dev_pid_vid.push_back( pair<int,int>(pid,vid));
}
else if(pid == 241)
{
m_hardwareName = HW_DIGIRED;
libusb_device_handle *tempDev_handle;
tempDev_handle = libusb_open_device_with_vid_pid(ctx, vid, pid);
if(libusb_kernel_driver_active(tempDev_handle, 0) == 1) //find out if kernel driver is attached
{
if(libusb_detach_kernel_driver(tempDev_handle, 0) == 0) //detach it
printf("Kernel Driver Detached!\n");
}
if(libusb_claim_interface(tempDev_handle, 0) < 0) //claim interface 0 (the first) of device
{
printf("Cannot Claim Interface\n");
}
string fullName;
//check operating speed
int speed = libusb_get_device_speed(devs[i]);
if(speed == LIBUSB_SPEED_HIGH)
fullName = "USB 2.0";
else if(speed == LIBUSB_SPEED_SUPER)
fullName = "USB 3.0";
else
fullName = "USB";
fullName += " (";
//read device name
char data[255];
memset(data, 0, 255);
int st = libusb_get_string_descriptor_ascii(tempDev_handle, 2, (unsigned char*)data, 255);
if(strlen(data) > 0)
fullName += data;
fullName += ")";
libusb_close(tempDev_handle);
m_deviceNames.push_back(fullName);
m_dev_pid_vid.push_back( pair<int,int>(pid,vid));
}
}
}
}
else
{
libusb_free_device_list(devs, 1);
return 0;
}
#endif
return m_deviceNames.size();
}
void ConnectionUSB::ClearComm()
{
}
/** @return name of currently opened device as string.
*/
string ConnectionUSB::DeviceName()
{
#ifndef __unix__
string name;
char tempName[USB_STRING_MAXLEN];
//memcpy(tempName, USBDevicePrimary->FriendlyName, USB_STRING_MAXLEN);
//name = tempName;
for (int i = 0; i < USB_STRING_MAXLEN; ++i)
tempName[i] = USBDevicePrimary->DeviceName[i];
if (USBDevicePrimary->bSuperSpeed == true)
name = "USB 3.0";
else if (USBDevicePrimary->bHighSpeed == true)
name = "USB 2.0";
else
name = "USB";
name += " (";
name += tempName;
name += ")";
return name;
#else
if(dev_handle != 0)
{
char data[255];
int st = libusb_get_string_descriptor_ascii(dev_handle, 2, (unsigned char*)data, 255);
return string(data);
}
return "no name";
#endif
}
/**
@brief Starts asynchronous data reading from board
@param *buffer buffer where to store received data
@param length number of bytes to read
@return handle of transfer context
*/
int ConnectionUSB::BeginDataReading(char *buffer, long length)
{
int i = 0;
bool contextFound = false;
//find not used context
for(i = 0; i<USB_MAX_CONTEXTS; i++)
{
if(!contexts[i].used)
{
contextFound = true;
break;
}
}
if(!contextFound)
return -1;
contexts[i].used = true;
#ifndef __unix__
if(InEndPt)
contexts[i].context = InEndPt->BeginDataXfer((unsigned char*)buffer, length, contexts[i].inOvLap);
return i;
#else
unsigned int Timeout = 1000;
libusb_transfer *tr = contexts[i].transfer;
libusb_fill_bulk_transfer(tr, dev_handle, 0x81, (unsigned char*)buffer, length, callback_libusbtransfer, &contexts[i], Timeout);
contexts[i].done = false;
contexts[i].bytesXfered = 0;
contexts[i].bytesExpected = length;
int status = libusb_submit_transfer(tr);
int actual = 0;
//int status = libusb_bulk_transfer(dev_handle, 0x81, (unsigned char*)buffer, length, &actual, USB_TIMEOUT);
if(status != 0)
printf("ERROR BEGIN DATA TRANSFER %s\n", libusb_error_name(status));
#endif
return i;
}
/**
@brief Waits for asynchronous data reception
@param contextHandle handle of which context data to wait
@param timeout_ms number of miliseconds to wait
@return 1-data received, 0-data not received
*/
int ConnectionUSB::WaitForReading(int contextHandle, unsigned int timeout_ms)
{
if( contexts[contextHandle].used == true && contextHandle >= 0)
{
int status = 0;
#ifndef __unix__
if(InEndPt)
status = InEndPt->WaitForXfer(contexts[contextHandle].inOvLap, timeout_ms);
return status;
#else
auto t1 = chrono::high_resolution_clock::now();
auto t2 = chrono::high_resolution_clock::now();
while(contexts[contextHandle].done == false && std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count() < timeout_ms)
{
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
//if(libusb_handle_events(ctx) != 0)
if(libusb_handle_events_timeout_completed(ctx, &tv, NULL) != 0)
printf("error libusb_handle_events %i\n", status);
t2 = chrono::high_resolution_clock::now();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
std::unique_lock<std::mutex> lck(contexts[contextHandle].m_lock);
while(contexts[contextHandle].done == false) //is changed in libusb callback
{
if(contexts[contextHandle].mPacketProcessed.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout)
return 0;
}
return contexts[contextHandle].done == true;
#endif
}
else
return 0;
}
/**
@brief Finishes asynchronous data reading from board
@param buffer array where to store received data
@param length number of bytes to read, function changes this value to number of bytes actually received
@param contextHandle handle of which context to finish
@return false failure, true number of bytes received
*/
int ConnectionUSB::FinishDataReading(char *buffer, long &length, int contextHandle)
{
if( contexts[contextHandle].used == true && contextHandle >= 0)
{
#ifndef __unix__
int status = 0;
if(InEndPt)
status = InEndPt->FinishDataXfer((unsigned char*)buffer, length, contexts[contextHandle].inOvLap, contexts[contextHandle].context);
contexts[contextHandle].used = false;
contexts[contextHandle].reset();
return length;
#else
length = contexts[contextHandle].bytesXfered;
contexts[contextHandle].used = false;
contexts[contextHandle].reset();
return length;
#endif
}
else
return 0;
}
int ConnectionUSB::ReadDataBlocking(char *buffer, long &length, int timeout_ms)
{
#ifndef __unix__
return InEndPt->XferData((unsigned char*)buffer, length);
#else
return 0;
#endif
}
/**
@brief Aborts reading operations
*/
void ConnectionUSB::AbortReading()
{
#ifndef __unix__
InEndPt->Abort();
#else
for(int i=0; i<USB_MAX_CONTEXTS; ++i)
{
libusb_cancel_transfer( contexts[i].transfer );
}
#endif
}
/**
@brief Starts asynchronous data Sending to board
@param *buffer buffer to send
@param length number of bytes to send
@return handle of transfer context
*/
int ConnectionUSB::BeginDataSending(const char *buffer, long length)
{
int i = 0;
//find not used context
bool contextFound = false;
for(i = 0; i<USB_MAX_CONTEXTS; i++)
{
if(!contextsToSend[i].used)
{
contextFound = true;
break;
}
}
if(!contextFound)
return -1;
contextsToSend[i].used = true;
#ifndef __unix__
if(OutEndPt)
contextsToSend[i].context = OutEndPt->BeginDataXfer((unsigned char*)buffer, length, contextsToSend[i].inOvLap);
return i;
#else
unsigned int Timeout = 1000;
libusb_transfer *tr = contextsToSend[i].transfer;
//libusb_set_iso_packet_lengths(contexts[i].transfer, 512*64);
libusb_fill_bulk_transfer(tr, dev_handle, 0x1, (unsigned char*)buffer, length, callback_libusbtransfer, &contextsToSend[i], Timeout);
contextsToSend[i].done = false;
contextsToSend[i].bytesXfered = 0;
contextsToSend[i].bytesExpected = length;
libusb_submit_transfer(tr);
#endif
return i;
}
/**
@brief Waits for asynchronous data sending
@param contextHandle handle of which context data to wait
@param timeout_ms number of miliseconds to wait
@return 1-data received, 0-data not received
*/
int ConnectionUSB::WaitForSending(int contextHandle, unsigned int timeout_ms)
{
if( contextsToSend[contextHandle].used == true )
{
#ifndef __unix__
int status = 0;
if(OutEndPt)
status = OutEndPt->WaitForXfer(contextsToSend[contextHandle].inOvLap, timeout_ms);
return status;
#else
auto t1 = chrono::high_resolution_clock::now();
auto t2 = chrono::high_resolution_clock::now();
while(contextsToSend[contextHandle].done == false && std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count() < timeout_ms)
{
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
int status = libusb_handle_events_timeout_completed(ctx, &tv, NULL);
if(status != 0)
printf("error libusb_handle_events %i\n", status);
t2 = chrono::high_resolution_clock::now();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
std::unique_lock<std::mutex> lck(contextsToSend[contextHandle].m_lock);
while(contextsToSend[contextHandle].done == false) //is changed in libusb callback
{
if(contextsToSend[contextHandle].mPacketProcessed.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout)
return 0;
}
return contextsToSend[contextHandle].done == true;
#endif
}
else
return 0;
}
/**
@brief Finishes asynchronous data sending to board
@param buffer array where to store received data
@param length number of bytes to read, function changes this value to number of bytes acctually received
@param contextHandle handle of which context to finish
@return false failure, true number of bytes sent
*/
int ConnectionUSB::FinishDataSending(const char *buffer, long &length, int contextHandle)
{
if( contextsToSend[contextHandle].used == true)
{
#ifndef __unix__
if(OutEndPt)
OutEndPt->FinishDataXfer((unsigned char*)buffer, length, contextsToSend[contextHandle].inOvLap, contextsToSend[contextHandle].context);
contextsToSend[contextHandle].used = false;
contextsToSend[contextHandle].reset();
return length;
#else
length = contextsToSend[contextHandle].bytesXfered;
contextsToSend[contextHandle].used = false;
contextsToSend[contextHandle].reset();
return length;
#endif
}
else
return 0;
}
/**
@brief Aborts sending operations
*/
void ConnectionUSB::AbortSending()
{
#ifndef __unix__
OutEndPt->Abort();
#else
for (int i = 0; i<USB_MAX_CONTEXTS; ++i)
{
libusb_cancel_transfer(contextsToSend[i].transfer);
}
for(int i=0; i<USB_MAX_CONTEXTS; ++i)
{
contextsToSend[i].used = false;
contextsToSend[i].reset();
}
#endif
}
int ConnectionUSB::GetOpenedIndex()
{
return currentDeviceIndex;
}
/** @brief Returns found devices names
@return vector of device names
*/
vector<string> ConnectionUSB::GetDeviceNames()
{
return m_deviceNames;
}
/**
@file ConnectionUSB.h
@author Lime Microsystems (www.limemicro.com)
@brief Class for data writing and reading through USB port
*/
#ifndef USB_PORT_CONNECTION_H
#define USB_PORT_CONNECTION_H
#include "IConnection.h"
#ifndef __unix__
#include "windows.h"
#include "CyAPI.h"
#else
#include <libusb-1.0/libusb.h>
#include <mutex>
#include <condition_variable>
#include <chrono>
#endif
#define USB_MAX_CONTEXTS 64 //maximum number of contexts for asynchronous transfers
/** @brief Wrapper class for holding USB asynchronous transfers contexts
*/
class USBTransferContext
{
public:
USBTransferContext() : used(false)
{
#ifndef __unix__
inOvLap = new OVERLAPPED;
memset(inOvLap, 0, sizeof(OVERLAPPED));
inOvLap->hEvent = CreateEvent(NULL, false, false, NULL);
context = NULL;
#else
transfer = libusb_alloc_transfer(0);
bytesXfered = 0;
bytesExpected = 0;
done = 0;
#endif
}
~USBTransferContext()
{
#ifndef __unix__
CloseHandle(inOvLap->hEvent);
delete inOvLap;
#else
libusb_free_transfer(transfer);
#endif
}
bool reset()
{
if(used)
return false;
#ifndef __unix__
CloseHandle(inOvLap->hEvent);
memset(inOvLap, 0, sizeof(OVERLAPPED));
inOvLap->hEvent = CreateEvent(NULL, false, false, NULL);
#endif
return true;
}
bool used;
#ifndef __unix__
PUCHAR context;
OVERLAPPED *inOvLap;
#else
libusb_transfer* transfer;
long bytesXfered;
long bytesExpected;
bool done;
std::mutex m_lock;
std::condition_variable mPacketProcessed;
#endif
};
class ConnectionUSB : public IConnection
{
public:
ConnectionUSB();
~ConnectionUSB();
void FindDevices();
DeviceStatus Open();
DeviceStatus Open(unsigned index);
void Close();
bool IsOpen();
int GetOpenedIndex();
int Write(const unsigned char *buffer, int length, int timeout_ms = 0);
int Read(unsigned char *buffer, int length, int timeout_ms = 0);
virtual int BeginDataReading(char *buffer, long length);
virtual int WaitForReading(int contextHandle, unsigned int timeout_ms);
virtual int FinishDataReading(char *buffer, long &length, int contextHandle);
virtual void AbortReading();
virtual int ReadDataBlocking(char *buffer, long &length, int timeout_ms);
virtual int BeginDataSending(const char *buffer, long length);
virtual int WaitForSending(int contextHandle, unsigned int timeout_ms);
virtual int FinishDataSending(const char *buffer, long &length, int contextHandle);
virtual void AbortSending();
std::vector<std::string> GetDeviceNames();
int RefreshDeviceList();
void ClearComm();
private:
int currentDeviceIndex;
std::string DeviceName();
std::vector<std::string> m_deviceNames;
std::string m_hardwareName;
int m_hardwareVer;
USBTransferContext contexts[USB_MAX_CONTEXTS];
USBTransferContext contextsToSend[USB_MAX_CONTEXTS];
void Initialize();
bool isConnected;
int currentPortIndex;
#ifndef __unix__
CCyUSBDevice *USBDevicePrimary;
//control endpoints for DigiRed
CCyControlEndPoint *InCtrlEndPt3;
CCyControlEndPoint *OutCtrlEndPt3;
//control endpoints for DigiGreen
CCyUSBEndPoint *OutCtrEndPt;
CCyUSBEndPoint *InCtrEndPt;
//end points for samples reading and writing
CCyUSBEndPoint *InEndPt;
CCyUSBEndPoint *OutEndPt;
#else
libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
libusb_device_handle *dev_handle; //a device handle
libusb_context *ctx; //a libusb session
std::vector<std::pair<int,int> > m_dev_pid_vid;
#endif
};
#endif
/**
@file IConnection.h
@author Lime Microsystems
@brief Interface class for connection types
*/
#ifndef ICONNECTION_H
#define ICONNECTION_H
#include <string>
#include <vector>
using namespace std;
class IConnection
{
public:
/// Supported connection types.
enum eConnectionType
{
CONNECTION_UNDEFINED = -1,
COM_PORT = 0,
USB_PORT = 1,
SPI_PORT = 2,
//insert new types here
CONNECTION_TYPES_COUNT //used only for memory allocation
};
enum DeviceStatus
{
SUCCESS,
FAILURE,
END_POINTS_NOT_FOUND,
CANNOT_CLAIM_INTERFACE
};
IConnection() : m_connectionType(CONNECTION_UNDEFINED){};
virtual ~IConnection(){};
virtual int RefreshDeviceList() = 0;
virtual DeviceStatus Open(unsigned i) = 0;
virtual void Close() = 0;
virtual bool IsOpen() = 0;
virtual int GetOpenedIndex() = 0;
virtual int Write(const unsigned char *buffer, int length, int timeout_ms = 0) = 0;
virtual int Read(unsigned char *buffer, int length, int timeout_ms = 0) = 0;
virtual std::vector<std::string> GetDeviceNames() = 0;
virtual eConnectionType GetType() { return m_connectionType; };
virtual bool SetParam(const char *name, const char* value) {return false;};
virtual int BeginDataReading(char *buffer, long length){ return -1; };
virtual int WaitForReading(int contextHandle, unsigned int timeout_ms){ return 0;};
virtual int FinishDataReading(char *buffer, long &length, int contextHandle){ return 0;}
virtual void AbortReading(){};
virtual int ReadDataBlocking(char *buffer, long &length, int timeout_ms){ return 0; }
virtual int BeginDataSending(const char *buffer, long length){ return -1; };
virtual int WaitForSending(int contextHandle, unsigned int timeout_ms){ return 0;};
virtual int FinishDataSending(const char *buffer, long &length, int contextHandle){ return 0;}
virtual void AbortSending(){};
protected:
eConnectionType m_connectionType;
};
#endif
/**
@file lms7002_defines.h
@author Lime Microsystems
@brief enumerations of available LMS7002M commands and statuses
*/
#pragma once
const int LMS_RST_DEACTIVATE = 0;
const int LMS_RST_ACTIVATE = 1;
const int LMS_RST_PULSE = 2;
enum eLMS_DEV
{
LMS_DEV_UNKNOWN,
LMS_DEV_EVB6,
LMS_DEV_DIGIGREEN,
LMS_DEV_DIGIRED,
LMS_DEV_EVB7,
LMS_DEV_ZIPPER,
LMS_DEV_SOCKETBOARD,
LMS_DEV_EVB7V2,
LMS_DEV_STREAM,
LMS_DEV_NOVENA,
LMS_DEV_DATASPARK,
LMS_DEV_RFSPARK,
LMS_DEV_LMS6002USB,
LMS_DEV_RFESPARK,
LMS_DEV_SODERA,
LMS_DEV_COUNT
};
const char LMS_DEV_NAMES[][80] =
{
"UNKNOWN",
"EVB6",
"DigiGreen",
"DigiRed",
"EVB7",
"ZIPPER",
"Socket Board",
"EVB7_v2",
"Stream",
"Novena",
"DataSpark",
"RF-Spark",
"LMS6002-USB Stick",
"RF-ESpark",
"SoDeRa",
};
static const char* GetDeviceName(const eLMS_DEV device)
{
if (LMS_DEV_UNKNOWN < device && device < LMS_DEV_COUNT)
return LMS_DEV_NAMES[device];
else
return LMS_DEV_NAMES[LMS_DEV_UNKNOWN];
}
enum eEXP_BOARD
{
EXP_BOARD_UNKNOWN,
EXP_BOARD_UNSUPPORTED,
EXP_BOARD_NO,
EXP_BOARD_MYRIAD1,
EXP_BOARD_MYRIAD2,
EXP_BOARD_MYRIAD_NOVENA,
EXP_BOARD_HPM1000,
EXP_BOARD_MYRIAD7,
EXP_BOARD_HPM7,
EXP_BOARD_COUNT
};
const char EXP_BOARD_NAMES[][80] =
{
"UNKNOWN",
"UNSUPPORTED",
"NOT AVAILABLE",
"Myriad1",
"Myriad2",
"Novena",
"HPM1000",
"Myriad7",
"HMP7"
};
static const char* GetExpansionBoardName(const eEXP_BOARD board)
{
if (EXP_BOARD_UNKNOWN < board && board < EXP_BOARD_COUNT)
return EXP_BOARD_NAMES[board];
else
return EXP_BOARD_NAMES[EXP_BOARD_UNKNOWN];
}
struct LMS64C_Info
{
unsigned char firmware;
unsigned char deviceType;
unsigned char protocol;
unsigned char hardware;
unsigned char expansionBoard;
};
enum eCMD_LMS
{
CMD_GET_INFO = 0x00,
CMD_LMS6002_RST = 0x10,
///Writes data to SI5356 synthesizer via I2C
CMD_SI5356_WR = 0x11,
///Reads data from SI5356 synthesizer via I2C
CMD_SI5356_RD = 0x12,
///Writes data to SI5351 synthesizer via I2C
CMD_SI5351_WR = 0x13,
///Reads data from SI5351 synthesizer via I2C
CMD_SI5351_RD = 0x14,
///PanelBus DVI (HDMI) Transmitter control
CMD_TFP410_WR = 0x15,
///PanelBus DVI (HDMI) Transmitter control
CMD_TFP410_RD = 0x16,
///Sets new LMS7002M chip’s RESET pin level (0, 1, pulse)
CMD_LMS7002_RST = 0x20,
///Writes data to LMS7002M chip via SPI
CMD_LMS7002_WR = 0x21,
///Reads data from LMS7002M chip via SPI
CMD_LMS7002_RD = 0x22,
///Writes data to LMS6002 chip via SPI
CMD_LMS6002_WR = 0x23,
///Reads data from LMS6002 chip via SPI
CMD_LMS6002_RD = 0x24,
CMD_LMS_LNA = 0x2A,
CMD_LMS_PA = 0x2B,
CMD_PROG_MCU = 0x2C,
///Writes data to ADF4002 chip via SPI
CMD_ADF4002_WR = 0x31,
CMD_USB_FIFO_RST = 0x40,
CMD_PE636040_WR = 0x41,
CMD_PE636040_RD = 0x42,
CMD_GPIO_WR = 0x51,
CMD_GPIO_RD = 0x52,
CMD_ALTERA_FPGA_GW_WR = 0x53,
CMD_ALTERA_FPGA_GW_RD = 0x54,
CMD_BRDSPI_WR = 0x55,//16 bit spi for stream, dataspark control
CMD_BRDSPI_RD = 0x56,//16 bit spi for stream, dataspark control
CMD_BRDSPI8_WR = 0x57, //8 + 8 bit spi for stream, dataspark control
CMD_BRDSPI8_RD = 0x58, //8 + 8 bit spi for stream, dataspark control
CMD_BRDCONF_WR = 0x5D, //write config data to board
CMD_BRDCONF_RD = 0x5E, //read config data from board
CMD_ANALOG_VAL_WR = 0x61, //write analog value
CMD_ANALOG_VAL_RD = 0x62, //read analog value
CMD_MYRIAD_RST = 0x80,
CMD_MYRIAD_WR = 0x81,
CMD_MYRIAD_RD = 0x82,
CMD_MYRIAD_PROG = 0x8C
};
enum eCMD_STATUS
{
STATUS_UNDEFINED,
STATUS_COMPLETED_CMD,
STATUS_UNKNOWN_CMD,
STATUS_BUSY_CMD,
STATUS_MANY_BLOCKS_CMD,
STATUS_ERROR_CMD,
STATUS_WRONG_ORDER_CMD,
STATUS_RESOURCE_DENIED_CMD,
STATUS_COUNT
};
static const char status_text[][32]=
{
"Undefined/Failure",
"Completed",
"Unknown command",
"Busy",
"Too many blocks",
"Error",
"Wrong order",
"Resource denied"
};
static const char* status2string(const int status)
{
if(status >= 0 && status < STATUS_COUNT)
return status_text[status];
else
return "Unknown status";
}
enum eADC_UNITS
{
RAW,
VOLTAGE,
CURRENT,
RESISTANCE,
POWER,
TEMPERATURE,
ADC_UNITS_COUNT
};
static const char adc_units_text[][8] = {"", "V", "A", "Ohm", "W", "C"};
static const char* adcUnits2string(const unsigned units)
{
if (units < ADC_UNITS_COUNT)
return adc_units_text[units];
else
return " unknown";
}
/**
@file LMScomms.cpp
@author Lime Microsystems (www.limemicro.com)
@brief Implementation of data transmission to LMS boards
*/
#include "lmsComms.h"
LMScomms::LMScomms()
{
callback_logData = nullptr;
unsigned short test = 0x1234;
unsigned char* bytes = (unsigned char*)&test;
if(bytes[0] == 0x12 && bytes[1] == 0x34)
mSystemBigEndian = true;
else
mSystemBigEndian = false;
}
LMScomms::~LMScomms()
{
}
/** @brief Transfers data between packet and connected device
@param pkt packet containing output data and to receive incomming data
@return 0: success, other: failure
*/
LMScomms::TransferStatus LMScomms::TransferPacket(GenericPacket& pkt)
{
std::lock_guard<std::mutex> lock(mControlPortLock);
TransferStatus status = TRANSFER_SUCCESS;
if(IsOpen() == false)
return NOT_CONNECTED;
int packetLen;
eLMS_PROTOCOL protocol = LMS_PROTOCOL_UNDEFINED;
if(activeControlPort->GetType() == IConnection::SPI_PORT)
protocol = LMS_PROTOCOL_NOVENA;
else
protocol = LMS_PROTOCOL_LMS64C;
switch(protocol)
{
case LMS_PROTOCOL_UNDEFINED:
return TRANSFER_FAILED;
case LMS_PROTOCOL_LMS64C:
packetLen = ProtocolLMS64C::pktLength;
break;
case LMS_PROTOCOL_NOVENA:
packetLen = pkt.outBuffer.size() > ProtocolNovena::pktLength ? ProtocolNovena::pktLength : pkt.outBuffer.size();
break;
default:
packetLen = 0;
return TRANSFER_FAILED;
}
int outLen = 0;
unsigned char* outBuffer = NULL;
outBuffer = PreparePacket(pkt, outLen, protocol);
unsigned char* inBuffer = new unsigned char[outLen];
memset(inBuffer, 0, outLen);
int outBufPos = 0;
int inDataPos = 0;
if(outLen == 0)
{
//printf("packet outlen = 0\n");
outLen = 1;
}
if(protocol == LMS_PROTOCOL_NOVENA)
{
bool transferData = true; //some commands are fake, so don't need transferring
if(pkt.cmd == CMD_GET_INFO)
{
//spi does not have GET INFO, fake it to inform what device it is
pkt.status = STATUS_COMPLETED_CMD;
pkt.inBuffer.clear();
pkt.inBuffer.resize(64, 0);
pkt.inBuffer[0] = 0; //firmware
pkt.inBuffer[1] = LMS_DEV_NOVENA; //device
pkt.inBuffer[2] = 0; //protocol
pkt.inBuffer[3] = 0; //hardware
pkt.inBuffer[4] = EXP_BOARD_UNSUPPORTED; //expansion
transferData = false;
}
if(transferData)
{
if (callback_logData)
callback_logData(true, outBuffer, outLen);
int bytesWritten = Write(outBuffer, outLen);
if( bytesWritten == outLen)
{
if(pkt.cmd == CMD_LMS7002_RD)
{
inDataPos = Read(&inBuffer[inDataPos], outLen);
if(inDataPos != outLen)
status = TRANSFER_FAILED;
else
{
if (callback_logData)
callback_logData(false, inBuffer, inDataPos);
}
}
ParsePacket(pkt, inBuffer, inDataPos, protocol);
}
else
status = TRANSFER_FAILED;
}
}
else
{
for(int i=0; i<outLen; i+=packetLen)
{
int bytesToSend = packetLen;
if (callback_logData)
callback_logData(true, &outBuffer[outBufPos], bytesToSend);
if( Write(&outBuffer[outBufPos], bytesToSend) )
{
outBufPos += packetLen;
long readLen = packetLen;
int bread = Read(&inBuffer[inDataPos], readLen);
if(bread != readLen && protocol != LMS_PROTOCOL_NOVENA)
{
status = TRANSFER_FAILED;
break;
}
if (callback_logData)
callback_logData(false, &inBuffer[inDataPos], bread);
inDataPos += bread;
}
else
{
status = TRANSFER_FAILED;
break;
}
}
ParsePacket(pkt, inBuffer, inDataPos, protocol);
}
delete outBuffer;
delete inBuffer;
return status;
}
/** @brief Returns connected device information
*/
LMSinfo LMScomms::GetInfo()
{
LMSinfo info;
info.device = LMS_DEV_UNKNOWN;
info.expansion = EXP_BOARD_UNKNOWN;
info.firmware = 0;
info.hardware = 0;
info.protocol = 0;
GenericPacket pkt;
pkt.cmd = CMD_GET_INFO;
LMScomms::TransferStatus status = TransferPacket(pkt);
if (status == LMScomms::TRANSFER_SUCCESS && pkt.inBuffer.size() >= 5)
{
info.firmware = pkt.inBuffer[0];
info.device = pkt.inBuffer[1] < LMS_DEV_COUNT ? (eLMS_DEV)pkt.inBuffer[1] : LMS_DEV_UNKNOWN;
info.protocol = pkt.inBuffer[2];
info.hardware = pkt.inBuffer[3];
info.expansion = pkt.inBuffer[4] < EXP_BOARD_COUNT ? (eEXP_BOARD)pkt.inBuffer[4] : EXP_BOARD_UNKNOWN;
}
return info;
}
/** @brief Takes generic packet and converts to specific protocol buffer
@param pkt generic data packet to convert
@param length returns length of returned buffer
@param protocol which protocol to use for data
@return pointer to data buffer, must be manually deleted after use
*/
unsigned char* LMScomms::PreparePacket(const GenericPacket& pkt, int& length, const eLMS_PROTOCOL protocol)
{
unsigned char* buffer = NULL;
if(protocol == LMS_PROTOCOL_UNDEFINED)
return NULL;
if(protocol == LMS_PROTOCOL_LMS64C)
{
ProtocolLMS64C packet;
int maxDataLength = packet.maxDataLength;
packet.cmd = pkt.cmd;
packet.status = pkt.status;
int byteBlockRatio = 1; //block ratio - how many bytes in one block
switch( packet.cmd )
{
case CMD_PROG_MCU:
case CMD_GET_INFO:
case CMD_SI5351_RD:
case CMD_SI5356_RD:
byteBlockRatio = 1;
break;
case CMD_SI5351_WR:
case CMD_SI5356_WR:
byteBlockRatio = 2;
break;
case CMD_LMS7002_RD:
case CMD_BRDSPI_RD:
case CMD_BRDSPI8_RD:
byteBlockRatio = 2;
break;
case CMD_ADF4002_WR:
byteBlockRatio = 3;
break;
case CMD_LMS7002_WR:
case CMD_BRDSPI_WR:
case CMD_ANALOG_VAL_WR:
byteBlockRatio = 4;
break;
default:
byteBlockRatio = 1;
}
if (packet.cmd == CMD_LMS7002_RD || packet.cmd == CMD_BRDSPI_RD)
maxDataLength = maxDataLength/2;
if (packet.cmd == CMD_ANALOG_VAL_RD)
maxDataLength = maxDataLength / 4;
int blockCount = pkt.outBuffer.size()/byteBlockRatio;
int bufLen = blockCount/(maxDataLength/byteBlockRatio)
+(blockCount%(maxDataLength/byteBlockRatio)!=0);
bufLen *= packet.pktLength;
if(bufLen == 0)
bufLen = packet.pktLength;
buffer = new unsigned char[bufLen];
memset(buffer, 0, bufLen);
int srcPos = 0;
for(int j=0; j*packet.pktLength<bufLen; ++j)
{
int pktPos = j*packet.pktLength;
buffer[pktPos] = packet.cmd;
buffer[pktPos+1] = packet.status;
if(blockCount > (maxDataLength/byteBlockRatio))
{
buffer[pktPos+2] = maxDataLength/byteBlockRatio;
blockCount -= buffer[pktPos+2];
}
else
buffer[pktPos+2] = blockCount;
memcpy(&buffer[pktPos+3], packet.reserved, sizeof(packet.reserved));
int bytesToPack = (maxDataLength/byteBlockRatio)*byteBlockRatio;
for (int k = 0; k<bytesToPack && srcPos < pkt.outBuffer.size(); ++srcPos, ++k)
buffer[pktPos + 8 + k] = pkt.outBuffer[srcPos];
}
length = bufLen;
}
else if(protocol == LMS_PROTOCOL_NOVENA)
{
const uint16_t NOVENA_GPIO_ADDR = 0x0706;
if(pkt.cmd == CMD_LMS7002_RST)
{
buffer = new unsigned char[8];
buffer[0] = (NOVENA_GPIO_ADDR >> 8) | 0x80;
buffer[1] = NOVENA_GPIO_ADDR & 0xFF;
buffer[2] = 0x00;
buffer[3] = 0x18;
buffer[4] = (NOVENA_GPIO_ADDR >> 8) | 0x80;
buffer[5] = NOVENA_GPIO_ADDR & 0xFF;
buffer[6] = 0x00;
buffer[7] = 0x38;
length = 8;
}
else
{
buffer = new unsigned char[pkt.outBuffer.size()];
memcpy(buffer, &pkt.outBuffer[0], pkt.outBuffer.size());
if (pkt.cmd == CMD_LMS7002_WR)
{
for(int i=0; i<pkt.outBuffer.size(); i+=4)
buffer[i] |= 0x80;
}
length = pkt.outBuffer.size();
}
}
return buffer;
}
/** @brief Parses given data buffer into generic packet
@param pkt destination packet
@param buffer received data from board
@param length received buffer length
@param protocol which protocol to use for data parsing
@return 1:success, 0:failure
*/
int LMScomms::ParsePacket(GenericPacket& pkt, const unsigned char* buffer, const int length, const eLMS_PROTOCOL protocol)
{
if(protocol == LMS_PROTOCOL_UNDEFINED)
return -1;
if(protocol == LMS_PROTOCOL_LMS64C)
{
ProtocolLMS64C packet;
int inBufPos = 0;
pkt.inBuffer.resize(packet.maxDataLength*(length / packet.pktLength + (length % packet.pktLength)), 0);
for(int i=0; i<length; i+=packet.pktLength)
{
pkt.cmd = (eCMD_LMS)buffer[i];
pkt.status = (eCMD_STATUS)buffer[i+1];
memcpy(&pkt.inBuffer[inBufPos], &buffer[i+8], packet.maxDataLength);
inBufPos += packet.maxDataLength;
}
}
else if(protocol == LMS_PROTOCOL_NOVENA)
{
pkt.cmd = CMD_LMS7002_RD;
pkt.status = STATUS_COMPLETED_CMD;
pkt.inBuffer.clear();
for(int i=0; i<length; i+=2)
{
//reading from spi returns only registers values
//fill addresses as zeros to match generic format of address, value pairs
pkt.inBuffer.push_back(0); //should be address msb
pkt.inBuffer.push_back(0); //should be address lsb
pkt.inBuffer.push_back(buffer[i]);
pkt.inBuffer.push_back(buffer[i+1]);
}
}
return 1;
}
/** @brief Sets callback function which gets called each time data is sent or received
*/
void LMScomms::SetDataLogCallback(std::function<void(bool, const unsigned char*, const unsigned int)> callback)
{
callback_logData = callback;
}
/**
@file LMScomms.h
@author Lime Microsystems (www.limemicro.com)
@brief Class for handling data transmission to LMS boards
*/
#ifndef LMS_COMMS_H
#define LMS_COMMS_H
#include "lms7002_defines.h"
#include "connectionManager/ConnectionManager.h"
#include <string.h>
#include <mutex>
struct LMSinfo
{
eLMS_DEV device;
eEXP_BOARD expansion;
int firmware;
int hardware;
int protocol;
};
/* @brief Class for abstracting transfering data to and from chip
*/
class LMScomms : public ConnectionManager
{
public:
enum TransferStatus
{
TRANSFER_SUCCESS,
TRANSFER_FAILED,
NOT_CONNECTED
};
enum eLMS_PROTOCOL
{
LMS_PROTOCOL_UNDEFINED = 0,
LMS_PROTOCOL_DIGIC,
LMS_PROTOCOL_LMS64C,
LMS_PROTOCOL_NOVENA,
};
struct ProtocolDIGIC
{
static const int pktLength = 64;
static const int maxDataLength = 60;
ProtocolDIGIC() : cmd(0), i2cAddr(0), blockCount(0) {};
unsigned char cmd;
unsigned char i2cAddr;
unsigned char blockCount;
unsigned char reserved;
unsigned char data[maxDataLength];
};
struct ProtocolLMS64C
{
static const int pktLength = 64;
static const int maxDataLength = 56;
ProtocolLMS64C() :cmd(0),status(STATUS_UNDEFINED),blockCount(0)
{
memset(reserved, 0, 5);
};
unsigned char cmd;
unsigned char status;
unsigned char blockCount;
unsigned char reserved[5];
unsigned char data[maxDataLength];
};
struct ProtocolNovena
{
static const int pktLength = 128;
static const int maxDataLength = 128;
ProtocolNovena() :cmd(0),status(0) {};
unsigned char cmd;
unsigned char status;
unsigned char blockCount;
unsigned char data[maxDataLength];
};
struct GenericPacket
{
GenericPacket()
{
cmd = CMD_GET_INFO;
status = STATUS_UNDEFINED;
}
eCMD_LMS cmd;
eCMD_STATUS status;
vector<unsigned char> outBuffer;
vector<unsigned char> inBuffer;
};
LMScomms();
~LMScomms();
virtual TransferStatus TransferPacket(GenericPacket &pkt);
LMSinfo GetInfo();
void SetDataLogCallback(std::function<void(bool, const unsigned char*, const unsigned int)> callback);
protected:
std::function<void(bool, const unsigned char*, const unsigned int)> callback_logData;
std::mutex mControlPortLock;
unsigned char* PreparePacket(const GenericPacket &pkt, int &length, const eLMS_PROTOCOL protocol);
int ParsePacket(GenericPacket &pkt, const unsigned char* buffer, const int length, const eLMS_PROTOCOL protocol);
protected:
bool mSystemBigEndian;
};
#endif // LMS_COMMS_H
/**
@file typedefs.h
@author Lime Microsystems (www.limemicro.com)
@brief Variables types definitions
*/
#ifndef LMS7002M_TYPEDEFS_H
#define LMS7002M_TYPEDEFS_H
typedef unsigned int uint32_t;
typedef int int32_t;
typedef unsigned short uint16_t;
typedef short int16_t;
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef double float_type;
#endif
/**
@author Lime Microsystems
@brief Stream board communications for Matlab
*/
#include "LMS_SDR.h"
#include "lmsComms.h"
#include "LMS_StreamBoard.h"
#include "ringBuffer.h"
#include "IConnection.h"
#include "fifo.h"
#include "dataTypes.h"
#include <unistd.h>
#include <thread>
#include <vector>
#include <atomic>
#include <thread>
#include <mutex>
#include <chrono>
#define _USE_MATH_DEFINES
#include <math.h>
using namespace std;
typedef enum
{
LMS_SUCCESS = 0,
LMS_ERROR
} LMS_STATUS;
LMS_SamplesFIFO rxBuffer(1);
static thread rxThread;
atomic<bool> rxStop(1);
atomic<bool> rxRunning(0);
atomic<unsigned long> rxDroppedSamples(0);
atomic<long> RxDataRate(0);
atomic<uint32_t> rxSamplingRate(0);
LMS_SamplesFIFO txBuffer(1);
static thread txThread;
atomic<bool> txStop(1);
atomic<bool> txRunning(0);
atomic<long> txDroppedSamples(0);
atomic<long> TxDataRate(0);
atomic<uint32_t> txSamplingRate(0);
LMScomms comPort(IConnection::COM_PORT);
LMScomms usbPort(IConnection::USB_PORT);
LMS_StreamBoard streamer(&usbPort);
const int samplesInPacket = 1024;
unsigned int opMode = 0;
DLL_EXPORT void LMS_Stats(uint32_t *RxBufSize, uint32_t *RxBufFilled, uint32_t *RxSamplingRate, uint32_t *TxBufSize, uint32_t *TxBufFilled, uint32_t *TxSamplingRate)
{
LMS_SamplesFIFO::BufferInfo rxStats = rxBuffer.GetInfo();
LMS_SamplesFIFO::BufferInfo txStats = txBuffer.GetInfo();
if (RxBufSize)
*RxBufSize = rxStats.size*samplesInPacket;
if (RxBufFilled)
*RxBufFilled = rxStats.itemsFilled*samplesInPacket;
if (TxBufSize)
*TxBufSize = txStats.size*samplesInPacket;
if (TxBufFilled)
*TxBufFilled = txStats.itemsFilled*samplesInPacket;
if (TxSamplingRate)
*TxSamplingRate = txSamplingRate.load();
if (RxSamplingRate)
*RxSamplingRate = rxSamplingRate.load();
}
DLL_EXPORT int LMS_Init(const int OperationMode, uint32_t trxBuffersLength)
{
opMode = OperationMode;
unsigned int packetsNeeded = trxBuffersLength / samplesInPacket;
if (trxBuffersLength % samplesInPacket != 0)
++packetsNeeded;
if (packetsNeeded >= (uint32_t)(1 << 31))
packetsNeeded = (uint32_t)(1 << 31);
for (int i = 0; i < 32; ++i)
if ((1 << i) >= packetsNeeded)
{
packetsNeeded = (1 << i);
break;
}
rxBuffer.Reset(packetsNeeded);
txBuffer.Reset(packetsNeeded);
return LMS_SUCCESS;
}
DLL_EXPORT int LMS_Destroy()
{
LMS_RxStop();
//buffers size is reduced to lower memory consumption when not used
rxBuffer.Reset(1);
txBuffer.Reset(1);
return LMS_SUCCESS;
}
DLL_EXPORT LMScomms* LMS_GetUSBPort()
{
return &usbPort;
}
DLL_EXPORT LMScomms* LMS_GetCOMPort()
{
return &comPort;
}
const int maxDevListLen = 32;
const int maxDevNameLen = 256; //each device name not longer than 256
static char DeviceNames[maxDevListLen][maxDevNameLen];
DLL_EXPORT int LMS_UpdateDeviceList(LMScomms* port)
{
memset(DeviceNames, 0, maxDevListLen*maxDevNameLen);
port->Close();
int devCount = port->RefreshDeviceList();
vector<string> names = port->GetDeviceList();
int charsWritten = 0;
for (unsigned int i = 0; i < names.size() && i < maxDevListLen; ++i)
{
charsWritten += sprintf(DeviceNames[i], "[%i] %.*s", i, maxDevNameLen, names[i].c_str());
}
return devCount;
}
DLL_EXPORT const char* LMS_GetDeviceName(LMScomms* port, unsigned int deviceIndex)
{
if (deviceIndex < maxDevListLen)
return DeviceNames[deviceIndex];
else
return "";
}
DLL_EXPORT int LMS_DeviceOpen(LMScomms* port, const uint32_t deviceIndex)
{
port->Close();
int status = port->Open(deviceIndex);
if (status == 1)
{
return LMS_SUCCESS;
}
else
{
return LMS_ERROR;
}
}
DLL_EXPORT void LMS_DeviceClose(LMScomms* port)
{
port->Close();
}
DLL_EXPORT uint32_t LMS_ControlWrite(LMScomms* port, const uint8_t *buffer, const uint16_t bufLen)
{
return port->Write(buffer, bufLen, 0);
}
DLL_EXPORT uint32_t LMS_ControlRead(LMScomms* port, uint8_t* buffer, const uint16_t bufLen)
{
return port->Read(buffer, bufLen, 0);
}
const int RX_BUFF_SZ (1020*1024/4);
uint32_t rx_buffer[RX_BUFF_SZ];
uint64_t start_timestamp = 0;;
uint32_t wr_pos = 0;
uint32_t rd_pos = 0;
void ReceivePackets()
{
rxRunning.store(true);
uint32_t samplesCollected = 0;
const int bufferSize = 4096;// 4096;
const int buffersCount = 32; // must be power of 2
const int buffersCountMask = buffersCount - 1;
int handles[buffersCount]= {0};
char buffers[buffersCount*bufferSize]={0};
struct sched_param sp;
sp.sched_priority = sched_get_priority_max(SCHED_FIFO);
if (pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)!=0)
{
printf("Shed prams failed\n");
}
//switch off Rx
uint16_t regVal = streamer.SPI_read(0x0005);
streamer.SPI_write(0x0005, regVal & ~0x6);
//USB FIFO reset
LMScomms::GenericPacket ctrPkt;
ctrPkt.cmd = CMD_USB_FIFO_RST;
ctrPkt.outBuffer.push_back(0x01);
usbPort.TransferPacket(ctrPkt);
ctrPkt.outBuffer[0] = 0x00;
usbPort.TransferPacket(ctrPkt);
streamer.SPI_write(0x0005, regVal | 0x6);
streamer.SPI_write(0x0001, 0x0001);
streamer.SPI_write(0x0007, 0x0000);
for (int i = 0; i<buffersCount; ++i)
handles[i] = usbPort.BeginDataReading(&buffers[i*bufferSize], bufferSize);
int bi = 0;
while (rxStop.load() != true)
{
if (usbPort.WaitForReading(handles[bi], 1000) == false)
break;
long bytesToRead = bufferSize;
long bytesReceived = usbPort.FinishDataReading(&buffers[bi*bufferSize], bytesToRead, handles[bi]);
if (bytesReceived > 0)
{
PacketLTE* pkt = (PacketLTE*)&buffers[bi*bufferSize];
for(uint16_t sampleIndex = 0; sampleIndex < sizeof(pkt->samples)/sizeof(int16_t); sampleIndex++)
{
pkt->samples[sampleIndex] <<= 4;
pkt->samples[sampleIndex] >>= 4;
}
rxBuffer.push_samples((complex16_t*)pkt->samples, 1020, pkt->counter, 100);
}
// Re-submit this request to keep the queue full
memset(&buffers[bi*bufferSize], 0, bufferSize);
handles[bi] = usbPort.BeginDataReading(&buffers[bi*bufferSize], bufferSize);
bi = (bi + 1) & buffersCountMask;
pthread_yield();
}
usbPort.AbortReading();
for (int j = 0; j<buffersCount; j++)
{
long bytesToRead = bufferSize;
usbPort.WaitForReading(handles[j], 1000);
usbPort.FinishDataReading(&buffers[j*bufferSize], bytesToRead, handles[j]);
}
rxRunning.store(false);
}
DLL_EXPORT uint32_t LMS_TRxWrite(const int16_t *data, const uint32_t samplesCount, const uint32_t antenna_id, uint64_t timestamp)
{
static uint32_t tx_buffer[1020];
static int index = 0;
const int bufferSize = 1024 * 4;
const int buffersCount = 32; // must be power of 2
const int buffersCountMask = buffersCount - 1;
static int handles[buffersCount] = {0};
static char buffers[buffersCount*bufferSize]={0};
static bool bufferUsed[buffersCount] = {0};
static int bi = 0; //buffer index
PacketLTE* pkt;
uint64_t ts = timestamp - index;
pkt = (PacketLTE*)&buffers[bi*bufferSize];
for (int i=0;i<samplesCount;i++)
{
((uint32_t*)pkt->samples)[index++]=(((uint32_t*)data)[i]& 0xFFF0FFF) | 0x1000;
if (index == 1020)
{
pkt->counter = ts;
if (bufferUsed[bi])
{
if (usbPort.WaitForSending(handles[bi], 1000) == false)
return -1;
// Must always call FinishDataXfer to release memory of contexts[i]
long tempToSend = sizeof(PacketLTE);
usbPort.FinishDataSending(&buffers[bi*bufferSize], tempToSend, handles[bi]);
bufferUsed[bi] = false;
}
handles[bi] = usbPort.BeginDataSending(&buffers[bi*bufferSize], sizeof(PacketLTE));
bufferUsed[bi] = true;
bi = (bi + 1) & buffersCountMask;
pkt = (PacketLTE*)&buffers[bi*bufferSize];
ts += 1020;
index = 0;
}
}
}
vector<PacketLTE> PacketsBuffer(2048, PacketLTE());
DLL_EXPORT uint32_t LMS_TRxRead(int16_t *buffer, const uint32_t samplesCount, const uint32_t antenna_id, uint64_t *timestamp, const uint32_t timeout_ms)
{
if (usbPort.IsOpen() == false && opMode != -1)
return 0;
pthread_yield();
uint32_t samplesPopped = rxBuffer.pop_samples((complex16_t*)buffer, samplesCount, timestamp, timeout_ms);
return samplesPopped;
}
DLL_EXPORT int LMS_RxStart()
{
if (rxRunning.load())
return 1;
if (usbPort.IsOpen() == false && opMode != -1)
return 1;
rxStop.store(false);
unsigned int bufSz = rxBuffer.GetInfo().size;
rxBuffer.Reset(bufSz);
rxThread = thread(ReceivePackets);
return 0;
}
DLL_EXPORT int LMS_RxStop()
{
if (rxRunning.load())
{
if (rxThread.joinable())
{
rxStop.store(true);
rxThread.join();
}
rxStop.store(true);
}
return 0;
}
/**
@author Lime Microsystems
@brief Interface for implementing SDR using Lime microsystems boards
*/
#ifndef LMS_SDR_INTERFACE_H
#define LMS_SDR_INTERFACE_H
#include <stdint.h>
#ifdef __cplusplus
class LMScomms;
#else
typedef void LMScomms;
#endif
#define BUILD_DLL
#ifndef __unix__
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#else
#define DLL_EXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Returns stats of internal buffers
@param RxBufSize Receiver buffer size in samples
@param RxBufFilled Number of samples currently in the receiver buffer
@param RxSamplingRate Approximate receiver sampling rate, calculated from incomming data
@param TxBufSize Transmitter buffer size in samples
@param TxBufFilled Number of samples currently in the transmitter buffer
@param TxSamplingRate Approximate transmitter sampling rate, calculated from incomming data
*/
DLL_EXPORT void LMS_Stats(uint32_t *RxBufSize, uint32_t *RxBufFilled, uint32_t *RxSamplingRate, uint32_t *TxBufSize, uint32_t *TxBufFilled, uint32_t *TxSamplingRate);
/** @brief Initializes internal memory for samples buffering to hardware
@param OperationMode samples transfering mode: 0-packets synchronized, 1-packets not synchronized
@param trxBuffersLength Rx and Tx internal buffers size in samples
@return 0 success, -1 failure
Generally trxBuffersSamplesCount should be more than 65536
*/
DLL_EXPORT int LMS_Init(const int OperationMode, uint32_t trxBuffersLength);
/** @brief Stops internal threads and frees internal buffers memory
@return 0 success, -1 failure
*/
DLL_EXPORT int LMS_Destroy();
///@name Device connection
/** @return object for communicating over USB port
*/
DLL_EXPORT LMScomms* LMS_GetUSBPort();
/** @return object for communicating over COM port
*/
DLL_EXPORT LMScomms* LMS_GetCOMPort();
/** @brief Refreshes currently connected device list
@param port Communications port to update
@return number of devices connected
*/
DLL_EXPORT int LMS_UpdateDeviceList(LMScomms* port);
/** @brief Returns pointer to static null terminated c-string name of selected device
@param port Communications port object
@param deviceIndex index from communications port device list
*/
DLL_EXPORT const char* LMS_GetDeviceName(LMScomms* port, unsigned int deviceIndex);
/** @brief Connects to selected device on given port
@param port Communications port object
@param deviceIndex index from communications port device list
@return 0-success
*/
DLL_EXPORT int LMS_DeviceOpen(LMScomms* port, const uint32_t deviceIndex);
/** @brief Closes connection on given port
@param port Communications port to close
*/
DLL_EXPORT void LMS_DeviceClose(LMScomms* port);
///@}
///@name Communications
/** @brief Writes given data to control port
@param port Port for communications
@param buffer data to be written
@param bufLen buffer length in bytes
@return number of bytes written
*/
DLL_EXPORT uint32_t LMS_ControlWrite(LMScomms* port, const uint8_t *buffer, const uint16_t bufLen);
/** @brief Reads given data from SPI regiter
@param port Port for communications
@param buffer destination buffer for data
@param bufLen number of bytes to read
@return number of bytes read
*/
DLL_EXPORT uint32_t LMS_ControlRead(LMScomms* port, uint8_t* buffer, const uint16_t bufLen);
/** @brief Starts thread for samples receiving
@return 0-success
*/
DLL_EXPORT int LMS_RxStart();
/** @brief Stops samples receiving thread
@return 0:success, 1:failed
*/
DLL_EXPORT int LMS_RxStop();
/** @brief Adds given samples to transmitter buffer, to be sent at specified timestamp
@param buffer source array for interleaved values (IQIQIQ...), each value amplitude should be from -2048 to 2047
@param samplesCount number of samples in buffer, 1 sample = 2 bytes I + 2 bytes Q
@param channel_id destination channel
@param timestamp timestamp when the first sample in buffer should be transmitted (used only in synchronized operating mode)
@param timeout_ms time amount in milliseconds to try adding samples
@return number of samples written
*/
DLL_EXPORT uint32_t LMS_TRxWrite(const int16_t *buffer, const uint32_t samplesCount, const uint32_t channel_id, uint64_t timestamp);
/** @brief Reads samples from receiver buffer
@param buffer destination array for interleaved values (IQIQIQ...), must be big enough to store requested number of samples, each value amplitude will be from -2048 to 2047
@param samplesCount number of samples to read, 1 sample = 2 bytes I + 2 bytes Q
@param antenna_id source channel
@param timestamp returns timestamp of the first sample in the buffer (used only in synchronized operating mode)
@param timeout_ms time amount in milliseconds to try reading samples
@return number of samples read
*/
DLL_EXPORT uint32_t LMS_TRxRead(int16_t *buffer, const uint32_t samplesCount, const uint32_t channel_id, uint64_t *timestamp, const uint32_t timeout_ms);
///@}
#ifdef __cplusplus
} //extern "C"
#endif
#endif //LMS_SDR_INTERFACE_H
set(streamBoard_src_files
LMS_StreamBoard.cpp
)
add_library(LMS_StreamBoard STATIC ${streamBoard_src_files})
target_include_directories(LMS_StreamBoard PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(LMS_StreamBoard ConnectionManager)
if(WIN32 AND ENABLE_USB_CONNECTION)
find_package(CyAPI REQUIRED)
LINK_DIRECTORIES(${CYAPI_LIBRARIES})
include_directories(${CYAPI_INCLUDE_DIRS})
set(CONNECTION_MANAGER_LIBS ${CYAPI_LIBRARIES} SetupAPI)
target_link_libraries(LMS_StreamBoard ${CONNECTION_MANAGER_LIBS})
endif()
if(UNIX AND ENABLE_USB_CONNECTION)
set(CONNECTION_MANAGER_LIBS usb-1.0 -lpthread)
target_link_libraries(LMS_StreamBoard ${CONNECTION_MANAGER_LIBS})
endif()
#include "LMS_StreamBoard.h"
#include "lmsComms.h"
#include "lms7002_defines.h"
#include <assert.h>
#include <iostream>
/** @brief Configures Stream board FPGA clocks
@param serPort Communications port to send data
@param fOutTx_MHz transmitter frequency in MHz
@param fOutRx_MHz receiver frequency in MHz
@param phaseShift_deg IQ phase shift in degrees
@return 0-success, other-failure
*/
LMS_StreamBoard::Status LMS_StreamBoard::ConfigurePLL(LMScomms *serPort, const float fOutTx_MHz, const float fOutRx_MHz, const float phaseShift_deg)
{
assert(serPort != nullptr);
if (serPort == NULL)
return FAILURE;
if (serPort->IsOpen() == false)
return FAILURE;
const float vcoLimits_MHz[2] = { 600, 1300 };
int M, C;
const short bufSize = 64;
float fOut_MHz = fOutTx_MHz;
float coef = 0.8*vcoLimits_MHz[1] / fOut_MHz;
M = C = (int)coef;
int chigh = (((int)coef) / 2) + ((int)(coef) % 2);
int clow = ((int)coef) / 2;
LMScomms::GenericPacket pkt;
pkt.cmd = CMD_BRDSPI_WR;
if (fOut_MHz*M > vcoLimits_MHz[0] && fOut_MHz*M < vcoLimits_MHz[1])
{
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x0F);
pkt.outBuffer.push_back(0x15); //c4-c2_bypassed
pkt.outBuffer.push_back(0x01 | ((M % 2 != 0) ? 0x08 : 0x00) | ((C % 2 != 0) ? 0x20 : 0x00)); //N_bypassed
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x08);
pkt.outBuffer.push_back(1); //N_high_cnt
pkt.outBuffer.push_back(1);//N_low_cnt
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x09);
pkt.outBuffer.push_back(chigh); //M_high_cnt
pkt.outBuffer.push_back(clow); //M_low_cnt
for (int i = 0; i <= 1; ++i)
{
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x0A + i);
pkt.outBuffer.push_back(chigh); //cX_high_cnt
pkt.outBuffer.push_back(clow); //cX_low_cnt
}
float Fstep_us = 1 / (8 * fOutTx_MHz*C);
float Fstep_deg = (360 * Fstep_us) / (1 / fOutTx_MHz);
short nSteps = phaseShift_deg / Fstep_deg;
unsigned short reg2 = 0x0400 | (nSteps & 0x3FF);
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x02);
pkt.outBuffer.push_back((reg2 >> 8));
pkt.outBuffer.push_back(reg2); //phase
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x03);
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x01);
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x03);
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x00);
reg2 = reg2 | 0x800;
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x02);
pkt.outBuffer.push_back((reg2 >> 8));
pkt.outBuffer.push_back(reg2);
if(serPort->TransferPacket(pkt) != LMScomms::TRANSFER_SUCCESS || pkt.status != STATUS_COMPLETED_CMD)
return FAILURE;
}
else
return FAILURE;
fOut_MHz = fOutRx_MHz;
coef = 0.8*vcoLimits_MHz[1] / fOut_MHz;
M = C = (int)coef;
chigh = (((int)coef) / 2) + ((int)(coef) % 2);
clow = ((int)coef) / 2;
if (fOut_MHz*M > vcoLimits_MHz[0] && fOut_MHz*M < vcoLimits_MHz[1])
{
short index = 0;
pkt.outBuffer.clear();
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x0F);
pkt.outBuffer.push_back(0x15); //c4-c2_bypassed
pkt.outBuffer.push_back(0x41 | ((M % 2 != 0) ? 0x08 : 0x00) | ((C % 2 != 0) ? 0x20 : 0x00)); //N_bypassed, c1 bypassed
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x08);
pkt.outBuffer.push_back(1); //N_high_cnt
pkt.outBuffer.push_back(1);//N_low_cnt
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x09);
pkt.outBuffer.push_back(chigh); //M_high_cnt
pkt.outBuffer.push_back(clow); //M_low_cnt
for (int i = 0; i <= 1; ++i)
{
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x0A + i);
pkt.outBuffer.push_back(chigh); //cX_high_cnt
pkt.outBuffer.push_back(clow); //cX_low_cnt
}
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x03);
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x02);
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x03);
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x00);
if (serPort->TransferPacket(pkt) != LMScomms::TRANSFER_SUCCESS || pkt.status != STATUS_COMPLETED_CMD)
return FAILURE;
}
else
return FAILURE;
return SUCCESS;
}
/** @brief Captures IQ samples from Stream board, this is blocking function, it blocks until desired frames count is captured
@param isamples destination array for I samples, must be big enough to contain samplesCount
@param qsamples destination array for Q samples, must be big enough to contain samplesCount
@param framesCount number of IQ frames to capture
@param frameStart frame start indicator 0 or 1
@return 0-success, other-failure
*/
LMS_StreamBoard::Status LMS_StreamBoard::CaptureIQSamples(LMScomms *dataPort, int16_t *isamples, int16_t *qsamples, const uint32_t framesCount, const bool frameStart)
{
assert(dataPort != nullptr);
if (dataPort == NULL)
return FAILURE;
if (dataPort->IsOpen() == false)
return FAILURE;
int16_t sample_value;
const uint32_t bufSize = framesCount * 2 * sizeof(uint16_t);
char *buffer = new char[bufSize];
if (buffer == 0)
{
#ifndef NDEBUG
std::cout << "Failed to allocate memory for samples buffer" << std::endl;
#endif
return FAILURE;
}
memset(buffer, 0, bufSize);
LMScomms::GenericPacket pkt;
pkt.cmd = CMD_BRDSPI_RD;
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x05);
dataPort->TransferPacket(pkt);
if (pkt.status != STATUS_COMPLETED_CMD)
return FAILURE;
uint16_t regVal = (pkt.inBuffer[2] * 256) + pkt.inBuffer[3];
pkt.cmd = CMD_BRDSPI_WR;
pkt.outBuffer.clear();
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x05);
pkt.outBuffer.push_back(0);
pkt.outBuffer.push_back(regVal | 0x4);
dataPort->TransferPacket(pkt);
if (pkt.status != STATUS_COMPLETED_CMD)
return FAILURE;
int bytesReceived = 0;
for(int i = 0; i<3; ++i)
bytesReceived = dataPort->ReadStream(buffer, bufSize, 5000);
if (bytesReceived > 0)
{
bool iqSelect = false;
int16_t frameCounter = 0;
for (uint32_t b = 0; b < bufSize;)
{
sample_value = buffer[b++] & 0xFF;
sample_value |= (buffer[b++] & 0x0F) << 8;
sample_value = sample_value << 4; //shift left then right to fill sign bits
sample_value = sample_value >> 4;
if (iqSelect == false)
isamples[frameCounter] = sample_value;
else
qsamples[frameCounter] = sample_value;
frameCounter += iqSelect;
iqSelect = !iqSelect;
}
}
pkt.cmd = CMD_BRDSPI_RD;
pkt.outBuffer.clear();
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x01);
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x05);
dataPort->TransferPacket(pkt);
regVal = (pkt.inBuffer[2] * 256) + pkt.inBuffer[3];
pkt.cmd = CMD_BRDSPI_WR;
pkt.outBuffer.clear();
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x05);
pkt.outBuffer.push_back(0);
pkt.outBuffer.push_back(regVal & ~0x4);
dataPort->TransferPacket(pkt);
delete[] buffer;
return SUCCESS;
}
/** @brief Blocking operation to upload IQ samples to Stream board RAM
@param serPort port to use for communication
@param isamples I channel samples
@param qsamples Q channel samples
@param framesCount number of samples in arrays
@return 0-success, other-failure
*/
LMS_StreamBoard::Status LMS_StreamBoard::UploadIQSamples(LMScomms* serPort, int16_t *isamples, int16_t *qsamples, const uint32_t framesCount)
{
int bufferSize = framesCount * 2;
uint16_t *buffer = new uint16_t[bufferSize];
memset(buffer, 0, bufferSize*sizeof(uint16_t));
int bufPos = 0;
for (unsigned i = 0; i<framesCount; ++i)
{
buffer[bufPos] = (isamples[i] & 0xFFF);
buffer[bufPos + 1] = (qsamples[i] & 0xFFF) | 0x1000;
bufPos += 2;
}
const long outLen = bufPos * 2;
int packetSize = 65536;
int sent = 0;
bool success = true;
LMScomms::GenericPacket pkt;
pkt.cmd = CMD_BRDSPI_RD;
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x05);
serPort->TransferPacket(pkt);
pkt.cmd = CMD_BRDSPI_WR;
pkt.outBuffer.clear();
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x05);
pkt.outBuffer.push_back(pkt.inBuffer[2]);
pkt.outBuffer.push_back(pkt.inBuffer[3] & ~0x7);
serPort->TransferPacket(pkt);
while (sent<outLen)
{
char *outBuf = (char*)buffer;
const long toSendBytes = outLen - sent > packetSize ? packetSize : outLen - sent;
long toSend = toSendBytes;
int context = serPort->BeginDataSending(&outBuf[sent], toSend);
if (serPort->WaitForSending(context, 5000) == false)
{
success = false;
serPort->FinishDataSending(&outBuf[sent], toSend, context);
break;
}
sent += serPort->FinishDataSending(&outBuf[sent], toSend, context);
}
pkt.cmd = CMD_BRDSPI_RD;
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x05);
serPort->TransferPacket(pkt);
pkt.cmd = CMD_BRDSPI_WR;
pkt.outBuffer.clear();
pkt.outBuffer.push_back(0x00);
pkt.outBuffer.push_back(0x05);
pkt.outBuffer.push_back(pkt.inBuffer[2]);
pkt.outBuffer.push_back(pkt.inBuffer[3] | 0x3);
serPort->TransferPacket(pkt);
return success ? SUCCESS : FAILURE;
}
LMS_StreamBoard::LMS_StreamBoard(LMScomms* dataPort)
{
mRxFrameStart.store(true);
mDataPort = dataPort;
mRxFIFO = new LMS_StreamBoard_FIFO<SamplesPacket>(1024*4);
mTxFIFO = new LMS_StreamBoard_FIFO<SamplesPacket>(1024*4);
mStreamRunning.store(false);
mTxCyclicRunning.store(false);
}
LMS_StreamBoard::~LMS_StreamBoard()
{
StopReceiving();
delete mRxFIFO;
delete mTxFIFO;
}
/** @brief Crates threads for packets receiving, processing and transmitting
*/
LMS_StreamBoard::Status LMS_StreamBoard::StartReceiving(unsigned int fftSize)
{
if (mStreamRunning.load() == true)
return FAILURE;
if (mDataPort->IsOpen() == false)
return FAILURE;
mRxFIFO->reset();
stopRx.store(false);
threadRx = std::thread(ReceivePackets, this);
mStreamRunning.store(true);
return SUCCESS;
}
/** @brief Stops receiving, processing and transmitting threads
*/
LMS_StreamBoard::Status LMS_StreamBoard::StopReceiving()
{
if (mStreamRunning.load() == false)
return FAILURE;
stopTx.store(true);
stopRx.store(true);
threadRx.join();
mStreamRunning.store(false);
return SUCCESS;
}
/** @brief Function dedicated for receiving data samples from board
*/
void LMS_StreamBoard::ReceivePackets(LMS_StreamBoard* pthis)
{
SamplesPacket pkt;
int samplesCollected = 0;
auto t1 = chrono::high_resolution_clock::now();
auto t2 = chrono::high_resolution_clock::now();
const int buffer_size = 65536;// 4096;
const int buffers_count = 16; // must be power of 2
const int buffers_count_mask = buffers_count - 1;
int handles[buffers_count];
memset(handles, 0, sizeof(int)*buffers_count);
char *buffers = NULL;
buffers = new char[buffers_count*buffer_size];
if (buffers == 0)
{
printf("error allocating buffers\n");
return;
}
memset(buffers, 0, buffers_count*buffer_size);
//USB FIFO reset
LMScomms::GenericPacket ctrPkt;
ctrPkt.cmd = CMD_USB_FIFO_RST;
ctrPkt.outBuffer.push_back(0x01);
pthis->mDataPort->TransferPacket(ctrPkt);
ctrPkt.outBuffer[0] = 0x00;
pthis->mDataPort->TransferPacket(ctrPkt);
uint16_t regVal = pthis->SPI_read(0x0005);
pthis->SPI_write(0x0005, regVal | 0x4);
for (int i = 0; i<buffers_count; ++i)
handles[i] = pthis->mDataPort->BeginDataReading(&buffers[i*buffer_size], buffer_size);
int bi = 0;
int packetsReceived = 0;
unsigned long BytesReceived = 0;
int m_bufferFailures = 0;
short sample;
bool frameStart = pthis->mRxFrameStart.load();
while (pthis->stopRx.load() == false)
{
if (pthis->mDataPort->WaitForReading(handles[bi], 1000) == false)
++m_bufferFailures;
long bytesToRead = buffer_size;
long bytesReceived = pthis->mDataPort->FinishDataReading(&buffers[bi*buffer_size], bytesToRead, handles[bi]);
if (bytesReceived > 0)
{
++packetsReceived;
BytesReceived += bytesReceived;
char* bufStart = &buffers[bi*buffer_size];
for (int p = 0; p < bytesReceived; p+=2)
{
if (samplesCollected == 0) //find frame start
{
int frameStartOffset = FindFrameStart(&bufStart[p], bytesReceived-p, frameStart);
if (frameStartOffset < 0)
break; //frame start was not found, move on to next buffer
p += frameStartOffset;
}
sample = (bufStart[p+1] & 0x0F);
sample = sample << 8;
sample |= (bufStart[p] & 0xFF);
sample = sample << 4;
sample = sample >> 4;
pkt.iqdata[samplesCollected] = sample;
++samplesCollected;
if (pkt.samplesCount == samplesCollected)
{
samplesCollected = 0;
if (pthis->mRxFIFO->push_back(pkt, 200) == false)
++m_bufferFailures;
}
}
}
else
{
++m_bufferFailures;
}
t2 = chrono::high_resolution_clock::now();
long timePeriod = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
if (timePeriod >= 1000)
{
// periodically update frame start, user might change it during operation
frameStart = pthis->mRxFrameStart.load();
float m_dataRate = 1000.0*BytesReceived / timePeriod;
t1 = t2;
BytesReceived = 0;
LMS_StreamBoard_FIFO<SamplesPacket>::Status rxstats = pthis->mRxFIFO->GetStatus();
pthis->mRxDataRate.store(m_dataRate);
pthis->mRxFIFOfilled.store(100.0*rxstats.filledElements / rxstats.maxElements);
#ifndef NDEBUG
printf("Rx: %.1f%% \t rate: %.0f kB/s failures:%i\n", 100.0*rxstats.filledElements / rxstats.maxElements, m_dataRate / 1000.0, m_bufferFailures);
#endif
m_bufferFailures = 0;
}
// Re-submit this request to keep the queue full
memset(&buffers[bi*buffer_size], 0, buffer_size);
handles[bi] = pthis->mDataPort->BeginDataReading(&buffers[bi*buffer_size], buffer_size);
bi = (bi + 1) & buffers_count_mask;
}
pthis->mDataPort->AbortReading();
for (int j = 0; j<buffers_count; j++)
{
long bytesToRead = buffer_size;
pthis->mDataPort->WaitForReading(handles[j], 1000);
pthis->mDataPort->FinishDataReading(&buffers[j*buffer_size], bytesToRead, handles[j]);
}
regVal = pthis->SPI_read(0x0005);
pthis->SPI_write(0x0005, regVal & ~0x4);
delete[] buffers;
#ifndef NDEBUG
printf("Rx finished\n");
#endif
}
/** @brief Function dedicated for transmitting samples to board
*/
void LMS_StreamBoard::TransmitPackets(LMS_StreamBoard* pthis)
{
const int packetsToBatch = 16;
const int buffer_size = sizeof(SamplesPacket)*packetsToBatch;
const int buffers_count = 16; // must be power of 2
const int buffers_count_mask = buffers_count - 1;
int handles[buffers_count];
memset(handles, 0, sizeof(int)*buffers_count);
char *buffers = NULL;
buffers = new char[buffers_count*buffer_size];
if (buffers == 0)
{
printf("error allocating buffers\n");
}
memset(buffers, 0, buffers_count*buffer_size);
bool *bufferUsed = new bool[buffers_count];
memset(bufferUsed, 0, sizeof(bool)*buffers_count);
int bi = 0; //buffer index
SamplesPacket* pkt = new SamplesPacket[packetsToBatch];
int m_bufferFailures = 0;
long bytesSent = 0;
auto t1 = chrono::high_resolution_clock::now();
auto t2 = chrono::high_resolution_clock::now();
long totalBytesSent = 0;
unsigned long outputCounter = 0;
while (pthis->stopTx.load() == false)
{
for (int i = 0; i < packetsToBatch; ++i)
{
if (pthis->mTxFIFO->pop_front(&pkt[i], 200) == false)
{
printf("Error popping from TX\n");
if (pthis->stopTx.load() == false)
break;
continue;
}
}
//wait for desired slot buffer to be transferred
if (bufferUsed[bi])
{
if (pthis->mDataPort->WaitForSending(handles[bi], 1000) == false)
{
++m_bufferFailures;
}
// Must always call FinishDataXfer to release memory of contexts[i]
long bytesToSend = buffer_size;
bytesSent = pthis->mDataPort->FinishDataSending(&buffers[bi*buffer_size], bytesToSend, handles[bi]);
if (bytesSent > 0)
totalBytesSent += bytesSent;
else
++m_bufferFailures;
bufferUsed[bi] = false;
}
memcpy(&buffers[bi*buffer_size], &pkt[0], sizeof(SamplesPacket)*packetsToBatch);
handles[bi] = pthis->mDataPort->BeginDataSending(&buffers[bi*buffer_size], buffer_size);
bufferUsed[bi] = true;
t2 = chrono::high_resolution_clock::now();
long timePeriod = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
if (timePeriod >= 1000)
{
float m_dataRate = 1000.0*totalBytesSent / timePeriod;
t1 = t2;
totalBytesSent = 0;
#ifndef NDEBUG
cout << "Tx rate: " << m_dataRate / 1000 << " kB/s\t failures: " << m_bufferFailures << endl;
#endif
LMS_StreamBoard_FIFO<SamplesPacket>::Status txstats = pthis->mTxFIFO->GetStatus();
pthis->mTxDataRate.store(m_dataRate);
pthis->mTxFIFOfilled.store(100.0*txstats.filledElements / txstats.maxElements);
m_bufferFailures = 0;
}
bi = (bi + 1) & buffers_count_mask;
}
// Wait for all the queued requests to be cancelled
pthis->mDataPort->AbortSending();
for (int j = 0; j<buffers_count; j++)
{
long bytesToSend = buffer_size;
if (bufferUsed[bi])
{
pthis->mDataPort->WaitForSending(handles[j], 1000);
pthis->mDataPort->FinishDataSending(&buffers[j*buffer_size], bytesToSend, handles[j]);
}
}
delete[] buffers;
delete[] bufferUsed;
delete[] pkt;
#ifndef NDEBUG
printf("Tx finished\n");
#endif
}
/** @brief Returns current data state for user interface
*/
LMS_StreamBoard::DataToGUI LMS_StreamBoard::GetIncomingData()
{
std::unique_lock<std::mutex> lck(mLockIncomingPacket);
return mIncomingPacket;
}
/** @brief Returns data rate info and Tx Rx FIFO fill percentage
*/
LMS_StreamBoard::ProgressStats LMS_StreamBoard::GetStats()
{
ProgressStats stats;
stats.RxRate_Bps = mRxDataRate.load();
stats.TxRate_Bps = mTxDataRate.load();
stats.RxFIFOfilled = mRxFIFOfilled.load();
stats.TxFIFOfilled = mTxFIFOfilled.load();
return stats;
}
/** @brief Helper function to write board spi regiters
@param address spi address
@param data register value
*/
LMS_StreamBoard::Status LMS_StreamBoard::SPI_write(uint16_t address, uint16_t data)
{
assert(mDataPort != nullptr);
LMScomms::GenericPacket ctrPkt;
ctrPkt.cmd = CMD_BRDSPI_WR;
ctrPkt.outBuffer.push_back((address >> 8) & 0xFF);
ctrPkt.outBuffer.push_back(address & 0xFF);
ctrPkt.outBuffer.push_back((data >> 8) & 0xFF);
ctrPkt.outBuffer.push_back(data & 0xFF);
mDataPort->TransferPacket(ctrPkt);
return ctrPkt.status == 1 ? SUCCESS : FAILURE;
}
/** @brief Helper function to read board spi registers
@param address spi address
@return register value
*/
uint16_t LMS_StreamBoard::SPI_read(uint16_t address)
{
assert(mDataPort != nullptr);
LMScomms::GenericPacket ctrPkt;
ctrPkt.cmd = CMD_BRDSPI_RD;
ctrPkt.outBuffer.push_back((address >> 8) & 0xFF);
ctrPkt.outBuffer.push_back(address & 0xFF);
mDataPort->TransferPacket(ctrPkt);
if (ctrPkt.status == STATUS_COMPLETED_CMD && ctrPkt.inBuffer.size() >= 4)
return ctrPkt.inBuffer[2] * 256 + ctrPkt.inBuffer[3];
else
return 0;
}
/** @brief Changes which frame start to look for when receiving data
*/
void LMS_StreamBoard::SetRxFrameStart(const bool startValue)
{
mRxFrameStart.store(startValue);
}
/** @brief Searches for frame start index in given buffer
@return frameStart index in buffer, -1 if frame start was not found
Frame start indicator is 13th bit inside each I and Q sample
*/
int LMS_StreamBoard::FindFrameStart(const char* buffer, const int bufLen, const bool frameStart)
{
int startIndex = -1;
for (int i = 0; i < bufLen; i+=2)
if ((buffer[i+1] & 0x10)>0 == frameStart)
{
startIndex = i;
break;
}
return startIndex;
}
/** @brief Starts a thread for continuous cyclic transmitting of given samples
@param isamples I channel samples
@param qsamples Q channel samples
@param framesCount number of samples in given arrays
@return 0:success, other:failure
*/
LMS_StreamBoard::Status LMS_StreamBoard::StartCyclicTransmitting(const int16_t* isamples, const int16_t* qsamples, uint32_t framesCount)
{
if (mDataPort->IsOpen() == false)
return FAILURE;
stopTxCyclic.store(false);
threadTxCyclic = std::thread([](LMS_StreamBoard* pthis)
{
const int buffer_size = 65536;
const int buffers_count = 16; // must be power of 2
const int buffers_count_mask = buffers_count - 1;
int handles[buffers_count];
memset(handles, 0, sizeof(int)*buffers_count);
char *buffers = NULL;
buffers = new char[buffers_count*buffer_size];
if (buffers == 0)
{
printf("error allocating buffers\n");
return 0;
}
memset(buffers, 0, buffers_count*buffer_size);
//timers for data rate calculation
auto t1 = chrono::high_resolution_clock::now();
auto t2 = chrono::high_resolution_clock::now();
int bi = 0; //buffer index
//setup output data
int dataIndex = 0;
for (int i = 0; i < buffers_count; ++i)
{
for (int j = 0; j < buffer_size; ++j)
{
buffers[i*buffer_size + j] = pthis->mCyclicTransmittingSourceData[dataIndex];
++dataIndex;
if (dataIndex > pthis->mCyclicTransmittingSourceData.size())
dataIndex = 0;
}
}
for (int i = 0; i < buffers_count; ++i)
handles[i] = pthis->mDataPort->BeginDataSending(&buffers[i*buffer_size], buffer_size);
int m_bufferFailures = 0;
int bytesSent = 0;
int totalBytesSent = 0;
int sleepTime = 200;
while (pthis->stopTxCyclic.load() != true)
{
if (pthis->mDataPort->WaitForSending(handles[bi], 1000) == false)
{
++m_bufferFailures;
}
long bytesToSend = buffer_size;
bytesSent = pthis->mDataPort->FinishDataSending(&buffers[bi*buffer_size], bytesToSend, handles[bi]);
if (bytesSent > 0)
totalBytesSent += bytesSent;
else
{
++m_bufferFailures;
}
t2 = chrono::high_resolution_clock::now();
long timePeriod = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
if (timePeriod >= 1000)
{
pthis->mTxDataRate.store(1000.0*totalBytesSent / timePeriod);
t1 = t2;
totalBytesSent = 0;
#ifndef NDEBUG
printf("Upload rate: %f\t failures:%li\n", 1000.0*totalBytesSent / timePeriod, m_bufferFailures);
#endif
m_bufferFailures = 0;
}
//fill up next buffer
for (int j = 0; j < buffer_size; ++j)
{
buffers[bi*buffer_size + j] = pthis->mCyclicTransmittingSourceData[dataIndex];
++dataIndex;
if (dataIndex >= pthis->mCyclicTransmittingSourceData.size())
dataIndex = 0;
}
// Re-submit this request to keep the queue full
handles[bi] = pthis->mDataPort->BeginDataSending(&buffers[bi*buffer_size], buffer_size);
bi = (bi + 1) & buffers_count_mask;
}
// Wait for all the queued requests to be cancelled
pthis->mDataPort->AbortSending();
for (int j = 0; j < buffers_count; j++)
{
long bytesToSend = buffer_size;
pthis->mDataPort->WaitForSending(handles[j], 1000);
pthis->mDataPort->FinishDataSending(&buffers[j*buffer_size], bytesToSend, handles[j]);
}
#ifndef NDEBUG
printf("Cyclic transmitting FULLY STOPPED\n");
#endif
delete[] buffers;
return 0;
}, this);
mTxCyclicRunning.store(true);
return LMS_StreamBoard::SUCCESS;
}
/** @brief Stops cyclic transmitting thread
*/
LMS_StreamBoard::Status LMS_StreamBoard::StopCyclicTransmitting()
{
stopTxCyclic.store(true);
if (mTxCyclicRunning.load() == true)
{
threadTxCyclic.join();
mTxCyclicRunning.store(false);
}
return LMS_StreamBoard::SUCCESS;
}
#ifndef STREAM_BOARD_API_H
#define STREAM_BOARD_API_H
#include <stdint.h>
#include <mutex>
#include <atomic>
#include <thread>
#include "LMS_StreamBoard_FIFO.h"
class LMScomms;
class LMS_StreamBoard
{
public:
struct SamplesPacket
{
public:
SamplesPacket() : channel(0)
{}
~SamplesPacket()
{}
SamplesPacket& operator=(const SamplesPacket& obj)
{
memcpy(this->iqdata, obj.iqdata, sizeof(float)*samplesCount);
this->channel = obj.channel;
return *this;
}
const static int samplesCount = 32768;
float iqdata[samplesCount];
int channel;
};
enum Status
{
SUCCESS,
FAILURE,
};
static Status CaptureIQSamples(LMScomms* serPort, int16_t *isamples, int16_t *qsamples, uint32_t framesCount, bool frameStart);
static Status UploadIQSamples(LMScomms* serPort, int16_t *isamples, int16_t *qsamples, uint32_t framesCount);
static Status ConfigurePLL(LMScomms *serPort, const float fOutTx_MHz, const float fOutRx_MHz, const float phaseShift_deg);
struct DataToGUI
{
std::vector<double> samplesI;
std::vector<double> samplesQ;
std::vector<double> fftBins_dbFS;
float nyquist_MHz;
};
struct ProgressStats
{
float RxRate_Bps;
float TxRate_Bps;
float RxFIFOfilled;
float TxFIFOfilled;
};
LMS_StreamBoard(LMScomms* dataPort);
virtual ~LMS_StreamBoard();
void SetRxFrameStart(const bool startValue);
virtual Status StartReceiving(unsigned int fftSize);
virtual Status StopReceiving();
virtual Status StartCyclicTransmitting(const int16_t* isamples, const int16_t* qsamples, uint32_t framesCount);
virtual Status StopCyclicTransmitting();
DataToGUI GetIncomingData();
ProgressStats GetStats();
Status SPI_write(uint16_t address, uint16_t data);
uint16_t SPI_read(uint16_t address);
protected:
static int FindFrameStart(const char* buffer, const int bufLen, const bool frameStart);
std::mutex mLockIncomingPacket;
DataToGUI mIncomingPacket;
LMS_StreamBoard_FIFO<SamplesPacket> *mRxFIFO;
LMS_StreamBoard_FIFO<SamplesPacket> *mTxFIFO;
static void ReceivePackets(LMS_StreamBoard* pthis);
static void TransmitPackets(LMS_StreamBoard* pthis);
std::atomic_bool mRxFrameStart;
std::atomic_bool mStreamRunning;
std::atomic_bool stopRx;
std::atomic_bool stopTx;
std::thread threadRx;
std::thread threadTx;
LMScomms* mDataPort;
std::atomic<unsigned long> mRxDataRate;
std::atomic<unsigned long> mTxDataRate;
std::atomic<int> mRxFIFOfilled;
std::atomic<int> mTxFIFOfilled;
std::vector<int16_t> mCyclicTransmittingSourceData;
std::atomic_bool mTxCyclicRunning;
std::thread threadTxCyclic;
std::atomic_bool stopTxCyclic;
};
#endif
/**
@file LMS_StreamBoard_FIFO.h
@author Lime Microsystems (www.limemicro.com)
@brief blocking FIFO for packets storing
*/
#ifndef LMS_STREAMBOARD_FIFO_H
#define LMS_STREAMBOARD_FIFO_H
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <vector>
#include <mutex>
#include <chrono>
#include <condition_variable>
template<class T>
class LMS_StreamBoard_FIFO
{
private:
LMS_StreamBoard_FIFO(){};
public:
struct Status
{
uint32_t maxElements;
uint32_t filledElements;
uint32_t head;
uint32_t tail;
};
LMS_StreamBoard_FIFO(uint64_t FIFO_length)
{
mHead = 0;
mTail = 0;
mElements.resize(FIFO_length);
mElementsFilled = 0;
}
~LMS_StreamBoard_FIFO()
{
}
/** @brief Copies given src element to queue.
@param src Source data
@return true if element was inserted
Copies element to queue. This function blocks until element is copied to
queue or certain amount of time has passed.
*/
bool push_back(const T &src, unsigned int timeout_ms = 200)
{
std::unique_lock<std::mutex> lck(mElementsLock);
while (mElementsFilled == mElements.size())
{
if (canWrite.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout)
return false;
}
memcpy(&mElements[mTail], &src, sizeof(T));
mTail = (mTail+1) % mElements.size();
++mElementsFilled;
canRead.notify_one();
return true;
}
/** @brief Copies and removes first element from queue to dest.
@param dest destination container for data
@return true if element was copied
Copies element from queue to destination and then removes it.
This function blocks until element is returned, or certain amount of time
has passed.
*/
bool pop_front(T *dest, unsigned int timeout_ms = 200)
{
assert(dest != nullptr);
std::unique_lock<std::mutex> lck(mElementsLock);
while (mElementsFilled == 0)
{
if (canRead.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout)
return false;
}
if (mElementsFilled == 0)
return false;
*dest = mElements[mHead];
memcpy(dest, &mElements[mHead], sizeof(T));
mHead = (mHead + 1) % mElements.size();
--mElementsFilled;
canWrite.notify_one();
return true;
}
void reset()
{
std::unique_lock<std::mutex> lck(mElementsLock);
mElementsFilled = 0;
mHead = 0;
mTail = 0;
}
Status GetStatus()
{
Status stats;
std::unique_lock<std::mutex> lck(mElementsLock);
stats.maxElements = mElements.size();
stats.filledElements = mElementsFilled;
stats.head = mHead;
stats.tail = mTail;
return stats;
};
protected:
uint32_t mHead; //reading pos
uint32_t mTail; //writing pos
uint32_t mElementsFilled;
std::mutex mElementsLock; // condition variable for critical section
std::vector<T> mElements;
std::condition_variable canWrite;
std::condition_variable canRead;
};
#endif // LMS_STREAMBOARD_FIFO_H
/**
@file lms7002_defines.h
@author Lime Microsystems
@brief enumerations of available LMS7002M commands and statuses
*/
#pragma once
const int LMS_RST_DEACTIVATE = 0;
const int LMS_RST_ACTIVATE = 1;
const int LMS_RST_PULSE = 2;
enum eLMS_DEV
{
LMS_DEV_UNKNOWN,
LMS_DEV_EVB6,
LMS_DEV_DIGIGREEN,
LMS_DEV_DIGIRED,
LMS_DEV_EVB7,
LMS_DEV_ZIPPER,
LMS_DEV_SOCKETBOARD,
LMS_DEV_EVB7V2,
LMS_DEV_STREAM,
LMS_DEV_NOVENA,
LMS_DEV_DATASPARK,
LMS_DEV_RFSPARK,
LMS_DEV_LMS6002USB,
LMS_DEV_RFESPARK,
LMS_DEV_COUNT
};
const char LMS_DEV_NAMES[][80] =
{
"UNKNOWN",
"EVB6",
"DigiGreen",
"DigiRed",
"EVB7",
"ZIPPER",
"Socket Board",
"EVB7_v2",
"Stream",
"Novena",
"DataSpark",
"RF-Spark",
"LMS6002-USB Stick",
"RF-ESpark"
};
static const char* GetDeviceName(const eLMS_DEV device)
{
if (LMS_DEV_UNKNOWN < device && device < LMS_DEV_COUNT)
return LMS_DEV_NAMES[device];
else
return LMS_DEV_NAMES[LMS_DEV_UNKNOWN];
}
enum eEXP_BOARD
{
EXP_BOARD_UNKNOWN,
EXP_BOARD_UNSUPPORTED,
EXP_BOARD_NO,
EXP_BOARD_MYRIAD1,
EXP_BOARD_MYRIAD2,
EXP_BOARD_MYRIAD_NOVENA,
EXP_BOARD_HPM1000,
EXP_BOARD_MYRIAD7,
EXP_BOARD_HPM7,
EXP_BOARD_COUNT
};
const char EXP_BOARD_NAMES[][80] =
{
"UNKNOWN",
"UNSUPPORTED",
"NOT AVAILABLE",
"Myriad1",
"Myriad2",
"Novena",
"HPM1000",
"Myriad7",
"HMP7"
};
static const char* GetExpansionBoardName(const eEXP_BOARD board)
{
if (EXP_BOARD_UNKNOWN < board && board < EXP_BOARD_COUNT)
return EXP_BOARD_NAMES[board];
else
return EXP_BOARD_NAMES[EXP_BOARD_UNKNOWN];
}
struct LMS64C_Info
{
unsigned char firmware;
unsigned char deviceType;
unsigned char protocol;
unsigned char hardware;
unsigned char expansionBoard;
};
enum eCMD_LMS
{
CMD_GET_INFO = 0x00,
CMD_LMS6002_RST = 0x10,
///Writes data to SI5356 synthesizer via I2C
CMD_SI5356_WR = 0x11,
///Reads data from SI5356 synthesizer via I2C
CMD_SI5356_RD = 0x12,
///Writes data to SI5351 synthesizer via I2C
CMD_SI5351_WR = 0x13,
///Reads data from SI5351 synthesizer via I2C
CMD_SI5351_RD = 0x14,
///PanelBus DVI (HDMI) Transmitter control
CMD_TFP410_WR = 0x15,
///PanelBus DVI (HDMI) Transmitter control
CMD_TFP410_RD = 0x16,
///Sets new LMS7002M chip’s RESET pin level (0, 1, pulse)
CMD_LMS7002_RST = 0x20,
///Writes data to LMS7002M chip via SPI
CMD_LMS7002_WR = 0x21,
///Reads data from LMS7002M chip via SPI
CMD_LMS7002_RD = 0x22,
///Writes data to LMS6002 chip via SPI
CMD_LMS6002_WR = 0x23,
///Reads data from LMS6002 chip via SPI
CMD_LMS6002_RD = 0x24,
CMD_LMS_LNA = 0x2A,
CMD_LMS_PA = 0x2B,
CMD_PROG_MCU = 0x2C,
///Writes data to ADF4002 chip via SPI
CMD_ADF4002_WR = 0x31,
CMD_USB_FIFO_RST = 0x40,
CMD_PE636040_WR = 0x41,
CMD_PE636040_RD = 0x42,
CMD_GPIO_WR = 0x51,
CMD_GPIO_RD = 0x52,
CMD_ALTERA_FPGA_GW_WR = 0x53,
CMD_ALTERA_FPGA_GW_RD = 0x54,
CMD_BRDSPI_WR = 0x55,//16 bit spi for stream, dataspark control
CMD_BRDSPI_RD = 0x56,//16 bit spi for stream, dataspark control
CMD_BRDSPI8_WR = 0x57, //8 + 8 bit spi for stream, dataspark control
CMD_BRDSPI8_RD = 0x58, //8 + 8 bit spi for stream, dataspark control
CMD_BRDCONF_WR = 0x5D, //write config data to board
CMD_BRDCONF_RD = 0x5E, //read config data from board
CMD_ANALOG_VAL_WR = 0x61, //write analog value
CMD_ANALOG_VAL_RD = 0x62, //read analog value
CMD_MYRIAD_RST = 0x80,
CMD_MYRIAD_WR = 0x81,
CMD_MYRIAD_RD = 0x82,
CMD_MYRIAD_PROG = 0x8C
};
enum eCMD_STATUS
{
STATUS_UNDEFINED,
STATUS_COMPLETED_CMD,
STATUS_UNKNOWN_CMD,
STATUS_BUSY_CMD,
STATUS_MANY_BLOCKS_CMD,
STATUS_ERROR_CMD,
STATUS_WRONG_ORDER_CMD,
STATUS_RESOURCE_DENIED_CMD,
STATUS_COUNT
};
static const char status_text[][32]=
{
"Undefined/Failure",
"Completed",
"Unknown command",
"Busy",
"Too many blocks",
"Error",
"Wrong order",
"Resource denied"
};
static const char* status2string(const int status)
{
if(status >= 0 && status < STATUS_COUNT)
return status_text[status];
else
return "Unknown status";
}
enum eADC_UNITS
{
RAW,
VOLTAGE,
CURRENT,
RESISTANCE,
POWER,
ADC_UNITS_COUNT
};
static const char adc_units_text[][8] = {"", "V", "A", "Ohm", "W"};
static const char* adcUnits2string(const unsigned units)
{
if (units < ADC_UNITS_COUNT)
return adc_units_text[units];
else
return " unknown";
}
set(ENABLE_USB_CONNECTION "YES" CACHE BOOL INTERNAL)
set(ENABLE_SPI_CONNECTION "NO" CACHE BOOL INTERNAL)
set(CONNECTION_MANAGER_DIR connectionManager)
set(connectionManager_src_files
ConnectionManager.cpp
ConnectionCOM.cpp
ConnectionManager.h
ConnectionCOM.h
lmsComms.h
lmsComms.cpp
)
if(ENABLE_USB_CONNECTION)
list(APPEND connectionManager_src_files ConnectionUSB.cpp ConnectionUSB.h)
add_definitions(-DENABLE_USB_CONNECTION)
endif()
if(ENABLE_SPI_CONNECTION)
list(APPEND connectionManager_src_files ConnectionSPI.cpp ConnectionSPI.h)
add_definitions(-DENABLE_SPI_CONNECTION)
endif()
add_library(ConnectionManager STATIC ${connectionManager_src_files})
target_include_directories(ConnectionManager PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
if(WIN32 AND ENABLE_USB_CONNECTION)
find_package(CyAPI REQUIRED)
LINK_DIRECTORIES(${CYAPI_LIBRARIES})
include_directories(${CYAPI_INCLUDE_DIRS})
set(CONNECTION_MANAGER_LIBS ${CYAPI_LIBRARIES} SetupAPI)
target_link_libraries(ConnectionManager ${CONNECTION_MANAGER_LIBS})
endif()
if(UNIX AND ENABLE_USB_CONNECTION)
set(CONNECTION_MANAGER_LIBS usb-1.0 -lpthread)
target_link_libraries(ConnectionManager ${CONNECTION_MANAGER_LIBS})
endif()
/**
@file ConnectionCOM.cpp
@author Lime Microsystems (www.limemicro.com)
@brief Implementation of communications through COM port
*/
#include "ConnectionCOM.h"
#include "string.h"
#ifdef __unix__
#include <fstream>
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <iostream>
#include <stdio.h>
#endif // LINUX
const int COM_RETRY_INTERVAL = 20; //ms
const int COM_TOTAL_TIMEOUT = 300; //ms
/** @brief Initializes com port connection
*/
ConnectionCOM::ConnectionCOM()
{
currentDeviceIndex = -1;
connected = false;
comPortList.clear();
m_deviceNames.clear();
m_connectionType = COM_PORT;
#ifndef __unix__
hComm = INVALID_HANDLE_VALUE;
#else
hComm = -1;
#endif
comBaudrate = 9600;
}
/** @brief When object is destroyed it closes it's opened COM port
*/
ConnectionCOM::~ConnectionCOM()
{
Close();
}
/** @brief Opens connection to first found chip
@return 0-success
*/
IConnection::DeviceStatus ConnectionCOM::Open()
{
comPortList.clear();
if(comPortList.size() == 0)
FindAllComPorts();
m_deviceNames.clear();
if(m_deviceNames.size() == 0)
RefreshDeviceList();
for(unsigned int i=0; i<m_deviceNames.size(); i++)
{
if( Open(i) == SUCCESS)
{
currentDeviceIndex = i;
return SUCCESS;
}
}
return FAILURE;
}
/** @brief Opens connection to selected chip
@param index chip index in device list
@return 0-success
*/
IConnection::DeviceStatus ConnectionCOM::Open(unsigned index)
{
unsigned int toOpen = index;
Close();
if(toOpen < m_deviceNames.size() && m_deviceNames.size() > 0 )
{
comPortName = m_deviceNames[toOpen];
IConnection::DeviceStatus status = Open(comPortName.c_str(), comBaudrate);
if( status == SUCCESS )
currentDeviceIndex = toOpen;
return status;
}
return FAILURE;
}
/** @brief Closes connection to chip
*/
void ConnectionCOM::Close()
{
connected = false;
currentDeviceIndex = -1;
#ifndef __unix__
if (hComm != INVALID_HANDLE_VALUE)
{
SetCommTimeouts(hComm, &m_ctmoOld);
CloseHandle(hComm);
}
hComm = INVALID_HANDLE_VALUE;
#else
if( hComm >= 0)
{
close(hComm);
}
hComm = -1;
#endif
}
/** @brief Returns whether chip is connected
@return chip is connected
*/
bool ConnectionCOM::IsOpen()
{
#ifndef __unix__
if (hComm != INVALID_HANDLE_VALUE && TestConnectivity() )
return true;
#else
if( hComm != -1 && TestConnectivity() )
return true;
#endif
return false;
}
int ConnectionCOM::GetOpenedIndex()
{
return currentDeviceIndex;
}
/** @brief Sends data through COM port
@param buffer data buffer to send
@param length size of data buffer
@param timeout_ms timeout limit for operation in milliseconds
@return Number of bytes sent
*/
int ConnectionCOM::Write(const unsigned char *buffer, int length, int timeout_ms)
{
if(timeout_ms == 0)
{
timeout_ms = COM_TOTAL_TIMEOUT;
}
int retryCount = 0;
const int maxRetries = (timeout_ms/COM_RETRY_INTERVAL) > 1 ? (timeout_ms/COM_RETRY_INTERVAL) : 1;
bool status = false;
#ifndef __unix__
unsigned long bytesWriten = 0;
m_osWOverlap.InternalHigh = 0;
for(int i = 0; i<maxRetries && status == false; ++i)
{
if (!WriteFile(hComm, buffer, length , &bytesWriten, NULL))
{
status = false;
}
else
status = true;
++retryCount;
}
#else
long bytesWriten = 0;
for(int i = 0; i<maxRetries && bytesWriten == 0; ++i)
{
bytesWriten = write(hComm, buffer, length);
if(bytesWriten <= 0)
{
// if(bytesWriten < 0)
// MessageLog::getInstance()->write("COM PORT: error writing data\n", LOG_ERROR);
// if(bytesWriten == 0)
// MessageLog::getInstance()->write("COM PORT: data bytes sent 0\n", LOG_WARNING);
status = false;
}
else
status = true;
++retryCount;
}
#endif
if(bytesWriten == length)
status = true;
return bytesWriten;
}
/** @brief Reads data from COM port
@param buffer pointer to data buffer for receiving
@param length number of bytes to read
@param timeout_ms timeout limit for operation in milliseconds
@return Number of bytes received
*/
int ConnectionCOM::Read(unsigned char *buffer, int length, int timeout_ms)
{
if(timeout_ms == 0)
{
timeout_ms = COM_TOTAL_TIMEOUT;
}
int retryCount = 0;
const int maxRetries = (timeout_ms/COM_RETRY_INTERVAL) > 1 ? (timeout_ms/COM_RETRY_INTERVAL) : 1;
bool status = false;
memset(buffer, 0, length);
long bytesReaded = 0;
unsigned long totalBytesReaded = 0;
char cRawData[COM_BUFFER_LENGTH];
unsigned long bytesToRead = length;
memset(cRawData, '\0', sizeof(cRawData[0])*COM_BUFFER_LENGTH);
for(int i=0; i<maxRetries && status == false; ++i)
{
memset(cRawData, '\0', sizeof(cRawData[0])*COM_BUFFER_LENGTH);
#ifndef __unix__
DWORD bytesReceived = 0;
if ( !ReadFile(hComm, cRawData, bytesToRead, &bytesReceived, NULL) )
{
status = false;
}
bytesReaded = bytesReceived;
#else
bytesReaded = read(hComm, cRawData, bytesToRead);
if(bytesReaded <= 0)
{
// if(bytesReaded < 0)
// MessageLog::getInstance()->write("COM PORT: error reading data\n", LOG_ERROR);
// if(bytesReaded == 0)
// MessageLog::getInstance()->write("COM PORT: reading 0 bytes\n", LOG_WARNING);
status = false;
}
#endif
retryCount++;
for(int j=0; j<bytesReaded; ++j)
{
buffer[totalBytesReaded+j] = cRawData[j];
}
totalBytesReaded += bytesReaded;
if(totalBytesReaded == bytesToRead)
status = true;
}
// ss << " read(" << totalBytesReaded << "): ";
// for(unsigned int i=0; i<64; ++i)
// ss << int2hex(buffer[i], 1) << " ";
// ss << " - retries: " << retryCount-1 << endl;
//MessageLog::getInstance()->write(ss.str(), LOG_DATA);
// if(retryCount == maxRetries)
// MessageLog::getInstance()->write("COM PORT: read data timeout\n", LOG_WARNING);
//
// if(totalBytesReaded > length)
// MessageLog::getInstance()->write("COM PORT: read data corrupted, received length > requested length\n", LOG_ERROR);
return totalBytesReaded;
}
/** @brief Searches for available COM ports and adds them to list
*/
void ConnectionCOM::FindAllComPorts()
{
Close();
comPortList.clear();
#ifndef __unix__
HKEY hSERIALCOMM;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hSERIALCOMM) == ERROR_SUCCESS)
{
// Get the max value name and max value lengths
DWORD dwMaxValueNameLen;
DWORD dwMaxValueLen;
DWORD dwQueryInfo = RegQueryInfoKey(hSERIALCOMM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL);
if (dwQueryInfo == ERROR_SUCCESS)
{
DWORD dwMaxValueNameSizeInChars = dwMaxValueNameLen + 1;
// Include space for the NULL terminator
DWORD dwMaxValueNameSizeInBytes = dwMaxValueNameSizeInChars*sizeof(TCHAR);
DWORD dwMaxValueDataSizeInChars = dwMaxValueLen / sizeof(TCHAR) + 1;
// Include space for the NULL terminator
DWORD dwMaxValueDataSizeInBytes = dwMaxValueDataSizeInChars*sizeof(TCHAR);
// Allocate some space for the value name and value data
TCHAR* szValueName = new TCHAR[dwMaxValueNameSizeInChars];
TCHAR* byValue = new TCHAR[dwMaxValueDataSizeInBytes];
if (szValueName && byValue)
{
// Enumerate all the values underneath HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM
DWORD dwIndex = 0;
DWORD dwType;
DWORD dwValueNameSize = dwMaxValueNameSizeInChars;
DWORD dwDataSize = dwMaxValueDataSizeInBytes;
memset(szValueName, 0, dwMaxValueNameSizeInBytes);
memset(byValue, 0, dwMaxValueDataSizeInBytes);
LONG nEnum = RegEnumValue(hSERIALCOMM, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, (LPBYTE)byValue, &dwDataSize);
while (nEnum == ERROR_SUCCESS)
{
// If the value is of the correct type, then add it to the array
if (dwType == REG_SZ)
{
char portname[512];
TCHAR* szPort = byValue;
int nUserNameLenUnicode = lstrlen( szPort ); // Convert all UNICODE characters
int nUserNameLen = WideCharToMultiByte( CP_ACP, // ANSI Code Page
0, // No special handling of unmapped chars
(LPCWSTR)szPort, // wide-character string to be converted
nUserNameLenUnicode,
NULL, 0, // No output buffer since we are calculating length
NULL, NULL ); // Unrepresented char replacement - Use Default
TCHAR* pszUserName = new TCHAR[ nUserNameLen ]; // nUserNameLen includes the NULL character
WideCharToMultiByte( CP_ACP, // ANSI Code Page
0, // No special handling of unmapped chars
(LPCWSTR)szPort, // wide-character string to be converted
nUserNameLenUnicode,
portname,
nUserNameLen,
NULL, NULL ); // Unrepresented char replacement - Use Default
portname[nUserNameLen] = 0;
#ifdef UNICODE
comPortList.push_back(portname);
#else
comPortList.push_back(szPort);
#endif
}
// Prepare for the next time around
dwValueNameSize = dwMaxValueNameSizeInChars;
dwDataSize = dwMaxValueDataSizeInBytes;
memset(szValueName, 0, dwMaxValueNameSizeInBytes);
memset(byValue, 0, dwMaxValueDataSizeInBytes);
++dwIndex;
nEnum = RegEnumValue(hSERIALCOMM, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, (LPBYTE)byValue, &dwDataSize);
}
}
delete szValueName;
delete byValue;
}
// Close the registry key now that we are finished with it
RegCloseKey(hSERIALCOMM);
if (dwQueryInfo != ERROR_SUCCESS)
SetLastError(dwQueryInfo);
}
#else
char tempBuffer[256];
string result = "";
#warning Currently searching only for ACM connections
system( "ls /dev | grep ttyACM > /tmp/foundSerialPorts.txt");
fstream fin;
fin.open("/tmp/foundSerialPorts.txt", ios::in);
while(!fin.eof())
{
fin.getline(tempBuffer, 256);
result = "/dev/";
result.append(tempBuffer);
if( strlen(tempBuffer) > 3 ) //longer than tty
comPortList.push_back(result);
}
fin.close();
#endif
}
/** @brief Opens COM port
@param comName COM port name
@param baudrate COM port baudrate
@return 0 on success
*/
IConnection::DeviceStatus ConnectionCOM::Open(const char *comName, int baudrate)
{
Close();
if (strlen(comName) == 0)
return FAILURE;
DeviceStatus errorCode = SUCCESS;
#ifndef __unix__
// Initialize Overlap structures
m_osROverlap.Internal = 0;
m_osROverlap.InternalHigh = 0;
m_osROverlap.Offset = 0;
m_osROverlap.OffsetHigh = 0;
m_osROverlap.hEvent = CreateEvent(NULL, false, false, NULL);
m_osWOverlap.Internal = 0;
m_osWOverlap.InternalHigh = 0;
m_osWOverlap.Offset = 0;
m_osWOverlap.OffsetHigh = 0;
m_osWOverlap.hEvent = CreateEvent(NULL, false, false, NULL);
// Initialize DSB structure
memset(&m_dcbCommPort, 0, sizeof(m_dcbCommPort));
m_dcbCommPort.BaudRate = comBaudrate;
m_dcbCommPort.fBinary = 1;
m_dcbCommPort.fParity = 0;
m_dcbCommPort.fOutxCtsFlow = 0;
m_dcbCommPort.fOutxDsrFlow = 0;
m_dcbCommPort.fDtrControl = 0;
m_dcbCommPort.fDsrSensitivity = 0;
m_dcbCommPort.fTXContinueOnXoff = 0;
m_dcbCommPort.fOutX = 0;
m_dcbCommPort.fInX = 0;
m_dcbCommPort.fErrorChar = 0;
m_dcbCommPort.fNull = 0;
m_dcbCommPort.fRtsControl = 0;
m_dcbCommPort.fAbortOnError = 0;
m_dcbCommPort.fDummy2 = 0;
// m_dcbCommPort.wReserved = 0;
m_dcbCommPort.XonLim = 512;
m_dcbCommPort.XoffLim = 512;
m_dcbCommPort.ByteSize = 8;
m_dcbCommPort.Parity = 0;
m_dcbCommPort.StopBits = 0;
//m_dcbCommPort.StopBits = 1;
m_dcbCommPort.XonChar = 17;
m_dcbCommPort.XoffChar = 19;
m_dcbCommPort.ErrorChar = 0;
m_dcbCommPort.EofChar = 26;
m_dcbCommPort.EvtChar = 0;
m_dcbCommPort.wReserved1 = 0;
m_dcbCommPort.DCBlength = sizeof(DCB);
// Initialize Timeout's
m_ctmoNew.ReadIntervalTimeout = 50;
m_ctmoNew.ReadTotalTimeoutMultiplier = 0;
m_ctmoNew.ReadTotalTimeoutConstant = 100; // 1;
m_ctmoNew.WriteTotalTimeoutMultiplier = 0;
m_ctmoNew.WriteTotalTimeoutConstant = 100;
// Open COM port
string stmp;
stmp = "\\\\.\\";
stmp.append(comName);
hComm = CreateFileA(stmp.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hComm != INVALID_HANDLE_VALUE)
{
// Set Events
if (!SetCommMask(hComm, 0))
errorCode = FAILURE;
// Set Timeouts
GetCommTimeouts(hComm, &m_ctmoOld);
if (!SetCommTimeouts(hComm, &m_ctmoNew))
errorCode = FAILURE;
// Set DCB
if (!SetCommState(hComm, &m_dcbCommPort))
errorCode = FAILURE;
}
else
{
errorCode = FAILURE;
};
// Check the results
if (errorCode != 0)
{
//unsigned long err = GetLastError();
CloseHandle(hComm);
hComm = INVALID_HANDLE_VALUE;
return errorCode;
}
else
{
PurgeComm(hComm, PURGE_TXCLEAR | PURGE_RXCLEAR);
return SUCCESS;
}
#else
hComm = open(comName, O_RDWR | O_NOCTTY | O_SYNC);
if(hComm < 0)
{
// printf("%s",strerror(errno));
// MessageLog::getInstance()->write("Connection manager: failed opening COM port\n", LOG_ERROR);
return FAILURE;
}
struct termios tty;
memset(&tty, 0, sizeof(tty));
if( tcgetattr(hComm, &tty) != 0)
{
// MessageLog::getInstance()->write("Connection Manager: error from tcgetattr\n", LOG_ERROR);
return FAILURE;
}
int speed = B9600;
cfsetospeed(&tty, speed);
cfsetispeed(&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
tty.c_iflag &= ~IGNBRK;
tty.c_lflag = 0;
tty.c_oflag = 0;
tty.c_cc[VMIN] = 0; // read non blocking
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_cflag |= (CLOCAL | CREAD);
if(tcsetattr(hComm, TCSANOW, &tty) != 0)
{
// MessageLog::getInstance()->write("Connection manager: error from tcsetattr\n", LOG_ERROR);
return FAILURE;
}
#endif
return SUCCESS;
}
/** @brief Checks if chip is connected to currently open port
@return chip is connected
*/
bool ConnectionCOM::TestConnectivity()
{
//currently set to always return true to show all com ports
return true;
#ifndef __unix__
if (hComm != INVALID_HANDLE_VALUE)
#else
if( hComm >= 0)
#endif
{
// unsigned char out[64];
// unsigned char in[64];
// memset(in, 0, 64);
// out[0] = CMD_GET_INFO;
// SendData(out, 64);
// ReadData(in, 64);
// if(in[0] == CMD_GET_INFO && in[1] == 0x01)
// return true;
// else
// return false;
}
return false;
}
/** @brief Finds all chips connected to com ports
@return number of devices found
*/
int ConnectionCOM::RefreshDeviceList()
{
int wasOpen = -1;
string wasOpenName = "";
if(IsOpen())
{
wasOpen = GetOpenedIndex();
wasOpenName = comPortName;
}
Close();
comPortList.clear();
if(comPortList.size() == 0)
FindAllComPorts();
m_deviceNames.clear();
string comName;
for(unsigned int i=0; i<comPortList.size(); i++)
{
comName = comPortList[i];
#ifndef __unix__
if( Open(comName.c_str(), comBaudrate) == SUCCESS)
{
if( TestConnectivity() ) //if responds add it to device list
m_deviceNames.push_back(comName);
}
Close();
#else
m_deviceNames.push_back(comName);
#endif
}
if(wasOpen != -1)
{
for(unsigned i=0; i<m_deviceNames.size(); ++i)
if(m_deviceNames[i] == wasOpenName)
{
Open(i);
break;
}
}
return m_deviceNames.size();
}
/** @brief Returns found devices names
@return vector of device names
*/
vector<string> ConnectionCOM::GetDeviceNames()
{
return m_deviceNames;
}
/** @brief Purges communication buffers
*/
void ConnectionCOM::ClearComm()
{
#ifndef __unix__
PurgeComm(hComm, PURGE_TXCLEAR|PURGE_RXCLEAR);
#endif
}
/**
@file ConnectionCOM.h
@author Lime Microsystems (www.limemicro.com)
@brief Class for data communications through COM port
*/
#ifndef CONNECTION_COM_PORT_H
#define CONNECTION_COM_PORT_H
#ifndef __unix__
#include "windows.h"
#endif
#include "IConnection.h"
class ConnectionCOM : public IConnection
{
public:
static const int COM_BUFFER_LENGTH = 1024; //max buffer size for data
ConnectionCOM();
~ConnectionCOM();
DeviceStatus Open();
DeviceStatus Open(unsigned i);
void Close();
bool IsOpen();
int GetOpenedIndex();
int Write(const unsigned char *buffer, int length, int timeout_ms = 0);
int Read(unsigned char *buffer, int length, int timeout_ms = 0);
std::vector<std::string> GetDeviceNames();
int RefreshDeviceList();
void ClearComm();
private:
void FindAllComPorts();
DeviceStatus Open(const char *comName, int baudrate);
bool TestConnectivity();
std::string comPortName;
int comBaudrate;
bool connected;
int currentDeviceIndex;
std::vector<std::string> comPortList;
std::vector<std::string> m_deviceNames;
#ifndef __unix__
HANDLE hComm;
COMMTIMEOUTS m_ctmoNew;
COMMTIMEOUTS m_ctmoOld;
OVERLAPPED m_osROverlap;
OVERLAPPED m_osWOverlap;
DCB m_dcbCommPort;
#else
int hComm; //com port file descriptor
#endif
};
#endif
/**
@file ConnectionManager.cpp
@author Lime Microsystems (www.limemicro.com)
@brief Implementation of various connection types to devices
*/
#include "ConnectionManager.h"
#include "ConnectionCOM.h"
#ifdef ENABLE_USB_CONNECTION
#include "ConnectionUSB.h"
#endif
#ifdef ENABLE_SPI_CONNECTION
#include "ConnectionSPI.h"
#endif
#include <sstream>
#include <iomanip>
#include <iostream>
/** @brief Creates connection interfaces
*/
ConnectionManager::ConnectionManager(const IConnection::eConnectionType port_type) : activeControlPort(NULL)
{
mLogData = false;
mOpenedDevice = -1;
if (port_type == IConnection::COM_PORT)
m_connections[IConnection::COM_PORT] = new ConnectionCOM();
#ifdef ENABLE_USB_CONNECTION
if (port_type == IConnection::USB_PORT)
m_connections[IConnection::USB_PORT] = new ConnectionUSB();
#endif
#ifdef ENABLE_SPI_CONNECTION
m_connections[IConnection::SPI_PORT] = new ConnectionSPI();
#endif
}
/** @brief Destroys connection interfaces
*/
ConnectionManager::~ConnectionManager()
{
for (auto iter = m_connections.begin(); iter != m_connections.end(); ++iter)
{
delete iter->second;
}
}
/** @brief Checks if connection to device is opened
@return True if device is connected
*/
bool ConnectionManager::IsOpen()
{
return activeControlPort ? activeControlPort->IsOpen() : false;
}
/** @brief Opens connection to first available device
@return True if connected to device
*/
bool ConnectionManager::Open()
{
return Open(0);
}
/** @brief Connects to selected device
@param i device index from device list
@return 1:Success, 0:failure
*/
int ConnectionManager::Open(unsigned i)
{
if(i >= mDevices.size())
return 0;
if(activeControlPort)
activeControlPort->Close();
switch(mDevices[i].port)
{
case IConnection::COM_PORT:
activeControlPort = m_connections[IConnection::COM_PORT];
break;
case IConnection::USB_PORT:
activeControlPort = m_connections[IConnection::USB_PORT];
break;
case IConnection::SPI_PORT:
activeControlPort = m_connections[IConnection::SPI_PORT];
break;
default:
return 0;
}
mOpenedDevice = -1;
if( i < mDevices.size() )
{
if (activeControlPort->Open(mDevices[i].portIndex) == IConnection::SUCCESS)
{
mOpenedDevice = i;
return 1;
}
}
return 0;
}
/** @brief Closes connection to device
*/
void ConnectionManager::Close()
{
if(activeControlPort)
{
activeControlPort->Close();
//Notify(LMS_Message(MSG_BOARD_DISCONNECTED, "", 0, 0));
}
mOpenedDevice = -1;
}
/** @brief Finds all currently connected devices and forms device list
@return number of devices found
*/
int ConnectionManager::RefreshDeviceList()
{
mDeviceList.clear();
mDevices.clear();
DeviceInfo dev;
for (auto iter = m_connections.begin(); iter != m_connections.end(); ++iter)
{
vector<string> names;
IConnection *port = iter->second;
if(port->RefreshDeviceList() > 0)
{
names = port->GetDeviceNames();
for(unsigned i=0; i<names.size(); ++i)
{
dev.name = names[i];
dev.port = iter->first;
dev.portIndex = i;
mDevices.push_back(dev);
}
}
}
for(unsigned i=0; i<mDevices.size(); ++i)
mDeviceList.push_back(mDevices[i].name);
return mDevices.size();
}
/** @brief Returns currently opened connection index
*/
int ConnectionManager::GetOpenedIndex()
{
return mOpenedDevice;
}
/** @brief Writes given data to currently opened connection
@param buffer outcomming data buffer
@param length bytes to write
@param timeout_ms timeout in milliseconds
@return number of bytes written, on failure negative values
*/
int ConnectionManager::Write(const unsigned char *buffer, const int length, int timeout_ms)
{
if(activeControlPort)
{
int bytesTransferred = activeControlPort->Write(buffer, length, timeout_ms);
#ifndef NDEBUG
if(mLogData)
{
stringstream ss;
ss << "WR(" << (bytesTransferred>=0?bytesTransferred: 0) << "): ";
ss << std::hex << std::setfill('0');
int repeatedZeros = 0;
for(int i=length-1; i>=0; --i)
if(buffer[i] == 0)
++repeatedZeros;
else break;
if(repeatedZeros == 1)
repeatedZeros = 0;
repeatedZeros = repeatedZeros - (repeatedZeros & 0x1);
for(int i=0; i<length-repeatedZeros; ++i)
//casting to short to print as numbers
ss << " " << std::setw(2) << (unsigned short)buffer[i];
if(repeatedZeros > 1)
ss << " (00 x " << std::dec << repeatedZeros << " times)";
cout << ss.str() << endl;
#ifndef __unix__
OutputDebugString(ss.str().c_str());
#endif
}
#endif
return bytesTransferred;
}
return -1;
}
/** @brief Receives data from currently opened connection
@param buffer incomming data buffer, must be big enough for length bytes
@param length bytes to read
@param timeout_ms timeout in milliseconds
@return number of bytes received
*/
int ConnectionManager::Read(unsigned char *buffer, int length, int timeout_ms)
{
if(activeControlPort)
{
int bytesTransferred = activeControlPort->Read(buffer, length, timeout_ms);
#ifndef NDEBUG
if(mLogData)
{
stringstream ss;
ss << "RD(" << (bytesTransferred>=0?bytesTransferred: 0) << "): ";
ss << std::hex << std::setfill('0');
int repeatedZeros = 0;
for(int i=length-1; i>=0; --i)
if(buffer[i] == 0)
++repeatedZeros;
else break;
if(repeatedZeros == 2)
repeatedZeros = 0;
repeatedZeros = repeatedZeros - (repeatedZeros & 0x1);
for(int i=0; i<length-repeatedZeros; ++i)
//casting to short to print as numbers
ss << " " << std::setw(2) << (unsigned short)buffer[i];
if(repeatedZeros > 2)
ss << " (00 x " << std::dec << repeatedZeros << " times)";
cout << ss.str() << endl;
}
#endif
return bytesTransferred;
}
return -1;
}
int ConnectionManager::WriteStream(const char *buffer, int length)
{
return 0;
}
int ConnectionManager::ReadStream(char *buffer, int length, unsigned int timeout_ms)
{
/*int handle = activeControlPort->BeginDataReading(buffer, length);
activeControlPort->WaitForReading(handle, timeout_ms);
long received = length;
activeControlPort->FinishDataReading(buffer, received, handle);
return received;
*/
long len = length;
int status = activeControlPort->ReadDataBlocking(buffer, len, 0);
return len;
}
int ConnectionManager::BeginDataReading(char *buffer, long length)
{
return activeControlPort->BeginDataReading(buffer, length);
}
/**
@brief Blocks until data is received or set number of milliseconds have passed.
@param contextHandle handle returned by BeginDataReading()
@param timeout_ms number of milliseconds to wait
@return 1-data received, 0-data not received
*/
int ConnectionManager::WaitForReading(int contextHandle, unsigned int timeout_ms)
{
return activeControlPort->WaitForReading(contextHandle, timeout_ms);
}
/**
@brief Finished asynchronous data reading.
@param buffer where to put received data
@param length number of bytes to read, will be changed to actual number of bytes received
@param contextHandle context handle returned by BeginDataReading()
@return received data length
*/
int ConnectionManager::FinishDataReading(char *buffer, long &length, int contextHandle)
{
return activeControlPort->FinishDataReading(buffer, length, contextHandle);
}
/**
@brief Aborts reading operations
*/
void ConnectionManager::AbortReading()
{
activeControlPort->AbortReading();
}
/**
@brief Start asynchronous data sending.
@param buffer data buffer to be sent
@param length number of bytes to send.
@return context handle
*/
int ConnectionManager::BeginDataSending(const char *buffer, long length)
{
return activeControlPort->BeginDataSending(buffer, length);
}
/**
@brief Blocks until data is sent or set number of miliseconds have passed.
@param contextHandle handle returned by BeginDataReading()
@param timeout_ms number of miliseconds to wait
@return 1-data sent, 0-data not sent
*/
int ConnectionManager::WaitForSending(int contextHandle, unsigned int timeout_ms)
{
return activeControlPort->WaitForSending(contextHandle, timeout_ms);
}
/**
@brief Finished asynchronous data sending.
@param buffer where to put received data
@param length number of bytes to send, will be changed to actual number of bytes sent
@param contextHandle context handle returned by BeginDataReading()
@return sent data length
*/
int ConnectionManager::FinishDataSending(const char *buffer, long &length, int contextHandle)
{
return activeControlPort->FinishDataSending(buffer, length, contextHandle);
}
/**
@brief Aborts sending operations
*/
void ConnectionManager::AbortSending()
{
activeControlPort->AbortSending();
}
/**
@file ConnectionManager.h
@author Lime Microsystems (www.limemicro.com)
@brief Class for managing connection to devices
*/
#ifndef LMS_CONNECTION_MANAGER_H
#define LMS_CONNECTION_MANAGER_H
#include "IConnection.h"
#include <map>
class ConnectionManager
{
public:
struct DeviceInfo
{
std::string name;
IConnection::eConnectionType port;
int portIndex;
};
ConnectionManager(const IConnection::eConnectionType port_type);
~ConnectionManager();
bool IsOpen();
bool Open();
int Open(unsigned i);
void Close();
int RefreshDeviceList();
int GetOpenedIndex();
std::vector<std::string> GetDeviceList(){return mDeviceList;};
int Write(const unsigned char *buffer, int length, int timeout_ms = 0);
int Read(unsigned char *buffer, int length, int timeout_ms = 0);
int WriteStream(const char *buffer, int length);
int ReadStream(char *buffer, int length, unsigned int timeout_ms);
int BeginDataReading(char *buffer, long length);
int WaitForReading(int contextHandle, unsigned int timeout_ms);
int FinishDataReading(char *buffer, long &length, int contextHandle);
void AbortReading();
int BeginDataSending(const char *buffer, long length);
int WaitForSending(int contextHandle, unsigned int timeout_ms);
int FinishDataSending(const char *buffer, long &length, int contextHandle);
void AbortSending();
protected:
bool mLogData;
/// Port used for communication.
IConnection *activeControlPort;
std::vector<DeviceInfo> mDevices;
std::vector<std::string> mDeviceList;
int mOpenedDevice;
std::map<IConnection::eConnectionType, IConnection*> m_connections;
};
#endif // LMS_CONNECTION_MANAGER_H
/**
@file ConnectionSPI.cpp
@author Lime Microsystems (www.limemicro.com)
@brief Implementation of communications through SPI port
*/
#include "ConnectionSPI.h"
#include "string.h"
#ifdef __unix__
#include <fstream>
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <linux/i2c-dev.h>
#endif // LINUX
#include <iostream>
#include <sstream>
const int ConnectionSPI::cSPI_BUF_SIZE = 128;
const int ConnectionSPI::cSPI_SPEED_HZ = 2000000;
/** @brief Tries to read EEPROM for Novena board signature
@return true if Novena board
*/
bool IsNovenaBoard()
{
#ifdef __unix__
char data[8];
int count = 6;
memset(data, 0, 8);
int addr = 0;
struct i2c_rdwr_ioctl_data session;
struct i2c_msg messages[2];
char set_addr_buf[2];
memset(set_addr_buf, 0, sizeof(set_addr_buf));
memset(data, 0, count);
set_addr_buf[0] = addr>>8;
set_addr_buf[1] = addr;
messages[0].addr = 0xac>>1;
messages[0].flags = 0;
messages[0].len = sizeof(set_addr_buf);
messages[0].buf = set_addr_buf;
messages[1].addr = 0xac>>1;
messages[1].flags = I2C_M_RD;
messages[1].len = count;
messages[1].buf = data;
session.msgs = messages;
session.nmsgs = 2;
bool isNovena = false;
int fd = open("/dev/i2c-2", O_RDWR);
if(fd > 0)
{
if(ioctl(fd, I2C_RDWR, &session) < 0)
{
perror("Unable to communicate with i2c device");
isNovena = false;
}
if(strcmp("Novena", data) == 0)
isNovena = true;
}
close(fd);
return isNovena;
#else
return false;
#endif
}
/** @brief Initializes SPI port and exports needed GPIO
*/
ConnectionSPI::ConnectionSPI()
{
fd = -1;
m_connectionType = SPI_PORT;
std::fstream gpio;
//export SEN pin
gpio.open("/sys/class/gpio/export", ios::out);
if(gpio.good())
{
gpio << 122;
gpio.flush();
gpio.close();
gpio.open("/sys/class/gpio/gpio122/direction", ios::out);
gpio << "out";
gpio.flush();
gpio.close();
m_SEN.open("/sys/class/gpio/gpio122/value", ios::out);
m_SEN<< 1;
m_SEN.flush();
cout << "GPIO122: set to 1" << endl;
}
}
ConnectionSPI::~ConnectionSPI()
{
Close();
m_SEN.close();
}
/** @brief Opens connection to first found chip
@return 0-success
*/
IConnection::DeviceStatus ConnectionSPI::Open()
{
Close();
#ifdef __unix__
fd = open("/dev/spidev2.0", O_RDWR | O_SYNC);
if (fd < 0)
{
//MessageLog::getInstance()->write("SPI PORT: device not found\n", LOG_ERROR);
return IConnection::FAILURE;
}
int mode = SPI_MODE_0;
int ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
printf("can't set spi mode");
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
printf("can't get spi mode");
/*
* bits per word
*/
int bits = 8;
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
printf("can't set bits per word");
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
printf("can't get bits per word");
/*
* max speed hz
*/
int speed = cSPI_SPEED_HZ;
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
printf("can't set max speed hz");
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
printf("can't get max speed hz");
printf("spi mode: 0x%x\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
return IConnection::SUCCESS;
#else
return IConnection::FAILURE;
#endif
}
/** @brief Opens connection to selected chip
@param index chip index in device list
@return 0-success
*/
IConnection::DeviceStatus ConnectionSPI::Open(unsigned index)
{
return Open();
}
/** @brief Closes connection to chip
*/
void ConnectionSPI::Close()
{
#ifdef __unix__
close(fd);
fd = -1;
#endif
}
/** @brief Returns whether chip is connected
@return chip is connected
*/
bool ConnectionSPI::IsOpen()
{
return (fd >= 0);
}
/** @brief Sends data through COM port
@param buffer data buffer to send
@param length size of data buffer
@param timeout_ms timeout limit for operation in milliseconds
@return Number of bytes sent
*/
int ConnectionSPI::Write(const unsigned char *buffer, int length, int timeout_ms)
{
#ifdef __unix__
if(fd < 0)
return 0;
m_SEN << 0;
m_SEN.flush();
unsigned long bytesWritten = 0;
rxbuf.clear();
int bytesReceived = 0;
char rxbytes[2];
while(bytesWritten < length)
{
int toWrite = length-bytesWritten > cSPI_BUF_SIZE ? cSPI_BUF_SIZE : length-bytesWritten;
for(int i=0; i<toWrite; i+=2)
{
if(buffer[i] < 0x80) //reading
{
write(fd, &buffer[i+bytesWritten], 2);
bytesReceived += read(fd, rxbytes, 2);
rxbuf.push_back(rxbytes[0]);
rxbuf.push_back(rxbytes[1]);
}
else //writing
{
write(fd, &buffer[i+bytesWritten], 4);
i+=2; //data bytes have been written
}
}
// stringstream ss;
// ss << "write(" << toWrite << "): ";
// for(int i=0; i<toWrite; ++i)
// {
// char ctemp[16];
// sprintf(ctemp, "%02X", buffer[bytesWritten+i]);
// ss << ctemp << " ";
// }
// ss << endl;
// if(bytesReceived > 0)
// {
// ss << " re443ad(" << toWrite << "): ";
// for(int i=0; i<toWrite; ++i)
// {
// char ctemp[16];
// sprintf(ctemp, "%02X", rxbuf[bytesWritten+i]);
// ss << ctemp << " ";
// }
// ss << endl;
// }
// cout << ss.str() << endl;
// MessageLog::getInstance()->write(ss.str(), LOG_DATA);
bytesWritten += toWrite;
}
m_SEN << 1;
m_SEN.flush();
return bytesWritten;
#else
return 0;
#endif
}
/** @brief Reads data from COM port
@param buffer pointer to data buffer for receiving
@param length number of bytes to read
@param timeout_ms timeout limit for operation in milliseconds
@return Number of bytes received
*/
int ConnectionSPI::Read(unsigned char *buffer, int length, int timeout_ms)
{
#ifdef __unix__
if(fd < 0)
return 0;
//because transfer is done in full duplex, function returns data from last transfer
int tocpy = length > rxbuf.size() ? rxbuf.size() : length;
memcpy(buffer, &rxbuf[0], tocpy);
rxbuf.clear();
return tocpy;
#else
return 0;
#endif
}
/** @brief Finds all chips connected to com ports
@return number of devices found
*/
int ConnectionSPI::RefreshDeviceList()
{
m_deviceNames.clear();
#ifdef __unix__
int spidev = open("/dev/spidev2.0", O_RDWR);
if (spidev >= 0)
{
if(IsNovenaBoard() == true)
m_deviceNames.push_back("SPI (Novena)");
else
m_deviceNames.push_back("SPI");
}
close(spidev);
#endif
return m_deviceNames.size();
}
/** @brief Returns found devices names
@return vector of device names
*/
vector<string> ConnectionSPI::GetDeviceNames()
{
return m_deviceNames;
}
int ConnectionSPI::GetOpenedIndex()
{
return 0;
}
/**
@file ConnectionSPI.h
@author Lime Microsystems (www.limemicro.com)
@brief Class for data communications through SPI port
*/
#ifndef CONNECTION_SPI_PORT_H
#define CONNECTION_SPI_PORT_H
#include "IConnection.h"
#include <fstream>
#include <string>
#include <vector>
class ConnectionSPI : public IConnection
{
public:
static const int cSPI_BUF_SIZE;
static const int cSPI_SPEED_HZ;
ConnectionSPI();
~ConnectionSPI();
DeviceStatus Open();
DeviceStatus Open(unsigned i);
void Close();
bool IsOpen();
int GetOpenedIndex();
int Write(const unsigned char *buffer, int length, int timeout_ms = 0);
int Read(unsigned char *buffer, int length, int timeout_ms = 0);
std::vector<std::string> GetDeviceNames();
int RefreshDeviceList();
protected:
std::vector<std::string> m_deviceNames;
std::vector<unsigned char> rxbuf;
int fd;
std::fstream m_SEN;
};
#endif
/**
@file ConnectionUSB.cpp
@author Lime Microsystems (www.limemicro.com)
@brief Data writing and reading through USB port
*/
#include "ConnectionUSB.h"
#include <string.h>
#ifdef __unix__
#include <thread>
#include <chrono>
#endif
#define USB_TIMEOUT 1000
#define HW_LDIGIRED L"DigiRed"
#define HW_LDIGIGREEN L"DigiGreen"
#define HW_LSTREAMER L"Stream"
#define HW_DIGIRED "DigiRed"
#define HW_DIGIGREEN "DigiGreen"
#define HW_STREAMER "Stream"
#define CTR_W_REQCODE 0xC1
#define CTR_W_VALUE 0x0000
#define CTR_W_INDEX 0x0000
#define CTR_R_REQCODE 0xC0
#define CTR_R_VALUE 0x0000
#define CTR_R_INDEX 0x0000
/** @brief Initializes port type and object necessary to communicate to usb device.
*/
ConnectionUSB::ConnectionUSB()
{
m_hardwareName = "";
isConnected = false;
m_connectionType = USB_PORT;
#ifndef __unix__
USBDevicePrimary = new CCyUSBDevice(NULL);
OutCtrEndPt = NULL;
InCtrEndPt = NULL;
InCtrlEndPt3 = NULL;
OutCtrlEndPt3 = NULL;
#else
dev_handle = 0;
devs = 0;
int r = libusb_init(&ctx); //initialize the library for the session we just declared
if(r < 0)
printf("Init Error %i\n", r); //there was an error
libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation
#endif
currentDeviceIndex = -1;
}
/** @brief Closes connection to chip and deallocates used memory.
*/
ConnectionUSB::~ConnectionUSB()
{
Close();
#ifndef __unix__
delete USBDevicePrimary;
#else
libusb_exit(ctx);
#endif
}
/** @brief Automatically open first available chip connected to usb port.
@return 0-success, other-failure
*/
IConnection::DeviceStatus ConnectionUSB::Open()
{
currentDeviceIndex = -1;
if(m_deviceNames.size() == 0)
RefreshDeviceList();
#ifndef __unix__
for(int i=0; i<USBDevicePrimary->DeviceCount(); ++i)
if( Open(i) == SUCCESS)
{
currentDeviceIndex = i;
return SUCCESS;
}
#else
if(Open(0) == SUCCESS)
return SUCCESS;
#endif
return FAILURE;
}
/** @brief Tries to open connected USB device and find communication endpoints.
@return Returns 1-Success, 0-EndPoints not found or device didn't connect.
*/
IConnection::DeviceStatus ConnectionUSB::Open(unsigned index)
{
#ifndef __unix__
wstring m_hardwareDesc = L"";
if( index < USBDevicePrimary->DeviceCount())
{
if(USBDevicePrimary->Open(index))
{
m_hardwareDesc = USBDevicePrimary->Product;
unsigned int pos;
//determine connected board type
pos = m_hardwareDesc.find(HW_LDIGIRED, 0);
if( pos != wstring::npos )
m_hardwareName = HW_DIGIRED;
else if (m_hardwareDesc.find(HW_LSTREAMER, 0) != wstring::npos)
m_hardwareName = HW_STREAMER;
else
m_hardwareName = HW_STREAMER;
if (InCtrlEndPt3)
{
delete InCtrlEndPt3;
InCtrlEndPt3 = NULL;
}
InCtrlEndPt3 = new CCyControlEndPoint(*USBDevicePrimary->ControlEndPt);
if (OutCtrlEndPt3)
{
delete OutCtrlEndPt3;
OutCtrlEndPt3 = NULL;
}
OutCtrlEndPt3 = new CCyControlEndPoint(*USBDevicePrimary->ControlEndPt);
InCtrlEndPt3->ReqCode = CTR_R_REQCODE;
InCtrlEndPt3->Value = CTR_R_VALUE;
InCtrlEndPt3->Index = CTR_R_INDEX;
OutCtrlEndPt3->ReqCode = CTR_W_REQCODE;
OutCtrlEndPt3->Value = CTR_W_VALUE;
OutCtrlEndPt3->Index = CTR_W_INDEX;
for (int i=0; i<USBDevicePrimary->EndPointCount(); i++)
if(USBDevicePrimary->EndPoints[i]->Address == 0x01)
{
OutEndPt = USBDevicePrimary->EndPoints[i];
long len = OutEndPt->MaxPktSize * 64;
OutEndPt->SetXferSize(len);
break;
}
for (int i=0; i<USBDevicePrimary->EndPointCount(); i++)
if(USBDevicePrimary->EndPoints[i]->Address == 0x81)
{
InEndPt = USBDevicePrimary->EndPoints[i];
long len = InEndPt->MaxPktSize * 64;
InEndPt->SetXferSize(len);
break;
}
isConnected = true;
return SUCCESS;
} //successfully opened device
} //if has devices
return FAILURE;
#else
if(index >= 0 && index < m_dev_pid_vid.size())
{
dev_handle = libusb_open_device_with_vid_pid(ctx, m_dev_pid_vid[index].second, m_dev_pid_vid[index].first);
if(dev_handle == 0)
return FAILURE;
if(libusb_kernel_driver_active(dev_handle, 0) == 1) //find out if kernel driver is attached
{
printf("Kernel Driver Active\n");
if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it
printf("Kernel Driver Detached!\n");
}
int r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the first) of device
if(r < 0)
{
printf("Cannot Claim Interface\n");
return CANNOT_CLAIM_INTERFACE;
}
printf("Claimed Interface\n");
isConnected = true;
return SUCCESS;
}
else
{
return FAILURE;
}
#endif
}
/** @brief Closes communication to device.
*/
void ConnectionUSB::Close()
{
#ifndef __unix__
USBDevicePrimary->Close();
InEndPt = NULL;
OutEndPt = NULL;
if (InCtrlEndPt3)
{
delete InCtrlEndPt3;
InCtrlEndPt3 = NULL;
}
if (OutCtrlEndPt3)
{
delete OutCtrlEndPt3;
OutCtrlEndPt3 = NULL;
}
#else
if(dev_handle != 0)
{
libusb_release_interface(dev_handle, 0);
libusb_close(dev_handle);
dev_handle = 0;
}
#endif
isConnected = false;
}
/** @brief Returns connection status
@return 1-connection open, 0-connection closed.
*/
bool ConnectionUSB::IsOpen()
{
#ifndef __unix__
return USBDevicePrimary->IsOpen() && isConnected;
#else
return isConnected;
#endif
}
/** @brief Sends given data buffer to chip through USB port.
@param buffer data buffer, must not be longer than 64 bytes.
@param length given buffer size.
@param timeout_ms timeout limit for operation in milliseconds
@return number of bytes sent.
*/
int ConnectionUSB::Write(const unsigned char *buffer, const int length, int timeout_ms)
{
long len = length;
if(IsOpen())
{
unsigned char* wbuffer = new unsigned char[length];
memcpy(wbuffer, buffer, length);
if(m_hardwareName == HW_DIGIRED || m_hardwareName == HW_STREAMER)
{
#ifndef __unix__
if(OutCtrlEndPt3)
OutCtrlEndPt3->Write(wbuffer, len);
else
len = 0;
#else
len = libusb_control_transfer(dev_handle, LIBUSB_REQUEST_TYPE_VENDOR,CTR_W_REQCODE ,CTR_W_VALUE, CTR_W_INDEX, wbuffer, length, USB_TIMEOUT);
#endif
}
else
{
#ifndef __unix__
if(OutCtrEndPt)
OutCtrEndPt->XferData(wbuffer, len);
else
len = 0;
#else
int actual = 0;
libusb_bulk_transfer(dev_handle, 0x01, wbuffer, len, &actual, USB_TIMEOUT);
len = actual;
#endif
}
delete wbuffer;
}
else
return 0;
return len;
}
/** @brief Reads data coming from the chip through USB port.
@param buffer pointer to array where received data will be copied, array must be
big enough to fit received data.
@param length number of bytes to read from chip.
@param timeout_ms timeout limit for operation in milliseconds
@return number of bytes received.
*/
int ConnectionUSB::Read(unsigned char *buffer, const int length, int timeout_ms)
{
long len = length;
if(IsOpen())
{
if(m_hardwareName == HW_DIGIRED || m_hardwareName == HW_STREAMER)
{
#ifndef __unix__
if(InCtrlEndPt3)
InCtrlEndPt3->Read(buffer, len);
else
len = 0;
#else
len = libusb_control_transfer(dev_handle, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN ,CTR_R_REQCODE ,CTR_R_VALUE, CTR_R_INDEX, buffer, len, USB_TIMEOUT);
#endif
}
else
{
#ifndef __unix__
if(InCtrEndPt)
InCtrEndPt->XferData(buffer, len);
else
len = 0;
#else
int actual = 0;
libusb_bulk_transfer(dev_handle, 0x81, buffer, len, &actual, USB_TIMEOUT);
len = actual;
#endif
}
}
return len;
}
#ifdef __unix__
/** @brief Function for handling libusb callbacks
*/
void callback_libusbtransfer(libusb_transfer *trans)
{
USBTransferContext *context = reinterpret_cast<USBTransferContext*>(trans->user_data);
switch(trans->status)
{
case LIBUSB_TRANSFER_CANCELLED:
printf("Transfer canceled\n" );
context->bytesXfered = trans->actual_length;
context->done = true;
context->used = false;
context->reset();
break;
case LIBUSB_TRANSFER_COMPLETED:
if(trans->actual_length == context->bytesExpected)
{
context->bytesXfered = trans->actual_length;
context->done = true;
}
//printf("Transfer complete %i\n", trans->actual_length);
break;
case LIBUSB_TRANSFER_ERROR:
printf("TRANSFER ERRRO\n");
break;
case LIBUSB_TRANSFER_TIMED_OUT:
printf("transfer timed out\n");
break;
case LIBUSB_TRANSFER_OVERFLOW:
printf("transfer overflow\n");
break;
case LIBUSB_TRANSFER_STALL:
printf("transfer stalled\n");
break;
}
context->mPacketProcessed.notify_one();
}
#endif
/** @brief Finds all chips connected to usb ports
@return number of devices found
*/
int ConnectionUSB::RefreshDeviceList()
{
#ifndef __unix__
USBDevicePrimary->Close();
currentDeviceIndex = -1;
m_deviceNames.clear();
string name;
if (USBDevicePrimary->DeviceCount())
{
for (int i=0; i<USBDevicePrimary->DeviceCount(); ++i)
{
Open(i);
name = DeviceName();
m_deviceNames.push_back(name);
}
currentDeviceIndex = -1;
}
#else
m_dev_pid_vid.clear();
m_deviceNames.clear();
int usbDeviceCount = libusb_get_device_list(ctx, &devs);
if(usbDeviceCount > 0)
{
libusb_device_descriptor desc;
for(int i=0; i<usbDeviceCount; ++i)
{
int r = libusb_get_device_descriptor(devs[i], &desc);
if(r<0)
printf("failed to get device description\n");
int pid = desc.idProduct;
int vid = desc.idVendor;
if( vid == 1204)
{
if(pid == 34323)
{
m_hardwareName = HW_DIGIGREEN;
m_deviceNames.push_back("DigiGreen");
m_dev_pid_vid.push_back( pair<int,int>(pid,vid));
}
else if(pid == 241)
{
m_hardwareName = HW_DIGIRED;
libusb_device_handle *tempDev_handle;
tempDev_handle = libusb_open_device_with_vid_pid(ctx, vid, pid);
if(libusb_kernel_driver_active(tempDev_handle, 0) == 1) //find out if kernel driver is attached
{
if(libusb_detach_kernel_driver(tempDev_handle, 0) == 0) //detach it
printf("Kernel Driver Detached!\n");
}
if(libusb_claim_interface(tempDev_handle, 0) < 0) //claim interface 0 (the first) of device
{
printf("Cannot Claim Interface\n");
}
string fullName;
//check operating speed
int speed = libusb_get_device_speed(devs[i]);
if(speed == LIBUSB_SPEED_HIGH)
fullName = "USB 2.0";
else if(speed == LIBUSB_SPEED_SUPER)
fullName = "USB 3.0";
else
fullName = "USB";
fullName += " (";
//read device name
char data[255];
memset(data, 0, 255);
int st = libusb_get_string_descriptor_ascii(tempDev_handle, 2, (unsigned char*)data, 255);
if(strlen(data) > 0)
fullName += data;
fullName += ")";
libusb_close(tempDev_handle);
m_deviceNames.push_back(fullName);
m_dev_pid_vid.push_back( pair<int,int>(pid,vid));
}
}
}
}
else
{
libusb_free_device_list(devs, 1);
return 0;
}
#endif
return m_deviceNames.size();
}
void ConnectionUSB::ClearComm()
{
}
/** @return name of currently opened device as string.
*/
string ConnectionUSB::DeviceName()
{
#ifndef __unix__
string name;
char tempName[USB_STRING_MAXLEN];
//memcpy(tempName, USBDevicePrimary->FriendlyName, USB_STRING_MAXLEN);
//name = tempName;
for (int i = 0; i < USB_STRING_MAXLEN; ++i)
tempName[i] = USBDevicePrimary->DeviceName[i];
if (USBDevicePrimary->bSuperSpeed == true)
name = "USB 3.0";
else if (USBDevicePrimary->bHighSpeed == true)
name = "USB 2.0";
else
name = "USB";
name += " (";
name += tempName;
name += ")";
return name;
#else
if(dev_handle != 0)
{
char data[255];
int st = libusb_get_string_descriptor_ascii(dev_handle, 2, (unsigned char*)data, 255);
return string(data);
}
return "no name";
#endif
}
/**
@brief Starts asynchronous data reading from board
@param *buffer buffer where to store received data
@param length number of bytes to read
@return handle of transfer context
*/
int ConnectionUSB::BeginDataReading(char *buffer, long length)
{
int i = 0;
bool contextFound = false;
//find not used context
for(i = 0; i<USB_MAX_CONTEXTS; i++)
{
if(!contexts[i].used)
{
contextFound = true;
break;
}
}
if(!contextFound)
return -1;
contexts[i].used = true;
#ifndef __unix__
if(InEndPt)
contexts[i].context = InEndPt->BeginDataXfer((unsigned char*)buffer, length, contexts[i].inOvLap);
return i;
#else
unsigned int Timeout = 1000;
libusb_transfer *tr = contexts[i].transfer;
libusb_fill_bulk_transfer(tr, dev_handle, 0x81, (unsigned char*)buffer, length, callback_libusbtransfer, &contexts[i], Timeout);
contexts[i].done = false;
contexts[i].bytesXfered = 0;
contexts[i].bytesExpected = length;
int status = libusb_submit_transfer(tr);
int actual = 0;
//int status = libusb_bulk_transfer(dev_handle, 0x81, (unsigned char*)buffer, length, &actual, USB_TIMEOUT);
if(status != 0)
printf("ERROR BEGIN DATA TRANSFER %s\n", libusb_error_name(status));
#endif
return i;
}
/**
@brief Waits for asynchronous data reception
@param contextHandle handle of which context data to wait
@param timeout_ms number of miliseconds to wait
@return 1-data received, 0-data not received
*/
int ConnectionUSB::WaitForReading(int contextHandle, unsigned int timeout_ms)
{
if( contexts[contextHandle].used == true && contextHandle >= 0)
{
int status = 0;
#ifndef __unix__
if(InEndPt)
status = InEndPt->WaitForXfer(contexts[contextHandle].inOvLap, timeout_ms);
return status;
#else
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
if(libusb_handle_events_timeout_completed(ctx, &tv, NULL) != 0)
printf("error libusb_handle_events %i\n", status);
auto t1 = chrono::high_resolution_clock::now();
auto t2 = chrono::high_resolution_clock::now();
while(contexts[contextHandle].done == false && std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count() < timeout_ms)
{
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 300;
std::this_thread::yield();
//if(libusb_handle_events(ctx) != 0)
if(libusb_handle_events_timeout_completed(ctx, &tv, NULL) != 0)
printf("error libusb_handle_events %i\n", status);
t2 = chrono::high_resolution_clock::now();
//std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
std::unique_lock<std::mutex> lck(contexts[contextHandle].m_lock);
while(contexts[contextHandle].done == false) //is changed in libusb callback
{
if(contexts[contextHandle].mPacketProcessed.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout)
return 0;
}
return contexts[contextHandle].done == true;
#endif
}
else
return 0;
}
/**
@brief Finishes asynchronous data reading from board
@param buffer array where to store received data
@param length number of bytes to read, function changes this value to number of bytes actually received
@param contextHandle handle of which context to finish
@return false failure, true number of bytes received
*/
int ConnectionUSB::FinishDataReading(char *buffer, long &length, int contextHandle)
{
if( contexts[contextHandle].used == true && contextHandle >= 0)
{
#ifndef __unix__
int status = 0;
if(InEndPt)
status = InEndPt->FinishDataXfer((unsigned char*)buffer, length, contexts[contextHandle].inOvLap, contexts[contextHandle].context);
contexts[contextHandle].used = false;
contexts[contextHandle].reset();
return length;
#else
length = contexts[contextHandle].bytesXfered;
contexts[contextHandle].used = false;
contexts[contextHandle].reset();
return length;
#endif
}
else
return 0;
}
int ConnectionUSB::ReadDataBlocking(char *buffer, long &length, int timeout_ms)
{
#ifndef __unix__
return InEndPt->XferData((unsigned char*)buffer, length);
#else
return 0;
#endif
}
/**
@brief Aborts reading operations
*/
void ConnectionUSB::AbortReading()
{
#ifndef __unix__
InEndPt->Abort();
#else
for(int i=0; i<USB_MAX_CONTEXTS; ++i)
{
libusb_cancel_transfer( contexts[i].transfer );
}
#endif
}
/**
@brief Starts asynchronous data Sending to board
@param *buffer buffer to send
@param length number of bytes to send
@return handle of transfer context
*/
int ConnectionUSB::BeginDataSending(const char *buffer, long length)
{
int i = 0;
//find not used context
bool contextFound = false;
for(i = 0; i<USB_MAX_CONTEXTS; i++)
{
if(!contextsToSend[i].used)
{
contextFound = true;
break;
}
}
if(!contextFound)
return -1;
contextsToSend[i].used = true;
#ifndef __unix__
if(OutEndPt)
contextsToSend[i].context = OutEndPt->BeginDataXfer((unsigned char*)buffer, length, contextsToSend[i].inOvLap);
return i;
#else
unsigned int Timeout = 1000;
libusb_transfer *tr = contextsToSend[i].transfer;
//libusb_set_iso_packet_lengths(contexts[i].transfer, 512*64);
libusb_fill_bulk_transfer(tr, dev_handle, 0x1, (unsigned char*)buffer, length, callback_libusbtransfer, &contextsToSend[i], Timeout);
contextsToSend[i].done = false;
contextsToSend[i].bytesXfered = 0;
contextsToSend[i].bytesExpected = length;
libusb_submit_transfer(tr);
#endif
return i;
}
/**
@brief Waits for asynchronous data sending
@param contextHandle handle of which context data to wait
@param timeout_ms number of miliseconds to wait
@return 1-data received, 0-data not received
*/
int ConnectionUSB::WaitForSending(int contextHandle, unsigned int timeout_ms)
{
if( contextsToSend[contextHandle].used == true )
{
#ifndef __unix__
int status = 0;
if(OutEndPt)
status = OutEndPt->WaitForXfer(contextsToSend[contextHandle].inOvLap, timeout_ms);
return status;
#else
auto t1 = chrono::high_resolution_clock::now();
auto t2 = chrono::high_resolution_clock::now();
while(contextsToSend[contextHandle].done == false && std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count() < timeout_ms)
{
/* struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
int status = libusb_handle_events_timeout_completed(ctx, &tv, NULL);
if(status != 0)
printf("error libusb_handle_events %i\n", status);*/
t2 = chrono::high_resolution_clock::now();
//std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
std::unique_lock<std::mutex> lck(contextsToSend[contextHandle].m_lock);
while(contextsToSend[contextHandle].done == false) //is changed in libusb callback
{
if(contextsToSend[contextHandle].mPacketProcessed.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout)
return 0;
}
return contextsToSend[contextHandle].done == true;
#endif
}
else
return 0;
}
/**
@brief Finishes asynchronous data sending to board
@param buffer array where to store received data
@param length number of bytes to read, function changes this value to number of bytes acctually received
@param contextHandle handle of which context to finish
@return false failure, true number of bytes sent
*/
int ConnectionUSB::FinishDataSending(const char *buffer, long &length, int contextHandle)
{
if( contextsToSend[contextHandle].used == true)
{
#ifndef __unix__
if(OutEndPt)
OutEndPt->FinishDataXfer((unsigned char*)buffer, length, contextsToSend[contextHandle].inOvLap, contextsToSend[contextHandle].context);
contextsToSend[contextHandle].used = false;
contextsToSend[contextHandle].reset();
return length;
#else
length = contextsToSend[contextHandle].bytesXfered;
contextsToSend[contextHandle].used = false;
contextsToSend[contextHandle].reset();
return length;
#endif
}
else
return 0;
}
/**
@brief Aborts sending operations
*/
void ConnectionUSB::AbortSending()
{
#ifndef __unix__
OutEndPt->Abort();
#else
for (int i = 0; i<USB_MAX_CONTEXTS; ++i)
{
libusb_cancel_transfer(contextsToSend[i].transfer);
}
for(int i=0; i<USB_MAX_CONTEXTS; ++i)
{
contextsToSend[i].used = false;
contextsToSend[i].reset();
}
#endif
}
int ConnectionUSB::GetOpenedIndex()
{
return currentDeviceIndex;
}
/** @brief Returns found devices names
@return vector of device names
*/
vector<string> ConnectionUSB::GetDeviceNames()
{
return m_deviceNames;
}
/**
@file ConnectionUSB.h
@author Lime Microsystems (www.limemicro.com)
@brief Class for data writing and reading through USB port
*/
#ifndef USB_PORT_CONNECTION_H
#define USB_PORT_CONNECTION_H
#include "IConnection.h"
#ifndef __unix__
#include "windows.h"
#include "CyAPI.h"
#else
#include <libusb-1.0/libusb.h>
#include <mutex>
#include <condition_variable>
#include <chrono>
#endif
#define USB_MAX_CONTEXTS 64 //maximum number of contexts for asynchronous transfers
/** @brief Wrapper class for holding USB asynchronous transfers contexts
*/
class USBTransferContext
{
public:
USBTransferContext() : used(false)
{
#ifndef __unix__
inOvLap = new OVERLAPPED;
memset(inOvLap, 0, sizeof(OVERLAPPED));
inOvLap->hEvent = CreateEvent(NULL, false, false, NULL);
context = NULL;
#else
transfer = libusb_alloc_transfer(0);
bytesXfered = 0;
bytesExpected = 0;
done = 0;
#endif
}
~USBTransferContext()
{
#ifndef __unix__
CloseHandle(inOvLap->hEvent);
delete inOvLap;
#else
libusb_free_transfer(transfer);
#endif
}
bool reset()
{
if(used)
return false;
#ifndef __unix__
CloseHandle(inOvLap->hEvent);
memset(inOvLap, 0, sizeof(OVERLAPPED));
inOvLap->hEvent = CreateEvent(NULL, false, false, NULL);
#endif
return true;
}
bool used;
#ifndef __unix__
PUCHAR context;
OVERLAPPED *inOvLap;
#else
libusb_transfer* transfer;
long bytesXfered;
long bytesExpected;
bool done;
std::mutex m_lock;
std::condition_variable mPacketProcessed;
#endif
};
class ConnectionUSB : public IConnection
{
public:
ConnectionUSB();
~ConnectionUSB();
void FindDevices();
DeviceStatus Open();
DeviceStatus Open(unsigned index);
void Close();
bool IsOpen();
int GetOpenedIndex();
int Write(const unsigned char *buffer, int length, int timeout_ms = 0);
int Read(unsigned char *buffer, int length, int timeout_ms = 0);
virtual int BeginDataReading(char *buffer, long length);
virtual int WaitForReading(int contextHandle, unsigned int timeout_ms);
virtual int FinishDataReading(char *buffer, long &length, int contextHandle);
virtual void AbortReading();
virtual int ReadDataBlocking(char *buffer, long &length, int timeout_ms);
virtual int BeginDataSending(const char *buffer, long length);
virtual int WaitForSending(int contextHandle, unsigned int timeout_ms);
virtual int FinishDataSending(const char *buffer, long &length, int contextHandle);
virtual void AbortSending();
std::vector<std::string> GetDeviceNames();
int RefreshDeviceList();
void ClearComm();
private:
int currentDeviceIndex;
std::string DeviceName();
std::vector<std::string> m_deviceNames;
std::string m_hardwareName;
int m_hardwareVer;
USBTransferContext contexts[USB_MAX_CONTEXTS];
USBTransferContext contextsToSend[USB_MAX_CONTEXTS];
void Initialize();
bool isConnected;
int currentPortIndex;
#ifndef __unix__
CCyUSBDevice *USBDevicePrimary;
//control endpoints for DigiRed
CCyControlEndPoint *InCtrlEndPt3;
CCyControlEndPoint *OutCtrlEndPt3;
//control endpoints for DigiGreen
CCyUSBEndPoint *OutCtrEndPt;
CCyUSBEndPoint *InCtrEndPt;
//end points for samples reading and writing
CCyUSBEndPoint *InEndPt;
CCyUSBEndPoint *OutEndPt;
#else
libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
libusb_device_handle *dev_handle; //a device handle
libusb_context *ctx; //a libusb session
std::vector<std::pair<int,int> > m_dev_pid_vid;
#endif
};
#endif
/**
@file IConnection.h
@author Lime Microsystems
@brief Interface class for connection types
*/
#ifndef ICONNECTION_H
#define ICONNECTION_H
#include <string>
#include <vector>
using namespace std;
class IConnection
{
public:
/// Supported connection types.
enum eConnectionType
{
CONNECTION_UNDEFINED = -1,
COM_PORT = 0,
USB_PORT = 1,
SPI_PORT = 2,
//insert new types here
CONNECTION_TYPES_COUNT //used only for memory allocation
};
enum DeviceStatus
{
SUCCESS,
FAILURE,
END_POINTS_NOT_FOUND,
CANNOT_CLAIM_INTERFACE
};
IConnection() : m_connectionType(CONNECTION_UNDEFINED){};
virtual ~IConnection(){};
virtual int RefreshDeviceList() = 0;
virtual DeviceStatus Open(unsigned i) = 0;
virtual void Close() = 0;
virtual bool IsOpen() = 0;
virtual int GetOpenedIndex() = 0;
virtual int Write(const unsigned char *buffer, int length, int timeout_ms = 0) = 0;
virtual int Read(unsigned char *buffer, int length, int timeout_ms = 0) = 0;
virtual std::vector<std::string> GetDeviceNames() = 0;
virtual eConnectionType GetType() { return m_connectionType; };
virtual bool SetParam(const char *name, const char* value) {return false;};
virtual int BeginDataReading(char *buffer, long length){ return -1; };
virtual int WaitForReading(int contextHandle, unsigned int timeout_ms){ return 0;};
virtual int FinishDataReading(char *buffer, long &length, int contextHandle){ return 0;}
virtual void AbortReading(){};
virtual int ReadDataBlocking(char *buffer, long &length, int timeout_ms){ return 0; }
virtual int BeginDataSending(const char *buffer, long length){ return -1; };
virtual int WaitForSending(int contextHandle, unsigned int timeout_ms){ return 0;};
virtual int FinishDataSending(const char *buffer, long &length, int contextHandle){ return 0;}
virtual void AbortSending(){};
protected:
eConnectionType m_connectionType;
};
#endif
/**
@file LMScomms.cpp
@author Lime Microsystems (www.limemicro.com)
@brief Implementation of data transmission to LMS boards
*/
#include "lmsComms.h"
LMScomms::LMScomms(const IConnection::eConnectionType port_type) : ConnectionManager(port_type)
{
callback_logData = nullptr;
unsigned short test = 0x1234;
unsigned char* bytes = (unsigned char*)&test;
if(bytes[0] == 0x12 && bytes[1] == 0x34)
mSystemBigEndian = true;
else
mSystemBigEndian = false;
}
LMScomms::~LMScomms()
{
}
/** @brief Transfers data between packet and connected device
@param pkt packet containing output data and to receive incomming data
@return 0: success, other: failure
*/
LMScomms::TransferStatus LMScomms::TransferPacket(GenericPacket& pkt)
{
std::lock_guard<std::mutex> lock(mControlPortLock);
TransferStatus status = TRANSFER_SUCCESS;
if(IsOpen() == false)
return NOT_CONNECTED;
int packetLen;
eLMS_PROTOCOL protocol = LMS_PROTOCOL_UNDEFINED;
if(activeControlPort->GetType() == IConnection::SPI_PORT)
protocol = LMS_PROTOCOL_NOVENA;
else
protocol = LMS_PROTOCOL_LMS64C;
switch(protocol)
{
case LMS_PROTOCOL_UNDEFINED:
return TRANSFER_FAILED;
case LMS_PROTOCOL_LMS64C:
packetLen = ProtocolLMS64C::pktLength;
break;
case LMS_PROTOCOL_NOVENA:
packetLen = pkt.outBuffer.size() > ProtocolNovena::pktLength ? ProtocolNovena::pktLength : pkt.outBuffer.size();
break;
default:
packetLen = 0;
return TRANSFER_FAILED;
}
int outLen = 0;
unsigned char* outBuffer = NULL;
outBuffer = PreparePacket(pkt, outLen, protocol);
unsigned char* inBuffer = new unsigned char[outLen];
memset(inBuffer, 0, outLen);
int outBufPos = 0;
int inDataPos = 0;
if(outLen == 0)
{
//printf("packet outlen = 0\n");
outLen = 1;
}
if(protocol == LMS_PROTOCOL_NOVENA)
{
bool transferData = true; //some commands are fake, so don't need transferring
if(pkt.cmd == CMD_GET_INFO)
{
//spi does not have GET INFO, fake it to inform what device it is
pkt.status = STATUS_COMPLETED_CMD;
pkt.inBuffer.clear();
pkt.inBuffer.resize(64, 0);
pkt.inBuffer[0] = 0; //firmware
pkt.inBuffer[1] = LMS_DEV_NOVENA; //device
pkt.inBuffer[2] = 0; //protocol
pkt.inBuffer[3] = 0; //hardware
pkt.inBuffer[4] = EXP_BOARD_UNSUPPORTED; //expansion
transferData = false;
}
if(transferData)
{
if (callback_logData)
callback_logData(true, outBuffer, outLen);
int bytesWritten = Write(outBuffer, outLen);
if( bytesWritten == outLen)
{
if(pkt.cmd == CMD_LMS7002_RD)
{
inDataPos = Read(&inBuffer[inDataPos], outLen);
if(inDataPos != outLen)
status = TRANSFER_FAILED;
else
{
if (callback_logData)
callback_logData(false, inBuffer, inDataPos);
}
}
ParsePacket(pkt, inBuffer, inDataPos, protocol);
}
else
status = TRANSFER_FAILED;
}
}
else
{
for(int i=0; i<outLen; i+=packetLen)
{
int bytesToSend = packetLen;
if (callback_logData)
callback_logData(true, &outBuffer[outBufPos], bytesToSend);
if( Write(&outBuffer[outBufPos], bytesToSend) )
{
outBufPos += packetLen;
long readLen = packetLen;
int bread = Read(&inBuffer[inDataPos], readLen);
if(bread != readLen && protocol != LMS_PROTOCOL_NOVENA)
{
status = TRANSFER_FAILED;
break;
}
if (callback_logData)
callback_logData(false, &inBuffer[inDataPos], bread);
inDataPos += bread;
}
else
{
status = TRANSFER_FAILED;
break;
}
}
ParsePacket(pkt, inBuffer, inDataPos, protocol);
}
delete outBuffer;
delete inBuffer;
return status;
}
/** @brief Returns connected device information
*/
LMSinfo LMScomms::GetInfo()
{
LMSinfo info;
info.device = LMS_DEV_UNKNOWN;
info.expansion = EXP_BOARD_UNKNOWN;
info.firmware = 0;
info.hardware = 0;
info.protocol = 0;
GenericPacket pkt;
pkt.cmd = CMD_GET_INFO;
LMScomms::TransferStatus status = TransferPacket(pkt);
if (status == LMScomms::TRANSFER_SUCCESS && pkt.inBuffer.size() >= 5)
{
info.firmware = pkt.inBuffer[0];
info.device = pkt.inBuffer[1] < LMS_DEV_COUNT ? (eLMS_DEV)pkt.inBuffer[1] : LMS_DEV_UNKNOWN;
info.protocol = pkt.inBuffer[2];
info.hardware = pkt.inBuffer[3];
info.expansion = pkt.inBuffer[4] < EXP_BOARD_COUNT ? (eEXP_BOARD)pkt.inBuffer[4] : EXP_BOARD_UNKNOWN;
}
return info;
}
/** @brief Takes generic packet and converts to specific protocol buffer
@param pkt generic data packet to convert
@param length returns length of returned buffer
@param protocol which protocol to use for data
@return pointer to data buffer, must be manually deleted after use
*/
unsigned char* LMScomms::PreparePacket(const GenericPacket& pkt, int& length, const eLMS_PROTOCOL protocol)
{
unsigned char* buffer = NULL;
if(protocol == LMS_PROTOCOL_UNDEFINED)
return NULL;
if(protocol == LMS_PROTOCOL_LMS64C)
{
ProtocolLMS64C packet;
int maxDataLength = packet.maxDataLength;
packet.cmd = pkt.cmd;
packet.status = pkt.status;
int byteBlockRatio = 1; //block ratio - how many bytes in one block
switch( packet.cmd )
{
case CMD_PROG_MCU:
case CMD_GET_INFO:
case CMD_SI5351_RD:
case CMD_SI5356_RD:
byteBlockRatio = 1;
break;
case CMD_SI5351_WR:
case CMD_SI5356_WR:
byteBlockRatio = 2;
break;
case CMD_LMS7002_RD:
case CMD_BRDSPI_RD:
case CMD_BRDSPI8_RD:
byteBlockRatio = 2;
break;
case CMD_ADF4002_WR:
byteBlockRatio = 3;
break;
case CMD_LMS7002_WR:
case CMD_BRDSPI_WR:
case CMD_ANALOG_VAL_WR:
byteBlockRatio = 4;
break;
default:
byteBlockRatio = 1;
}
if (packet.cmd == CMD_LMS7002_RD || packet.cmd == CMD_BRDSPI_RD)
maxDataLength = maxDataLength/2;
if (packet.cmd == CMD_ANALOG_VAL_RD)
maxDataLength = maxDataLength / 4;
int blockCount = pkt.outBuffer.size()/byteBlockRatio;
int bufLen = blockCount/(maxDataLength/byteBlockRatio)
+(blockCount%(maxDataLength/byteBlockRatio)!=0);
bufLen *= packet.pktLength;
if(bufLen == 0)
bufLen = packet.pktLength;
buffer = new unsigned char[bufLen];
memset(buffer, 0, bufLen);
int srcPos = 0;
for(int j=0; j*packet.pktLength<bufLen; ++j)
{
int pktPos = j*packet.pktLength;
buffer[pktPos] = packet.cmd;
buffer[pktPos+1] = packet.status;
if(blockCount > (maxDataLength/byteBlockRatio))
{
buffer[pktPos+2] = maxDataLength/byteBlockRatio;
blockCount -= buffer[pktPos+2];
}
else
buffer[pktPos+2] = blockCount;
memcpy(&buffer[pktPos+3], packet.reserved, sizeof(packet.reserved));
int bytesToPack = (maxDataLength/byteBlockRatio)*byteBlockRatio;
for (int k = 0; k<bytesToPack && srcPos < pkt.outBuffer.size(); ++srcPos, ++k)
buffer[pktPos + 8 + k] = pkt.outBuffer[srcPos];
}
length = bufLen;
}
else if(protocol == LMS_PROTOCOL_NOVENA)
{
if(pkt.cmd == CMD_LMS7002_RST)
{
buffer = new unsigned char[8];
buffer[0] = 0x88;
buffer[1] = 0x06;
buffer[2] = 0x00;
buffer[3] = 0x18;
buffer[4] = 0x88;
buffer[5] = 0x06;
buffer[6] = 0x00;
buffer[7] = 0x38;
length = 8;
}
else
{
buffer = new unsigned char[pkt.outBuffer.size()];
memcpy(buffer, &pkt.outBuffer[0], pkt.outBuffer.size());
if (pkt.cmd == CMD_LMS7002_WR)
{
for(int i=0; i<pkt.outBuffer.size(); i+=4)
buffer[i] |= 0x80;
}
length = pkt.outBuffer.size();
}
}
return buffer;
}
/** @brief Parses given data buffer into generic packet
@param pkt destination packet
@param buffer received data from board
@param length received buffer length
@param protocol which protocol to use for data parsing
@return 1:success, 0:failure
*/
int LMScomms::ParsePacket(GenericPacket& pkt, const unsigned char* buffer, const int length, const eLMS_PROTOCOL protocol)
{
if(protocol == LMS_PROTOCOL_UNDEFINED)
return -1;
if(protocol == LMS_PROTOCOL_LMS64C)
{
ProtocolLMS64C packet;
int inBufPos = 0;
pkt.inBuffer.resize(packet.maxDataLength*(length / packet.pktLength + (length % packet.pktLength)), 0);
for(int i=0; i<length; i+=packet.pktLength)
{
pkt.cmd = (eCMD_LMS)buffer[i];
pkt.status = (eCMD_STATUS)buffer[i+1];
memcpy(&pkt.inBuffer[inBufPos], &buffer[i+8], packet.maxDataLength);
inBufPos += packet.maxDataLength;
}
}
else if(protocol == LMS_PROTOCOL_NOVENA)
{
pkt.cmd = CMD_LMS7002_RD;
pkt.status = STATUS_COMPLETED_CMD;
pkt.inBuffer.clear();
for(int i=0; i<length; i+=2)
{
//reading from spi returns only registers values
//fill addresses as zeros to match generic format of address, value pairs
pkt.inBuffer.push_back(0); //should be address msb
pkt.inBuffer.push_back(0); //should be address lsb
pkt.inBuffer.push_back(buffer[i]);
pkt.inBuffer.push_back(buffer[i+1]);
}
}
return 1;
}
/** @brief Sets callback function which gets called each time data is sent or received
*/
void LMScomms::SetDataLogCallback(std::function<void(bool, const unsigned char*, const unsigned int)> callback)
{
callback_logData = callback;
}
/**
@file LMScomms.h
@author Lime Microsystems (www.limemicro.com)
@brief Class for handling data transmission to LMS boards
*/
#ifndef LMS_COMMS_H
#define LMS_COMMS_H
#include "lms7002_defines.h"
#include "ConnectionManager.h"
#include <string.h>
#include <mutex>
struct LMSinfo
{
eLMS_DEV device;
eEXP_BOARD expansion;
int firmware;
int hardware;
int protocol;
};
/* @brief Class for abstracting transfering data to and from chip
*/
class LMScomms : public ConnectionManager
{
public:
enum TransferStatus
{
TRANSFER_SUCCESS,
TRANSFER_FAILED,
NOT_CONNECTED
};
enum eLMS_PROTOCOL
{
LMS_PROTOCOL_UNDEFINED = 0,
LMS_PROTOCOL_DIGIC,
LMS_PROTOCOL_LMS64C,
LMS_PROTOCOL_NOVENA,
};
struct ProtocolDIGIC
{
static const int pktLength = 64;
static const int maxDataLength = 60;
ProtocolDIGIC() : cmd(0), i2cAddr(0), blockCount(0) {};
unsigned char cmd;
unsigned char i2cAddr;
unsigned char blockCount;
unsigned char reserved;
unsigned char data[maxDataLength];
};
struct ProtocolLMS64C
{
static const int pktLength = 64;
static const int maxDataLength = 56;
ProtocolLMS64C() :cmd(0),status(STATUS_UNDEFINED),blockCount(0)
{
memset(reserved, 0, 5);
};
unsigned char cmd;
unsigned char status;
unsigned char blockCount;
unsigned char reserved[5];
unsigned char data[maxDataLength];
};
struct ProtocolNovena
{
static const int pktLength = 128;
static const int maxDataLength = 128;
ProtocolNovena() :cmd(0),status(0) {};
unsigned char cmd;
unsigned char status;
unsigned char blockCount;
unsigned char data[maxDataLength];
};
struct GenericPacket
{
GenericPacket()
{
cmd = CMD_GET_INFO;
status = STATUS_UNDEFINED;
}
eCMD_LMS cmd;
eCMD_STATUS status;
vector<unsigned char> outBuffer;
vector<unsigned char> inBuffer;
};
LMScomms(const IConnection::eConnectionType port_type);
~LMScomms();
virtual TransferStatus TransferPacket(GenericPacket &pkt);
LMSinfo GetInfo();
void SetDataLogCallback(std::function<void(bool, const unsigned char*, const unsigned int)> callback);
protected:
std::function<void(bool, const unsigned char*, const unsigned int)> callback_logData;
std::mutex mControlPortLock;
unsigned char* PreparePacket(const GenericPacket &pkt, int &length, const eLMS_PROTOCOL protocol);
int ParsePacket(GenericPacket &pkt, const unsigned char* buffer, const int length, const eLMS_PROTOCOL protocol);
protected:
bool mSystemBigEndian;
};
#endif // LMS_COMMS_H
#ifndef LMS_DATA_TYPES_H
#define LMS_DATA_TYPES_H
typedef struct
{
uint8_t reserved[8];
uint64_t counter;
int16_t samples[2040];
} PacketLTE;
typedef struct
{
int16_t i;
int16_t q;
} complex16_t;
typedef struct
{
uint64_t timestamp; //timestamp of the packet
uint16_t first; //index of first unused sample in samples[]
uint16_t last; //end index of samples
static const uint16_t samplesCount = 1024; //maximum number of samples in packet
complex16_t samples[samplesCount]; //must be power of two
} SamplesPacket;
complex16_t operator &=(complex16_t & other1, const complex16_t & other) // copy assignment
{
other1.i = other.i;
other1.q = other.q;
return other1;
}
#endif
\ No newline at end of file
#ifndef LMS_FIFO_BUFFER_H
#define LMS_FIFO_BUFFER_H
#include <mutex>
#include <atomic>
#include <vector>
#include <thread>
#include <condition_variable>
#include "dataTypes.h"
class LMS_SamplesFIFO
{
public:
struct BufferInfo
{
uint32_t size;
uint32_t itemsFilled;
};
BufferInfo GetInfo()
{
std::unique_lock<std::mutex> lck2(readLock);
std::unique_lock<std::mutex> lck(writeLock);
BufferInfo stats;
stats.size = (uint32_t)mBuffer.size();
stats.itemsFilled = mElementsFilled.load();
return stats;
}
LMS_SamplesFIFO(uint32_t bufLength)
{
Reset(bufLength);
}
~LMS_SamplesFIFO(){};
/** @brief inserts items to ring buffer
@param buffer data source
@param itemCount number of buffer items to insert
@param timeout_ms timeout duration for operation
@param overwrite enable to overwrite oldest items inside the buffer
@return number of items added
*/
uint32_t push_packet(SamplesPacket *buffer, const uint32_t itemCount, const uint32_t timeout_ms, const bool overwrite = true)
{
uint32_t addedItems = 0;
std::unique_lock<std::mutex> lck(writeLock);
while (addedItems < itemCount)
{
while (mElementsFilled.load() >= mBuffer.size()) //wait for free space to insert items
{
if (canWrite.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout)
return addedItems; //dropped all items
}
uint32_t itemsToInsert = itemCount - addedItems;
uint32_t itemsToEnd = (uint32_t)mBuffer.size() - mTail.load(); //might need to split memcpy into two operations
if (itemsToInsert > itemsToEnd)
{
memcpy(&mBuffer[mTail], &buffer[addedItems], itemsToEnd*sizeof(SamplesPacket));
memcpy(&mBuffer[0], &buffer[addedItems+itemsToEnd], (itemsToInsert - itemsToEnd)*sizeof(SamplesPacket));
}
else
memcpy(&mBuffer[mTail], &buffer[addedItems], itemsToInsert*sizeof(SamplesPacket));
mTail.store((mTail.load() + itemsToInsert) & (mBuffer.size() - 1));
mElementsFilled.fetch_add(itemsToInsert);
canRead.notify_one();
addedItems += itemsToInsert;
}
return addedItems;
}
/** @brief inserts items to ring buffer
@param buffer data source
@param itemCount number of buffer items to insert
@param timeout_ms timeout duration for operation
@param overwrite enable to overwrite oldest items inside the buffer
@return number of items added
*/
uint32_t push_samples(const complex16_t *buffer, const uint32_t samplesCount, uint64_t timestamp, const uint32_t timeout_ms, const bool overwrite = true)
{
assert(buffer != nullptr);
const int samplesInPacket = SamplesPacket::samplesCount;
uint32_t samplesTaken = 0;
std::unique_lock<std::mutex> lck(writeLock);
while (samplesTaken < samplesCount)
{
while (mElementsFilled.load() >= mBuffer.size()) //buffer might be full, wait for free slots
{
if (canWrite.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout)
return samplesTaken;
}
int tailIndex = mTail.load(); //which element to fill
while (mElementsFilled.load() < mBuffer.size() && samplesTaken < samplesCount) // not to release lock too often
{
mBuffer[tailIndex].timestamp = timestamp + samplesTaken;
mBuffer[tailIndex].first = 0;
mBuffer[tailIndex].last = 0;
while (mBuffer[tailIndex].last < samplesInPacket && samplesTaken < samplesCount)
{
mBuffer[tailIndex].samples[mBuffer[tailIndex].last++] = buffer[samplesTaken++];
}
mTail.store((tailIndex + 1) & (mBuffer.size() - 1));//advance to next one
tailIndex = mTail.load();
mElementsFilled.fetch_add(1);
canRead.notify_one();
}
}
return samplesTaken;
}
/** @brief Takes items out of ring buffer
@param buffer data destination
@param samplesCount number of samples to pop
@param timestamp returns timestamp of the first sample in buffer
@param timeout_ms timeout duration for operation
@return number of samples returned
*/
uint32_t pop_samples(complex16_t* buffer, const uint32_t samplesCount, uint64_t *timestamp, const uint32_t timeout_ms)
{
assert(buffer != nullptr);
const int samplesInPacket = SamplesPacket::samplesCount;
uint32_t samplesFilled = 0;
*timestamp = 0;
std::unique_lock<std::mutex> lck(readLock);
while (samplesFilled < samplesCount)
{
while (mElementsFilled.load() == 0) //buffer might be empty, wait for packets
{
if (canRead.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout)
return samplesFilled;
}
if(samplesFilled == 0)
*timestamp = mBuffer[mHead.load()].timestamp + mBuffer[mHead.load()].first;
while(mElementsFilled.load() > 0 && samplesFilled < samplesCount)
{
int headIndex = mHead.load();
while (mBuffer[headIndex].first < mBuffer[headIndex].last && samplesFilled < samplesCount)
{
buffer[samplesFilled++] = mBuffer[headIndex].samples[mBuffer[headIndex].first++];
}
if (mBuffer[headIndex].first == mBuffer[headIndex].last) //packet depleated
{
mBuffer[headIndex].first = 0;
mBuffer[headIndex].last = 0;
mBuffer[headIndex].timestamp = 0;
mHead.store( (headIndex + 1) & (mBuffer.size() - 1) );//advance to next one
headIndex = mHead.load();
mElementsFilled.fetch_sub(1);
canWrite.notify_one();
}
}
}
return samplesFilled;
}
void Reset(uint32_t bufLength)
{
std::unique_lock<std::mutex> lck(writeLock);
std::unique_lock<std::mutex> lck2(readLock);
mBuffer.resize(bufLength);
mHead.store(0);
mTail.store(0);
mElementsFilled.store(0);
}
protected:
std::vector<SamplesPacket> mBuffer;
std::atomic<uint32_t> mHead;
std::atomic<uint32_t> mTail;
std::mutex writeLock;
std::mutex readLock;
std::atomic<uint32_t> mElementsFilled;
std::condition_variable canWrite;
std::condition_variable canRead;
};
#endif
#ifndef LMS_RING_BUFFER_H
#define LMS_RING_BUFFER_H
#include <mutex>
#include <atomic>
#include <vector>
#include <condition_variable>
template<class T>
class RingBuffer
{
public:
struct BufferInfo
{
uint32_t size;
uint32_t itemsFilled;
};
BufferInfo GetInfo()
{
unique_lock<mutex> lck(mLock);
BufferInfo stats;
stats.size = (uint32_t)mBuffer.size();
stats.itemsFilled = mElementsFilled;
return stats;
}
RingBuffer(uint32_t bufLength)
{
Reset(bufLength);
}
~RingBuffer(){};
/** @brief inserts items to ring buffer
@param buffer data source
@param itemCount number of buffer items to insert
@param timeout_ms timeout duration for operation
@return number of items added
*/
uint32_t push_back(const T* buffer, const uint32_t itemCount, const uint32_t timeout_ms)
{
uint32_t addedItems = 0;
while (addedItems < itemCount)
{
unique_lock<mutex> lck(mLock);
while (mElementsFilled >= mBuffer.size()) //wait for free space to insert items
{
if (canWrite.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout)
return addedItems; //dropped all items
}
uint32_t itemsToInsert = itemCount - addedItems;
uint32_t itemsToEnd = (uint32_t)mBuffer.size() - mTail.load(); //might need to split memcpy into two operations
if (itemsToInsert > itemsToEnd)
{
memcpy(&mBuffer[mTail], &buffer[addedItems], itemsToEnd*sizeof(T));
memcpy(&mBuffer[0], &buffer[addedItems+itemsToEnd], (itemsToInsert - itemsToEnd)*sizeof(T));
}
else
memcpy(&mBuffer[mTail], &buffer[addedItems], itemsToInsert*sizeof(T));
mTail.store((mTail.load() + itemsToInsert) & (mBuffer.size() - 1));
mElementsFilled += itemsToInsert;
lck.unlock();
canRead.notify_one();
addedItems += itemsToInsert;
}
return addedItems;
}
/** @brief Takes items out of ring buffer
@param buffer data destination
@param itemCount number of items to extract from ring buffer
@param timeout_ms timeout duration for operation
@return number of items returned
*/
uint32_t pop_front(T* buffer, const uint32_t itemCount, const uint32_t timeout_ms)
{
assert(buffer != nullptr);
uint32_t itemsTaken = 0;
T* destBuffer = buffer;
while (itemsTaken < itemCount)
{
unique_lock<mutex> lck(mLock);
while (mElementsFilled == 0) //buffer might be empty, wait for items
{
if (canRead.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout)
return itemsTaken;
}
unsigned int itemsToCopy = itemCount - itemsTaken;
if (itemsToCopy > mElementsFilled)
itemsToCopy = mElementsFilled;
unsigned int itemsToEnd = (uint32_t)mBuffer.size() - mHead.load(); //migth need to split memcpy into two operations
if (itemsToEnd < itemsToCopy)
{
memcpy(&destBuffer[itemsTaken], &mBuffer[mHead.load()], sizeof(T)*itemsToEnd);
memcpy(&destBuffer[itemsTaken+itemsToEnd], &mBuffer[0], sizeof(T)*(itemsToCopy - itemsToEnd));
mHead.store((itemsToCopy - itemsToEnd) & (mBuffer.size() - 1));
}
else
{
memcpy(&destBuffer[itemsTaken], &mBuffer[mHead.load()], sizeof(T)*itemsToCopy);
int headVal = mHead.load();
int valueToStore = (headVal + itemsToCopy) & (mBuffer.size() - 1);
mHead.store(valueToStore);
headVal = mHead.load();
}
mElementsFilled -= itemsToCopy;
lck.unlock();
canWrite.notify_one();
itemsTaken += itemsToCopy;
}
return itemsTaken;
}
void Reset(uint32_t bufLength)
{
std::unique_lock<std::mutex> lck(mLock);
if (bufLength >= (uint32_t)(1 << 31))
bufLength = (uint32_t)(1 << 31);
for (int i = 0; i < 32; ++i)
if ((1 << i) >= bufLength)
{
bufLength = (1 << i);
break;
}
mBuffer.resize(bufLength);
mHead.store(0);
mTail.store(0);
mElementsFilled = 0;
}
protected:
std::vector<T> mBuffer;
std::atomic<uint32_t> mHead;
std::atomic<uint32_t> mTail;
std::mutex mLock;
uint32_t mElementsFilled;
std::condition_variable canWrite;
std::condition_variable canRead;
};
#endif
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface 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.
OpenAirInterface 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 OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/ether.h>
#include <unistd.h>
#include <errno.h>
#include "common_lib.h"
#include "LMS_SDR.h"
#include "LMS7002M.h"
#include "Si5351C.h"
#include "LMS_StreamBoard.h"
#include "LMS7002M_RegistersMap.h"
#include <cmath>
///define for parameter enumeration if prefix might be needed
#define LMS7param(id) id
LMScomms* usbport;
LMScomms* comport;
LMS7002M* lms7;
Si5351C* Si;
LMS_StreamBoard *lmsStream;
#define RXDCLENGTH 4096
#define NUMBUFF 40
int16_t cos_fsover8[8] = {2047, 1447, 0, -1448, -2047, -1448, 0, 1447};
int16_t cos_3fsover8[8] = {2047, -1448, 0, 1447, -2047, 1447, 0, -1448};
extern "C"
{
int write_output(const char *fname,const char *vname,void *data,int length,int dec,char format);
}
int trx_lms_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int antenna_id, int flags) {
LMS_TRxWrite((int16_t*)buff[0], nsamps,0, timestamp);
return nsamps;
}
int trx_lms_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int antenna_id) {
uint64_t timestamp;
int16_t *dst_ptr = (int16_t*) buff[0];
int ret;
ret = LMS_TRxRead(dst_ptr, nsamps,0,&timestamp, 100);
*ptimestamp=timestamp;
return ret;
}
void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index) {
int i=0;
// loop through calibration table to find best adjustment factor for RX frequency
double min_diff = 6e9,diff;
while (openair0_cfg->rx_gain_calib_table[i].freq>0) {
diff = fabs(openair0_cfg->rx_freq[chain_index] - openair0_cfg->rx_gain_calib_table[i].freq);
printf("cal %d: freq %f, offset %f, diff %f\n",
i,
openair0_cfg->rx_gain_calib_table[i].freq,
openair0_cfg->rx_gain_calib_table[i].offset,diff);
if (min_diff > diff) {
min_diff = diff;
openair0_cfg->rx_gain_offset[chain_index] = openair0_cfg->rx_gain_calib_table[i].offset;
}
i++;
}
}
/*
void calibrate_rf(openair0_device *device) {
openair0_timestamp ptimestamp;
int16_t *calib_buffp,*calib_tx_buffp;
int16_t calib_buff[2*RXDCLENGTH];
int16_t calib_tx_buff[2*RXDCLENGTH];
int i,j;
int8_t offI,offQ,offIold,offQold,offInew,offQnew,offphase,offphaseold,offphasenew,offgain,offgainold,offgainnew;
int32_t meanI,meanQ,meanIold,meanQold;
int cnt=0,loop;
liblms7_status opStatus;
int16_t dcoffi;
int16_t dcoffq;
int16_t dccorri;
int16_t dccorrq;
const int16_t firCoefs[] =
{
-2531,
-517,
2708,
188,
-3059,
216,
3569,
-770,
-4199,
1541,
4886,
-2577,
-5552,
3909,
6108,
-5537,
-6457,
7440,
6507,
-9566,
-6174,
11845,
5391,
-14179,
-4110,
16457,
2310,
-18561,
0,
20369,
-2780,
-21752,
5963,
22610,
-9456,
-22859,
13127,
22444,
-16854,
-21319,
20489,
19492,
-23883,
-17002,
26881,
13902,
-29372,
-10313,
31226,
6345,
-32380,
-2141,
32767,
-2141,
-32380,
6345,
31226,
-10313,
-29372,
13902,
26881,
-17002,
-23883,
19492,
20489,
-21319,
-16854,
22444,
13127,
-22859,
-9456,
22610,
5963,
-21752,
-2780,
20369,
0,
-18561,
2310,
16457,
-4110,
-14179,
5391,
11845,
-6174,
-9566,
6507,
7440,
-6457,
-5537,
6108,
3909,
-5552,
-2577,
4886,
1541,
-4199,
-770,
3569,
216,
-3059,
188,
2708,
-517,
-2531
};
j=0;
for (i=0;i<RXDCLENGTH;i++) {
calib_tx_buff[j++] = cos_fsover8[i&7];
calib_tx_buff[j++] = cos_fsover8[(i+6)&7]; // sin
}
calib_buffp = &calib_buff[0];
calib_tx_buffp = &calib_tx_buff[0];
lms7->BackupAllRegisters();
uint8_t ch = (uint8_t)lms7->Get_SPI_Reg_bits(LMS7param(MAC));
//Stage 1
uint8_t sel_band1_trf = (uint8_t)lms7->Get_SPI_Reg_bits(LMS7param(SEL_BAND1_TRF));
uint8_t sel_band2_trf = (uint8_t)lms7->Get_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF));
{
uint16_t requiredRegs[] = { 0x0400, 0x040A, 0x010D, 0x040C };
uint16_t requiredMask[] = { 0x6000, 0x3007, 0x0040, 0x00FF }; //CAPSEL, AGC_MODE, AGC_AVG, EN_DCOFF, Bypasses
uint16_t requiredValue[] = { 0x0000, 0x1007, 0x0040, 0x00BD };
lms7->Modify_SPI_Reg_mask(requiredRegs, requiredMask, requiredValue, 0, 3);
}
// opStatus = lms7->SetFrequencySX(LMS7002M::Rx, device->openair0_cfg[0].tx_freq[0]/1e6,30.72);
// put TX on fs/4
opStatus = lms7->CalibrateRxSetup(device->openair0_cfg[0].sample_rate/1e6);
if (opStatus != LIBLMS7_SUCCESS) {
printf("Cannot calibrate for %f MHz\n",device->openair0_cfg[0].sample_rate/1e6);
exit(-1);
}
// fill TX buffer with fs/8 complex sinusoid
offIold=offQold=64;
lms7->SetRxDCOFF(offIold,offQold);
LMS_RxStart();
for (i=0;i<NUMBUFF;i++)
trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
for (meanIold=meanQold=i=j=0;i<RXDCLENGTH;i++) {
meanIold+=calib_buff[j++];
meanQold+=calib_buff[j++];
}
meanIold/=RXDCLENGTH;
meanQold/=RXDCLENGTH;
printf("[LMS] RX DC: (%d,%d) => (%d,%d)\n",offIold,offQold,meanIold,meanQold);
offI=offQ=-64;
lms7->SetRxDCOFF(offI,offQ);
for (i=0;i<NUMBUFF;i++)
trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) {
meanI+=calib_buff[j++];
meanQ+=calib_buff[j++];
}
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
printf("[LMS] RX DC: (%d,%d) => (%d,%d)\n",offI,offQ,meanI,meanQ);
while (cnt++ < 7) {
offInew=(offIold+offI)>>1;
offQnew=(offQold+offQ)>>1;
if (meanI*meanI < meanIold*meanIold) {
meanIold = meanI;
offIold = offI;
printf("[LMS] *** RX DC: offI %d => %d\n",offIold,meanI);
}
if (meanQ*meanQ < meanQold*meanQold) {
meanQold = meanQ;
offQold = offQ;
printf("[LMS] *** RX DC: offQ %d => %d\n",offQold,meanQ);
}
offI = offInew;
offQ = offQnew;
lms7->SetRxDCOFF(offI,offQ);
for (i=0;i<NUMBUFF;i++)
trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) {
meanI+=calib_buff[j++];
meanQ+=calib_buff[j++];
}
meanI/=RXDCLENGTH;
meanQ/=RXDCLENGTH;
printf("[LMS] RX DC: (%d,%d) => (%d,%d)\n",offI,offQ,meanI,meanQ);
}
if (meanI*meanI < meanIold*meanIold) {
meanIold = meanI;
offIold = offI;
printf("[LMS] *** RX DC: offI %d => %d\n",offIold,meanI);
}
if (meanQ*meanQ < meanQold*meanQold) {
meanQold = meanQ;
offQold = offQ;
printf("[LMS] *** RX DC: offQ %d => %d\n",offQold,meanQ);
}
printf("[LMS] RX DC: (%d,%d) => (%d,%d)\n",offIold,offQold,meanIold,meanQold);
lms7->SetRxDCOFF(offIold,offQold);
dcoffi = offIold;
dcoffq = offQold;
lms7->Modify_SPI_Reg_bits(LMS7param(MAC), ch);
lms7->Modify_SPI_Reg_bits(LMS7param(AGC_MODE_RXTSP), 1);
lms7->Modify_SPI_Reg_bits(LMS7param(CAPSEL), 0);
// TX LO leakage
offQold=offIold=127;
lms7->SPI_write(0x0204,(((int16_t)offIold)<<7)|offQold);
{
uint16_t requiredRegs[] = { 0x0400, 0x040A, 0x010D, 0x040C };
uint16_t requiredMask[] = { 0x6000, 0x3007, 0x0040, 0x00FF }; //CAPSEL, AGC_MODE, AGC_AVG, EN_DCOFF, Bypasses
uint16_t requiredValue[] = { 0x0000, 0x1007, 0x0040, 0x00BD };
lms7->Modify_SPI_Reg_mask(requiredRegs, requiredMask, requiredValue, 0, 3);
}
sel_band1_trf = (uint8_t)lms7->Get_SPI_Reg_bits(LMS7param(SEL_BAND1_TRF));
sel_band2_trf = (uint8_t)lms7->Get_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF));
//B
lms7->Modify_SPI_Reg_bits(0x0100, 0, 0, 1); //EN_G_TRF 1
if (sel_band1_trf == 1)
{
lms7->Modify_SPI_Reg_bits(LMS7param(PD_RLOOPB_1_RFE), 0); //PD_RLOOPB_1_RFE 0
lms7->Modify_SPI_Reg_bits(LMS7param(EN_INSHSW_LB1_RFE), 0); //EN_INSHSW_LB1 0
}
if (sel_band2_trf == 1)
{
lms7->Modify_SPI_Reg_bits(LMS7param(PD_RLOOPB_2_RFE), 0); //PD_RLOOPB_2_RFE 0
lms7->Modify_SPI_Reg_bits(LMS7param(EN_INSHSW_LB2_RFE), 0); // EN_INSHSW_LB2 0
}
// FixRXSaturation();
lms7->Modify_SPI_Reg_bits(LMS7param(GFIR3_BYP_RXTSP), 0); //GFIR3_BYP 0
lms7->Modify_SPI_Reg_bits(LMS7param(HBD_OVR_RXTSP), 2);
lms7->Modify_SPI_Reg_bits(LMS7param(GFIR3_L_RXTSP), 7);
lms7->Modify_SPI_Reg_bits(LMS7param(GFIR3_N_RXTSP), 7);
lms7->SetGFIRCoefficients(LMS7002M::Rx, 2, firCoefs, sizeof(firCoefs) / sizeof(int16_t));
for (i=0;i<NUMBUFF;i++) {
trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_lms_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
write_output("calibrx.m","rxs",calib_buffp,RXDCLENGTH,1,1);
exit(-1);
for (meanIold=meanQold=i=j=0;i<RXDCLENGTH;i++) {
switch (i&3) {
case 0:
meanIold+=calib_buff[j++];
break;
case 1:
meanQold+=calib_buff[j++];
break;
case 2:
meanIold-=calib_buff[j++];
break;
case 3:
meanQold-=calib_buff[j++];
break;
}
}
// meanIold/=RXDCLENGTH;
// meanQold/=RXDCLENGTH;
printf("[LMS] TX DC (offI): %d => (%d,%d)\n",offIold,meanIold,meanQold);
offI=-128;
lms7->SPI_write(0x0204,(((int16_t)offI)<<7)|offQold);
for (i=0;i<NUMBUFF;i++) {
trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_lms_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) {
switch (i&3) {
case 0:
meanI+=calib_buff[j++];
break;
case 1:
meanQ+=calib_buff[j++];
break;
case 2:
meanI-=calib_buff[j++];
break;
case 3:
meanQ-=calib_buff[j++];
break;
}
}
// meanI/=RXDCLENGTH;
// meanQ/=RXDCLENGTH;
printf("[LMS] TX DC (offI): %d => (%d,%d)\n",offI,meanI,meanQ);
cnt = 0;
while (cnt++ < 8) {
offInew=(offIold+offI)>>1;
if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) {
printf("[LMS] TX DC (offI): ([%d,%d]) => %d : %d\n",offIold,offI,offInew,meanI*meanI+meanQ*meanQ);
meanIold = meanI;
meanQold = meanQ;
offIold = offI;
}
offI = offInew;
lms7->SPI_write(0x0204,(((int16_t)offI)<<7)|offQold);
for (i=0;i<NUMBUFF;i++) {
trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_lms_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) {
switch (i&3) {
case 0:
meanI+=calib_buff[j++];
break;
case 1:
meanQ+=calib_buff[j++];
break;
case 2:
meanI-=calib_buff[j++];
break;
case 3:
meanQ-=calib_buff[j++];
break;
}
}
// meanI/=RXDCLENGTH;
// meanQ/=RXDCLENGTH;
// printf("[LMS] TX DC (offI): %d => (%d,%d)\n",offI,meanI,meanQ);
}
if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) {
printf("[LMS] TX DC (offI): ([%d,%d]) => %d : %d\n",offIold,offI,offInew,meanI*meanI+meanQ*meanQ);
meanIold = meanI;
meanQold = meanQ;
offIold = offI;
}
offQ=-128;
lms7->SPI_write(0x0204,(((int16_t)offIold)<<7)|offQ);
for (i=0;i<NUMBUFF;i++) {
trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_lms_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) {
switch (i&3) {
case 0:
meanI+=calib_buff[j++];
break;
case 1:
meanQ+=calib_buff[j++];
break;
case 2:
meanI-=calib_buff[j++];
break;
case 3:
meanQ-=calib_buff[j++];
break;
}
}
// meanI/=RXDCLENGTH;
// meanQ/=RXDCLENGTH;
printf("[LMS] TX DC (offQ): %d => (%d,%d)\n",offQ,meanI,meanQ);
cnt=0;
while (cnt++ < 8) {
offQnew=(offQold+offQ)>>1;
if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) {
printf("[LMS] TX DC (offQ): ([%d,%d]) => %d : %d\n",offQold,offQ,offQnew,meanI*meanI+meanQ*meanQ);
meanIold = meanI;
meanQold = meanQ;
offQold = offQ;
}
offQ = offQnew;
lms7->SPI_write(0x0204,(((int16_t)offIold)<<7)|offQ);
for (i=0;i<NUMBUFF;i++) {
trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0);
trx_lms_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0);
}
for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) {
switch (i&3) {
case 0:
meanI+=calib_buff[j++];
break;
case 1:
meanQ+=calib_buff[j++];
break;
case 2:
meanI-=calib_buff[j++];
break;
case 3:
meanQ-=calib_buff[j++];
break;
}
}
// meanI/=RXDCLENGTH;
// meanQ/=RXDCLENGTH;
// printf("[LMS] TX DC (offQ): %d => (%d,%d)\n",offQ,meanI,meanQ);
}
LMS_RxStop();
printf("[LMS] TX DC: (%d,%d) => (%d,%d)\n",offIold,offQold,meanIold,meanQold);
dccorri = offIold;
dccorrq = offQold;
lms7->RestoreAllRegisters();
lms7->Modify_SPI_Reg_bits(LMS7param(MAC), ch);
lms7->Modify_SPI_Reg_bits(LMS7param(DCOFFI_RFE), dcoffi);
lms7->Modify_SPI_Reg_bits(LMS7param(DCOFFQ_RFE), dcoffq);
lms7->Modify_SPI_Reg_bits(LMS7param(DCCORRI_TXTSP), dccorri);
lms7->Modify_SPI_Reg_bits(LMS7param(DCCORRQ_TXTSP), dccorrq);
// lms7->Modify_SPI_Reg_bits(LMS7param(GCORRI_TXTSP), gcorri);
// lms7->Modify_SPI_Reg_bits(LMS7param(GCORRQ_TXTSP), gcorrq);
// lms7->Modify_SPI_Reg_bits(LMS7param(IQCORR_TXTSP), iqcorr);
// lms7->Modify_SPI_Reg_bits(LMS7param(DC_BYP_TXTSP), 0); //DC_BYP
lms7->Modify_SPI_Reg_bits(0x0208, 1, 0, 0); //GC_BYP PH_BYP
}
*/
int trx_lms_start(openair0_device *device){
LMS_Init(0, 128*1024);
usbport = LMS_GetUSBPort();
//connect data stream port
LMS_UpdateDeviceList(usbport);
const char *name = LMS_GetDeviceName(usbport, 0);
printf("Connecting to device: %s\n",name);
if (LMS_DeviceOpen(usbport, 0)==0)
{
Si = new Si5351C();
lms7 = new LMS7002M(usbport);
liblms7_status opStatus;
printf("Configuring Si5351C\n");
Si->Initialize(usbport);
Si->SetPLL(0, 25000000, 0);
Si->SetPLL(1, 25000000, 0);
Si->SetClock(0, 27000000, true, false);
Si->SetClock(1, 27000000, true, false);
for (int i = 2; i < 8; ++i)
Si->SetClock(i, 27000000, false, false);
Si5351C::Status status = Si->ConfigureClocks();
if (status != Si5351C::SUCCESS)
{
printf("Failed to configure Si5351C");
exit(-1);
}
status = Si->UploadConfiguration();
if (status != Si5351C::SUCCESS)
printf("Failed to upload Si5351C configuration");
lms7->ResetChip();
opStatus = lms7->LoadConfig(device->openair0_cfg[0].configFilename);
if (opStatus != LIBLMS7_SUCCESS) {
printf("Failed to load configuration file %s\n",device->openair0_cfg[0].configFilename);
exit(-1);
}
opStatus = lms7->UploadAll();
if (opStatus != LIBLMS7_SUCCESS) {
printf("Failed to upload configuration file\n");
exit(-1);
}
// Set TX filter
printf("Tuning TX filter\n");
opStatus = lms7->TuneTxFilter(LMS7002M::TxFilter::TX_HIGHBAND,28.0);
if (opStatus != LIBLMS7_SUCCESS) {
printf("Warning: Could not tune TX filter\n");
}
printf("Tuning RX filter\n");
opStatus = lms7->TuneRxFilter(LMS7002M::RxFilter::RX_LPF_LOWBAND,5.0);
if (opStatus != LIBLMS7_SUCCESS) {
printf("Warning: Could not tune TX filter\n");
}
opStatus = lms7->SetInterfaceFrequency(lms7->GetFrequencyCGEN_MHz(),
lms7->Get_SPI_Reg_bits(HBI_OVR_TXTSP),
lms7->Get_SPI_Reg_bits(HBD_OVR_RXTSP));
if (opStatus != LIBLMS7_SUCCESS) {
printf("SetInterfaceFrequency failed: %f,%d,%d\n",
lms7->GetFrequencyCGEN_MHz(),
lms7->Get_SPI_Reg_bits(HBI_OVR_TXTSP),
lms7->Get_SPI_Reg_bits(HBD_OVR_RXTSP));
}
else {
printf("SetInterfaceFrequency as %f,%d,%d\n",
lms7->GetFrequencyCGEN_MHz(),
lms7->Get_SPI_Reg_bits(HBI_OVR_TXTSP),
lms7->Get_SPI_Reg_bits(HBD_OVR_RXTSP));
}
lmsStream = new LMS_StreamBoard(usbport);
LMS_StreamBoard::Status opStreamStatus;
// this will configure that sampling rate at output of FPGA
opStreamStatus = lmsStream->ConfigurePLL(usbport,device->openair0_cfg[0].sample_rate,device->openair0_cfg[0].sample_rate,90);
if (opStatus != LIBLMS7_SUCCESS){
printf("Sample rate programming failed\n");
exit(-1);
}
opStatus = lms7->SetFrequencySX(LMS7002M::Tx, device->openair0_cfg[0].tx_freq[0]/1e6,30.72);
if (opStatus != LIBLMS7_SUCCESS) {
printf("Cannot set TX frequency %f MHz\n",device->openair0_cfg[0].tx_freq[0]/1e6);
exit(-1);
}
else {
printf("Set TX frequency %f MHz\n",device->openair0_cfg[0].tx_freq[0]/1e6);
}
opStatus = lms7->SetFrequencySX(LMS7002M::Rx, device->openair0_cfg[0].rx_freq[0]/1e6,30.72);
if (opStatus != LIBLMS7_SUCCESS) {
printf("Cannot set RX frequency %f MHz\n",device->openair0_cfg[0].rx_freq[0]/1e6);
exit(-1);
}
else {
printf("Set RX frequency %f MHz\n",device->openair0_cfg[0].rx_freq[0]/1e6);
}
// Run calibration procedure
// calibrate_rf(device);
//lms7->CalibrateTx(5.0);
LMS_RxStart();
}
else
{
return(-1);
}
//connect control port
/* comport = LMS_GetCOMPort();
LMS_UpdateDeviceList(comport);
name = LMS_GetDeviceName(comport, 0);
if (*name == 0)
comport = usbport; //attempt to use data port
else
{
printf("Connecting to device: %s\n",name);
if (LMS_DeviceOpen(comport, 0)!=0)
return (-1);
}
lms7 = new LMS7002M(comport);
if( access( "./config.ini", F_OK ) != -1 ) //load config file
lms7->LoadConfig("./config.ini");
//calibration takes too long
//lms7->CalibrateRx(5.0);
//lms7->CalibrateTx(5.0);
*/
return 0;
}
int trx_lms_stop(int card) {
/*
LMS_DeviceClose(usbport);
LMS_DeviceClose(comport);
delete lms7;
return LMS_Destroy();
*/
}
int trx_lms_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config) {
//Control port must be connected
lms7->SetFrequencySX(LMS7002M::Tx,openair0_cfg->tx_freq[0]/1e6,30.72);
lms7->SetFrequencySX(LMS7002M::Rx,openair0_cfg->rx_freq[0]/1e6,30.72);
printf ("[LMS] rx frequency:%f;\n",openair0_cfg->rx_freq[0]/1e6);
set_rx_gain_offset(openair0_cfg,0);
return(0);
}
// 31 = 19 dB => 105 dB total gain @ 2.6 GHz
rx_gain_calib_table_t calib_table_sodera[] = {
{3500000000.0,70.0},
{2660000000.0,80.0},
{2300000000.0,80.0},
{1880000000.0,80.0},
{816000000.0,80.0},
{-1,0}};
int trx_lms_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) {
double gv = openair0_cfg[0].rx_gain[0] - openair0_cfg[0].rx_gain_offset[0];
if (gv > 31) {
printf("RX Gain 0 too high, reduce by %f dB\n",gv-31);
gv = 31;
}
if (gv < 0) {
printf("RX Gain 0 too low, increase by %f dB\n",-gv);
gv = 0;
}
printf("[LMS] Setting 7002M G_PGA_RBB to %d\n", (int16_t)gv);
lms7->Modify_SPI_Reg_bits(LMS7param(G_PGA_RBB),(int16_t)gv);
return(0);
}
int trx_lms_get_stats(openair0_device* device) {
return(0);
}
int trx_lms_reset_stats(openair0_device* device) {
return(0);
}
int openair0_set_gains(openair0_device* device,
openair0_config_t *openair0_cfg) {
return(0);
}
int openair0_set_frequencies(openair0_device* device, openair0_config_t *openair0_cfg, int dummy) {
return(0);
}
void trx_lms_end(openair0_device *device) {
}
int openair0_dev_init_lms(openair0_device *device, openair0_config_t *openair0_cfg){
printf("LMSSDR: Initializing openair0_device for %s ...\n", ((device->func_type == BBU_FUNC) ? "BBU": "RRH"));
switch ((int)openair0_cfg[0].sample_rate) {
case 30720000:
// from usrp_time_offset
openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 30.72e6;
openair0_cfg[0].rx_bw = 30.72e6;
openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet;
break;
case 15360000:
openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 45;
openair0_cfg[0].tx_bw = 15.36e6;
openair0_cfg[0].rx_bw = 15.36e6;
openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet;
break;
case 7680000:
openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 70;
openair0_cfg[0].tx_bw = 7.68e6;
openair0_cfg[0].rx_bw = 7.68e6;
openair0_cfg[0].tx_scheduling_advance = 12*openair0_cfg[0].samples_per_packet;
break;
case 1920000:
openair0_cfg[0].samples_per_packet = 256;
openair0_cfg[0].tx_sample_advance = 50;
openair0_cfg[0].tx_bw = 1.25e6;
openair0_cfg[0].rx_bw = 1.25e6;
openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet;
break;
default:
printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
exit(-1);
break;
}
openair0_cfg[0].rx_gain_calib_table = calib_table_sodera;
set_rx_gain_offset(openair0_cfg,0);
device->Mod_id = 1;
device->trx_start_func = trx_lms_start;
device->trx_write_func = trx_lms_write;
device->trx_read_func = trx_lms_read;
device->trx_get_stats_func = trx_lms_get_stats;
device->trx_reset_stats_func = trx_lms_reset_stats;
device->trx_end_func = trx_lms_end;
device->trx_stop_func = trx_lms_stop;
device->trx_set_freq_func = trx_lms_set_freq;
device->trx_set_gains_func = trx_lms_set_gains;
device->openair0_cfg = openair0_cfg;
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment