summaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2011-01-19 22:23:46 -0800
committerJosh Blum <josh@joshknows.com>2011-01-19 22:23:46 -0800
commit9239878b0b81c3a368bf11cfc2fe48bfb05ff902 (patch)
treef41a5e58eac89b35cb99537a0a0b64662384a9f2 /host
parentfc138381ee4bd8d191795230b7447071a85e1f28 (diff)
parent7d918c5f6acc9a5d2c8ae03e2e67b403f7efd5ff (diff)
downloaduhd-9239878b0b81c3a368bf11cfc2fe48bfb05ff902.tar.gz
uhd-9239878b0b81c3a368bf11cfc2fe48bfb05ff902.tar.bz2
uhd-9239878b0b81c3a368bf11cfc2fe48bfb05ff902.zip
Merge branch 'next'
Conflicts: host/lib/usrp/usrp2/codec_impl.cpp
Diffstat (limited to 'host')
-rw-r--r--host/CMakeLists.txt26
-rw-r--r--host/Modules/FindDocutils.cmake2
-rw-r--r--host/Modules/FindGit.cmake46
-rw-r--r--host/Modules/UHDComponent.cmake27
-rw-r--r--host/Modules/UHDVersion.cmake6
-rw-r--r--host/docs/CMakeLists.txt4
-rw-r--r--host/docs/transport.rst2
-rw-r--r--host/docs/usrp1.rst46
-rw-r--r--host/docs/usrp2.rst64
-rw-r--r--host/examples/rx_ascii_art_dft.cpp8
-rw-r--r--host/examples/rx_samples_to_file.cpp7
-rw-r--r--host/examples/rx_samples_to_udp.cpp7
-rw-r--r--host/examples/rx_timed_samples.cpp8
-rw-r--r--host/examples/test_pps_input.cpp37
-rw-r--r--host/examples/tx_from_file.cpp15
-rw-r--r--host/examples/tx_timed_samples.cpp16
-rw-r--r--host/examples/tx_waveforms.cpp10
-rw-r--r--host/include/uhd/CMakeLists.txt3
-rw-r--r--host/include/uhd/config.hpp92
-rw-r--r--host/include/uhd/convert.hpp90
-rw-r--r--host/include/uhd/transport/CMakeLists.txt7
-rw-r--r--host/include/uhd/transport/alignment_buffer.hpp69
-rw-r--r--host/include/uhd/transport/alignment_buffer.ipp144
-rw-r--r--host/include/uhd/transport/bounded_buffer.ipp13
-rw-r--r--host/include/uhd/transport/buffer_pool.hpp59
-rw-r--r--host/include/uhd/transport/convert_types.hpp96
-rw-r--r--host/include/uhd/transport/convert_types.ipp43
-rw-r--r--host/include/uhd/transport/if_addrs.hpp8
-rw-r--r--host/include/uhd/types/CMakeLists.txt4
-rw-r--r--host/include/uhd/types/clock_config.hpp9
-rw-r--r--host/include/uhd/types/dict.hpp24
-rw-r--r--host/include/uhd/types/dict.ipp23
-rw-r--r--host/include/uhd/types/ranges.hpp44
-rw-r--r--host/include/uhd/types/ranges.ipp188
-rw-r--r--host/include/uhd/types/sensors.hpp131
-rw-r--r--host/include/uhd/usrp/CMakeLists.txt1
-rw-r--r--host/include/uhd/usrp/codec_props.hpp6
-rw-r--r--host/include/uhd/usrp/dboard_iface.hpp8
-rw-r--r--host/include/uhd/usrp/gps_ctrl.hpp (renamed from host/lib/usrp/usrp2/gps_ctrl.hpp)13
-rw-r--r--host/include/uhd/usrp/mboard_props.hpp2
-rw-r--r--host/include/uhd/usrp/multi_usrp.hpp40
-rw-r--r--host/include/uhd/usrp/single_usrp.hpp28
-rw-r--r--host/include/uhd/usrp/subdev_props.hpp6
-rw-r--r--host/include/uhd/utils/algorithm.hpp31
-rw-r--r--host/include/uhd/utils/gain_group.hpp10
-rw-r--r--host/include/uhd/utils/static.hpp15
-rw-r--r--host/lib/CMakeLists.txt27
-rw-r--r--host/lib/convert/CMakeLists.txt65
-rw-r--r--host/lib/convert/convert_common.hpp90
-rw-r--r--host/lib/convert/convert_impl.cpp111
-rw-r--r--host/lib/convert/convert_with_neon.cpp61
-rw-r--r--host/lib/convert/convert_with_sse2.cpp148
-rw-r--r--host/lib/convert/gen_convert_general.py93
-rw-r--r--host/lib/convert/gen_convert_pred.py163
-rw-r--r--host/lib/gain_group.cpp149
-rw-r--r--host/lib/transport/CMakeLists.txt42
-rw-r--r--host/lib/transport/buffer_pool.cpp80
-rw-r--r--host/lib/transport/convert_types_impl.hpp345
-rwxr-xr-xhost/lib/transport/gen_convert_types.py211
-rw-r--r--host/lib/transport/libusb1_zero_copy.cpp29
-rw-r--r--host/lib/transport/udp_zero_copy_asio.cpp26
-rw-r--r--host/lib/transport/vrt_packet_handler.hpp46
-rw-r--r--host/lib/types.cpp350
-rw-r--r--host/lib/types/CMakeLists.txt31
-rw-r--r--host/lib/types/clock_config.cpp44
-rw-r--r--host/lib/types/device_addr.cpp73
-rw-r--r--host/lib/types/mac_addr.cpp76
-rw-r--r--host/lib/types/ranges.cpp163
-rw-r--r--host/lib/types/sensors.cpp81
-rw-r--r--host/lib/types/serial.cpp56
-rw-r--r--host/lib/types/time_spec.cpp86
-rw-r--r--host/lib/types/tune.cpp52
-rw-r--r--host/lib/types/types.cpp86
-rw-r--r--host/lib/usrp/CMakeLists.txt1
-rw-r--r--host/lib/usrp/dboard/db_basic_and_lf.cpp10
-rw-r--r--host/lib/usrp/dboard/db_dbsrx.cpp24
-rw-r--r--host/lib/usrp/dboard/db_dbsrx2.cpp24
-rw-r--r--host/lib/usrp/dboard/db_rfx.cpp30
-rw-r--r--host/lib/usrp/dboard/db_tvrx.cpp22
-rw-r--r--host/lib/usrp/dboard/db_unknown.cpp10
-rw-r--r--host/lib/usrp/dboard/db_wbx.cpp36
-rw-r--r--host/lib/usrp/dboard/db_xcvr2450.cpp48
-rw-r--r--host/lib/usrp/gps_ctrl.cpp (renamed from host/lib/usrp/usrp2/gps_ctrl.cpp)43
-rw-r--r--host/lib/usrp/mboard_eeprom.cpp12
-rw-r--r--host/lib/usrp/misc_utils.cpp22
-rw-r--r--host/lib/usrp/multi_usrp.cpp44
-rw-r--r--host/lib/usrp/single_usrp.cpp20
-rw-r--r--host/lib/usrp/subdev_spec.cpp14
-rw-r--r--host/lib/usrp/usrp1/CMakeLists.txt3
-rw-r--r--host/lib/usrp/usrp1/codec_ctrl.cpp38
-rw-r--r--host/lib/usrp/usrp1/codec_ctrl.hpp19
-rw-r--r--host/lib/usrp/usrp1/codec_impl.cpp8
-rw-r--r--host/lib/usrp/usrp1/dboard_iface.cpp10
-rw-r--r--host/lib/usrp/usrp1/io_impl.cpp39
-rw-r--r--host/lib/usrp/usrp1/mboard_impl.cpp25
-rw-r--r--host/lib/usrp/usrp1/soft_time_ctrl.cpp224
-rw-r--r--host/lib/usrp/usrp1/soft_time_ctrl.hpp69
-rw-r--r--host/lib/usrp/usrp1/usrp1_ctrl.cpp29
-rw-r--r--host/lib/usrp/usrp1/usrp1_ctrl.hpp17
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.cpp6
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.hpp9
-rw-r--r--host/lib/usrp/usrp2/CMakeLists.txt4
-rw-r--r--host/lib/usrp/usrp2/clock_ctrl.cpp57
-rw-r--r--host/lib/usrp/usrp2/clock_ctrl.hpp12
-rw-r--r--host/lib/usrp/usrp2/codec_ctrl.cpp8
-rw-r--r--host/lib/usrp/usrp2/codec_ctrl.hpp6
-rw-r--r--host/lib/usrp/usrp2/codec_impl.cpp12
-rw-r--r--host/lib/usrp/usrp2/dboard_iface.cpp12
-rw-r--r--host/lib/usrp/usrp2/fw_common.h59
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp216
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp117
-rw-r--r--host/lib/usrp/usrp2/serdes_ctrl.cpp46
-rw-r--r--host/lib/usrp/usrp2/serdes_ctrl.hpp40
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.cpp22
-rw-r--r--host/lib/usrp/usrp2/usrp2_iface.hpp18
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp45
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp26
-rw-r--r--host/lib/usrp/usrp2/usrp2_regs.cpp10
-rw-r--r--host/lib/usrp/usrp2/usrp2_regs.hpp18
-rw-r--r--host/lib/usrp/usrp_e100/codec_ctrl.cpp32
-rw-r--r--host/lib/usrp/usrp_e100/codec_ctrl.hpp14
-rw-r--r--host/lib/usrp/usrp_e100/codec_impl.cpp8
-rw-r--r--host/lib/usrp/usrp_e100/dboard_iface.cpp10
-rw-r--r--host/lib/usrp/usrp_e100/dsp_impl.cpp4
-rw-r--r--host/lib/usrp/usrp_e100/mboard_impl.cpp30
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_impl.hpp2
-rw-r--r--host/lib/usrp/usrp_e100/usrp_e100_regs.hpp10
-rw-r--r--host/lib/utils/CMakeLists.txt3
-rw-r--r--host/lib/utils/gain_group.cpp20
-rw-r--r--host/lib/utils/paths.cpp10
-rw-r--r--host/lib/utils/static.cpp (renamed from host/lib/transport/msvc/stdint.h)67
-rw-r--r--host/lib/utils/warning.cpp10
-rw-r--r--host/msvc/inttypes.h301
-rw-r--r--host/msvc/stdint.h226
-rw-r--r--host/tests/CMakeLists.txt (renamed from host/test/CMakeLists.txt)5
-rw-r--r--host/tests/addr_test.cpp (renamed from host/test/addr_test.cpp)0
-rw-r--r--host/tests/buffer_test.cpp (renamed from host/test/buffer_test.cpp)51
-rw-r--r--host/tests/byteswap_test.cpp (renamed from host/test/byteswap_test.cpp)0
-rw-r--r--host/tests/convert_test.cpp (renamed from host/test/convert_types_test.cpp)99
-rw-r--r--host/tests/dict_test.cpp (renamed from host/test/dict_test.cpp)0
-rw-r--r--host/tests/error_test.cpp (renamed from host/test/error_test.cpp)0
-rw-r--r--host/tests/gain_group_test.cpp (renamed from host/test/gain_group_test.cpp)38
-rw-r--r--host/tests/module_test.cpp (renamed from host/test/module_test.cpp)0
-rw-r--r--host/tests/ranges_test.cpp (renamed from host/test/ranges_test.cpp)16
-rw-r--r--host/tests/subdev_spec_test.cpp (renamed from host/test/subdev_spec_test.cpp)0
-rw-r--r--host/tests/time_spec_test.cpp (renamed from host/test/time_spec_test.cpp)0
-rw-r--r--host/tests/tune_helper_test.cpp (renamed from host/test/tune_helper_test.cpp)0
-rw-r--r--host/tests/vrt_test.cpp (renamed from host/test/vrt_test.cpp)0
-rw-r--r--host/tests/warning_test.cpp (renamed from host/test/warning_test.cpp)0
-rw-r--r--host/tests/wax_test.cpp (renamed from host/test/wax_test.cpp)0
-rw-r--r--host/utils/CMakeLists.txt1
-rw-r--r--host/utils/uhd_usrp_probe.cpp7
-rw-r--r--host/utils/usrp-e-debug-pins.c3
-rw-r--r--host/utils/usrp_e_regs.hpp196
154 files changed, 4099 insertions, 2970 deletions
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt
index f59cda23f..d0c576ee5 100644
--- a/host/CMakeLists.txt
+++ b/host/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -74,6 +74,7 @@ IF(CMAKE_COMPILER_IS_GNUCXX)
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
IF(MSVC)
+ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/msvc)
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501) #minimum version required is windows xp
ADD_DEFINITIONS(-DNOMINMAX) #disables stupidity and enables std::min and std::max
ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS) #avoid warnings from boost::split
@@ -89,7 +90,7 @@ IF(UNIX AND EXISTS "/usr/lib64")
ENDIF(UNIX AND EXISTS "/usr/lib64")
SET(Boost_ADDITIONAL_VERSIONS "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44")
-FIND_PACKAGE(Boost ${BOOST_MIN_VERSION} REQUIRED COMPONENTS
+FIND_PACKAGE(Boost ${BOOST_MIN_VERSION} COMPONENTS
date_time
filesystem
program_options
@@ -103,6 +104,23 @@ INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
########################################################################
+# Check Python Modules
+########################################################################
+INCLUDE(UHDPython)
+
+PYTHON_CHECK_MODULE(
+ "Python version 2.6 or greater"
+ "platform" "platform.python_version() >= '2.6'"
+ HAVE_PYTHON_PLAT_MIN_VERSION
+)
+
+PYTHON_CHECK_MODULE(
+ "Cheetah templates 2.0.0 or greater"
+ "Cheetah" "Cheetah.Version >= '2.0.0'"
+ HAVE_PYTHON_MODULE_CHEETAH
+)
+
+########################################################################
# Create Uninstall Target
########################################################################
CONFIGURE_FILE(
@@ -140,7 +158,7 @@ INSTALL(FILES
########################################################################
# Register top level components
########################################################################
-SET(ENABLE_LIBUHD ON) #always enabled
+LIBUHD_REGISTER_COMPONENT("LibUHD" ENABLE_LIBUHD ON "Boost_FOUND;HAVE_PYTHON_PLAT_MIN_VERSION;HAVE_PYTHON_MODULE_CHEETAH" OFF)
LIBUHD_REGISTER_COMPONENT("Examples" ENABLE_EXAMPLES ON "ENABLE_LIBUHD" OFF)
LIBUHD_REGISTER_COMPONENT("Utils" ENABLE_UTILS ON "ENABLE_LIBUHD" OFF)
LIBUHD_REGISTER_COMPONENT("Tests" ENABLE_TESTS ON "ENABLE_LIBUHD" OFF)
@@ -161,7 +179,7 @@ IF(ENABLE_LIBUHD)
ENDIF(ENABLE_LIBUHD)
IF(ENABLE_TESTS)
- ADD_SUBDIRECTORY(test)
+ ADD_SUBDIRECTORY(tests)
ENDIF(ENABLE_TESTS)
IF(ENABLE_UTILS)
diff --git a/host/Modules/FindDocutils.cmake b/host/Modules/FindDocutils.cmake
index b9996f3f1..3a97d8643 100644
--- a/host/Modules/FindDocutils.cmake
+++ b/host/Modules/FindDocutils.cmake
@@ -1,5 +1,5 @@
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2011-2011 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/host/Modules/FindGit.cmake b/host/Modules/FindGit.cmake
new file mode 100644
index 000000000..2d8214287
--- /dev/null
+++ b/host/Modules/FindGit.cmake
@@ -0,0 +1,46 @@
+# The module defines the following variables:
+# GIT_EXECUTABLE - path to git command line client
+# GIT_FOUND - true if the command line client was found
+# Example usage:
+# find_package(Git)
+# if(GIT_FOUND)
+# message("git found: ${GIT_EXECUTABLE}")
+# endif()
+
+#=============================================================================
+# Copyright 2010 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distributed this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+# Look for 'git' or 'eg' (easy git)
+#
+set(git_names git eg)
+
+# Prefer .cmd variants on Windows unless running in a Makefile
+# in the MSYS shell.
+#
+if(WIN32)
+ if(NOT CMAKE_GENERATOR MATCHES "MSYS")
+ set(git_names git.cmd git eg.cmd eg)
+ endif()
+endif()
+
+find_program(GIT_EXECUTABLE
+ NAMES ${git_names}
+ DOC "git command line client"
+ )
+mark_as_advanced(GIT_EXECUTABLE)
+
+# Handle the QUIETLY and REQUIRED arguments and set GIT_FOUND to TRUE if
+# all listed variables are TRUE
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Git DEFAULT_MSG GIT_EXECUTABLE)
diff --git a/host/Modules/UHDComponent.cmake b/host/Modules/UHDComponent.cmake
index 0263b071f..4ea55bbb9 100644
--- a/host/Modules/UHDComponent.cmake
+++ b/host/Modules/UHDComponent.cmake
@@ -27,27 +27,17 @@ SET(_uhd_disabled_components "" CACHE INTERNAL "" FORCE)
# - deps a list of dependencies
# - dis the default disable setting
########################################################################
-FUNCTION(LIBUHD_REGISTER_COMPONENT name var enb deps dis)
- INCLUDE(CMakeDependentOption)
+MACRO(LIBUHD_REGISTER_COMPONENT name var enb deps dis)
MESSAGE(STATUS "")
MESSAGE(STATUS "Configuring ${name} support...")
- IF(DEFINED ${var})
- MESSAGE(STATUS "${name} support configured ${var}=${${var}}")
- ELSE(DEFINED ${var}) #not defined: automatic enabling of component
- MESSAGE(STATUS "${name} support configured automatically")
- ENDIF(DEFINED ${var})
+ FOREACH(dep ${deps})
+ MESSAGE(STATUS " Dependency ${dep} = ${${dep}}")
+ ENDFOREACH(dep)
#setup the dependent option for this component
+ INCLUDE(CMakeDependentOption)
CMAKE_DEPENDENT_OPTION(${var} "enable ${name} support" ${enb} "${deps}" ${dis})
- #remove previous occurrence of component in either list
- IF(DEFINED _uhd_enabled_components)
- LIST(REMOVE_ITEM _uhd_enabled_components ${name})
- ENDIF(DEFINED _uhd_enabled_components)
- IF(DEFINED _uhd_disabled_components)
- LIST(REMOVE_ITEM _uhd_disabled_components ${name})
- ENDIF(DEFINED _uhd_disabled_components)
-
#append the component into one of the lists
IF(${var})
MESSAGE(STATUS " Enabling ${name} support.")
@@ -56,11 +46,12 @@ FUNCTION(LIBUHD_REGISTER_COMPONENT name var enb deps dis)
MESSAGE(STATUS " Disabling ${name} support.")
LIST(APPEND _uhd_disabled_components ${name})
ENDIF(${var})
+ MESSAGE(STATUS " Override with -D${var}=ON/OFF")
#make components lists into global variables
SET(_uhd_enabled_components ${_uhd_enabled_components} CACHE INTERNAL "" FORCE)
SET(_uhd_disabled_components ${_uhd_disabled_components} CACHE INTERNAL "" FORCE)
-ENDFUNCTION(LIBUHD_REGISTER_COMPONENT)
+ENDMACRO(LIBUHD_REGISTER_COMPONENT)
########################################################################
# Print the registered component summary
@@ -68,7 +59,7 @@ ENDFUNCTION(LIBUHD_REGISTER_COMPONENT)
FUNCTION(UHD_PRINT_COMPONENT_SUMMARY)
MESSAGE(STATUS "")
MESSAGE(STATUS "######################################################")
- MESSAGE(STATUS "# LibUHD enabled components ")
+ MESSAGE(STATUS "# UHD enabled components ")
MESSAGE(STATUS "######################################################")
FOREACH(comp ${_uhd_enabled_components})
MESSAGE(STATUS " * ${comp}")
@@ -76,7 +67,7 @@ FUNCTION(UHD_PRINT_COMPONENT_SUMMARY)
MESSAGE(STATUS "")
MESSAGE(STATUS "######################################################")
- MESSAGE(STATUS "# LibUHD disabled components ")
+ MESSAGE(STATUS "# UHD disabled components ")
MESSAGE(STATUS "######################################################")
FOREACH(comp ${_uhd_disabled_components})
MESSAGE(STATUS " * ${comp}")
diff --git a/host/Modules/UHDVersion.cmake b/host/Modules/UHDVersion.cmake
index 4bd740185..c22286d59 100644
--- a/host/Modules/UHDVersion.cmake
+++ b/host/Modules/UHDVersion.cmake
@@ -1,5 +1,5 @@
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@ INCLUDE(UHDPython) #requires python for parsing
########################################################################
# Setup Version Numbers
########################################################################
-SET(UHD_VERSION_MAJOR 0001) #API compatibility number
+SET(UHD_VERSION_MAJOR 002) #API compatibility number
SET(UHD_VERSION_MINOR 0) #Timestamp of git commit
SET(UHD_VERSION_PATCH 0) #Short hash of git commit
@@ -34,7 +34,7 @@ IF(GIT_FOUND)
#grab the git log entry for the current head
EXECUTE_PROCESS(
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
- COMMAND ${GIT_EXECUTABLE} log HEAD~..HEAD --date=raw
+ COMMAND ${GIT_EXECUTABLE} log HEAD~..HEAD --date=raw -n1
OUTPUT_VARIABLE _git_log OUTPUT_STRIP_TRAILING_WHITESPACE
)
diff --git a/host/docs/CMakeLists.txt b/host/docs/CMakeLists.txt
index 592d66526..ace48f008 100644
--- a/host/docs/CMakeLists.txt
+++ b/host/docs/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -36,7 +36,7 @@ SET(manual_sources
# Setup Manual
########################################################################
MESSAGE(STATUS "")
-FIND_PACKAGE(Docutils REQUIRED)
+FIND_PACKAGE(Docutils)
LIBUHD_REGISTER_COMPONENT("Manual" ENABLE_MANUAL ON "DOCUTILS_FOUND" OFF)
diff --git a/host/docs/transport.rst b/host/docs/transport.rst
index d9abd4923..018f909c1 100644
--- a/host/docs/transport.rst
+++ b/host/docs/transport.rst
@@ -36,7 +36,7 @@ The following parameters can be used to alter the transport's default behavior:
* **num_send_frames:** The number of send buffers to allocate
* **concurrency_hint:** The number of threads to run the IO service
-**Note:** num_send_frames and concurrency_hint will not have an effect
+**Note:** num_send_frames will not have an effect
as the asynchronous send implementation is currently disabled.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/host/docs/usrp1.rst b/host/docs/usrp1.rst
index 9038616a8..0a8224850 100644
--- a/host/docs/usrp1.rst
+++ b/host/docs/usrp1.rst
@@ -4,9 +4,9 @@ UHD - USRP1 Application Notes
.. contents:: Table of Contents
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+------------------------------------------------------------------------
Specify a non-standard image
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+------------------------------------------------------------------------
The standard USRP1 images installer comes with two FPGA images:
* **usrp1_fpga.rbf:** 2 DDCs + 2 DUCs
* **usrp1_fpga_4rx.rbf:** 4 DDCs + 0 DUCs
@@ -66,7 +66,37 @@ Notice that the subdevice name is always specified in the 3 possible cases.
B:B
------------------------------------------------------------------------
-OS Specific Notes
+Missing and emulated features
+------------------------------------------------------------------------
+The USRP1 FPGA does not have the necessary space to support the advanced
+streaming capabilities that are possible with the newer USRP devices.
+Some of these features are emulated in software to support the API.
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+List of emulated features
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+* Setting the current device time
+* Getting the current device time
+* Transmitting at a specific time
+* Receiving at a specific time
+* Receiving a specific number of samples
+* End of burst flags for transmit/receive
+
+**Note:**
+These emulated features rely on the host system's clock for timed operations,
+and therefore may not have sufficient precision for the application.
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+List of missing features
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+* Notification on late stream command
+* Notification on late transmit packet
+* Notification on broken chain error
+* Notification on underflow or overflow
+* Start of burst flags for transmit/receive
+
+------------------------------------------------------------------------
+OS specific notes
------------------------------------------------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -90,13 +120,13 @@ On Windows, a driver must be installed the first time the USRP1 is attached to t
A download link for this driver can be found on the UHD wiki page.
Download and unpack the driver, and direct the Windows driver install wizard to the .inf file.
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Hardware setup notes
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
------------------------------------------------------------------------
-External Clock Modification
+Hardware setup notes
------------------------------------------------------------------------
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+External clock modification
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The USRP can be modified to accept an external clock reference instead of the 64MHz onboard reference.
* Solder SMA (LTI-SASF54GT) connector to J2001
* Move 0 ohm 0603 resistor R2029 to R2930
diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst
index 8e5743102..3031a0075 100644
--- a/host/docs/usrp2.rst
+++ b/host/docs/usrp2.rst
@@ -101,7 +101,7 @@ On some systems, the firewall will block UDP broadcast packets.
It is recommended that you change or disable your firewall settings.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Multiple device configuration
+Multiple devices per host
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For maximum throughput, one ethernet interface per USRP2 is recommended,
although multiple devices may be connected via a gigabit ethernet switch.
@@ -210,6 +210,66 @@ Example device address string representation for 2 USRP2s with IPv4 addresses 19
addr0=192.168.10.2, addr1=192.168.20.2
------------------------------------------------------------------------
+Using the MIMO Cable
+------------------------------------------------------------------------
+The MIMO cable allows two USRP devices to share reference clocks,
+time synchronization, and the ethernet interface.
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Shared ethernet mode
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+In shared ethernet mode,
+only one device in the configuration can be attached to the ethernet.
+This device will be referred to as the master, and the other device, the slave.
+
+* The master provides reference clock and time synchronization to the slave.
+* All data passing between the host and the slave is routed over the MIMO cable.
+* Both master and slave must have different IPv4 addresses in the same subnet.
+* The master and slave may be used individually or in a multi-device configuration.
+* External clocking is optional, and should only be supplied to the master device.
+* The role of slave and master may be switched with the "mimo_mode" device address (see dual ethernet mode).
+
+Example device address string representation for 2 USRP2s with IPv4 addresses 192.168.10.2 (master) and 192.168.10.3 (slave)
+::
+
+ -- Multi-device example --
+
+ addr0=192.168.10.2, addr1=192.168.10.3
+
+ -- Two single devices example --
+
+ addr=192.168.10.2
+
+ addr=192.168.10.3
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Dual ethernet mode
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+In dual ethernet mode,
+both devices in the configuration must be attached to the ethernet.
+One of the devices in the configuration will be configured to provide synchronization.
+This device will be referred to as the master, and the other device, the slave.
+
+* The master provides reference clock and time synchronization to the slave.
+* The devices require the special device address argument "mimo_mode" set.
+* Both master and slave must have different IPv4 addresses in different subnets.
+* The master and slave may be used individually or in a multi-device configuration.
+* External clocking is optional, and should only be supplied to the master device.
+
+Example device address string representation for 2 USRP2s with IPv4 addresses 192.168.10.2 (master) and 192.168.20.2 (slave)
+::
+
+ -- Multi-device example --
+
+ addr0=192.168.10.2, mimo_mode0=master, addr1=192.168.20.2, mimo_mode1=slave
+
+ -- Two single devices example --
+
+ addr=192.168.10.2, mimo_mode=master
+
+ addr=192.168.20.2, mimo_mode=slave
+
+------------------------------------------------------------------------
Hardware setup notes
------------------------------------------------------------------------
@@ -220,7 +280,7 @@ The LEDs on the front panel can be useful in debugging hardware and software iss
The LEDs reveal the following about the state of the device:
* **LED A:** transmitting
-* **LED B:** serdes link
+* **LED B:** mimo cable link
* **LED C:** receiving
* **LED D:** firmware loaded
* **LED E:** reference lock
diff --git a/host/examples/rx_ascii_art_dft.cpp b/host/examples/rx_ascii_art_dft.cpp
index 5a24867b4..260feca24 100644
--- a/host/examples/rx_ascii_art_dft.cpp
+++ b/host/examples/rx_ascii_art_dft.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -34,8 +34,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//variables to be set by po
std::string args;
size_t num_bins;
- double rate, freq, frame_rate;
- float gain, ref_lvl, dyn_rng;
+ double rate, freq, gain, frame_rate;
+ float ref_lvl, dyn_rng;
//setup the program options
po::options_description desc("Allowed options");
@@ -45,7 +45,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
// hardware parameters
("rate", po::value<double>(&rate), "rate of incoming samples (sps)")
("freq", po::value<double>(&freq)->default_value(0), "RF center frequency in Hz")
- ("gain", po::value<float>(&gain)->default_value(0), "gain for the RF chain")
+ ("gain", po::value<double>(&gain)->default_value(0), "gain for the RF chain")
// display parameters
("num-bins", po::value<size_t>(&num_bins)->default_value(512), "the number of bins in the DFT")
("frame-rate", po::value<double>(&frame_rate)->default_value(5), "frame rate of the display (fps)")
diff --git a/host/examples/rx_samples_to_file.cpp b/host/examples/rx_samples_to_file.cpp
index c80d2a6de..81977035e 100644
--- a/host/examples/rx_samples_to_file.cpp
+++ b/host/examples/rx_samples_to_file.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -33,8 +33,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//variables to be set by po
std::string args, file;
size_t total_num_samps;
- double rate, freq;
- float gain;
+ double rate, freq, gain;
//setup the program options
po::options_description desc("Allowed options");
@@ -45,7 +44,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
("nsamps", po::value<size_t>(&total_num_samps)->default_value(1000), "total number of samples to receive")
("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of incoming samples")
("freq", po::value<double>(&freq)->default_value(0), "rf center frequency in Hz")
- ("gain", po::value<float>(&gain)->default_value(0), "gain for the RF chain")
+ ("gain", po::value<double>(&gain)->default_value(0), "gain for the RF chain")
;
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
diff --git a/host/examples/rx_samples_to_udp.cpp b/host/examples/rx_samples_to_udp.cpp
index 488c95494..55b9a50ba 100644
--- a/host/examples/rx_samples_to_udp.cpp
+++ b/host/examples/rx_samples_to_udp.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -33,8 +33,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//variables to be set by po
std::string args;
size_t total_num_samps;
- double rate, freq;
- float gain;
+ double rate, freq, gain;
std::string addr, port;
//setup the program options
@@ -45,7 +44,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
("nsamps", po::value<size_t>(&total_num_samps)->default_value(1000), "total number of samples to receive")
("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of incoming samples")
("freq", po::value<double>(&freq)->default_value(0), "rf center frequency in Hz")
- ("gain", po::value<float>(&gain)->default_value(0), "gain for the RF chain")
+ ("gain", po::value<double>(&gain)->default_value(0), "gain for the RF chain")
("port", po::value<std::string>(&port)->default_value("7124"), "server udp port")
("addr", po::value<std::string>(&addr)->default_value("192.168.1.10"), "resolvable server address")
;
diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp
index 8a810811f..a19532f50 100644
--- a/host/examples/rx_timed_samples.cpp
+++ b/host/examples/rx_timed_samples.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -30,7 +30,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//variables to be set by po
std::string args;
- time_t seconds_in_future;
+ double seconds_in_future;
size_t total_num_samps;
double rate, freq;
@@ -39,7 +39,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
desc.add_options()
("help", "help message")
("args", po::value<std::string>(&args)->default_value(""), "single uhd device address args")
- ("secs", po::value<time_t>(&seconds_in_future)->default_value(3), "number of seconds in the future to receive")
+ ("secs", po::value<double>(&seconds_in_future)->default_value(3), "number of seconds in the future to receive")
("nsamps", po::value<size_t>(&total_num_samps)->default_value(1000), "total number of samples to receive")
("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of incoming samples")
("freq", po::value<double>(&freq)->default_value(0), "rf center frequency in Hz")
@@ -80,7 +80,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//setup streaming
std::cout << std::endl;
std::cout << boost::format(
- "Begin streaming %u samples, %d seconds in the future..."
+ "Begin streaming %u samples, %f seconds in the future..."
) % total_num_samps % seconds_in_future << std::endl;
uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
stream_cmd.num_samps = total_num_samps;
diff --git a/host/examples/test_pps_input.cpp b/host/examples/test_pps_input.cpp
index 4b2bb62a3..273c73df0 100644
--- a/host/examples/test_pps_input.cpp
+++ b/host/examples/test_pps_input.cpp
@@ -17,7 +17,7 @@
#include <uhd/utils/thread_priority.hpp>
#include <uhd/utils/safe_main.hpp>
-#include <uhd/usrp/single_usrp.hpp>
+#include <uhd/usrp/multi_usrp.hpp>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
#include <boost/thread.hpp>
@@ -31,7 +31,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//variables to be set by po
std::string args;
- double seconds;
//setup the program options
po::options_description desc("Allowed options");
@@ -52,35 +51,13 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//create a usrp device
std::cout << std::endl;
std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
- uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args);
+ uhd::usrp::multi_usrp::sptr sdev = uhd::usrp::multi_usrp::make(args);
uhd::device::sptr dev = sdev->get_device();
std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl;
- //set a known time value
- std::cout << "Set time to known value (100.0) without regard to pps:" << std::endl;
- sdev->set_time_now(uhd::time_spec_t(100.0));
- boost::this_thread::sleep(boost::posix_time::seconds(1));
- std::cout << boost::format("Reading time 1 second later: %f\n") % (sdev->get_time_now().get_real_secs()) << std::endl;
-
- //store the time to see if PPS resets it
- seconds = sdev->get_time_now().get_real_secs();
-
- //set a known time at next PPS, check that time increments
- uhd::time_spec_t time_spec = uhd::time_spec_t(0.0);
- std::cout << "Set time to known value (0.0) at next pps:" << std::endl;
- sdev->set_time_next_pps(time_spec);
- boost::this_thread::sleep(boost::posix_time::seconds(1));
- std::cout << boost::format("Reading time 1 second later: %f\n") % (sdev->get_time_now().get_real_secs()) << std::endl;
-
- //finished
- if (seconds > sdev->get_time_now().get_real_secs()){
- std::cout << std::endl << "Success!" << std::endl << std::endl;
- return 0;
- } else {
- std::cout << std::endl << "Failed!" << std::endl << std::endl
- << "If you expected PPS to work:" << std::endl
- << "\tsee Device App Notes for PPS level information"
- << std::endl << std::endl;
- return -1;
- }
+ //set the time at an unknown pps (will throw if no pps)
+ std::cout << std::endl << "Attempt to detect the PPS and set the time..." << std::endl << std::endl;
+ sdev->set_time_unknown_pps(uhd::time_spec_t(0.0));
+ std::cout << std::endl << "Success!" << std::endl << std::endl;
+ return 0;
}
diff --git a/host/examples/tx_from_file.cpp b/host/examples/tx_from_file.cpp
index 9611cf47c..8af9b0f4a 100644
--- a/host/examples/tx_from_file.cpp
+++ b/host/examples/tx_from_file.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -31,24 +31,23 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//variables to be set by po
std::string args;
- time_t seconds_in_future;
+ double seconds_in_future;
size_t total_num_samps;
size_t samps_per_packet;
- double tx_rate, freq;
+ double tx_rate, freq, gain;
float ampl;
- float tx_gain;
//setup the program options
po::options_description desc("Allowed options");
desc.add_options()
("help", "help message")
("args", po::value<std::string>(&args)->default_value(""), "simple uhd device address args")
- ("secs", po::value<time_t>(&seconds_in_future)->default_value(3), "number of seconds in the future to transmit")
+ ("secs", po::value<double>(&seconds_in_future)->default_value(3), "number of seconds in the future to transmit")
("nsamps", po::value<size_t>(&total_num_samps)->default_value(1000), "total number of samples to transmit")
("txrate", po::value<double>(&tx_rate)->default_value(100e6/16), "rate of outgoing samples")
("freq", po::value<double>(&freq)->default_value(0), "rf center frequency in Hz")
("ampl", po::value<float>(&ampl)->default_value(float(0.3)), "amplitude of each sample")
- ("gain", po::value<float>(&tx_gain)->default_value(float(0)), "amplitude of each sample")
+ ("gain", po::value<double>(&gain)->default_value(0), "amplitude of each sample")
("dilv", "specify to disable inner-loop verbose")
;
po::variables_map vm;
@@ -78,7 +77,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
sdev->set_tx_freq(freq);
sdev->set_time_now(uhd::time_spec_t(0.0));
- sdev->set_tx_gain(tx_gain);
+ sdev->set_gain(gain);
//allocate data to send
std::vector<std::complex<short> > buff;
@@ -102,7 +101,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
size_t num_packets = (total_num_samps+samps_per_packet-1)/samps_per_packet;
for (size_t i = 0; i < num_packets; i++){
//setup the metadata flags and time spec
- md.start_of_burst = true; //always SOB (good for continuous streaming)
+ md.start_of_burst = (i == 0); //only first packet has SOB
md.end_of_burst = (i == num_packets-1); //only last packet has EOB
md.has_time_spec = (i == 0); //only first packet has time
md.time_spec = uhd::time_spec_t(seconds_in_future);
diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp
index 799da37e0..6d6aa7010 100644
--- a/host/examples/tx_timed_samples.cpp
+++ b/host/examples/tx_timed_samples.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -30,7 +30,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//variables to be set by po
std::string args;
- time_t seconds_in_future;
+ double seconds_in_future;
size_t total_num_samps;
size_t samps_per_packet;
double rate, freq;
@@ -41,7 +41,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
desc.add_options()
("help", "help message")
("args", po::value<std::string>(&args)->default_value(""), "single uhd device address args")
- ("secs", po::value<time_t>(&seconds_in_future)->default_value(3), "number of seconds in the future to transmit")
+ ("secs", po::value<double>(&seconds_in_future)->default_value(3), "number of seconds in the future to transmit")
("nsamps", po::value<size_t>(&total_num_samps)->default_value(1000), "total number of samples to transmit")
("spp", po::value<size_t>(&samps_per_packet)->default_value(1000), "number of samples per packet")
("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of outgoing samples")
@@ -84,15 +84,17 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//allocate data to send
std::vector<std::complex<float> > buff(samps_per_packet, std::complex<float>(ampl, ampl));
+ uhd::tx_metadata_t md;
+ md.time_spec = uhd::time_spec_t(seconds_in_future);
+
//send the data in multiple packets
size_t num_packets = (total_num_samps+samps_per_packet-1)/samps_per_packet;
for (size_t i = 0; i < num_packets; i++){
- //setup the metadata flags and time spec
- uhd::tx_metadata_t md;
- md.start_of_burst = true; //always SOB (good for continuous streaming)
+
+ //setup the metadata flags per fragment
+ md.start_of_burst = (i == 0); //only first packet has SOB
md.end_of_burst = (i == num_packets-1); //only last packet has EOB
md.has_time_spec = (i == 0); //only first packet has time
- md.time_spec = uhd::time_spec_t(seconds_in_future);
size_t samps_to_send = std::min(total_num_samps - samps_per_packet*i, samps_per_packet);
diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp
index 50982cf88..7cc1f5ae0 100644
--- a/host/examples/tx_waveforms.cpp
+++ b/host/examples/tx_waveforms.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -63,8 +63,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//variables to be set by po
std::string args, wave_type;
size_t total_duration, spb;
- double rate, freq, wave_freq;
- float ampl, gain;
+ double rate, freq, gain, wave_freq;
+ float ampl;
//setup the program options
po::options_description desc("Allowed options");
@@ -76,7 +76,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
("rate", po::value<double>(&rate)->default_value(1.5e6), "rate of outgoing samples")
("freq", po::value<double>(&freq)->default_value(0), "rf center frequency in Hz")
("ampl", po::value<float>(&ampl)->default_value(float(0.3)), "amplitude of the waveform")
- ("gain", po::value<float>(&gain)->default_value(float(0)), "gain for the RF chain")
+ ("gain", po::value<double>(&gain)->default_value(0), "gain for the RF chain")
("wave-type", po::value<std::string>(&wave_type)->default_value("CONST"), "waveform type (CONST, SQUARE, RAMP, SINE)")
("wave-freq", po::value<double>(&wave_freq)->default_value(0), "waveform frequency in Hz")
;
@@ -142,7 +142,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//setup the metadata flags
uhd::tx_metadata_t md;
- md.start_of_burst = true; //always SOB (good for continuous streaming)
+ md.start_of_burst = false; //never SOB when continuous
md.end_of_burst = false;
//send the data in multiple packets
diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt
index ad528c9fb..fee1270e9 100644
--- a/host/include/uhd/CMakeLists.txt
+++ b/host/include/uhd/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -23,6 +23,7 @@ ADD_SUBDIRECTORY(utils)
INSTALL(FILES
config.hpp
+ convert.hpp
device.hpp
device.ipp
version.hpp
diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp
index 9a29fb246..912fbc204 100644
--- a/host/include/uhd/config.hpp
+++ b/host/include/uhd/config.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -18,9 +18,10 @@
#ifndef INCLUDED_UHD_CONFIG_HPP
#define INCLUDED_UHD_CONFIG_HPP
-// suppress warnings
#include <boost/config.hpp>
+
#ifdef BOOST_MSVC
+// suppress warnings
//# pragma warning(push)
//# pragma warning(disable: 4511) // copy constructor can't not be generated
//# pragma warning(disable: 4512) // assignment operator can't not be generated
@@ -37,76 +38,43 @@
//# pragma warning(disable: 4511) // 'class' : copy constructor could not be generated
//# pragma warning(disable: 4250) // 'class' : inherits 'method' via dominance
# pragma warning(disable: 4200) // nonstandard extension used : zero-sized array in struct/union
-#endif
// define logical operators
-#ifdef BOOST_MSVC
- #include <ciso646>
-#endif
+#include <ciso646>
// define ssize_t
-#ifdef BOOST_MSVC
- #include <cstddef>
- typedef ptrdiff_t ssize_t;
-#endif
-
-// http://gcc.gnu.org/wiki/Visibility
-// Generic helper definitions for shared library support
-#if defined(BOOST_HAS_DECLSPEC)
- #define UHD_HELPER_DLL_IMPORT __declspec(dllimport)
- #define UHD_HELPER_DLL_EXPORT __declspec(dllexport)
- #define UHD_HELPER_DLL_LOCAL
- #define UHD_HELPER_EXIM_TMPL
-#elif defined(__GNUG__) && __GNUG__ >= 4
- #define UHD_HELPER_DLL_IMPORT __attribute__ ((visibility("default")))
- #define UHD_HELPER_DLL_EXPORT __attribute__ ((visibility("default")))
- #define UHD_HELPER_DLL_LOCAL __attribute__ ((visibility("hidden")))
- #define UHD_HELPER_EXIM_TMPL extern
-#else
- #define UHD_HELPER_DLL_IMPORT
- #define UHD_HELPER_DLL_EXPORT
- #define UHD_HELPER_DLL_LOCAL
- #define UHD_HELPER_EXIM_TMPL extern
-#endif
-
-// Now we use the generic helper definitions above to define UHD_API and UHD_LOCAL.
-// UHD_API is used for the public API symbols. It either DLL imports or DLL exports (or does nothing for static build)
-// UHD_LOCAL is used for non-api symbols.
-
-#define UHD_DLL // defined here, put into configuration if we need to make static libs
+#include <cstddef>
+typedef ptrdiff_t ssize_t;
-#ifdef UHD_DLL // defined if UHD is compiled as a DLL
- #ifdef UHD_DLL_EXPORTS // defined if we are building the UHD DLL (instead of using it)
- #define UHD_API UHD_HELPER_DLL_EXPORT
- #define UHD_EXIM_TMPL UHD_HELPER_EXIM_TMPL
- #else
- #define UHD_API UHD_HELPER_DLL_IMPORT
- #define UHD_EXIM_TMPL UHD_HELPER_EXIM_TMPL
- #endif // UHD_DLL_EXPORTS
- #define UHD_LOCAL UHD_HELPER_DLL_LOCAL
-#else // UHD_DLL is not defined: this means UHD is a static lib.
- #define UHD_API
- #define UHD_LOCAL
- #define UHD_EXIM_TMPL
-#endif // UHD_DLL
+#endif //BOOST_MSVC
-// Define force inline macro
-#if defined(BOOST_MSVC)
- #define UHD_INLINE __forceinline
+//define cross platform attribute macros
+#if defined(BOOST_MSVC) || defined(BOOST_HAS_DECLSPEC)
+ #define UHD_EXPORT __declspec(dllexport)
+ #define UHD_IMPORT __declspec(dllimport)
+ #define UHD_INLINE __forceinline
+ #define UHD_DEPRECATED __declspec(deprecated)
+ #define UHD_ALIGNED(x) __declspec(align(x))
#elif defined(__GNUG__) && __GNUG__ >= 4
- #define UHD_INLINE inline __attribute__((always_inline))
+ #define UHD_EXPORT __attribute__((visibility("default")))
+ #define UHD_IMPORT __attribute__((visibility("default")))
+ #define UHD_INLINE inline __attribute__((always_inline))
+ #define UHD_DEPRECATED __attribute__((deprecated))
+ #define UHD_ALIGNED(x) __attribute__((aligned(x)))
#else
- #define UHD_INLINE inline
+ #define UHD_EXPORT
+ #define UHD_IMPORT
+ #define UHD_INLINE inline
+ #define UHD_DEPRECATED
+ #define UHD_ALIGNED(x)
#endif
-// Define deprecated attribute macro
-#if defined(BOOST_MSVC)
- #define UHD_DEPRECATED __declspec(deprecated)
-#elif defined(__GNUG__) && __GNUG__ >= 4
- #define UHD_DEPRECATED __attribute__ ((deprecated))
+// Define API declaration macro
+#ifdef UHD_DLL_EXPORTS
+ #define UHD_API UHD_EXPORT
#else
- #define UHD_DEPRECATED
-#endif
+ #define UHD_API UHD_IMPORT
+#endif // UHD_DLL_EXPORTS
// Platform defines for conditional parts of headers:
// Taken from boost/config/select_platform_config.hpp,
@@ -117,6 +85,8 @@
#define UHD_PLATFORM_WIN32
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
#define UHD_PLATFORM_MACOS
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+ #define UHD_PLATFORM_BSD
#endif
#endif /* INCLUDED_UHD_CONFIG_HPP */
diff --git a/host/include/uhd/convert.hpp b/host/include/uhd/convert.hpp
new file mode 100644
index 000000000..bfe8c8267
--- /dev/null
+++ b/host/include/uhd/convert.hpp
@@ -0,0 +1,90 @@
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_CONVERT_HPP
+#define INCLUDED_UHD_CONVERT_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/types/io_type.hpp>
+#include <uhd/types/otw_type.hpp>
+#include <boost/function.hpp>
+#include <string>
+#include <vector>
+
+namespace uhd{ namespace convert{
+
+ typedef std::vector<void *> output_type;
+ typedef std::vector<const void *> input_type;
+ typedef boost::function<void(input_type&, output_type&, size_t)> function_type;
+
+ /*!
+ * Describe the priority of a converter function.
+ * A higher priority function takes precedence.
+ * The general case function are the lowest.
+ * Next comes the liborc implementations.
+ * Custom intrinsics implementations are highest.
+ */
+ enum priority_type{
+ PRIORITY_GENERAL = 0,
+ PRIORITY_LIBORC = 1,
+ PRIORITY_CUSTOM = 2,
+ PRIORITY_EMPTY = -1,
+ };
+
+ /*!
+ * Register a converter function that converts cpu type to/from otw type.
+ * \param markup representing the signature
+ * \param fcn a pointer to the converter
+ * \param prio the function priority
+ */
+ UHD_API void register_converter(
+ const std::string &markup,
+ function_type fcn,
+ priority_type prio
+ );
+
+ /*!
+ * Get a converter function that converts cpu to otw.
+ * \param io_type the type of the input samples
+ * \param otw_type the type of the output samples
+ * \param num_input_buffs the number of inputs
+ * \param num_output_buffs the number of outputs
+ */
+ UHD_API const function_type &get_converter_cpu_to_otw(
+ const io_type_t &io_type,
+ const otw_type_t &otw_type,
+ size_t num_input_buffs,
+ size_t num_output_buffs
+ );
+
+ /*!
+ * Get a converter function that converts otw to cpu.
+ * \param io_type the type of the input samples
+ * \param otw_type the type of the output samples
+ * \param num_input_buffs the number of inputs
+ * \param num_output_buffs the number of outputs
+ */
+ UHD_API const function_type &get_converter_otw_to_cpu(
+ const io_type_t &io_type,
+ const otw_type_t &otw_type,
+ size_t num_input_buffs,
+ size_t num_output_buffs
+ );
+
+}} //namespace
+
+#endif /* INCLUDED_UHD_CONVERT_HPP */
diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt
index 2c84c0724..14ca82226 100644
--- a/host/include/uhd/transport/CMakeLists.txt
+++ b/host/include/uhd/transport/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,12 +17,9 @@
INSTALL(FILES
- alignment_buffer.hpp
- alignment_buffer.ipp
bounded_buffer.hpp
bounded_buffer.ipp
- convert_types.hpp
- convert_types.ipp
+ buffer_pool.hpp
if_addrs.hpp
udp_simple.hpp
udp_zero_copy.hpp
diff --git a/host/include/uhd/transport/alignment_buffer.hpp b/host/include/uhd/transport/alignment_buffer.hpp
deleted file mode 100644
index f44a037f8..000000000
--- a/host/include/uhd/transport/alignment_buffer.hpp
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#ifndef INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_HPP
-#define INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_HPP
-
-#include <uhd/config.hpp>
-#include <uhd/transport/bounded_buffer.hpp> //time_duration_t
-#include <boost/shared_ptr.hpp>
-#include <vector>
-
-namespace uhd{ namespace transport{
-
- /*!
- * Implement a templated alignment buffer:
- * Used for aligning asynchronously pushed elements with matching ids.
- */
- template <typename elem_type, typename seq_type> class alignment_buffer{
- public:
- typedef boost::shared_ptr<alignment_buffer<elem_type, seq_type> > sptr;
-
- /*!
- * Make a new alignment buffer object.
- * \param capacity the maximum elements per index
- * \param width the number of elements to align
- */
- static sptr make(size_t capacity, size_t width);
-
- /*!
- * Push an element with sequence id into the buffer at index.
- * \param elem the element to push
- * \param seq the sequence identifier
- * \param index the buffer index
- * \return true if the element fit without popping for space
- */
- virtual bool push_with_pop_on_full(
- const elem_type &elem, const seq_type &seq, size_t index
- ) = 0;
-
- /*!
- * Pop an aligned set of elements from this alignment buffer.
- * \param elems a collection to store the aligned elements
- * \param timeout the timeout in seconds
- * \return false when the operation times out
- */
- virtual bool pop_elems_with_timed_wait(
- std::vector<elem_type> &elems, double timeout
- ) = 0;
- };
-
-}} //namespace
-
-#include <uhd/transport/alignment_buffer.ipp>
-
-#endif /* INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_HPP */
diff --git a/host/include/uhd/transport/alignment_buffer.ipp b/host/include/uhd/transport/alignment_buffer.ipp
deleted file mode 100644
index 833b5d399..000000000
--- a/host/include/uhd/transport/alignment_buffer.ipp
+++ /dev/null
@@ -1,144 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#ifndef INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP
-#define INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP
-
-#include <uhd/transport/bounded_buffer.hpp>
-#include <boost/thread/condition_variable.hpp>
-#include <utility>
-
-namespace uhd{ namespace transport{ namespace{ /*anon*/
-
- /*!
- * Imlement a templated alignment buffer:
- * Used for aligning asynchronously pushed elements with matching ids.
- */
- template <typename elem_type, typename seq_type>
- class alignment_buffer_impl : public alignment_buffer<elem_type, seq_type>{
- public:
-
- alignment_buffer_impl(size_t capacity, size_t width) : _last_seqs(width){
- for (size_t i = 0; i < width; i++){
- _buffs.push_back(bounded_buffer<buff_contents_type>::make(capacity));
- _all_indexes.push_back(i);
- }
- _there_was_a_clear = false;
- }
-
- UHD_INLINE bool push_with_pop_on_full(
- const elem_type &elem, const seq_type &seq, size_t index
- ){
- //clear the buffer for this index if the seqs are mis-ordered
- if (seq < _last_seqs[index]){
- _buffs[index]->clear();
- _there_was_a_clear = true;
- } _last_seqs[index] = seq;
- return _buffs[index]->push_with_pop_on_full(buff_contents_type(elem, seq));
- }
-
- UHD_INLINE bool pop_elems_with_timed_wait(
- std::vector<elem_type> &elems, double timeout
- ){
- boost::system_time exit_time = boost::get_system_time() + to_time_dur(timeout);
- buff_contents_type buff_contents_tmp;
- std::list<size_t> indexes_to_do(_all_indexes);
-
- //do an initial pop to load an initial sequence id
- size_t index = indexes_to_do.front();
- if (not _buffs[index]->pop_with_timed_wait(
- buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time())
- )) return false;
- elems[index] = buff_contents_tmp.first;
- seq_type expected_seq_id = buff_contents_tmp.second;
- indexes_to_do.pop_front();
-
- //get an aligned set of elements from the buffers:
- while(indexes_to_do.size() != 0){
-
- //respond to a clear by starting from scratch
- if(_there_was_a_clear){
- _there_was_a_clear = false;
- indexes_to_do = _all_indexes;
- index = indexes_to_do.front();
- if (not _buffs[index]->pop_with_timed_wait(
- buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time())
- )) return false;
- elems[index] = buff_contents_tmp.first;
- expected_seq_id = buff_contents_tmp.second;
- indexes_to_do.pop_front();
- }
-
- //pop an element off for this index
- index = indexes_to_do.front();
- if (not _buffs[index]->pop_with_timed_wait(
- buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time())
- )) return false;
-
- //if the sequence id matches:
- // store the popped element into the output,
- // remove this index from the list and continue
- if (buff_contents_tmp.second == expected_seq_id){
- elems[index] = buff_contents_tmp.first;
- indexes_to_do.pop_front();
- continue;
- }
-
- //if the sequence id is older:
- // continue with the same index to try again
- if (buff_contents_tmp.second < expected_seq_id){
- continue;
- }
-
- //if the sequence id is newer:
- // store the popped element into the output,
- // add all other indexes back into the list
- if (buff_contents_tmp.second > expected_seq_id){
- elems[index] = buff_contents_tmp.first;
- expected_seq_id = buff_contents_tmp.second;
- indexes_to_do = _all_indexes;
- indexes_to_do.remove(index);
- continue;
- }
- }
- return true;
- }
-
- private:
- //a vector of bounded buffers for each index
- typedef std::pair<elem_type, seq_type> buff_contents_type;
- std::vector<typename bounded_buffer<buff_contents_type>::sptr> _buffs;
- std::vector<seq_type> _last_seqs;
- std::list<size_t> _all_indexes;
- bool _there_was_a_clear;
- };
-
-}}} //namespace
-
-namespace uhd{ namespace transport{
-
- template <typename elem_type, typename seq_type>
- typename alignment_buffer<elem_type, seq_type>::sptr
- alignment_buffer<elem_type, seq_type>::make(size_t capacity, size_t width){
- return typename alignment_buffer<elem_type, seq_type>::sptr(
- new alignment_buffer_impl<elem_type, seq_type>(capacity, width)
- );
- }
-
-}} //namespace
-
-#endif /* INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP */
diff --git a/host/include/uhd/transport/bounded_buffer.ipp b/host/include/uhd/transport/bounded_buffer.ipp
index edc7faa06..f7915d866 100644
--- a/host/include/uhd/transport/bounded_buffer.ipp
+++ b/host/include/uhd/transport/bounded_buffer.ipp
@@ -26,14 +26,6 @@
namespace uhd{ namespace transport{ namespace{ /*anon*/
- static UHD_INLINE boost::posix_time::time_duration to_time_dur(double timeout){
- return boost::posix_time::microseconds(long(timeout*1e6));
- }
-
- static UHD_INLINE double from_time_dur(const boost::posix_time::time_duration &time_dur){
- return 1e-6*time_dur.total_microseconds();
- }
-
template <typename elem_type>
class bounded_buffer_impl : public bounded_buffer<elem_type>{
public:
@@ -127,6 +119,11 @@ namespace uhd{ namespace transport{ namespace{ /*anon*/
_buffer.pop_back();
return elem;
}
+
+ static UHD_INLINE boost::posix_time::time_duration to_time_dur(double timeout){
+ return boost::posix_time::microseconds(long(timeout*1e6));
+ }
+
};
}}} //namespace
diff --git a/host/include/uhd/transport/buffer_pool.hpp b/host/include/uhd/transport/buffer_pool.hpp
new file mode 100644
index 000000000..84a338097
--- /dev/null
+++ b/host/include/uhd/transport/buffer_pool.hpp
@@ -0,0 +1,59 @@
+//
+// Copyright 2011-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TRANSPORT_BUFFER_POOL_HPP
+#define INCLUDED_UHD_TRANSPORT_BUFFER_POOL_HPP
+
+#include <uhd/config.hpp>
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace uhd{ namespace transport{
+
+ /*!
+ * A buffer pool manages memory for a homogeneous set of buffers.
+ * Each buffer is the pool start at a 16-byte alignment boundary.
+ */
+ class UHD_API buffer_pool : boost::noncopyable{
+ public:
+ typedef boost::shared_ptr<buffer_pool> sptr;
+ typedef void * ptr_type;
+
+ /*!
+ * Make a new buffer pool.
+ * \param num_buffs the number of buffers to allocate
+ * \param buff_size the size of each buffer in bytes
+ * \param alignment the alignment boundary in bytes
+ * \return a new buffer pool buff_size X num_buffs
+ */
+ static sptr make(
+ const size_t num_buffs,
+ const size_t buff_size,
+ const size_t alignment = 16
+ );
+
+ //! Get a pointer to the buffer start at the specified index
+ virtual ptr_type at(const size_t index) const = 0;
+
+ //! Get the number of buffers in this pool
+ virtual size_t size(void) const = 0;
+ };
+
+}} //namespace
+
+
+#endif /* INCLUDED_UHD_TRANSPORT_BUFFER_POOL_HPP */
diff --git a/host/include/uhd/transport/convert_types.hpp b/host/include/uhd/transport/convert_types.hpp
deleted file mode 100644
index dc7fa6c1a..000000000
--- a/host/include/uhd/transport/convert_types.hpp
+++ /dev/null
@@ -1,96 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#ifndef INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_HPP
-#define INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_HPP
-
-#include <uhd/config.hpp>
-#include <uhd/types/io_type.hpp>
-#include <uhd/types/otw_type.hpp>
-#include <vector>
-
-namespace uhd{ namespace transport{
-
-/*!
- * Convert IO samples to OWT samples.
- *
- * \param io_buff memory containing samples
- * \param io_type the type of these samples
- * \param otw_buff memory to write converted samples
- * \param otw_type the type of these samples
- * \param num_samps the number of samples in io_buff
- */
-UHD_API void convert_io_type_to_otw_type(
- const void *io_buff, const io_type_t &io_type,
- void *otw_buff, const otw_type_t &otw_type,
- size_t num_samps
-);
-
-/*!
- * Convert IO samples to OWT samples + interleave.
- *
- * \param io_buffs buffers containing samples
- * \param io_type the type of these samples
- * \param otw_buff memory to write converted samples
- * \param otw_type the type of these samples
- * \param nsamps_per_io_buff samples per io_buff
- */
-UHD_API void convert_io_type_to_otw_type(
- const std::vector<const void *> &io_buffs,
- const io_type_t &io_type,
- void *otw_buff,
- const otw_type_t &otw_type,
- size_t nsamps_per_io_buff
-);
-
-/*!
- * Convert OTW samples to IO samples.
- *
- * \param otw_buff memory containing samples
- * \param otw_type the type of these samples
- * \param io_buff memory to write converted samples
- * \param io_type the type of these samples
- * \param num_samps the number of samples in io_buff
- */
-UHD_API void convert_otw_type_to_io_type(
- const void *otw_buff, const otw_type_t &otw_type,
- void *io_buff, const io_type_t &io_type,
- size_t num_samps
-);
-
-/*!
- * Convert OTW samples to IO samples + de-interleave.
- *
- * \param otw_buff memory containing samples
- * \param otw_type the type of these samples
- * \param io_buffs buffers to write converted samples
- * \param io_type the type of these samples
- * \param nsamps_per_io_buff samples per io_buff
- */
-UHD_API void convert_otw_type_to_io_type(
- const void *otw_buff,
- const otw_type_t &otw_type,
- std::vector<void *> &io_buffs,
- const io_type_t &io_type,
- size_t nsamps_per_io_buff
-);
-
-}} //namespace
-
-#include <uhd/transport/convert_types.ipp>
-
-#endif /* INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_HPP */
diff --git a/host/include/uhd/transport/convert_types.ipp b/host/include/uhd/transport/convert_types.ipp
deleted file mode 100644
index 914ca6f17..000000000
--- a/host/include/uhd/transport/convert_types.ipp
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#ifndef INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_IPP
-#define INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_IPP
-
-UHD_INLINE void uhd::transport::convert_io_type_to_otw_type(
- const void *io_buff, const io_type_t &io_type,
- void *otw_buff, const otw_type_t &otw_type,
- size_t num_samps
-){
- std::vector<const void *> buffs(1, io_buff);
- return uhd::transport::convert_io_type_to_otw_type(
- buffs, io_type, otw_buff, otw_type, num_samps
- );
-}
-
-UHD_INLINE void uhd::transport::convert_otw_type_to_io_type(
- const void *otw_buff, const otw_type_t &otw_type,
- void *io_buff, const io_type_t &io_type,
- size_t num_samps
-){
- std::vector<void *> buffs(1, io_buff);
- return uhd::transport::convert_otw_type_to_io_type(
- otw_buff, otw_type, buffs, io_type, num_samps
- );
-}
-
-#endif /* INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_IPP */
diff --git a/host/include/uhd/transport/if_addrs.hpp b/host/include/uhd/transport/if_addrs.hpp
index fbbb35e1d..c831750d7 100644
--- a/host/include/uhd/transport/if_addrs.hpp
+++ b/host/include/uhd/transport/if_addrs.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -15,8 +15,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#ifndef INCLUDED_UHD_IFADDRS_HPP
-#define INCLUDED_UHD_IFADDRS_HPP
+#ifndef INCLUDED_UHD_TRANSPORT_IF_ADDRS_HPP
+#define INCLUDED_UHD_TRANSPORT_IF_ADDRS_HPP
#include <uhd/config.hpp>
#include <string>
@@ -44,4 +44,4 @@ namespace uhd{ namespace transport{
}} //namespace
-#endif /* INCLUDED_UHD_IFADDRS_HPP */
+#endif /* INCLUDED_UHD_TRANSPORT_IF_ADDRS_HPP */
diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt
index 1d2c0c41c..51be164aa 100644
--- a/host/include/uhd/types/CMakeLists.txt
+++ b/host/include/uhd/types/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -25,8 +25,8 @@ INSTALL(FILES
mac_addr.hpp
metadata.hpp
otw_type.hpp
- ranges.ipp
ranges.hpp
+ sensors.hpp
serial.hpp
stream_cmd.hpp
time_spec.hpp
diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp
index 9342fbb7b..a72eb63de 100644
--- a/host/include/uhd/types/clock_config.hpp
+++ b/host/include/uhd/types/clock_config.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -28,16 +28,19 @@ namespace uhd{
* The source and polarity for the PPS clock.
*/
struct UHD_API clock_config_t{
+ //------ simple usage --------//
+ static clock_config_t external(void);
+ static clock_config_t internal(void);
+
+ //------ advanced usage --------//
enum ref_source_t {
REF_AUTO = 'a', //automatic (device specific)
REF_INT = 'i', //internal reference
REF_SMA = 's', //external sma port
- REF_MIMO = 'm' //mimo cable (usrp2 only)
} ref_source;
enum pps_source_t {
PPS_INT = 'i', //there is no internal
PPS_SMA = 's', //external sma port
- PPS_MIMO = 'm' //mimo cable (usrp2 only)
} pps_source;
enum pps_polarity_t {
PPS_NEG = 'n', //negative edge
diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp
index 6166140a0..97fa8f09c 100644
--- a/host/include/uhd/types/dict.hpp
+++ b/host/include/uhd/types/dict.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -54,14 +54,14 @@ namespace uhd{
* Key order depends on insertion precedence.
* \return vector of keys
*/
- const std::vector<Key> keys(void) const;
+ std::vector<Key> keys(void) const;
/*!
* Get a list of the values in this dict.
* Value order depends on insertion precedence.
* \return vector of values
*/
- const std::vector<Val> vals(void) const;
+ std::vector<Val> vals(void) const;
/*!
* Does the dictionary contain this key?
@@ -73,10 +73,24 @@ namespace uhd{
/*!
* Get a value in the dict or default.
* \param key the key to look for
- * \param def use if key not found
+ * \param other use if key not found
* \return the value or default
*/
- const Val &get(const Key &key, const Val &def) const;
+ const Val &get(const Key &key, const Val &other) const;
+
+ /*!
+ * Get a value in the dict or throw.
+ * \param key the key to look for
+ * \return the value or default
+ */
+ const Val &get(const Key &key) const;
+
+ /*!
+ * Set a value in the dict at the key.
+ * \param key the key to set at
+ * \param val the value to set
+ */
+ void set(const Key &key, const Val &val);
/*!
* Get a value for the given key if it exists.
diff --git a/host/include/uhd/types/dict.ipp b/host/include/uhd/types/dict.ipp
index f037d7988..0c014474e 100644
--- a/host/include/uhd/types/dict.ipp
+++ b/host/include/uhd/types/dict.ipp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -59,7 +59,7 @@ namespace uhd{
}
template <typename Key, typename Val>
- const std::vector<Key> dict<Key, Val>::keys(void) const{
+ std::vector<Key> dict<Key, Val>::keys(void) const{
std::vector<Key> keys;
BOOST_FOREACH(const pair_t &p, _map){
keys.push_back(p.first);
@@ -68,7 +68,7 @@ namespace uhd{
}
template <typename Key, typename Val>
- const std::vector<Val> dict<Key, Val>::vals(void) const{
+ std::vector<Val> dict<Key, Val>::vals(void) const{
std::vector<Val> vals;
BOOST_FOREACH(const pair_t &p, _map){
vals.push_back(p.second);
@@ -85,11 +85,24 @@ namespace uhd{
}
template <typename Key, typename Val>
- const Val &dict<Key, Val>::get(const Key &key, const Val &def) const{
+ const Val &dict<Key, Val>::get(const Key &key, const Val &other) const{
BOOST_FOREACH(const pair_t &p, _map){
if (p.first == key) return p.second;
}
- return def;
+ return other;
+ }
+
+ template <typename Key, typename Val>
+ const Val &dict<Key, Val>::get(const Key &key) const{
+ BOOST_FOREACH(const pair_t &p, _map){
+ if (p.first == key) return p.second;
+ }
+ throw key_not_found<Key, Val>(key);
+ }
+
+ template <typename Key, typename Val>
+ void dict<Key, Val>::set(const Key &key, const Val &val){
+ (*this)[key] = val;
}
template <typename Key, typename Val>
diff --git a/host/include/uhd/types/ranges.hpp b/host/include/uhd/types/ranges.hpp
index 366efb1f3..f0d0e1c0b 100644
--- a/host/include/uhd/types/ranges.hpp
+++ b/host/include/uhd/types/ranges.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -22,7 +22,6 @@
#include <uhd/utils/pimpl.hpp>
#include <string>
#include <vector>
-#include <string>
namespace uhd{
@@ -30,14 +29,15 @@ namespace uhd{
* A range object describes a set of discrete values of the form:
* y = start + step*n, where n is an integer between 0 and (stop - start)/step
*/
- template <typename T> class range_t{
+ class UHD_API range_t{
public:
+
/*!
* Create a range from a single value.
* The step size will be taken as zero.
* \param value the only possible value in this range
*/
- range_t(const T &value = T(0));
+ range_t(double value = 0);
/*!
* Create a range from a full set of values.
@@ -46,28 +46,27 @@ namespace uhd{
* \param stop the maximum value for this range
* \param step the step size for this range
*/
- range_t(const T &start, const T &stop, const T &step = T(0));
+ range_t(double start, double stop, double step = 0);
//! Get the start value for this range.
- const T start(void) const;
+ double start(void) const;
//! Get the stop value for this range.
- const T stop(void) const;
+ double stop(void) const;
//! Get the step value for this range.
- const T step(void) const;
+ double step(void) const;
//! Convert this range to a printable string
const std::string to_pp_string(void) const;
- private:
- UHD_PIMPL_DECL(impl) _impl;
+ private: UHD_PIMPL_DECL(impl) _impl;
};
/*!
* A meta-range object holds a list of individual ranges.
*/
- template <typename T> struct meta_range_t : std::vector<range_t<T> >{
+ struct UHD_API meta_range_t : std::vector<range_t>{
//! A default constructor for an empty meta-range
meta_range_t(void);
@@ -79,7 +78,8 @@ namespace uhd{
* \param last the end iterator
*/
template <typename InputIterator>
- meta_range_t(InputIterator first, InputIterator last);
+ meta_range_t(InputIterator first, InputIterator last):
+ std::vector<range_t>(first, last){ /* NOP */ }
/*!
* A convenience constructor for a single range.
@@ -88,16 +88,16 @@ namespace uhd{
* \param stop the maximum value for this range
* \param step the step size for this range
*/
- meta_range_t(const T &start, const T &stop, const T &step = T(0));
+ meta_range_t(double start, double stop, double step = 0);
//! Get the overall start value for this meta-range.
- const T start(void) const;
+ double start(void) const;
//! Get the overall stop value for this meta-range.
- const T stop(void) const;
+ double stop(void) const;
//! Get the overall step value for this meta-range.
- const T step(void) const;
+ double step(void) const;
/*!
* Clip the target value to a possible range value.
@@ -105,22 +105,16 @@ namespace uhd{
* \param clip_step if true, clip to steps as well
* \return a value that is in one of the ranges
*/
- const T clip(const T &value, bool clip_step = false) const;
+ double clip(double value, bool clip_step = false) const;
//! Convert this meta-range to a printable string
const std::string to_pp_string(void) const;
};
- //!typedef for a gain meta-range
- typedef meta_range_t<float> gain_range_t;
-
- //!typedef for a frequency meta-range
- typedef meta_range_t<double> freq_range_t;
-
+ typedef meta_range_t gain_range_t;
+ typedef meta_range_t freq_range_t;
} //namespace uhd
-#include <uhd/types/ranges.ipp>
-
#endif /* INCLUDED_UHD_TYPES_RANGES_HPP */
diff --git a/host/include/uhd/types/ranges.ipp b/host/include/uhd/types/ranges.ipp
deleted file mode 100644
index 944ada51f..000000000
--- a/host/include/uhd/types/ranges.ipp
+++ /dev/null
@@ -1,188 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#ifndef INCLUDED_UHD_TYPES_RANGES_IPP
-#define INCLUDED_UHD_TYPES_RANGES_IPP
-
-#include <boost/math/special_functions/round.hpp>
-#include <boost/foreach.hpp>
-#include <algorithm>
-#include <stdexcept>
-#include <sstream>
-
-namespace uhd{
-
- /*******************************************************************
- * range_t implementation code
- ******************************************************************/
- template <typename T> struct range_t<T>::impl{
- impl(const T &start, const T &stop, const T &step):
- start(start), stop(stop), step(step)
- {
- /* NOP */
- }
- const T start, stop, step;
- };
-
- template <typename T> range_t<T>::range_t(const T &value):
- _impl(UHD_PIMPL_MAKE(impl, (value, value, T(0))))
- {
- /* NOP */
- }
-
- template <typename T> range_t<T>::range_t(
- const T &start, const T &stop, const T &step
- ):
- _impl(UHD_PIMPL_MAKE(impl, (start, stop, step)))
- {
- if (stop < start){
- throw std::invalid_argument("cannot make range where stop < start");
- }
- }
-
- template <typename T> const T range_t<T>::start(void) const{
- return _impl->start;
- }
-
- template <typename T> const T range_t<T>::stop(void) const{
- return _impl->stop;
- }
-
- template <typename T> const T range_t<T>::step(void) const{
- return _impl->step;
- }
-
- template <typename T> const std::string range_t<T>::to_pp_string(void) const{
- std::stringstream ss;
- ss << "(" << this->start();
- if (this->start() != this->stop()) ss << ", " << this->stop();
- if (this->step() != T(0)) ss << ", " << this->step();
- ss << ")";
- return ss.str();
- }
-
- /*******************************************************************
- * meta_range_t implementation code
- ******************************************************************/
-
- namespace /*anon*/{
- template <typename T> inline
- void check_meta_range_monotonic(const meta_range_t<T> &mr){
- if (mr.empty()){
- throw std::runtime_error("meta-range cannot be empty");
- }
- for (size_t i = 1; i < mr.size(); i++){
- if (mr.at(i).start() < mr.at(i-1).stop()){
- throw std::runtime_error("meta-range is not monotonic");
- }
- }
- }
- } //namespace /*anon*/
-
-
- template <typename T> meta_range_t<T>::meta_range_t(void){
- /* NOP */
- }
-
- template <typename T> template <typename InputIterator>
- meta_range_t<T>::meta_range_t(
- InputIterator first, InputIterator last
- ):
- std::vector<range_t<T> >(first, last)
- {
- /* NOP */
- }
-
- template <typename T> meta_range_t<T>::meta_range_t(
- const T &start, const T &stop, const T &step
- ):
- std::vector<range_t<T> > (1, range_t<T>(start, stop, step))
- {
- /* NOP */
- }
-
- template <typename T> const T meta_range_t<T>::start(void) const{
- check_meta_range_monotonic(*this);
- T min_start = this->front().start();
- BOOST_FOREACH(const range_t<T> &r, (*this)){
- min_start = std::min(min_start, r.start());
- }
- return min_start;
- }
-
- template <typename T> const T meta_range_t<T>::stop(void) const{
- check_meta_range_monotonic(*this);
- T max_stop = this->front().stop();
- BOOST_FOREACH(const range_t<T> &r, (*this)){
- max_stop = std::max(max_stop, r.stop());
- }
- return max_stop;
- }
-
- template <typename T> const T meta_range_t<T>::step(void) const{
- check_meta_range_monotonic(*this);
- std::vector<T> non_zero_steps;
- range_t<T> last = this->front();
- BOOST_FOREACH(const range_t<T> &r, (*this)){
- //steps at each range
- if (r.step() > T(0)) non_zero_steps.push_back(r.step());
- //and steps in-between ranges
- T ibtw_step = r.start() - last.stop();
- if (ibtw_step > T(0)) non_zero_steps.push_back(ibtw_step);
- //store ref to last
- last = r;
- }
- if (non_zero_steps.empty()) return T(0); //all zero steps, its zero...
- return *std::min_element(non_zero_steps.begin(), non_zero_steps.end());
- }
-
- template <typename T> const T meta_range_t<T>::clip(
- const T &value, bool clip_step
- ) const{
- check_meta_range_monotonic(*this);
- T last_stop = this->front().stop();
- BOOST_FOREACH(const range_t<T> &r, (*this)){
- //in-between ranges, clip to nearest
- if (value < r.start()){
- return (std::abs(value - r.start()) < std::abs(value - last_stop))?
- r.start() : last_stop;
- }
- //in this range, clip here
- if (value <= r.stop()){
- if (not clip_step or r.step() == T(0)) return value;
- return boost::math::round((value - r.start())/r.step())*r.step() + r.start();
- }
- //continue on to the next range
- last_stop = r.stop();
- }
- return last_stop;
- }
-
- template <typename T> const std::string meta_range_t<T>::to_pp_string(void) const{
- std::stringstream ss;
- BOOST_FOREACH(const range_t<T> &r, (*this)){
- ss << r.to_pp_string() << std::endl;
- }
- return ss.str();
- }
-
- UHD_EXIM_TMPL template struct UHD_API meta_range_t<float>;
- UHD_EXIM_TMPL template struct UHD_API meta_range_t<double>;
-
-} //namespace uhd
-
-#endif /* INCLUDED_UHD_TYPES_RANGES_IPP */
diff --git a/host/include/uhd/types/sensors.hpp b/host/include/uhd/types/sensors.hpp
new file mode 100644
index 000000000..6f003bb40
--- /dev/null
+++ b/host/include/uhd/types/sensors.hpp
@@ -0,0 +1,131 @@
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TYPES_SENSORS_HPP
+#define INCLUDED_UHD_TYPES_SENSORS_HPP
+
+#include <uhd/config.hpp>
+#include <string>
+
+namespace uhd{
+
+ /*!
+ * A sensor value stores a sensor reading as a string with unit and data type.
+ * The sensor value class can be used in the following way:
+ *
+ * sensor_value_t ref_lock_sensor("Reference", my_lock, "unlocked", "locked");
+ * std::cout << ref_lock_sensor.to_pp_string() << std::endl;
+ * //prints Reference: locked
+ *
+ * sensor_value_t temp_sensor("Temperature", my_temp, "C");
+ * std::cout << temp_sensor.to_pp_string() << std::endl;
+ * //prints Temperature: 38.5 C
+ */
+ struct UHD_API sensor_value_t{
+
+ //! typedef for the signed integer type
+ typedef signed int_type;
+
+ //! typedef for the real number type
+ typedef double real_type;
+
+ /*!
+ * Create a sensor value from a boolean.
+ * \param name the name of the sensor
+ * \param value the value true or false
+ * \param ufalse the unit string when value is false
+ * \param utrue the unit string when value is true
+ */
+ sensor_value_t(
+ const std::string &name,
+ bool value,
+ const std::string &ufalse,
+ const std::string &utrue
+ );
+
+ /*!
+ * Create a sensor value from an integer.
+ * \param name the name of the sensor
+ * \param value the signed integer value
+ * \param unit the associated unit type
+ * \param formatter the formatter string
+ */
+ sensor_value_t(
+ const std::string &name,
+ int_type value,
+ const std::string &unit,
+ const std::string &formatter = "%d"
+ );
+
+ /*!
+ * Create a sensor value from a real number.
+ * \param name the name of the sensor
+ * \param value the real number value
+ * \param unit the associated unit type
+ * \param formatter the formatter string
+ */
+ sensor_value_t(
+ const std::string &name,
+ real_type value,
+ const std::string &unit,
+ const std::string &formatter = "%f"
+ );
+
+ /*!
+ * Create a sensor value from a string.
+ * \param name the name of the sensor
+ * \param value the real number value
+ * \param unit the associated unit type
+ */
+ sensor_value_t(
+ const std::string &name,
+ const std::string &value,
+ const std::string &unit
+ );
+
+ //! The name of the sensor value
+ const std::string name;
+
+ /*!
+ * The sensor value as a string.
+ * For integer and real number types, this will be the output of the formatter.
+ * For boolean types, the value will be the string literal "true" or "false".
+ */
+ const std::string value;
+
+ /*!
+ * The sensor value's unit type.
+ * For boolean types, this will be the one of the two units
+ * depending upon the value of the boolean true or false.
+ */
+ const std::string unit;
+
+ //! The data type of the value
+ const enum{
+ BOOLEAN = 'b',
+ INTEGER = 'i',
+ REALNUM = 'r',
+ STRING = 's'
+ } type;
+
+ //! Convert this sensor value into a printable string
+ std::string to_pp_string(void) const;
+ };
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_TYPES_SENSORS_HPP */
diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt
index c8d7281d3..f60b35e59 100644
--- a/host/include/uhd/usrp/CMakeLists.txt
+++ b/host/include/uhd/usrp/CMakeLists.txt
@@ -34,6 +34,7 @@ INSTALL(FILES
### utilities ###
dsp_utils.hpp
+ gps_ctrl.hpp
mboard_eeprom.hpp
misc_utils.hpp
subdev_spec.hpp
diff --git a/host/include/uhd/usrp/codec_props.hpp b/host/include/uhd/usrp/codec_props.hpp
index ab09b1703..5d0a2913c 100644
--- a/host/include/uhd/usrp/codec_props.hpp
+++ b/host/include/uhd/usrp/codec_props.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -30,8 +30,8 @@ namespace uhd{ namespace usrp{
enum codec_prop_t{
CODEC_PROP_NAME = 'n', //ro, std::string
CODEC_PROP_OTHERS = 'o', //ro, prop_names_t
- CODEC_PROP_GAIN_I = 'i', //rw, float
- CODEC_PROP_GAIN_Q = 'q', //rw, float
+ CODEC_PROP_GAIN_I = 'i', //rw, double
+ CODEC_PROP_GAIN_Q = 'q', //rw, double
CODEC_PROP_GAIN_RANGE = 'r', //ro, gain_range_t
CODEC_PROP_GAIN_NAMES = 'G' //ro, prop_names_t
};
diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp
index b04756c47..cfb727017 100644
--- a/host/include/uhd/usrp/dboard_iface.hpp
+++ b/host/include/uhd/usrp/dboard_iface.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -102,7 +102,7 @@ public:
* \param which_dac the dac index 0, 1, 2, 3...
* \param value the value in volts
*/
- virtual void write_aux_dac(unit_t unit, aux_dac_t which_dac, float value) = 0;
+ virtual void write_aux_dac(unit_t unit, aux_dac_t which_dac, double value) = 0;
/*!
* Read from an aux adc.
@@ -111,7 +111,7 @@ public:
* \param which_adc the adc index 0, 1, 2, 3...
* \return the value in volts
*/
- virtual float read_aux_adc(unit_t unit, aux_adc_t which_adc) = 0;
+ virtual double read_aux_adc(unit_t unit, aux_adc_t which_adc) = 0;
/*!
* Set a daughterboard output pin control source.
@@ -191,8 +191,6 @@ public:
*/
virtual boost::uint16_t get_gpio_out(unit_t unit);
- UHD_DEPRECATED void write_gpio(unit_t unit, boost::uint16_t value){set_gpio_out(unit, value);}
-
/*!
* Setup the GPIO debug mux.
*
diff --git a/host/lib/usrp/usrp2/gps_ctrl.hpp b/host/include/uhd/usrp/gps_ctrl.hpp
index 5936a6fb6..74f984ee0 100644
--- a/host/lib/usrp/usrp2/gps_ctrl.hpp
+++ b/host/include/uhd/usrp/gps_ctrl.hpp
@@ -18,21 +18,24 @@
#ifndef INCLUDED_GPS_CTRL_HPP
#define INCLUDED_GPS_CTRL_HPP
-#include "usrp2_iface.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
+#include <boost/function.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
using namespace boost::posix_time;
-class usrp2_gps_ctrl : boost::noncopyable{
+typedef boost::function<void(std::string)> gps_send_fn_t;
+typedef boost::function<std::string(void)> gps_recv_fn_t;
+
+class gps_ctrl : boost::noncopyable{
public:
- typedef boost::shared_ptr<usrp2_gps_ctrl> sptr;
+ typedef boost::shared_ptr<gps_ctrl> sptr;
/*!
* Make a GPS config for Jackson Labs or generic NMEA GPS devices
*/
- static sptr make(usrp2_iface::sptr iface);
+ static sptr make(gps_send_fn_t, gps_recv_fn_t);
/*!
* Get the current GPS time and date
@@ -50,4 +53,4 @@ public:
};
-#endif /* INCLUDED_CLOCK_CTRL_HPP */
+#endif /* INCLUDED_GPS_CTRL_HPP */
diff --git a/host/include/uhd/usrp/mboard_props.hpp b/host/include/uhd/usrp/mboard_props.hpp
index df94d1678..c82bfc21a 100644
--- a/host/include/uhd/usrp/mboard_props.hpp
+++ b/host/include/uhd/usrp/mboard_props.hpp
@@ -43,7 +43,7 @@ namespace uhd{ namespace usrp{
MBOARD_PROP_TX_SUBDEV_SPEC = 'R', //rw, subdev_spec_t
MBOARD_PROP_CLOCK_CONFIG = 'C', //rw, clock_config_t
MBOARD_PROP_TIME_NOW = 't', //rw, time_spec_t
- MBOARD_PROP_TIME_NEXT_PPS = 'T', //wo, time_spec_t
+ MBOARD_PROP_TIME_PPS = 'T', //wo, time_spec_t
MBOARD_PROP_STREAM_CMD = 's', //wo, stream_cmd_t
MBOARD_PROP_EEPROM_MAP = 'M' //wr, mboard_eeprom_t::sptr
};
diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp
index 98ba07fc0..b603d4324 100644
--- a/host/include/uhd/usrp/multi_usrp.hpp
+++ b/host/include/uhd/usrp/multi_usrp.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -51,7 +51,8 @@ namespace uhd{ namespace usrp{
*
* //create a multi_usrp with two boards in the configuration
* device_addr_t dev_addr;
- * dev_addr["addr"] = "192.168.10.2 192.168.10.3";
+ * dev_addr["addr0"] = "192.168.10.2"
+ * dev_addr["addr1"] = "192.168.10.3";
* multi_usrp::sptr dev = multi_usrp::make(dev_addr);
*
* //set the board on 10.2 to use the A RX subdevice (RX channel 0)
@@ -108,12 +109,18 @@ public:
virtual std::string get_mboard_name(size_t mboard) = 0;
/*!
- * Gets the current time in the usrp time registers.
+ * Get the current time in the usrp time registers.
* \return a timespec representing current usrp time
*/
virtual time_spec_t get_time_now(void) = 0;
/*!
+ * Get the time when the last pps pulse occured.
+ * \return a timespec representing the last pps
+ */
+ virtual time_spec_t get_time_last_pps(void) = 0;
+
+ /*!
* Set the time registers on the usrp at the next pps tick.
* The values will not be latched in until the pulse occurs.
* It is recommended that the user sleep(1) after calling to ensure
@@ -133,14 +140,13 @@ public:
* Ex: Host machine is not attached to serial port of GPSDO
* and can therefore not query the GPSDO for the PPS edge.
*
- * This is a 3-step process, and will take at most 3 seconds to complete.
+ * This is a 2-step process, and will take at most 2 seconds to complete.
* Upon completion, the times will be synchronized to the time provided.
*
- * - Step1: set the time at the next pps (potential race condition)
- * - Step2: wait for the seconds to rollover to catch the pps edge
- * - Step3: set the time at the next pps (synchronous for all boards)
+ * - Step1: wait for the last pps time to transition to catch the edge
+ * - Step2: set the time at the next pps (synchronous for all boards)
*
- * \param time_spec the time to latch into the usrp device
+ * \param time_spec the time to latch at the next pps after catching the edge
*/
virtual void set_time_unknown_pps(const time_spec_t &time_spec) = 0;
@@ -251,10 +257,10 @@ public:
* \param name the name of the gain element
* \param chan the channel index 0 to N-1
*/
- virtual void set_rx_gain(float gain, const std::string &name, size_t chan) = 0;
+ virtual void set_rx_gain(double gain, const std::string &name, size_t chan) = 0;
//! A convenience wrapper for setting overall RX gain
- void set_rx_gain(float gain, size_t chan){
+ void set_rx_gain(double gain, size_t chan){
return this->set_rx_gain(gain, ALL_GAINS, chan);
}
@@ -265,10 +271,10 @@ public:
* \param chan the channel index 0 to N-1
* \return the gain in dB
*/
- virtual float get_rx_gain(const std::string &name, size_t chan) = 0;
+ virtual double get_rx_gain(const std::string &name, size_t chan) = 0;
//! A convenience wrapper for getting overall RX gain
- float get_rx_gain(size_t chan){
+ double get_rx_gain(size_t chan){
return this->get_rx_gain(ALL_GAINS, chan);
}
@@ -342,7 +348,7 @@ public:
* \return the rssi in dB
* \throw exception if RSSI readback not supported
*/
- virtual float read_rssi(size_t chan) = 0;
+ virtual double read_rssi(size_t chan) = 0;
/*!
* Get the dboard interface object for the RX subdevice.
@@ -430,10 +436,10 @@ public:
* \param name the name of the gain element
* \param chan the channel index 0 to N-1
*/
- virtual void set_tx_gain(float gain, const std::string &name, size_t chan) = 0;
+ virtual void set_tx_gain(double gain, const std::string &name, size_t chan) = 0;
//! A convenience wrapper for setting overall TX gain
- void set_tx_gain(float gain, size_t chan){
+ void set_tx_gain(double gain, size_t chan){
return this->set_tx_gain(gain, ALL_GAINS, chan);
}
@@ -444,10 +450,10 @@ public:
* \param chan the channel index 0 to N-1
* \return the gain in dB
*/
- virtual float get_tx_gain(const std::string &name, size_t chan) = 0;
+ virtual double get_tx_gain(const std::string &name, size_t chan) = 0;
//! A convenience wrapper for getting overall TX gain
- float get_tx_gain(size_t chan){
+ double get_tx_gain(size_t chan){
return this->get_tx_gain(ALL_GAINS, chan);
}
diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp
index 26303fe10..d80999300 100644
--- a/host/include/uhd/usrp/single_usrp.hpp
+++ b/host/include/uhd/usrp/single_usrp.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -77,12 +77,18 @@ public:
virtual std::string get_mboard_name(void) = 0;
/*!
- * Gets the current time in the usrp time registers.
+ * Get the current time in the usrp time registers.
* \return a timespec representing current usrp time
*/
virtual time_spec_t get_time_now(void) = 0;
/*!
+ * Get the time when the last pps pulse occured.
+ * \return a timespec representing the last pps
+ */
+ virtual time_spec_t get_time_last_pps(void) = 0;
+
+ /*!
* Sets the time registers on the usrp immediately.
* \param time_spec the time to latch into the usrp device
*/
@@ -184,10 +190,10 @@ public:
* \param name the name of the gain element
* \param chan the channel index 0 to N-1
*/
- virtual void set_rx_gain(float gain, const std::string &name, size_t chan = 0) = 0;
+ virtual void set_rx_gain(double gain, const std::string &name, size_t chan = 0) = 0;
//! A convenience wrapper for setting overall RX gain
- void set_rx_gain(float gain, size_t chan = 0){
+ void set_rx_gain(double gain, size_t chan = 0){
return this->set_rx_gain(gain, ALL_GAINS, chan);
}
@@ -198,10 +204,10 @@ public:
* \param chan the channel index 0 to N-1
* \return the gain in dB
*/
- virtual float get_rx_gain(const std::string &name, size_t chan = 0) = 0;
+ virtual double get_rx_gain(const std::string &name, size_t chan = 0) = 0;
//! A convenience wrapper for getting overall RX gain
- float get_rx_gain(size_t chan = 0){
+ double get_rx_gain(size_t chan = 0){
return this->get_rx_gain(ALL_GAINS, chan);
}
@@ -275,7 +281,7 @@ public:
* \return the rssi in dB
* \throw exception if RSSI readback not supported
*/
- virtual float read_rssi(size_t chan = 0) = 0;
+ virtual double read_rssi(size_t chan = 0) = 0;
/*!
* Get the dboard interface object for the RX subdevice.
@@ -353,10 +359,10 @@ public:
* \param name the name of the gain element
* \param chan the channel index 0 to N-1
*/
- virtual void set_tx_gain(float gain, const std::string &name, size_t chan = 0) = 0;
+ virtual void set_tx_gain(double gain, const std::string &name, size_t chan = 0) = 0;
//! A convenience wrapper for setting overall TX gain
- void set_tx_gain(float gain, size_t chan = 0){
+ void set_tx_gain(double gain, size_t chan = 0){
return this->set_tx_gain(gain, ALL_GAINS, chan);
}
@@ -367,10 +373,10 @@ public:
* \param chan the channel index 0 to N-1
* \return the gain in dB
*/
- virtual float get_tx_gain(const std::string &name, size_t chan = 0) = 0;
+ virtual double get_tx_gain(const std::string &name, size_t chan = 0) = 0;
//! A convenience wrapper for getting overall TX gain
- float get_tx_gain(size_t chan = 0){
+ double get_tx_gain(size_t chan = 0){
return this->get_tx_gain(ALL_GAINS, chan);
}
diff --git a/host/include/uhd/usrp/subdev_props.hpp b/host/include/uhd/usrp/subdev_props.hpp
index 8f096ffe4..8d05f4c27 100644
--- a/host/include/uhd/usrp/subdev_props.hpp
+++ b/host/include/uhd/usrp/subdev_props.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@ namespace uhd{ namespace usrp{
enum subdev_prop_t{
SUBDEV_PROP_NAME = 'n', //ro, std::string
SUBDEV_PROP_OTHERS = 'o', //ro, prop_names_t
- SUBDEV_PROP_GAIN = 'g', //rw, float
+ SUBDEV_PROP_GAIN = 'g', //rw, double
SUBDEV_PROP_GAIN_RANGE = 'r', //ro, gain_range_t
SUBDEV_PROP_GAIN_NAMES = 'G', //ro, prop_names_t
SUBDEV_PROP_FREQ = 'f', //rw, double
@@ -55,7 +55,7 @@ namespace uhd{ namespace usrp{
SUBDEV_PROP_CONNECTION = 'c', //ro, subdev_conn_t
SUBDEV_PROP_ENABLED = 'e', //rw, bool
SUBDEV_PROP_USE_LO_OFFSET = 'l', //ro, bool
- SUBDEV_PROP_RSSI = 'R', //ro, float
+ SUBDEV_PROP_RSSI = 'R', //ro, double
SUBDEV_PROP_BANDWIDTH = 'B' //rw, double
};
diff --git a/host/include/uhd/utils/algorithm.hpp b/host/include/uhd/utils/algorithm.hpp
index 53c571e4e..5e2230371 100644
--- a/host/include/uhd/utils/algorithm.hpp
+++ b/host/include/uhd/utils/algorithm.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -22,9 +22,6 @@
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
-#include <boost/algorithm/string.hpp>
-#include <vector>
-#include <string>
/*! \file algorithm.hpp
* Useful templated functions and classes that I like to pretend are part of stl.
@@ -33,24 +30,6 @@
namespace std{
/*!
- * Split a string at the separation characters.
- * \param string the string to split
- * \param sep the separator characters
- * \return a range of strings
- */
- inline std::vector<std::string> split_string(
- const std::string &string, const std::string &sep = "\t "
- ){
- std::vector<std::string> strings;
- if (not string.empty()) boost::split(
- // do not split an empty string:
- // let me tell you about the time when boost::split segfaulted...
- strings, string, boost::is_any_of(sep)
- );
- return strings;
- }
-
- /*!
* A wrapper around std::copy that takes ranges instead of iterators.
*
* Copy the elements of the source range into the destination range.
@@ -164,8 +143,12 @@ namespace std{
* \param bound2 the upper or lower bound
* \return the value clipped at the bounds
*/
- template<typename T> inline T clip(T val, T bound1, T bound2){
- return std::min(std::max(val, std::min(bound1, bound2)), std::max(bound1, bound2));
+ template<typename T> inline T clip(const T &val, const T &bound1, const T &bound2){
+ const T minimum = std::min(bound1, bound2);
+ if (val < minimum) return minimum;
+ const T maximum = std::max(bound1, bound2);
+ if (val > maximum) return maximum;
+ return val;
}
}//namespace std
diff --git a/host/include/uhd/utils/gain_group.hpp b/host/include/uhd/utils/gain_group.hpp
index c863248ce..7ef7bdcf5 100644
--- a/host/include/uhd/utils/gain_group.hpp
+++ b/host/include/uhd/utils/gain_group.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -33,8 +33,8 @@ namespace uhd{
*/
struct UHD_API gain_fcns_t{
boost::function<gain_range_t(void)> get_range;
- boost::function<float(void)> get_value;
- boost::function<void(float)> set_value;
+ boost::function<double(void)> get_value;
+ boost::function<void(double)> set_value;
};
class UHD_API gain_group : boost::noncopyable{
@@ -56,7 +56,7 @@ public:
* \param name name of the gain element (optional)
* \return a gain value of the element or all elements
*/
- virtual float get_value(const std::string &name = "") = 0;
+ virtual double get_value(const std::string &name = "") = 0;
/*!
* Set the gain value for the gain element specified by name.
@@ -66,7 +66,7 @@ public:
* \param gain the gain to set for the lement or across the group
* \param name name of the gain element (optional)
*/
- virtual void set_value(float gain, const std::string &name = "") = 0;
+ virtual void set_value(double gain, const std::string &name = "") = 0;
/*!
* Get a list of names of registered gain elements.
diff --git a/host/include/uhd/utils/static.hpp b/host/include/uhd/utils/static.hpp
index c61f10884..82cdf36d9 100644
--- a/host/include/uhd/utils/static.hpp
+++ b/host/include/uhd/utils/static.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -30,8 +30,17 @@
/*!
* Defines a static code block that will be called before main()
- * \param _x the name of the defined struct (must be unique in file)
+ * The static block will catch and print exceptions to std error.
+ * \param _x the unique name of the fixture (unique per source)
*/
-#define UHD_STATIC_BLOCK(_x) static struct _x{_x();}_x;_x::_x()
+#define UHD_STATIC_BLOCK(_x) \
+ void _x(void); \
+ static _uhd_static_fixture _x##_fixture(&_x, #_x); \
+ void _x(void)
+
+//! Helper for static block, constructor calls function
+struct UHD_API _uhd_static_fixture{
+ _uhd_static_fixture(void (*)(void), const char *);
+};
#endif /* INCLUDED_UHD_UTILS_STATIC_HPP */
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index 498841561..d2845ffda 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -16,27 +16,6 @@
#
########################################################################
-# Check Python Modules
-########################################################################
-INCLUDE(UHDPython)
-
-PYTHON_CHECK_MODULE(
- "Python version 2.6 or greater"
- "platform" "platform.python_version() >= '2.6'"
- HAVE_PYTHON_PLAT_MIN_VERSION
-)
-
-PYTHON_CHECK_MODULE(
- "Cheetah templates 2.0.0 or greater"
- "Cheetah" "Cheetah.Version >= '2.0.0'"
- HAVE_PYTHON_MODULE_CHEETAH
-)
-
-IF(NOT HAVE_PYTHON_PLAT_MIN_VERSION OR NOT HAVE_PYTHON_MODULE_CHEETAH)
- MESSAGE(FATAL_ERROR "Error: python requirements not met for the build system.")
-ENDIF(NOT HAVE_PYTHON_PLAT_MIN_VERSION OR NOT HAVE_PYTHON_MODULE_CHEETAH)
-
-########################################################################
# Helpful Macros
########################################################################
MACRO(LIBUHD_APPEND_SOURCES)
@@ -89,6 +68,8 @@ ENDMACRO(INCLUDE_SUBDIRECTORY)
# Include subdirectories (different than add)
########################################################################
INCLUDE_SUBDIRECTORY(ic_reg_maps)
+INCLUDE_SUBDIRECTORY(types)
+INCLUDE_SUBDIRECTORY(convert)
INCLUDE_SUBDIRECTORY(transport)
INCLUDE_SUBDIRECTORY(usrp)
INCLUDE_SUBDIRECTORY(utils)
@@ -116,7 +97,6 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_BINARY_DIR}/constants.hpp
${CMAKE_CURRENT_SOURCE_DIR}/device.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/types.cpp
${CMAKE_CURRENT_SOURCE_DIR}/version.cpp
${CMAKE_CURRENT_SOURCE_DIR}/wax.cpp
)
@@ -127,6 +107,7 @@ LIBUHD_APPEND_SOURCES(
ADD_LIBRARY(uhd SHARED ${libuhd_sources})
TARGET_LINK_LIBRARIES(uhd ${Boost_LIBRARIES} ${libuhd_libs})
SET_TARGET_PROPERTIES(uhd PROPERTIES DEFINE_SYMBOL "UHD_DLL_EXPORTS")
+SET_TARGET_PROPERTIES(uhd PROPERTIES SOVERSION ${UHD_VERSION_MAJOR})
INSTALL(TARGETS uhd
LIBRARY DESTINATION ${LIBRARY_DIR} # .so file
diff --git a/host/lib/convert/CMakeLists.txt b/host/lib/convert/CMakeLists.txt
new file mode 100644
index 000000000..a9f977cdc
--- /dev/null
+++ b/host/lib/convert/CMakeLists.txt
@@ -0,0 +1,65 @@
+#
+# Copyright 2011 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+########################################################################
+# This file included, use CMake directory variables
+########################################################################
+INCLUDE(CheckIncludeFileCXX)
+MESSAGE(STATUS "")
+
+########################################################################
+# Check for SIMD headers
+########################################################################
+CHECK_INCLUDE_FILE_CXX(emmintrin.h HAVE_EMMINTRIN_H)
+IF(HAVE_EMMINTRIN_H)
+ LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/convert_with_sse2.cpp
+ )
+ENDIF(HAVE_EMMINTRIN_H)
+
+CHECK_INCLUDE_FILE_CXX(arm_neon.h HAVE_ARM_NEON_H)
+IF(HAVE_ARM_NEON_H)
+ LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/convert_with_neon.cpp
+ )
+ENDIF(HAVE_ARM_NEON_H)
+
+########################################################################
+# Convert types generation
+########################################################################
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
+LIBUHD_PYTHON_GEN_SOURCE(
+ ${CMAKE_CURRENT_SOURCE_DIR}/gen_convert_pred.py
+ ${CMAKE_CURRENT_BINARY_DIR}/convert_pred.hpp
+)
+
+INCLUDE(AddFileDependencies)
+ADD_FILE_DEPENDENCIES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/convert_impl.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/convert_pred.hpp
+)
+
+LIBUHD_PYTHON_GEN_SOURCE(
+ ${CMAKE_CURRENT_SOURCE_DIR}/gen_convert_general.py
+ ${CMAKE_CURRENT_BINARY_DIR}/convert_general.cpp
+)
+
+LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/convert_impl.cpp
+)
diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp
new file mode 100644
index 000000000..1a653a56f
--- /dev/null
+++ b/host/lib/convert/convert_common.hpp
@@ -0,0 +1,90 @@
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_LIBUHD_CONVERT_COMMON_HPP
+#define INCLUDED_LIBUHD_CONVERT_COMMON_HPP
+
+#include <uhd/convert.hpp>
+#include <uhd/utils/static.hpp>
+#include <boost/cstdint.hpp>
+#include <complex>
+
+#define DECLARE_CONVERTER(fcn, prio) \
+ static void fcn( \
+ uhd::convert::input_type &inputs, \
+ uhd::convert::output_type &outputs, \
+ size_t nsamps \
+ ); \
+ UHD_STATIC_BLOCK(register_##fcn##_##prio){ \
+ uhd::convert::register_converter(#fcn, fcn, prio); \
+ } \
+ static void fcn( \
+ uhd::convert::input_type &inputs, \
+ uhd::convert::output_type &outputs, \
+ size_t nsamps \
+ )
+
+/***********************************************************************
+ * Typedefs
+ **********************************************************************/
+typedef std::complex<float> fc32_t;
+typedef std::complex<boost::int16_t> sc16_t;
+typedef boost::uint32_t item32_t;
+
+/***********************************************************************
+ * Convert complex short buffer to items32
+ **********************************************************************/
+static UHD_INLINE item32_t sc16_to_item32(sc16_t num){
+ boost::uint16_t real = num.real();
+ boost::uint16_t imag = num.imag();
+ return (item32_t(real) << 16) | (item32_t(imag) << 0);
+}
+
+/***********************************************************************
+ * Convert items32 buffer to complex short
+ **********************************************************************/
+static UHD_INLINE sc16_t item32_to_sc16(item32_t item){
+ return sc16_t(
+ boost::int16_t(item >> 16),
+ boost::int16_t(item >> 0)
+ );
+}
+
+/***********************************************************************
+ * Convert complex float buffer to items32 (no swap)
+ **********************************************************************/
+static const float shorts_per_float = float(32767);
+
+static UHD_INLINE item32_t fc32_to_item32(fc32_t num){
+ boost::uint16_t real = boost::int16_t(num.real()*shorts_per_float);
+ boost::uint16_t imag = boost::int16_t(num.imag()*shorts_per_float);
+ return (item32_t(real) << 16) | (item32_t(imag) << 0);
+}
+
+/***********************************************************************
+ * Convert items32 buffer to complex float
+ **********************************************************************/
+static const float floats_per_short = float(1.0/shorts_per_float);
+
+static UHD_INLINE fc32_t item32_to_fc32(item32_t item){
+ return fc32_t(
+ float(boost::int16_t(item >> 16)*floats_per_short),
+ float(boost::int16_t(item >> 0)*floats_per_short)
+ );
+}
+
+#endif /* INCLUDED_LIBUHD_CONVERT_COMMON_HPP */
diff --git a/host/lib/convert/convert_impl.cpp b/host/lib/convert/convert_impl.cpp
new file mode 100644
index 000000000..6a5a1465d
--- /dev/null
+++ b/host/lib/convert/convert_impl.cpp
@@ -0,0 +1,111 @@
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/convert.hpp>
+#include <uhd/utils/static.hpp>
+#include <uhd/utils/exception.hpp>
+#include <iostream>
+
+using namespace uhd;
+
+#include "convert_pred.hpp"
+
+static const bool debug = false;
+
+/***********************************************************************
+ * Define types for the function tables
+ **********************************************************************/
+struct fcn_table_entry_type{
+ convert::priority_type prio;
+ convert::function_type fcn;
+ fcn_table_entry_type(void)
+ : prio(convert::PRIORITY_EMPTY), fcn(NULL){
+ /* NOP */
+ }
+};
+typedef std::vector<fcn_table_entry_type> fcn_table_type;
+
+/***********************************************************************
+ * Setup the table registry
+ **********************************************************************/
+UHD_SINGLETON_FCN(fcn_table_type, get_cpu_to_otw_table);
+UHD_SINGLETON_FCN(fcn_table_type, get_otw_to_cpu_table);
+
+fcn_table_type &get_table(dir_type dir){
+ switch(dir){
+ case DIR_OTW_TO_CPU: return get_otw_to_cpu_table();
+ case DIR_CPU_TO_OTW: return get_cpu_to_otw_table();
+ }
+ UHD_THROW_INVALID_CODE_PATH();
+}
+
+/***********************************************************************
+ * The registry functions
+ **********************************************************************/
+void uhd::convert::register_converter(
+ const std::string &markup,
+ function_type fcn,
+ priority_type prio
+){
+ //extract the predicate and direction from the markup
+ dir_type dir;
+ pred_type pred = make_pred(markup, dir);
+
+ //get a reference to the function table
+ fcn_table_type &table = get_table(dir);
+
+ //resize the table so that its at least pred+1
+ if (table.size() <= pred) table.resize(pred+1);
+
+ //register the function if higher priority
+ if (table[pred].prio < prio){
+ table[pred].fcn = fcn;
+ table[pred].prio = prio;
+ }
+
+ //----------------------------------------------------------------//
+ if (debug) std::cout << "register_converter: " << markup << std::endl
+ << " prio: " << prio << std::endl
+ << " pred: " << pred << std::endl
+ << " dir: " << dir << std::endl
+ << std::endl
+ ;
+ //----------------------------------------------------------------//
+}
+
+/***********************************************************************
+ * The converter functions
+ **********************************************************************/
+const convert::function_type &convert::get_converter_cpu_to_otw(
+ const io_type_t &io_type,
+ const otw_type_t &otw_type,
+ size_t num_input_buffs,
+ size_t num_output_buffs
+){
+ pred_type pred = make_pred(io_type, otw_type, num_input_buffs, num_output_buffs);
+ return get_cpu_to_otw_table().at(pred).fcn;
+}
+
+const convert::function_type &convert::get_converter_otw_to_cpu(
+ const io_type_t &io_type,
+ const otw_type_t &otw_type,
+ size_t num_input_buffs,
+ size_t num_output_buffs
+){
+ pred_type pred = make_pred(io_type, otw_type, num_input_buffs, num_output_buffs);
+ return get_otw_to_cpu_table().at(pred).fcn;
+}
diff --git a/host/lib/convert/convert_with_neon.cpp b/host/lib/convert/convert_with_neon.cpp
new file mode 100644
index 000000000..3d677db5b
--- /dev/null
+++ b/host/lib/convert/convert_with_neon.cpp
@@ -0,0 +1,61 @@
+//
+// Copyright 2011-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include "convert_common.hpp"
+#include <arm_neon.h>
+
+using namespace uhd::convert;
+
+DECLARE_CONVERTER(convert_fc32_1_to_item32_1_nswap, PRIORITY_CUSTOM){
+ const fc32_t *input = reinterpret_cast<const fc32_t *>(inputs[0]);
+ item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
+
+ size_t i;
+
+ float32x4_t Q0 = vdupq_n_f32(shorts_per_float);
+ for (i=0; i < (nsamps & ~0x03); i+=2) {
+ float32x4_t Q1 = vld1q_f32(reinterpret_cast<const float *>(&input[i]));
+ float32x4_t Q2 = vmulq_f32(Q1, Q0);
+ int32x4_t Q3 = vcvtq_s32_f32(Q2);
+ int16x4_t D8 = vmovn_s32(Q3);
+ int16x4_t D9 = vrev32_s16(D8);
+ vst1_s16((reinterpret_cast<int16_t *>(&output[i])), D9);
+ }
+
+ for (; i < nsamps; i++)
+ output[i] = fc32_to_item32(input[i]);
+}
+
+DECLARE_CONVERTER(convert_item32_1_to_fc32_1_nswap, PRIORITY_CUSTOM){
+ const item32_t *input = reinterpret_cast<const item32_t *>(inputs[0]);
+ fc32_t *output = reinterpret_cast<fc32_t *>(outputs[0]);
+
+ size_t i;
+
+ float32x4_t Q1 = vdupq_n_f32(floats_per_short);
+ for (i=0; i < (nsamps & ~0x03); i+=2) {
+ int16x4_t D0 = vld1_s16(reinterpret_cast<const int16_t *>(&input[i]));
+ int16x4_t D1 = vrev32_s16(D0);
+ int32x4_t Q2 = vmovl_s16(D1);
+ float32x4_t Q3 = vcvtq_f32_s32(Q2);
+ float32x4_t Q4 = vmulq_f32(Q3, Q1);
+ vst1q_f32((reinterpret_cast<float *>(&output[i])), Q4);
+ }
+
+ for (; i < nsamps; i++)
+ output[i] = item32_to_fc32(input[i]);
+}
diff --git a/host/lib/convert/convert_with_sse2.cpp b/host/lib/convert/convert_with_sse2.cpp
new file mode 100644
index 000000000..96ee9134c
--- /dev/null
+++ b/host/lib/convert/convert_with_sse2.cpp
@@ -0,0 +1,148 @@
+//
+// Copyright 2011-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include "convert_common.hpp"
+#include <uhd/utils/byteswap.hpp>
+#include <emmintrin.h>
+
+using namespace uhd::convert;
+
+DECLARE_CONVERTER(convert_fc32_1_to_item32_1_nswap, PRIORITY_CUSTOM){
+ const fc32_t *input = reinterpret_cast<const fc32_t *>(inputs[0]);
+ item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
+
+ __m128 scalar = _mm_set_ps1(shorts_per_float);
+
+ //convert blocks of samples with intrinsics
+ size_t i = 0; for (; i < (nsamps & ~0x3); i+=4){
+ //load from input
+ __m128 tmplo = _mm_loadu_ps(reinterpret_cast<const float *>(input+i+0));
+ __m128 tmphi = _mm_loadu_ps(reinterpret_cast<const float *>(input+i+2));
+
+ //convert and scale
+ __m128i tmpilo = _mm_cvtps_epi32(_mm_mul_ps(tmplo, scalar));
+ __m128i tmpihi = _mm_cvtps_epi32(_mm_mul_ps(tmphi, scalar));
+
+ //pack + swap 16-bit pairs
+ __m128i tmpi = _mm_packs_epi32(tmpilo, tmpihi);
+ tmpi = _mm_shufflelo_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
+ tmpi = _mm_shufflehi_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
+
+ //store to output
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(output+i), tmpi);
+ }
+
+ //convert remainder
+ for (; i < nsamps; i++){
+ output[i] = fc32_to_item32(input[i]);
+ }
+}
+
+DECLARE_CONVERTER(convert_fc32_1_to_item32_1_bswap, PRIORITY_CUSTOM){
+ const fc32_t *input = reinterpret_cast<const fc32_t *>(inputs[0]);
+ item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
+
+ __m128 scalar = _mm_set_ps1(shorts_per_float);
+
+ //convert blocks of samples with intrinsics
+ size_t i = 0; for (; i < (nsamps & ~0x3); i+=4){
+ //load from input
+ __m128 tmplo = _mm_loadu_ps(reinterpret_cast<const float *>(input+i+0));
+ __m128 tmphi = _mm_loadu_ps(reinterpret_cast<const float *>(input+i+2));
+
+ //convert and scale
+ __m128i tmpilo = _mm_cvtps_epi32(_mm_mul_ps(tmplo, scalar));
+ __m128i tmpihi = _mm_cvtps_epi32(_mm_mul_ps(tmphi, scalar));
+
+ //pack + byteswap -> byteswap 16 bit words
+ __m128i tmpi = _mm_packs_epi32(tmpilo, tmpihi);
+ tmpi = _mm_or_si128(_mm_srli_epi16(tmpi, 8), _mm_slli_epi16(tmpi, 8));
+
+ //store to output
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(output+i), tmpi);
+ }
+
+ //convert remainder
+ for (; i < nsamps; i++){
+ output[i] = uhd::byteswap(fc32_to_item32(input[i]));
+ }
+}
+
+DECLARE_CONVERTER(convert_item32_1_to_fc32_1_nswap, PRIORITY_CUSTOM){
+ const item32_t *input = reinterpret_cast<const item32_t *>(inputs[0]);
+ fc32_t *output = reinterpret_cast<fc32_t *>(outputs[0]);
+
+ __m128 scalar = _mm_set_ps1(floats_per_short/(1 << 16));
+ __m128i zeroi = _mm_setzero_si128();
+
+ //convert blocks of samples with intrinsics
+ size_t i = 0; for (; i < (nsamps & ~0x3); i+=4){
+ //load from input
+ __m128i tmpi = _mm_loadu_si128(reinterpret_cast<const __m128i *>(input+i));
+
+ //unpack + swap 16-bit pairs
+ tmpi = _mm_shufflelo_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
+ tmpi = _mm_shufflehi_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
+ __m128i tmpilo = _mm_unpacklo_epi16(zeroi, tmpi); //value in upper 16 bits
+ __m128i tmpihi = _mm_unpackhi_epi16(zeroi, tmpi);
+
+ //convert and scale
+ __m128 tmplo = _mm_mul_ps(_mm_cvtepi32_ps(tmpilo), scalar);
+ __m128 tmphi = _mm_mul_ps(_mm_cvtepi32_ps(tmpihi), scalar);
+
+ //store to output
+ _mm_storeu_ps(reinterpret_cast<float *>(output+i+0), tmplo);
+ _mm_storeu_ps(reinterpret_cast<float *>(output+i+2), tmphi);
+ }
+
+ //convert remainder
+ for (; i < nsamps; i++){
+ output[i] = item32_to_fc32(input[i]);
+ }
+}
+
+DECLARE_CONVERTER(convert_item32_1_to_fc32_1_bswap, PRIORITY_CUSTOM){
+ const item32_t *input = reinterpret_cast<const item32_t *>(inputs[0]);
+ fc32_t *output = reinterpret_cast<fc32_t *>(outputs[0]);
+
+ __m128 scalar = _mm_set_ps1(floats_per_short/(1 << 16));
+ __m128i zeroi = _mm_setzero_si128();
+
+ //convert blocks of samples with intrinsics
+ size_t i = 0; for (; i < (nsamps & ~0x3); i+=4){
+ //load from input
+ __m128i tmpi = _mm_loadu_si128(reinterpret_cast<const __m128i *>(input+i));
+
+ //byteswap + unpack -> byteswap 16 bit words
+ tmpi = _mm_or_si128(_mm_srli_epi16(tmpi, 8), _mm_slli_epi16(tmpi, 8));
+ __m128i tmpilo = _mm_unpacklo_epi16(zeroi, tmpi); //value in upper 16 bits
+ __m128i tmpihi = _mm_unpackhi_epi16(zeroi, tmpi);
+
+ //convert and scale
+ __m128 tmplo = _mm_mul_ps(_mm_cvtepi32_ps(tmpilo), scalar);
+ __m128 tmphi = _mm_mul_ps(_mm_cvtepi32_ps(tmpihi), scalar);
+
+ //store to output
+ _mm_storeu_ps(reinterpret_cast<float *>(output+i+0), tmplo);
+ _mm_storeu_ps(reinterpret_cast<float *>(output+i+2), tmphi);
+ }
+
+ //convert remainder
+ for (; i < nsamps; i++){
+ output[i] = item32_to_fc32(uhd::byteswap(input[i]));
+ }
+}
diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py
new file mode 100644
index 000000000..47c4cd7d0
--- /dev/null
+++ b/host/lib/convert/gen_convert_general.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+#
+# Copyright 2011 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+TMPL_HEADER = """
+#import time
+/***********************************************************************
+ * This file was generated by $file on $time.strftime("%c")
+ **********************************************************************/
+
+\#include "convert_common.hpp"
+\#include <uhd/utils/byteswap.hpp>
+
+using namespace uhd::convert;
+"""
+
+TMPL_CONV_TO_FROM_ITEM32_1 = """
+DECLARE_CONVERTER(convert_$(cpu_type)_1_to_item32_1_$(swap), PRIORITY_GENERAL){
+ const $(cpu_type)_t *input = reinterpret_cast<const $(cpu_type)_t *>(inputs[0]);
+ item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
+
+ for (size_t i = 0; i < nsamps; i++){
+ output[i] = $(swap_fcn)($(cpu_type)_to_item32(input[i]));
+ }
+}
+
+DECLARE_CONVERTER(convert_item32_1_to_$(cpu_type)_1_$(swap), PRIORITY_GENERAL){
+ const item32_t *input = reinterpret_cast<const item32_t *>(inputs[0]);
+ $(cpu_type)_t *output = reinterpret_cast<$(cpu_type)_t *>(outputs[0]);
+
+ for (size_t i = 0; i < nsamps; i++){
+ output[i] = item32_to_$(cpu_type)($(swap_fcn)(input[i]));
+ }
+}
+"""
+TMPL_CONV_TO_FROM_ITEM32_X = """
+DECLARE_CONVERTER(convert_$(cpu_type)_$(width)_to_item32_1_$(swap), PRIORITY_GENERAL){
+ #for $w in range($width)
+ const $(cpu_type)_t *input$(w) = reinterpret_cast<const $(cpu_type)_t *>(inputs[$(w)]);
+ #end for
+ item32_t *output = reinterpret_cast<item32_t *>(outputs[0]);
+
+ for (size_t i = 0, j = 0; i < nsamps; i++){
+ #for $w in range($width)
+ output[j++] = $(swap_fcn)($(cpu_type)_to_item32(input$(w)[i]));
+ #end for
+ }
+}
+
+DECLARE_CONVERTER(convert_item32_1_to_$(cpu_type)_$(width)_$(swap), PRIORITY_GENERAL){
+ const item32_t *input = reinterpret_cast<const item32_t *>(inputs[0]);
+ #for $w in range($width)
+ $(cpu_type)_t *output$(w) = reinterpret_cast<$(cpu_type)_t *>(outputs[$(w)]);
+ #end for
+
+ for (size_t i = 0, j = 0; i < nsamps; i++){
+ #for $w in range($width)
+ output$(w)[i] = item32_to_$(cpu_type)($(swap_fcn)(input[j++]));
+ #end for
+ }
+}
+"""
+
+def parse_tmpl(_tmpl_text, **kwargs):
+ from Cheetah.Template import Template
+ return str(Template(_tmpl_text, kwargs))
+
+if __name__ == '__main__':
+ import sys, os
+ file = os.path.basename(__file__)
+ output = parse_tmpl(TMPL_HEADER, file=file)
+ for width in 1, 2, 3, 4:
+ for swap, swap_fcn in (('nswap', ''), ('bswap', 'uhd::byteswap')):
+ for cpu_type in 'fc32', 'sc16':
+ output += parse_tmpl(
+ TMPL_CONV_TO_FROM_ITEM32_1 if width == 1 else TMPL_CONV_TO_FROM_ITEM32_X,
+ width=width, swap=swap, swap_fcn=swap_fcn, cpu_type=cpu_type
+ )
+ open(sys.argv[1], 'w').write(output)
diff --git a/host/lib/convert/gen_convert_pred.py b/host/lib/convert/gen_convert_pred.py
new file mode 100644
index 000000000..1d573bf1a
--- /dev/null
+++ b/host/lib/convert/gen_convert_pred.py
@@ -0,0 +1,163 @@
+#!/usr/bin/env python
+#
+# Copyright 2011-2011 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+TMPL_TEXT = """
+#import time
+/***********************************************************************
+ * This file was generated by $file on $time.strftime("%c")
+ **********************************************************************/
+typedef size_t pred_type;
+
+\#include <boost/tokenizer.hpp>
+\#include <boost/lexical_cast.hpp>
+\#include <boost/detail/endian.hpp>
+\#include <boost/cstdint.hpp>
+\#include <stdexcept>
+\#include <string>
+\#include <vector>
+
+enum dir_type{
+ DIR_OTW_TO_CPU = 0,
+ DIR_CPU_TO_OTW = 1
+};
+
+struct pred_error : std::runtime_error{
+ pred_error(const std::string &what)
+ :std::runtime_error("convert::make_pred: " + what){
+ /* NOP */
+ }
+};
+
+pred_type make_pred(const std::string &markup, dir_type &dir){
+ pred_type pred = 0;
+
+ try{
+ boost::tokenizer<boost::char_separator<char> > tokenizer(markup, boost::char_separator<char>("_"));
+ std::vector<std::string> tokens(tokenizer.begin(), tokenizer.end());
+ //token 0 is <convert>
+ std::string inp_type = tokens.at(1);
+ std::string num_inps = tokens.at(2);
+ //token 3 is <to>
+ std::string out_type = tokens.at(4);
+ std::string num_outs = tokens.at(5);
+ std::string swap_type = tokens.at(6);
+
+ std::string cpu_type, otw_type;
+ if (inp_type.find("item") == std::string::npos){
+ cpu_type = inp_type;
+ otw_type = out_type;
+ dir = DIR_CPU_TO_OTW;
+ }
+ else{
+ cpu_type = out_type;
+ otw_type = inp_type;
+ dir = DIR_OTW_TO_CPU;
+ }
+
+ if (cpu_type == "fc32") pred |= $ph.fc32_p;
+ else if (cpu_type == "sc16") pred |= $ph.sc16_p;
+ else throw pred_error("unhandled io type " + cpu_type);
+
+ if (otw_type == "item32") pred |= $ph.item32_p;
+ else throw pred_error("unhandled otw type " + otw_type);
+
+ int num_inputs = boost::lexical_cast<int>(num_inps);
+ int num_outputs = boost::lexical_cast<int>(num_outs);
+
+ switch(num_inputs*num_outputs){ //FIXME treated as one value
+ case 1: pred |= $ph.chan1_p; break;
+ case 2: pred |= $ph.chan2_p; break;
+ case 3: pred |= $ph.chan3_p; break;
+ case 4: pred |= $ph.chan4_p; break;
+ default: throw pred_error("unhandled number of channels");
+ }
+
+ if (swap_type == "bswap") pred |= $ph.bswap_p;
+ else if (swap_type == "nswap") pred |= $ph.nswap_p;
+ else throw pred_error("unhandled swap type");
+
+ }
+ catch(...){
+ throw pred_error("could not parse markup: " + markup);
+ }
+
+ return pred;
+}
+
+UHD_INLINE pred_type make_pred(
+ const io_type_t &io_type,
+ const otw_type_t &otw_type,
+ size_t num_inputs,
+ size_t num_outputs
+){
+ pred_type pred = 0;
+
+ switch(otw_type.byteorder){
+ \#ifdef BOOST_BIG_ENDIAN
+ case otw_type_t::BO_BIG_ENDIAN: pred |= $ph.nswap_p; break;
+ case otw_type_t::BO_LITTLE_ENDIAN: pred |= $ph.bswap_p; break;
+ \#else
+ case otw_type_t::BO_BIG_ENDIAN: pred |= $ph.bswap_p; break;
+ case otw_type_t::BO_LITTLE_ENDIAN: pred |= $ph.nswap_p; break;
+ \#endif
+ case otw_type_t::BO_NATIVE: pred |= $ph.nswap_p; break;
+ default: throw pred_error("unhandled otw byteorder type");
+ }
+
+ switch(otw_type.get_sample_size()){
+ case sizeof(boost::uint32_t): pred |= $ph.item32_p; break;
+ default: throw pred_error("unhandled otw sample size");
+ }
+
+ switch(io_type.tid){
+ case io_type_t::COMPLEX_FLOAT32: pred |= $ph.fc32_p; break;
+ case io_type_t::COMPLEX_INT16: pred |= $ph.sc16_p; break;
+ default: throw pred_error("unhandled io type id");
+ }
+
+ switch(num_inputs*num_outputs){ //FIXME treated as one value
+ case 1: pred |= $ph.chan1_p; break;
+ case 2: pred |= $ph.chan2_p; break;
+ case 3: pred |= $ph.chan3_p; break;
+ case 4: pred |= $ph.chan4_p; break;
+ default: throw pred_error("unhandled number of channels");
+ }
+
+ return pred;
+}
+"""
+
+def parse_tmpl(_tmpl_text, **kwargs):
+ from Cheetah.Template import Template
+ return str(Template(_tmpl_text, kwargs))
+
+class ph:
+ bswap_p = 0b00001
+ nswap_p = 0b00000
+ item32_p = 0b00000
+ sc16_p = 0b00010
+ fc32_p = 0b00000
+ chan1_p = 0b00000
+ chan2_p = 0b00100
+ chan3_p = 0b01000
+ chan4_p = 0b01100
+
+if __name__ == '__main__':
+ import sys, os
+ file = os.path.basename(__file__)
+ open(sys.argv[1], 'w').write(parse_tmpl(TMPL_TEXT, file=file, ph=ph))
diff --git a/host/lib/gain_group.cpp b/host/lib/gain_group.cpp
deleted file mode 100644
index 1be09dee2..000000000
--- a/host/lib/gain_group.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#include <uhd/utils/gain_group.hpp>
-#include <uhd/types/dict.hpp>
-#include <uhd/utils/algorithm.hpp>
-#include <uhd/utils/assert.hpp>
-#include <boost/foreach.hpp>
-#include <boost/bind.hpp>
-#include <algorithm>
-#include <vector>
-#include <iostream>
-
-using namespace uhd;
-
-static const bool verbose = false;
-
-static bool compare_by_step_size(
- const size_t &rhs, const size_t &lhs, std::vector<gain_fcns_t> &fcns
-){
- return fcns.at(rhs).get_range().step > fcns.at(lhs).get_range().step;
-}
-
-/***********************************************************************
- * gain group implementation
- **********************************************************************/
-class gain_group_impl : public gain_group{
-public:
- gain_group_impl(void){
- /*NOP*/
- }
-
- gain_range_t get_range(void){
- float overall_min = 0, overall_max = 0, overall_step = 0;
- BOOST_FOREACH(const gain_fcns_t &fcns, get_all_fcns()){
- const gain_range_t range = fcns.get_range();
- overall_min += range.min;
- overall_max += range.max;
- //the overall step is the min (zero is invalid, first run)
- if (overall_step == 0) overall_step = range.step;
- overall_step = std::min(overall_step, range.step);
- }
- return gain_range_t(overall_min, overall_max, overall_step);
- }
-
- float get_value(void){
- float overall_gain = 0;
- BOOST_FOREACH(const gain_fcns_t &fcns, get_all_fcns()){
- overall_gain += fcns.get_value();
- }
- return overall_gain;
- }
-
- void set_value(float gain){
- std::vector<gain_fcns_t> all_fcns = get_all_fcns();
- if (all_fcns.size() == 0) return; //nothing to set!
-
- //get the max step size among the gains
- float max_step = 0;
- BOOST_FOREACH(const gain_fcns_t &fcns, all_fcns){
- max_step = std::max(max_step, fcns.get_range().step);
- }
-
- //create gain bucket to distribute power
- std::vector<float> gain_bucket;
-
- //distribute power according to priority (round to max step)
- float gain_left_to_distribute = gain;
- BOOST_FOREACH(const gain_fcns_t &fcns, all_fcns){
- const gain_range_t range = fcns.get_range();
- gain_bucket.push_back(
- max_step*int(std::clip(gain_left_to_distribute, range.min, range.max)/max_step)
- );
- gain_left_to_distribute -= gain_bucket.back();
- }
-
- //get a list of indexes sorted by step size large to small
- std::vector<size_t> indexes_step_size_dec;
- for (size_t i = 0; i < all_fcns.size(); i++){
- indexes_step_size_dec.push_back(i);
- }
- std::sort(
- indexes_step_size_dec.begin(), indexes_step_size_dec.end(),
- boost::bind(&compare_by_step_size, _1, _2, all_fcns)
- );
- UHD_ASSERT_THROW(
- all_fcns.at(indexes_step_size_dec.front()).get_range().step >=
- all_fcns.at(indexes_step_size_dec.back()).get_range().step
- );
-
- //distribute the remainder (less than max step)
- //fill in the largest step sizes first that are less than the remainder
- BOOST_FOREACH(size_t i, indexes_step_size_dec){
- const gain_range_t range = all_fcns.at(i).get_range();
- float additional_gain = range.step*int(
- std::clip(gain_bucket.at(i) + gain_left_to_distribute, range.min, range.max
- )/range.step) - gain_bucket.at(i);
- gain_bucket.at(i) += additional_gain;
- gain_left_to_distribute -= additional_gain;
- }
- if (verbose) std::cout << "gain_left_to_distribute " << gain_left_to_distribute << std::endl;
-
- //now write the bucket out to the individual gain values
- for (size_t i = 0; i < gain_bucket.size(); i++){
- if (verbose) std::cout << gain_bucket.at(i) << std::endl;
- all_fcns.at(i).set_value(gain_bucket.at(i));
- }
- }
-
- void register_fcns(
- const gain_fcns_t &gain_fcns, size_t priority
- ){
- _registry[priority].push_back(gain_fcns);
- }
-
-private:
- //! get the gain function sets in order (highest priority first)
- std::vector<gain_fcns_t> get_all_fcns(void){
- std::vector<gain_fcns_t> all_fcns;
- BOOST_FOREACH(ssize_t key, std::sorted(_registry.keys())){
- const std::vector<gain_fcns_t> &fcns = _registry[key];
- all_fcns.insert(all_fcns.begin(), fcns.begin(), fcns.end());
- }
- return all_fcns;
- }
-
- uhd::dict<size_t, std::vector<gain_fcns_t> > _registry;
-};
-
-/***********************************************************************
- * gain group factory function
- **********************************************************************/
-gain_group::sptr gain_group::make(void){
- return sptr(new gain_group_impl());
-}
diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt
index 0d6226e4c..8765c6703 100644
--- a/host/lib/transport/CMakeLists.txt
+++ b/host/lib/transport/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@
# Setup libusb
########################################################################
MESSAGE(STATUS "")
-FIND_PACKAGE(USB1 REQUIRED)
+FIND_PACKAGE(USB1)
LIBUHD_REGISTER_COMPONENT("USB" ENABLE_USB ON "ENABLE_LIBUHD;LIBUSB_FOUND" OFF)
@@ -37,9 +37,6 @@ IF(ENABLE_USB)
${CMAKE_CURRENT_SOURCE_DIR}/libusb1_base.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libusb1_base.hpp
)
- IF(MSVC) #include our custom stdint for libusb
- INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/msvc)
- ENDIF(MSVC)
ELSE(ENABLE_USB)
LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/usb_dummy_impl.cpp
@@ -47,25 +44,6 @@ ELSE(ENABLE_USB)
ENDIF(ENABLE_USB)
########################################################################
-# Check for SIMD headers
-########################################################################
-MESSAGE(STATUS "")
-
-INCLUDE(CheckIncludeFileCXX)
-CHECK_INCLUDE_FILE_CXX(emmintrin.h HAVE_EMMINTRIN_H)
-
-IF(HAVE_EMMINTRIN_H)
- ADD_DEFINITIONS(-DHAVE_EMMINTRIN_H)
-ENDIF(HAVE_EMMINTRIN_H)
-
-INCLUDE(CheckIncludeFileCXX)
-CHECK_INCLUDE_FILE_CXX(arm_neon.h HAVE_ARM_NEON_H)
-
-IF(HAVE_ARM_NEON_H)
- ADD_DEFINITIONS(-DHAVE_ARM_NEON_H)
-ENDIF(HAVE_ARM_NEON_H)
-
-########################################################################
# Setup defines for interface address discovery
########################################################################
MESSAGE(STATUS "")
@@ -93,22 +71,8 @@ LIBUHD_PYTHON_GEN_SOURCE(
${CMAKE_CURRENT_BINARY_DIR}/vrt_if_packet.cpp
)
-LIBUHD_PYTHON_GEN_SOURCE(
- ${CMAKE_CURRENT_SOURCE_DIR}/gen_convert_types.py
- ${CMAKE_CURRENT_BINARY_DIR}/convert_types.cpp
-)
-
-# append this directory to the include path so the generated convert types
-# can include the implementation convert types file in the source directory
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
-
-# make the generated convert types depend on the implementation header
-SET_SOURCE_FILES_PROPERTIES(
- ${CMAKE_CURRENT_BINARY_DIR}/convert_types.cpp PROPERTIES
- OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/convert_types_impl.hpp
-)
-
LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/buffer_pool.cpp
${CMAKE_CURRENT_SOURCE_DIR}/if_addrs.cpp
${CMAKE_CURRENT_SOURCE_DIR}/udp_simple.cpp
${CMAKE_CURRENT_SOURCE_DIR}/udp_zero_copy_asio.cpp
diff --git a/host/lib/transport/buffer_pool.cpp b/host/lib/transport/buffer_pool.cpp
new file mode 100644
index 000000000..971bbb75a
--- /dev/null
+++ b/host/lib/transport/buffer_pool.cpp
@@ -0,0 +1,80 @@
+//
+// Copyright 2011-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/transport/buffer_pool.hpp>
+#include <boost/shared_array.hpp>
+#include <vector>
+
+using namespace uhd::transport;
+
+//! pad the byte count to a multiple of alignment
+static size_t pad_to_boundary(const size_t bytes, const size_t alignment){
+ return bytes + (alignment - bytes)%alignment;
+}
+
+/***********************************************************************
+ * Buffer pool implementation
+ **********************************************************************/
+class buffer_pool_impl : public buffer_pool{
+public:
+ buffer_pool_impl(
+ const std::vector<ptr_type> &ptrs,
+ boost::shared_array<char> mem
+ ): _ptrs(ptrs), _mem(mem){
+ /* NOP */
+ }
+
+ ptr_type at(const size_t index) const{
+ return _ptrs.at(index);
+ }
+
+ size_t size(void) const{
+ return _ptrs.size();
+ }
+
+private:
+ std::vector<ptr_type> _ptrs;
+ boost::shared_array<char> _mem;
+};
+
+/***********************************************************************
+ * Buffer pool factor function
+ **********************************************************************/
+buffer_pool::sptr buffer_pool::make(
+ const size_t num_buffs,
+ const size_t buff_size,
+ const size_t alignment
+){
+ //1) pad the buffer size to be a multiple of alignment
+ //2) pad the overall memory size for room after alignment
+ //3) allocate the memory in one block of sufficient size
+ const size_t padded_buff_size = pad_to_boundary(buff_size, alignment);
+ boost::shared_array<char> mem(new char[padded_buff_size*num_buffs + alignment-1]);
+
+ //Fill a vector with boundary-aligned points in the memory
+ const size_t mem_start = pad_to_boundary(size_t(mem.get()), alignment);
+ std::vector<ptr_type> ptrs(num_buffs);
+ for (size_t i = 0; i < num_buffs; i++){
+ ptrs[i] = ptr_type(mem_start + padded_buff_size*i);
+ }
+
+ //Create a new buffer pool implementation with:
+ // - the pre-computed pointers, and
+ // - the reference to allocated memory.
+ return sptr(new buffer_pool_impl(ptrs, mem));
+}
+
diff --git a/host/lib/transport/convert_types_impl.hpp b/host/lib/transport/convert_types_impl.hpp
deleted file mode 100644
index 48ff99725..000000000
--- a/host/lib/transport/convert_types_impl.hpp
+++ /dev/null
@@ -1,345 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#ifndef INCLUDED_LIBUHD_TRANSPORT_CONVERT_TYPES_IMPL_HPP
-#define INCLUDED_LIBUHD_TRANSPORT_CONVERT_TYPES_IMPL_HPP
-
-#include <uhd/config.hpp>
-#include <uhd/utils/byteswap.hpp>
-#include <boost/cstdint.hpp>
-#include <cstring>
-#include <complex>
-
-#ifdef HAVE_EMMINTRIN_H
- #define USE_EMMINTRIN_H //use sse2 intrinsics
-#endif
-
-#if defined(USE_EMMINTRIN_H)
- #include <emmintrin.h>
-#endif
-
-#ifdef HAVE_ARM_NEON_H
- #define USE_ARM_NEON_H
-#endif
-
-#if defined(USE_ARM_NEON_H)
- #include <arm_neon.h>
-#endif
-
-/***********************************************************************
- * Typedefs
- **********************************************************************/
-typedef std::complex<float> fc32_t;
-typedef std::complex<boost::int16_t> sc16_t;
-typedef boost::uint32_t item32_t;
-
-/***********************************************************************
- * Convert complex short buffer to items32
- **********************************************************************/
-static UHD_INLINE item32_t sc16_to_item32(sc16_t num){
- boost::uint16_t real = num.real();
- boost::uint16_t imag = num.imag();
- return (item32_t(real) << 16) | (item32_t(imag) << 0);
-}
-
-static UHD_INLINE void sc16_to_item32_nswap(
- const sc16_t *input, item32_t *output, size_t nsamps
-){
- for (size_t i = 0; i < nsamps; i++){
- output[i] = sc16_to_item32(input[i]);
- }
-}
-
-static UHD_INLINE void sc16_to_item32_bswap(
- const sc16_t *input, item32_t *output, size_t nsamps
-){
- for (size_t i = 0; i < nsamps; i++){
- output[i] = uhd::byteswap(sc16_to_item32(input[i]));
- }
-}
-
-/***********************************************************************
- * Convert items32 buffer to complex short
- **********************************************************************/
-static UHD_INLINE sc16_t item32_to_sc16(item32_t item){
- return sc16_t(
- boost::int16_t(item >> 16),
- boost::int16_t(item >> 0)
- );
-}
-
-static UHD_INLINE void item32_to_sc16_nswap(
- const item32_t *input, sc16_t *output, size_t nsamps
-){
- for (size_t i = 0; i < nsamps; i++){
- output[i] = item32_to_sc16(input[i]);
- }
-}
-
-static UHD_INLINE void item32_to_sc16_bswap(
- const item32_t *input, sc16_t *output, size_t nsamps
-){
- for (size_t i = 0; i < nsamps; i++){
- output[i] = item32_to_sc16(uhd::byteswap(input[i]));
- }
-}
-
-/***********************************************************************
- * Convert complex float buffer to items32 (no swap)
- **********************************************************************/
-static const float shorts_per_float = float(32767);
-
-static UHD_INLINE item32_t fc32_to_item32(fc32_t num){
- boost::uint16_t real = boost::int16_t(num.real()*shorts_per_float);
- boost::uint16_t imag = boost::int16_t(num.imag()*shorts_per_float);
- return (item32_t(real) << 16) | (item32_t(imag) << 0);
-}
-
-////////////////////////////////////
-// none-swap
-////////////////////////////////////
-#if defined(USE_EMMINTRIN_H)
-static UHD_INLINE void fc32_to_item32_nswap(
- const fc32_t *input, item32_t *output, size_t nsamps
-){
- __m128 scalar = _mm_set_ps1(shorts_per_float);
-
- //convert blocks of samples with intrinsics
- size_t i = 0; for (; i < (nsamps & ~0x3); i+=4){
- //load from input
- __m128 tmplo = _mm_loadu_ps(reinterpret_cast<const float *>(input+i+0));
- __m128 tmphi = _mm_loadu_ps(reinterpret_cast<const float *>(input+i+2));
-
- //convert and scale
- __m128i tmpilo = _mm_cvtps_epi32(_mm_mul_ps(tmplo, scalar));
- __m128i tmpihi = _mm_cvtps_epi32(_mm_mul_ps(tmphi, scalar));
-
- //pack + swap 16-bit pairs
- __m128i tmpi = _mm_packs_epi32(tmpilo, tmpihi);
- tmpi = _mm_shufflelo_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
- tmpi = _mm_shufflehi_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
-
- //store to output
- _mm_storeu_si128(reinterpret_cast<__m128i *>(output+i), tmpi);
- }
-
- //convert remainder
- for (; i < nsamps; i++){
- output[i] = fc32_to_item32(input[i]);
- }
-}
-
-#elif defined(USE_ARM_NEON_H)
-static UHD_INLINE void fc32_to_item32_nswap(
- const fc32_t *input, item32_t *output, size_t nsamps)
-{
- size_t i;
-
- float32x4_t Q0 = vdupq_n_f32(shorts_per_float);
- for (i=0; i < (nsamps & ~0x03); i+=2) {
- float32x4_t Q1 = vld1q_f32(reinterpret_cast<const float *>(&input[i]));
- float32x4_t Q2 = vmulq_f32(Q1, Q0);
- int32x4_t Q3 = vcvtq_s32_f32(Q2);
- int16x4_t D8 = vmovn_s32(Q3);
- int16x4_t D9 = vrev32_s16(D8);
- vst1_s16((reinterpret_cast<int16_t *>(&output[i])), D9);
- }
-
- for (; i < nsamps; i++)
- output[i] = fc32_to_item32(input[i]);
-}
-
-#else
-static UHD_INLINE void fc32_to_item32_nswap(
- const fc32_t *input, item32_t *output, size_t nsamps
-){
- for (size_t i = 0; i < nsamps; i++){
- output[i] = fc32_to_item32(input[i]);
- }
-}
-
-#endif
-
-////////////////////////////////////
-// byte-swap
-////////////////////////////////////
-#if defined(USE_EMMINTRIN_H)
-static UHD_INLINE void fc32_to_item32_bswap(
- const fc32_t *input, item32_t *output, size_t nsamps
-){
- __m128 scalar = _mm_set_ps1(shorts_per_float);
-
- //convert blocks of samples with intrinsics
- size_t i = 0; for (; i < (nsamps & ~0x3); i+=4){
- //load from input
- __m128 tmplo = _mm_loadu_ps(reinterpret_cast<const float *>(input+i+0));
- __m128 tmphi = _mm_loadu_ps(reinterpret_cast<const float *>(input+i+2));
-
- //convert and scale
- __m128i tmpilo = _mm_cvtps_epi32(_mm_mul_ps(tmplo, scalar));
- __m128i tmpihi = _mm_cvtps_epi32(_mm_mul_ps(tmphi, scalar));
-
- //pack + byteswap -> byteswap 16 bit words
- __m128i tmpi = _mm_packs_epi32(tmpilo, tmpihi);
- tmpi = _mm_or_si128(_mm_srli_epi16(tmpi, 8), _mm_slli_epi16(tmpi, 8));
-
- //store to output
- _mm_storeu_si128(reinterpret_cast<__m128i *>(output+i), tmpi);
- }
-
- //convert remainder
- for (; i < nsamps; i++){
- output[i] = uhd::byteswap(fc32_to_item32(input[i]));
- }
-}
-
-#else
-static UHD_INLINE void fc32_to_item32_bswap(
- const fc32_t *input, item32_t *output, size_t nsamps
-){
- for (size_t i = 0; i < nsamps; i++){
- output[i] = uhd::byteswap(fc32_to_item32(input[i]));
- }
-}
-
-#endif
-
-/***********************************************************************
- * Convert items32 buffer to complex float
- **********************************************************************/
-static const float floats_per_short = float(1.0/shorts_per_float);
-
-static UHD_INLINE fc32_t item32_to_fc32(item32_t item){
- return fc32_t(
- float(boost::int16_t(item >> 16)*floats_per_short),
- float(boost::int16_t(item >> 0)*floats_per_short)
- );
-}
-
-////////////////////////////////////
-// none-swap
-////////////////////////////////////
-#if defined(USE_EMMINTRIN_H)
-static UHD_INLINE void item32_to_fc32_nswap(
- const item32_t *input, fc32_t *output, size_t nsamps
-){
- __m128 scalar = _mm_set_ps1(floats_per_short/(1 << 16));
- __m128i zeroi = _mm_setzero_si128();
-
- //convert blocks of samples with intrinsics
- size_t i = 0; for (; i < (nsamps & ~0x3); i+=4){
- //load from input
- __m128i tmpi = _mm_loadu_si128(reinterpret_cast<const __m128i *>(input+i));
-
- //unpack + swap 16-bit pairs
- tmpi = _mm_shufflelo_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
- tmpi = _mm_shufflehi_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
- __m128i tmpilo = _mm_unpacklo_epi16(zeroi, tmpi); //value in upper 16 bits
- __m128i tmpihi = _mm_unpackhi_epi16(zeroi, tmpi);
-
- //convert and scale
- __m128 tmplo = _mm_mul_ps(_mm_cvtepi32_ps(tmpilo), scalar);
- __m128 tmphi = _mm_mul_ps(_mm_cvtepi32_ps(tmpihi), scalar);
-
- //store to output
- _mm_storeu_ps(reinterpret_cast<float *>(output+i+0), tmplo);
- _mm_storeu_ps(reinterpret_cast<float *>(output+i+2), tmphi);
- }
-
- //convert remainder
- for (; i < nsamps; i++){
- output[i] = item32_to_fc32(input[i]);
- }
-}
-
-#elif defined(USE_ARM_NEON_H)
-static UHD_INLINE void item32_to_fc32_nswap(
- const item32_t *input, fc32_t *output, size_t nsamps)
-{
- size_t i;
-
- float32x4_t Q1 = vdupq_n_f32(floats_per_short);
- for (i=0; i < (nsamps & ~0x03); i+=2) {
- int16x4_t D0 = vld1_s16(reinterpret_cast<const int16_t *>(&input[i]));
- int16x4_t D1 = vrev32_s16(D0);
- int32x4_t Q2 = vmovl_s16(D1);
- float32x4_t Q3 = vcvtq_f32_s32(Q2);
- float32x4_t Q4 = vmulq_f32(Q3, Q1);
- vst1q_f32((reinterpret_cast<float *>(&output[i])), Q4);
- }
-
- for (; i < nsamps; i++)
- output[i] = item32_to_fc32(input[i]);
-}
-
-#else
-static UHD_INLINE void item32_to_fc32_nswap(
- const item32_t *input, fc32_t *output, size_t nsamps
-){
- for (size_t i = 0; i < nsamps; i++){
- output[i] = item32_to_fc32(input[i]);
- }
-}
-#endif
-
-////////////////////////////////////
-// byte-swap
-////////////////////////////////////
-#if defined(USE_EMMINTRIN_H)
-static UHD_INLINE void item32_to_fc32_bswap(
- const item32_t *input, fc32_t *output, size_t nsamps
-){
- __m128 scalar = _mm_set_ps1(floats_per_short/(1 << 16));
- __m128i zeroi = _mm_setzero_si128();
-
- //convert blocks of samples with intrinsics
- size_t i = 0; for (; i < (nsamps & ~0x3); i+=4){
- //load from input
- __m128i tmpi = _mm_loadu_si128(reinterpret_cast<const __m128i *>(input+i));
-
- //byteswap + unpack -> byteswap 16 bit words
- tmpi = _mm_or_si128(_mm_srli_epi16(tmpi, 8), _mm_slli_epi16(tmpi, 8));
- __m128i tmpilo = _mm_unpacklo_epi16(zeroi, tmpi); //value in upper 16 bits
- __m128i tmpihi = _mm_unpackhi_epi16(zeroi, tmpi);
-
- //convert and scale
- __m128 tmplo = _mm_mul_ps(_mm_cvtepi32_ps(tmpilo), scalar);
- __m128 tmphi = _mm_mul_ps(_mm_cvtepi32_ps(tmpihi), scalar);
-
- //store to output
- _mm_storeu_ps(reinterpret_cast<float *>(output+i+0), tmplo);
- _mm_storeu_ps(reinterpret_cast<float *>(output+i+2), tmphi);
- }
-
- //convert remainder
- for (; i < nsamps; i++){
- output[i] = item32_to_fc32(uhd::byteswap(input[i]));
- }
-}
-
-#else
-static UHD_INLINE void item32_to_fc32_bswap(
- const item32_t *input, fc32_t *output, size_t nsamps
-){
- for (size_t i = 0; i < nsamps; i++){
- output[i] = item32_to_fc32(uhd::byteswap(input[i]));
- }
-}
-
-#endif
-
-#endif /* INCLUDED_LIBUHD_TRANSPORT_CONVERT_TYPES_IMPL_HPP */
diff --git a/host/lib/transport/gen_convert_types.py b/host/lib/transport/gen_convert_types.py
deleted file mode 100755
index f9509c81d..000000000
--- a/host/lib/transport/gen_convert_types.py
+++ /dev/null
@@ -1,211 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2010 Ettus Research LLC
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-
-TMPL_TEXT = """
-#import time
-/***********************************************************************
- * This file was generated by $file on $time.strftime("%c")
- **********************************************************************/
-
-\#include <uhd/config.hpp>
-\#include <uhd/transport/convert_types.hpp>
-\#include <boost/cstdint.hpp>
-\#include <boost/detail/endian.hpp>
-\#include <stdexcept>
-\#include "convert_types_impl.hpp"
-
-using namespace uhd;
-
-/***********************************************************************
- * Generate predicate for jump table
- **********************************************************************/
-UHD_INLINE boost::uint8_t get_pred(
- const io_type_t &io_type,
- const otw_type_t &otw_type,
- size_t num_chans
-){
- boost::uint8_t pred = 0;
-
- switch(otw_type.byteorder){
- \#ifdef BOOST_BIG_ENDIAN
- case otw_type_t::BO_BIG_ENDIAN: pred |= $ph.nswap_p; break;
- case otw_type_t::BO_LITTLE_ENDIAN: pred |= $ph.bswap_p; break;
- \#else
- case otw_type_t::BO_BIG_ENDIAN: pred |= $ph.bswap_p; break;
- case otw_type_t::BO_LITTLE_ENDIAN: pred |= $ph.nswap_p; break;
- \#endif
- case otw_type_t::BO_NATIVE: pred |= $ph.nswap_p; break;
- default: throw std::runtime_error("unhandled otw byteorder type");
- }
-
- switch(otw_type.get_sample_size()){
- case sizeof(boost::uint32_t): pred |= $ph.item32_p; break;
- default: throw std::runtime_error("unhandled otw sample size");
- }
-
- switch(io_type.tid){
- case io_type_t::COMPLEX_FLOAT32: pred |= $ph.fc32_p; break;
- case io_type_t::COMPLEX_INT16: pred |= $ph.sc16_p; break;
- default: throw std::runtime_error("unhandled io type id");
- }
-
- switch(num_chans){
- case 1: pred |= $ph.chan1_p; break;
- case 2: pred |= $ph.chan2_p; break;
- case 3: pred |= $ph.chan3_p; break;
- case 4: pred |= $ph.chan4_p; break;
- default: throw std::runtime_error("unhandled number of channels");
- }
-
- return pred;
-}
-
-/***********************************************************************
- * Convert host type to device type
- **********************************************************************/
-void transport::convert_io_type_to_otw_type(
- const std::vector<const void *> &io_buffs,
- const io_type_t &io_type,
- void *otw_buff,
- const otw_type_t &otw_type,
- size_t nsamps_per_io_buff
-){
- switch(get_pred(io_type, otw_type, io_buffs.size())){
- #for $pred in range(2**$ph.nbits)
- case $pred:
- #set $out_type = $ph.get_dev_type($pred)
- #set $in_type = $ph.get_host_type($pred)
- #set $num_chans = $ph.get_num_chans($pred)
- #set $converter = '_'.join([$in_type, 'to', $out_type])
- #if $num_chans == 1
- $(converter)_$ph.get_swap_type($pred)(
- reinterpret_cast<const $(in_type)_t *>(io_buffs.front()),
- reinterpret_cast<$(out_type)_t *>(otw_buff),
- nsamps_per_io_buff
- );
- #else
- for (size_t i = 0, j = 0; i < nsamps_per_io_buff; i++){
- #for $j in range($num_chans)
- reinterpret_cast<$(out_type)_t *>(otw_buff)[j++] =
- #if $ph.get_swap_type($pred) == 'bswap'
- uhd::byteswap($(converter)(reinterpret_cast<const $(in_type)_t *>(io_buffs[$j])[i]));
- #else
- $(converter)(reinterpret_cast<const $(in_type)_t *>(io_buffs[$j])[i]);
- #end if
- #end for
- }
- #end if
- break;
- #end for
- }
-}
-
-/***********************************************************************
- * Convert device type to host type
- **********************************************************************/
-void transport::convert_otw_type_to_io_type(
- const void *otw_buff,
- const otw_type_t &otw_type,
- std::vector<void *> &io_buffs,
- const io_type_t &io_type,
- size_t nsamps_per_io_buff
-){
- switch(get_pred(io_type, otw_type, io_buffs.size())){
- #for $pred in range(2**$ph.nbits)
- case $pred:
- #set $out_type = $ph.get_host_type($pred)
- #set $in_type = $ph.get_dev_type($pred)
- #set $num_chans = $ph.get_num_chans($pred)
- #set $converter = '_'.join([$in_type, 'to', $out_type])
- #if $num_chans == 1
- $(converter)_$ph.get_swap_type($pred)(
- reinterpret_cast<const $(in_type)_t *>(otw_buff),
- reinterpret_cast<$(out_type)_t *>(io_buffs.front()),
- nsamps_per_io_buff
- );
- #else
- for (size_t i = 0, j = 0; i < nsamps_per_io_buff; i++){
- #for $j in range($num_chans)
- reinterpret_cast<$(out_type)_t *>(io_buffs[$j])[i] =
- #if $ph.get_swap_type($pred) == 'bswap'
- $(converter)(uhd::byteswap(reinterpret_cast<const $(in_type)_t *>(otw_buff)[j++]));
- #else
- $(converter)(reinterpret_cast<const $(in_type)_t *>(otw_buff)[j++]);
- #end if
- #end for
- }
- #end if
- break;
- #end for
- }
-}
-
-"""
-
-def parse_tmpl(_tmpl_text, **kwargs):
- from Cheetah.Template import Template
- return str(Template(_tmpl_text, kwargs))
-
-class ph:
- bswap_p = 0b00001
- nswap_p = 0b00000
- item32_p = 0b00000
- sc16_p = 0b00010
- fc32_p = 0b00000
- chan1_p = 0b00000
- chan2_p = 0b00100
- chan3_p = 0b01000
- chan4_p = 0b01100
-
- nbits = 4 #see above
-
- @staticmethod
- def has(pred, mask, flag): return (pred & mask) == flag
-
- @staticmethod
- def get_swap_type(pred):
- mask = 0b1
- if ph.has(pred, mask, ph.bswap_p): return 'bswap'
- if ph.has(pred, mask, ph.nswap_p): return 'nswap'
- raise NotImplementedError
-
- @staticmethod
- def get_dev_type(pred):
- mask = 0b0
- if ph.has(pred, mask, ph.item32_p): return 'item32'
- raise NotImplementedError
-
- @staticmethod
- def get_host_type(pred):
- mask = 0b10
- if ph.has(pred, mask, ph.sc16_p): return 'sc16'
- if ph.has(pred, mask, ph.fc32_p): return 'fc32'
- raise NotImplementedError
-
- @staticmethod
- def get_num_chans(pred):
- mask = 0b1100
- if ph.has(pred, mask, ph.chan1_p): return 1
- if ph.has(pred, mask, ph.chan2_p): return 2
- if ph.has(pred, mask, ph.chan3_p): return 3
- if ph.has(pred, mask, ph.chan4_p): return 4
- raise NotImplementedError
-
-if __name__ == '__main__':
- import sys
- open(sys.argv[1], 'w').write(parse_tmpl(TMPL_TEXT, file=__file__, ph=ph))
diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp
index f589d7c77..adc590284 100644
--- a/host/lib/transport/libusb1_zero_copy.cpp
+++ b/host/lib/transport/libusb1_zero_copy.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -18,9 +18,9 @@
#include "libusb1_base.hpp"
#include <uhd/transport/usb_zero_copy.hpp>
#include <uhd/transport/bounded_buffer.hpp>
+#include <uhd/transport/buffer_pool.hpp>
#include <uhd/utils/thread_priority.hpp>
#include <uhd/utils/assert.hpp>
-#include <boost/shared_array.hpp>
#include <boost/foreach.hpp>
#include <boost/thread.hpp>
#include <boost/enable_shared_from_this.hpp>
@@ -105,8 +105,8 @@ private:
//! a list of all transfer structs we allocated
std::vector<libusb_transfer *> _all_luts;
- //! a block of memory for the transfer buffers
- boost::shared_array<char> _buffer;
+ //! memory allocated for the transfer buffers
+ buffer_pool::sptr _buffer_pool;
// Calls for processing asynchronous I/O
libusb_transfer *allocate_transfer(void *mem, size_t len);
@@ -134,7 +134,6 @@ static void callback(libusb_transfer *lut){
* \param pointer to libusb_transfer
*/
void usb_endpoint::callback_handle_transfer(libusb_transfer *lut){
- boost::this_thread::disable_interruption di; //disable because the wait can throw
_completed_list->push_with_wait(lut);
}
@@ -157,9 +156,9 @@ usb_endpoint::usb_endpoint(
_input(input)
{
_completed_list = lut_buff_type::make(num_transfers);
- _buffer = boost::shared_array<char>(new char[num_transfers*transfer_size]);
+ _buffer_pool = buffer_pool::make(num_transfers, transfer_size);
for (size_t i = 0; i < num_transfers; i++){
- _all_luts.push_back(allocate_transfer(_buffer.get() + i*transfer_size, transfer_size));
+ _all_luts.push_back(allocate_transfer(_buffer_pool->at(i), transfer_size));
//input luts are immediately submitted to be filled
//output luts go into the completed list as free buffers
@@ -272,7 +271,6 @@ void usb_endpoint::print_transfer_status(libusb_transfer *lut){
}
libusb_transfer *usb_endpoint::get_lut_with_wait(double timeout){
- boost::this_thread::disable_interruption di; //disable because the wait can throw
libusb_transfer *lut;
if (_completed_list->pop_with_timed_wait(lut, timeout)) return lut;
return NULL;
@@ -293,6 +291,7 @@ public:
~libusb_zero_copy_impl(void){
_threads_running = false;
+ _thread_group.interrupt_all();
_thread_group.join_all();
}
@@ -333,12 +332,14 @@ private:
set_thread_priority_safe();
libusb::session::sptr session = libusb::session::get_global_session();
_threads_running = true;
- while(_threads_running){
- timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 100000; //100ms
- libusb_handle_events_timeout(session->get_context(), &tv);
- }
+ try{
+ while(_threads_running){
+ timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000; //100ms
+ libusb_handle_events_timeout(session->get_context(), &tv);
+ }
+ } catch(const boost::thread_interrupted &){}
}
};
diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp
index c758fa894..5c049cfad 100644
--- a/host/lib/transport/udp_zero_copy_asio.cpp
+++ b/host/lib/transport/udp_zero_copy_asio.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -18,10 +18,10 @@
#include <uhd/transport/udp_zero_copy.hpp>
#include <uhd/transport/udp_simple.hpp> //mtu
#include <uhd/transport/bounded_buffer.hpp>
+#include <uhd/transport/buffer_pool.hpp>
#include <uhd/utils/thread_priority.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/utils/warning.hpp>
-#include <boost/shared_array.hpp>
#include <boost/asio.hpp>
#include <boost/format.hpp>
#include <boost/thread.hpp>
@@ -37,14 +37,15 @@ namespace asio = boost::asio;
**********************************************************************/
//Define this to the the boost async io calls to perform receive.
//Otherwise, get_recv_buff uses a blocking receive with timeout.
-//#define USE_ASIO_ASYNC_RECV
+#define USE_ASIO_ASYNC_RECV
//Define this to the the boost async io calls to perform send.
//Otherwise, the commit callback uses a blocking send.
//#define USE_ASIO_ASYNC_SEND
-//enough buffering for half a second of samples at full rate on usrp2
-static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(4 * 25e6 * 0.5);
+//By default, this buffer is sized insufficiently small.
+//For peformance, this buffer should be 10s of megabytes.
+static const size_t MIN_RECV_SOCK_BUFF_SIZE = size_t(10e3);
//Large buffers cause more underflow at high rates.
//Perhaps this is due to the kernel scheduling,
@@ -123,16 +124,16 @@ public:
void init(void){
//allocate all recv frames and release them to begin xfers
_pending_recv_buffs = pending_buffs_type::make(_num_recv_frames);
- _recv_buffer = boost::shared_array<char>(new char[_num_recv_frames*_recv_frame_size]);
+ _recv_buffer_pool = buffer_pool::make(_num_recv_frames, _recv_frame_size);
for (size_t i = 0; i < _num_recv_frames; i++){
- release(_recv_buffer.get() + i*_recv_frame_size);
+ release(_recv_buffer_pool->at(i));
}
//allocate all send frames and push them into the fifo
_pending_send_buffs = pending_buffs_type::make(_num_send_frames);
- _send_buffer = boost::shared_array<char>(new char[_num_send_frames*_send_frame_size]);
+ _send_buffer_pool = buffer_pool::make(_num_send_frames, _send_frame_size);
for (size_t i = 0; i < _num_send_frames; i++){
- handle_send(_send_buffer.get() + i*_send_frame_size);
+ handle_send(_send_buffer_pool->at(i));
}
//spawn the service threads that will run the io service
@@ -302,7 +303,7 @@ public:
private:
//memory management -> buffers and fifos
boost::thread_group _thread_group;
- boost::shared_array<char> _send_buffer, _recv_buffer;
+ buffer_pool::sptr _send_buffer_pool, _recv_buffer_pool;
typedef bounded_buffer<asio::mutable_buffer> pending_buffs_type;
pending_buffs_type::sptr _pending_recv_buffs, _pending_send_buffs;
const size_t _recv_frame_size, _num_recv_frames;
@@ -321,12 +322,13 @@ private:
**********************************************************************/
template<typename Opt> static void resize_buff_helper(
udp_zero_copy_asio_impl::sptr udp_trans,
- size_t target_size,
+ const size_t target_size,
const std::string &name
){
size_t min_sock_buff_size = 0;
if (name == "recv") min_sock_buff_size = MIN_RECV_SOCK_BUFF_SIZE;
if (name == "send") min_sock_buff_size = MIN_SEND_SOCK_BUFF_SIZE;
+ min_sock_buff_size = std::max(min_sock_buff_size, target_size);
std::string help_message;
#if defined(UHD_PLATFORM_LINUX)
@@ -347,7 +349,7 @@ template<typename Opt> static void resize_buff_helper(
) % name % actual_size << std::endl;
if (actual_size < target_size) uhd::warning::post(str(boost::format(
"The %s buffer is smaller than the requested size.\n"
- "The minimum recommended buffer size is %d bytes.\n"
+ "The minimum requested buffer size is %d bytes.\n"
"See the transport application notes on buffer resizing.\n%s"
) % name % min_sock_buff_size % help_message));
}
diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp
index 278bcfeaa..c535edd04 100644
--- a/host/lib/transport/vrt_packet_handler.hpp
+++ b/host/lib/transport/vrt_packet_handler.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -26,7 +26,7 @@
#include <uhd/types/otw_type.hpp>
#include <uhd/types/metadata.hpp>
#include <uhd/transport/vrt_if_packet.hpp>
-#include <uhd/transport/convert_types.hpp>
+#include <uhd/convert.hpp>
#include <uhd/transport/zero_copy.hpp>
#include <boost/function.hpp>
#include <stdexcept>
@@ -35,6 +35,9 @@
namespace vrt_packet_handler{
+//this may change in the future but its a constant for now
+static const size_t OTW_BYTES_PER_SAMP = sizeof(boost::uint32_t);
+
template <typename T> UHD_INLINE T get_context_code(
const boost::uint32_t *vrt_hdr,
const uhd::transport::vrt::if_packet_info_t &if_packet_info
@@ -91,6 +94,7 @@ template <typename T> UHD_INLINE T get_context_code(
//vrt unpack each managed buffer
uhd::transport::vrt::if_packet_info_t if_packet_info;
for (size_t i = 0; i < state.width; i++){
+ if (state.managed_buffs[i].get() == NULL) continue; //better have a message packet coming up...
//extract packet words and check thats its enough to move on
size_t num_packet_words32 = state.managed_buffs[i]->size()/sizeof(boost::uint32_t);
@@ -144,8 +148,7 @@ template <typename T> UHD_INLINE T get_context_code(
size_t offset_bytes,
size_t total_samps,
uhd::rx_metadata_t &metadata,
- const uhd::io_type_t &io_type,
- const uhd::otw_type_t &otw_type,
+ uhd::convert::function_type &converter,
double tick_rate,
const vrt_unpacker_t &vrt_unpacker,
const get_recv_buffs_t &get_recv_buffs,
@@ -183,7 +186,7 @@ template <typename T> UHD_INLINE T get_context_code(
}
//extract the number of samples available to copy
- size_t bytes_per_item = otw_type.get_sample_size();
+ size_t bytes_per_item = OTW_BYTES_PER_SAMP;
size_t nsamps_available = state.size_of_copy_buffs/bytes_per_item;
size_t nsamps_to_copy = std::min(total_samps*chans_per_otw_buff, nsamps_available);
size_t bytes_to_copy = nsamps_to_copy*bytes_per_item;
@@ -198,9 +201,8 @@ template <typename T> UHD_INLINE T get_context_code(
}
//copy-convert the samples from the recv buffer
- uhd::transport::convert_otw_type_to_io_type(
- state.copy_buffs[i], otw_type, io_buffs, io_type, nsamps_to_copy_per_io_buff
- );
+ uhd::convert::input_type otw_buffs(1, state.copy_buffs[i]);
+ converter(otw_buffs, io_buffs, nsamps_to_copy_per_io_buff);
//update the rx copy buffer to reflect the bytes copied
state.copy_buffs[i] += bytes_to_copy;
@@ -234,6 +236,11 @@ template <typename T> UHD_INLINE T get_context_code(
size_t vrt_header_offset_words32 = 0,
size_t chans_per_otw_buff = 1
){
+ uhd::convert::function_type converter(
+ uhd::convert::get_converter_otw_to_cpu(
+ io_type, otw_type, 1, chans_per_otw_buff
+ ));
+
switch(recv_mode){
////////////////////////////////////////////////////////////////
@@ -244,7 +251,7 @@ template <typename T> UHD_INLINE T get_context_code(
buffs, 0,
total_num_samps,
metadata,
- io_type, otw_type,
+ converter,
tick_rate,
vrt_unpacker,
get_recv_buffs,
@@ -265,7 +272,7 @@ template <typename T> UHD_INLINE T get_context_code(
buffs, accum_num_samps*io_type.size,
total_num_samps - accum_num_samps,
(accum_num_samps == 0)? metadata : tmp_md, //only the first metadata gets kept
- io_type, otw_type,
+ converter,
tick_rate,
vrt_unpacker,
get_recv_buffs,
@@ -309,15 +316,14 @@ template <typename T> UHD_INLINE T get_context_code(
const size_t offset_bytes,
const size_t num_samps,
uhd::transport::vrt::if_packet_info_t &if_packet_info,
- const uhd::io_type_t &io_type,
- const uhd::otw_type_t &otw_type,
+ uhd::convert::function_type &converter,
const vrt_packer_t &vrt_packer,
const get_send_buffs_t &get_send_buffs,
const size_t vrt_header_offset_words32,
const size_t chans_per_otw_buff
){
//load the rest of the if_packet_info in here
- if_packet_info.num_payload_words32 = (num_samps*chans_per_otw_buff*otw_type.get_sample_size())/sizeof(boost::uint32_t);
+ if_packet_info.num_payload_words32 = (num_samps*chans_per_otw_buff*OTW_BYTES_PER_SAMP)/sizeof(boost::uint32_t);
if_packet_info.packet_count = state.next_packet_seq;
//get send buffers for each channel
@@ -337,9 +343,8 @@ template <typename T> UHD_INLINE T get_context_code(
otw_mem += if_packet_info.num_header_words32;
//copy-convert the samples into the send buffer
- uhd::transport::convert_io_type_to_otw_type(
- io_buffs, io_type, otw_mem, otw_type, num_samps
- );
+ uhd::convert::output_type otw_buffs(1, otw_mem);
+ converter(io_buffs, otw_buffs, num_samps);
//commit the samples to the zero-copy interface
size_t num_bytes_total = (vrt_header_offset_words32+if_packet_info.num_packet_words32)*sizeof(boost::uint32_t);
@@ -367,6 +372,11 @@ template <typename T> UHD_INLINE T get_context_code(
size_t vrt_header_offset_words32 = 0,
size_t chans_per_otw_buff = 1
){
+ uhd::convert::function_type converter(
+ uhd::convert::get_converter_cpu_to_otw(
+ io_type, otw_type, chans_per_otw_buff, 1
+ ));
+
//translate the metadata to vrt if packet info
uhd::transport::vrt::if_packet_info_t if_packet_info;
if_packet_info.has_sid = false;
@@ -402,7 +412,7 @@ template <typename T> UHD_INLINE T get_context_code(
buffs_, 0,
std::min(total_num_samps_, max_samples_per_packet),
if_packet_info,
- io_type, otw_type,
+ converter,
vrt_packer,
get_send_buffs,
vrt_header_offset_words32,
@@ -435,7 +445,7 @@ template <typename T> UHD_INLINE T get_context_code(
buffs, total_num_samps_sent*io_type.size,
std::min(total_num_samps_unsent, max_samples_per_packet),
if_packet_info,
- io_type, otw_type,
+ converter,
vrt_packer,
get_send_buffs,
vrt_header_offset_words32,
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
deleted file mode 100644
index bea20a4aa..000000000
--- a/host/lib/types.cpp
+++ /dev/null
@@ -1,350 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#include <uhd/utils/assert.hpp>
-#include <uhd/types/tune_request.hpp>
-#include <uhd/types/tune_result.hpp>
-#include <uhd/types/clock_config.hpp>
-#include <uhd/types/stream_cmd.hpp>
-#include <uhd/types/metadata.hpp>
-#include <uhd/types/ranges.hpp>
-#include <uhd/types/time_spec.hpp>
-#include <uhd/types/device_addr.hpp>
-#include <uhd/types/mac_addr.hpp>
-#include <uhd/types/otw_type.hpp>
-#include <uhd/types/io_type.hpp>
-#include <uhd/types/serial.hpp>
-#include <boost/math/special_functions/round.hpp>
-#include <boost/foreach.hpp>
-#include <boost/format.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/assign/list_of.hpp>
-#include <boost/thread.hpp>
-#include <stdexcept>
-#include <complex>
-#include <sstream>
-
-using namespace uhd;
-
-/***********************************************************************
- * ranges template instantiation
- **********************************************************************/
-template struct uhd::meta_range_t<float>;
-template struct uhd::meta_range_t<double>;
-
-/***********************************************************************
- * tune request
- **********************************************************************/
-tune_request_t::tune_request_t(double target_freq):
- target_freq(target_freq),
- inter_freq_policy(POLICY_AUTO),
- dsp_freq_policy(POLICY_AUTO)
-{
- /* NOP */
-}
-
-tune_request_t::tune_request_t(double target_freq, double lo_off):
- target_freq(target_freq),
- inter_freq_policy(POLICY_MANUAL),
- inter_freq(target_freq + lo_off),
- dsp_freq_policy(POLICY_AUTO)
-{
- /* NOP */
-}
-
-/***********************************************************************
- * tune result
- **********************************************************************/
-std::string tune_result_t::to_pp_string(void) const{
- return str(boost::format(
- "Tune Result:\n"
- " Target Intermediate Freq: %f (MHz)\n"
- " Actual Intermediate Freq: %f (MHz)\n"
- " Target DSP Freq Shift: %f (MHz)\n"
- " Actual DSP Freq Shift: %f (MHz)\n"
- )
- % (target_inter_freq/1e6) % (actual_inter_freq/1e6)
- % (target_dsp_freq/1e6) % (actual_dsp_freq/1e6)
- );
-}
-
-/***********************************************************************
- * clock config
- **********************************************************************/
-clock_config_t::clock_config_t(void):
- ref_source(REF_INT),
- pps_source(PPS_INT),
- pps_polarity(PPS_NEG)
-{
- /* NOP */
-}
-
-/***********************************************************************
- * stream command
- **********************************************************************/
-stream_cmd_t::stream_cmd_t(const stream_mode_t &stream_mode):
- stream_mode(stream_mode),
- num_samps(0),
- stream_now(true)
-{
- /* NOP */
-}
-
-/***********************************************************************
- * metadata
- **********************************************************************/
-tx_metadata_t::tx_metadata_t(void):
- has_time_spec(false),
- time_spec(time_spec_t()),
- start_of_burst(false),
- end_of_burst(false)
-{
- /* NOP */
-}
-
-/***********************************************************************
- * time spec
- **********************************************************************/
-time_spec_t::time_spec_t(double secs):
- _full_secs(0),
- _frac_secs(secs)
-{
- /* NOP */
-}
-
-time_spec_t::time_spec_t(time_t full_secs, double frac_secs):
- _full_secs(full_secs),
- _frac_secs(frac_secs)
-{
- /* NOP */
-}
-
-time_spec_t::time_spec_t(time_t full_secs, long tick_count, double tick_rate):
- _full_secs(full_secs),
- _frac_secs(double(tick_count)/tick_rate)
-{
- /* NOP */
-}
-
-long time_spec_t::get_tick_count(double tick_rate) const{
- return boost::math::iround(this->get_frac_secs()*tick_rate);
-}
-
-double time_spec_t::get_real_secs(void) const{
- return this->_full_secs + this->_frac_secs;
-}
-
-time_t time_spec_t::get_full_secs(void) const{
- double intpart;
- std::modf(this->_frac_secs, &intpart);
- return this->_full_secs + time_t(intpart);
-}
-
-double time_spec_t::get_frac_secs(void) const{
- return std::fmod(this->_frac_secs, 1.0);
-}
-
-time_spec_t &time_spec_t::operator+=(const time_spec_t &rhs){
- this->_full_secs += rhs.get_full_secs();
- this->_frac_secs += rhs.get_frac_secs();
- return *this;
-}
-
-time_spec_t &time_spec_t::operator-=(const time_spec_t &rhs){
- this->_full_secs -= rhs.get_full_secs();
- this->_frac_secs -= rhs.get_frac_secs();
- return *this;
-}
-
-bool uhd::operator==(const time_spec_t &lhs, const time_spec_t &rhs){
- return
- lhs.get_full_secs() == rhs.get_full_secs() and
- lhs.get_frac_secs() == rhs.get_frac_secs()
- ;
-}
-
-bool uhd::operator<(const time_spec_t &lhs, const time_spec_t &rhs){
- return (
- (lhs.get_full_secs() < rhs.get_full_secs()) or (
- (lhs.get_full_secs() == rhs.get_full_secs()) and
- (lhs.get_frac_secs() < rhs.get_frac_secs())
- ));
-}
-
-/***********************************************************************
- * device addr
- **********************************************************************/
-static const std::string arg_delim = ",";
-static const std::string pair_delim = "=";
-
-static std::string trim(const std::string &in){
- return boost::algorithm::trim_copy(in);
-}
-
-device_addr_t::device_addr_t(const std::string &args){
- BOOST_FOREACH(const std::string &pair, std::split_string(args, arg_delim)){
- if (trim(pair) == "") continue;
-
- std::vector<std::string> key_val = std::split_string(pair, pair_delim);
- if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args);
- (*this)[trim(key_val.front())] = trim(key_val.back());
- }
-}
-
-std::string device_addr_t::to_pp_string(void) const{
- if (this->size() == 0) return "Empty Device Address";
-
- std::stringstream ss;
- ss << "Device Address:" << std::endl;
- BOOST_FOREACH(std::string key, this->keys()){
- ss << boost::format(" %s: %s") % key % (*this)[key] << std::endl;
- }
- return ss.str();
-}
-
-std::string device_addr_t::to_string(void) const{
- std::string args_str;
- size_t count = 0;
- BOOST_FOREACH(const std::string &key, this->keys()){
- args_str += ((count++)? arg_delim : "") + key + pair_delim + (*this)[key];
- }
- return args_str;
-}
-
-/***********************************************************************
- * mac addr
- **********************************************************************/
-mac_addr_t::mac_addr_t(const byte_vector_t &bytes) : _bytes(bytes){
- UHD_ASSERT_THROW(_bytes.size() == 6);
-}
-
-mac_addr_t mac_addr_t::from_bytes(const byte_vector_t &bytes){
- return mac_addr_t(bytes);
-}
-
-mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){
-
- byte_vector_t bytes;
-
- try{
- if (mac_addr_str.size() != 17){
- throw std::runtime_error("expected exactly 17 characters");
- }
-
- //split the mac addr hex string at the colons
- BOOST_FOREACH(const std::string &hex_str, std::split_string(mac_addr_str, ":")){
- int hex_num;
- std::istringstream iss(hex_str);
- iss >> std::hex >> hex_num;
- bytes.push_back(boost::uint8_t(hex_num));
- }
-
- }
- catch(std::exception const& e){
- throw std::runtime_error(str(
- boost::format("Invalid mac address: %s\n\t%s") % mac_addr_str % e.what()
- ));
- }
-
- return mac_addr_t::from_bytes(bytes);
-}
-
-byte_vector_t mac_addr_t::to_bytes(void) const{
- return _bytes;
-}
-
-std::string mac_addr_t::to_string(void) const{
- std::string addr = "";
- BOOST_FOREACH(boost::uint8_t byte, this->to_bytes()){
- addr += str(boost::format("%s%02x") % ((addr == "")?"":":") % int(byte));
- }
- return addr;
-}
-
-/***********************************************************************
- * otw type
- **********************************************************************/
-size_t otw_type_t::get_sample_size(void) const{
- return (this->width * 2) / 8;
-}
-
-otw_type_t::otw_type_t(void):
- width(0),
- shift(0),
- byteorder(BO_NATIVE)
-{
- /* NOP */
-}
-
-/***********************************************************************
- * io type
- **********************************************************************/
-static size_t tid_to_size(io_type_t::tid_t tid){
- switch(tid){
- case io_type_t::COMPLEX_FLOAT32: return sizeof(std::complex<float>);
- case io_type_t::COMPLEX_INT16: return sizeof(std::complex<boost::int16_t>);
- case io_type_t::COMPLEX_INT8: return sizeof(std::complex<boost::int8_t>);
- default: throw std::runtime_error("unknown io type tid");
- }
-}
-
-io_type_t::io_type_t(tid_t tid)
-: size(tid_to_size(tid)), tid(tid){
- /* NOP */
-}
-
-io_type_t::io_type_t(size_t size)
-: size(size), tid(CUSTOM_TYPE){
- /* NOP */
-}
-
-/***********************************************************************
- * serial
- **********************************************************************/
-spi_config_t::spi_config_t(edge_t edge):
- mosi_edge(edge),
- miso_edge(edge)
-{
- /* NOP */
-}
-
-void i2c_iface::write_eeprom(
- boost::uint8_t addr,
- boost::uint8_t offset,
- const byte_vector_t &bytes
-){
- for (size_t i = 0; i < bytes.size(); i++){
- //write a byte at a time, its easy that way
- byte_vector_t cmd = boost::assign::list_of(offset+i)(bytes[i]);
- this->write_i2c(addr, cmd);
- boost::this_thread::sleep(boost::posix_time::milliseconds(10)); //worst case write
- }
-}
-
-byte_vector_t i2c_iface::read_eeprom(
- boost::uint8_t addr,
- boost::uint8_t offset,
- size_t num_bytes
-){
- byte_vector_t bytes;
- for (size_t i = 0; i < num_bytes; i++){
- //do a zero byte write to start read cycle
- this->write_i2c(addr, byte_vector_t(1, offset+i));
- bytes.push_back(this->read_i2c(addr, 1).at(0));
- }
- return bytes;
-}
diff --git a/host/lib/types/CMakeLists.txt b/host/lib/types/CMakeLists.txt
new file mode 100644
index 000000000..dfb7cf903
--- /dev/null
+++ b/host/lib/types/CMakeLists.txt
@@ -0,0 +1,31 @@
+#
+# Copyright 2011 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+########################################################################
+# This file included, use CMake directory variables
+########################################################################
+LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/clock_config.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/device_addr.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/mac_addr.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/ranges.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/sensors.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/serial.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/time_spec.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/tune.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/types.cpp
+)
diff --git a/host/lib/types/clock_config.cpp b/host/lib/types/clock_config.cpp
new file mode 100644
index 000000000..c150c5cc3
--- /dev/null
+++ b/host/lib/types/clock_config.cpp
@@ -0,0 +1,44 @@
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/types/clock_config.hpp>
+
+using namespace uhd;
+
+clock_config_t clock_config_t::external(void){
+ clock_config_t clock_config;
+ clock_config.ref_source = clock_config_t::REF_SMA;
+ clock_config.pps_source = clock_config_t::PPS_SMA;
+ clock_config.pps_polarity = clock_config_t::PPS_POS;
+ return clock_config;
+}
+
+clock_config_t clock_config_t::internal(void){
+ clock_config_t clock_config;
+ clock_config.ref_source = clock_config_t::REF_INT;
+ clock_config.pps_source = clock_config_t::PPS_SMA;
+ clock_config.pps_polarity = clock_config_t::PPS_POS;
+ return clock_config;
+}
+
+clock_config_t::clock_config_t(void):
+ ref_source(REF_INT),
+ pps_source(PPS_SMA),
+ pps_polarity(PPS_POS)
+{
+ /* NOP */
+}
diff --git a/host/lib/types/device_addr.cpp b/host/lib/types/device_addr.cpp
new file mode 100644
index 000000000..14afaa24b
--- /dev/null
+++ b/host/lib/types/device_addr.cpp
@@ -0,0 +1,73 @@
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/types/device_addr.hpp>
+#include <boost/algorithm/string.hpp> //for trim
+#include <boost/tokenizer.hpp>
+#include <boost/foreach.hpp>
+#include <boost/format.hpp>
+#include <stdexcept>
+#include <sstream>
+
+using namespace uhd;
+
+static const std::string arg_delim = ",";
+static const std::string pair_delim = "=";
+
+static std::string trim(const std::string &in){
+ return boost::algorithm::trim_copy(in);
+}
+
+#define tokenizer(inp, sep) \
+ boost::tokenizer<boost::char_separator<char> > \
+ (inp, boost::char_separator<char>(sep.c_str()))
+
+device_addr_t::device_addr_t(const std::string &args){
+ BOOST_FOREACH(const std::string &pair, tokenizer(args, arg_delim)){
+ if (trim(pair) == "") continue;
+ std::string key;
+ BOOST_FOREACH(const std::string &tok, tokenizer(pair, pair_delim)){
+ if (key.empty()) key = tok;
+ else{
+ this->set(trim(key), trim(tok));
+ goto continue_next_arg;
+ }
+ }
+ throw std::runtime_error("invalid args string: "+args);
+ continue_next_arg: continue;
+ }
+}
+
+std::string device_addr_t::to_pp_string(void) const{
+ if (this->size() == 0) return "Empty Device Address";
+
+ std::stringstream ss;
+ ss << "Device Address:" << std::endl;
+ BOOST_FOREACH(std::string key, this->keys()){
+ ss << boost::format(" %s: %s") % key % this->get(key) << std::endl;
+ }
+ return ss.str();
+}
+
+std::string device_addr_t::to_string(void) const{
+ std::string args_str;
+ size_t count = 0;
+ BOOST_FOREACH(const std::string &key, this->keys()){
+ args_str += ((count++)? arg_delim : "") + key + pair_delim + this->get(key);
+ }
+ return args_str;
+}
diff --git a/host/lib/types/mac_addr.cpp b/host/lib/types/mac_addr.cpp
new file mode 100644
index 000000000..cf3c3fa97
--- /dev/null
+++ b/host/lib/types/mac_addr.cpp
@@ -0,0 +1,76 @@
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/types/mac_addr.hpp>
+#include <uhd/utils/assert.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/foreach.hpp>
+#include <boost/format.hpp>
+#include <boost/cstdint.hpp>
+#include <stdexcept>
+#include <sstream>
+
+using namespace uhd;
+
+mac_addr_t::mac_addr_t(const byte_vector_t &bytes) : _bytes(bytes){
+ UHD_ASSERT_THROW(_bytes.size() == 6);
+}
+
+mac_addr_t mac_addr_t::from_bytes(const byte_vector_t &bytes){
+ return mac_addr_t(bytes);
+}
+
+mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){
+
+ byte_vector_t bytes;
+
+ try{
+ if (mac_addr_str.size() != 17){
+ throw std::runtime_error("expected exactly 17 characters");
+ }
+
+ //split the mac addr hex string at the colons
+ boost::tokenizer<boost::char_separator<char> > hex_num_toks(
+ mac_addr_str, boost::char_separator<char>(":"));
+ BOOST_FOREACH(const std::string &hex_str, hex_num_toks){
+ int hex_num;
+ std::istringstream iss(hex_str);
+ iss >> std::hex >> hex_num;
+ bytes.push_back(boost::uint8_t(hex_num));
+ }
+
+ }
+ catch(std::exception const& e){
+ throw std::runtime_error(str(
+ boost::format("Invalid mac address: %s\n\t%s") % mac_addr_str % e.what()
+ ));
+ }
+
+ return mac_addr_t::from_bytes(bytes);
+}
+
+byte_vector_t mac_addr_t::to_bytes(void) const{
+ return _bytes;
+}
+
+std::string mac_addr_t::to_string(void) const{
+ std::string addr = "";
+ BOOST_FOREACH(boost::uint8_t byte, this->to_bytes()){
+ addr += str(boost::format("%s%02x") % ((addr == "")?"":":") % int(byte));
+ }
+ return addr;
+}
diff --git a/host/lib/types/ranges.cpp b/host/lib/types/ranges.cpp
new file mode 100644
index 000000000..4a0d05d80
--- /dev/null
+++ b/host/lib/types/ranges.cpp
@@ -0,0 +1,163 @@
+//
+// Copyright 2011-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/types/ranges.hpp>
+#include <boost/math/special_functions/round.hpp>
+#include <boost/foreach.hpp>
+#include <algorithm>
+#include <stdexcept>
+#include <sstream>
+
+using namespace uhd;
+
+/***********************************************************************
+ * range_t implementation code
+ **********************************************************************/
+struct range_t::impl{
+ impl(double start, double stop, double step):
+ start(start), stop(stop), step(step)
+ {
+ /* NOP */
+ }
+ double start, stop, step;
+};
+
+range_t::range_t(double value):
+ _impl(UHD_PIMPL_MAKE(impl, (value, value, 0)))
+{
+ /* NOP */
+}
+
+range_t::range_t(
+ double start, double stop, double step
+):
+ _impl(UHD_PIMPL_MAKE(impl, (start, stop, step)))
+{
+ if (stop < start){
+ throw std::invalid_argument("cannot make range where stop < start");
+ }
+}
+
+double range_t::start(void) const{
+ return _impl->start;
+}
+
+double range_t::stop(void) const{
+ return _impl->stop;
+}
+
+double range_t::step(void) const{
+ return _impl->step;
+}
+
+const std::string range_t::to_pp_string(void) const{
+ std::stringstream ss;
+ ss << "(" << this->start();
+ if (this->start() != this->stop()) ss << ", " << this->stop();
+ if (this->step() != 0) ss << ", " << this->step();
+ ss << ")";
+ return ss.str();
+}
+
+/***********************************************************************
+ * meta_range_t implementation code
+ **********************************************************************/
+void check_meta_range_monotonic(const meta_range_t &mr){
+ if (mr.empty()){
+ throw std::runtime_error("meta-range cannot be empty");
+ }
+ for (size_t i = 1; i < mr.size(); i++){
+ if (mr.at(i).start() < mr.at(i-1).stop()){
+ throw std::runtime_error("meta-range is not monotonic");
+ }
+ }
+}
+
+meta_range_t::meta_range_t(void){
+ /* NOP */
+}
+
+meta_range_t::meta_range_t(
+ double start, double stop, double step
+):
+ std::vector<range_t > (1, range_t(start, stop, step))
+{
+ /* NOP */
+}
+
+double meta_range_t::start(void) const{
+ check_meta_range_monotonic(*this);
+ double min_start = this->front().start();
+ BOOST_FOREACH(const range_t &r, (*this)){
+ min_start = std::min(min_start, r.start());
+ }
+ return min_start;
+}
+
+double meta_range_t::stop(void) const{
+ check_meta_range_monotonic(*this);
+ double max_stop = this->front().stop();
+ BOOST_FOREACH(const range_t &r, (*this)){
+ max_stop = std::max(max_stop, r.stop());
+ }
+ return max_stop;
+}
+
+double meta_range_t::step(void) const{
+ check_meta_range_monotonic(*this);
+ std::vector<double> non_zero_steps;
+ range_t last = this->front();
+ BOOST_FOREACH(const range_t &r, (*this)){
+ //steps at each range
+ if (r.step() > 0) non_zero_steps.push_back(r.step());
+ //and steps in-between ranges
+ double ibtw_step = r.start() - last.stop();
+ if (ibtw_step > 0) non_zero_steps.push_back(ibtw_step);
+ //store ref to last
+ last = r;
+ }
+ if (non_zero_steps.empty()) return 0; //all zero steps, its zero...
+ return *std::min_element(non_zero_steps.begin(), non_zero_steps.end());
+}
+
+double meta_range_t::clip(double value, bool clip_step) const{
+ check_meta_range_monotonic(*this);
+ double last_stop = this->front().stop();
+ BOOST_FOREACH(const range_t &r, (*this)){
+ //in-between ranges, clip to nearest
+ if (value < r.start()){
+ return (std::abs(value - r.start()) < std::abs(value - last_stop))?
+ r.start() : last_stop;
+ }
+ //in this range, clip here
+ if (value <= r.stop()){
+ if (not clip_step or r.step() == 0) return value;
+ return boost::math::round((value - r.start())/r.step())*r.step() + r.start();
+ }
+ //continue on to the next range
+ last_stop = r.stop();
+ }
+ return last_stop;
+}
+
+const std::string meta_range_t::to_pp_string(void) const{
+ std::stringstream ss;
+ BOOST_FOREACH(const range_t &r, (*this)){
+ ss << r.to_pp_string() << std::endl;
+ }
+ return ss.str();
+}
diff --git a/host/lib/types/sensors.cpp b/host/lib/types/sensors.cpp
new file mode 100644
index 000000000..2bff136a4
--- /dev/null
+++ b/host/lib/types/sensors.cpp
@@ -0,0 +1,81 @@
+//
+// Copyright 2011-2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/types/sensors.hpp>
+#include <uhd/utils/exception.hpp>
+#include <boost/format.hpp>
+
+using namespace uhd;
+
+sensor_value_t::sensor_value_t(
+ const std::string &name,
+ bool value,
+ const std::string &ufalse,
+ const std::string &utrue
+):
+ name(name), value(value?"true":"false"),
+ unit(value?utrue:ufalse), type(BOOLEAN)
+{
+ /* NOP */
+}
+
+sensor_value_t::sensor_value_t(
+ const std::string &name,
+ int_type value,
+ const std::string &unit,
+ const std::string &formatter
+):
+ name(name), value(str(boost::format(formatter) % value)),
+ unit(unit), type(INTEGER)
+{
+ /* NOP */
+}
+
+sensor_value_t::sensor_value_t(
+ const std::string &name,
+ real_type value,
+ const std::string &unit,
+ const std::string &formatter
+):
+ name(name), value(str(boost::format(formatter) % value)),
+ unit(unit), type(REALNUM)
+{
+ /* NOP */
+}
+
+sensor_value_t::sensor_value_t(
+ const std::string &name,
+ const std::string &value,
+ const std::string &unit
+):
+ name(name), value(value),
+ unit(unit), type(STRING)
+{
+ /* NOP */
+}
+
+std::string sensor_value_t::to_pp_string(void) const{
+ switch(type){
+ case BOOLEAN:
+ return str(boost::format("%s: %s") % name % unit);
+ case INTEGER:
+ case REALNUM:
+ case STRING:
+ return str(boost::format("%s: %s %s") % name % value % unit);
+ }
+ UHD_THROW_INVALID_CODE_PATH();
+}
diff --git a/host/lib/types/serial.cpp b/host/lib/types/serial.cpp
new file mode 100644
index 000000000..9acf7156a
--- /dev/null
+++ b/host/lib/types/serial.cpp
@@ -0,0 +1,56 @@
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/types/serial.hpp>
+#include <boost/thread.hpp> //for sleeping
+#include <boost/assign/list_of.hpp>
+
+using namespace uhd;
+
+spi_config_t::spi_config_t(edge_t edge):
+ mosi_edge(edge),
+ miso_edge(edge)
+{
+ /* NOP */
+}
+
+void i2c_iface::write_eeprom(
+ boost::uint8_t addr,
+ boost::uint8_t offset,
+ const byte_vector_t &bytes
+){
+ for (size_t i = 0; i < bytes.size(); i++){
+ //write a byte at a time, its easy that way
+ byte_vector_t cmd = boost::assign::list_of(offset+i)(bytes[i]);
+ this->write_i2c(addr, cmd);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10)); //worst case write
+ }
+}
+
+byte_vector_t i2c_iface::read_eeprom(
+ boost::uint8_t addr,
+ boost::uint8_t offset,
+ size_t num_bytes
+){
+ byte_vector_t bytes;
+ for (size_t i = 0; i < num_bytes; i++){
+ //do a zero byte write to start read cycle
+ this->write_i2c(addr, byte_vector_t(1, offset+i));
+ bytes.push_back(this->read_i2c(addr, 1).at(0));
+ }
+ return bytes;
+}
diff --git a/host/lib/types/time_spec.cpp b/host/lib/types/time_spec.cpp
new file mode 100644
index 000000000..f39625a11
--- /dev/null
+++ b/host/lib/types/time_spec.cpp
@@ -0,0 +1,86 @@
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/types/time_spec.hpp>
+#include <boost/math/special_functions/round.hpp>
+
+using namespace uhd;
+time_spec_t::time_spec_t(double secs):
+ _full_secs(0),
+ _frac_secs(secs)
+{
+ /* NOP */
+}
+
+time_spec_t::time_spec_t(time_t full_secs, double frac_secs):
+ _full_secs(full_secs),
+ _frac_secs(frac_secs)
+{
+ /* NOP */
+}
+
+time_spec_t::time_spec_t(time_t full_secs, long tick_count, double tick_rate):
+ _full_secs(full_secs),
+ _frac_secs(double(tick_count)/tick_rate)
+{
+ /* NOP */
+}
+
+long time_spec_t::get_tick_count(double tick_rate) const{
+ return boost::math::iround(this->get_frac_secs()*tick_rate);
+}
+
+double time_spec_t::get_real_secs(void) const{
+ return this->_full_secs + this->_frac_secs;
+}
+
+time_t time_spec_t::get_full_secs(void) const{
+ double intpart;
+ std::modf(this->_frac_secs, &intpart);
+ return this->_full_secs + time_t(intpart);
+}
+
+double time_spec_t::get_frac_secs(void) const{
+ return std::fmod(this->_frac_secs, 1.0);
+}
+
+time_spec_t &time_spec_t::operator+=(const time_spec_t &rhs){
+ this->_full_secs += rhs.get_full_secs();
+ this->_frac_secs += rhs.get_frac_secs();
+ return *this;
+}
+
+time_spec_t &time_spec_t::operator-=(const time_spec_t &rhs){
+ this->_full_secs -= rhs.get_full_secs();
+ this->_frac_secs -= rhs.get_frac_secs();
+ return *this;
+}
+
+bool uhd::operator==(const time_spec_t &lhs, const time_spec_t &rhs){
+ return
+ lhs.get_full_secs() == rhs.get_full_secs() and
+ lhs.get_frac_secs() == rhs.get_frac_secs()
+ ;
+}
+
+bool uhd::operator<(const time_spec_t &lhs, const time_spec_t &rhs){
+ return (
+ (lhs.get_full_secs() < rhs.get_full_secs()) or (
+ (lhs.get_full_secs() == rhs.get_full_secs()) and
+ (lhs.get_frac_secs() < rhs.get_frac_secs())
+ ));
+}
diff --git a/host/lib/types/tune.cpp b/host/lib/types/tune.cpp
new file mode 100644
index 000000000..601bc20e8
--- /dev/null
+++ b/host/lib/types/tune.cpp
@@ -0,0 +1,52 @@
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/types/tune_request.hpp>
+#include <uhd/types/tune_result.hpp>
+#include <boost/format.hpp>
+
+using namespace uhd;
+
+tune_request_t::tune_request_t(double target_freq):
+ target_freq(target_freq),
+ inter_freq_policy(POLICY_AUTO),
+ dsp_freq_policy(POLICY_AUTO)
+{
+ /* NOP */
+}
+
+tune_request_t::tune_request_t(double target_freq, double lo_off):
+ target_freq(target_freq),
+ inter_freq_policy(POLICY_MANUAL),
+ inter_freq(target_freq + lo_off),
+ dsp_freq_policy(POLICY_AUTO)
+{
+ /* NOP */
+}
+
+std::string tune_result_t::to_pp_string(void) const{
+ return str(boost::format(
+ "Tune Result:\n"
+ " Target Intermediate Freq: %f (MHz)\n"
+ " Actual Intermediate Freq: %f (MHz)\n"
+ " Target DSP Freq Shift: %f (MHz)\n"
+ " Actual DSP Freq Shift: %f (MHz)\n"
+ )
+ % (target_inter_freq/1e6) % (actual_inter_freq/1e6)
+ % (target_dsp_freq/1e6) % (actual_dsp_freq/1e6)
+ );
+}
diff --git a/host/lib/types/types.cpp b/host/lib/types/types.cpp
new file mode 100644
index 000000000..34d5947eb
--- /dev/null
+++ b/host/lib/types/types.cpp
@@ -0,0 +1,86 @@
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/types/stream_cmd.hpp>
+#include <uhd/types/metadata.hpp>
+#include <uhd/types/otw_type.hpp>
+#include <uhd/types/io_type.hpp>
+#include <boost/cstdint.hpp>
+#include <stdexcept>
+#include <complex>
+
+using namespace uhd;
+
+/***********************************************************************
+ * stream command
+ **********************************************************************/
+stream_cmd_t::stream_cmd_t(const stream_mode_t &stream_mode):
+ stream_mode(stream_mode),
+ num_samps(0),
+ stream_now(true)
+{
+ /* NOP */
+}
+
+/***********************************************************************
+ * metadata
+ **********************************************************************/
+tx_metadata_t::tx_metadata_t(void):
+ has_time_spec(false),
+ time_spec(time_spec_t()),
+ start_of_burst(false),
+ end_of_burst(false)
+{
+ /* NOP */
+}
+
+/***********************************************************************
+ * otw type
+ **********************************************************************/
+size_t otw_type_t::get_sample_size(void) const{
+ return (this->width * 2) / 8;
+}
+
+otw_type_t::otw_type_t(void):
+ width(0),
+ shift(0),
+ byteorder(BO_NATIVE)
+{
+ /* NOP */
+}
+
+/***********************************************************************
+ * io type
+ **********************************************************************/
+static size_t tid_to_size(io_type_t::tid_t tid){
+ switch(tid){
+ case io_type_t::COMPLEX_FLOAT32: return sizeof(std::complex<float>);
+ case io_type_t::COMPLEX_INT16: return sizeof(std::complex<boost::int16_t>);
+ case io_type_t::COMPLEX_INT8: return sizeof(std::complex<boost::int8_t>);
+ default: throw std::runtime_error("unknown io type tid");
+ }
+}
+
+io_type_t::io_type_t(tid_t tid)
+: size(tid_to_size(tid)), tid(tid){
+ /* NOP */
+}
+
+io_type_t::io_type_t(size_t size)
+: size(size), tid(CUSTOM_TYPE){
+ /* NOP */
+}
diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt
index 9dc74a5fe..bd25aec2b 100644
--- a/host/lib/usrp/CMakeLists.txt
+++ b/host/lib/usrp/CMakeLists.txt
@@ -25,6 +25,7 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/dboard_iface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/dboard_manager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/dsp_utils.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/gps_ctrl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mboard_eeprom.cpp
${CMAKE_CURRENT_SOURCE_DIR}/misc_utils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/multi_usrp.cpp
diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp
index f771595b6..b311576d2 100644
--- a/host/lib/usrp/dboard/db_basic_and_lf.cpp
+++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -134,7 +134,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- val = float(0);
+ val = double(0);
return;
case SUBDEV_PROP_GAIN_RANGE:
@@ -192,7 +192,7 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_GAIN:
- UHD_ASSERT_THROW(val.as<float>() == float(0));
+ UHD_ASSERT_THROW(val.as<double>() == double(0));
return;
case SUBDEV_PROP_ANTENNA:
@@ -245,7 +245,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- val = float(0);
+ val = double(0);
return;
case SUBDEV_PROP_GAIN_RANGE:
@@ -303,7 +303,7 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_GAIN:
- UHD_ASSERT_THROW(val.as<float>() == float(0));
+ UHD_ASSERT_THROW(val.as<double>() == double(0));
return;
case SUBDEV_PROP_ANTENNA:
diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp
index 7250136f5..3ea9cea80 100644
--- a/host/lib/usrp/dboard/db_dbsrx.cpp
+++ b/host/lib/usrp/dboard/db_dbsrx.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -70,7 +70,7 @@ public:
private:
double _lo_freq;
double _bandwidth;
- uhd::dict<std::string, float> _gains;
+ uhd::dict<std::string, double> _gains;
max2118_write_regs_t _max2118_write_regs;
max2118_read_regs_t _max2118_read_regs;
boost::uint8_t _max2118_addr(void){
@@ -78,7 +78,7 @@ private:
};
void set_lo_freq(double target_freq);
- void set_gain(float gain, const std::string &name);
+ void set_gain(double gain, const std::string &name);
void set_bandwidth(double bandwidth);
void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){
@@ -418,17 +418,17 @@ void dbsrx::set_lo_freq(double target_freq){
* \param gain the requested gain in dB
* \return 5 bit the register value
*/
-static int gain_to_gc2_vga_reg(float &gain){
+static int gain_to_gc2_vga_reg(double &gain){
int reg = 0;
gain = dbsrx_gain_ranges["GC2"].clip(gain);
// Half dB steps from 0-5dB, 1dB steps from 5-24dB
if (gain < 5) {
reg = boost::math::iround(31.0 - gain/0.5);
- gain = float(boost::math::iround(gain) * 0.5);
+ gain = double(boost::math::iround(gain) * 0.5);
} else {
reg = boost::math::iround(22.0 - (gain - 4.0));
- gain = float(boost::math::iround(gain));
+ gain = double(boost::math::iround(gain));
}
if (dbsrx_debug) std::cerr << boost::format(
@@ -444,16 +444,16 @@ static int gain_to_gc2_vga_reg(float &gain){
* \param gain the requested gain in dB
* \return dac voltage value
*/
-static float gain_to_gc1_rfvga_dac(float &gain){
+static double gain_to_gc1_rfvga_dac(double &gain){
//clip the input
gain = dbsrx_gain_ranges["GC1"].clip(gain);
//voltage level constants
- static const float max_volts = float(1.2), min_volts = float(2.7);
- static const float slope = (max_volts-min_volts)/dbsrx_gain_ranges["GC1"].stop();
+ static const double max_volts = 1.2, min_volts = 2.7;
+ static const double slope = (max_volts-min_volts)/dbsrx_gain_ranges["GC1"].stop();
//calculate the voltage for the aux dac
- float dac_volts = gain*slope + min_volts;
+ double dac_volts = gain*slope + min_volts;
if (dbsrx_debug) std::cerr << boost::format(
"DBSRX GC1 Gain: %f dB, dac_volts: %f V"
@@ -465,7 +465,7 @@ static float gain_to_gc1_rfvga_dac(float &gain){
return dac_volts;
}
-void dbsrx::set_gain(float gain, const std::string &name){
+void dbsrx::set_gain(double gain, const std::string &name){
assert_has(dbsrx_gain_ranges.keys(), name, "dbsrx gain name");
if (name == "GC2"){
_max2118_write_regs.gc2 = gain_to_gc2_vga_reg(gain);
@@ -584,7 +584,7 @@ void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_gain(val.as<float>(), key.name);
+ this->set_gain(val.as<double>(), key.name);
return;
case SUBDEV_PROP_ENABLED:
diff --git a/host/lib/usrp/dboard/db_dbsrx2.cpp b/host/lib/usrp/dboard/db_dbsrx2.cpp
index cdafd6a78..defb70ff5 100644
--- a/host/lib/usrp/dboard/db_dbsrx2.cpp
+++ b/host/lib/usrp/dboard/db_dbsrx2.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -48,7 +48,7 @@ static const int dbsrx2_ref_divider = 4; // Hitachi HMC426 divider (U7)
static const prop_names_t dbsrx2_antennas = list_of("J3");
static const uhd::dict<std::string, gain_range_t> dbsrx2_gain_ranges = map_list_of
- ("GC1", gain_range_t(0, 73, float(0.05)))
+ ("GC1", gain_range_t(0, 73, 0.05))
("BBG", gain_range_t(0, 15, 1))
;
@@ -66,7 +66,7 @@ public:
private:
double _lo_freq;
double _bandwidth;
- uhd::dict<std::string, float> _gains;
+ uhd::dict<std::string, double> _gains;
max2112_write_regs_t _max2112_write_regs;
max2112_read_regs_t _max2112_read_regs;
boost::uint8_t _max2112_addr(){ //0x60 or 0x61 depending on which side
@@ -74,7 +74,7 @@ private:
}
void set_lo_freq(double target_freq);
- void set_gain(float gain, const std::string &name);
+ void set_gain(double gain, const std::string &name);
void set_bandwidth(double bandwidth);
void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){
@@ -269,10 +269,10 @@ void dbsrx2::set_lo_freq(double target_freq){
* \param gain the requested gain in dB
* \return 4 bit the register value
*/
-static int gain_to_bbg_vga_reg(float &gain){
+static int gain_to_bbg_vga_reg(double &gain){
int reg = boost::math::iround(dbsrx2_gain_ranges["BBG"].clip(gain));
- gain = float(reg);
+ gain = double(reg);
if (dbsrx2_debug) std::cerr
<< boost::format("DBSRX2 BBG Gain:\n")
@@ -288,16 +288,16 @@ static int gain_to_bbg_vga_reg(float &gain){
* \param gain the requested gain in dB
* \return dac voltage value
*/
-static float gain_to_gc1_rfvga_dac(float &gain){
+static double gain_to_gc1_rfvga_dac(double &gain){
//clip the input
gain = dbsrx2_gain_ranges["GC1"].clip(gain);
//voltage level constants
- static const float max_volts = float(0.5), min_volts = float(2.7);
- static const float slope = (max_volts-min_volts)/dbsrx2_gain_ranges["GC1"].stop();
+ static const double max_volts = 0.5, min_volts = 2.7;
+ static const double slope = (max_volts-min_volts)/dbsrx2_gain_ranges["GC1"].stop();
//calculate the voltage for the aux dac
- float dac_volts = gain*slope + min_volts;
+ double dac_volts = gain*slope + min_volts;
if (dbsrx2_debug) std::cerr
<< boost::format("DBSRX2 GC1 Gain:\n")
@@ -310,7 +310,7 @@ static float gain_to_gc1_rfvga_dac(float &gain){
return dac_volts;
}
-void dbsrx2::set_gain(float gain, const std::string &name){
+void dbsrx2::set_gain(double gain, const std::string &name){
assert_has(dbsrx2_gain_ranges.keys(), name, "dbsrx2 gain name");
if (name == "BBG"){
_max2112_write_regs.bbg = gain_to_bbg_vga_reg(gain);
@@ -423,7 +423,7 @@ void dbsrx2::rx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_gain(val.as<float>(), key.name);
+ this->set_gain(val.as<double>(), key.name);
return;
case SUBDEV_PROP_ENABLED:
diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index 74a9fb37b..cd25ee9b7 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -67,11 +67,11 @@ static const prop_names_t rfx_rx_antennas = list_of("TX/RX")("RX2");
static const uhd::dict<std::string, gain_range_t> rfx_tx_gain_ranges; //empty
static const uhd::dict<std::string, gain_range_t> rfx_rx_gain_ranges = map_list_of
- ("PGA0", gain_range_t(0, 70, float(0.022)))
+ ("PGA0", gain_range_t(0, 70, 0.022))
;
static const uhd::dict<std::string, gain_range_t> rfx400_rx_gain_ranges = map_list_of
- ("PGA0", gain_range_t(0, 45, float(0.022)))
+ ("PGA0", gain_range_t(0, 45, 0.022))
;
/***********************************************************************
@@ -98,14 +98,14 @@ private:
const uhd::dict<dboard_iface::unit_t, bool> _div2;
double _rx_lo_freq, _tx_lo_freq;
std::string _rx_ant;
- uhd::dict<std::string, float> _rx_gains;
+ uhd::dict<std::string, double> _rx_gains;
void set_rx_lo_freq(double freq);
void set_tx_lo_freq(double freq);
void set_rx_ant(const std::string &ant);
void set_tx_ant(const std::string &ant);
- void set_rx_gain(float gain, const std::string &name);
- void set_tx_gain(float gain, const std::string &name);
+ void set_rx_gain(double gain, const std::string &name);
+ void set_tx_gain(double gain, const std::string &name);
/*!
* Set the LO frequency for the particular dboard unit.
@@ -240,13 +240,13 @@ void rfx_xcvr::set_tx_ant(const std::string &ant){
/***********************************************************************
* Gain Handling
**********************************************************************/
-static float rx_pga0_gain_to_dac_volts(float &gain, float range){
+static double rx_pga0_gain_to_dac_volts(double &gain, double range){
//voltage level constants (negative slope)
- static const float max_volts = float(.2), min_volts = float(1.2);
- static const float slope = (max_volts-min_volts)/(range);
+ static const double max_volts = .2, min_volts = 1.2;
+ static const double slope = (max_volts-min_volts)/(range);
//calculate the voltage for the aux dac
- float dac_volts = std::clip<float>(gain*slope + min_volts, max_volts, min_volts);
+ double dac_volts = std::clip<double>(gain*slope + min_volts, max_volts, min_volts);
//the actual gain setting
gain = (dac_volts - min_volts)/slope;
@@ -254,15 +254,15 @@ static float rx_pga0_gain_to_dac_volts(float &gain, float range){
return dac_volts;
}
-void rfx_xcvr::set_tx_gain(float, const std::string &name){
+void rfx_xcvr::set_tx_gain(double, const std::string &name){
assert_has(rfx_tx_gain_ranges.keys(), name, "rfx tx gain name");
UHD_THROW_INVALID_CODE_PATH(); //no gains to set
}
-void rfx_xcvr::set_rx_gain(float gain, const std::string &name){
+void rfx_xcvr::set_rx_gain(double gain, const std::string &name){
assert_has(_rx_gain_ranges.keys(), name, "rfx rx gain name");
if(name == "PGA0"){
- float dac_volts = rx_pga0_gain_to_dac_volts(gain,
+ double dac_volts = rx_pga0_gain_to_dac_volts(gain,
(_rx_gain_ranges["PGA0"].stop() - _rx_gain_ranges["PGA0"].start()));
_rx_gains[name] = gain;
@@ -474,7 +474,7 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_rx_gain(val.as<float>(), key.name);
+ this->set_rx_gain(val.as<double>(), key.name);
return;
case SUBDEV_PROP_ANTENNA:
@@ -571,7 +571,7 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_tx_gain(val.as<float>(), key.name);
+ this->set_tx_gain(val.as<double>(), key.name);
return;
case SUBDEV_PROP_ANTENNA:
diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp
index 2508555d0..4eb29c3e8 100644
--- a/host/lib/usrp/dboard/db_tvrx.cpp
+++ b/host/lib/usrp/dboard/db_tvrx.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -119,8 +119,8 @@ static uhd::dict<std::string, gain_range_t> get_tvrx_gain_ranges(void) {
double ifmax = tvrx_if_gains_db.back();
return map_list_of
- ("RF", gain_range_t(float(rfmin), float(rfmax), float((rfmax-rfmin)/4096.0)))
- ("IF", gain_range_t(float(ifmin), float(ifmax), float((ifmax-ifmin)/4096.0)))
+ ("RF", gain_range_t(rfmin, rfmax, (rfmax-rfmin)/4096.0))
+ ("IF", gain_range_t(ifmin, ifmax, (ifmax-ifmin)/4096.0))
;
}
@@ -141,14 +141,14 @@ public:
void rx_set(const wax::obj &key, const wax::obj &val);
private:
- uhd::dict<std::string, float> _gains;
+ uhd::dict<std::string, double> _gains;
double _lo_freq;
tuner_4937di5_regs_t _tuner_4937di5_regs;
boost::uint8_t _tuner_4937di5_addr(void){
return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x61 : 0x60; //ok really? we could rename that call
};
- void set_gain(float gain, const std::string &name);
+ void set_gain(double gain, const std::string &name);
void set_freq(double freq);
void update_regs(void){
@@ -275,7 +275,7 @@ static double gain_interp(double gain, boost::array<double, 17> db_vector, boost
* \return dac voltage value
*/
-static float rf_gain_to_voltage(float gain, double lo_freq){
+static double rf_gain_to_voltage(double gain, double lo_freq){
//clip the input
gain = get_tvrx_gain_ranges()["RF"].clip(gain);
@@ -293,7 +293,7 @@ static float rf_gain_to_voltage(float gain, double lo_freq){
"tvrx RF AGC gain: %f dB, dac_volts: %f V"
) % gain % dac_volts << std::endl;
- return float(dac_volts);
+ return dac_volts;
}
/*!
@@ -303,7 +303,7 @@ static float rf_gain_to_voltage(float gain, double lo_freq){
* \return dac voltage value
*/
-static float if_gain_to_voltage(float gain){
+static double if_gain_to_voltage(double gain){
//clip the input
gain = get_tvrx_gain_ranges()["IF"].clip(gain);
@@ -316,10 +316,10 @@ static float if_gain_to_voltage(float gain){
"tvrx IF AGC gain: %f dB, dac_volts: %f V"
) % gain % dac_volts << std::endl;
- return float(dac_volts);
+ return dac_volts;
}
-void tvrx::set_gain(float gain, const std::string &name){
+void tvrx::set_gain(double gain, const std::string &name){
assert_has(get_tvrx_gain_ranges().keys(), name, "tvrx gain name");
if (name == "RF"){
this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_B, rf_gain_to_voltage(gain, _lo_freq));
@@ -473,7 +473,7 @@ void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_GAIN:
- this->set_gain(val.as<float>(), key.name);
+ this->set_gain(val.as<double>(), key.name);
return;
case SUBDEV_PROP_FREQ:
diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp
index 168e1971c..d91d58409 100644
--- a/host/lib/usrp/dboard/db_unknown.cpp
+++ b/host/lib/usrp/dboard/db_unknown.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -115,7 +115,7 @@ void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- val = float(0);
+ val = double(0);
return;
case SUBDEV_PROP_GAIN_RANGE:
@@ -173,7 +173,7 @@ void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_GAIN:
- UHD_ASSERT_THROW(val.as<float>() == float(0));
+ UHD_ASSERT_THROW(val.as<double>() == double(0));
return;
case SUBDEV_PROP_ANTENNA:
@@ -217,7 +217,7 @@ void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- val = float(0);
+ val = double(0);
return;
case SUBDEV_PROP_GAIN_RANGE:
@@ -275,7 +275,7 @@ void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_GAIN:
- UHD_ASSERT_THROW(val.as<float>() == float(0));
+ UHD_ASSERT_THROW(val.as<double>() == double(0));
return;
case SUBDEV_PROP_ANTENNA:
diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp
index dd5bd600b..135997789 100644
--- a/host/lib/usrp/dboard/db_wbx.cpp
+++ b/host/lib/usrp/dboard/db_wbx.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -94,11 +94,11 @@ static const prop_names_t wbx_tx_antennas = list_of("TX/RX");
static const prop_names_t wbx_rx_antennas = list_of("TX/RX")("RX2");
static const uhd::dict<std::string, gain_range_t> wbx_tx_gain_ranges = map_list_of
- ("PGA0", gain_range_t(0, 25, float(0.05)))
+ ("PGA0", gain_range_t(0, 25, 0.05))
;
static const uhd::dict<std::string, gain_range_t> wbx_rx_gain_ranges = map_list_of
- ("PGA0", gain_range_t(0, 31.5, float(0.5)))
+ ("PGA0", gain_range_t(0, 31.5, 0.5))
;
/***********************************************************************
@@ -116,7 +116,7 @@ public:
void tx_set(const wax::obj &key, const wax::obj &val);
private:
- uhd::dict<std::string, float> _tx_gains, _rx_gains;
+ uhd::dict<std::string, double> _tx_gains, _rx_gains;
double _rx_lo_freq, _tx_lo_freq;
std::string _tx_ant, _rx_ant;
@@ -124,8 +124,8 @@ private:
void set_tx_lo_freq(double freq);
void set_rx_ant(const std::string &ant);
void set_tx_ant(const std::string &ant);
- void set_rx_gain(float gain, const std::string &name);
- void set_tx_gain(float gain, const std::string &name);
+ void set_rx_gain(double gain, const std::string &name);
+ void set_tx_gain(double gain, const std::string &name);
void update_atr(void);
@@ -196,12 +196,12 @@ wbx_xcvr::~wbx_xcvr(void){
/***********************************************************************
* Gain Handling
**********************************************************************/
-static int rx_pga0_gain_to_iobits(float &gain){
+static int rx_pga0_gain_to_iobits(double &gain){
//clip the input
gain = wbx_rx_gain_ranges["PGA0"].clip(gain);
//convert to attenuation and update iobits for atr
- float attn = wbx_rx_gain_ranges["PGA0"].stop() - gain;
+ double attn = wbx_rx_gain_ranges["PGA0"].stop() - gain;
//calculate the attenuation
int attn_code = boost::math::iround(attn*2);
@@ -212,21 +212,21 @@ static int rx_pga0_gain_to_iobits(float &gain){
) % attn % attn_code % (iobits & RX_ATTN_MASK) % RX_ATTN_MASK << std::endl;
//the actual gain setting
- gain = wbx_rx_gain_ranges["PGA0"].stop() - float(attn_code)/2;
+ gain = wbx_rx_gain_ranges["PGA0"].stop() - double(attn_code)/2;
return iobits;
}
-static float tx_pga0_gain_to_dac_volts(float &gain){
+static double tx_pga0_gain_to_dac_volts(double &gain){
//clip the input
gain = wbx_tx_gain_ranges["PGA0"].clip(gain);
//voltage level constants
- static const float max_volts = float(0.5), min_volts = float(1.4);
- static const float slope = (max_volts-min_volts)/wbx_tx_gain_ranges["PGA0"].stop();
+ static const double max_volts = 0.5, min_volts = 1.4;
+ static const double slope = (max_volts-min_volts)/wbx_tx_gain_ranges["PGA0"].stop();
//calculate the voltage for the aux dac
- float dac_volts = gain*slope + min_volts;
+ double dac_volts = gain*slope + min_volts;
if (wbx_debug) std::cerr << boost::format(
"WBX TX Gain: %f dB, dac_volts: %f V"
@@ -238,10 +238,10 @@ static float tx_pga0_gain_to_dac_volts(float &gain){
return dac_volts;
}
-void wbx_xcvr::set_tx_gain(float gain, const std::string &name){
+void wbx_xcvr::set_tx_gain(double gain, const std::string &name){
assert_has(wbx_tx_gain_ranges.keys(), name, "wbx tx gain name");
if(name == "PGA0"){
- float dac_volts = tx_pga0_gain_to_dac_volts(gain);
+ double dac_volts = tx_pga0_gain_to_dac_volts(gain);
_tx_gains[name] = gain;
//write the new voltage to the aux dac
@@ -250,7 +250,7 @@ void wbx_xcvr::set_tx_gain(float gain, const std::string &name){
else UHD_THROW_INVALID_CODE_PATH();
}
-void wbx_xcvr::set_rx_gain(float gain, const std::string &name){
+void wbx_xcvr::set_rx_gain(double gain, const std::string &name){
assert_has(wbx_rx_gain_ranges.keys(), name, "wbx rx gain name");
if(name == "PGA0"){
rx_pga0_gain_to_iobits(gain);
@@ -544,7 +544,7 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_rx_gain(val.as<float>(), key.name);
+ this->set_rx_gain(val.as<double>(), key.name);
return;
case SUBDEV_PROP_ANTENNA:
@@ -645,7 +645,7 @@ void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_tx_gain(val.as<float>(), key.name);
+ this->set_tx_gain(val.as<double>(), key.name);
return;
case SUBDEV_PROP_ANTENNA:
diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp
index e76727bec..6fb5a26a8 100644
--- a/host/lib/usrp/dboard/db_xcvr2450.cpp
+++ b/host/lib/usrp/dboard/db_xcvr2450.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -73,8 +73,8 @@ using namespace boost::assign;
static const bool xcvr2450_debug = false;
static const freq_range_t xcvr_freq_range = list_of
- (range_t<double>(2.4e9, 2.5e9))
- (range_t<double>(4.9e9, 6.0e9))
+ (range_t(2.4e9, 2.5e9))
+ (range_t(4.9e9, 6.0e9))
;
static const prop_names_t xcvr_antennas = list_of("J1")("J2");
@@ -85,9 +85,9 @@ static const uhd::dict<std::string, gain_range_t> xcvr_tx_gain_ranges = map_list
;
static const uhd::dict<std::string, gain_range_t> xcvr_rx_gain_ranges = map_list_of
("LNA", gain_range_t(list_of
- (range_t<float>(0))
- (range_t<float>(15))
- (range_t<float>(30.5))
+ (range_t(0))
+ (range_t(15))
+ (range_t(30.5))
))
("VGA", gain_range_t(0, 62, 2.0))
;
@@ -109,7 +109,7 @@ public:
private:
double _lo_freq;
double _rx_bandwidth, _tx_bandwidth;
- uhd::dict<std::string, float> _tx_gains, _rx_gains;
+ uhd::dict<std::string, double> _tx_gains, _rx_gains;
std::string _tx_ant, _rx_ant;
int _ad9515div;
max2829_regs_t _max2829_regs;
@@ -117,8 +117,8 @@ private:
void set_lo_freq(double target_freq);
void set_tx_ant(const std::string &ant);
void set_rx_ant(const std::string &ant);
- void set_tx_gain(float gain, const std::string &name);
- void set_rx_gain(float gain, const std::string &name);
+ void set_tx_gain(double gain, const std::string &name);
+ void set_rx_gain(double gain, const std::string &name);
void set_rx_bandwidth(double bandwidth);
void set_tx_bandwidth(double bandwidth);
@@ -150,12 +150,12 @@ private:
* Read the RSSI from the aux adc
* \return the rssi in dB
*/
- float get_rssi(void){
+ double get_rssi(void){
//constants for the rssi calculation
- static const float min_v = float(0.5), max_v = float(2.5);
- static const float rssi_dyn_range = 60;
+ static const double min_v = 0.5, max_v = 2.5;
+ static const double rssi_dyn_range = 60;
//calculate the rssi from the voltage
- float voltage = this->get_iface()->read_aux_adc(dboard_iface::UNIT_RX, dboard_iface::AUX_ADC_B);
+ double voltage = this->get_iface()->read_aux_adc(dboard_iface::UNIT_RX, dboard_iface::AUX_ADC_B);
return rssi_dyn_range*(voltage - min_v)/(max_v - min_v);
}
};
@@ -355,14 +355,14 @@ void xcvr2450::set_rx_ant(const std::string &ant){
* \param gain the requested gain in dB
* \return 6 bit the register value
*/
-static int gain_to_tx_vga_reg(float &gain){
+static int gain_to_tx_vga_reg(double &gain){
//calculate the register value
int reg = std::clip(boost::math::iround(gain*60/30.0) + 3, 0, 63);
//calculate the actual gain value
if (reg < 4) gain = 0;
- else if (reg < 48) gain = float(reg/2 - 1);
- else gain = float(reg/2.0 - 1.5);
+ else if (reg < 48) gain = double(reg/2 - 1);
+ else gain = double(reg/2.0 - 1.5);
//return register value
return reg;
@@ -374,7 +374,7 @@ static int gain_to_tx_vga_reg(float &gain){
* \param gain the requested gain in dB
* \return gain enum value
*/
-static max2829_regs_t::tx_baseband_gain_t gain_to_tx_bb_reg(float &gain){
+static max2829_regs_t::tx_baseband_gain_t gain_to_tx_bb_reg(double &gain){
int reg = std::clip(boost::math::iround(gain*3/5.0), 0, 3);
switch(reg){
case 0:
@@ -399,9 +399,9 @@ static max2829_regs_t::tx_baseband_gain_t gain_to_tx_bb_reg(float &gain){
* \param gain the requested gain in dB
* \return 5 bit the register value
*/
-static int gain_to_rx_vga_reg(float &gain){
+static int gain_to_rx_vga_reg(double &gain){
int reg = std::clip(boost::math::iround(gain/2.0), 0, 31);
- gain = float(reg*2);
+ gain = double(reg*2);
return reg;
}
@@ -411,7 +411,7 @@ static int gain_to_rx_vga_reg(float &gain){
* \param gain the requested gain in dB
* \return 2 bit the register value
*/
-static int gain_to_rx_lna_reg(float &gain){
+static int gain_to_rx_lna_reg(double &gain){
int reg = std::clip(boost::math::iround(gain*2/30.5) + 1, 0, 3);
switch(reg){
case 0:
@@ -422,7 +422,7 @@ static int gain_to_rx_lna_reg(float &gain){
return reg;
}
-void xcvr2450::set_tx_gain(float gain, const std::string &name){
+void xcvr2450::set_tx_gain(double gain, const std::string &name){
assert_has(xcvr_tx_gain_ranges.keys(), name, "xcvr tx gain name");
if (name == "VGA"){
_max2829_regs.tx_vga_gain = gain_to_tx_vga_reg(gain);
@@ -436,7 +436,7 @@ void xcvr2450::set_tx_gain(float gain, const std::string &name){
_tx_gains[name] = gain;
}
-void xcvr2450::set_rx_gain(float gain, const std::string &name){
+void xcvr2450::set_rx_gain(double gain, const std::string &name){
assert_has(xcvr_rx_gain_ranges.keys(), name, "xcvr rx gain name");
if (name == "VGA"){
_max2829_regs.rx_vga_gain = gain_to_rx_vga_reg(gain);
@@ -643,7 +643,7 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_rx_gain(val.as<float>(), key.name);
+ this->set_rx_gain(val.as<double>(), key.name);
return;
case SUBDEV_PROP_ANTENNA:
@@ -742,7 +742,7 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_GAIN:
- this->set_tx_gain(val.as<float>(), key.name);
+ this->set_tx_gain(val.as<double>(), key.name);
return;
case SUBDEV_PROP_BANDWIDTH:
diff --git a/host/lib/usrp/usrp2/gps_ctrl.cpp b/host/lib/usrp/gps_ctrl.cpp
index 2273b2cd9..3c7c00134 100644
--- a/host/lib/usrp/usrp2/gps_ctrl.cpp
+++ b/host/lib/usrp/gps_ctrl.cpp
@@ -15,7 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include "gps_ctrl.hpp"
+#include <uhd/usrp/gps_ctrl.hpp>
#include <uhd/utils/assert.hpp>
#include <boost/cstdint.hpp>
#include <string>
@@ -30,14 +30,15 @@ using namespace boost::posix_time;
using namespace boost::algorithm;
/*!
- * A usrp2 GPS control for Jackson Labs devices
+ * A GPS control for Jackson Labs devices (and other NMEA compatible GPS's)
*/
//TODO: multiple baud rate support (requires mboard_impl changes for poking UART registers)
-class usrp2_gps_ctrl_impl : public usrp2_gps_ctrl{
+class gps_ctrl_impl : public gps_ctrl{
public:
- usrp2_gps_ctrl_impl(usrp2_iface::sptr iface){
- _iface = iface;
+ gps_ctrl_impl(gps_send_fn_t send, gps_recv_fn_t recv){
+ _send = send;
+ _recv = recv;
std::string reply;
bool i_heard_some_nmea = false, i_heard_something_weird = false;
@@ -47,8 +48,8 @@ public:
// set_uart_baud_rate(GPS_UART, 115200);
//first we look for a Jackson Labs Firefly (since that's what we sell with the USRP2+...)
- _iface->read_uart(GPS_UART); //get whatever junk is in the rx buffer right now, and throw it away
- _iface->write_uart(GPS_UART, "HAAAY GUYYYYS\n"); //to elicit a response from the Firefly
+ _recv(); //get whatever junk is in the rx buffer right now, and throw it away
+ _send("HAAAY GUYYYYS\n"); //to elicit a response from the Firefly
//then we loop until we either timeout, or until we get a response that indicates we're a JL device
int timeout = GPS_TIMEOUT_TRIES;
@@ -60,13 +61,14 @@ public:
}
else if(reply.substr(0, 3) == "$GP") i_heard_some_nmea = true; //but keep looking for that "Command Error" response
else if(reply.length() != 0) i_heard_something_weird = true; //probably wrong baud rate
+ boost::this_thread::sleep(boost::posix_time::milliseconds(200));
}
if((i_heard_some_nmea) && (gps_type != GPS_TYPE_JACKSON_LABS)) gps_type = GPS_TYPE_GENERIC_NMEA;
//otherwise, we can try some other common baud rates looking to see if a GPS is connected (todo, later)
if((gps_type == GPS_TYPE_NONE) && i_heard_something_weird) {
- std::cout << "Invalid reply, possible incorrect baud rate" << std::endl;
+ std::cout << "GPS invalid reply \"" << reply << "\", assuming none available" << std::endl;
}
bool found_gprmc = false;
@@ -78,15 +80,15 @@ public:
//none of these should issue replies so we don't bother looking for them
//we have to sleep between commands because the JL device, despite not acking, takes considerable time to process each command.
boost::this_thread::sleep(boost::posix_time::milliseconds(FIREFLY_STUPID_DELAY_MS));
- _iface->write_uart(GPS_UART, "SYST:COMM:SER:ECHO OFF\n");
+ _send("SYST:COMM:SER:ECHO OFF\n");
boost::this_thread::sleep(boost::posix_time::milliseconds(FIREFLY_STUPID_DELAY_MS));
- _iface->write_uart(GPS_UART, "SYST:COMM:SER:PRO OFF\n");
+ _send("SYST:COMM:SER:PRO OFF\n");
boost::this_thread::sleep(boost::posix_time::milliseconds(FIREFLY_STUPID_DELAY_MS));
- _iface->write_uart(GPS_UART, "GPS:GPGGA 0\n");
+ _send("GPS:GPGGA 0\n");
boost::this_thread::sleep(boost::posix_time::milliseconds(FIREFLY_STUPID_DELAY_MS));
- _iface->write_uart(GPS_UART, "GPS:GGAST 0\n");
+ _send("GPS:GGAST 0\n");
boost::this_thread::sleep(boost::posix_time::milliseconds(FIREFLY_STUPID_DELAY_MS));
- _iface->write_uart(GPS_UART, "GPS:GPRMC 1\n");
+ _send("GPS:GPRMC 1\n");
boost::this_thread::sleep(boost::posix_time::milliseconds(FIREFLY_STUPID_DELAY_MS));
// break;
@@ -119,15 +121,15 @@ public:
}
- ~usrp2_gps_ctrl_impl(void){
+ ~gps_ctrl_impl(void){
}
+//TODO: this isn't generalizeable to non-USRP2 USRPs.
std::string safe_gps_read() {
std::string reply;
try {
- reply = _iface->read_uart(GPS_UART);
- //std::cerr << "Got reply from GPS: " << reply.c_str() << " with length = " << reply.length() << std::endl;
+ reply = _recv();
} catch (std::runtime_error err) {
if(err.what() != std::string("usrp2 no control response")) throw; //sorry can't cope with that
else { //we don't actually have a GPS installed
@@ -185,7 +187,8 @@ public:
}
private:
- usrp2_iface::sptr _iface;
+ gps_send_fn_t _send;
+ gps_recv_fn_t _recv;
enum {
GPS_TYPE_JACKSON_LABS,
@@ -193,8 +196,8 @@ private:
GPS_TYPE_NONE
} gps_type;
- static const int GPS_UART = 2; //TODO: this should be plucked from fw_common.h or memory_map.h or somewhere in common with the firmware
static const int GPS_TIMEOUT_TRIES = 5;
+ static const int GPS_TIMEOUT_DELAY_MS = 200;
static const int FIREFLY_STUPID_DELAY_MS = 200;
};
@@ -202,6 +205,6 @@ private:
/***********************************************************************
* Public make function for the GPS control
**********************************************************************/
-usrp2_gps_ctrl::sptr usrp2_gps_ctrl::make(usrp2_iface::sptr iface){
- return sptr(new usrp2_gps_ctrl_impl(iface));
+gps_ctrl::sptr gps_ctrl::make(gps_send_fn_t send, gps_recv_fn_t recv){
+ return sptr(new gps_ctrl_impl(send, recv));
}
diff --git a/host/lib/usrp/mboard_eeprom.cpp b/host/lib/usrp/mboard_eeprom.cpp
index 863a80191..f7f4b2c68 100644
--- a/host/lib/usrp/mboard_eeprom.cpp
+++ b/host/lib/usrp/mboard_eeprom.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -97,8 +97,14 @@ static void load_n100(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
N100_EEPROM_ADDR, USRP_N100_OFFSETS["name"], NAME_MAX_LEN
));
- //empty serial correction: use the mac address
- if (mb_eeprom["serial"].empty()) mb_eeprom["serial"] = mb_eeprom["mac-addr"];
+ //Empty serial correction: use the mac address to determine serial.
+ //Older usrp2 models don't have a serial burned into EEPROM.
+ //The lower mac address bits will function as the serial number.
+ if (mb_eeprom["serial"].empty()){
+ byte_vector_t mac_addr_bytes = mac_addr_t::from_string(mb_eeprom["mac-addr"]).to_bytes();
+ unsigned serial = mac_addr_bytes.at(5) | (unsigned(mac_addr_bytes.at(4) & 0x0f) << 8);
+ mb_eeprom["serial"] = boost::lexical_cast<std::string>(serial);
+ }
}
static void store_n100(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp
index 5856d706f..02f4b216d 100644
--- a/host/lib/usrp/misc_utils.cpp
+++ b/host/lib/usrp/misc_utils.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -39,24 +39,24 @@ static gain_range_t get_codec_gain_range(wax::obj codec, const std::string &name
return codec[named_prop_t(CODEC_PROP_GAIN_RANGE, name)].as<gain_range_t>();
}
-static float get_codec_gain_i(wax::obj codec, const std::string &name){
- return codec[named_prop_t(CODEC_PROP_GAIN_I, name)].as<float>();
+static double get_codec_gain_i(wax::obj codec, const std::string &name){
+ return codec[named_prop_t(CODEC_PROP_GAIN_I, name)].as<double>();
}
-static float get_codec_gain_q(wax::obj codec, const std::string &name){
- return codec[named_prop_t(CODEC_PROP_GAIN_Q, name)].as<float>();
+static double get_codec_gain_q(wax::obj codec, const std::string &name){
+ return codec[named_prop_t(CODEC_PROP_GAIN_Q, name)].as<double>();
}
-static void set_codec_gain_both(wax::obj codec, const std::string &name, float gain){
+static void set_codec_gain_both(wax::obj codec, const std::string &name, double gain){
codec[named_prop_t(CODEC_PROP_GAIN_I, name)] = gain;
codec[named_prop_t(CODEC_PROP_GAIN_Q, name)] = gain;
}
-static void set_codec_gain_i(wax::obj codec, const std::string &name, float gain){
+static void set_codec_gain_i(wax::obj codec, const std::string &name, double gain){
codec[named_prop_t(CODEC_PROP_GAIN_I, name)] = gain;
}
-static void set_codec_gain_q(wax::obj codec, const std::string &name, float gain){
+static void set_codec_gain_q(wax::obj codec, const std::string &name, double gain){
codec[named_prop_t(CODEC_PROP_GAIN_Q, name)] = gain;
}
@@ -64,15 +64,15 @@ static void set_codec_gain_q(wax::obj codec, const std::string &name, float gain
* subdev gain group helper functions:
* do this so we dont have to bind a templated function
**********************************************************************/
-static float get_subdev_gain(wax::obj subdev, const std::string &name){
- return subdev[named_prop_t(SUBDEV_PROP_GAIN, name)].as<float>();
+static double get_subdev_gain(wax::obj subdev, const std::string &name){
+ return subdev[named_prop_t(SUBDEV_PROP_GAIN, name)].as<double>();
}
static gain_range_t get_subdev_gain_range(wax::obj subdev, const std::string &name){
return subdev[named_prop_t(SUBDEV_PROP_GAIN_RANGE, name)].as<gain_range_t>();
}
-static void set_subdev_gain(wax::obj subdev, const std::string &name, float gain){
+static void set_subdev_gain(wax::obj subdev, const std::string &name, double gain){
subdev[named_prop_t(SUBDEV_PROP_GAIN, name)] = gain;
}
diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp
index 876f1a3fc..48eec28c1 100644
--- a/host/lib/usrp/multi_usrp.cpp
+++ b/host/lib/usrp/multi_usrp.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -117,26 +117,32 @@ public:
return _mboard(0)[MBOARD_PROP_TIME_NOW].as<time_spec_t>();
}
+ time_spec_t get_time_last_pps(void){
+ return _mboard(0)[MBOARD_PROP_TIME_PPS].as<time_spec_t>();
+ }
+
void set_time_next_pps(const time_spec_t &time_spec){
for (size_t m = 0; m < get_num_mboards(); m++){
- _mboard(m)[MBOARD_PROP_TIME_NEXT_PPS] = time_spec;
+ _mboard(m)[MBOARD_PROP_TIME_PPS] = time_spec;
}
}
void set_time_unknown_pps(const time_spec_t &time_spec){
- std::cout << "Set time with unknown pps edge:" << std::endl;
- std::cout << " 1) set times next pps (race condition)" << std::endl;
- set_time_next_pps(time_spec);
- boost::this_thread::sleep(boost::posix_time::seconds(1));
-
- std::cout << " 2) catch seconds rollover at pps edge" << std::endl;
- time_t last_secs = 0, curr_secs = 0;
- while(curr_secs == last_secs){
- last_secs = curr_secs;
- curr_secs = get_time_now().get_full_secs();
+ std::cout << " 1) catch time transition at pps edge" << std::endl;
+ time_spec_t time_start = get_time_now();
+ time_spec_t time_start_last_pps = get_time_last_pps();
+ while(true){
+ if (get_time_last_pps() != time_start_last_pps) break;
+ if ((get_time_now() - time_start) > time_spec_t(1.1)){
+ throw std::runtime_error(
+ "Board 0 may not be getting a PPS signal!\n"
+ "No PPS detected within the time interval.\n"
+ "See the application notes for your device.\n"
+ );
+ }
}
- std::cout << " 3) set times next pps (synchronously)" << std::endl;
+ std::cout << " 2) set times next pps (synchronously)" << std::endl;
set_time_next_pps(time_spec);
boost::this_thread::sleep(boost::posix_time::seconds(1));
@@ -233,11 +239,11 @@ public:
return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsp(chan/rx_cpm()));
}
- void set_rx_gain(float gain, const std::string &name, size_t chan){
+ void set_rx_gain(double gain, const std::string &name, size_t chan){
return _rx_gain_group(chan)->set_value(gain, name);
}
- float get_rx_gain(const std::string &name, size_t chan){
+ double get_rx_gain(const std::string &name, size_t chan){
return _rx_gain_group(chan)->get_value(name);
}
@@ -273,8 +279,8 @@ public:
return _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as<double>();
}
- float read_rssi(size_t chan){
- return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as<float>();
+ double read_rssi(size_t chan){
+ return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as<double>();
}
dboard_iface::sptr get_rx_dboard_iface(size_t chan){
@@ -331,11 +337,11 @@ public:
return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsp(chan/tx_cpm()));
}
- void set_tx_gain(float gain, const std::string &name, size_t chan){
+ void set_tx_gain(double gain, const std::string &name, size_t chan){
return _tx_gain_group(chan)->set_value(gain, name);
}
- float get_tx_gain(const std::string &name, size_t chan){
+ double get_tx_gain(const std::string &name, size_t chan){
return _tx_gain_group(chan)->get_value(name);
}
diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp
index a0456d1f0..c37449c5f 100644
--- a/host/lib/usrp/single_usrp.cpp
+++ b/host/lib/usrp/single_usrp.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -106,12 +106,16 @@ public:
return _mboard()[MBOARD_PROP_TIME_NOW].as<time_spec_t>();
}
+ time_spec_t get_time_last_pps(void){
+ return _mboard()[MBOARD_PROP_TIME_PPS].as<time_spec_t>();
+ }
+
void set_time_now(const time_spec_t &time_spec){
_mboard()[MBOARD_PROP_TIME_NOW] = time_spec;
}
void set_time_next_pps(const time_spec_t &time_spec){
- _mboard()[MBOARD_PROP_TIME_NEXT_PPS] = time_spec;
+ _mboard()[MBOARD_PROP_TIME_PPS] = time_spec;
}
void issue_stream_cmd(const stream_cmd_t &stream_cmd){
@@ -160,11 +164,11 @@ public:
return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsp());
}
- void set_rx_gain(float gain, const std::string &name, size_t chan){
+ void set_rx_gain(double gain, const std::string &name, size_t chan){
return _rx_gain_group(chan)->set_value(gain, name);
}
- float get_rx_gain(const std::string &name, size_t chan){
+ double get_rx_gain(const std::string &name, size_t chan){
return _rx_gain_group(chan)->get_value(name);
}
@@ -200,8 +204,8 @@ public:
return _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as<double>();
}
- float read_rssi(size_t chan){
- return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as<float>();
+ double read_rssi(size_t chan){
+ return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as<double>();
}
dboard_iface::sptr get_rx_dboard_iface(size_t chan){
@@ -246,11 +250,11 @@ public:
return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsp());
}
- void set_tx_gain(float gain, const std::string &name, size_t chan){
+ void set_tx_gain(double gain, const std::string &name, size_t chan){
return _tx_gain_group(chan)->set_value(gain, name);
}
- float get_tx_gain(const std::string &name, size_t chan){
+ double get_tx_gain(const std::string &name, size_t chan){
return _tx_gain_group(chan)->get_value(name);
}
diff --git a/host/lib/usrp/subdev_spec.cpp b/host/lib/usrp/subdev_spec.cpp
index 95d2cbb12..51c88bda3 100644
--- a/host/lib/usrp/subdev_spec.cpp
+++ b/host/lib/usrp/subdev_spec.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -16,15 +16,21 @@
//
#include <uhd/usrp/subdev_spec.hpp>
-#include <uhd/utils/algorithm.hpp>
+#include <boost/algorithm/string.hpp> //for split
+#include <boost/tokenizer.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <stdexcept>
#include <sstream>
+#include <vector>
using namespace uhd;
using namespace uhd::usrp;
+#define pair_tokenizer(inp) \
+ boost::tokenizer<boost::char_separator<char> > \
+ (inp, boost::char_separator<char>(" "))
+
subdev_spec_pair_t::subdev_spec_pair_t(
const std::string &db_name, const std::string &sd_name
):
@@ -39,9 +45,9 @@ bool usrp::operator==(const subdev_spec_pair_t &lhs, const subdev_spec_pair_t &r
}
subdev_spec_t::subdev_spec_t(const std::string &markup){
- BOOST_FOREACH(const std::string &pair, std::split_string(markup)){
+ BOOST_FOREACH(const std::string &pair, pair_tokenizer(markup)){
if (pair == "") continue;
- std::vector<std::string> db_sd = std::split_string(pair, ":");
+ std::vector<std::string> db_sd; boost::split(db_sd, pair, boost::is_any_of(":"));
switch(db_sd.size()){
case 1: this->push_back(subdev_spec_pair_t("", db_sd.front())); break;
case 2: this->push_back(subdev_spec_pair_t(db_sd.front(), db_sd.back())); break;
diff --git a/host/lib/usrp/usrp1/CMakeLists.txt b/host/lib/usrp/usrp1/CMakeLists.txt
index 519e17bfa..9e50f5728 100644
--- a/host/lib/usrp/usrp1/CMakeLists.txt
+++ b/host/lib/usrp/usrp1/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -38,6 +38,7 @@ IF(ENABLE_USRP1)
${CMAKE_CURRENT_SOURCE_DIR}/dsp_impl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/io_impl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mboard_impl.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/soft_time_ctrl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/usrp1_iface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/usrp1_iface.hpp
${CMAKE_CURRENT_SOURCE_DIR}/usrp1_impl.cpp
diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp
index 18f794632..f3816b377 100644
--- a/host/lib/usrp/usrp1/codec_ctrl.cpp
+++ b/host/lib/usrp/usrp1/codec_ctrl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -35,7 +35,7 @@ using namespace uhd;
static const bool codec_debug = false;
-const gain_range_t usrp1_codec_ctrl::tx_pga_gain_range(-20, 0, float(0.1));
+const gain_range_t usrp1_codec_ctrl::tx_pga_gain_range(-20, 0, double(0.1));
const gain_range_t usrp1_codec_ctrl::rx_pga_gain_range(0, 20, 1);
/***********************************************************************
@@ -50,17 +50,18 @@ public:
~usrp1_codec_ctrl_impl(void);
//aux adc and dac control
- float read_aux_adc(aux_adc_t which);
- void write_aux_dac(aux_dac_t which, float volts);
+ double read_aux_adc(aux_adc_t which);
+ void write_aux_dac(aux_dac_t which, double volts);
//duc control
void set_duc_freq(double freq);
+ void enable_tx_digital(bool enb);
//pga gain control
- void set_tx_pga_gain(float);
- float get_tx_pga_gain(void);
- void set_rx_pga_gain(float, char);
- float get_rx_pga_gain(char);
+ void set_tx_pga_gain(double);
+ double get_tx_pga_gain(void);
+ void set_rx_pga_gain(double, char);
+ double get_rx_pga_gain(char);
//rx adc buffer control
void bypass_adc_buffers(bool bypass);
@@ -159,19 +160,19 @@ usrp1_codec_ctrl_impl::~usrp1_codec_ctrl_impl(void)
**********************************************************************/
static const int mtpgw = 255; //maximum tx pga gain word
-void usrp1_codec_ctrl_impl::set_tx_pga_gain(float gain){
+void usrp1_codec_ctrl_impl::set_tx_pga_gain(double gain){
int gain_word = int(mtpgw*(gain - tx_pga_gain_range.start())/(tx_pga_gain_range.stop() - tx_pga_gain_range.start()));
_ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, mtpgw);
this->send_reg(16);
}
-float usrp1_codec_ctrl_impl::get_tx_pga_gain(void){
+double usrp1_codec_ctrl_impl::get_tx_pga_gain(void){
return (_ad9862_regs.tx_pga_gain*(tx_pga_gain_range.stop() - tx_pga_gain_range.start())/mtpgw) + tx_pga_gain_range.start();
}
static const int mrpgw = 0x14; //maximum rx pga gain word
-void usrp1_codec_ctrl_impl::set_rx_pga_gain(float gain, char which){
+void usrp1_codec_ctrl_impl::set_rx_pga_gain(double gain, char which){
int gain_word = int(mrpgw*(gain - rx_pga_gain_range.start())/(rx_pga_gain_range.stop() - rx_pga_gain_range.start()));
gain_word = std::clip(gain_word, 0, mrpgw);
switch(which){
@@ -187,7 +188,7 @@ void usrp1_codec_ctrl_impl::set_rx_pga_gain(float gain, char which){
}
}
-float usrp1_codec_ctrl_impl::get_rx_pga_gain(char which){
+double usrp1_codec_ctrl_impl::get_rx_pga_gain(char which){
int gain_word;
switch(which){
case 'A': gain_word = _ad9862_regs.rx_pga_a; break;
@@ -200,12 +201,12 @@ float usrp1_codec_ctrl_impl::get_rx_pga_gain(char which){
/***********************************************************************
* Codec Control AUX ADC Methods
**********************************************************************/
-static float aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low)
+static double aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low)
{
- return float(((boost::uint16_t(high) << 2) | low)*3.3)/0x3ff;
+ return double(((boost::uint16_t(high) << 2) | low)*3.3)/0x3ff;
}
-float usrp1_codec_ctrl_impl::read_aux_adc(aux_adc_t which)
+double usrp1_codec_ctrl_impl::read_aux_adc(aux_adc_t which)
{
//check to see if the switch needs to be set
bool write_switch = false;
@@ -259,7 +260,7 @@ float usrp1_codec_ctrl_impl::read_aux_adc(aux_adc_t which)
/***********************************************************************
* Codec Control AUX DAC Methods
**********************************************************************/
-void usrp1_codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts)
+void usrp1_codec_ctrl_impl::write_aux_dac(aux_dac_t which, double volts)
{
//special case for aux dac d (aka sigma delta word)
if (which == AUX_DAC_D) {
@@ -421,6 +422,11 @@ void usrp1_codec_ctrl_impl::set_duc_freq(double freq)
this->send_reg(23);
}
+void usrp1_codec_ctrl_impl::enable_tx_digital(bool enb){
+ _ad9862_regs.tx_digital_pd = (enb)? 0 : 1;
+ this->send_reg(8);
+}
+
/***********************************************************************
* Codec Control ADC buffer bypass
* Disable this for AC-coupled daughterboards (TVRX)
diff --git a/host/lib/usrp/usrp1/codec_ctrl.hpp b/host/lib/usrp/usrp1/codec_ctrl.hpp
index e2e8a010d..20e4015c5 100644
--- a/host/lib/usrp/usrp1/codec_ctrl.hpp
+++ b/host/lib/usrp/usrp1/codec_ctrl.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -61,7 +61,7 @@ public:
* \param which which of the 4 adcs
* \return a value in volts
*/
- virtual float read_aux_adc(aux_adc_t which) = 0;
+ virtual double read_aux_adc(aux_adc_t which) = 0;
//! aux dac identifier constants
enum aux_dac_t{
@@ -76,23 +76,26 @@ public:
* \param which which of the 4 dacs
* \param volts the level in in volts
*/
- virtual void write_aux_dac(aux_dac_t which, float volts) = 0;
+ virtual void write_aux_dac(aux_dac_t which, double volts) = 0;
//! Set the TX PGA gain
- virtual void set_tx_pga_gain(float gain) = 0;
+ virtual void set_tx_pga_gain(double gain) = 0;
//! Get the TX PGA gain
- virtual float get_tx_pga_gain(void) = 0;
+ virtual double get_tx_pga_gain(void) = 0;
//! Set the RX PGA gain ('A' or 'B')
- virtual void set_rx_pga_gain(float gain, char which) = 0;
+ virtual void set_rx_pga_gain(double gain, char which) = 0;
//! Get the RX PGA gain ('A' or 'B')
- virtual float get_rx_pga_gain(char which) = 0;
+ virtual double get_rx_pga_gain(char which) = 0;
//! Set the TX modulator frequency
virtual void set_duc_freq(double freq) = 0;
-
+
+ //! Enable or disable the digital part of the DAC
+ virtual void enable_tx_digital(bool enb) = 0;
+
//! Enable or disable ADC buffer bypass
virtual void bypass_adc_buffers(bool bypass) = 0;
};
diff --git a/host/lib/usrp/usrp1/codec_impl.cpp b/host/lib/usrp/usrp1/codec_impl.cpp
index db53be53e..14ecd2d2e 100644
--- a/host/lib/usrp/usrp1/codec_impl.cpp
+++ b/host/lib/usrp/usrp1/codec_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -92,12 +92,12 @@ void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_
switch(key.as<codec_prop_t>()) {
case CODEC_PROP_GAIN_I:
UHD_ASSERT_THROW(key.name == adc_pga_gain_name);
- _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as<float>(), 'A');
+ _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as<double>(), 'A');
return;
case CODEC_PROP_GAIN_Q:
UHD_ASSERT_THROW(key.name == adc_pga_gain_name);
- _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as<float>(), 'B');
+ _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as<double>(), 'B');
return;
default: UHD_THROW_PROP_SET_ERROR();
@@ -151,7 +151,7 @@ void usrp1_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_
case CODEC_PROP_GAIN_I: //only one gain for I and Q
case CODEC_PROP_GAIN_Q:
UHD_ASSERT_THROW(key.name == dac_pga_gain_name);
- _codec_ctrls[dboard_slot]->set_tx_pga_gain(val.as<float>());
+ _codec_ctrls[dboard_slot]->set_tx_pga_gain(val.as<double>());
return;
default: UHD_THROW_PROP_SET_ERROR();
diff --git a/host/lib/usrp/usrp1/dboard_iface.cpp b/host/lib/usrp/usrp1/dboard_iface.cpp
index 4e47d6bf6..eec4a52db 100644
--- a/host/lib/usrp/usrp1/dboard_iface.cpp
+++ b/host/lib/usrp/usrp1/dboard_iface.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -72,8 +72,8 @@ public:
return props;
}
- void write_aux_dac(unit_t, aux_dac_t, float);
- float read_aux_adc(unit_t, aux_adc_t);
+ void write_aux_dac(unit_t, aux_dac_t, double);
+ double read_aux_adc(unit_t, aux_adc_t);
void _set_pin_ctrl(unit_t, boost::uint16_t);
void _set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);
@@ -369,7 +369,7 @@ byte_vector_t usrp1_dboard_iface::read_i2c(boost::uint8_t addr,
* Aux DAX/ADC
**********************************************************************/
void usrp1_dboard_iface::write_aux_dac(dboard_iface::unit_t,
- aux_dac_t which, float value)
+ aux_dac_t which, double value)
{
//same aux dacs for each unit
static const uhd::dict<aux_dac_t, usrp1_codec_ctrl::aux_dac_t>
@@ -382,7 +382,7 @@ void usrp1_dboard_iface::write_aux_dac(dboard_iface::unit_t,
_codec->write_aux_dac(which_to_aux_dac[which], value);
}
-float usrp1_dboard_iface::read_aux_adc(dboard_iface::unit_t unit,
+double usrp1_dboard_iface::read_aux_adc(dboard_iface::unit_t unit,
aux_adc_t which)
{
static const
diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp
index 6728d9b15..9fa1b4f72 100644
--- a/host/lib/usrp/usrp1/io_impl.cpp
+++ b/host/lib/usrp/usrp1/io_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -19,7 +19,6 @@
#include "usrp_commands.h"
#include "usrp1_impl.hpp"
#include <uhd/utils/thread_priority.hpp>
-#include <uhd/transport/convert_types.hpp>
#include <uhd/transport/bounded_buffer.hpp>
#include <boost/bind.hpp>
#include <boost/format.hpp>
@@ -92,6 +91,7 @@ struct usrp1_impl::io_impl{
void commit_send_buff(offset_send_buffer::sptr, offset_send_buffer::sptr, size_t);
void flush_send_buff(void);
bool get_send_buffs(vrt_packet_handler::managed_send_buffs_t &, double);
+ bool transmitting_enb;
};
/*!
@@ -184,6 +184,28 @@ void usrp1_impl::io_init(void){
_tx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN;
_io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transport));
+
+ _soft_time_ctrl = soft_time_ctrl::make(
+ boost::bind(&usrp1_impl::rx_stream_on_off, this, _1)
+ );
+
+ rx_stream_on_off(false);
+ tx_stream_on_off(false);
+}
+
+void usrp1_impl::rx_stream_on_off(bool enb){
+ return _iface->write_firmware_cmd(VRQ_FPGA_SET_RX_ENABLE, enb, 0, 0, 0);
+ //drain any junk in the receive transport after stop streaming command
+ while(not enb and _data_transport->get_recv_buff().get() != NULL){
+ /* NOP */
+ }
+}
+
+void usrp1_impl::tx_stream_on_off(bool enb){
+ if (not enb) _io_impl->flush_send_buff();
+ _codec_ctrls[DBOARD_SLOT_A]->enable_tx_digital(enb);
+ _codec_ctrls[DBOARD_SLOT_B]->enable_tx_digital(enb);
+ _io_impl->transmitting_enb = enb;
}
/***********************************************************************
@@ -209,6 +231,9 @@ size_t usrp1_impl::send(
const tx_metadata_t &metadata, const io_type_t &io_type,
send_mode_t send_mode, double timeout
){
+ if (_soft_time_ctrl->send_pre(metadata, timeout)) return num_samps;
+ if (not _io_impl->transmitting_enb) tx_stream_on_off(true);
+
size_t num_samps_sent = vrt_packet_handler::send(
_io_impl->packet_handler_send_state, //last state of the send handler
buffs, num_samps, //buffer to fill
@@ -222,9 +247,11 @@ size_t usrp1_impl::send(
_tx_subdev_spec.size() //num channels
);
- //Don't honor sob because it is normal to be always bursting...
- //handle eob flag (commit the buffer)
- if (metadata.end_of_burst) _io_impl->flush_send_buff();
+ //handle eob flag (commit the buffer, disable the DACs)
+ //check num samps sent to avoid flush on incomplete/timeout
+ if (metadata.end_of_burst and num_samps_sent == num_samps){
+ this->tx_stream_on_off(false);
+ }
//handle the polling for underflow conditions
_io_impl->underflow_poll_samp_count += num_samps_sent;
@@ -296,6 +323,8 @@ size_t usrp1_impl::recv(
_rx_subdev_spec.size() //num channels
);
+ _soft_time_ctrl->recv_post(metadata, num_samps_recvd);
+
//handle the polling for overflow conditions
_io_impl->overflow_poll_samp_count += num_samps_recvd;
if (_io_impl->overflow_poll_samp_count >= _rx_samps_per_poll_interval){
diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp
index 4df5ada0a..23c8f03c4 100644
--- a/host/lib/usrp/usrp1/mboard_impl.cpp
+++ b/host/lib/usrp/usrp1/mboard_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -240,19 +240,6 @@ void usrp1_impl::mboard_init(void)
}
}
-void usrp1_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd)
-{
- switch(stream_cmd.stream_mode){
- case stream_cmd_t::STREAM_MODE_START_CONTINUOUS:
- return _iface->write_firmware_cmd(VRQ_FPGA_SET_RX_ENABLE, true, 0, 0, 0);
-
- case stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS:
- return _iface->write_firmware_cmd(VRQ_FPGA_SET_RX_ENABLE, false, 0, 0, 0);
-
- default: throw std::runtime_error("unsupported stream command type for USRP1");
- }
-}
-
/***********************************************************************
* Mboard Get
**********************************************************************/
@@ -326,6 +313,10 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val)
val = _iface->mb_eeprom;
return;
+ case MBOARD_PROP_TIME_NOW:
+ val = _soft_time_ctrl->get_time();
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -348,7 +339,7 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val)
switch(key.as<mboard_prop_t>()){
case MBOARD_PROP_STREAM_CMD:
- issue_stream_cmd(val.as<stream_cmd_t>());
+ _soft_time_ctrl->issue_stream_cmd(val.as<stream_cmd_t>());
return;
case MBOARD_PROP_RX_SUBDEV_SPEC:
@@ -384,6 +375,10 @@ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val)
_iface->mb_eeprom = mboard_eeprom_t(*_iface, mboard_eeprom_t::MAP_B000);
return;
+ case MBOARD_PROP_TIME_NOW:
+ _soft_time_ctrl->set_time(val.as<time_spec_t>());
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
diff --git a/host/lib/usrp/usrp1/soft_time_ctrl.cpp b/host/lib/usrp/usrp1/soft_time_ctrl.cpp
new file mode 100644
index 000000000..4d6abe218
--- /dev/null
+++ b/host/lib/usrp/usrp1/soft_time_ctrl.cpp
@@ -0,0 +1,224 @@
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include "soft_time_ctrl.hpp"
+#include <uhd/transport/bounded_buffer.hpp>
+#include <boost/any.hpp>
+#include <boost/thread.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/date_time/local_time/local_time.hpp>
+#include <iostream>
+
+using namespace uhd;
+using namespace uhd::usrp;
+using namespace uhd::transport;
+namespace pt = boost::posix_time;
+namespace lt = boost::local_time;
+
+static const time_spec_t TWIDDLE(0.0015);
+
+/***********************************************************************
+ * Utility helper functions
+ **********************************************************************/
+
+//TODO put these in time_spec_t (maybe useful)
+
+static const double time_dur_tps = double(pt::time_duration::ticks_per_second());
+
+time_spec_t time_dur_to_time_spec(const pt::time_duration &time_dur){
+ return time_spec_t(
+ time_dur.total_seconds(),
+ long(time_dur.fractional_seconds()),
+ time_dur_tps
+ );
+}
+
+pt::time_duration time_spec_to_time_dur(const time_spec_t &time_spec){
+ return pt::time_duration(
+ 0, 0, long(time_spec.get_full_secs()),
+ time_spec.get_tick_count(time_dur_tps)
+ );
+}
+
+/***********************************************************************
+ * Soft time control implementation
+ **********************************************************************/
+class soft_time_ctrl_impl : public soft_time_ctrl{
+public:
+
+ soft_time_ctrl_impl(const cb_fcn_type &stream_on_off):
+ _nsamps_remaining(0),
+ _stream_mode(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS),
+ _cmd_queue(bounded_buffer<boost::any>::make(2)),
+ _stream_on_off(stream_on_off)
+ {
+ //synchronously spawn a new thread
+ _update_mutex.lock(); //lock mutex before spawned
+ _thread_group.create_thread(boost::bind(&soft_time_ctrl_impl::recv_cmd_dispatcher, this));
+ _update_mutex.lock(); //lock blocks until spawned
+ _update_mutex.unlock(); //unlock mutex before done
+ }
+
+ ~soft_time_ctrl_impl(void){
+ _thread_group.interrupt_all();
+ _thread_group.join_all();
+ }
+
+ /*******************************************************************
+ * Time control
+ ******************************************************************/
+ void set_time(const time_spec_t &time){
+ boost::mutex::scoped_lock lock(_update_mutex);
+ _time_offset = boost::get_system_time() - time_spec_to_time_dur(time);
+ }
+
+ time_spec_t get_time(void){
+ boost::mutex::scoped_lock lock(_update_mutex);
+ return time_now();
+ }
+
+ UHD_INLINE time_spec_t time_now(void){
+ //internal get time without scoped lock
+ return time_dur_to_time_spec(boost::get_system_time() - _time_offset);
+ }
+
+ UHD_INLINE void sleep_until_time(
+ boost::mutex::scoped_lock &lock, const time_spec_t &time
+ ){
+ boost::condition_variable cond;
+ //use a condition variable to unlock, sleep, lock
+ cond.timed_wait(lock, _time_offset + time_spec_to_time_dur(time));
+ }
+
+ /*******************************************************************
+ * Receive control
+ ******************************************************************/
+ void recv_post(rx_metadata_t &md, size_t &nsamps){
+ boost::mutex::scoped_lock lock(_update_mutex);
+
+ //load the metadata with the expected time
+ md.has_time_spec = true;
+ md.time_spec = time_now();
+
+ //none of the stuff below matters in continuous streaming mode
+ if (_stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS) return;
+
+ //When to stop streaming:
+ //The samples have been received and the stream mode is non-continuous.
+ //Rewrite the sample count to clip to the requested number of samples.
+ if (_nsamps_remaining <= nsamps){
+ nsamps = _nsamps_remaining; //set nsamps, then stop
+ md.end_of_burst = true;
+ stream_on_off(false);
+ return;
+ }
+
+ //update the consumed samples
+ _nsamps_remaining -= nsamps;
+ }
+
+ void issue_stream_cmd(const stream_cmd_t &cmd){
+ _cmd_queue->push_with_wait(cmd);
+ }
+
+ void stream_on_off(bool enb){
+ _stream_on_off(enb);
+ _nsamps_remaining = 0;
+ }
+
+ /*******************************************************************
+ * Transmit control
+ ******************************************************************/
+ bool send_pre(const tx_metadata_t &md, double &timeout){
+ if (not md.has_time_spec) return false;
+
+ boost::mutex::scoped_lock lock(_update_mutex);
+
+ time_spec_t time_at(md.time_spec - TWIDDLE);
+
+ //handle late packets
+ if (time_at < time_now()){
+ //TODO post async message
+ return true;
+ }
+
+ timeout -= (time_at - time_now()).get_real_secs();
+ sleep_until_time(lock, time_at);
+ return false;
+ }
+
+ /*******************************************************************
+ * Thread control
+ ******************************************************************/
+ void recv_cmd_handle_cmd(const stream_cmd_t &cmd){
+ boost::mutex::scoped_lock lock(_update_mutex);
+
+ //handle the stream at time by sleeping
+ if (not cmd.stream_now){
+ time_spec_t time_at(cmd.time_spec - TWIDDLE);
+ if (time_at < time_now()){
+ //TODO inject late cmd inline error
+ }
+ else{
+ sleep_until_time(lock, time_at);
+ }
+ }
+
+ //When to stop streaming:
+ //Stop streaming when the command is a stop and streaming.
+ if (cmd.stream_mode == stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS
+ and _stream_mode != stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS
+ ) stream_on_off(false);
+
+ //When to start streaming:
+ //Start streaming when the command is not a stop and not streaming.
+ if (cmd.stream_mode != stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS
+ and _stream_mode == stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS
+ ) stream_on_off(true);
+
+ //update the state
+ _nsamps_remaining += cmd.num_samps;
+ _stream_mode = cmd.stream_mode;
+ }
+
+ void recv_cmd_dispatcher(void){
+ _update_mutex.unlock();
+ try{
+ boost::any cmd;
+ while (true){
+ _cmd_queue->pop_with_wait(cmd);
+ recv_cmd_handle_cmd(boost::any_cast<stream_cmd_t>(cmd));
+ }
+ } catch(const boost::thread_interrupted &){}
+ }
+
+private:
+ boost::mutex _update_mutex;
+ size_t _nsamps_remaining;
+ stream_cmd_t::stream_mode_t _stream_mode;
+ pt::ptime _time_offset;
+ bounded_buffer<boost::any>::sptr _cmd_queue;
+ const cb_fcn_type _stream_on_off;
+ boost::thread_group _thread_group;
+};
+
+/***********************************************************************
+ * Soft time control factor
+ **********************************************************************/
+soft_time_ctrl::sptr soft_time_ctrl::make(const cb_fcn_type &stream_on_off){
+ return sptr(new soft_time_ctrl_impl(stream_on_off));
+}
diff --git a/host/lib/usrp/usrp1/soft_time_ctrl.hpp b/host/lib/usrp/usrp1/soft_time_ctrl.hpp
new file mode 100644
index 000000000..7fdac7fc8
--- /dev/null
+++ b/host/lib/usrp/usrp1/soft_time_ctrl.hpp
@@ -0,0 +1,69 @@
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_LIBUHD_USRP_USRP1_SOFT_TIME_CTRL_HPP
+#define INCLUDED_LIBUHD_USRP_USRP1_SOFT_TIME_CTRL_HPP
+
+#include <uhd/types/stream_cmd.hpp>
+#include <uhd/types/time_spec.hpp>
+#include <uhd/types/metadata.hpp>
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+
+namespace uhd{ namespace usrp{
+
+/*!
+ * The soft time control emulates some of the
+ * advanced streaming capabilities of the later USRP models.
+ * Soft time control uses the system time to emulate
+ * timed transmits, timed receive commands, device time,
+ * and inline and async error messages.
+ */
+class soft_time_ctrl : boost::noncopyable{
+public:
+ typedef boost::shared_ptr<soft_time_ctrl> sptr;
+ typedef boost::function<void(bool)> cb_fcn_type;
+
+ /*!
+ * Make a new soft time control.
+ * \param stream_on_off a function to enable/disable rx
+ * \return a new soft time control object
+ */
+ static sptr make(const cb_fcn_type &stream_on_off);
+ //TODO pass in the error queue for async msgs
+ //TODO pass in the queue for inline msgs
+
+ //! Set the current time
+ virtual void set_time(const time_spec_t &time) = 0;
+
+ //! Get the current time
+ virtual time_spec_t get_time(void) = 0;
+
+ //! Call after the internal recv function
+ virtual void recv_post(rx_metadata_t &md, size_t &nsamps) = 0;
+
+ //! Call before the internal send function
+ virtual bool send_pre(const tx_metadata_t &md, double &timeout) = 0;
+
+ //! Issue a stream command to receive
+ virtual void issue_stream_cmd(const stream_cmd_t &cmd) = 0;
+};
+
+}} //namespace
+
+#endif /* INCLUDED_LIBUHD_USRP_USRP1_SOFT_TIME_CTRL_HPP */
diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp
index 5043aed7d..09f854813 100644
--- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp
+++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp
@@ -139,13 +139,6 @@ public:
_ctrl_transport = ctrl_transport;
}
-
- ~usrp_ctrl_impl(void)
- {
- /* NOP */
- }
-
-
int usrp_load_firmware(std::string filestring, bool force)
{
const char *filename = filestring.c_str();
@@ -233,6 +226,20 @@ public:
return -1;
}
+ void usrp_init(void){
+ /* not calling because this causes junk to come at init
+ * and it does not seem to be necessary to call anyway
+ usrp_rx_enable(false);
+ usrp_rx_reset(true);
+ usrp_rx_reset(false);
+ usrp_rx_enable(true);
+ */
+
+ usrp_tx_enable(false);
+ usrp_tx_reset(true);
+ usrp_tx_reset(false);
+ usrp_tx_enable(true);
+ }
int usrp_load_fpga(std::string filestring)
{
@@ -288,7 +295,7 @@ public:
usrp_set_fpga_hash(hash);
file.close();
if (load_img_msg) std::cout << " done" << std::endl;
- return 0;
+ return 0;
}
int usrp_load_eeprom(std::string filestring)
@@ -393,6 +400,12 @@ public:
}
+ int usrp_rx_reset(bool on)
+ {
+ return usrp_control_write_cmd(VRQ_FPGA_SET_RX_RESET, on, 0);
+ }
+
+
int usrp_control_write(boost::uint8_t request,
boost::uint16_t value,
boost::uint16_t index,
diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.hpp b/host/lib/usrp/usrp1/usrp1_ctrl.hpp
index a02d9f96c..8ccfacab7 100644
--- a/host/lib/usrp/usrp1/usrp1_ctrl.hpp
+++ b/host/lib/usrp/usrp1/usrp1_ctrl.hpp
@@ -33,6 +33,9 @@ public:
*/
static sptr make(uhd::transport::usb_control::sptr ctrl_transport);
+ //! Call init after the fpga is loaded
+ virtual void usrp_init(void) = 0;
+
/*!
* Load firmware in Intel HEX Format onto device
* \param filename name of firmware file
@@ -93,20 +96,6 @@ public:
virtual int usrp_set_fpga_hash(size_t hash) = 0;
/*!
- * Set rx enable or disable
- * \param on enable or disable value
- * \return 0 on success, error code otherwise
- */
- virtual int usrp_rx_enable(bool on) = 0;
-
- /*!
- * Set rx enable or disable
- * \param on enable or disable value
- * \return 0 on success, error code otherwise
- */
- virtual int usrp_tx_enable(bool on) = 0;
-
- /*!
* Submit an IN transfer
* \param request device specific request
* \param value device specific field
diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp
index 6016b0979..c395db0b9 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.cpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -139,6 +139,7 @@ static device::sptr usrp1_make(const device_addr_t &device_addr){
usb_control::sptr ctrl_transport = usb_control::make(handle);
usrp_ctrl::sptr usrp_ctrl = usrp_ctrl::make(ctrl_transport);
usrp_ctrl->usrp_load_fpga(usrp1_fpga_image);
+ usrp_ctrl->usrp_init();
usb_zero_copy::sptr data_transport = usb_zero_copy::make(
handle, // identifier
6, // IN endpoint
@@ -192,9 +193,6 @@ usrp1_impl::usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport,
//initialize the send/recv
io_init();
- //turn on the transmitter
- _ctrl_transport->usrp_tx_enable(true);
-
//init the subdev specs
this->mboard_set(MBOARD_PROP_RX_SUBDEV_SPEC, subdev_spec_t());
this->mboard_set(MBOARD_PROP_TX_SUBDEV_SPEC, subdev_spec_t());
diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp
index ff4d40762..057725394 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.hpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
#include "usrp1_ctrl.hpp"
#include "clock_ctrl.hpp"
#include "codec_ctrl.hpp"
+#include "soft_time_ctrl.hpp"
#include <uhd/device.hpp>
#include <uhd/utils/pimpl.hpp>
#include <uhd/types/dict.hpp>
@@ -114,13 +115,17 @@ private:
const uhd::usrp::dboard_id_t &rx_dboard_id
);
+ //soft time control emulation
+ uhd::usrp::soft_time_ctrl::sptr _soft_time_ctrl;
+
//interface to ioctls and file descriptor
usrp1_iface::sptr _iface;
//handle io stuff
UHD_PIMPL_DECL(io_impl) _io_impl;
void io_init(void);
- void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd);
+ void rx_stream_on_off(bool);
+ void tx_stream_on_off(bool);
void handle_overrun(size_t);
//underrun and overrun poll intervals
diff --git a/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt
index 527669852..e8811a8fb 100644
--- a/host/lib/usrp/usrp2/CMakeLists.txt
+++ b/host/lib/usrp/usrp2/CMakeLists.txt
@@ -34,12 +34,8 @@ IF(ENABLE_USRP2)
${CMAKE_CURRENT_SOURCE_DIR}/dboard_impl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/dboard_iface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/dsp_impl.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/gps_ctrl.hpp
- ${CMAKE_CURRENT_SOURCE_DIR}/gps_ctrl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/io_impl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mboard_impl.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/serdes_ctrl.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/serdes_ctrl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/usrp2_iface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/usrp2_iface.hpp
${CMAKE_CURRENT_SOURCE_DIR}/usrp2_impl.cpp
diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp
index 428d5539b..27ccefb2b 100644
--- a/host/lib/usrp/usrp2/clock_ctrl.cpp
+++ b/host/lib/usrp/usrp2/clock_ctrl.cpp
@@ -22,10 +22,13 @@
#include <uhd/utils/assert.hpp>
#include <boost/cstdint.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/math/special_functions/round.hpp>
#include <iostream>
using namespace uhd;
+static const bool enb_test_clk = false;
+
/*!
* A usrp2 clock control specific to the ad9510 ic.
*/
@@ -66,13 +69,12 @@ public:
this->enable_external_ref(false);
this->enable_rx_dboard_clock(false);
this->enable_tx_dboard_clock(false);
+ this->enable_mimo_clock_out(false);
/* private clock enables, must be set here */
this->enable_dac_clock(true);
this->enable_adc_clock(true);
-
- /* always driving the mimo reference */
- this->enable_mimo_clock_out(true);
+ this->enable_test_clock(enb_test_clk);
}
~usrp2_clock_ctrl_impl(void){
@@ -83,6 +85,7 @@ public:
this->enable_dac_clock(false);
this->enable_adc_clock(false);
this->enable_mimo_clock_out(false);
+ this->enable_test_clock(false);
}
void enable_mimo_clock_out(bool enb){
@@ -246,6 +249,54 @@ public:
double get_master_clock_rate(void){
return 100e6;
}
+
+ void set_mimo_clock_delay(double delay) {
+ //delay_val is a 5-bit value (0-31) for fine control
+ //the equations below determine delay for a given ramp current, # of caps and fine delay register
+ //delay range:
+ //range_ns = 200*((caps+3)/i_ramp_ua)*1.3286
+ //offset (zero delay):
+ //offset_ns = 0.34 + (1600 - i_ramp_ua)*1e-4 + ((caps-1)/ramp)*6
+ //delay_ns = offset_ns + range_ns * delay / 31
+
+ int delay_val = boost::math::iround(delay/9.744e-9*31);
+
+ if(delay_val == 0) {
+ switch(clk_regs.exp) {
+ case 5:
+ _ad9510_regs.delay_control_out5 = 1;
+ break;
+ case 6:
+ _ad9510_regs.delay_control_out6 = 1;
+ break;
+ default:
+ break; //delay not supported on U2 rev 3
+ }
+ } else {
+ switch(clk_regs.exp) {
+ case 5:
+ _ad9510_regs.delay_control_out5 = 0;
+ _ad9510_regs.ramp_current_out5 = ad9510_regs_t::RAMP_CURRENT_OUT5_200UA;
+ _ad9510_regs.ramp_capacitor_out5 = ad9510_regs_t::RAMP_CAPACITOR_OUT5_4CAPS;
+ _ad9510_regs.delay_fine_adjust_out5 = delay_val;
+ this->write_reg(0x34);
+ this->write_reg(0x35);
+ this->write_reg(0x36);
+ break;
+ case 6:
+ _ad9510_regs.delay_control_out6 = 0;
+ _ad9510_regs.ramp_current_out6 = ad9510_regs_t::RAMP_CURRENT_OUT6_200UA;
+ _ad9510_regs.ramp_capacitor_out6 = ad9510_regs_t::RAMP_CAPACITOR_OUT6_4CAPS;
+ _ad9510_regs.delay_fine_adjust_out6 = delay_val;
+ this->write_reg(0x38);
+ this->write_reg(0x39);
+ this->write_reg(0x3A);
+ break;
+ default:
+ break;
+ }
+ }
+ }
private:
/*!
diff --git a/host/lib/usrp/usrp2/clock_ctrl.hpp b/host/lib/usrp/usrp2/clock_ctrl.hpp
index db6c52c83..9ccbc959e 100644
--- a/host/lib/usrp/usrp2/clock_ctrl.hpp
+++ b/host/lib/usrp/usrp2/clock_ctrl.hpp
@@ -91,8 +91,18 @@ public:
virtual void enable_test_clock(bool enb) = 0;
/*!
- * TODO other clock control api here....
+ * Enable/disable the ref clock output over the serdes cable.
+ * \param enb true to enable
+ */
+ virtual void enable_mimo_clock_out(bool enb) = 0;
+
+ /*!
+ * Set the output delay of the mimo clock
+ * Used to synchronise daisy-chained USRPs over the MIMO cable
+ * Can also be used to adjust delay for uneven reference cable lengths
+ * \param delay the clock delay in seconds
*/
+ virtual void set_mimo_clock_delay(double delay) = 0;
};
diff --git a/host/lib/usrp/usrp2/codec_ctrl.cpp b/host/lib/usrp/usrp2/codec_ctrl.cpp
index 3a34afe11..890969b5a 100644
--- a/host/lib/usrp/usrp2/codec_ctrl.cpp
+++ b/host/lib/usrp/usrp2/codec_ctrl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -124,7 +124,7 @@ public:
this->send_ad9777_reg(0x01); //set the register
}
- void set_rx_digital_gain(float gain) { //fine digital gain
+ void set_rx_digital_gain(double gain) { //fine digital gain
switch(_iface->get_rev()){
case usrp2_iface::USRP_N200:
case usrp2_iface::USRP_N210:
@@ -136,7 +136,7 @@ public:
}
}
- void set_rx_digital_fine_gain(float gain) { //gain correction
+ void set_rx_digital_fine_gain(double gain) { //gain correction
switch(_iface->get_rev()){
case usrp2_iface::USRP_N200:
case usrp2_iface::USRP_N210:
@@ -148,7 +148,7 @@ public:
}
}
- void set_rx_analog_gain(bool gain) { //turns on/off analog 3.5dB preamp
+ void set_rx_analog_gain(bool /*gain*/) { //turns on/off analog 3.5dB preamp
switch(_iface->get_rev()){
case usrp2_iface::USRP_N200:
case usrp2_iface::USRP_N210:
diff --git a/host/lib/usrp/usrp2/codec_ctrl.hpp b/host/lib/usrp/usrp2/codec_ctrl.hpp
index c8d977a1f..ca300e2b1 100644
--- a/host/lib/usrp/usrp2/codec_ctrl.hpp
+++ b/host/lib/usrp/usrp2/codec_ctrl.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -54,14 +54,14 @@ public:
* \param gain from 0-6dB
*/
- virtual void set_rx_digital_gain(float gain) = 0;
+ virtual void set_rx_digital_gain(double gain) = 0;
/*!
* Set the digital gain correction on the USRP2+ ADC (ADS62P44).
* \param gain from 0-0.5dB
*/
- virtual void set_rx_digital_fine_gain(float gain) = 0;
+ virtual void set_rx_digital_fine_gain(double gain) = 0;
};
diff --git a/host/lib/usrp/usrp2/codec_impl.cpp b/host/lib/usrp/usrp2/codec_impl.cpp
index 8299ce0a6..d7078d985 100644
--- a/host/lib/usrp/usrp2/codec_impl.cpp
+++ b/host/lib/usrp/usrp2/codec_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -28,10 +28,10 @@ using namespace uhd;
using namespace uhd::usrp;
using namespace boost::assign;
-//this only applies to USRP2P
+//this only applies to N2XX
static const uhd::dict<std::string, gain_range_t> codec_rx_gain_ranges = map_list_of
- ("digital", gain_range_t(0, float(6.0), float(0.5)))
- ("digital-fine", gain_range_t(0, float(0.5), float(0.05)));
+ ("digital", gain_range_t(0, 6.0, 0.5))
+ ("digital-fine", gain_range_t(0, 0.5, 0.05));
/***********************************************************************
@@ -111,7 +111,7 @@ void usrp2_mboard_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){
switch(key.as<codec_prop_t>()) {
case CODEC_PROP_GAIN_I:
case CODEC_PROP_GAIN_Q:
- this->rx_codec_set_gain(val.as<float>(), key.name);
+ this->rx_codec_set_gain(val.as<double>(), key.name);
return;
default: UHD_THROW_PROP_SET_ERROR();
@@ -122,7 +122,7 @@ void usrp2_mboard_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){
* Helper function to set RX codec gain
***********************************************************************/
-void usrp2_mboard_impl::rx_codec_set_gain(float gain, const std::string &name){
+void usrp2_mboard_impl::rx_codec_set_gain(double gain, const std::string &name){
assert_has(codec_rx_gain_ranges.keys(), name, "codec rx gain name");
_codec_rx_gains[name] = gain;
diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp
index 54c1c735c..c539b0058 100644
--- a/host/lib/usrp/usrp2/dboard_iface.cpp
+++ b/host/lib/usrp/usrp2/dboard_iface.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -44,8 +44,8 @@ public:
return props;
}
- void write_aux_dac(unit_t, aux_dac_t, float);
- float read_aux_adc(unit_t, aux_adc_t);
+ void write_aux_dac(unit_t, aux_dac_t, double);
+ double read_aux_adc(unit_t, aux_adc_t);
void _set_pin_ctrl(unit_t, boost::uint16_t);
void _set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);
@@ -294,7 +294,7 @@ void usrp2_dboard_iface::_write_aux_dac(unit_t unit){
);
}
-void usrp2_dboard_iface::write_aux_dac(unit_t unit, aux_dac_t which, float value){
+void usrp2_dboard_iface::write_aux_dac(unit_t unit, aux_dac_t which, double value){
_dac_regs[unit].data = boost::math::iround(4095*value/3.3);
_dac_regs[unit].cmd = ad5623_regs_t::CMD_WR_UP_DAC_CHAN_N;
@@ -317,7 +317,7 @@ void usrp2_dboard_iface::write_aux_dac(unit_t unit, aux_dac_t which, float value
this->_write_aux_dac(unit);
}
-float usrp2_dboard_iface::read_aux_adc(unit_t unit, aux_adc_t which){
+double usrp2_dboard_iface::read_aux_adc(unit_t unit, aux_adc_t which){
static const uhd::dict<unit_t, int> unit_to_spi_adc = map_list_of
(UNIT_RX, SPI_SS_RX_ADC)
(UNIT_TX, SPI_SS_TX_ADC)
@@ -346,5 +346,5 @@ float usrp2_dboard_iface::read_aux_adc(unit_t unit, aux_adc_t which){
)));
//convert to voltage and return
- return float(3.3*ad7922_regs.result/4095);
+ return 3.3*ad7922_regs.result/4095;
}
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index a9c39e650..a22f805e1 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -18,23 +18,20 @@
#ifndef INCLUDED_USRP2_FW_COMMON_H
#define INCLUDED_USRP2_FW_COMMON_H
+#include <stdint.h>
+
/*!
* Structs and constants for usrp2 communication.
* This header is shared by the firmware and host code.
* Therefore, this header may only contain valid C code.
*/
#ifdef __cplusplus
- #include <boost/cstdint.hpp>
- #define __stdint(type) boost::type
extern "C" {
-#else
- #include <stdint.h>
- #define __stdint(type) type
#endif
//fpga and firmware compatibility numbers
-#define USRP2_FPGA_COMPAT_NUM 3
-#define USRP2_FW_COMPAT_NUM 7
+#define USRP2_FPGA_COMPAT_NUM 4
+#define USRP2_FW_COMPAT_NUM 8
//used to differentiate control packets over data port
#define USRP2_INVALID_VRT_HEADER 0
@@ -42,7 +39,9 @@ extern "C" {
// udp ports for the usrp2 communication
// Dynamic and/or private ports: 49152-65535
#define USRP2_UDP_CTRL_PORT 49152
-#define USRP2_UDP_DATA_PORT 49153
+//#define USRP2_UDP_UPDATE_PORT 49154
+#define USRP2_UDP_DATA_PORT 49156
+#define USRP2_UDP_ERR0_PORT 49157
////////////////////////////////////////////////////////////////////////
// I2C addresses
@@ -104,40 +103,38 @@ typedef enum{
} usrp2_clk_edge_t;
typedef struct{
- __stdint(uint32_t) proto_ver;
- __stdint(uint32_t) id;
- __stdint(uint32_t) seq;
+ uint32_t proto_ver;
+ uint32_t id;
+ uint32_t seq;
union{
- __stdint(uint32_t) ip_addr;
+ uint32_t ip_addr;
struct {
- __stdint(uint32_t) dev;
- __stdint(uint32_t) data;
- __stdint(uint8_t) miso_edge;
- __stdint(uint8_t) mosi_edge;
- __stdint(uint8_t) num_bits;
- __stdint(uint8_t) readback;
+ uint32_t dev;
+ uint32_t data;
+ uint8_t miso_edge;
+ uint8_t mosi_edge;
+ uint8_t num_bits;
+ uint8_t readback;
} spi_args;
struct {
- __stdint(uint8_t) addr;
- __stdint(uint8_t) bytes;
- __stdint(uint8_t) data[20];
+ uint8_t addr;
+ uint8_t bytes;
+ uint8_t data[20];
} i2c_args;
struct {
- __stdint(uint32_t) addr;
- __stdint(uint32_t) data;
- __stdint(uint32_t) addrhi;
- __stdint(uint32_t) datahi;
- __stdint(uint8_t) num_bytes; //1, 2, 4, 8
+ uint32_t addr;
+ uint32_t data;
+ uint32_t _pad[2];
+ uint8_t num_bytes; //1, 2, 4
} poke_args;
struct {
- __stdint(uint8_t) dev;
- __stdint(uint8_t) bytes;
- __stdint(uint8_t) data[20];
+ uint8_t dev;
+ uint8_t bytes;
+ uint8_t data[20];
} uart_args;
} data;
} usrp2_ctrl_data_t;
-#undef __stdint
#ifdef __cplusplus
}
#endif
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index cbc0a0817..30eaecae2 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -20,12 +20,13 @@
#include "usrp2_regs.hpp"
#include <uhd/utils/byteswap.hpp>
#include <uhd/utils/thread_priority.hpp>
-#include <uhd/transport/convert_types.hpp>
-#include <uhd/transport/alignment_buffer.hpp>
+#include <uhd/transport/bounded_buffer.hpp>
#include <boost/format.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <iostream>
+#include <list>
using namespace uhd;
using namespace uhd::usrp;
@@ -108,16 +109,24 @@ private:
* - vrt packet handler states
**********************************************************************/
struct usrp2_impl::io_impl{
- typedef alignment_buffer<managed_recv_buffer::sptr, time_spec_t> alignment_buffer_type;
- io_impl(size_t num_recv_frames, size_t send_frame_size, size_t width):
+ io_impl(size_t send_frame_size, size_t width):
packet_handler_recv_state(width),
- recv_pirate_booty(alignment_buffer_type::make(num_recv_frames-3, width)),
async_msg_fifo(bounded_buffer<async_metadata_t>::make(100/*messages deep*/))
{
- for (size_t i = 0; i < width; i++) fc_mons.push_back(
- flow_control_monitor::sptr(new flow_control_monitor(usrp2_impl::sram_bytes/send_frame_size))
- );
+ for (size_t i = 0; i < width; i++){
+ fc_mons.push_back(flow_control_monitor::sptr(
+ new flow_control_monitor(usrp2_impl::sram_bytes/send_frame_size)
+ ));
+ //init empty packet infos
+ vrt::if_packet_info_t packet_info;
+ packet_info.packet_count = 0xf;
+ packet_info.has_tsi = true;
+ packet_info.tsi = 0;
+ packet_info.has_tsf = true;
+ packet_info.tsf = 0;
+ prev_infos.push_back(packet_info);
+ }
}
~io_impl(void){
@@ -126,11 +135,6 @@ struct usrp2_impl::io_impl{
recv_pirate_crew.join_all();
}
- bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, double timeout){
- boost::this_thread::disable_interruption di; //disable because the wait can throw
- return recv_pirate_booty->pop_elems_with_timed_wait(buffs, timeout);
- }
-
bool get_send_buffs(
const std::vector<zero_copy_if::sptr> &trans,
vrt_packet_handler::managed_send_buffs_t &buffs,
@@ -151,6 +155,15 @@ struct usrp2_impl::io_impl{
return true;
}
+ bool get_recv_buffs(
+ const std::vector<zero_copy_if::sptr> &xports,
+ vrt_packet_handler::managed_recv_buffs_t &buffs,
+ double timeout
+ );
+
+ //previous state for each buffer
+ std::vector<vrt::if_packet_info_t> prev_infos;
+
//flow control monitors
std::vector<flow_control_monitor::sptr> fc_mons;
@@ -162,29 +175,28 @@ struct usrp2_impl::io_impl{
void recv_pirate_loop(zero_copy_if::sptr, usrp2_mboard_impl::sptr, size_t);
boost::thread_group recv_pirate_crew;
bool recv_pirate_crew_raiding;
- alignment_buffer_type::sptr recv_pirate_booty;
bounded_buffer<async_metadata_t>::sptr async_msg_fifo;
boost::mutex spawn_mutex;
};
/***********************************************************************
* Receive Pirate Loop
- * - while raiding, loot for recv buffers
- * - put booty into the alignment buffer
+ * - while raiding, loot for message packet
+ * - update flow control condition count
+ * - put async message packets into queue
**********************************************************************/
void usrp2_impl::io_impl::recv_pirate_loop(
- zero_copy_if::sptr zc_if,
+ zero_copy_if::sptr zc_if_err0,
usrp2_mboard_impl::sptr mboard,
size_t index
){
set_thread_priority_safe();
recv_pirate_crew_raiding = true;
- size_t next_packet_seq = 0;
spawn_mutex.unlock();
while(recv_pirate_crew_raiding){
- managed_recv_buffer::sptr buff = zc_if->get_recv_buff();
+ managed_recv_buffer::sptr buff = zc_if_err0->get_recv_buff();
if (not buff.get()) continue; //ignore timeout/error buffers
try{
@@ -194,26 +206,6 @@ void usrp2_impl::io_impl::recv_pirate_loop(
const boost::uint32_t *vrt_hdr = buff->cast<const boost::uint32_t *>();
vrt::if_hdr_unpack_be(vrt_hdr, if_packet_info);
- //handle the rx data stream
- if (if_packet_info.sid == usrp2_impl::RECV_SID){
- //handle the packet count / sequence number
- if (if_packet_info.packet_count != next_packet_seq){
- //std::cerr << "S" << (if_packet_info.packet_count - next_packet_seq)%16;
- std::cerr << "O" << std::flush; //report overflow (drops in the kernel)
- }
- next_packet_seq = (if_packet_info.packet_count+1)%16;
-
- //extract the timespec and round to the nearest packet
- UHD_ASSERT_THROW(if_packet_info.has_tsi and if_packet_info.has_tsf);
- time_spec_t time(
- time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), mboard->get_master_clock_freq()
- );
-
- //push the packet into the buffer with the new time
- recv_pirate_booty->push_with_pop_on_full(buff, time, index);
- continue;
- }
-
//handle a tx async report message
if (if_packet_info.sid == usrp2_impl::ASYNC_SID and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){
@@ -253,21 +245,10 @@ void usrp2_impl::io_impl::recv_pirate_loop(
void usrp2_impl::io_init(void){
//the assumption is that all data transports should be identical
- const size_t num_recv_frames = _data_transports.front()->get_num_recv_frames();
const size_t send_frame_size = _data_transports.front()->get_send_frame_size();
//create new io impl
- _io_impl = UHD_PIMPL_MAKE(io_impl, (num_recv_frames, send_frame_size, _data_transports.size()));
-
- //TODO temporary fix for weird power up state, remove when FPGA fixed
- {
- //send an initial packet to all transports
- tx_metadata_t md; md.end_of_burst = true;
- this->send(
- std::vector<const void *>(_data_transports.size(), NULL), 0, md,
- io_type_t::COMPLEX_FLOAT32, device::SEND_MODE_ONE_PACKET, 0
- );
- }
+ _io_impl = UHD_PIMPL_MAKE(io_impl, (send_frame_size, _data_transports.size()));
//create a new pirate thread for each zc if (yarr!!)
for (size_t i = 0; i < _data_transports.size(); i++){
@@ -276,7 +257,7 @@ void usrp2_impl::io_init(void){
//spawn a new pirate to plunder the recv booty
_io_impl->recv_pirate_crew.create_thread(boost::bind(
&usrp2_impl::io_impl::recv_pirate_loop,
- _io_impl.get(), _data_transports.at(i),
+ _io_impl.get(), _err0_transports.at(i),
_mboards.at(i), i
));
//block here until the spawned thread unlocks
@@ -328,6 +309,133 @@ size_t usrp2_impl::send(
}
/***********************************************************************
+ * Alignment logic on receive
+ **********************************************************************/
+static UHD_INLINE boost::posix_time::time_duration to_time_dur(double timeout){
+ return boost::posix_time::microseconds(long(timeout*1e6));
+}
+
+static UHD_INLINE double from_time_dur(const boost::posix_time::time_duration &time_dur){
+ return 1e-6*time_dur.total_microseconds();
+}
+
+static UHD_INLINE time_spec_t extract_time_spec(
+ const vrt::if_packet_info_t &packet_info
+){
+ return time_spec_t( //assumes has_tsi and has_tsf are true
+ time_t(packet_info.tsi), size_t(packet_info.tsf),
+ 100e6 //tick rate does not have to be correct for comparison purposes
+ );
+}
+
+static UHD_INLINE void extract_packet_info(
+ managed_recv_buffer::sptr &buff,
+ vrt::if_packet_info_t &prev_info,
+ time_spec_t &time, bool &clear, bool &msg
+){
+ //extract packet info
+ vrt::if_packet_info_t next_info;
+ next_info.num_packet_words32 = buff->size()/sizeof(boost::uint32_t);
+ vrt::if_hdr_unpack_be(buff->cast<const boost::uint32_t *>(), next_info);
+
+ //handle the packet count / sequence number
+ if ((prev_info.packet_count+1)%16 != next_info.packet_count){
+ std::cerr << "O" << std::flush; //report overflow (drops in the kernel)
+ }
+
+ time = extract_time_spec(next_info);
+ clear = extract_time_spec(prev_info) > time;
+ msg = next_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA;
+ prev_info = next_info;
+}
+
+static UHD_INLINE bool handle_msg_packet(
+ vrt_packet_handler::managed_recv_buffs_t &buffs, size_t index
+){
+ for (size_t i = 0; i < buffs.size(); i++){
+ if (i == index) continue;
+ buffs[i].reset(); //set NULL
+ }
+ return true;
+}
+
+UHD_INLINE bool usrp2_impl::io_impl::get_recv_buffs(
+ const std::vector<zero_copy_if::sptr> &xports,
+ vrt_packet_handler::managed_recv_buffs_t &buffs,
+ double timeout
+){
+ if (buffs.size() == 1){
+ buffs[0] = xports[0]->get_recv_buff(timeout);
+ if (buffs[0].get() == NULL) return false;
+ bool clear, msg; time_spec_t time; //unused variables
+ //call extract_packet_info to handle printing the overflows
+ extract_packet_info(buffs[0], this->prev_infos[0], time, clear, msg);
+ return true;
+ }
+ //-------------------- begin alignment logic ---------------------//
+ boost::system_time exit_time = boost::get_system_time() + to_time_dur(timeout);
+ managed_recv_buffer::sptr buff_tmp;
+ std::list<size_t> _all_indexes, indexes_to_do;
+ for (size_t i = 0; i < buffs.size(); i++) _all_indexes.push_back(i);
+ bool clear, msg;
+ time_spec_t expected_time;
+
+ //respond to a clear by starting from scratch
+ got_clear:
+ indexes_to_do = _all_indexes;
+ clear = false;
+
+ //do an initial pop to load an initial sequence id
+ size_t index = indexes_to_do.front();
+ buff_tmp = xports[index]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time()));
+ if (buff_tmp.get() == NULL) return false;
+ extract_packet_info(buff_tmp, this->prev_infos[index], expected_time, clear, msg);
+ if (clear) goto got_clear;
+ buffs[index] = buff_tmp;
+ if (msg) return handle_msg_packet(buffs, index);
+ indexes_to_do.pop_front();
+
+ //get an aligned set of elements from the buffers:
+ while(indexes_to_do.size() != 0){
+
+ //pop an element off for this index
+ index = indexes_to_do.front();
+ buff_tmp = xports[index]->get_recv_buff(from_time_dur(exit_time - boost::get_system_time()));
+ if (buff_tmp.get() == NULL) return false;
+ time_spec_t this_time;
+ extract_packet_info(buff_tmp, this->prev_infos[index], this_time, clear, msg);
+ if (clear) goto got_clear;
+ buffs[index] = buff_tmp;
+ if (msg) return handle_msg_packet(buffs, index);
+
+ //if the sequence id matches:
+ // remove this index from the list and continue
+ if (this_time == expected_time){
+ indexes_to_do.pop_front();
+ continue;
+ }
+
+ //if the sequence id is older:
+ // continue with the same index to try again
+ else if (this_time < expected_time){
+ continue;
+ }
+
+ //if the sequence id is newer:
+ // use the new expected time for comparison
+ // add all other indexes back into the list
+ else{
+ expected_time = this_time;
+ indexes_to_do = _all_indexes;
+ indexes_to_do.remove(index);
+ continue;
+ }
+ }
+ return true;
+ //-------------------- end alignment logic -----------------------//
+}
+
+/***********************************************************************
* Receive Data
**********************************************************************/
size_t usrp2_impl::get_max_recv_samps_per_packet(void) const{
@@ -357,7 +465,7 @@ size_t usrp2_impl::recv(
io_type, _rx_otw_type, //input and output types to convert
_mboards.front()->get_master_clock_freq(), //master clock tick rate
uhd::transport::vrt::if_hdr_unpack_be,
- boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout),
+ boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _data_transports, _1, timeout),
boost::bind(&handle_overflow, _mboards, _1)
);
}
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 766ea993c..95f7013e7 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -17,6 +17,7 @@
#include "usrp2_impl.hpp"
#include "usrp2_regs.hpp"
+#include <uhd/usrp/gps_ctrl.hpp>
#include <uhd/usrp/misc_utils.hpp>
#include <uhd/usrp/dsp_utils.hpp>
#include <uhd/usrp/mboard_props.hpp>
@@ -25,11 +26,13 @@
#include <uhd/utils/algorithm.hpp>
#include <boost/bind.hpp>
#include <iostream>
-#include <boost/date_time/posix_time/posix_time.hpp>
+
+static const double mimo_clock_delay_usrp2_rev4 = 4.18e-9;
+static const double mimo_clock_delay_usrp_n2xx = 3.55e-9;
+static const size_t mimo_clock_sync_delay_cycles = 137;
using namespace uhd;
using namespace uhd::usrp;
-using namespace boost::posix_time;
/***********************************************************************
* Structors
@@ -38,8 +41,9 @@ usrp2_mboard_impl::usrp2_mboard_impl(
size_t index,
transport::udp_simple::sptr ctrl_transport,
transport::zero_copy_if::sptr data_transport,
- size_t recv_samps_per_packet,
- const device_addr_t &flow_control_hints
+ transport::zero_copy_if::sptr err0_transport,
+ const device_addr_t &device_args,
+ size_t recv_samps_per_packet
):
_index(index),
_iface(usrp2_iface::make(ctrl_transport))
@@ -47,19 +51,24 @@ usrp2_mboard_impl::usrp2_mboard_impl(
//Send a small data packet so the usrp2 knows the udp source port.
//This setup must happen before further initialization occurs
//or the async update packets will cause ICMP destination unreachable.
- transport::managed_send_buffer::sptr send_buff = data_transport->get_send_buff();
+ transport::managed_send_buffer::sptr send_buff;
static const boost::uint32_t data[2] = {
uhd::htonx(boost::uint32_t(0 /* don't care seq num */)),
uhd::htonx(boost::uint32_t(USRP2_INVALID_VRT_HEADER))
};
+ send_buff = data_transport->get_send_buff();
+ std::memcpy(send_buff->cast<void*>(), &data, sizeof(data));
+ send_buff->commit(sizeof(data));
+ send_buff = err0_transport->get_send_buff();
std::memcpy(send_buff->cast<void*>(), &data, sizeof(data));
send_buff->commit(sizeof(data));
//contruct the interfaces to mboard perifs
_clock_ctrl = usrp2_clock_ctrl::make(_iface);
_codec_ctrl = usrp2_codec_ctrl::make(_iface);
- _serdes_ctrl = usrp2_serdes_ctrl::make(_iface);
- //_gps_ctrl = usrp2_gps_ctrl::make(_iface);
+ //_gps_ctrl = gps_ctrl::make(
+ // _iface->get_gps_write_fn(),
+ // _iface->get_gps_read_fn());
//if(_gps_ctrl->gps_detected()) std::cout << "GPS time: " << _gps_ctrl->get_time() << std::endl;
@@ -98,14 +107,14 @@ usrp2_mboard_impl::usrp2_mboard_impl(
_iface->poke32(_iface->regs.tx_ctrl_policy, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET);
//setting the cycles per update (disabled by default)
- const double ups_per_sec = flow_control_hints.cast<double>("ups_per_sec", 0.0);
+ const double ups_per_sec = device_args.cast<double>("ups_per_sec", 0.0);
if (ups_per_sec > 0.0){
const size_t cycles_per_up = size_t(_clock_ctrl->get_master_clock_rate()/ups_per_sec);
_iface->poke32(_iface->regs.tx_ctrl_cycles_per_up, U2_FLAG_TX_CTRL_UP_ENB | cycles_per_up);
}
//setting the packets per update (enabled by default)
- const double ups_per_fifo = flow_control_hints.cast<double>("ups_per_fifo", 8.0);
+ const double ups_per_fifo = device_args.cast<double>("ups_per_fifo", 8.0);
if (ups_per_fifo > 0.0){
const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/data_transport->get_send_frame_size());
_iface->poke32(_iface->regs.tx_ctrl_packets_per_up, U2_FLAG_TX_CTRL_UP_ENB | packets_per_up);
@@ -118,7 +127,26 @@ usrp2_mboard_impl::usrp2_mboard_impl(
init_duc_config();
//initialize the clock configuration
- init_clock_config();
+ if (device_args.has_key("mimo_mode")){
+ if (device_args["mimo_mode"] == "master"){
+ _mimo_clocking_mode_is_master = true;
+ }
+ else if (device_args["mimo_mode"] == "slave"){
+ _mimo_clocking_mode_is_master = false;
+ }
+ else throw std::runtime_error(
+ "mimo_mode must be set to master or slave"
+ );
+ }
+ else {
+ _mimo_clocking_mode_is_master = (_iface->peek32(_iface->regs.status) & (1 << 8)) != 0;
+ }
+ std::cout << boost::format("mboard%d MIMO %s") % _index %
+ (_mimo_clocking_mode_is_master?"master":"slave") << std::endl;
+
+ //init the clock config
+ _clock_config = clock_config_t::internal();
+ update_clock_config();
//init the codec before the dboard
codec_init();
@@ -139,23 +167,12 @@ usrp2_mboard_impl::~usrp2_mboard_impl(void){
/***********************************************************************
* Helper Methods
**********************************************************************/
-void usrp2_mboard_impl::init_clock_config(void){
- //setup the clock configuration settings
- _clock_config.ref_source = clock_config_t::REF_INT;
- _clock_config.pps_source = clock_config_t::PPS_SMA;
- _clock_config.pps_polarity = clock_config_t::PPS_NEG;
-
- //update the clock config (sends a control packet)
- update_clock_config();
-}
-
void usrp2_mboard_impl::update_clock_config(void){
boost::uint32_t pps_flags = 0;
//translate pps source enums
switch(_clock_config.pps_source){
case clock_config_t::PPS_SMA: pps_flags |= U2_FLAG_TIME64_PPS_SMA; break;
- case clock_config_t::PPS_MIMO: pps_flags |= U2_FLAG_TIME64_PPS_MIMO; break;
default: throw std::runtime_error("unhandled clock configuration pps source");
}
@@ -176,7 +193,6 @@ void usrp2_mboard_impl::update_clock_config(void){
switch(_clock_config.ref_source){
case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x12); break;
case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break;
- case clock_config_t::REF_MIMO: _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); break;
default: throw std::runtime_error("unhandled clock configuration reference source");
}
_clock_ctrl->enable_external_ref(true); //USRP2P has an internal 10MHz TCXO
@@ -187,7 +203,6 @@ void usrp2_mboard_impl::update_clock_config(void){
switch(_clock_config.ref_source){
case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x10); break;
case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break;
- case clock_config_t::REF_MIMO: _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); break;
default: throw std::runtime_error("unhandled clock configuration reference source");
}
_clock_ctrl->enable_external_ref(_clock_config.ref_source != clock_config_t::REF_INT);
@@ -195,6 +210,36 @@ void usrp2_mboard_impl::update_clock_config(void){
case usrp2_iface::USRP_NXXX: break;
}
+
+ //Handle the serdes clocking based on master/slave mode:
+ // - Masters always drive the clock over serdes.
+ // - Slaves always lock to this serdes clock.
+ // - Slaves lock their time over the serdes.
+ if (_mimo_clocking_mode_is_master){
+ _clock_ctrl->enable_mimo_clock_out(true);
+ switch(_iface->get_rev()){
+ case usrp2_iface::USRP_N200:
+ case usrp2_iface::USRP_N210:
+ _clock_ctrl->set_mimo_clock_delay(mimo_clock_delay_usrp_n2xx);
+ break;
+
+ case usrp2_iface::USRP2_REV4:
+ _clock_ctrl->set_mimo_clock_delay(mimo_clock_delay_usrp2_rev4);
+ break;
+
+ default: break; //not handled
+ }
+ _iface->poke32(_iface->regs.time64_mimo_sync, 0);
+ }
+ else{
+ _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15);
+ _clock_ctrl->enable_external_ref(true);
+ _clock_ctrl->enable_mimo_clock_out(false);
+ _iface->poke32(_iface->regs.time64_mimo_sync,
+ (1 << 8) | (mimo_clock_sync_delay_cycles & 0xff)
+ );
+ }
+
}
void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){
@@ -279,15 +324,21 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){
val = _clock_config;
return;
- case MBOARD_PROP_TIME_NOW:{
- usrp2_iface::pair64 time64(
- _iface->peek64(_iface->regs.time64_secs_rb, _iface->regs.time64_ticks_rb)
- );
- val = time_spec_t(
- time64.first, time64.second, get_master_clock_freq()
- );
- }
+ case MBOARD_PROP_TIME_NOW: while(true){
+ uint32_t secs = _iface->peek32(_iface->regs.time64_secs_rb_imm);
+ uint32_t ticks = _iface->peek32(_iface->regs.time64_ticks_rb_imm);
+ if (secs != _iface->peek32(_iface->regs.time64_secs_rb_imm)) continue;
+ val = time_spec_t(secs, ticks, get_master_clock_freq());
return;
+ }
+
+ case MBOARD_PROP_TIME_PPS: while(true){
+ uint32_t secs = _iface->peek32(_iface->regs.time64_secs_rb_pps);
+ uint32_t ticks = _iface->peek32(_iface->regs.time64_ticks_rb_pps);
+ if (secs != _iface->peek32(_iface->regs.time64_secs_rb_pps)) continue;
+ val = time_spec_t(secs, ticks, get_master_clock_freq());
+ return;
+ }
case MBOARD_PROP_RX_SUBDEV_SPEC:
val = _rx_subdev_spec;
@@ -321,7 +372,7 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){
set_time_spec(val.as<time_spec_t>(), true);
return;
- case MBOARD_PROP_TIME_NEXT_PPS:
+ case MBOARD_PROP_TIME_PPS:
set_time_spec(val.as<time_spec_t>(), false);
return;
diff --git a/host/lib/usrp/usrp2/serdes_ctrl.cpp b/host/lib/usrp/usrp2/serdes_ctrl.cpp
deleted file mode 100644
index 1cda22f45..000000000
--- a/host/lib/usrp/usrp2/serdes_ctrl.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#include "serdes_ctrl.hpp"
-#include "usrp2_regs.hpp"
-
-using namespace uhd;
-
-/*!
- * A usrp2 serdes control implementation
- */
-class usrp2_serdes_ctrl_impl : public usrp2_serdes_ctrl{
-public:
- usrp2_serdes_ctrl_impl(usrp2_iface::sptr iface){
- _iface = iface;
- _iface->poke32(_iface->regs.misc_ctrl_serdes, U2_FLAG_MISC_CTRL_SERDES_ENABLE | U2_FLAG_MISC_CTRL_SERDES_RXEN);
- }
-
- ~usrp2_serdes_ctrl_impl(void){
- _iface->poke32(_iface->regs.misc_ctrl_serdes, 0); //power-down
- }
-
-private:
- usrp2_iface::sptr _iface;
-};
-
-/***********************************************************************
- * Public make function for the usrp2 serdes control
- **********************************************************************/
-usrp2_serdes_ctrl::sptr usrp2_serdes_ctrl::make(usrp2_iface::sptr iface){
- return sptr(new usrp2_serdes_ctrl_impl(iface));
-}
diff --git a/host/lib/usrp/usrp2/serdes_ctrl.hpp b/host/lib/usrp/usrp2/serdes_ctrl.hpp
deleted file mode 100644
index 3c909c531..000000000
--- a/host/lib/usrp/usrp2/serdes_ctrl.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#ifndef INCLUDED_SERDES_CTRL_HPP
-#define INCLUDED_SERDES_CTRL_HPP
-
-#include "usrp2_iface.hpp"
-#include <boost/shared_ptr.hpp>
-#include <boost/utility.hpp>
-
-class usrp2_serdes_ctrl : boost::noncopyable{
-public:
- typedef boost::shared_ptr<usrp2_serdes_ctrl> sptr;
-
- /*!
- * Make a serdes control object for the usrp2 serdes port.
- * \param _iface a pointer to the usrp2 interface object
- * \return a new serdes control object
- */
- static sptr make(usrp2_iface::sptr iface);
-
- //TODO fill me in with virtual methods
-
-};
-
-#endif /* INCLUDED_SERDES_CTRL_HPP */
diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp
index ffbe8eedb..149c5011f 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.cpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.cpp
@@ -93,20 +93,6 @@ public:
return this->peek<boost::uint16_t>(addr);
}
- pair64 peek64(boost::uint32_t addrlo, boost::uint32_t addrhi){
- //setup the out data
- usrp2_ctrl_data_t out_data;
- out_data.id = htonl(USRP2_CTRL_ID_PEEK_AT_THIS_REGISTER_FOR_ME_BRO);
- out_data.data.poke_args.addr = htonl(addrlo);
- out_data.data.poke_args.addrhi = htonl(addrhi);
- out_data.data.poke_args.num_bytes = sizeof(boost::uint64_t);
-
- //send and recv
- usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
- UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE);
- return pair64(ntohl(in_data.data.poke_args.data), ntohl(in_data.data.poke_args.datahi));
- }
-
/***********************************************************************
* SPI
**********************************************************************/
@@ -232,6 +218,14 @@ public:
}
return result;
}
+
+ gps_send_fn_t get_gps_write_fn(void) {
+ return boost::bind(&usrp2_iface_impl::write_uart, this, 2, _1); //2 is the GPS UART port on USRP2
+ }
+
+ gps_recv_fn_t get_gps_read_fn(void) {
+ return boost::bind(&usrp2_iface_impl::read_uart, this, 2); //2 is the GPS UART port on USRP2
+ }
/***********************************************************************
* Send/Recv over control
diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp
index af3ed6c9f..49cb0e6dc 100644
--- a/host/lib/usrp/usrp2/usrp2_iface.hpp
+++ b/host/lib/usrp/usrp2/usrp2_iface.hpp
@@ -24,11 +24,17 @@
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
#include <boost/cstdint.hpp>
+#include <boost/function.hpp>
#include <utility>
#include <string>
#include "fw_common.h"
#include "usrp2_regs.hpp"
+
+//TODO: kill this crap when you have the top level GPS include file
+typedef boost::function<void(std::string)> gps_send_fn_t;
+typedef boost::function<std::string(void)> gps_recv_fn_t;
+
/*!
* The usrp2 interface class:
* Provides a set of functions to implementation layer.
@@ -37,7 +43,6 @@
class usrp2_iface : public uhd::i2c_iface, boost::noncopyable{
public:
typedef boost::shared_ptr<usrp2_iface> sptr;
- typedef std::pair<boost::uint32_t, boost::uint32_t> pair64;
/*!
* Make a new usrp2 interface with the control transport.
@@ -54,14 +59,6 @@ public:
virtual usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &data) = 0;
/*!
- * Read a dual register (64 bits)
- * \param addrlo the address for the low-32 bits
- * \param addrhi the address for the high-32 bits
- * \return a pair of 32 bit integers lo, hi
- */
- virtual pair64 peek64(boost::uint32_t addrlo, boost::uint32_t addrhi) = 0;
-
- /*!
* Write a register (32 bits)
* \param addr the address
* \param data the 32bit data
@@ -109,6 +106,9 @@ public:
virtual void write_uart(boost::uint8_t dev, const std::string &buf) = 0;
virtual std::string read_uart(boost::uint8_t dev) = 0;
+
+ virtual gps_recv_fn_t get_gps_read_fn(void) = 0;
+ virtual gps_send_fn_t get_gps_write_fn(void) = 0;
//! The list of possible revision types
enum rev_type {
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index c3bbe4d65..059ddf65f 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -22,7 +22,7 @@
#include <uhd/utils/assert.hpp>
#include <uhd/utils/static.hpp>
#include <uhd/utils/warning.hpp>
-#include <uhd/utils/algorithm.hpp>
+#include <boost/algorithm/string.hpp> //for split
#include <boost/assign/list_of.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
@@ -31,6 +31,7 @@
#include <boost/bind.hpp>
#include <boost/asio.hpp> //htonl and ntohl
#include <iostream>
+#include <vector>
using namespace uhd;
using namespace uhd::usrp;
@@ -47,8 +48,8 @@ template <class T> std::string num2str(T num){
//! separate indexed device addresses into a vector of device addresses
device_addrs_t sep_indexed_dev_addrs(const device_addr_t &dev_addr){
//------------ support old deprecated way and print warning --------
- if (dev_addr.has_key("addr")){
- std::vector<std::string> addrs = std::split_string(dev_addr["addr"]);
+ if (dev_addr.has_key("addr") and not dev_addr["addr"].empty()){
+ std::vector<std::string> addrs; boost::split(addrs, dev_addr["addr"], boost::is_any_of(" "));
if (addrs.size() > 1){
device_addr_t fixed_dev_addr = dev_addr;
fixed_dev_addr.pop("addr");
@@ -197,24 +198,36 @@ static device_addrs_t usrp2_find(const device_addr_t &hint_){
* Make
**********************************************************************/
static device::sptr usrp2_make(const device_addr_t &device_addr){
-sep_indexed_dev_addrs(device_addr);
+
+ //setup the dsp transport hints (default to a large recv buff)
+ device_addr_t dsp_xport_hints = device_addr;
+ if (not dsp_xport_hints.has_key("recv_buff_size")){
+ //set to half-a-second of buffering at max rate
+ dsp_xport_hints["recv_buff_size"] = "50e6";
+ }
+
//create a ctrl and data transport for each address
std::vector<udp_simple::sptr> ctrl_transports;
std::vector<zero_copy_if::sptr> data_transports;
+ std::vector<zero_copy_if::sptr> err0_transports;
+ const device_addrs_t device_addrs = sep_indexed_dev_addrs(device_addr);
- BOOST_FOREACH(const device_addr_t &dev_addr_i, sep_indexed_dev_addrs(device_addr)){
+ BOOST_FOREACH(const device_addr_t &dev_addr_i, device_addrs){
ctrl_transports.push_back(udp_simple::make_connected(
dev_addr_i["addr"], num2str(USRP2_UDP_CTRL_PORT)
));
data_transports.push_back(udp_zero_copy::make(
- dev_addr_i["addr"], num2str(USRP2_UDP_DATA_PORT), device_addr
+ dev_addr_i["addr"], num2str(USRP2_UDP_DATA_PORT), dsp_xport_hints
+ ));
+ err0_transports.push_back(udp_zero_copy::make(
+ dev_addr_i["addr"], num2str(USRP2_UDP_ERR0_PORT), device_addr_t()
));
}
//create the usrp2 implementation guts
- return device::sptr(
- new usrp2_impl(ctrl_transports, data_transports, device_addr)
- );
+ return device::sptr(new usrp2_impl(
+ ctrl_transports, data_transports, err0_transports, device_addrs
+ ));
}
UHD_STATIC_BLOCK(register_usrp2_device){
@@ -227,9 +240,11 @@ UHD_STATIC_BLOCK(register_usrp2_device){
usrp2_impl::usrp2_impl(
std::vector<udp_simple::sptr> ctrl_transports,
std::vector<zero_copy_if::sptr> data_transports,
- const device_addr_t &flow_control_hints
+ std::vector<zero_copy_if::sptr> err0_transports,
+ const device_addrs_t &device_args
):
- _data_transports(data_transports)
+ _data_transports(data_transports),
+ _err0_transports(err0_transports)
{
//setup rx otw type
_rx_otw_type.width = 16;
@@ -244,11 +259,11 @@ usrp2_impl::usrp2_impl(
//!!!!! set the otw type here before continuing, its used below
//create a new mboard handler for each control transport
- for(size_t i = 0; i < ctrl_transports.size(); i++){
+ for(size_t i = 0; i < device_args.size(); i++){
_mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl(
i, ctrl_transports[i], data_transports[i],
- this->get_max_recv_samps_per_packet(),
- flow_control_hints
+ err0_transports[i], device_args[i],
+ this->get_max_recv_samps_per_packet()
)));
//use an empty name when there is only one mboard
std::string name = (ctrl_transports.size() > 1)? boost::lexical_cast<std::string>(i) : "";
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index aa8eb0155..ad95b2a4a 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -21,8 +21,7 @@
#include "usrp2_iface.hpp"
#include "clock_ctrl.hpp"
#include "codec_ctrl.hpp"
-#include "gps_ctrl.hpp"
-#include "serdes_ctrl.hpp"
+#include <uhd/usrp/gps_ctrl.hpp>
#include <uhd/device.hpp>
#include <uhd/utils/pimpl.hpp>
#include <uhd/types/dict.hpp>
@@ -86,8 +85,9 @@ public:
size_t index,
uhd::transport::udp_simple::sptr,
uhd::transport::zero_copy_if::sptr,
- size_t recv_samps_per_packet,
- const uhd::device_addr_t &flow_control_hints
+ uhd::transport::zero_copy_if::sptr,
+ const uhd::device_addr_t &device_args,
+ size_t recv_samps_per_packet
);
~usrp2_mboard_impl(void);
@@ -100,13 +100,13 @@ public:
private:
size_t _index;
bool _continuous_streaming;
+ bool _mimo_clocking_mode_is_master;
//interfaces
usrp2_iface::sptr _iface;
usrp2_clock_ctrl::sptr _clock_ctrl;
usrp2_codec_ctrl::sptr _codec_ctrl;
- usrp2_serdes_ctrl::sptr _serdes_ctrl;
- usrp2_gps_ctrl::sptr _gps_ctrl;
+ gps_ctrl::sptr _gps_ctrl;
//properties for this mboard
void get(const wax::obj &, wax::obj &);
@@ -120,7 +120,6 @@ private:
//methods and shadows for clock configuration
uhd::clock_config_t _clock_config;
- void init_clock_config(void);
void update_clock_config(void);
void set_time_spec(const uhd::time_spec_t &time_spec, bool now);
@@ -133,8 +132,8 @@ private:
wax_obj_proxy::sptr _rx_codec_proxy;
wax_obj_proxy::sptr _tx_codec_proxy;
- void rx_codec_set_gain(float, const std::string &);
- uhd::dict<std::string, float> _codec_rx_gains;
+ void rx_codec_set_gain(double, const std::string &);
+ uhd::dict<std::string, double> _codec_rx_gains;
//properties interface for rx dboard
void rx_dboard_get(const wax::obj &, wax::obj &);
@@ -187,12 +186,14 @@ public:
* Create a new usrp2 impl base.
* \param ctrl_transports the udp transports for control
* \param data_transports the udp transports for data
- * \param flow_control_hints optional flow control params
+ * \param err0_transports the udp transports for error
+ * \param device_args optional misc device parameters
*/
usrp2_impl(
std::vector<uhd::transport::udp_simple::sptr> ctrl_transports,
std::vector<uhd::transport::zero_copy_if::sptr> data_transports,
- const uhd::device_addr_t &flow_control_hints
+ std::vector<uhd::transport::zero_copy_if::sptr> err0_transports,
+ const uhd::device_addrs_t &device_args
);
~usrp2_impl(void);
@@ -223,6 +224,7 @@ private:
//io impl methods and members
std::vector<uhd::transport::zero_copy_if::sptr> _data_transports;
+ std::vector<uhd::transport::zero_copy_if::sptr> _err0_transports;
uhd::otw_type_t _rx_otw_type, _tx_otw_type;
UHD_PIMPL_DECL(io_impl) _io_impl;
void io_init(void);
diff --git a/host/lib/usrp/usrp2/usrp2_regs.cpp b/host/lib/usrp/usrp2/usrp2_regs.cpp
index dd0433816..84907c32e 100644
--- a/host/lib/usrp/usrp2/usrp2_regs.cpp
+++ b/host/lib/usrp/usrp2/usrp2_regs.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -57,9 +57,13 @@ usrp2_regs_t usrp2_get_regs(bool use_n2xx_map) {
x.time64_flags = sr_addr(misc_output_base, x.sr_time64 + 2);
x.time64_imm = sr_addr(misc_output_base, x.sr_time64 + 3);
x.time64_tps = sr_addr(misc_output_base, x.sr_time64 + 4);
- x.time64_secs_rb = bp_base + 4*10;
- x.time64_ticks_rb = bp_base + 4*11;
+ x.time64_mimo_sync = sr_addr(misc_output_base, x.sr_time64 + 5);
+ x.status = bp_base + 4*8;
+ x.time64_secs_rb_imm = bp_base + 4*10;
+ x.time64_ticks_rb_imm = bp_base + 4*11;
x.compat_num_rb = bp_base + 4*12;
+ x.time64_secs_rb_pps = bp_base + 4*14;
+ x.time64_ticks_rb_pps = bp_base + 4*15;
x.dsp_tx_freq = sr_addr(misc_output_base, x.sr_tx_dsp + 0);
x.dsp_tx_scale_iq = sr_addr(misc_output_base, x.sr_tx_dsp + 1);
x.dsp_tx_interp_rate = sr_addr(misc_output_base, x.sr_tx_dsp + 2);
diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp
index 9936d634a..977b342cb 100644
--- a/host/lib/usrp/usrp2/usrp2_regs.hpp
+++ b/host/lib/usrp/usrp2/usrp2_regs.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -25,10 +25,10 @@
#define USRP2_ATR_BASE 0xE400
#define USRP2_BP_STATUS_BASE 0xCC00
-#define USRP2P_MISC_OUTPUT_BASE 0x2000
-#define USRP2P_GPIO_BASE 0x3200
-#define USRP2P_ATR_BASE 0x3800
-#define USRP2P_BP_STATUS_BASE 0x3300
+#define USRP2P_MISC_OUTPUT_BASE 0x5000
+#define USRP2P_GPIO_BASE 0x6200
+#define USRP2P_ATR_BASE 0x6800
+#define USRP2P_BP_STATUS_BASE 0x6300
typedef struct {
int sr_misc;
@@ -57,8 +57,12 @@ typedef struct {
int time64_flags; // flags -- see chart below
int time64_imm; // set immediate (0=latch on next pps, 1=latch immediate, default=0)
int time64_tps; // ticks per second rollover count
- int time64_secs_rb;
- int time64_ticks_rb;
+ int time64_mimo_sync;
+ int status;
+ int time64_secs_rb_imm;
+ int time64_ticks_rb_imm;
+ int time64_secs_rb_pps;
+ int time64_ticks_rb_pps;
int compat_num_rb;
int dsp_tx_freq;
int dsp_tx_scale_iq;
diff --git a/host/lib/usrp/usrp_e100/codec_ctrl.cpp b/host/lib/usrp/usrp_e100/codec_ctrl.cpp
index 18d9daca0..b33c8ae65 100644
--- a/host/lib/usrp/usrp_e100/codec_ctrl.cpp
+++ b/host/lib/usrp/usrp_e100/codec_ctrl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -31,7 +31,7 @@ using namespace uhd;
static const bool codec_debug = false;
-const gain_range_t usrp_e100_codec_ctrl::tx_pga_gain_range(-20, 0, float(0.1));
+const gain_range_t usrp_e100_codec_ctrl::tx_pga_gain_range(-20, 0, double(0.1));
const gain_range_t usrp_e100_codec_ctrl::rx_pga_gain_range(0, 20, 1);
/***********************************************************************
@@ -44,14 +44,14 @@ public:
~usrp_e100_codec_ctrl_impl(void);
//aux adc and dac control
- float read_aux_adc(aux_adc_t which);
- void write_aux_dac(aux_dac_t which, float volts);
+ double read_aux_adc(aux_adc_t which);
+ void write_aux_dac(aux_dac_t which, double volts);
//pga gain control
- void set_tx_pga_gain(float);
- float get_tx_pga_gain(void);
- void set_rx_pga_gain(float, char);
- float get_rx_pga_gain(char);
+ void set_tx_pga_gain(double);
+ double get_tx_pga_gain(void);
+ void set_rx_pga_gain(double, char);
+ double get_rx_pga_gain(char);
private:
usrp_e100_iface::sptr _iface;
@@ -135,19 +135,19 @@ usrp_e100_codec_ctrl_impl::~usrp_e100_codec_ctrl_impl(void){
**********************************************************************/
static const int mtpgw = 255; //maximum tx pga gain word
-void usrp_e100_codec_ctrl_impl::set_tx_pga_gain(float gain){
+void usrp_e100_codec_ctrl_impl::set_tx_pga_gain(double gain){
int gain_word = int(mtpgw*(gain - tx_pga_gain_range.start())/(tx_pga_gain_range.stop() - tx_pga_gain_range.start()));
_ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, mtpgw);
this->send_reg(16);
}
-float usrp_e100_codec_ctrl_impl::get_tx_pga_gain(void){
+double usrp_e100_codec_ctrl_impl::get_tx_pga_gain(void){
return (_ad9862_regs.tx_pga_gain*(tx_pga_gain_range.stop() - tx_pga_gain_range.start())/mtpgw) + tx_pga_gain_range.start();
}
static const int mrpgw = 0x14; //maximum rx pga gain word
-void usrp_e100_codec_ctrl_impl::set_rx_pga_gain(float gain, char which){
+void usrp_e100_codec_ctrl_impl::set_rx_pga_gain(double gain, char which){
int gain_word = int(mrpgw*(gain - rx_pga_gain_range.start())/(rx_pga_gain_range.stop() - rx_pga_gain_range.start()));
gain_word = std::clip(gain_word, 0, mrpgw);
switch(which){
@@ -163,7 +163,7 @@ void usrp_e100_codec_ctrl_impl::set_rx_pga_gain(float gain, char which){
}
}
-float usrp_e100_codec_ctrl_impl::get_rx_pga_gain(char which){
+double usrp_e100_codec_ctrl_impl::get_rx_pga_gain(char which){
int gain_word;
switch(which){
case 'A': gain_word = _ad9862_regs.rx_pga_a; break;
@@ -176,11 +176,11 @@ float usrp_e100_codec_ctrl_impl::get_rx_pga_gain(char which){
/***********************************************************************
* Codec Control AUX ADC Methods
**********************************************************************/
-static float aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low){
- return float((boost::uint16_t(high) << 2) | low)*3.3/0x3ff;
+static double aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low){
+ return double((boost::uint16_t(high) << 2) | low)*3.3/0x3ff;
}
-float usrp_e100_codec_ctrl_impl::read_aux_adc(aux_adc_t which){
+double usrp_e100_codec_ctrl_impl::read_aux_adc(aux_adc_t which){
//check to see if the switch needs to be set
bool write_switch = false;
switch(which){
@@ -233,7 +233,7 @@ float usrp_e100_codec_ctrl_impl::read_aux_adc(aux_adc_t which){
/***********************************************************************
* Codec Control AUX DAC Methods
**********************************************************************/
-void usrp_e100_codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts){
+void usrp_e100_codec_ctrl_impl::write_aux_dac(aux_dac_t which, double volts){
//special case for aux dac d (aka sigma delta word)
if (which == AUX_DAC_D){
boost::uint16_t dac_word = std::clip(boost::math::iround(volts*0xfff/3.3), 0, 0xfff);
diff --git a/host/lib/usrp/usrp_e100/codec_ctrl.hpp b/host/lib/usrp/usrp_e100/codec_ctrl.hpp
index 74ce9bd9a..05d7aab38 100644
--- a/host/lib/usrp/usrp_e100/codec_ctrl.hpp
+++ b/host/lib/usrp/usrp_e100/codec_ctrl.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -57,7 +57,7 @@ public:
* \param which which of the 4 adcs
* \return a value in volts
*/
- virtual float read_aux_adc(aux_adc_t which) = 0;
+ virtual double read_aux_adc(aux_adc_t which) = 0;
//! aux dac identifier constants
enum aux_dac_t{
@@ -72,19 +72,19 @@ public:
* \param which which of the 4 dacs
* \param volts the level in in volts
*/
- virtual void write_aux_dac(aux_dac_t which, float volts) = 0;
+ virtual void write_aux_dac(aux_dac_t which, double volts) = 0;
//! Set the TX PGA gain
- virtual void set_tx_pga_gain(float gain) = 0;
+ virtual void set_tx_pga_gain(double gain) = 0;
//! Get the TX PGA gain
- virtual float get_tx_pga_gain(void) = 0;
+ virtual double get_tx_pga_gain(void) = 0;
//! Set the RX PGA gain ('A' or 'B')
- virtual void set_rx_pga_gain(float gain, char which) = 0;
+ virtual void set_rx_pga_gain(double gain, char which) = 0;
//! Get the RX PGA gain ('A' or 'B')
- virtual float get_rx_pga_gain(char which) = 0;
+ virtual double get_rx_pga_gain(char which) = 0;
};
#endif /* INCLUDED_USRP_E100_CODEC_CTRL_HPP */
diff --git a/host/lib/usrp/usrp_e100/codec_impl.cpp b/host/lib/usrp/usrp_e100/codec_impl.cpp
index 6fd44bad3..0d91fb42c 100644
--- a/host/lib/usrp/usrp_e100/codec_impl.cpp
+++ b/host/lib/usrp/usrp_e100/codec_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -86,12 +86,12 @@ void usrp_e100_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){
switch(key.as<codec_prop_t>()){
case CODEC_PROP_GAIN_I:
UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name);
- _codec_ctrl->set_rx_pga_gain(val.as<float>(), 'A');
+ _codec_ctrl->set_rx_pga_gain(val.as<double>(), 'A');
return;
case CODEC_PROP_GAIN_Q:
UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name);
- _codec_ctrl->set_rx_pga_gain(val.as<float>(), 'B');
+ _codec_ctrl->set_rx_pga_gain(val.as<double>(), 'B');
return;
default: UHD_THROW_PROP_SET_ERROR();
@@ -141,7 +141,7 @@ void usrp_e100_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val){
case CODEC_PROP_GAIN_I: //only one gain for I and Q
case CODEC_PROP_GAIN_Q:
UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name);
- _codec_ctrl->set_tx_pga_gain(val.as<float>());
+ _codec_ctrl->set_tx_pga_gain(val.as<double>());
return;
default: UHD_THROW_PROP_SET_ERROR();
diff --git a/host/lib/usrp/usrp_e100/dboard_iface.cpp b/host/lib/usrp/usrp_e100/dboard_iface.cpp
index a5032f86f..e4c3856c9 100644
--- a/host/lib/usrp/usrp_e100/dboard_iface.cpp
+++ b/host/lib/usrp/usrp_e100/dboard_iface.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -60,8 +60,8 @@ public:
return props;
}
- void write_aux_dac(unit_t, aux_dac_t, float);
- float read_aux_adc(unit_t, aux_adc_t);
+ void write_aux_dac(unit_t, aux_dac_t, double);
+ double read_aux_adc(unit_t, aux_adc_t);
void _set_pin_ctrl(unit_t, boost::uint16_t);
void _set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);
@@ -270,7 +270,7 @@ byte_vector_t usrp_e100_dboard_iface::read_i2c(boost::uint8_t addr, size_t num_b
/***********************************************************************
* Aux DAX/ADC
**********************************************************************/
-void usrp_e100_dboard_iface::write_aux_dac(dboard_iface::unit_t, aux_dac_t which, float value){
+void usrp_e100_dboard_iface::write_aux_dac(dboard_iface::unit_t, aux_dac_t which, double value){
//same aux dacs for each unit
static const uhd::dict<aux_dac_t, usrp_e100_codec_ctrl::aux_dac_t> which_to_aux_dac = map_list_of
(AUX_DAC_A, usrp_e100_codec_ctrl::AUX_DAC_A)
@@ -281,7 +281,7 @@ void usrp_e100_dboard_iface::write_aux_dac(dboard_iface::unit_t, aux_dac_t which
_codec->write_aux_dac(which_to_aux_dac[which], value);
}
-float usrp_e100_dboard_iface::read_aux_adc(dboard_iface::unit_t unit, aux_adc_t which){
+double usrp_e100_dboard_iface::read_aux_adc(dboard_iface::unit_t unit, aux_adc_t which){
static const uhd::dict<
unit_t, uhd::dict<aux_adc_t, usrp_e100_codec_ctrl::aux_adc_t>
> unit_to_which_to_aux_adc = map_list_of
diff --git a/host/lib/usrp/usrp_e100/dsp_impl.cpp b/host/lib/usrp/usrp_e100/dsp_impl.cpp
index 43a3bd3be..7d358a607 100644
--- a/host/lib/usrp/usrp_e100/dsp_impl.cpp
+++ b/host/lib/usrp/usrp_e100/dsp_impl.cpp
@@ -38,7 +38,7 @@ void usrp_e100_impl::rx_ddc_init(void){
//initial config and update
rx_ddc_set(DSP_PROP_FREQ_SHIFT, double(0));
- rx_ddc_set(DSP_PROP_HOST_RATE, double(64e6/10));
+ rx_ddc_set(DSP_PROP_HOST_RATE, double(16e6));
}
/***********************************************************************
@@ -121,7 +121,7 @@ void usrp_e100_impl::tx_duc_init(void){
//initial config and update
tx_duc_set(DSP_PROP_FREQ_SHIFT, double(0));
- tx_duc_set(DSP_PROP_HOST_RATE, double(64e6/10));
+ tx_duc_set(DSP_PROP_HOST_RATE, double(16e6));
}
/***********************************************************************
diff --git a/host/lib/usrp/usrp_e100/mboard_impl.cpp b/host/lib/usrp/usrp_e100/mboard_impl.cpp
index fe26cd63d..f52d2e6fb 100644
--- a/host/lib/usrp/usrp_e100/mboard_impl.cpp
+++ b/host/lib/usrp/usrp_e100/mboard_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -36,11 +36,13 @@ void usrp_e100_impl::mboard_init(void){
boost::bind(&usrp_e100_impl::mboard_set, this, _1, _2)
);
- //init the clock config
- _clock_config.ref_source = clock_config_t::REF_AUTO;
- _clock_config.pps_source = clock_config_t::PPS_SMA;
- _clock_config.pps_polarity = clock_config_t::PPS_NEG;
+ //set the ticks per seconds into the vita time control
+ _iface->poke32(UE_REG_TIME64_TPS,
+ boost::uint32_t(_clock_ctrl->get_fpga_clock_rate())
+ );
+ //init the clock config
+ _clock_config = clock_config_t::internal();
update_clock_config();
}
@@ -134,6 +136,22 @@ void usrp_e100_impl::mboard_get(const wax::obj &key_, wax::obj &val){
val = _iface->mb_eeprom;
return;
+ case MBOARD_PROP_TIME_NOW: while(true){
+ uint32_t secs = _iface->peek32(UE_REG_RB_TIME_NOW_SECS);
+ uint32_t ticks = _iface->peek32(UE_REG_RB_TIME_NOW_TICKS);
+ if (secs != _iface->peek32(UE_REG_RB_TIME_NOW_SECS)) continue;
+ val = time_spec_t(secs, ticks, _clock_ctrl->get_fpga_clock_rate());
+ return;
+ }
+
+ case MBOARD_PROP_TIME_PPS: while(true){
+ uint32_t secs = _iface->peek32(UE_REG_RB_TIME_PPS_SECS);
+ uint32_t ticks = _iface->peek32(UE_REG_RB_TIME_PPS_TICKS);
+ if (secs != _iface->peek32(UE_REG_RB_TIME_PPS_SECS)) continue;
+ val = time_spec_t(secs, ticks, _clock_ctrl->get_fpga_clock_rate());
+ return;
+ }
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -150,7 +168,7 @@ void usrp_e100_impl::mboard_set(const wax::obj &key, const wax::obj &val){
return;
case MBOARD_PROP_TIME_NOW:
- case MBOARD_PROP_TIME_NEXT_PPS:{
+ case MBOARD_PROP_TIME_PPS:{
time_spec_t time_spec = val.as<time_spec_t>();
_iface->poke32(UE_REG_TIME64_TICKS, time_spec.get_tick_count(_clock_ctrl->get_fpga_clock_rate()));
boost::uint32_t imm_flags = (key.as<mboard_prop_t>() == MBOARD_PROP_TIME_NOW)? 1 : 0;
diff --git a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp
index de158ea5e..864e82099 100644
--- a/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp
+++ b/host/lib/usrp/usrp_e100/usrp_e100_impl.hpp
@@ -30,7 +30,7 @@
#ifndef INCLUDED_USRP_E100_IMPL_HPP
#define INCLUDED_USRP_E100_IMPL_HPP
-static const boost::uint16_t USRP_E_COMPAT_NUM = 0x02;
+static const boost::uint16_t USRP_E_COMPAT_NUM = 0x03;
//! load an fpga image from a bin file into the usrp-e fpga
extern void usrp_e100_load_fpga(const std::string &bin_file);
diff --git a/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp b/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp
index 625fb2c35..a57fe5171 100644
--- a/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp
+++ b/host/lib/usrp/usrp_e100/usrp_e100_regs.hpp
@@ -114,6 +114,16 @@
#define UE_REG_ATR_FULL_RXSIDE UE_REG_ATR_BASE + 12
#define UE_REG_ATR_FULL_TXSIDE UE_REG_ATR_BASE + 14
+///////////////////////////////////////////////////
+// Slave 7 -- Readback Mux 32
+
+#define UE_REG_RB_MUX_32_BASE UE_REG_SLAVE(7)
+
+#define UE_REG_RB_TIME_NOW_SECS UE_REG_RB_MUX_32_BASE + 0
+#define UE_REG_RB_TIME_NOW_TICKS UE_REG_RB_MUX_32_BASE + 4
+#define UE_REG_RB_TIME_PPS_SECS UE_REG_RB_MUX_32_BASE + 8
+#define UE_REG_RB_TIME_PPS_TICKS UE_REG_RB_MUX_32_BASE + 12
+
/////////////////////////////////////////////////
// DSP RX Regs
////////////////////////////////////////////////
diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt
index 60df24eef..5fa5b4d6d 100644
--- a/host/lib/utils/CMakeLists.txt
+++ b/host/lib/utils/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -87,6 +87,7 @@ LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/load_modules.cpp
${CMAKE_CURRENT_SOURCE_DIR}/paths.cpp
${CMAKE_CURRENT_SOURCE_DIR}/props.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/static.cpp
${CMAKE_CURRENT_SOURCE_DIR}/thread_priority.cpp
${CMAKE_CURRENT_SOURCE_DIR}/warning.cpp
)
diff --git a/host/lib/utils/gain_group.cpp b/host/lib/utils/gain_group.cpp
index 11bbb8c0a..07aa21115 100644
--- a/host/lib/utils/gain_group.cpp
+++ b/host/lib/utils/gain_group.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -39,7 +39,7 @@ static bool compare_by_step_size(
* Get a multiple of step with the following relation:
* result = step*floor(num/step)
*
- * Due to small floating-point inaccuracies:
+ * Due to small doubleing-point inaccuracies:
* num = n*step + e, where e is a small inaccuracy.
* When e is negative, floor would yeild (n-1)*step,
* despite that n*step is really the desired result.
@@ -66,7 +66,7 @@ public:
gain_range_t get_range(const std::string &name){
if (not name.empty()) return _name_to_fcns[name].get_range();
- float overall_min = 0, overall_max = 0, overall_step = 0;
+ double overall_min = 0, overall_max = 0, overall_step = 0;
BOOST_FOREACH(const gain_fcns_t &fcns, get_all_fcns()){
const gain_range_t range = fcns.get_range();
overall_min += range.start();
@@ -78,33 +78,33 @@ public:
return gain_range_t(overall_min, overall_max, overall_step);
}
- float get_value(const std::string &name){
+ double get_value(const std::string &name){
if (not name.empty()) return _name_to_fcns[name].get_value();
- float overall_gain = 0;
+ double overall_gain = 0;
BOOST_FOREACH(const gain_fcns_t &fcns, get_all_fcns()){
overall_gain += fcns.get_value();
}
return overall_gain;
}
- void set_value(float gain, const std::string &name){
+ void set_value(double gain, const std::string &name){
if (not name.empty()) return _name_to_fcns[name].set_value(gain);
std::vector<gain_fcns_t> all_fcns = get_all_fcns();
if (all_fcns.size() == 0) return; //nothing to set!
//get the max step size among the gains
- float max_step = 0;
+ double max_step = 0;
BOOST_FOREACH(const gain_fcns_t &fcns, all_fcns){
max_step = std::max(max_step, fcns.get_range().step());
}
//create gain bucket to distribute power
- std::vector<float> gain_bucket;
+ std::vector<double> gain_bucket;
//distribute power according to priority (round to max step)
- float gain_left_to_distribute = gain;
+ double gain_left_to_distribute = gain;
BOOST_FOREACH(const gain_fcns_t &fcns, all_fcns){
const gain_range_t range = fcns.get_range();
gain_bucket.push_back(floor_step(std::clip(
@@ -131,7 +131,7 @@ public:
//fill in the largest step sizes first that are less than the remainder
BOOST_FOREACH(size_t i, indexes_step_size_dec){
const gain_range_t range = all_fcns.at(i).get_range();
- float additional_gain = floor_step(std::clip(
+ double additional_gain = floor_step(std::clip(
gain_bucket.at(i) + gain_left_to_distribute, range.start(), range.stop()
), range.step()) - gain_bucket.at(i);
gain_bucket.at(i) += additional_gain;
diff --git a/host/lib/utils/paths.cpp b/host/lib/utils/paths.cpp
index 9e9525caf..93d15d290 100644
--- a/host/lib/utils/paths.cpp
+++ b/host/lib/utils/paths.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@
#include "constants.hpp"
#include <uhd/config.hpp>
-#include <uhd/utils/algorithm.hpp>
+#include <boost/tokenizer.hpp>
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
@@ -38,6 +38,10 @@ namespace fs = boost::filesystem;
static const std::string env_path_sep = ":";
#endif /*UHD_PLATFORM_WIN32*/
+#define path_tokenizer(inp) \
+ boost::tokenizer<boost::char_separator<char> > \
+ (inp, boost::char_separator<char>(env_path_sep.c_str()))
+
/***********************************************************************
* Get a list of paths for an environment variable
**********************************************************************/
@@ -60,7 +64,7 @@ static std::vector<fs::path> get_env_paths(const std::string &var_name){
//convert to filesystem path, filter blank paths
std::vector<fs::path> paths;
- BOOST_FOREACH(const std::string &path_string, std::split_string(var_value, env_path_sep)){
+ BOOST_FOREACH(const std::string &path_string, path_tokenizer(var_value)){
if (path_string.empty()) continue;
paths.push_back(fs::system_complete(path_string));
}
diff --git a/host/lib/transport/msvc/stdint.h b/host/lib/utils/static.cpp
index b3eb61aae..a0dea3372 100644
--- a/host/lib/transport/msvc/stdint.h
+++ b/host/lib/utils/static.cpp
@@ -1,35 +1,32 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#ifndef INCLUDED_LIBUHD_TRANSPORT_STDINT_H
-#define INCLUDED_LIBUHD_TRANSPORT_STDINT_H
-
-#include <boost/cstdint.hpp>
-
-//provide a stdint implementation for libusb
-
-typedef boost::uint64_t uint64_t;
-typedef boost::uint32_t uint32_t;
-typedef boost::uint16_t uint16_t;
-typedef boost::uint8_t uint8_t;
-
-typedef boost::int64_t int64_t;
-typedef boost::int32_t int32_t;
-typedef boost::int16_t int16_t;
-typedef boost::int8_t int8_t;
-
-#endif /* INCLUDED_LIBUHD_TRANSPORT_STDINT_H */
+//
+// Copyright 2011 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/static.hpp>
+#include <stdexcept>
+#include <iostream>
+_uhd_static_fixture::_uhd_static_fixture(void (*fcn)(void), const char *name){
+ try{
+ fcn();
+ }
+ catch(const std::exception &e){
+ std::cerr << "Exception in static block " << name << std::endl;
+ std::cerr << " " << e.what() << std::endl;
+ }
+ catch(...){
+ std::cerr << "Exception in static block " << name << std::endl;
+ }
+}
diff --git a/host/lib/utils/warning.cpp b/host/lib/utils/warning.cpp
index 05be7ae4d..bc4c79b6e 100644
--- a/host/lib/utils/warning.cpp
+++ b/host/lib/utils/warning.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
//
#include <uhd/utils/warning.hpp>
-#include <uhd/utils/algorithm.hpp>
+#include <boost/tokenizer.hpp>
#include <uhd/utils/static.hpp>
#include <uhd/types/dict.hpp>
#include <boost/foreach.hpp>
@@ -27,6 +27,10 @@
using namespace uhd;
+#define tokenizer(inp, sep) \
+ boost::tokenizer<boost::char_separator<char> > \
+ (inp, boost::char_separator<char>(sep))
+
/***********************************************************************
* Registry implementation
**********************************************************************/
@@ -52,7 +56,7 @@ void warning::post(const std::string &msg){
//format the warning message
ss << std::endl << "Warning:" << std::endl;
- BOOST_FOREACH(const std::string &line, std::split_string(msg, "\n")){
+ BOOST_FOREACH(const std::string &line, tokenizer(msg, "\n")){
ss << " " << line << std::endl;
}
diff --git a/host/msvc/inttypes.h b/host/msvc/inttypes.h
new file mode 100644
index 000000000..1c2baa82e
--- /dev/null
+++ b/host/msvc/inttypes.h
@@ -0,0 +1,301 @@
+// ISO C9x compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+// Copyright (c) 2006 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. The name of the author may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include <stdint.h>
+
+// 7.8 Format conversion of integer types
+
+typedef struct {
+ intmax_t quot;
+ intmax_t rem;
+} imaxdiv_t;
+
+// 7.8.1 Macros for format specifiers
+
+// The fprintf macros for signed integers are:
+#define PRId8 "d"
+#define PRIi8 "i"
+#define PRIdLEAST8 "d"
+#define PRIiLEAST8 "i"
+#define PRIdFAST8 "d"
+#define PRIiFAST8 "i"
+
+#define PRId16 "hd"
+#define PRIi16 "hi"
+#define PRIdLEAST16 "hd"
+#define PRIiLEAST16 "hi"
+#define PRIdFAST16 "hd"
+#define PRIiFAST16 "hi"
+
+#define PRId32 "I32d"
+#define PRIi32 "I32i"
+#define PRIdLEAST32 "I32d"
+#define PRIiLEAST32 "I32i"
+#define PRIdFAST32 "I32d"
+#define PRIiFAST32 "I32i"
+
+#define PRId64 "I64d"
+#define PRIi64 "I64i"
+#define PRIdLEAST64 "I64d"
+#define PRIiLEAST64 "I64i"
+#define PRIdFAST64 "I64d"
+#define PRIiFAST64 "I64i"
+
+#define PRIdMAX "I64d"
+#define PRIiMAX "I64i"
+
+#define PRIdPTR "Id"
+#define PRIiPTR "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8 "o"
+#define PRIu8 "u"
+#define PRIx8 "x"
+#define PRIX8 "X"
+#define PRIoLEAST8 "o"
+#define PRIuLEAST8 "u"
+#define PRIxLEAST8 "x"
+#define PRIXLEAST8 "X"
+#define PRIoFAST8 "o"
+#define PRIuFAST8 "u"
+#define PRIxFAST8 "x"
+#define PRIXFAST8 "X"
+
+#define PRIo16 "ho"
+#define PRIu16 "hu"
+#define PRIx16 "hx"
+#define PRIX16 "hX"
+#define PRIoLEAST16 "ho"
+#define PRIuLEAST16 "hu"
+#define PRIxLEAST16 "hx"
+#define PRIXLEAST16 "hX"
+#define PRIoFAST16 "ho"
+#define PRIuFAST16 "hu"
+#define PRIxFAST16 "hx"
+#define PRIXFAST16 "hX"
+
+#define PRIo32 "I32o"
+#define PRIu32 "I32u"
+#define PRIx32 "I32x"
+#define PRIX32 "I32X"
+#define PRIoLEAST32 "I32o"
+#define PRIuLEAST32 "I32u"
+#define PRIxLEAST32 "I32x"
+#define PRIXLEAST32 "I32X"
+#define PRIoFAST32 "I32o"
+#define PRIuFAST32 "I32u"
+#define PRIxFAST32 "I32x"
+#define PRIXFAST32 "I32X"
+
+#define PRIo64 "I64o"
+#define PRIu64 "I64u"
+#define PRIx64 "I64x"
+#define PRIX64 "I64X"
+#define PRIoLEAST64 "I64o"
+#define PRIuLEAST64 "I64u"
+#define PRIxLEAST64 "I64x"
+#define PRIXLEAST64 "I64X"
+#define PRIoFAST64 "I64o"
+#define PRIuFAST64 "I64u"
+#define PRIxFAST64 "I64x"
+#define PRIXFAST64 "I64X"
+
+#define PRIoMAX "I64o"
+#define PRIuMAX "I64u"
+#define PRIxMAX "I64x"
+#define PRIXMAX "I64X"
+
+#define PRIoPTR "Io"
+#define PRIuPTR "Iu"
+#define PRIxPTR "Ix"
+#define PRIXPTR "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8 "d"
+#define SCNi8 "i"
+#define SCNdLEAST8 "d"
+#define SCNiLEAST8 "i"
+#define SCNdFAST8 "d"
+#define SCNiFAST8 "i"
+
+#define SCNd16 "hd"
+#define SCNi16 "hi"
+#define SCNdLEAST16 "hd"
+#define SCNiLEAST16 "hi"
+#define SCNdFAST16 "hd"
+#define SCNiFAST16 "hi"
+
+#define SCNd32 "ld"
+#define SCNi32 "li"
+#define SCNdLEAST32 "ld"
+#define SCNiLEAST32 "li"
+#define SCNdFAST32 "ld"
+#define SCNiFAST32 "li"
+
+#define SCNd64 "I64d"
+#define SCNi64 "I64i"
+#define SCNdLEAST64 "I64d"
+#define SCNiLEAST64 "I64i"
+#define SCNdFAST64 "I64d"
+#define SCNiFAST64 "I64i"
+
+#define SCNdMAX "I64d"
+#define SCNiMAX "I64i"
+
+#ifdef _WIN64 // [
+# define SCNdPTR "I64d"
+# define SCNiPTR "I64i"
+#else // _WIN64 ][
+# define SCNdPTR "ld"
+# define SCNiPTR "li"
+#endif // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8 "o"
+#define SCNu8 "u"
+#define SCNx8 "x"
+#define SCNX8 "X"
+#define SCNoLEAST8 "o"
+#define SCNuLEAST8 "u"
+#define SCNxLEAST8 "x"
+#define SCNXLEAST8 "X"
+#define SCNoFAST8 "o"
+#define SCNuFAST8 "u"
+#define SCNxFAST8 "x"
+#define SCNXFAST8 "X"
+
+#define SCNo16 "ho"
+#define SCNu16 "hu"
+#define SCNx16 "hx"
+#define SCNX16 "hX"
+#define SCNoLEAST16 "ho"
+#define SCNuLEAST16 "hu"
+#define SCNxLEAST16 "hx"
+#define SCNXLEAST16 "hX"
+#define SCNoFAST16 "ho"
+#define SCNuFAST16 "hu"
+#define SCNxFAST16 "hx"
+#define SCNXFAST16 "hX"
+
+#define SCNo32 "lo"
+#define SCNu32 "lu"
+#define SCNx32 "lx"
+#define SCNX32 "lX"
+#define SCNoLEAST32 "lo"
+#define SCNuLEAST32 "lu"
+#define SCNxLEAST32 "lx"
+#define SCNXLEAST32 "lX"
+#define SCNoFAST32 "lo"
+#define SCNuFAST32 "lu"
+#define SCNxFAST32 "lx"
+#define SCNXFAST32 "lX"
+
+#define SCNo64 "I64o"
+#define SCNu64 "I64u"
+#define SCNx64 "I64x"
+#define SCNX64 "I64X"
+#define SCNoLEAST64 "I64o"
+#define SCNuLEAST64 "I64u"
+#define SCNxLEAST64 "I64x"
+#define SCNXLEAST64 "I64X"
+#define SCNoFAST64 "I64o"
+#define SCNuFAST64 "I64u"
+#define SCNxFAST64 "I64x"
+#define SCNXFAST64 "I64X"
+
+#define SCNoMAX "I64o"
+#define SCNuMAX "I64u"
+#define SCNxMAX "I64x"
+#define SCNXMAX "I64X"
+
+#ifdef _WIN64 // [
+# define SCNoPTR "I64o"
+# define SCNuPTR "I64u"
+# define SCNxPTR "I64x"
+# define SCNXPTR "I64X"
+#else // _WIN64 ][
+# define SCNoPTR "lo"
+# define SCNuPTR "lu"
+# define SCNxPTR "lx"
+# define SCNXPTR "lX"
+#endif // _WIN64 ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c found
+// in %MSVC.NET%\crt\src\div.c
+#ifdef STATIC_IMAXDIV // [
+static
+#else // STATIC_IMAXDIV ][
+_inline
+#endif // STATIC_IMAXDIV ]
+imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+ imaxdiv_t result;
+
+ result.quot = numer / denom;
+ result.rem = numer % denom;
+
+ if (numer < 0 && result.rem > 0) {
+ // did division wrong; must fix up
+ ++result.quot;
+ result.rem -= denom;
+ }
+
+ return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+
+#endif // _MSC_INTTYPES_H_ ]
diff --git a/host/msvc/stdint.h b/host/msvc/stdint.h
new file mode 100644
index 000000000..15333b467
--- /dev/null
+++ b/host/msvc/stdint.h
@@ -0,0 +1,226 @@
+// ISO C9x compliant stdint.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+// Copyright (c) 2006 Alexander Chemeris
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. The name of the author may be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include <limits.h>
+
+// For Visual Studio 6 in C++ mode wrap <wchar.h> include with 'extern "C++" {}'
+// or compiler give many errors like this:
+// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
+#if (_MSC_VER < 1300) && defined(__cplusplus)
+ extern "C++" {
+#endif
+# include <wchar.h>
+#if (_MSC_VER < 1300) && defined(__cplusplus)
+ }
+#endif
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+typedef __int8 int8_t;
+typedef __int16 int16_t;
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t int_least8_t;
+typedef int16_t int_least16_t;
+typedef int32_t int_least32_t;
+typedef int64_t int_least64_t;
+typedef uint8_t uint_least8_t;
+typedef uint16_t uint_least16_t;
+typedef uint32_t uint_least32_t;
+typedef uint64_t uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t int_fast8_t;
+typedef int16_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef int64_t int_fast64_t;
+typedef uint8_t uint_fast8_t;
+typedef uint16_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+typedef uint64_t uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+#ifdef _WIN64 // [
+ typedef __int64 intptr_t;
+ typedef unsigned __int64 uintptr_t;
+#else // _WIN64 ][
+ typedef int intptr_t;
+ typedef unsigned int uintptr_t;
+#endif // _WIN64 ]
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t intmax_t;
+typedef uint64_t uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN ((int8_t)_I8_MIN)
+#define INT8_MAX _I8_MAX
+#define INT16_MIN ((int16_t)_I16_MIN)
+#define INT16_MAX _I16_MAX
+#define INT32_MIN ((int32_t)_I32_MIN)
+#define INT32_MAX _I32_MAX
+#define INT64_MIN ((int64_t)_I64_MIN)
+#define INT64_MAX _I64_MAX
+#define UINT8_MAX _UI8_MAX
+#define UINT16_MAX _UI16_MAX
+#define UINT32_MAX _UI32_MAX
+#define UINT64_MAX _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST8_MAX INT8_MAX
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST16_MAX INT16_MAX
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST32_MAX INT32_MAX
+#define INT_LEAST64_MIN INT64_MIN
+#define INT_LEAST64_MAX INT64_MAX
+#define UINT_LEAST8_MAX UINT8_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN INT8_MIN
+#define INT_FAST8_MAX INT8_MAX
+#define INT_FAST16_MIN INT16_MIN
+#define INT_FAST16_MAX INT16_MAX
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST32_MAX INT32_MAX
+#define INT_FAST64_MIN INT64_MIN
+#define INT_FAST64_MAX INT64_MAX
+#define UINT_FAST8_MAX UINT8_MAX
+#define UINT_FAST16_MAX UINT16_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+# define INTPTR_MIN INT64_MIN
+# define INTPTR_MAX INT64_MAX
+# define UINTPTR_MAX UINT64_MAX
+#else // _WIN64 ][
+# define INTPTR_MIN INT32_MIN
+# define INTPTR_MAX INT32_MAX
+# define UINTPTR_MAX UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+# define PTRDIFF_MIN _I64_MIN
+# define PTRDIFF_MAX _I64_MAX
+#else // _WIN64 ][
+# define PTRDIFF_MIN _I32_MIN
+# define PTRDIFF_MAX _I32_MAX
+#endif // _WIN64 ]
+
+#define SIG_ATOMIC_MIN INT_MIN
+#define SIG_ATOMIC_MAX INT_MAX
+
+#ifndef SIZE_MAX // [
+# ifdef _WIN64 // [
+# define SIZE_MAX _UI64_MAX
+# else // _WIN64 ][
+# define SIZE_MAX _UI32_MAX
+# endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+# define WCHAR_MIN 0
+#endif // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+# define WCHAR_MAX _UI16_MAX
+#endif // WCHAR_MAX ]
+
+#define WINT_MIN 0
+#define WINT_MAX _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val) val##i8
+#define INT16_C(val) val##i16
+#define INT32_C(val) val##i32
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val) val##ui8
+#define UINT16_C(val) val##ui16
+#define UINT32_C(val) val##ui32
+#define UINT64_C(val) val##ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+#ifndef INTMAX_C
+#define INTMAX_C INT64_C
+#endif
+#ifndef UINTMAX_C
+#define UINTMAX_C UINT64_C
+#endif
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+
+#endif // _MSC_STDINT_H_ ]
diff --git a/host/test/CMakeLists.txt b/host/tests/CMakeLists.txt
index bdbde4b2c..79b20cd47 100644
--- a/host/test/CMakeLists.txt
+++ b/host/tests/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright 2010 Ettus Research LLC
+# Copyright 2010-2011 Ettus Research LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -22,7 +22,7 @@ SET(test_sources
addr_test.cpp
buffer_test.cpp
byteswap_test.cpp
- convert_types_test.cpp
+ convert_test.cpp
dict_test.cpp
error_test.cpp
gain_group_test.cpp
@@ -51,6 +51,7 @@ ENDFOREACH(test_source)
# demo of a loadable module
########################################################################
ADD_LIBRARY(module_test MODULE module_test.cpp)
+TARGET_LINK_LIBRARIES(module_test uhd)
INSTALL(TARGETS
RUNTIME DESTINATION ${PKG_DATA_DIR}/tests
diff --git a/host/test/addr_test.cpp b/host/tests/addr_test.cpp
index d4b45aa1a..d4b45aa1a 100644
--- a/host/test/addr_test.cpp
+++ b/host/tests/addr_test.cpp
diff --git a/host/test/buffer_test.cpp b/host/tests/buffer_test.cpp
index 8445412e7..e7bc88699 100644
--- a/host/test/buffer_test.cpp
+++ b/host/tests/buffer_test.cpp
@@ -17,7 +17,6 @@
#include <boost/test/unit_test.hpp>
#include <uhd/transport/bounded_buffer.hpp>
-#include <uhd/transport/alignment_buffer.hpp>
#include <boost/assign/list_of.hpp>
using namespace boost::assign;
@@ -63,53 +62,3 @@ BOOST_AUTO_TEST_CASE(test_bounded_buffer_with_pop_on_full){
BOOST_CHECK(bb->pop_with_timed_wait(val, timeout));
BOOST_CHECK_EQUAL(val, 3);
}
-
-BOOST_AUTO_TEST_CASE(test_alignment_buffer){
- alignment_buffer<int, size_t>::sptr ab(alignment_buffer<int, size_t>::make(7, 3));
- //load index 0 with all good seq numbers
- BOOST_CHECK(ab->push_with_pop_on_full(0, 0, 0));
- BOOST_CHECK(ab->push_with_pop_on_full(1, 1, 0));
- BOOST_CHECK(ab->push_with_pop_on_full(2, 2, 0));
- BOOST_CHECK(ab->push_with_pop_on_full(3, 3, 0));
- BOOST_CHECK(ab->push_with_pop_on_full(4, 4, 0));
-
- //load index 1 with some skipped seq numbers
- BOOST_CHECK(ab->push_with_pop_on_full(10, 0, 1));
- BOOST_CHECK(ab->push_with_pop_on_full(11, 1, 1));
- BOOST_CHECK(ab->push_with_pop_on_full(14, 4, 1));
- BOOST_CHECK(ab->push_with_pop_on_full(15, 5, 1));
- BOOST_CHECK(ab->push_with_pop_on_full(16, 6, 1));
-
- //load index 2 with all good seq numbers
- BOOST_CHECK(ab->push_with_pop_on_full(20, 0, 2));
- BOOST_CHECK(ab->push_with_pop_on_full(21, 1, 2));
- BOOST_CHECK(ab->push_with_pop_on_full(22, 2, 2));
- BOOST_CHECK(ab->push_with_pop_on_full(23, 3, 2));
- BOOST_CHECK(ab->push_with_pop_on_full(24, 4, 2));
-
- //readback aligned values
- std::vector<int> aligned_elems(3);
-
- static const std::vector<int> expected_elems0 = list_of(0)(10)(20);
- BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout));
- BOOST_CHECK_EQUAL_COLLECTIONS(
- aligned_elems.begin(), aligned_elems.end(),
- expected_elems0.begin(), expected_elems0.end()
- );
-
- static const std::vector<int> expected_elems1 = list_of(1)(11)(21);
- BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout));
- BOOST_CHECK_EQUAL_COLLECTIONS(
- aligned_elems.begin(), aligned_elems.end(),
- expected_elems1.begin(), expected_elems1.end()
- );
-
- //there was a skip now find 4
-
- static const std::vector<int> expected_elems4 = list_of(4)(14)(24);
- BOOST_CHECK(ab->pop_elems_with_timed_wait(aligned_elems, timeout));
- BOOST_CHECK_EQUAL_COLLECTIONS(
- aligned_elems.begin(), aligned_elems.end(),
- expected_elems4.begin(), expected_elems4.end()
- );
-}
diff --git a/host/test/byteswap_test.cpp b/host/tests/byteswap_test.cpp
index 3d50c9bfa..3d50c9bfa 100644
--- a/host/test/byteswap_test.cpp
+++ b/host/tests/byteswap_test.cpp
diff --git a/host/test/convert_types_test.cpp b/host/tests/convert_test.cpp
index 378e184de..5f2aaf3d1 100644
--- a/host/test/convert_types_test.cpp
+++ b/host/tests/convert_test.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2011-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -15,14 +15,14 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/transport/convert_types.hpp>
+#include <uhd/convert.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp>
#include <boost/cstdint.hpp>
-#include <boost/asio/buffer.hpp>
#include <complex>
#include <vector>
#include <cstdlib>
+#include <iostream>
using namespace uhd;
@@ -30,14 +30,6 @@ using namespace uhd;
typedef std::complex<boost::int16_t> sc16_t;
typedef std::complex<float> fc32_t;
-//extract pointer to POD since using &vector.front() throws in MSVC
-template <typename T> void * pod2ptr(T &pod){
- return boost::asio::buffer_cast<void *>(boost::asio::buffer(pod));
-}
-template <typename T> const void * pod2ptr(const T &pod){
- return boost::asio::buffer_cast<const void *>(boost::asio::buffer(pod));
-}
-
#define MY_CHECK_CLOSE(a, b, f) if ((std::abs(a) > (f) and std::abs(b) > (f))) \
BOOST_CHECK_CLOSE_FRACTION(a, b, f)
@@ -54,21 +46,20 @@ template <typename Range> static void loopback(
Range &output
){
//item32 is largest device type
- std::vector<boost::uint32_t> dev(nsamps);
+ std::vector<boost::uint32_t> interm(nsamps);
- //convert to dev type
- transport::convert_io_type_to_otw_type(
- pod2ptr(input), io_type,
- pod2ptr(dev), otw_type,
- nsamps
- );
+ convert::input_type input0(1, &input[0]), input1(1, &interm[0]);
+ convert::output_type output0(1, &interm[0]), output1(1, &output[0]);
+
+ //convert to intermediate type
+ convert::get_converter_cpu_to_otw(
+ io_type, otw_type, input0.size(), output0.size()
+ )(input0, output0, nsamps);
//convert back to host type
- transport::convert_otw_type_to_io_type(
- pod2ptr(dev), otw_type,
- pod2ptr(output), io_type,
- nsamps
- );
+ convert::get_converter_otw_to_cpu(
+ io_type, otw_type, input1.size(), output1.size()
+ )(input1, output1, nsamps);
}
/***********************************************************************
@@ -98,7 +89,7 @@ BOOST_AUTO_TEST_CASE(test_convert_types_be_sc16){
otw_type.width = 16;
//try various lengths to test edge cases
- for (size_t nsamps = 0; nsamps < 16; nsamps++){
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
test_convert_types_sc16(nsamps, io_type, otw_type);
}
}
@@ -110,7 +101,7 @@ BOOST_AUTO_TEST_CASE(test_convert_types_le_sc16){
otw_type.width = 16;
//try various lengths to test edge cases
- for (size_t nsamps = 0; nsamps < 16; nsamps++){
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
test_convert_types_sc16(nsamps, io_type, otw_type);
}
}
@@ -145,7 +136,7 @@ BOOST_AUTO_TEST_CASE(test_convert_types_be_fc32){
otw_type.width = 16;
//try various lengths to test edge cases
- for (size_t nsamps = 0; nsamps < 16; nsamps++){
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
test_convert_types_fc32(nsamps, io_type, otw_type);
}
}
@@ -157,7 +148,7 @@ BOOST_AUTO_TEST_CASE(test_convert_types_le_fc32){
otw_type.width = 16;
//try various lengths to test edge cases
- for (size_t nsamps = 0; nsamps < 16; nsamps++){
+ for (size_t nsamps = 1; nsamps < 16; nsamps++){
test_convert_types_fc32(nsamps, io_type, otw_type);
}
}
@@ -179,22 +170,21 @@ BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16){
(std::rand()/float(RAND_MAX/2)) - 1,
(std::rand()/float(RAND_MAX/2)) - 1
);
+ std::vector<boost::uint32_t> interm(nsamps);
+ std::vector<sc16_t> output(nsamps);
- //convert float to dev
- std::vector<boost::uint32_t> tmp(nsamps);
- transport::convert_io_type_to_otw_type(
- pod2ptr(input), io_type_in,
- pod2ptr(tmp), otw_type,
- nsamps
- );
+ convert::input_type input0(1, &input[0]), input1(1, &interm[0]);
+ convert::output_type output0(1, &interm[0]), output1(1, &output[0]);
- //convert dev to short
- std::vector<sc16_t> output(nsamps);
- transport::convert_otw_type_to_io_type(
- pod2ptr(tmp), otw_type,
- pod2ptr(output), io_type_out,
- nsamps
- );
+ //convert float to intermediate
+ convert::get_converter_cpu_to_otw(
+ io_type_in, otw_type, input0.size(), output0.size()
+ )(input0, output0, nsamps);
+
+ //convert intermediate to short
+ convert::get_converter_otw_to_cpu(
+ io_type_out, otw_type, input1.size(), output1.size()
+ )(input1, output1, nsamps);
//test that the inputs and outputs match
for (size_t i = 0; i < nsamps; i++){
@@ -220,22 +210,21 @@ BOOST_AUTO_TEST_CASE(test_convert_types_sc16_to_fc32){
std::rand()-(RAND_MAX/2),
std::rand()-(RAND_MAX/2)
);
+ std::vector<boost::uint32_t> interm(nsamps);
+ std::vector<fc32_t> output(nsamps);
- //convert short to dev
- std::vector<boost::uint32_t> tmp(nsamps);
- transport::convert_io_type_to_otw_type(
- pod2ptr(input), io_type_in,
- pod2ptr(tmp), otw_type,
- nsamps
- );
+ convert::input_type input0(1, &input[0]), input1(1, &interm[0]);
+ convert::output_type output0(1, &interm[0]), output1(1, &output[0]);
- //convert dev to float
- std::vector<fc32_t> output(nsamps);
- transport::convert_otw_type_to_io_type(
- pod2ptr(tmp), otw_type,
- pod2ptr(output), io_type_out,
- nsamps
- );
+ //convert short to intermediate
+ convert::get_converter_cpu_to_otw(
+ io_type_in, otw_type, input0.size(), output0.size()
+ )(input0, output0, nsamps);
+
+ //convert intermediate to float
+ convert::get_converter_otw_to_cpu(
+ io_type_out, otw_type, input1.size(), output1.size()
+ )(input1, output1, nsamps);
//test that the inputs and outputs match
for (size_t i = 0; i < nsamps; i++){
diff --git a/host/test/dict_test.cpp b/host/tests/dict_test.cpp
index 0501a7878..0501a7878 100644
--- a/host/test/dict_test.cpp
+++ b/host/tests/dict_test.cpp
diff --git a/host/test/error_test.cpp b/host/tests/error_test.cpp
index c76a15ab7..c76a15ab7 100644
--- a/host/test/error_test.cpp
+++ b/host/tests/error_test.cpp
diff --git a/host/test/gain_group_test.cpp b/host/tests/gain_group_test.cpp
index dbb585987..53142ef21 100644
--- a/host/test/gain_group_test.cpp
+++ b/host/tests/gain_group_test.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -35,37 +35,37 @@ public:
return gain_range_t(0, 90, 1);
}
- float get_value(void){
+ double get_value(void){
return _gain;
}
- void set_value(float gain){
- float step = get_range().step();
+ void set_value(double gain){
+ double step = get_range().step();
_gain = step*rint(gain/step);
}
private:
- float _gain;
+ double _gain;
};
class gain_element2{
public:
gain_range_t get_range(void){
- return gain_range_t(-20, 10, float(0.1));
+ return gain_range_t(-20, 10, 0.1);
}
- float get_value(void){
+ double get_value(void){
return _gain;
}
- void set_value(float gain){
- float step = get_range().step();
+ void set_value(double gain){
+ double step = get_range().step();
_gain = step*rint(gain/step);
}
private:
- float _gain;
+ double _gain;
};
//create static instances of gain elements to be shared by the tests
@@ -94,17 +94,17 @@ static gain_group::sptr get_gain_group(size_t pri1 = 0, size_t pri2 = 0){
/***********************************************************************
* Test cases
**********************************************************************/
-static const float tolerance = float(0.001);
+static const double tolerance = 0.001;
BOOST_AUTO_TEST_CASE(test_gain_group_overall){
gain_group::sptr gg = get_gain_group();
//test the overall stuff
gg->set_value(80);
- BOOST_CHECK_CLOSE(gg->get_value(), float(80), tolerance);
- BOOST_CHECK_CLOSE(gg->get_range().start(), float(-20), tolerance);
- BOOST_CHECK_CLOSE(gg->get_range().stop(), float(100), tolerance);
- BOOST_CHECK_CLOSE(gg->get_range().step(), float(0.1), tolerance);
+ BOOST_CHECK_CLOSE(gg->get_value(), 80, tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().start(), -20, tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().stop(), 100, tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().step(), 0.1, tolerance);
}
BOOST_AUTO_TEST_CASE(test_gain_group_priority){
@@ -112,10 +112,10 @@ BOOST_AUTO_TEST_CASE(test_gain_group_priority){
//test the overall stuff
gg->set_value(80);
- BOOST_CHECK_CLOSE(gg->get_value(), float(80), tolerance);
- BOOST_CHECK_CLOSE(gg->get_range().start(), float(-20), tolerance);
- BOOST_CHECK_CLOSE(gg->get_range().stop(), float(100), tolerance);
- BOOST_CHECK_CLOSE(gg->get_range().step(), float(0.1), tolerance);
+ BOOST_CHECK_CLOSE(gg->get_value(), 80, tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().start(), -20, tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().stop(), 100, tolerance);
+ BOOST_CHECK_CLOSE(gg->get_range().step(), 0.1, tolerance);
//test the the higher priority gain got filled first (gain 2)
BOOST_CHECK_CLOSE(g2.get_value(), g2.get_range().stop(), tolerance);
diff --git a/host/test/module_test.cpp b/host/tests/module_test.cpp
index 47a0e1af9..47a0e1af9 100644
--- a/host/test/module_test.cpp
+++ b/host/tests/module_test.cpp
diff --git a/host/test/ranges_test.cpp b/host/tests/ranges_test.cpp
index ad61867e1..5f6de4645 100644
--- a/host/test/ranges_test.cpp
+++ b/host/tests/ranges_test.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -24,18 +24,18 @@ using namespace uhd;
static const double tolerance = 0.001;
BOOST_AUTO_TEST_CASE(test_ranges_bounds){
- meta_range_t<double> mr;
- mr.push_back(range_t<double>(-1.0, +1.0, 0.1));
+ meta_range_t mr;
+ mr.push_back(range_t(-1.0, +1.0, 0.1));
BOOST_CHECK_CLOSE(mr.start(), -1.0, tolerance);
BOOST_CHECK_CLOSE(mr.stop(), +1.0, tolerance);
BOOST_CHECK_CLOSE(mr.step(), 0.1, tolerance);
- mr.push_back(range_t<double>(40.0, 60.0, 1.0));
+ mr.push_back(range_t(40.0, 60.0, 1.0));
BOOST_CHECK_CLOSE(mr.start(), -1.0, tolerance);
BOOST_CHECK_CLOSE(mr.stop(), 60.0, tolerance);
BOOST_CHECK_CLOSE(mr.step(), 0.1, tolerance);
- BOOST_CHECK_EQUAL(mr.size(), 2);
+ BOOST_CHECK_EQUAL(mr.size(), unsigned(2));
BOOST_CHECK_CLOSE(mr[0].start(), -1.0, tolerance);
BOOST_CHECK_CLOSE(mr[0].stop(), +1.0, tolerance);
@@ -43,9 +43,9 @@ BOOST_AUTO_TEST_CASE(test_ranges_bounds){
}
BOOST_AUTO_TEST_CASE(test_ranges_clip){
- meta_range_t<double> mr;
- mr.push_back(range_t<double>(-1.0, +1.0, 0.1));
- mr.push_back(range_t<double>(40.0, 60.0, 1.0));
+ meta_range_t mr;
+ mr.push_back(range_t(-1.0, +1.0, 0.1));
+ mr.push_back(range_t(40.0, 60.0, 1.0));
BOOST_CHECK_CLOSE(mr.clip(-30.0), -1.0, tolerance);
BOOST_CHECK_CLOSE(mr.clip(70.0), 60.0, tolerance);
diff --git a/host/test/subdev_spec_test.cpp b/host/tests/subdev_spec_test.cpp
index 8817d5eee..8817d5eee 100644
--- a/host/test/subdev_spec_test.cpp
+++ b/host/tests/subdev_spec_test.cpp
diff --git a/host/test/time_spec_test.cpp b/host/tests/time_spec_test.cpp
index 5ad782160..5ad782160 100644
--- a/host/test/time_spec_test.cpp
+++ b/host/tests/time_spec_test.cpp
diff --git a/host/test/tune_helper_test.cpp b/host/tests/tune_helper_test.cpp
index 735e7e948..735e7e948 100644
--- a/host/test/tune_helper_test.cpp
+++ b/host/tests/tune_helper_test.cpp
diff --git a/host/test/vrt_test.cpp b/host/tests/vrt_test.cpp
index 9e131a10b..9e131a10b 100644
--- a/host/test/vrt_test.cpp
+++ b/host/tests/vrt_test.cpp
diff --git a/host/test/warning_test.cpp b/host/tests/warning_test.cpp
index db19955de..db19955de 100644
--- a/host/test/warning_test.cpp
+++ b/host/tests/warning_test.cpp
diff --git a/host/test/wax_test.cpp b/host/tests/wax_test.cpp
index 731f470ed..731f470ed 100644
--- a/host/test/wax_test.cpp
+++ b/host/tests/wax_test.cpp
diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt
index a8e50f72b..2df1c3529 100644
--- a/host/utils/CMakeLists.txt
+++ b/host/utils/CMakeLists.txt
@@ -47,6 +47,7 @@ ENDIF(ENABLE_USRP1)
IF(ENABLE_USRP_E100)
ENABLE_LANGUAGE(C)
+ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e100/include)
LIST(APPEND util_share_sources
fpga-downloader.cpp
diff --git a/host/utils/uhd_usrp_probe.cpp b/host/utils/uhd_usrp_probe.cpp
index 5cba7c362..b32131b2a 100644
--- a/host/utils/uhd_usrp_probe.cpp
+++ b/host/utils/uhd_usrp_probe.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2010 Ettus Research LLC
+// Copyright 2010-2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -18,7 +18,7 @@
#include <uhd/utils/safe_main.hpp>
#include <uhd/device.hpp>
#include <uhd/types/ranges.hpp>
-#include <uhd/utils/algorithm.hpp>
+#include <boost/algorithm/string.hpp> //for split
#include <uhd/usrp/device_props.hpp>
#include <uhd/usrp/mboard_props.hpp>
#include <uhd/usrp/dboard_props.hpp>
@@ -32,6 +32,7 @@
#include <boost/foreach.hpp>
#include <iostream>
#include <sstream>
+#include <vector>
namespace po = boost::program_options;
using namespace uhd;
@@ -44,7 +45,7 @@ static std::string make_border(const std::string &text){
std::stringstream ss;
ss << boost::format(" _____________________________________________________") << std::endl;
ss << boost::format(" /") << std::endl;
- std::vector<std::string> lines = std::split_string(text, "\n");
+ std::vector<std::string> lines; boost::split(lines, text, boost::is_any_of("\n"));
while (lines.back() == "") lines.pop_back(); //strip trailing newlines
if (lines.size()) lines[0] = " " + lines[0]; //indent the title line
BOOST_FOREACH(const std::string &line, lines){
diff --git a/host/utils/usrp-e-debug-pins.c b/host/utils/usrp-e-debug-pins.c
index 1ed2c8983..94f898b67 100644
--- a/host/utils/usrp-e-debug-pins.c
+++ b/host/utils/usrp-e-debug-pins.c
@@ -7,7 +7,7 @@
#include <sys/ioctl.h>
#include <linux/usrp_e.h>
-#include "usrp_e_regs.hpp"
+#include "usrp_e100_regs.hpp"
// Usage: usrp_e_gpio <string>
@@ -42,6 +42,7 @@ int main(int argc, char *argv[])
test = 0;
if (argc < 2) {
printf("%s 0|1|off\n", argv[0]);
+ return -1;
}
fp = open("/dev/usrp_e0", O_RDWR);
diff --git a/host/utils/usrp_e_regs.hpp b/host/utils/usrp_e_regs.hpp
deleted file mode 100644
index a4f42093e..000000000
--- a/host/utils/usrp_e_regs.hpp
+++ /dev/null
@@ -1,196 +0,0 @@
-
-
-////////////////////////////////////////////////////////////////
-//
-// Memory map for embedded wishbone bus
-//
-////////////////////////////////////////////////////////////////
-
-// All addresses are byte addresses. All accesses are word (16-bit) accesses.
-// This means that address bit 0 is usually 0.
-// There are 11 bits of address for the control.
-
-#ifndef __USRP_E_REGS_H
-#define __USRP_E_REGS_H
-
-/////////////////////////////////////////////////////
-// Slave pointers
-
-#define UE_REG_SLAVE(n) ((n)<<7)
-#define UE_REG_SR_ADDR(n) ((UE_REG_SLAVE(5)) + (4*(n)))
-
-/////////////////////////////////////////////////////
-// Slave 0 -- Misc Regs
-
-#define UE_REG_MISC_BASE UE_REG_SLAVE(0)
-
-#define UE_REG_MISC_LED UE_REG_MISC_BASE + 0
-#define UE_REG_MISC_SW UE_REG_MISC_BASE + 2
-#define UE_REG_MISC_CGEN_CTRL UE_REG_MISC_BASE + 4
-#define UE_REG_MISC_CGEN_ST UE_REG_MISC_BASE + 6
-#define UE_REG_MISC_TEST UE_REG_MISC_BASE + 8
-#define UE_REG_MISC_RX_LEN UE_REG_MISC_BASE + 10
-#define UE_REG_MISC_TX_LEN UE_REG_MISC_BASE + 12
-
-/////////////////////////////////////////////////////
-// Slave 1 -- UART
-// CLKDIV is 16 bits, others are only 8
-
-#define UE_REG_UART_BASE UE_REG_SLAVE(1)
-
-#define UE_REG_UART_CLKDIV UE_REG_UART_BASE + 0
-#define UE_REG_UART_TXLEVEL UE_REG_UART_BASE + 2
-#define UE_REG_UART_RXLEVEL UE_REG_UART_BASE + 4
-#define UE_REG_UART_TXCHAR UE_REG_UART_BASE + 6
-#define UE_REG_UART_RXCHAR UE_REG_UART_BASE + 8
-
-/////////////////////////////////////////////////////
-// Slave 2 -- SPI Core
-// This should be accessed through the IOCTL
-// Users should not touch directly
-
-#define UE_REG_SPI_BASE UE_REG_SLAVE(2)
-
-//spi slave constants
-#define UE_SPI_SS_AD9522 (1 << 3)
-#define UE_SPI_SS_AD9862 (1 << 2)
-#define UE_SPI_SS_TX_DB (1 << 1)
-#define UE_SPI_SS_RX_DB (1 << 0)
-
-////////////////////////////////////////////////
-// Slave 3 -- I2C Core
-// This should be accessed through the IOCTL
-// Users should not touch directly
-
-#define UE_REG_I2C_BASE UE_REG_SLAVE(3)
-
-
-////////////////////////////////////////////////
-// Slave 4 -- GPIO
-
-#define UE_REG_GPIO_BASE UE_REG_SLAVE(4)
-
-#define UE_REG_GPIO_RX_IO UE_REG_GPIO_BASE + 0
-#define UE_REG_GPIO_TX_IO UE_REG_GPIO_BASE + 2
-#define UE_REG_GPIO_RX_DDR UE_REG_GPIO_BASE + 4
-#define UE_REG_GPIO_TX_DDR UE_REG_GPIO_BASE + 6
-#define UE_REG_GPIO_RX_SEL UE_REG_GPIO_BASE + 8
-#define UE_REG_GPIO_TX_SEL UE_REG_GPIO_BASE + 10
-#define UE_REG_GPIO_RX_DBG UE_REG_GPIO_BASE + 12
-#define UE_REG_GPIO_TX_DBG UE_REG_GPIO_BASE + 14
-
-//possible bit values for sel when dbg is 0:
-#define GPIO_SEL_SW 0 // if pin is an output, set by software in the io reg
-#define GPIO_SEL_ATR 1 // if pin is an output, set by ATR logic
-
-//possible bit values for sel when dbg is 1:
-#define GPIO_SEL_DEBUG_0 0 // if pin is an output, debug lines from FPGA fabric
-#define GPIO_SEL_DEBUG_1 1 // if pin is an output, debug lines from FPGA fabric
-
-
-////////////////////////////////////////////////////
-// Slave 5 -- Settings Bus
-//
-// Output-only, no readback, 32 registers total
-// Each register must be written 32 bits at a time
-// First the address xxx_xx00 and then xxx_xx10
-
-#define UE_REG_SETTINGS_BASE UE_REG_SLAVE(5)
-
-///////////////////////////////////////////////////
-// Slave 6 -- ATR Controller
-// 16 regs
-
-#define UE_REG_ATR_BASE UE_REG_SLAVE(6)
-
-#define UE_REG_ATR_IDLE_RXSIDE UE_REG_ATR_BASE + 0
-#define UE_REG_ATR_IDLE_TXSIDE UE_REG_ATR_BASE + 2
-#define UE_REG_ATR_INTX_RXSIDE UE_REG_ATR_BASE + 4
-#define UE_REG_ATR_INTX_TXSIDE UE_REG_ATR_BASE + 6
-#define UE_REG_ATR_INRX_RXSIDE UE_REG_ATR_BASE + 8
-#define UE_REG_ATR_INRX_TXSIDE UE_REG_ATR_BASE + 10
-#define UE_REG_ATR_FULL_RXSIDE UE_REG_ATR_BASE + 12
-#define UE_REG_ATR_FULL_TXSIDE UE_REG_ATR_BASE + 14
-
-/////////////////////////////////////////////////
-// DSP RX Regs
-////////////////////////////////////////////////
-#define UE_REG_DSP_RX_FREQ UE_REG_SR_ADDR(0)
-#define UE_REG_DSP_RX_SCALE_IQ UE_REG_SR_ADDR(1) // {scale_i,scale_q}
-#define UE_REG_DSP_RX_DECIM_RATE UE_REG_SR_ADDR(2) // hb and decim rate
-#define UE_REG_DSP_RX_DCOFFSET_I UE_REG_SR_ADDR(3) // Bit 31 high sets fixed offset mode, using lower 14 bits, // otherwise it is automatic
-#define UE_REG_DSP_RX_DCOFFSET_Q UE_REG_SR_ADDR(4) // Bit 31 high sets fixed offset mode, using lower 14 bits
-#define UE_REG_DSP_RX_MUX UE_REG_SR_ADDR(5)
-
-///////////////////////////////////////////////////
-// VITA RX CTRL regs
-///////////////////////////////////////////////////
-// The following 3 are logically a single command register.
-// They are clocked into the underlying fifo when time_ticks is written.
-#define UE_REG_CTRL_RX_STREAM_CMD UE_REG_SR_ADDR(8) // {now, chain, num_samples(30)
-#define UE_REG_CTRL_RX_TIME_SECS UE_REG_SR_ADDR(9)
-#define UE_REG_CTRL_RX_TIME_TICKS UE_REG_SR_ADDR(10)
-#define UE_REG_CTRL_RX_CLEAR_OVERRUN UE_REG_SR_ADDR(11) // write anything to clear overrun
-#define UE_REG_CTRL_RX_VRT_HEADER UE_REG_SR_ADDR(12) // word 0 of packet. FPGA fills in packet counter
-#define UE_REG_CTRL_RX_VRT_STREAM_ID UE_REG_SR_ADDR(13) // word 1 of packet.
-#define UE_REG_CTRL_RX_VRT_TRAILER UE_REG_SR_ADDR(14)
-#define UE_REG_CTRL_RX_NSAMPS_PER_PKT UE_REG_SR_ADDR(15)
-#define UE_REG_CTRL_RX_NCHANNELS UE_REG_SR_ADDR(16) // 1 in basic case, up to 4 for vector sources
-
-/////////////////////////////////////////////////
-// DSP TX Regs
-////////////////////////////////////////////////
-#define UE_REG_DSP_TX_FREQ UE_REG_SR_ADDR(17)
-#define UE_REG_DSP_TX_SCALE_IQ UE_REG_SR_ADDR(18) // {scale_i,scale_q}
-#define UE_REG_DSP_TX_INTERP_RATE UE_REG_SR_ADDR(19)
-#define UE_REG_DSP_TX_UNUSED UE_REG_SR_ADDR(20)
-#define UE_REG_DSP_TX_MUX UE_REG_SR_ADDR(21)
-
-/////////////////////////////////////////////////
-// VITA TX CTRL regs
-////////////////////////////////////////////////
-#define UE_REG_CTRL_TX_NCHANNELS UE_REG_SR_ADDR(24)
-#define UE_REG_CTRL_TX_CLEAR_UNDERRUN UE_REG_SR_ADDR(25)
-#define UE_REG_CTRL_TX_REPORT_SID UE_REG_SR_ADDR(26)
-#define UE_REG_CTRL_TX_POLICY UE_REG_SR_ADDR(27)
-
-#define UE_FLAG_CTRL_TX_POLICY_WAIT (0x1 << 0)
-#define UE_FLAG_CTRL_TX_POLICY_NEXT_PACKET (0x1 << 1)
-#define UE_FLAG_CTRL_TX_POLICY_NEXT_BURST (0x1 << 2)
-
-/////////////////////////////////////////////////
-// VITA49 64 bit time (write only)
-////////////////////////////////////////////////
- /*!
- * \brief Time 64 flags
- *
- * <pre>
- *
- * 3 2 1
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------------------------------------------------------+-+-+
- * | |S|P|
- * +-----------------------------------------------------------+-+-+
- *
- * P - PPS edge selection (0=negedge, 1=posedge, default=0)
- * S - Source (0=sma, 1=mimo, 0=default)
- *
- * </pre>
- */
-#define UE_REG_TIME64_SECS UE_REG_SR_ADDR(28) // value to set absolute secs to on next PPS
-#define UE_REG_TIME64_TICKS UE_REG_SR_ADDR(29) // value to set absolute ticks to on next PPS
-#define UE_REG_TIME64_FLAGS UE_REG_SR_ADDR(30) // flags - see chart above
-#define UE_REG_TIME64_IMM UE_REG_SR_ADDR(31) // set immediate (0=latch on next pps, 1=latch immediate, default=0)
-#define UE_REG_TIME64_TPS UE_REG_SR_ADDR(31) // clock ticks per second (counter rollover)
-
-//pps flags (see above)
-#define UE_FLAG_TIME64_PPS_NEGEDGE (0 << 0)
-#define UE_FLAG_TIME64_PPS_POSEDGE (1 << 0)
-#define UE_FLAG_TIME64_PPS_SMA (0 << 1)
-#define UE_FLAG_TIME64_PPS_MIMO (1 << 1)
-
-#define UE_FLAG_TIME64_LATCH_NOW 1
-#define UE_FLAG_TIME64_LATCH_NEXT_PPS 0
-
-#endif
-