aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--firmware/microblaze/lib/net_common.c19
-rw-r--r--fpga/usrp2/control_lib/nsgpio.v2
-rw-r--r--fpga/usrp2/sdr_lib/cordic_z24.v48
-rw-r--r--fpga/usrp2/sdr_lib/dsp_core_rx.v10
-rw-r--r--fpga/usrp2/top/u2_rev3/Makefile2
-rw-r--r--fpga/usrp2/top/u2_rev3/u2_rev3.ucf2
-rw-r--r--fpga/usrp2/top/u2_rev3/u2_rev3.v15
-rw-r--r--host/CMakeLists.txt3
-rw-r--r--host/docs/build.rst2
-rw-r--r--host/docs/usrp2.rst11
-rw-r--r--host/include/uhd/config.hpp22
-rw-r--r--host/include/uhd/transport/udp_zero_copy.hpp24
-rw-r--r--host/include/uhd/types/device_addr.hpp10
-rw-r--r--host/include/uhd/types/dict.hpp4
-rw-r--r--host/include/uhd/usrp/dboard_base.hpp24
-rw-r--r--host/include/uhd/usrp/dboard_id.hpp64
-rw-r--r--host/include/uhd/usrp/dboard_manager.hpp2
-rw-r--r--host/include/uhd/utils/CMakeLists.txt1
-rw-r--r--host/include/uhd/utils/algorithm.hpp30
-rw-r--r--host/include/uhd/utils/assert.hpp39
-rw-r--r--host/include/uhd/utils/exception.hpp38
-rw-r--r--host/include/uhd/utils/props.hpp13
-rw-r--r--host/include/uhd/utils/safe_main.hpp3
-rw-r--r--host/lib/CMakeLists.txt126
-rw-r--r--host/lib/device.cpp4
-rw-r--r--host/lib/ic_reg_maps/CMakeLists.txt65
-rw-r--r--host/lib/ic_reg_maps/common.py97
-rwxr-xr-xhost/lib/ic_reg_maps/gen_ad5624_regs.py66
-rwxr-xr-xhost/lib/ic_reg_maps/gen_ad7922_regs.py78
-rwxr-xr-xhost/lib/ic_reg_maps/gen_ad9510_regs.py104
-rwxr-xr-xhost/lib/ic_reg_maps/gen_ad9522_regs.py183
-rwxr-xr-xhost/lib/ic_reg_maps/gen_ad9777_regs.py93
-rwxr-xr-xhost/lib/ic_reg_maps/gen_ad9862_regs.py246
-rwxr-xr-xhost/lib/ic_reg_maps/gen_adf4350_regs.py121
-rwxr-xr-xhost/lib/ic_reg_maps/gen_adf4360_regs.py83
-rwxr-xr-xhost/lib/ic_reg_maps/gen_max2829_regs.py85
-rw-r--r--host/lib/load_modules.cpp34
-rw-r--r--host/lib/transport/CMakeLists.txt52
-rwxr-xr-xhost/lib/transport/gen_vrt.py4
-rw-r--r--host/lib/transport/udp_zero_copy_asio.cpp57
-rw-r--r--host/lib/types.cpp4
-rw-r--r--host/lib/usrp/CMakeLists.txt27
-rw-r--r--host/lib/usrp/dboard/CMakeLists.txt26
-rw-r--r--host/lib/usrp/dboard/db_basic_and_lf.cpp20
-rw-r--r--host/lib/usrp/dboard/db_rfx.cpp18
-rw-r--r--host/lib/usrp/dboard/db_wbx.cpp613
-rw-r--r--host/lib/usrp/dboard/db_xcvr2450.cpp13
-rw-r--r--host/lib/usrp/dboard_base.cpp42
-rw-r--r--host/lib/usrp/dboard_ctor_args.hpp32
-rw-r--r--host/lib/usrp/dboard_eeprom.cpp13
-rw-r--r--host/lib/usrp/dboard_id.cpp68
-rw-r--r--host/lib/usrp/dboard_manager.cpp75
-rw-r--r--host/lib/usrp/usrp2/CMakeLists.txt29
-rw-r--r--host/lib/usrp/usrp2/dboard_iface.cpp57
-rw-r--r--host/lib/usrp/usrp2/dsp_impl.cpp24
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp3
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.cpp32
-rw-r--r--host/lib/utils.cpp9
-rw-r--r--host/test/CMakeLists.txt2
-rw-r--r--host/test/addr_test.cpp17
-rw-r--r--host/test/dict_test.cpp72
-rw-r--r--host/test/error_test.cpp48
-rw-r--r--host/utils/uhd_burn_db_eeprom.cpp8
-rw-r--r--host/utils/uhd_find_devices.cpp2
64 files changed, 2350 insertions, 790 deletions
diff --git a/firmware/microblaze/lib/net_common.c b/firmware/microblaze/lib/net_common.c
index 67a3ff964..6c9509c92 100644
--- a/firmware/microblaze/lib/net_common.c
+++ b/firmware/microblaze/lib/net_common.c
@@ -303,7 +303,24 @@ handle_icmp_packet(struct ip_addr src, struct ip_addr dst,
}
break;
- case ICMP_ECHO:
+ case ICMP_ECHO:{
+ struct icmp_echo_hdr echo_reply;
+ echo_reply.type = 0;
+ echo_reply.code = 0;
+ echo_reply.chksum = 0;
+ echo_reply.id = icmp->id;
+ echo_reply.seqno = icmp->seqno;
+ echo_reply.chksum = ~chksum_buffer(
+ (unsigned short *)&echo_reply,
+ sizeof(echo_reply)/sizeof(short),
+ 0);
+ send_ip_pkt(
+ src, IP_PROTO_ICMP, &echo_reply, sizeof(echo_reply),
+ ((uint8_t*)icmp) + sizeof(struct icmp_echo_hdr),
+ len - sizeof(struct icmp_echo_hdr)
+ );
+ break;
+ }
default:
break;
}
diff --git a/fpga/usrp2/control_lib/nsgpio.v b/fpga/usrp2/control_lib/nsgpio.v
index 937ea7020..26130cc8e 100644
--- a/fpga/usrp2/control_lib/nsgpio.v
+++ b/fpga/usrp2/control_lib/nsgpio.v
@@ -95,7 +95,7 @@ module nsgpio
integer n;
reg [31:0] igpio; // temporary internal signal
- always @(ctrl or line or debug_1 or debug_0 or atr)
+ always @(ctrl or line or debug_1 or debug_0 or atr or ddr)
for(n=0;n<32;n=n+1)
igpio[n] <= ddr[n] ? (ctrl[2*n+1] ? (ctrl[2*n] ? debug_1[n] : debug_0[n]) :
(ctrl[2*n] ? atr[n] : line[n]) )
diff --git a/fpga/usrp2/sdr_lib/cordic_z24.v b/fpga/usrp2/sdr_lib/cordic_z24.v
index cf668d5ec..97b7beaf7 100644
--- a/fpga/usrp2/sdr_lib/cordic_z24.v
+++ b/fpga/usrp2/sdr_lib/cordic_z24.v
@@ -45,30 +45,30 @@ module cordic_z24(clock, reset, enable, xi, yi, zi, xo, yo, zo );
// see gen_cordic_consts.py
// constants for 24 bit wide phase
- localparam c00 = 24'd2097152;
- localparam c01 = 24'd1238021;
- localparam c02 = 24'd654136;
- localparam c03 = 24'd332050;
- localparam c04 = 24'd166669;
- localparam c05 = 24'd83416;
- localparam c06 = 24'd41718;
- localparam c07 = 24'd20860;
- localparam c08 = 24'd10430;
- localparam c09 = 24'd5215;
- localparam c10 = 24'd2608;
- localparam c11 = 24'd1304;
- localparam c12 = 24'd652;
- localparam c13 = 24'd326;
- localparam c14 = 24'd163;
- localparam c15 = 24'd81;
- localparam c16 = 24'd41;
- localparam c17 = 24'd20;
- localparam c18 = 24'd10;
- localparam c19 = 24'd5;
- localparam c20 = 24'd3;
- localparam c21 = 24'd1;
- localparam c22 = 24'd1;
- localparam c23 = 24'd0;
+ localparam c00 = 23'd2097152;
+ localparam c01 = 23'd1238021;
+ localparam c02 = 23'd654136;
+ localparam c03 = 23'd332050;
+ localparam c04 = 23'd166669;
+ localparam c05 = 23'd83416;
+ localparam c06 = 23'd41718;
+ localparam c07 = 23'd20860;
+ localparam c08 = 23'd10430;
+ localparam c09 = 23'd5215;
+ localparam c10 = 23'd2608;
+ localparam c11 = 23'd1304;
+ localparam c12 = 23'd652;
+ localparam c13 = 23'd326;
+ localparam c14 = 23'd163;
+ localparam c15 = 23'd81;
+ localparam c16 = 23'd41;
+ localparam c17 = 23'd20;
+ localparam c18 = 23'd10;
+ localparam c19 = 23'd5;
+ localparam c20 = 23'd3;
+ localparam c21 = 23'd1;
+ localparam c22 = 23'd1;
+ localparam c23 = 23'd0;
always @(posedge clock)
if(reset)
diff --git a/fpga/usrp2/sdr_lib/dsp_core_rx.v b/fpga/usrp2/sdr_lib/dsp_core_rx.v
index 2ac429630..1e689fc7f 100644
--- a/fpga/usrp2/sdr_lib/dsp_core_rx.v
+++ b/fpga/usrp2/sdr_lib/dsp_core_rx.v
@@ -32,6 +32,10 @@ module dsp_core_rx
wire strobe_cic, strobe_hb1, strobe_hb2;
wire enable_hb1, enable_hb2;
wire [7:0] cic_decim_rate;
+
+ wire [31:10] UNUSED_1;
+ wire [31:4] UNUSED_2;
+ wire [31:2] UNUSED_3;
setting_reg #(.my_addr(BASE+0)) sr_0
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
@@ -43,7 +47,7 @@ module dsp_core_rx
setting_reg #(.my_addr(BASE+2)) sr_2
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
- .in(set_data),.out({enable_hb1, enable_hb2, cic_decim_rate}),.changed());
+ .in(set_data),.out({UNUSED_1, enable_hb1, enable_hb2, cic_decim_rate}),.changed());
rx_dcoffset #(.WIDTH(14),.ADDR(BASE+3)) rx_dcoffset_a
(.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
@@ -56,12 +60,12 @@ module dsp_core_rx
wire [3:0] muxctrl;
setting_reg #(.my_addr(BASE+5)) sr_8
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
- .in(set_data),.out(muxctrl),.changed());
+ .in(set_data),.out({UNUSED_2,muxctrl}),.changed());
wire [1:0] gpio_ena;
setting_reg #(.my_addr(BASE+6)) sr_9
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
- .in(set_data),.out(gpio_ena),.changed());
+ .in(set_data),.out({UNUSED_3,gpio_ena}),.changed());
// The TVRX connects to what is called adc_b, thus A and B are
// swapped throughout the design.
diff --git a/fpga/usrp2/top/u2_rev3/Makefile b/fpga/usrp2/top/u2_rev3/Makefile
index 1fd8638d9..867fb5cab 100644
--- a/fpga/usrp2/top/u2_rev3/Makefile
+++ b/fpga/usrp2/top/u2_rev3/Makefile
@@ -199,7 +199,7 @@ top/u2_rev3/u2_rev3.v
# Process Properties
##################################################
export SYNTHESIZE_PROPERTIES := \
-"Number of Clock Buffers" 6 \
+"Number of Clock Buffers" 8 \
"Pack I/O Registers into IOBs" Yes \
"Optimization Effort" High \
"Optimize Instantiated Primitives" TRUE \
diff --git a/fpga/usrp2/top/u2_rev3/u2_rev3.ucf b/fpga/usrp2/top/u2_rev3/u2_rev3.ucf
index 255a298ac..6aa699d2a 100644
--- a/fpga/usrp2/top/u2_rev3/u2_rev3.ucf
+++ b/fpga/usrp2/top/u2_rev3/u2_rev3.ucf
@@ -331,3 +331,5 @@ NET "cpld_clk" CLOCK_DEDICATED_ROUTE = FALSE;
#NET "adc_a<*>" OFFSET = IN 1 ns VALID 5 ns BEFORE "clk_fpga_p" RISING;
#NET "adc_b<*>" OFFSET = IN 1 ns VALID 5 ns BEFORE "clk_fpga_p" RISING;
+
+TIMESPEC "TS_clk_div_to_dsp_clk" = FROM "clk_div" TO "dcm_out" 10 ns;
diff --git a/fpga/usrp2/top/u2_rev3/u2_rev3.v b/fpga/usrp2/top/u2_rev3/u2_rev3.v
index 23a825007..3a43e4ffe 100644
--- a/fpga/usrp2/top/u2_rev3/u2_rev3.v
+++ b/fpga/usrp2/top/u2_rev3/u2_rev3.v
@@ -171,8 +171,15 @@ module u2_rev3
wd <= wd + 1;
assign WDI = wd[15];
- IBUFGDS clk_fpga_pin (.O(clk_fpga),.I(clk_fpga_p),.IB(clk_fpga_n));
+ wire clk_fpga_unbuf;
+
+ IBUFGDS clk_fpga_pin (.O(clk_fpga_unbuf),.I(clk_fpga_p),.IB(clk_fpga_n));
+ BUFG clk_fpga_BUF (.O(clk_fpga),.I(clk_fpga_unbuf));
+
defparam clk_fpga_pin.IOSTANDARD = "LVPECL_25";
+
+ wire cpld_clock_buf;
+ BUFG cpld_clock_BUF (.O(cpld_clock_buf),.I(cpld_clock));
wire exp_pps_in;
IBUFDS exp_pps_in_pin (.O(exp_pps_in),.I(exp_pps_in_p),.IB(exp_pps_in_n));
@@ -310,7 +317,9 @@ module u2_rev3
reg [15:0] ser_r_int;
reg ser_rklsb_int, ser_rkmsb_int;
- always @(posedge ser_rx_clk)
+ wire ser_rx_clk_buf;
+ BUFG ser_rx_clk_BUF (.O(ser_rx_clk_buf),.I(ser_rx_clk));
+ always @(posedge ser_rx_clk_buf)
begin
ser_r_int <= ser_r;
ser_rklsb_int <= ser_rklsb;
@@ -367,7 +376,7 @@ module u2_rev3
.ser_t (ser_t_unreg[15:0]),
.ser_tklsb (ser_tklsb_unreg),
.ser_tkmsb (ser_tkmsb_unreg),
- .ser_rx_clk (ser_rx_clk),
+ .ser_rx_clk (ser_rx_clk_buf),
.ser_r (ser_r_int[15:0]),
.ser_rklsb (ser_rklsb_int),
.ser_rkmsb (ser_rkmsb_int),
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt
index bf8d71b21..f2725e4b3 100644
--- a/host/CMakeLists.txt
+++ b/host/CMakeLists.txt
@@ -68,7 +68,6 @@ IF(WIN32)
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
- ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) #avoid warnings from std::getenv
ADD_DEFINITIONS(-DBOOST_ALL_DYN_LINK) #setup boost auto-linking in msvc
ENDIF(WIN32)
@@ -76,7 +75,7 @@ ENDIF(WIN32)
# Setup Boost
########################################################################
SET(Boost_ADDITIONAL_VERSIONS "1.42.0" "1.42")
-FIND_PACKAGE(Boost 1.37 REQUIRED COMPONENTS
+FIND_PACKAGE(Boost 1.36 REQUIRED COMPONENTS
date_time
filesystem
program_options
diff --git a/host/docs/build.rst b/host/docs/build.rst
index 81e61475e..d28682764 100644
--- a/host/docs/build.rst
+++ b/host/docs/build.rst
@@ -40,7 +40,7 @@ CMake
^^^^^^^^^^^^^^^^
Boost
^^^^^^^^^^^^^^^^
-* **Version:** at least 3.7 unix, at least 4.0 windows
+* **Version:** at least 3.6 unix, at least 4.0 windows
* **Required for:** build time + run time
* **Download URL:** http://www.boost.org/users/download/
* **Download URL (windows installer):** http://www.boostpro.com/download
diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst
index f4c36fb27..dfde06b27 100644
--- a/host/docs/usrp2.rst
+++ b/host/docs/usrp2.rst
@@ -117,6 +117,17 @@ Run the following commands:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Debugging networking problems
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+**Disable the firewall:**
+If uhd_find_devices gives you nothing
+but uhd_find_devices --args addr=192.168.10.2 yeilds a discovered device,
+then your firewall may be blocking replies to UDP broadcast packets.
+
+**Ping the USRP2:**
+The USRP2 will reply to icmp echo requests.
+::
+
+ ping 192.168.10.2
+
**Monitor the USRP2:**
You can read the serial port on the rear of the USRP2
to get debug verbose from the embedded microcontroller.
diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp
index 941219ac7..32eafc89b 100644
--- a/host/include/uhd/config.hpp
+++ b/host/include/uhd/config.hpp
@@ -39,27 +39,23 @@
//define logical operators
#ifdef BOOST_MSVC
- #define not !
- #define and &&
- #define or ||
+ #include <ciso646>
#endif
// http://gcc.gnu.org/wiki/Visibility
// Generic helper definitions for shared library support
-#if defined _WIN32 || defined __CYGWIN__
+#if defined(BOOST_HAS_DECLSPEC)
#define UHD_HELPER_DLL_IMPORT __declspec(dllimport)
#define UHD_HELPER_DLL_EXPORT __declspec(dllexport)
#define UHD_HELPER_DLL_LOCAL
+#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")))
#else
- #if __GNUC__ >= 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")))
- #else
- #define UHD_HELPER_DLL_IMPORT
- #define UHD_HELPER_DLL_EXPORT
- #define UHD_HELPER_DLL_LOCAL
- #endif
+ #define UHD_HELPER_DLL_IMPORT
+ #define UHD_HELPER_DLL_EXPORT
+ #define UHD_HELPER_DLL_LOCAL
#endif
// Now we use the generic helper definitions above to define UHD_API and UHD_LOCAL.
diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp
index c74e6d7b7..525606a9f 100644
--- a/host/include/uhd/transport/udp_zero_copy.hpp
+++ b/host/include/uhd/transport/udp_zero_copy.hpp
@@ -50,23 +50,15 @@ public:
*
* \param addr a string representing the destination address
* \param port a string representing the destination port
+ * \param recv_buff_size size in bytes for the recv buffer, 0 for automatic
+ * \param send_buff_size size in bytes for the send buffer, 0 for automatic
*/
- static sptr make(const std::string &addr, const std::string &port);
-
- /*!
- * Resize the the rx buffer size on the socket.
- * \param num_bytes the new size for the socket buffer
- * \return the actual number of bytes allowed by the OS
- */
- virtual size_t resize_recv_buff_size(size_t num_bytes) = 0;
-
- /*!
- * Resize the the tx buffer size on the socket.
- * \param num_bytes the new size for the socket buffer
- * \return the actual number of bytes allowed by the OS
- */
- virtual size_t resize_send_buff_size(size_t num_bytes) = 0;
-
+ static sptr make(
+ const std::string &addr,
+ const std::string &port,
+ size_t recv_buff_size = 0,
+ size_t send_buff_size = 0
+ );
};
}} //namespace
diff --git a/host/include/uhd/types/device_addr.hpp b/host/include/uhd/types/device_addr.hpp
index e8da2a1ab..e359d9467 100644
--- a/host/include/uhd/types/device_addr.hpp
+++ b/host/include/uhd/types/device_addr.hpp
@@ -40,7 +40,7 @@ namespace uhd{
* An arguments string, is a way to represent a device address
* using a single string with delimiter characters.
* - Ex: addr=192.168.10.2
- * - Ex: addr=192.168.10.2, rx_buff_size=1e6
+ * - Ex: addr=192.168.10.2, recv_buff_size=1e6
*/
class UHD_API device_addr_t : public dict<std::string, std::string>{
public:
@@ -51,17 +51,17 @@ namespace uhd{
device_addr_t(const std::string &args = "");
/*!
- * Convert a device address into a printable string.
- * \return string good for use with std::cout <<
+ * Convert a device address into a pretty print string.
+ * \return a printable string representing the device address
*/
- std::string to_string(void) const;
+ std::string to_pp_string(void) const;
/*!
* Convert the device address into an args string.
* The args string contains delimiter symbols.
* \return a string with delimiter markup
*/
- std::string to_args_str(void) const;
+ std::string to_string(void) const;
};
//handy typedef for a vector of device addresses
diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp
index c8fbc5a9f..b5fb11120 100644
--- a/host/include/uhd/types/dict.hpp
+++ b/host/include/uhd/types/dict.hpp
@@ -29,7 +29,7 @@ namespace uhd{
/*!
* A templated dictionary class with a python-like interface.
*/
- template <class Key, class Val> class dict{
+ template <typename Key, typename Val> class dict{
public:
typedef std::pair<Key, Val> pair_t;
@@ -130,7 +130,7 @@ namespace uhd{
BOOST_FOREACH(pair_t &p, _map){
if (p.first == key) return p.second;
}
- _map.push_back(pair_t(key, Val()));
+ _map.push_back(std::make_pair(key, Val()));
return _map.back().second;
}
diff --git a/host/include/uhd/usrp/dboard_base.hpp b/host/include/uhd/usrp/dboard_base.hpp
index 2025760ee..28bf2ae66 100644
--- a/host/include/uhd/usrp/dboard_base.hpp
+++ b/host/include/uhd/usrp/dboard_base.hpp
@@ -22,7 +22,6 @@
#include <uhd/wax.hpp>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
-#include <boost/tuple/tuple.hpp>
#include <uhd/usrp/dboard_id.hpp>
#include <uhd/usrp/dboard_iface.hpp>
@@ -35,13 +34,15 @@ namespace uhd{ namespace usrp{
class UHD_API dboard_base : boost::noncopyable{
public:
typedef boost::shared_ptr<dboard_base> sptr;
- //the constructor args consist of a subdev name, interface, and ids
- //derived classes should pass the args into the dboard_base class ctor
- //but should not have to deal with the internals of the args
- typedef boost::tuple<std::string, dboard_iface::sptr, dboard_id_t, dboard_id_t> ctor_args_t;
+ /*!
+ * An opaque type for the dboard constructor args.
+ * Derived classes should pass the args into the base class,
+ * but should not deal with the internals of the args.
+ */
+ struct ctor_args_impl; typedef ctor_args_impl* ctor_args_t;
//structors
- dboard_base(ctor_args_t const&);
+ dboard_base(ctor_args_t);
virtual ~dboard_base(void);
//interface
@@ -57,9 +58,8 @@ protected:
dboard_id_t get_tx_id(void);
private:
- std::string _subdev_name;
- dboard_iface::sptr _dboard_iface;
- dboard_id_t _rx_id, _tx_id;
+ struct dboard_base_impl;
+ dboard_base_impl *_impl;
};
/*!
@@ -71,7 +71,7 @@ public:
/*!
* Create a new xcvr dboard object, override in subclasses.
*/
- xcvr_dboard_base(ctor_args_t const&);
+ xcvr_dboard_base(ctor_args_t);
virtual ~xcvr_dboard_base(void);
};
@@ -85,7 +85,7 @@ public:
/*!
* Create a new rx dboard object, override in subclasses.
*/
- rx_dboard_base(ctor_args_t const&);
+ rx_dboard_base(ctor_args_t);
virtual ~rx_dboard_base(void);
@@ -103,7 +103,7 @@ public:
/*!
* Create a new rx dboard object, override in subclasses.
*/
- tx_dboard_base(ctor_args_t const&);
+ tx_dboard_base(ctor_args_t);
virtual ~tx_dboard_base(void);
diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp
index afacaf8ff..8b6eaf6bd 100644
--- a/host/include/uhd/usrp/dboard_id.hpp
+++ b/host/include/uhd/usrp/dboard_id.hpp
@@ -20,16 +20,70 @@
#include <uhd/config.hpp>
#include <boost/cstdint.hpp>
+#include <boost/operators.hpp>
#include <string>
namespace uhd{ namespace usrp{
-typedef boost::uint16_t dboard_id_t;
+ class UHD_API dboard_id_t : boost::equality_comparable1<dboard_id_t>{
+ public:
+ /*!
+ * Create a dboard id from an integer.
+ * \param id the integer representation
+ */
+ dboard_id_t(boost::uint16_t id = 0xffff);
-namespace dboard_id{
- static const dboard_id_t NONE = 0xffff;
- UHD_API std::string to_string(const dboard_id_t &id);
-}
+ /*!
+ * Obtain a dboard id that represents no dboard.
+ * \return the dboard id with the 0xffff id.
+ */
+ static dboard_id_t none(void);
+
+ /*!
+ * Create a new dboard id from an integer representation.
+ * \param uint16 an unsigned 16 bit integer
+ * \return a new dboard id containing the integer
+ */
+ static dboard_id_t from_uint16(boost::uint16_t uint16);
+
+ /*!
+ * Get the dboard id represented as an integer.
+ * \return an unsigned 16 bit integer representation
+ */
+ boost::uint16_t to_uint16(void) const;
+
+ /*!
+ * Create a new dboard id from a string representation.
+ * If the string has a 0x prefix, it will be parsed as hex.
+ * \param string a numeric string, possibly hex
+ * \return a new dboard id containing the integer
+ */
+ static dboard_id_t from_string(const std::string &string);
+
+ /*!
+ * Get the dboard id represented as an integer.
+ * \return a hex string representation with 0x prefix
+ */
+ std::string to_string(void) const;
+
+ /*!
+ * Get the pretty print representation of this dboard id.
+ * \return a string with the dboard name and id number
+ */
+ std::string to_pp_string(void) const;
+
+ private:
+ boost::uint16_t _id; //internal representation
+ };
+
+ /*!
+ * Comparator operator overloaded for dboard ids.
+ * The boost::equality_comparable provides the !=.
+ * \param lhs the dboard id to the left of the operator
+ * \param rhs the dboard id to the right of the operator
+ * \return true when the dboard ids are equal
+ */
+ UHD_API bool operator==(const dboard_id_t &lhs, const dboard_id_t &rhs);
}} //namespace
diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp
index 007d85bb4..b84fee4e7 100644
--- a/host/include/uhd/usrp/dboard_manager.hpp
+++ b/host/include/uhd/usrp/dboard_manager.hpp
@@ -37,7 +37,7 @@ public:
typedef boost::shared_ptr<dboard_manager> sptr;
//dboard constructor (each dboard should have a ::make with this signature)
- typedef dboard_base::sptr(*dboard_ctor_t)(dboard_base::ctor_args_t const&);
+ typedef dboard_base::sptr(*dboard_ctor_t)(dboard_base::ctor_args_t);
/*!
* Register a dboard into the system.
diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt
index 2831ab0b0..f588c6310 100644
--- a/host/include/uhd/utils/CMakeLists.txt
+++ b/host/include/uhd/utils/CMakeLists.txt
@@ -18,6 +18,7 @@
INSTALL(FILES
algorithm.hpp
assert.hpp
+ exception.hpp
gain_handler.hpp
props.hpp
safe_main.hpp
diff --git a/host/include/uhd/utils/algorithm.hpp b/host/include/uhd/utils/algorithm.hpp
index 8fe9cde82..72b655745 100644
--- a/host/include/uhd/utils/algorithm.hpp
+++ b/host/include/uhd/utils/algorithm.hpp
@@ -19,43 +19,25 @@
#define INCLUDED_UHD_UTILS_ALGORITHM_HPP
#include <algorithm>
+#include <boost/range/functions.hpp>
/*!
* Useful templated functions and classes that I like to pretend are part of stl
*/
namespace std{
- template<class T, class InputIterator, class Function>
- T reduce(InputIterator first, InputIterator last, Function fcn, T init = 0){
- T tmp = init;
- for ( ; first != last; ++first ){
- tmp = fcn(tmp, *first);
- }
- return tmp;
+ template<typename Range, typename T> inline
+ bool has(const Range &range, const T &value){
+ return boost::end(range) != std::find(boost::begin(range), boost::end(range), value);
}
- template<class T, class Iterable, class Function>
- T reduce(Iterable iterable, Function fcn, T init = 0){
- return reduce(iterable.begin(), iterable.end(), fcn, init);
- }
-
- template<class T, class InputIterator>
- bool has(InputIterator first, InputIterator last, const T &elem){
- return last != std::find(first, last, elem);
- }
-
- template<class T, class Iterable>
- bool has(const Iterable &iterable, const T &elem){
- return has(iterable.begin(), iterable.end(), elem);
- }
-
- template<class T> T signum(T n){
+ template<typename T> inline T signum(T n){
if (n < 0) return -1;
if (n > 0) return 1;
return 0;
}
- template<class T> T clip(T val, T minVal, T maxVal){
+ template<typename T> inline T clip(T val, T minVal, T maxVal){
return std::min(std::max(val, minVal), maxVal);
}
diff --git a/host/include/uhd/utils/assert.hpp b/host/include/uhd/utils/assert.hpp
index 01beed757..2f0ed4ff1 100644
--- a/host/include/uhd/utils/assert.hpp
+++ b/host/include/uhd/utils/assert.hpp
@@ -19,26 +19,24 @@
#define INCLUDED_UHD_UTILS_ASSERT_HPP
#include <uhd/config.hpp>
+#include <uhd/utils/exception.hpp>
#include <uhd/utils/algorithm.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
-#include <boost/throw_exception.hpp>
-#include <boost/exception/info.hpp>
#include <stdexcept>
#include <string>
namespace uhd{
//! The exception to throw when assertions fail
- struct UHD_API assert_error : virtual std::exception, virtual boost::exception{};
-
- //! The assertion info, the code that failed
- typedef boost::error_info<struct tag_assert_info, std::string> assert_info;
+ struct UHD_API assert_error : std::runtime_error{
+ assert_error(const std::string &what);
+ };
//! Throw an assert error with throw-site information
#define UHD_ASSERT_THROW(_x) if (not (_x)) \
- BOOST_THROW_EXCEPTION(uhd::assert_error() << uhd::assert_info(#_x))
+ throw uhd::assert_error(UHD_THROW_SITE_INFO("assertion failed: " + std::string(#_x)))
/*!
* Check that an element is found in a container.
@@ -46,30 +44,31 @@ namespace uhd{
* The "what" in the error will show what is
* being set and a list of known good values.
*
- * \param iterable a list of possible settings
- * \param elem an element that may be in the list
+ * \param range a list of possible settings
+ * \param value an element that may be in the list
* \param what a description of what is being set
* \throw assertion_error when elem not in list
*/
- template<class T, class Iterable> void assert_has(
- const Iterable &iterable,
- const T &elem,
+ template<typename T, typename Range> void assert_has(
+ const Range &range,
+ const T &value,
const std::string &what = "unknown"
){
- if (std::has(iterable, elem)) return;
+ if (std::has(range, value)) return;
std::string possible_values = "";
size_t i = 0;
- BOOST_FOREACH(const T &e, iterable){
+ BOOST_FOREACH(const T &v, range){
if (i++ > 0) possible_values += ", ";
- possible_values += boost::lexical_cast<std::string>(e);
+ possible_values += boost::lexical_cast<std::string>(v);
}
- boost::throw_exception(uhd::assert_error() << assert_info(str(boost::format(
- "Error: %s is not a valid %s. "
- "Possible values are: [%s]."
+ throw uhd::assert_error(str(boost::format(
+ "assertion failed:\n"
+ " %s is not a valid %s.\n"
+ " possible values are: [%s].\n"
)
- % boost::lexical_cast<std::string>(elem)
+ % boost::lexical_cast<std::string>(value)
% what % possible_values
- )));
+ ));
}
}//namespace uhd
diff --git a/host/include/uhd/utils/exception.hpp b/host/include/uhd/utils/exception.hpp
new file mode 100644
index 000000000..40e81fae0
--- /dev/null
+++ b/host/include/uhd/utils/exception.hpp
@@ -0,0 +1,38 @@
+//
+// 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_UTILS_EXCEPTION_HPP
+#define INCLUDED_UHD_UTILS_EXCEPTION_HPP
+
+#include <uhd/config.hpp>
+#include <boost/current_function.hpp>
+#include <stdexcept>
+#include <string>
+
+/*!
+ * Create a formated string with throw-site information.
+ * Fills in the function name, file name, and line number.
+ * \param what the std::exeption message
+ * \return the formatted exception message
+ */
+#define UHD_THROW_SITE_INFO(what) std::string( \
+ std::string(what) + "\n" + \
+ " in " + std::string(BOOST_CURRENT_FUNCTION) + "\n" + \
+ " at " + std::string(__FILE__) + ":" + BOOST_STRINGIZE(__LINE__) + "\n" \
+)
+
+#endif /* INCLUDED_UHD_UTILS_EXCEPTION_HPP */
diff --git a/host/include/uhd/utils/props.hpp b/host/include/uhd/utils/props.hpp
index 516102a5f..f376d2612 100644
--- a/host/include/uhd/utils/props.hpp
+++ b/host/include/uhd/utils/props.hpp
@@ -20,9 +20,8 @@
#include <uhd/config.hpp>
#include <uhd/wax.hpp>
+#include <uhd/utils/exception.hpp>
#include <boost/tuple/tuple.hpp>
-#include <boost/throw_exception.hpp>
-#include <boost/exception/info.hpp>
#include <stdexcept>
#include <vector>
#include <string>
@@ -59,25 +58,19 @@ namespace uhd{
const std::string &name = ""
);
- //! The exception to throw for property errors
- struct UHD_API prop_error : virtual std::exception, virtual boost::exception{};
-
- //! The property error info (verbose or message)
- typedef boost::error_info<struct tag_prop_info, std::string> prop_info;
-
/*!
* Throw when getting a not-implemented or write-only property.
* Throw-site information will be included with this error.
*/
#define UHD_THROW_PROP_GET_ERROR() \
- BOOST_THROW_EXCEPTION(uhd::prop_error() << uhd::prop_info("cannot get this property"))
+ throw std::runtime_error(UHD_THROW_SITE_INFO("cannot get this property"))
/*!
* Throw when setting a not-implemented or read-only property.
* Throw-site information will be included with this error.
*/
#define UHD_THROW_PROP_SET_ERROR() \
- BOOST_THROW_EXCEPTION(uhd::prop_error() << uhd::prop_info("cannot set this property"))
+ throw std::runtime_error(UHD_THROW_SITE_INFO("cannot set this property"))
} //namespace uhd
diff --git a/host/include/uhd/utils/safe_main.hpp b/host/include/uhd/utils/safe_main.hpp
index a4e4e06e8..b682aa540 100644
--- a/host/include/uhd/utils/safe_main.hpp
+++ b/host/include/uhd/utils/safe_main.hpp
@@ -19,7 +19,6 @@
#define INCLUDED_UHD_UTILS_SAFE_MAIN_HPP
#include <uhd/config.hpp>
-#include <boost/exception/diagnostic_information.hpp>
#include <iostream>
#include <stdexcept>
@@ -34,8 +33,6 @@
int main(int argc, char *argv[]){ \
try { \
return _main(argc, argv); \
- } catch(const boost::exception &e){ \
- std::cerr << "Error: " << boost::diagnostic_information(e) << std::endl; \
} catch(const std::exception &e) { \
std::cerr << "Error: " << e.what() << std::endl; \
} catch(...) { \
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index 5252eda8f..7b765b0d3 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -15,7 +15,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-
########################################################################
# Setup Python
########################################################################
@@ -43,29 +42,13 @@ IF(NOT HAVE_PYTHON_MODULE_CHEETAH)
ENDIF(NOT HAVE_PYTHON_MODULE_CHEETAH)
########################################################################
-# Create a list of libuhd sources
+# Helpful Macros
########################################################################
-SET(libuhd_sources
- device.cpp
- gain_handler.cpp
- load_modules.cpp
- types.cpp
- utils.cpp
- wax.cpp
- transport/convert_types.cpp
- transport/if_addrs.cpp
- transport/udp_simple.cpp
- usrp/dboard_base.cpp
- usrp/dboard_eeprom.cpp
- usrp/simple_usrp.cpp
- usrp/dboard_manager.cpp
- usrp/tune_helper.cpp
-)
+MACRO(LIBUHD_APPEND_SOURCES)
+ LIST(APPEND libuhd_sources ${ARGV})
+ENDMACRO(LIBUHD_APPEND_SOURCES)
-########################################################################
-# Generate Files
-########################################################################
-MACRO(UHD_PYTHON_GEN_SOURCE_FILE pyfile outfile)
+MACRO(LIBUHD_PYTHON_GEN_SOURCE pyfile outfile)
#ensure that the directory exists for outfile
GET_FILENAME_COMPONENT(outfile_dir ${outfile} PATH)
FILE(MAKE_DIRECTORY ${outfile_dir})
@@ -78,75 +61,17 @@ MACRO(UHD_PYTHON_GEN_SOURCE_FILE pyfile outfile)
)
#make libuhd depend on the outfile
- LIST(APPEND libuhd_sources ${outfile})
-ENDMACRO(UHD_PYTHON_GEN_SOURCE_FILE)
-
-UHD_PYTHON_GEN_SOURCE_FILE(
- ${CMAKE_CURRENT_SOURCE_DIR}/transport/gen_vrt.py
- ${CMAKE_CURRENT_BINARY_DIR}/transport/vrt.cpp
-)
-
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps)
-
-UHD_PYTHON_GEN_SOURCE_FILE(
- ${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/gen_adf4360_regs.py
- ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/adf4360_regs.hpp
-)
-
-UHD_PYTHON_GEN_SOURCE_FILE(
- ${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/gen_ad9510_regs.py
- ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/ad9510_regs.hpp
-)
-
-UHD_PYTHON_GEN_SOURCE_FILE(
- ${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/gen_ad9777_regs.py
- ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/ad9777_regs.hpp
-)
-
-UHD_PYTHON_GEN_SOURCE_FILE(
- ${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/gen_ad5624_regs.py
- ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/ad5624_regs.hpp
-)
+ LIBUHD_APPEND_SOURCES(${outfile})
+ENDMACRO(LIBUHD_PYTHON_GEN_SOURCE)
-UHD_PYTHON_GEN_SOURCE_FILE(
- ${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/gen_ad7922_regs.py
- ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/ad7922_regs.hpp
-)
-
-UHD_PYTHON_GEN_SOURCE_FILE(
- ${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/gen_max2829_regs.py
- ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/max2829_regs.hpp
-)
-
-########################################################################
-# Add dboard sources
########################################################################
-LIST(APPEND libuhd_sources
- usrp/dboard/db_basic_and_lf.cpp
- usrp/dboard/db_rfx.cpp
- usrp/dboard/db_xcvr2450.cpp
-)
-
+# Include CMakeLists.txt from subdirectories
########################################################################
-# Add usrp2 sources
-########################################################################
-LIST(APPEND libuhd_sources
- usrp/usrp2/clock_control.cpp
- usrp/usrp2/dboard_impl.cpp
- usrp/usrp2/dboard_iface.cpp
- usrp/usrp2/dsp_impl.cpp
- usrp/usrp2/io_impl.cpp
- usrp/usrp2/mboard_impl.cpp
- usrp/usrp2/usrp2_iface.cpp
- usrp/usrp2/usrp2_impl.cpp
-)
-
-########################################################################
-# Conditionally add the udp sources
-########################################################################
-LIST(APPEND libuhd_sources
- transport/udp_zero_copy_asio.cpp
-)
+INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/CMakeLists.txt)
+INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/transport/CMakeLists.txt)
+INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/usrp/CMakeLists.txt)
+INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/usrp/dboard/CMakeLists.txt)
+INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/usrp/usrp2/CMakeLists.txt)
########################################################################
# Setup defines for module loading
@@ -168,23 +93,16 @@ ELSE(HAVE_DLFCN_H)
ENDIF(HAVE_DLFCN_H)
########################################################################
-# Setup defines for interface address discovery
+# Append to the list of sources for lib uhd
########################################################################
-MESSAGE(STATUS "Configuring interface address discovery...")
-
-INCLUDE(CheckIncludeFileCXX)
-CHECK_INCLUDE_FILE_CXX(ifaddrs.h HAVE_IFADDRS_H)
-CHECK_INCLUDE_FILE_CXX(winsock2.h HAVE_WINSOCK2_H)
-
-IF(HAVE_IFADDRS_H)
- MESSAGE(STATUS " Interface address discovery supported through getifaddrs.")
- ADD_DEFINITIONS(-DHAVE_IFADDRS_H)
-ELSEIF(HAVE_WINSOCK2_H)
- MESSAGE(STATUS " Interface address discovery supported through SIO_GET_INTERFACE_LIST.")
- ADD_DEFINITIONS(-DHAVE_WINSOCK2_H)
-ELSE(HAVE_IFADDRS_H)
- MESSAGE(STATUS " Interface address discovery not supported.")
-ENDIF(HAVE_IFADDRS_H)
+LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/device.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/gain_handler.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/load_modules.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/types.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/utils.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/wax.cpp
+)
########################################################################
# Setup libuhd library
diff --git a/host/lib/device.cpp b/host/lib/device.cpp
index 88bd2cff4..f139ecb20 100644
--- a/host/lib/device.cpp
+++ b/host/lib/device.cpp
@@ -105,14 +105,14 @@ device::sptr device::make(const device_addr_t &hint, size_t which){
//check that we found any devices
if (dev_addr_makers.size() == 0){
throw std::runtime_error(str(
- boost::format("No devices found for ----->\n%s") % hint.to_string()
+ boost::format("No devices found for ----->\n%s") % hint.to_pp_string()
));
}
//check that the which index is valid
if (dev_addr_makers.size() <= which){
throw std::runtime_error(str(
- boost::format("No device at index %d for ----->\n%s") % which % hint.to_string()
+ boost::format("No device at index %d for ----->\n%s") % which % hint.to_pp_string()
));
}
diff --git a/host/lib/ic_reg_maps/CMakeLists.txt b/host/lib/ic_reg_maps/CMakeLists.txt
new file mode 100644
index 000000000..63378eb89
--- /dev/null
+++ b/host/lib/ic_reg_maps/CMakeLists.txt
@@ -0,0 +1,65 @@
+#
+# 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/>.
+#
+
+#This file will be included by cmake, use absolute paths!
+
+INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/lib/ic_reg_maps)
+
+LIBUHD_PYTHON_GEN_SOURCE(
+ ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_adf4350_regs.py
+ ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/adf4350_regs.hpp
+)
+
+LIBUHD_PYTHON_GEN_SOURCE(
+ ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_adf4360_regs.py
+ ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/adf4360_regs.hpp
+)
+
+LIBUHD_PYTHON_GEN_SOURCE(
+ ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_ad9510_regs.py
+ ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/ad9510_regs.hpp
+)
+
+LIBUHD_PYTHON_GEN_SOURCE(
+ ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_ad9777_regs.py
+ ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/ad9777_regs.hpp
+)
+
+LIBUHD_PYTHON_GEN_SOURCE(
+ ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_ad5624_regs.py
+ ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/ad5624_regs.hpp
+)
+
+LIBUHD_PYTHON_GEN_SOURCE(
+ ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_ad7922_regs.py
+ ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/ad7922_regs.hpp
+)
+
+LIBUHD_PYTHON_GEN_SOURCE(
+ ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_max2829_regs.py
+ ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/max2829_regs.hpp
+)
+
+LIBUHD_PYTHON_GEN_SOURCE(
+ ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_ad9862_regs.py
+ ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/ad9862_regs.hpp
+)
+
+LIBUHD_PYTHON_GEN_SOURCE(
+ ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_ad9522_regs.py
+ ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/ad9522_regs.hpp
+)
diff --git a/host/lib/ic_reg_maps/common.py b/host/lib/ic_reg_maps/common.py
index d05470706..e27c2816d 100644
--- a/host/lib/ic_reg_maps/common.py
+++ b/host/lib/ic_reg_maps/common.py
@@ -16,23 +16,98 @@
#
import re
+import sys
import math
from Cheetah.Template import Template
+COMMON_TMPL = """\
+#import time
+/***********************************************************************
+ * This file was generated by $file on $time.strftime("%c")
+ **********************************************************************/
+
+\#ifndef INCLUDED_$(name.upper())_HPP
+\#define INCLUDED_$(name.upper())_HPP
+
+\#include <uhd/config.hpp>
+\#include <boost/cstdint.hpp>
+\#include <stdexcept>
+\#include <set>
+
+class $(name)_t{
+public:
+ #for $reg in $regs
+ #if $reg.get_enums()
+ enum $reg.get_type(){
+ #for $i, $enum in enumerate($reg.get_enums())
+ #set $end_comma = ',' if $i < len($reg.get_enums())-1 else ''
+ $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma
+ #end for
+ };
+ #end if
+ $reg.get_type() $reg.get_name();
+ #end for
+
+ $(name)_t(void){
+ _state = NULL;
+ #for $reg in $regs
+ $reg.get_name() = $reg.get_default();
+ #end for
+ }
+
+ ~$(name)_t(void){
+ delete _state;
+ }
+
+$body
+
+ void save_state(void){
+ if (_state == NULL) _state = new $(name)_t();
+ #for $reg in $regs
+ _state->$reg.get_name() = this->$reg.get_name();
+ #end for
+ }
+
+ template<typename T> std::set<T> get_changed_addrs(void){
+ if (_state == NULL) throw std::runtime_error("no saved state");
+ //check each register for changes
+ std::set<T> addrs;
+ #for $reg in $regs
+ if(_state->$reg.get_name() != this->$reg.get_name()){
+ addrs.insert($reg.get_addr());
+ }
+ #end for
+ return addrs;
+ }
+
+private:
+ $(name)_t *_state;
+};
+
+\#endif /* INCLUDED_$(name.upper())_HPP */
+"""
+
def parse_tmpl(_tmpl_text, **kwargs):
return str(Template(_tmpl_text, kwargs))
+def to_num(arg): return eval(arg)
+
class reg:
def __init__(self, reg_des):
+ try: self.parse(reg_des)
+ except Exception, e:
+ raise Exception, 'Error parsing register description: "%s"\nWhat: %s'%(reg_des, e)
+
+ def parse(self, reg_des):
x = re.match('^(\w*)\s*(\w*)\[(.*)\]\s*(\w*)\s*(.*)$', reg_des)
name, addr, bit_range, default, enums = x.groups()
#store variables
self._name = name
- self._addr = int(addr, 16)
+ self._addr = to_num(addr)
if ':' in bit_range: self._addr_spec = sorted(map(int, bit_range.split(':')))
else: self._addr_spec = int(bit_range), int(bit_range)
- self._default = int(default, 16)
+ self._default = to_num(default)
#extract enum
self._enums = list()
@@ -41,7 +116,7 @@ class reg:
for enum_str in map(str.strip, enums.split(',')):
if '=' in enum_str:
enum_name, enum_val = enum_str.split('=')
- enum_val = int(enum_val)
+ enum_val = to_num(enum_val)
else: enum_name = enum_str
self._enums.append((enum_name, enum_val))
enum_val += 1
@@ -53,8 +128,20 @@ class reg:
for key, val in self.get_enums():
if val == self._default: return str.upper('%s_%s'%(self.get_name(), key))
return self._default
- def get_stdint_type(self):\
- return 'uint%d_t'%max(2**math.ceil(math.log(self.get_bit_width(), 2)), 8)
+ def get_type(self):
+ if self.get_enums(): return '%s_t'%self.get_name()
+ return 'boost::uint%d_t'%max(2**math.ceil(math.log(self.get_bit_width(), 2)), 8)
def get_shift(self): return self._addr_spec[0]
def get_mask(self): return hex(int('1'*self.get_bit_width(), 2))
def get_bit_width(self): return self._addr_spec[1] - self._addr_spec[0] + 1
+
+def generate(name, regs_tmpl, body_tmpl='', file=__file__):
+ regs = map(reg, parse_tmpl(regs_tmpl).splitlines())
+ body = parse_tmpl(body_tmpl, regs=regs).replace('\n', '\n ').strip()
+ code = parse_tmpl(COMMON_TMPL,
+ name=name,
+ regs=regs,
+ body=body,
+ file=file,
+ )
+ open(sys.argv[1], 'w').write(code)
diff --git a/host/lib/ic_reg_maps/gen_ad5624_regs.py b/host/lib/ic_reg_maps/gen_ad5624_regs.py
index 9e8ae5be5..24401b878 100755
--- a/host/lib/ic_reg_maps/gen_ad5624_regs.py
+++ b/host/lib/ic_reg_maps/gen_ad5624_regs.py
@@ -16,67 +16,33 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import sys
-from common import *
-
########################################################################
# Template for raw text data describing registers
# name addr[bit range inclusive] default optional enums
########################################################################
-REGS_DATA_TMPL="""\
+REGS_TMPL="""\
data 0[4:15] 0
addr 0[16:18] 0 DAC_A=0, DAC_B=1, DAC_C=2, DAC_D=3, ALL=7
cmd 0[19:21] 0 wr_input_n, up_dac_n, wr_input_n_up_all, wr_up_dac_chan_n, power_down, reset, load_ldac
"""
########################################################################
-# Header and Source templates below
+# Template for methods in the body of the struct
########################################################################
-HEADER_TEXT="""
-#import time
-
-/***********************************************************************
- * This file was generated by $file on $time.strftime("%c")
- **********************************************************************/
-
-\#ifndef INCLUDED_AD5624_REGS_HPP
-\#define INCLUDED_AD5624_REGS_HPP
-
-\#include <boost/cstdint.hpp>
-
-struct ad5624_regs_t{
-#for $reg in $regs
- #if $reg.get_enums()
- enum $(reg.get_name())_t{
- #for $i, $enum in enumerate($reg.get_enums())
- #set $end_comma = ',' if $i < len($reg.get_enums())-1 else ''
- $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma
- #end for
- } $reg.get_name();
- #else
- boost::$reg.get_stdint_type() $reg.get_name();
- #end if
-#end for
-
- ad5624_regs_t(void){
-#for $reg in $regs
- $reg.get_name() = $reg.get_default();
-#end for
- }
-
- boost::uint32_t get_reg(void){
- boost::uint32_t reg = 0;
- #for $reg in filter(lambda r: r.get_addr() == 0, $regs)
- reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
- #end for
- return reg;
- }
-
-};
-
-\#endif /* INCLUDED_AD5624_REGS_HPP */
+BODY_TMPL="""\
+boost::uint32_t get_reg(void){
+ boost::uint32_t reg = 0;
+ #for $reg in filter(lambda r: r.get_addr() == 0, $regs)
+ reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
+ #end for
+ return reg;
+}
"""
if __name__ == '__main__':
- regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines())
- open(sys.argv[1], 'w').write(parse_tmpl(HEADER_TEXT, regs=regs, file=__file__))
+ import common; common.generate(
+ name='ad5624_regs',
+ regs_tmpl=REGS_TMPL,
+ body_tmpl=BODY_TMPL,
+ file=__file__,
+ )
diff --git a/host/lib/ic_reg_maps/gen_ad7922_regs.py b/host/lib/ic_reg_maps/gen_ad7922_regs.py
index 23f28c0da..5cec1924a 100755
--- a/host/lib/ic_reg_maps/gen_ad7922_regs.py
+++ b/host/lib/ic_reg_maps/gen_ad7922_regs.py
@@ -16,73 +16,39 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import sys
-from common import *
-
########################################################################
# Template for raw text data describing registers
# name addr[bit range inclusive] default optional enums
########################################################################
-REGS_DATA_TMPL="""\
+REGS_TMPL="""\
result 0[0:11] 0
mod 0[12] 0
chn 0[13] 0
"""
########################################################################
-# Header and Source templates below
+# Template for methods in the body of the struct
########################################################################
-HEADER_TEXT="""
-#import time
-
-/***********************************************************************
- * This file was generated by $file on $time.strftime("%c")
- **********************************************************************/
-
-\#ifndef INCLUDED_AD7922_REGS_HPP
-\#define INCLUDED_AD7922_REGS_HPP
-
-\#include <boost/cstdint.hpp>
-
-struct ad7922_regs_t{
-#for $reg in $regs
- #if $reg.get_enums()
- enum $(reg.get_name())_t{
- #for $i, $enum in enumerate($reg.get_enums())
- #set $end_comma = ',' if $i < len($reg.get_enums())-1 else ''
- $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma
- #end for
- } $reg.get_name();
- #else
- boost::$reg.get_stdint_type() $reg.get_name();
- #end if
-#end for
-
- ad7922_regs_t(void){
-#for $reg in $regs
- $reg.get_name() = $reg.get_default();
-#end for
- }
-
- boost::uint16_t get_reg(void){
- boost::uint16_t reg = 0;
- #for $reg in filter(lambda r: r.get_addr() == 0, $regs)
- reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
- #end for
- return reg;
- }
-
- void set_reg(boost::uint16_t reg){
- #for $reg in filter(lambda r: r.get_addr() == 0, $regs)
- $reg.get_name() = (reg >> $reg.get_shift()) & $reg.get_mask();
- #end for
- }
-
-};
-
-\#endif /* INCLUDED_AD7922_REGS_HPP */
+BODY_TMPL="""\
+boost::uint16_t get_reg(void){
+ boost::uint16_t reg = 0;
+ #for $reg in filter(lambda r: r.get_addr() == 0, $regs)
+ reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
+ #end for
+ return reg;
+}
+
+void set_reg(boost::uint16_t reg){
+ #for $reg in filter(lambda r: r.get_addr() == 0, $regs)
+ $reg.get_name() = $(reg.get_type())((reg >> $reg.get_shift()) & $reg.get_mask());
+ #end for
+}
"""
if __name__ == '__main__':
- regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines())
- open(sys.argv[1], 'w').write(parse_tmpl(HEADER_TEXT, regs=regs, file=__file__))
+ import common; common.generate(
+ name='ad7922_regs',
+ regs_tmpl=REGS_TMPL,
+ body_tmpl=BODY_TMPL,
+ file=__file__,
+ )
diff --git a/host/lib/ic_reg_maps/gen_ad9510_regs.py b/host/lib/ic_reg_maps/gen_ad9510_regs.py
index 2dc19c691..83236c921 100755
--- a/host/lib/ic_reg_maps/gen_ad9510_regs.py
+++ b/host/lib/ic_reg_maps/gen_ad9510_regs.py
@@ -16,14 +16,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import sys
-from common import *
-
########################################################################
# Template for raw text data describing registers
# name addr[bit range inclusive] default optional enums
########################################################################
-REGS_DATA_TMPL="""\
+REGS_TMPL="""\
########################################################################
## serial control port config
########################################################################
@@ -46,14 +43,14 @@ reset_all_counters 9[0] 0
ncounter_reset 9[1] 0
rcounter_reset 9[2] 0
cp_current_setting 9[4:6] 0 0_60ma, 1_2ma, 1_8ma, 2_4ma, 3_0ma, 3_6ma, 4_2ma, 4_8ma
-pll_power_down A[0:1] 0 normal=0, async_pd=1, sync_pd=3
-prescaler_value A[2:4] 0 div1, div2, 2_3, 4_5, 8_9, 16_17, 32_33, div3
-b_counter_bypass A[6] 0
-ref_counter_msb B[0:5] 0
-ref_counter_lsb C[0:7] 0
-antibacklash_pw D[0:1] 0 1_3ns, 2_9ns, 6_0ns
-dld_window D[5] 0 9_5ns, 3_5ns
-lock_detect_disable D[6] 0 enb, dis
+pll_power_down 0xA[0:1] 0 normal=0, async_pd=1, sync_pd=3
+prescaler_value 0xA[2:4] 0 div1, div2, 2_3, 4_5, 8_9, 16_17, 32_33, div3
+b_counter_bypass 0xA[6] 0
+ref_counter_msb 0xB[0:5] 0
+ref_counter_lsb 0xC[0:7] 0
+antibacklash_pw 0xD[0:1] 0 1_3ns, 2_9ns, 6_0ns
+dld_window 0xD[5] 0 9_5ns, 3_5ns
+lock_detect_disable 0xD[6] 0 enb, dis
########################################################################
## fine delay adjust
########################################################################
@@ -103,71 +100,40 @@ soft_sync 58[2] 0
dist_power_down 58[3] 0
sync_power_down 58[4] 0
function_pin_select 58[5:6] 0 resetb, syncb, test, pdb
-update_registers 5A[0] 0
+update_registers 0x5A[0] 0
"""
########################################################################
-# Header and Source templates below
+# Template for methods in the body of the struct
########################################################################
-HEADER_TEXT="""
-#import time
-
-/***********************************************************************
- * This file was generated by $file on $time.strftime("%c")
- **********************************************************************/
-
-\#ifndef INCLUDED_AD9510_REGS_HPP
-\#define INCLUDED_AD9510_REGS_HPP
-
-\#include <boost/cstdint.hpp>
-
-struct ad9510_regs_t{
-#for $reg in $regs
- #if $reg.get_enums()
- enum $(reg.get_name())_t{
- #for $i, $enum in enumerate($reg.get_enums())
- #set $end_comma = ',' if $i < len($reg.get_enums())-1 else ''
- $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma
+BODY_TMPL="""\
+boost::uint8_t get_reg(boost::uint16_t addr){
+ boost::uint8_t reg = 0;
+ switch(addr){
+ #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs)))
+ case $addr:
+ #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
+ reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
#end for
- } $reg.get_name();
- #else
- boost::$reg.get_stdint_type() $reg.get_name();
- #end if
-#end for
-
- ad9510_regs_t(void){
-#for $reg in $regs
- $reg.get_name() = $reg.get_default();
-#end for
- }
-
- boost::uint8_t get_reg(boost::uint16_t addr){
- boost::uint8_t reg = 0;
- switch(addr){
- #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs)))
- case $addr:
- #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
- reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
- #end for
- break;
- #end for
- }
- return reg;
- }
-
- boost::uint32_t get_write_reg(boost::uint16_t addr){
- return (boost::uint32_t(addr) << 8) | get_reg(addr);
- }
-
- boost::uint32_t get_read_reg(boost::uint16_t addr){
- return (boost::uint32_t(addr) << 8) | (1 << 15);
+ break;
+ #end for
}
+ return reg;
+}
-};
+boost::uint32_t get_write_reg(boost::uint16_t addr){
+ return (boost::uint32_t(addr) << 8) | get_reg(addr);
+}
-\#endif /* INCLUDED_AD9510_REGS_HPP */
+boost::uint32_t get_read_reg(boost::uint16_t addr){
+ return (boost::uint32_t(addr) << 8) | (1 << 23);
+}
"""
if __name__ == '__main__':
- regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines())
- open(sys.argv[1], 'w').write(parse_tmpl(HEADER_TEXT, regs=regs, file=__file__))
+ import common; common.generate(
+ name='ad9510_regs',
+ regs_tmpl=REGS_TMPL,
+ body_tmpl=BODY_TMPL,
+ file=__file__,
+ )
diff --git a/host/lib/ic_reg_maps/gen_ad9522_regs.py b/host/lib/ic_reg_maps/gen_ad9522_regs.py
new file mode 100755
index 000000000..9da51205b
--- /dev/null
+++ b/host/lib/ic_reg_maps/gen_ad9522_regs.py
@@ -0,0 +1,183 @@
+#!/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/>.
+#
+
+########################################################################
+# Template for raw text data describing registers
+# name addr[bit range inclusive] default optional enums
+########################################################################
+REGS_TMPL="""\
+sdo_active 0x000[7] 0 sdio, sdo_sdio
+lsb_first_addr_incr 0x000[6] 0 msb, lsb
+soft_reset 0x000[5] 0
+mirror 0x000[3:0] 0
+readback_active_registers 0x004[0] 0 buffer, active
+pfd_polarity 0x010[7] 0 pos, neg
+cp_current 0x010[6:4] 7 0_6ma, 1_2ma, 1_8ma, 2_4ma, 3_0ma, 3_6ma, 4_2ma, 4_8ma
+cp_mode 0x010[3:2] 3 high_imp, force_source, force_sink, normal
+pll_power_down 0x010[1:0] 1 normal=0, async=1, sync=3
+r_counter_lsb 0x011[7:0] 1
+r_counter_msb 0x012[5:0] 0
+a_counter 0x013[5:0] 0
+b_counter_lsb 0x014[7:0] 3
+b_counter_msb 0x015[4:0] 0
+set_cp_pin_to_vcp_2 0x016[7] 0 normal, vcp_2
+reset_r_counter 0x016[6] 0
+reset_a_and_b_counters 0x016[5] 0
+reset_all_counters 0x016[4] 0
+b_counter_bypass 0x016[3] 0 normal, div1
+prescaler_p 0x016[2:0] 6 div1, div2, div2_3, div4_5, div8_9, div16_17, div32_33, div3
+status_pin_control 0x017[7:2] 0
+antibacklash_pulse_width 0x017[1:0] 0 2_9ns, 1_3ns, 6_0ns
+enb_cmos_ref_input_dc_off 0x018[7] 0
+lock_detect_counter 0x018[6:5] 0 5cyc, 16cyc, 64cyc, 255cyc
+digital_lock_detect_window 0x018[4] 0 high_range, low_range
+disable_digital_lock_detect 0x018[3] 0 normal, disabled
+vco_calibration_divider 0x018[2:1] 3 div2, div4, div8, div16
+vco_calibration_now 0x018[0] 0
+r_a_b_counters_sync_pin_rst 0x019[7:6] 0 nothing, async, sync
+r_path_delay 0x019[5:3] 0
+n_path_delay 0x019[2:0] 0
+enable_status_pin_divider 0x01A[7] 0
+ref_freq_monitor_threshold 0x01A[6] 0 1_02mhz, 6khz
+ld_pin_control 0x01A[5:0] 0
+enable_vco_freq_monitor 0x01B[7] 0
+enable_ref2_freq_monitor 0x01B[6] 0
+enable_ref1_freq_monitor 0x01B[5] 0
+refmon_pin_control 0x01B[4:0] 0
+disable_switchover_deglitch 0x01C[7] 0
+select_ref 0x01C[6] 0 ref1, ref2
+use_ref_sel_pin 0x01C[5] 0 register, ref_sel
+enb_auto_ref_switchover 0x01C[4] 0 manual, auto
+stay_on_ref2 0x01C[3] 0 return_ref1, stay_ref2
+enable_ref2 0x01C[2] 0
+enable_ref1 0x01C[1] 0
+enable_differential_ref 0x01C[0] 0
+enb_stat_eeprom_at_stat_pin 0x01D[7] 1
+enable_xtal_osc 0x01D[6] 0
+enable_clock_doubler 0x01D[5] 0
+disable_pll_status_reg 0x01D[4] 0
+enable_ld_pin_comparator 0x01D[3] 0
+enable_external_holdover 0x01D[1] 0
+enable_holdover 0x01D[0] 0
+external_zero_delay_fcds 0x01E[4:3] 0
+enable_external_zero_delay 0x01E[2] 0
+enable_zero_delay 0x01E[1] 0
+########################################################################
+#for $i in range(12)
+#set $addr = ($i + 0x0F0)
+out$(i)_format $(addr)[7] 0 lvds, cmos
+out$(i)_cmos_configuration $(addr)[6:5] 3 off, a_on, b_on, ab_on
+out$(i)_polarity $(addr)[4:3] 0 lvds_a_non_b_inv=0, lvds_a_inv_b_non=1, cmos_ab_non=0, cmos_ab_inv=1, cmos_a_non_b_inv=2, cmos_a_inv_b_non=3
+out$(i)_lvds_diff_voltage $(addr)[2:1] 1 1_75ma, 3_5ma, 5_25ma, 7_0ma
+out$(i)_lvds_power_down $(addr)[0] 0
+#end for
+########################################################################
+#for $i in reversed(range(8))
+csdld_en_out_$i 0x0FC[$i] 0 ignore, async
+#end for
+########################################################################
+#for $i in reversed(range(4))
+csdld_en_out_$(8 + $i) 0x0FD[$i] 0 ignore, async
+#end for
+########################################################################
+#set $default_val = 0x7
+#for $i in range(4)
+#set $addr0 = hex($i*3 + 0x190)
+#set $addr1 = hex($i*3 + 0x191)
+#set $addr2 = hex($i*3 + 0x192)
+divider$(i)_low_cycles $(addr0)[7:4] $default_val
+divider$(i)_high_cycles $(addr0)[3:0] $default_val
+divider$(i)_bypass $(addr1)[7] 0
+divider$(i)_ignore_sync $(addr1)[6] 0
+divider$(i)_force_high $(addr1)[5] 0
+divider$(i)_start_high $(addr1)[4] 0
+divider$(i)_phase_offset $(addr1)[3:0] 0
+channel$(i)_power_down $(addr2)[2] 0
+disable_divider$(i)_ddc $(addr2)[0] 0
+#set $default_val /= 2
+#end for
+########################################################################
+vco_divider 0x1E0[2:0] 2 div2, div3, div4, div5, div6, static, div1
+power_down_clock_input_sel 0x1E1[4] 0
+power_down_vco_clock_ifc 0x1E1[3] 0
+power_down_vco_and_clock 0x1E1[2] 0
+select_vco_or_clock 0x1E1[1] 0 external, vco
+bypass_vco_divider 0x1E1[0] 0
+disable_power_on_sync 0x230[3] 0
+power_down_sync 0x230[2] 0
+power_down_dist_ref 0x230[1] 0
+soft_sync 0x230[0] 0
+io_update 0x232[0] 0
+soft_eeprom 0xB02[1] 0
+enable_eeprom_write 0xB02[0] 0
+reg2eeprom 0xB03[0] 0
+"""
+
+########################################################################
+# Template for methods in the body of the struct
+########################################################################
+BODY_TMPL="""\
+boost::uint8_t get_reg(boost::uint16_t addr){
+ boost::uint8_t reg = 0;
+ switch(addr){
+ #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs)))
+ case $addr:
+ #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
+ reg |= (boost::uint8_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
+ #end for
+ break;
+ #end for
+ }
+ if (addr == 0){ //mirror 4 bits in register 0
+ reg |= ((reg >> 7) & 0x1) << 0;
+ reg |= ((reg >> 6) & 0x1) << 1;
+ reg |= ((reg >> 5) & 0x1) << 2;
+ reg |= ((reg >> 4) & 0x1) << 3;
+ }
+ return reg;
+}
+
+void set_reg(boost::uint8_t addr, boost::uint32_t reg){
+ switch(addr){
+ #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs)))
+ case $addr:
+ #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
+ $reg.get_name() = $(reg.get_type())((reg >> $reg.get_shift()) & $reg.get_mask());
+ #end for
+ break;
+ #end for
+ }
+}
+
+boost::uint32_t get_write_reg(boost::uint16_t addr){
+ return (boost::uint32_t(addr) << 8) | get_reg(addr);
+}
+
+boost::uint32_t get_read_reg(boost::uint16_t addr){
+ return (boost::uint32_t(addr) << 8) | (1 << 23);
+}
+
+"""
+
+if __name__ == '__main__':
+ import common; common.generate(
+ name='ad9522_regs',
+ regs_tmpl=REGS_TMPL,
+ body_tmpl=BODY_TMPL,
+ file=__file__,
+ )
diff --git a/host/lib/ic_reg_maps/gen_ad9777_regs.py b/host/lib/ic_reg_maps/gen_ad9777_regs.py
index 2ac73efcf..abb839f0f 100755
--- a/host/lib/ic_reg_maps/gen_ad9777_regs.py
+++ b/host/lib/ic_reg_maps/gen_ad9777_regs.py
@@ -16,14 +16,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import sys
-from common import *
-
########################################################################
# Template for raw text data describing registers
# name addr[bit range inclusive] default optional enums
########################################################################
-REGS_DATA_TMPL="""\
+REGS_TMPL="""\
########################################################################
## address 0
########################################################################
@@ -73,79 +70,49 @@ qdac_fine_gain_adjust 9[0:7] 0
## address 6 and A
########################################################################
idac_coarse_gain_adjust 6[0:3] 0
-qdac_coarse_gain_adjust A[0:3] 0
+qdac_coarse_gain_adjust 0xA[0:3] 0
########################################################################
## address 7, 8 and B, C
########################################################################
idac_offset_adjust_msb 7[0:7] 0
idac_offset_adjust_lsb 8[0:1] 0
idac_ioffset_direction 8[7] 0 out_a, out_b
-qdac_offset_adjust_msb B[0:7] 0
-qdac_offset_adjust_lsb C[0:1] 0
-qdac_ioffset_direction C[7] 0 out_a, out_b
+qdac_offset_adjust_msb 0xB[0:7] 0
+qdac_offset_adjust_lsb 0xC[0:1] 0
+qdac_ioffset_direction 0xC[7] 0 out_a, out_b
"""
########################################################################
-# Header and Source templates below
+# Template for methods in the body of the struct
########################################################################
-HEADER_TEXT="""
-#import time
-
-/***********************************************************************
- * This file was generated by $file on $time.strftime("%c")
- **********************************************************************/
-
-\#ifndef INCLUDED_AD9777_REGS_HPP
-\#define INCLUDED_AD9777_REGS_HPP
-
-\#include <boost/cstdint.hpp>
-
-struct ad9777_regs_t{
-#for $reg in $regs
- #if $reg.get_enums()
- enum $(reg.get_name())_t{
- #for $i, $enum in enumerate($reg.get_enums())
- #set $end_comma = ',' if $i < len($reg.get_enums())-1 else ''
- $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma
- #end for
- } $reg.get_name();
- #else
- boost::$reg.get_stdint_type() $reg.get_name();
- #end if
-#end for
-
- ad9777_regs_t(void){
-#for $reg in $regs
- $reg.get_name() = $reg.get_default();
-#end for
- }
-
- boost::uint8_t get_reg(boost::uint8_t addr){
- boost::uint8_t reg = 0;
- switch(addr){
- #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs)))
- case $addr:
- #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
- reg |= (boost::uint8_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
- #end for
- break;
+BODY_TMPL="""\
+boost::uint8_t get_reg(boost::uint8_t addr){
+ boost::uint8_t reg = 0;
+ switch(addr){
+ #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs)))
+ case $addr:
+ #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
+ reg |= (boost::uint8_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
#end for
- }
- return reg;
+ break;
+ #end for
}
+ return reg;
+}
- boost::uint16_t get_write_reg(boost::uint8_t addr){
- return (boost::uint16_t(addr) << 8) | get_reg(addr);
- }
-
- boost::uint16_t get_read_reg(boost::uint8_t addr){
- return (boost::uint16_t(addr) << 8) | (1 << 7);
- }
-};
+boost::uint16_t get_write_reg(boost::uint8_t addr){
+ return (boost::uint16_t(addr) << 8) | get_reg(addr);
+}
-\#endif /* INCLUDED_AD9777_REGS_HPP */
+boost::uint16_t get_read_reg(boost::uint8_t addr){
+ return (boost::uint16_t(addr) << 8) | (1 << 7);
+}
"""
if __name__ == '__main__':
- regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines())
- open(sys.argv[1], 'w').write(parse_tmpl(HEADER_TEXT, regs=regs, file=__file__))
+ import common; common.generate(
+ name='ad9777_regs',
+ regs_tmpl=REGS_TMPL,
+ body_tmpl=BODY_TMPL,
+ file=__file__,
+ )
diff --git a/host/lib/ic_reg_maps/gen_ad9862_regs.py b/host/lib/ic_reg_maps/gen_ad9862_regs.py
new file mode 100755
index 000000000..fdbea5828
--- /dev/null
+++ b/host/lib/ic_reg_maps/gen_ad9862_regs.py
@@ -0,0 +1,246 @@
+#!/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/>.
+#
+
+########################################################################
+# Template for raw text data describing registers
+# name addr[bit range inclusive] default optional enums
+########################################################################
+REGS_TMPL="""\
+########################################################################
+## General
+########################################################################
+sdio_bidir 0[7] 0 sdio_sdo, sdio
+lsb_first 0[6] 0 msb, lsb
+soft_reset 0[5] 0
+########################################################################
+## Rx Power Down
+########################################################################
+pd_vref_diff 1[7] 0
+pd_vref 1[6] 0
+pd_rx_digital 1[5] 0
+pd_rx_channel_b 1[4] 0
+pd_rx_channel_a 1[3] 0
+pd_buffer_b 1[2] 0
+pd_buffer_a 1[1] 0
+pd_all_rx 1[0] 0
+########################################################################
+## Rx A and B
+########################################################################
+#for $x, $i in (('a', 2), ('b', 3))
+byp_buffer_$x $(i)[7] 0
+rx_pga_$x $(i)[0:4] 0
+#end for
+########################################################################
+## Rx Misc
+########################################################################
+hs_duty_cycle 4[2] 0
+shared_ref 4[1] 0
+clk_duty 4[0] 0
+########################################################################
+## RX I/F (INTERFACE)
+########################################################################
+three_state 5[4] 0
+rx_retime 5[3] 0 clkout1, clkout2
+rx_twos_comp 5[2] 0
+inv_rxsync 5[1] 0
+mux_out 5[0] 0 rx_mux_mode=1, dual_port_mode=0
+########################################################################
+## RX Digital
+########################################################################
+two_channel 6[3] 1 rx_b_dis, both_enb
+rx_keep_ve 6[2] 0 pass_pos, pass_neg
+rx_hilbert 6[1] 0 dis, enb
+decimate 6[0] 0 dis, enb
+########################################################################
+## TX Power Down
+########################################################################
+alt_timing_mode 8[5] 0
+txoff_enable 8[4] 0
+tx_digital_pd 8[3] 0
+tx_analog_pd 8[0:2] 0 none=0, txb=4, txa=2, both=7
+########################################################################
+## Tx Offset and Gain
+########################################################################
+#for $x, $i, $j, $k in (('a', 10, 11, 14), ('b', 12, 13, 15))
+dac_$(x)_offset_1_0 $(i)[6:7] 0
+dac_$(x)_offset_dir $(i)[0] 0 neg_diff, pos_dif
+dac_$(x)_offset_9_2 $(j)[0:7] 0
+dac_$(x)_coarse_gain $(k)[6:7] 0
+dac_$(x)_fine_gain $(k)[0:5] 0
+#end for
+tx_pga_gain 16[0:7] 0
+########################################################################
+## Tx Misc
+########################################################################
+tx_slave_enable 17[1] 0
+tx_pga_mode 17[0] 0 normal, fast
+########################################################################
+## Tx IF (INTERFACE)
+########################################################################
+tx_retime 18[6] 1 clkout1=1, clkout2=0
+qi_order 18[5] 0 iq, qi
+inv_txsync 18[4] 0
+tx_twos_comp 18[3] 0
+inverse_samp 18[2] 0 rise, fall
+edges 18[1] 0 normal, both
+interleaved 18[0] 0 single, interleaved
+########################################################################
+## TX Digital
+########################################################################
+two_data_paths 19[4] 0 single, both
+tx_keep_ve 19[3] 0 pass_pos, pass_neg
+tx_hilbert 19[2] 0 dis, enb
+interp 19[0:1] 0 1, 2, 4
+########################################################################
+## TX Modulator
+########################################################################
+neg_fine_tune 20[5] 0 pos_shift, neg_shift
+fine_mode 20[4] 0 bypass, nco
+real_mix_mode 20[3] 0 complex, real
+neg_coarse_tune 20[2] 0 pos_shift, neg_shift
+coarse_mod 20[0:1] 0 bypass, fdac_4, fdac_8
+########################################################################
+## NCO Tuning Word
+########################################################################
+ftw_7_0 21[0:7] 0
+ftw_15_8 22[0:7] 0
+ftw_23_16 23[0:7] 0
+########################################################################
+## DLL
+########################################################################
+input_clk_ctrl 24[6] 0 external, internal
+adc_div2 24[5] 0 normal, div2
+dll_mult 24[3:4] 0 1, 2, 4
+dll_pd 24[2] 0
+dll_mode 24[0] 0 slow, fast
+########################################################################
+## Clock Out
+########################################################################
+clkout2_div_factor 25[6:7] 0 1, 2, 4, 8
+inv2 25[5] 0 normal, inverted
+inv1 25[1] 0 normal, inverted
+dis2 25[4] 0 enb, dis
+dis1 25[0] 0 enb, dis
+########################################################################
+## Aux ADC
+########################################################################
+#for $x, $i in (('a2', 26), ('a1', 28), ('b2', 30), ('b1', 32))
+aux_adc_$(x)_1_0 $(i)[6:7] 0
+aux_adc_$(x)_9_2 $int(1+$i)[0:7] 0
+#end for
+########################################################################
+## Aux ADC Control
+########################################################################
+aux_spi 34[7] 0 dis, enb
+sel_bnota 34[6] 0 adc_a, adc_b
+#for $x, $i in (('b', 5), ('a', 2))
+refsel_$(x) 34[$i] 0 external, internal
+select_$(x) 34[$int($i-1)] 0 aux_adc2, aux_adc1
+start_$(x) 34[$int($i-2)] 0
+#end for
+########################################################################
+## Aux ADC Clock
+########################################################################
+clk_4 35[0] 0 1_2, 1_4
+########################################################################
+## Aux DAC
+########################################################################
+#for $x, $i in (('a', 36), ('b', 37), ('c', 38))
+aux_dac_$x $(i)[0:7] 0
+#end for
+########################################################################
+## Aux DAC Update
+########################################################################
+aux_dac_slave_enable 39[7] 0
+aux_dacupdate_c 39[2] 0
+aux_dacupdate_b 39[1] 0
+aux_dacupdate_a 39[0] 0
+########################################################################
+## AUX DAC Power Down
+########################################################################
+aux_dac_pd_a 40[2] 0
+aux_dac_pd_b 40[1] 0
+aux_dac_pd_c 40[0] 0
+########################################################################
+## AUX DAC Control
+########################################################################
+aux_dac_invert_a 41[2] 0
+aux_dac_invert_b 41[1] 0
+aux_dac_invert_c 41[0] 0
+########################################################################
+## Sig Delt
+########################################################################
+sig_delt_3_0 42[4:7] 0
+sig_delt_11_4 43[0:7] 0
+########################################################################
+## ADC Low Power
+########################################################################
+rx_low_power_mode_r49 49[0:7] 0
+rx_low_power_mode_r50 50[0:7] 0
+########################################################################
+## Chip ID
+########################################################################
+chip_id 63[0:7] 0
+"""
+
+########################################################################
+# Header and Source templates below
+########################################################################
+BODY_TMPL="""
+boost::uint8_t get_reg(boost::uint8_t addr){
+ boost::uint8_t reg = 0;
+ switch(addr){
+ #for $addr in range(0, 63+1)
+ case $addr:
+ #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
+ reg |= (boost::uint16_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
+ #end for
+ break;
+ #end for
+ }
+ return reg;
+}
+
+void set_reg(boost::uint8_t addr, boost::uint16_t reg){
+ switch(addr){
+ #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs)))
+ case $addr:
+ #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
+ $reg.get_name() = $(reg.get_type())((reg >> $reg.get_shift()) & $reg.get_mask());
+ #end for
+ break;
+ #end for
+ }
+}
+
+boost::uint16_t get_write_reg(boost::uint8_t addr){
+ return (boost::uint16_t(addr) << 8) | get_reg(addr);
+}
+
+boost::uint16_t get_read_reg(boost::uint8_t addr){
+ return (boost::uint16_t(addr) << 8) | (1 << 7);
+}
+"""
+
+if __name__ == '__main__':
+ import common; common.generate(
+ name='ad9862_regs',
+ regs_tmpl=REGS_TMPL,
+ body_tmpl=BODY_TMPL,
+ file=__file__,
+ )
diff --git a/host/lib/ic_reg_maps/gen_adf4350_regs.py b/host/lib/ic_reg_maps/gen_adf4350_regs.py
new file mode 100755
index 000000000..e97772843
--- /dev/null
+++ b/host/lib/ic_reg_maps/gen_adf4350_regs.py
@@ -0,0 +1,121 @@
+#!/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/>.
+#
+
+########################################################################
+# Template for raw text data describing registers
+# name addr[bit range inclusive] default optional enums
+########################################################################
+REGS_TMPL="""\
+########################################################################
+## address 0
+########################################################################
+frac_12_bit 0[3:14] 0
+int_16_bit 0[15:30] 0x23
+##reserved 0[31] 0
+########################################################################
+## address 1
+########################################################################
+mod_12_bit 1[3:14] 0xfff
+phase_12_bit 1[15:26] 0
+prescaler 1[27] 0 4_5, 8_9
+##reserved 1[28:31] 0
+########################################################################
+## address 2
+########################################################################
+counter_reset 2[3] 0 disabled, enabled
+cp_three_state 2[4] 0 disabled, enabled
+power_down 2[5] 0 disabled, enabled
+pd_polarity 2[6] 1 negative, positive
+ldp 2[7] 0 10ns, 6ns
+ldf 2[8] 0 frac_n, int_n
+#set $current_setting_enums = ', '.join(map(lambda x: '_'.join(("%0.2fma"%(round(x*31.27 + 31.27)/100)).split('.')), range(0,16)))
+charge_pump_current 2[9:12] 5 $current_setting_enums
+double_buffer 2[13] 0 disabled, enabled
+r_counter_10_bit 2[14:23] 0
+reference_divide_by_2 2[24] 1 disabled, enabled
+reference_doubler 2[25] 0 disabled, enabled
+muxout 2[26:28] 1 3state, dvdd, dgnd, rdiv, ndiv, analog_ld, dld, reserved
+low_noise_and_spur 2[29:30] 3 low_noise, reserved0, reserved1, low_spur
+########################################################################
+## address 3
+########################################################################
+clock_divider_12_bit 3[3:14] 0
+clock_div_mode 3[15:16] 0 clock_divider_off, fast_lock, resync_enable, reserved
+##reserved 3[17] 0
+cycle_slip_reduction 3[18] 0 disabled, enabled
+##reserved 3[19:20] 0
+##reserved 3[21:31] 0
+########################################################################
+## address 4
+########################################################################
+output_power 4[3:4] 3 m4dbm, m1dbm, 2dbm, 5dbm
+rf_output_enable 4[5] 1 disabled, enabled
+aux_output_power 4[6:7] 0 m4dbm, m1dbm, 2dbm, 5dbm
+aux_output_enable 4[8] 0 disabled, enabled
+aux_output_select 4[9] 1 divided, fundamental
+mute_till_lock_detect 4[10] 0 mute_disabled, mute_enabled
+vco_power_down 4[11] 0 vco_powered_up, vco_powered_down
+band_select_clock_div 4[12:19] 0
+rf_divider_select 4[20:22] 0 div1, div2, div4, div8, div16
+feedback_select 4[23] 1 divided, fundamental
+##reserved 4[24:31] 0
+########################################################################
+## address 5
+########################################################################
+##reserved 5[3:18] 0
+##reserved 5[19:20] 0
+##reserved 5[21] 0
+ld_pin_mode 5[22:23] 1 low0, dld, low, high
+##reserved 5[24:31] 0
+"""
+
+########################################################################
+# Template for methods in the body of the struct
+########################################################################
+BODY_TMPL="""\
+enum addr_t{
+ ADDR_R0 = 0,
+ ADDR_R1 = 1,
+ ADDR_R2 = 2,
+ ADDR_R3 = 3,
+ ADDR_R4 = 4,
+ ADDR_R5 = 5
+};
+
+boost::uint32_t get_reg(boost::uint8_t addr){
+ boost::uint32_t reg = addr & 0x7;
+ switch(addr){
+ #for $addr in range(5+1)
+ case $addr:
+ #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
+ reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
+ #end for
+ break;
+ #end for
+ }
+ return reg;
+}
+"""
+
+if __name__ == '__main__':
+ import common; common.generate(
+ name='adf4350_regs',
+ regs_tmpl=REGS_TMPL,
+ body_tmpl=BODY_TMPL,
+ file=__file__,
+ )
diff --git a/host/lib/ic_reg_maps/gen_adf4360_regs.py b/host/lib/ic_reg_maps/gen_adf4360_regs.py
index 478e471a3..3fd8707a7 100755
--- a/host/lib/ic_reg_maps/gen_adf4360_regs.py
+++ b/host/lib/ic_reg_maps/gen_adf4360_regs.py
@@ -16,14 +16,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import sys
-from common import *
-
########################################################################
# Template for raw text data describing registers
# name addr[bit range inclusive] default optional enums
########################################################################
-REGS_DATA_TMPL="""\
+REGS_TMPL="""\
########################################################################
## address 0
########################################################################
@@ -59,64 +56,34 @@ band_select_clock_div 1[20:21] 0 1, 2, 4, 8
"""
########################################################################
-# Header and Source templates below
+# Template for methods in the body of the struct
########################################################################
-HEADER_TEXT="""
-#import time
-
-/***********************************************************************
- * This file was generated by $file on $time.strftime("%c")
- **********************************************************************/
-
-\#ifndef INCLUDED_ADF4360_REGS_HPP
-\#define INCLUDED_ADF4360_REGS_HPP
-
-\#include <boost/cstdint.hpp>
-
-struct adf4360_regs_t{
-#for $reg in $regs
- #if $reg.get_enums()
- enum $(reg.get_name())_t{
- #for $i, $enum in enumerate($reg.get_enums())
- #set $end_comma = ',' if $i < len($reg.get_enums())-1 else ''
- $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma
- #end for
- } $reg.get_name();
- #else
- boost::$reg.get_stdint_type() $reg.get_name();
- #end if
-#end for
-
- adf4360_regs_t(void){
-#for $reg in $regs
- $reg.get_name() = $reg.get_default();
-#end for
- }
-
- enum addr_t{
- ADDR_CONTROL = 0,
- ADDR_NCOUNTER = 2,
- ADDR_RCOUNTER = 1
- };
+BODY_TMPL="""\
+enum addr_t{
+ ADDR_CONTROL = 0,
+ ADDR_NCOUNTER = 2,
+ ADDR_RCOUNTER = 1
+};
- boost::uint32_t get_reg(addr_t addr){
- boost::uint32_t reg = addr & 0x3;
- switch(addr){
- #for $addr in (0, 1, 2)
- case $addr:
- #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
- reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
- #end for
- break;
+boost::uint32_t get_reg(addr_t addr){
+ boost::uint32_t reg = addr & 0x3;
+ switch(addr){
+ #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs)))
+ case $addr:
+ #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
+ reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
#end for
- }
- return reg;
+ break;
+ #end for
}
-};
-
-\#endif /* INCLUDED_ADF4360_REGS_HPP */
+ return reg;
+}
"""
if __name__ == '__main__':
- regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines())
- open(sys.argv[1], 'w').write(parse_tmpl(HEADER_TEXT, regs=regs, file=__file__))
+ import common; common.generate(
+ name='adf4360_regs',
+ regs_tmpl=REGS_TMPL,
+ body_tmpl=BODY_TMPL,
+ file=__file__,
+ )
diff --git a/host/lib/ic_reg_maps/gen_max2829_regs.py b/host/lib/ic_reg_maps/gen_max2829_regs.py
index 7fef302a8..383131c18 100755
--- a/host/lib/ic_reg_maps/gen_max2829_regs.py
+++ b/host/lib/ic_reg_maps/gen_max2829_regs.py
@@ -16,14 +16,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import sys
-from common import *
-
########################################################################
# Template for raw text data describing registers
# name addr[bit range inclusive] default optional enums
########################################################################
-REGS_DATA_TMPL="""\
+REGS_TMPL="""\
########################################################################
## Note: offsets given from perspective of data bits (excludes address)
########################################################################
@@ -41,7 +38,7 @@ mimo_select 2[13] 0 normal, mimo
########################################################################
## Integer Divider Ratio (3)
########################################################################
-int_div_ratio_word 3[0:7] a2
+int_div_ratio_word 3[0:7] 0xa2
frac_div_ratio_lsb 3[12:13] 0
########################################################################
## Fractional Divider Ratio (4)
@@ -95,72 +92,42 @@ tx_vga_gain_spi 9[10] 0 io, spi
########################################################################
## PA Bias DAC (10)
########################################################################
-pa_bias_dac_out_curr a[0:5] 0
-pa_bias_dac_delay a[6:9] f
+pa_bias_dac_out_curr 10[0:5] 0
+pa_bias_dac_delay 10[6:9] 0xf
########################################################################
## Rx Gain (11)
########################################################################
-rx_vga_gain b[0:4] 1f
-rx_lna_gain b[5:6] 3
+rx_vga_gain 11[0:4] 0x1f
+rx_lna_gain 11[5:6] 3
########################################################################
## Tx VGA Gain (12)
########################################################################
-tx_vga_gain c[0:5] 0
+tx_vga_gain 12[0:5] 0
"""
########################################################################
-# Header and Source templates below
+# Template for methods in the body of the struct
########################################################################
-HEADER_TEXT="""
-#import time
-
-/***********************************************************************
- * This file was generated by $file on $time.strftime("%c")
- **********************************************************************/
-
-\#ifndef INCLUDED_MAX2829_REGS_HPP
-\#define INCLUDED_MAX2829_REGS_HPP
-
-\#include <boost/cstdint.hpp>
-
-struct max2829_regs_t{
-#for $reg in $regs
- #if $reg.get_enums()
- enum $(reg.get_name())_t{
- #for $i, $enum in enumerate($reg.get_enums())
- #set $end_comma = ',' if $i < len($reg.get_enums())-1 else ''
- $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma
+BODY_TMPL="""\
+boost::uint32_t get_reg(boost::uint8_t addr){
+ boost::uint16_t reg = 0;
+ switch(addr){
+ #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs)))
+ case $addr:
+ #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
+ reg |= (boost::uint16_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
#end for
- } $reg.get_name();
- #else
- boost::$reg.get_stdint_type() $reg.get_name();
- #end if
-#end for
-
- max2829_regs_t(void){
-#for $reg in $regs
- $reg.get_name() = $reg.get_default();
-#end for
+ break;
+ #end for
}
-
- boost::uint32_t get_reg(boost::uint8_t addr){
- boost::uint16_t reg = 0;
- switch(addr){
- #for $addr in range(2, 12+1)
- case $addr:
- #for $reg in filter(lambda r: r.get_addr() == addr, $regs)
- reg |= (boost::uint16_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift();
- #end for
- break;
- #end for
- }
- return (boost::uint32_t(reg) << 4) | (addr & 0xf);
- }
-};
-
-\#endif /* INCLUDED_MAX2829_REGS_HPP */
+ return (boost::uint32_t(reg) << 4) | (addr & 0xf);
+}
"""
if __name__ == '__main__':
- regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines())
- open(sys.argv[1], 'w').write(parse_tmpl(HEADER_TEXT, regs=regs, file=__file__))
+ import common; common.generate(
+ name='max2829_regs',
+ regs_tmpl=REGS_TMPL,
+ body_tmpl=BODY_TMPL,
+ file=__file__,
+ )
diff --git a/host/lib/load_modules.cpp b/host/lib/load_modules.cpp
index ef633325d..d6bfe1369 100644
--- a/host/lib/load_modules.cpp
+++ b/host/lib/load_modules.cpp
@@ -20,10 +20,11 @@
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
+#include <boost/program_options.hpp>
#include <iostream>
#include <stdexcept>
-#include <cstdlib>
+namespace po = boost::program_options;
namespace fs = boost::filesystem;
/***********************************************************************
@@ -100,14 +101,39 @@ static void load_path(const fs::path &path){
}
}
+//! The string constant for the module path environment variable
+static const std::string MODULE_PATH_KEY = "UHD_MODULE_PATH";
+
+/*!
+ * Name mapper function for the environment variable parser.
+ * Map environment variable names (that we use) to option names.
+ * \param the variable name
+ * \return the option name or blank string
+ */
+static std::string name_mapper(const std::string &var_name){
+ if (var_name == MODULE_PATH_KEY) return var_name;
+ return "";
+}
+
/*!
* Load all the modules given by the module path enviroment variable.
* The path variable may be several paths split by path separators.
*/
UHD_STATIC_BLOCK(load_modules){
- //get the environment variable module path
- char *env_module_path = std::getenv("UHD_MODULE_PATH");
- if (env_module_path == NULL) return;
+ //register the options
+ std::string env_module_path;
+ po::options_description desc("UHD Module Options");
+ desc.add_options()
+ (MODULE_PATH_KEY.c_str(), po::value<std::string>(&env_module_path)->default_value(""))
+ ;
+
+ //parse environment variables
+ po::variables_map vm;
+ po::store(po::parse_environment(desc, &name_mapper), vm);
+ po::notify(vm);
+
+ if (env_module_path == "") return;
+ //std::cout << "env_module_path: " << env_module_path << std::endl;
//split the path at the path separators
std::vector<std::string> module_paths;
diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt
new file mode 100644
index 000000000..a36f0fc03
--- /dev/null
+++ b/host/lib/transport/CMakeLists.txt
@@ -0,0 +1,52 @@
+#
+# 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/>.
+#
+
+#This file will be included by cmake, use absolute paths!
+
+########################################################################
+# Setup defines for interface address discovery
+########################################################################
+MESSAGE(STATUS "Configuring interface address discovery...")
+
+INCLUDE(CheckIncludeFileCXX)
+CHECK_INCLUDE_FILE_CXX(ifaddrs.h HAVE_IFADDRS_H)
+CHECK_INCLUDE_FILE_CXX(winsock2.h HAVE_WINSOCK2_H)
+
+IF(HAVE_IFADDRS_H)
+ MESSAGE(STATUS " Interface address discovery supported through getifaddrs.")
+ ADD_DEFINITIONS(-DHAVE_IFADDRS_H)
+ELSEIF(HAVE_WINSOCK2_H)
+ MESSAGE(STATUS " Interface address discovery supported through SIO_GET_INTERFACE_LIST.")
+ ADD_DEFINITIONS(-DHAVE_WINSOCK2_H)
+ELSE(HAVE_IFADDRS_H)
+ MESSAGE(STATUS " Interface address discovery not supported.")
+ENDIF(HAVE_IFADDRS_H)
+
+########################################################################
+# Append to the list of sources for lib uhd
+########################################################################
+LIBUHD_PYTHON_GEN_SOURCE(
+ ${CMAKE_SOURCE_DIR}/lib/transport/gen_vrt.py
+ ${CMAKE_BINARY_DIR}/lib/transport/vrt.cpp
+)
+
+LIBUHD_APPEND_SOURCES(
+ ${CMAKE_SOURCE_DIR}/lib/transport/convert_types.cpp
+ ${CMAKE_SOURCE_DIR}/lib/transport/if_addrs.cpp
+ ${CMAKE_SOURCE_DIR}/lib/transport/udp_simple.cpp
+ ${CMAKE_SOURCE_DIR}/lib/transport/udp_zero_copy_asio.cpp
+)
diff --git a/host/lib/transport/gen_vrt.py b/host/lib/transport/gen_vrt.py
index 38a394dee..9a57c83c3 100755
--- a/host/lib/transport/gen_vrt.py
+++ b/host/lib/transport/gen_vrt.py
@@ -200,15 +200,11 @@ void vrt::unpack(
}
"""
-import os
import sys
from Cheetah.Template import Template
def parse_tmpl(_tmpl_text, **kwargs):
return str(Template(_tmpl_text, kwargs))
-def safe_makedirs(path):
- not os.path.isdir(path) and os.makedirs(path)
if __name__ == '__main__':
- safe_makedirs(os.path.dirname(sys.argv[1]))
open(sys.argv[1], 'w').write(parse_tmpl(TMPL_TEXT, file=__file__))
diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp
index 09386a60c..ee44803f4 100644
--- a/host/lib/transport/udp_zero_copy_asio.cpp
+++ b/host/lib/transport/udp_zero_copy_asio.cpp
@@ -19,6 +19,8 @@
#include <boost/cstdint.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
+#include <boost/format.hpp>
+#include <iostream>
using namespace uhd::transport;
@@ -103,8 +105,18 @@ public:
managed_send_buffer::sptr get_send_buff(void);
//resize
- size_t resize_recv_buff_size(size_t num_bytes);
- size_t resize_send_buff_size(size_t num_bytes);
+ size_t resize_recv_buff(size_t num_bytes){
+ boost::asio::socket_base::receive_buffer_size option(num_bytes);
+ _socket->set_option(option);
+ _socket->get_option(option);
+ return option.value();
+ }
+ size_t resize_send_buff(size_t num_bytes){
+ boost::asio::socket_base::send_buffer_size option(num_bytes);
+ _socket->set_option(option);
+ _socket->get_option(option);
+ return option.value();
+ }
private:
boost::asio::ip::udp::socket *_socket;
@@ -157,25 +169,34 @@ managed_send_buffer::sptr udp_zero_copy_impl::get_send_buff(void){
);
}
-size_t udp_zero_copy_impl::resize_recv_buff_size(size_t num_bytes){
- boost::asio::socket_base::receive_buffer_size option(num_bytes);
- _socket->set_option(option);
- _socket->get_option(option);
- return option.value();
-}
-
-size_t udp_zero_copy_impl::resize_send_buff_size(size_t num_bytes){
- boost::asio::socket_base::send_buffer_size option(num_bytes);
- _socket->set_option(option);
- _socket->get_option(option);
- return option.value();
-}
-
/***********************************************************************
* UDP zero copy make function
**********************************************************************/
udp_zero_copy::sptr udp_zero_copy::make(
- const std::string &addr, const std::string &port
+ const std::string &addr,
+ const std::string &port,
+ size_t recv_buff_size,
+ size_t send_buff_size
){
- return sptr(new udp_zero_copy_impl(addr, port));
+ boost::shared_ptr<udp_zero_copy_impl> udp_trans(new udp_zero_copy_impl(addr, port));
+
+ //resize the recv buffer if size was provided
+ if (recv_buff_size > 0){
+ size_t actual_bytes = udp_trans->resize_recv_buff(recv_buff_size);
+ if (recv_buff_size != actual_bytes) std::cout << boost::format(
+ "Target recv buffer size: %d\n"
+ "Actual recv byffer size: %d"
+ ) % recv_buff_size % actual_bytes << std::endl;
+ }
+
+ //resize the send buffer if size was provided
+ if (send_buff_size > 0){
+ size_t actual_bytes = udp_trans->resize_send_buff(send_buff_size);
+ if (send_buff_size != actual_bytes) std::cout << boost::format(
+ "Target send buffer size: %d\n"
+ "Actual send byffer size: %d"
+ ) % send_buff_size % actual_bytes << std::endl;
+ }
+
+ return udp_trans;
}
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
index 14f7651d4..ec9c8ac01 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -143,7 +143,7 @@ device_addr_t::device_addr_t(const std::string &args){
}
}
-std::string device_addr_t::to_string(void) const{
+std::string device_addr_t::to_pp_string(void) const{
if (this->size() == 0) return "Empty Device Address";
std::stringstream ss;
@@ -153,7 +153,7 @@ std::string device_addr_t::to_string(void) const{
return ss.str();
}
-std::string device_addr_t::to_args_str(void) const{
+std::string device_addr_t::to_string(void) const{
std::string args_str;
BOOST_FOREACH(const std::string &key, this->keys()){
args_str += key + pair_delim + (*this)[key] + arg_delim;
diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt
new file mode 100644
index 000000000..39a72ab37
--- /dev/null
+++ b/host/lib/usrp/CMakeLists.txt
@@ -0,0 +1,27 @@
+#
+# 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/>.
+#
+
+#This file will be included by cmake, use absolute paths!
+
+LIBUHD_APPEND_SOURCES(
+ ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_base.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_eeprom.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_id.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_manager.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/simple_usrp.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/tune_helper.cpp
+)
diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt
new file mode 100644
index 000000000..3a6c2d84a
--- /dev/null
+++ b/host/lib/usrp/dboard/CMakeLists.txt
@@ -0,0 +1,26 @@
+#
+# 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/>.
+#
+
+#This file will be included by cmake, use absolute paths!
+
+LIBUHD_APPEND_SOURCES(
+ ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_basic_and_lf.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_rfx.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_xcvr2450.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_wbx.cpp
+)
+
diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp
index b0fbbd2ec..23ac98872 100644
--- a/host/lib/usrp/dboard/db_basic_and_lf.cpp
+++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp
@@ -34,7 +34,7 @@ using namespace boost::assign;
**********************************************************************/
class basic_rx : public rx_dboard_base{
public:
- basic_rx(ctor_args_t const& args, double max_freq);
+ basic_rx(ctor_args_t args, double max_freq);
~basic_rx(void);
void rx_get(const wax::obj &key, wax::obj &val);
@@ -46,7 +46,7 @@ private:
class basic_tx : public tx_dboard_base{
public:
- basic_tx(ctor_args_t const& args, double max_freq);
+ basic_tx(ctor_args_t args, double max_freq);
~basic_tx(void);
void tx_get(const wax::obj &key, wax::obj &val);
@@ -59,19 +59,19 @@ private:
/***********************************************************************
* Register the basic and LF dboards
**********************************************************************/
-static dboard_base::sptr make_basic_rx(dboard_base::ctor_args_t const& args){
+static dboard_base::sptr make_basic_rx(dboard_base::ctor_args_t args){
return dboard_base::sptr(new basic_rx(args, 90e9));
}
-static dboard_base::sptr make_basic_tx(dboard_base::ctor_args_t const& args){
+static dboard_base::sptr make_basic_tx(dboard_base::ctor_args_t args){
return dboard_base::sptr(new basic_tx(args, 90e9));
}
-static dboard_base::sptr make_lf_rx(dboard_base::ctor_args_t const& args){
+static dboard_base::sptr make_lf_rx(dboard_base::ctor_args_t args){
return dboard_base::sptr(new basic_rx(args, 32e6));
}
-static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t const& args){
+static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t args){
return dboard_base::sptr(new basic_tx(args, 32e6));
}
@@ -85,7 +85,7 @@ UHD_STATIC_BLOCK(reg_basic_and_lf_dboards){
/***********************************************************************
* Basic and LF RX dboard
**********************************************************************/
-basic_rx::basic_rx(ctor_args_t const& args, double max_freq) : rx_dboard_base(args){
+basic_rx::basic_rx(ctor_args_t args, double max_freq) : rx_dboard_base(args){
_max_freq = max_freq;
}
@@ -101,7 +101,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_NAME:
val = std::string(str(boost::format("%s - %s")
- % dboard_id::to_string(get_rx_id())
+ % get_rx_id().to_pp_string()
% get_subdev_name()
));
return;
@@ -187,7 +187,7 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){
/***********************************************************************
* Basic and LF TX dboard
**********************************************************************/
-basic_tx::basic_tx(ctor_args_t const& args, double max_freq) : tx_dboard_base(args){
+basic_tx::basic_tx(ctor_args_t args, double max_freq) : tx_dboard_base(args){
_max_freq = max_freq;
}
@@ -202,7 +202,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_NAME:
- val = dboard_id::to_string(get_tx_id());
+ val = get_tx_id().to_pp_string();
return;
case SUBDEV_PROP_OTHERS:
diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index 175f55eab..bbc9716b1 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -63,7 +63,7 @@ static const float _max_rx_pga0_gain = 45;
class rfx_xcvr : public xcvr_dboard_base{
public:
rfx_xcvr(
- ctor_args_t const& args,
+ ctor_args_t args,
const freq_range_t &freq_range,
bool rx_div2, bool tx_div2
);
@@ -108,23 +108,23 @@ private:
/***********************************************************************
* Register the RFX dboards (min freq, max freq, rx div2, tx div2)
**********************************************************************/
-static dboard_base::sptr make_rfx_flex400(dboard_base::ctor_args_t const& args){
+static dboard_base::sptr make_rfx_flex400(dboard_base::ctor_args_t args){
return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(400e6, 500e6), false, true));
}
-static dboard_base::sptr make_rfx_flex900(dboard_base::ctor_args_t const& args){
+static dboard_base::sptr make_rfx_flex900(dboard_base::ctor_args_t args){
return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(750e6, 1050e6), true, true));
}
-static dboard_base::sptr make_rfx_flex1800(dboard_base::ctor_args_t const& args){
+static dboard_base::sptr make_rfx_flex1800(dboard_base::ctor_args_t args){
return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(1500e6, 2100e6), false, false));
}
-static dboard_base::sptr make_rfx_flex1200(dboard_base::ctor_args_t const& args){
+static dboard_base::sptr make_rfx_flex1200(dboard_base::ctor_args_t args){
return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(1150e6, 1450e6), true, true));
}
-static dboard_base::sptr make_rfx_flex2400(dboard_base::ctor_args_t const& args){
+static dboard_base::sptr make_rfx_flex2400(dboard_base::ctor_args_t args){
return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(2300e6, 2900e6), false, false));
}
@@ -149,7 +149,7 @@ UHD_STATIC_BLOCK(reg_rfx_dboards){
* Structors
**********************************************************************/
rfx_xcvr::rfx_xcvr(
- ctor_args_t const& args,
+ ctor_args_t args,
const freq_range_t &freq_range,
bool rx_div2, bool tx_div2
) : xcvr_dboard_base(args){
@@ -351,7 +351,7 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_NAME:
- val = dboard_id::to_string(get_rx_id());
+ val = get_rx_id().to_pp_string();
return;
case SUBDEV_PROP_OTHERS:
@@ -448,7 +448,7 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_NAME:
- val = dboard_id::to_string(get_tx_id());
+ val = get_tx_id().to_pp_string();
return;
case SUBDEV_PROP_OTHERS:
diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp
new file mode 100644
index 000000000..2a8a3a9f2
--- /dev/null
+++ b/host/lib/usrp/dboard/db_wbx.cpp
@@ -0,0 +1,613 @@
+//
+// 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/>.
+//
+
+static const bool wbx_debug = false;
+
+// Common IO Pins
+#define ANTSW_IO ((1 << 5)|(1 << 15)) // on UNIT_TX, 0 = TX, 1 = RX, on UNIT_RX 0 = main ant, 1 = RX2
+#define ADF4350_CE (1 << 3)
+#define ADF4350_PDBRF (1 << 2)
+#define ADF4350_MUXOUT (1 << 1) // INPUT!!!
+#define LOCKDET_MASK (1 << 0) // INPUT!!!
+
+// TX IO Pins
+#define TX_PUP_5V (1 << 7) // enables 5.0V power supply
+#define TX_PUP_3V (1 << 6) // enables 3.3V supply
+#define TXMOD_EN (1 << 4) // on UNIT_TX, 1 enables TX Modulator
+
+// RX IO Pins
+#define RX_PUP_5V (1 << 7) // enables 5.0V power supply
+#define RX_PUP_3V (1 << 6) // enables 3.3V supply
+#define RXBB_PDB (1 << 4) // on UNIT_RX, 1 powers up RX baseband
+
+// RX Attenuator Pins
+#define RX_ATTN_SHIFT 8 // lsb of RX Attenuator Control
+#define RX_ATTN_MASK (63 << RX_ATTN_SHIFT) // valid bits of RX Attenuator Control
+
+// Mixer functions
+#define TX_MIXER_ENB (TXMOD_EN|ADF4350_PDBRF)
+#define TX_MIXER_DIS 0
+
+#define RX_MIXER_ENB (RXBB_PDB|ADF4350_PDBRF)
+#define RX_MIXER_DIS 0
+
+// Pin functions
+#define TX_POWER_IO (TX_PUP_5V|TX_PUP_3V) // high enables power supply
+#define TXIO_MASK (TX_POWER_IO|ANTSW_IO|ADF4350_CE|ADF4350_PDBRF|TXMOD_EN)
+
+#define RX_POWER_IO (RX_PUP_5V|RX_PUP_3V) // high enables power supply
+#define RXIO_MASK (RX_POWER_IO|ANTSW_IO|ADF4350_CE|ADF4350_PDBRF|RXBB_PDB|RX_ATTN_MASK)
+
+// Power functions
+#define TX_POWER_UP (TX_POWER_IO|ADF4350_CE)
+#define TX_POWER_DOWN 0
+
+#define RX_POWER_UP (RX_POWER_IO|ADF4350_CE)
+#define RX_POWER_DOWN 0
+
+// Antenna constants
+#define ANT_TX 0 //the tx line is transmitting
+#define ANT_RX ANTSW_IO //the tx line is receiving
+#define ANT_TXRX 0 //the rx line is on txrx
+#define ANT_RX2 ANTSW_IO //the rx line in on rx2
+#define ANT_XX 0 //dont care how the antenna is set
+
+#include "adf4350_regs.hpp"
+#include <uhd/types/dict.hpp>
+#include <uhd/usrp/subdev_props.hpp>
+#include <uhd/types/ranges.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/utils/static.hpp>
+#include <uhd/utils/algorithm.hpp>
+#include <uhd/usrp/dboard_base.hpp>
+#include <uhd/usrp/dboard_manager.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/format.hpp>
+#include <boost/math/special_functions/round.hpp>
+
+using namespace uhd;
+using namespace uhd::usrp;
+using namespace boost::assign;
+
+/***********************************************************************
+ * The WBX dboard
+ **********************************************************************/
+static const float _max_rx_pga0_gain = 31.5;
+static const float _max_tx_pga0_gain = 25;
+
+class wbx_xcvr : public xcvr_dboard_base{
+public:
+ wbx_xcvr(
+ ctor_args_t args,
+ const freq_range_t &freq_range
+ );
+ ~wbx_xcvr(void);
+
+ void rx_get(const wax::obj &key, wax::obj &val);
+ void rx_set(const wax::obj &key, const wax::obj &val);
+
+ void tx_get(const wax::obj &key, wax::obj &val);
+ void tx_set(const wax::obj &key, const wax::obj &val);
+
+private:
+ freq_range_t _freq_range;
+ uhd::dict<dboard_iface::unit_t, bool> _div2;
+ double _rx_lo_freq, _tx_lo_freq;
+ std::string _rx_ant;
+ int _rx_pga0_attn_iobits;
+ float _rx_pga0_gain;
+ float _tx_pga0_gain;
+
+ void set_rx_lo_freq(double freq);
+ void set_tx_lo_freq(double freq);
+ void set_rx_ant(const std::string &ant);
+ void set_rx_pga0_gain(float gain);
+ void set_rx_pga0_attn(float attn);
+ void set_tx_pga0_gain(float gain);
+
+ void update_atr(void);
+
+ /*!
+ * Set the LO frequency for the particular dboard unit.
+ * \param unit which unit rx or tx
+ * \param target_freq the desired frequency in Hz
+ * \return the actual frequency in Hz
+ */
+ double set_lo_freq(dboard_iface::unit_t unit, double target_freq);
+
+ /*!
+ * Get the lock detect status of the LO.
+ * \param unit which unit rx or tx
+ * \return true for locked
+ */
+ bool get_locked(dboard_iface::unit_t unit){
+ return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0;
+ }
+};
+
+/***********************************************************************
+ * Register the WBX dboard (min freq, max freq, rx div2, tx div2)
+ **********************************************************************/
+static dboard_base::sptr make_wbx(dboard_base::ctor_args_t args){
+ return dboard_base::sptr(new wbx_xcvr(args, freq_range_t(50e6, 2220e6)));
+}
+
+UHD_STATIC_BLOCK(reg_wbx_dboards){
+ dboard_manager::register_dboard(0x0052, &make_wbx, "WBX RX");
+ dboard_manager::register_dboard(0x0053, &make_wbx, "WBX TX");
+}
+
+/***********************************************************************
+ * Structors
+ **********************************************************************/
+wbx_xcvr::wbx_xcvr(
+ ctor_args_t args,
+ const freq_range_t &freq_range
+) : xcvr_dboard_base(args){
+ _freq_range = freq_range;
+
+ //enable the clocks that we need
+ this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true);
+ this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true);
+
+ //set the gpio directions
+ this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TXIO_MASK);
+ this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RXIO_MASK);
+ if (wbx_debug) std::cerr << boost::format(
+ "WBX GPIO Direction: RX: 0x%08x, TX: 0x%08x"
+ ) % RXIO_MASK % TXIO_MASK << std::endl;
+
+ //set some default values
+ set_rx_lo_freq((_freq_range.min + _freq_range.max)/2.0);
+ set_tx_lo_freq((_freq_range.min + _freq_range.max)/2.0);
+ set_rx_ant("RX2");
+ set_rx_pga0_gain(0);
+ set_tx_pga0_gain(0);
+}
+
+wbx_xcvr::~wbx_xcvr(void){
+ /* NOP */
+}
+
+/***********************************************************************
+ * Helper Methods
+ **********************************************************************/
+void wbx_xcvr::update_atr(void){
+ //calculate atr pins
+
+ //setup the tx atr (this does not change with antenna)
+ this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, TX_POWER_UP | ANT_XX | TX_MIXER_DIS);
+ this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, TX_POWER_UP | ANT_RX | TX_MIXER_DIS);
+ this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, TX_POWER_UP | ANT_TX | TX_MIXER_ENB);
+ this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, TX_POWER_UP | ANT_TX | TX_MIXER_ENB);
+
+ //setup the rx atr (this does not change with antenna)
+ this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE,
+ _rx_pga0_attn_iobits | RX_POWER_UP | ANT_XX | RX_MIXER_DIS);
+ this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY,
+ _rx_pga0_attn_iobits | RX_POWER_UP | ANT_XX | RX_MIXER_DIS);
+ this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX,
+ _rx_pga0_attn_iobits | RX_POWER_UP | ANT_RX2| RX_MIXER_ENB);
+
+ //set the rx atr regs that change with antenna setting
+ this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY,
+ _rx_pga0_attn_iobits | RX_POWER_UP | RX_MIXER_ENB | ((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2));
+ if (wbx_debug) std::cerr << boost::format(
+ "WBX RXONLY ATR REG: 0x%08x"
+ ) % (_rx_pga0_attn_iobits | RX_POWER_UP | RX_MIXER_ENB | ((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2)) << std::endl;
+}
+
+void wbx_xcvr::set_rx_lo_freq(double freq){
+ _rx_lo_freq = set_lo_freq(dboard_iface::UNIT_RX, freq);
+}
+
+void wbx_xcvr::set_tx_lo_freq(double freq){
+ _tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, freq);
+}
+
+void wbx_xcvr::set_rx_ant(const std::string &ant){
+ //validate input
+ UHD_ASSERT_THROW(ant == "TX/RX" or ant == "RX2");
+
+ //shadow the setting
+ _rx_ant = ant;
+
+ //write the new antenna setting to atr regs
+ update_atr();
+}
+
+void wbx_xcvr::set_rx_pga0_gain(float gain){
+ //clip the input
+ gain = std::clip<float>(gain, 0, _max_rx_pga0_gain);
+
+ //shadow the setting (does not account for precision loss)
+ _rx_pga0_gain = gain;
+
+ //convert to attenuation and update iobits for atr
+ set_rx_pga0_attn(_max_rx_pga0_gain - gain);
+
+ //write the new gain to atr regs
+ update_atr();
+}
+
+void wbx_xcvr::set_rx_pga0_attn(float attn)
+{
+ int attn_code = int(floor(attn*2));
+ _rx_pga0_attn_iobits = ((~attn_code) << RX_ATTN_SHIFT) & RX_ATTN_MASK;
+ if (wbx_debug) std::cerr << boost::format(
+ "WBX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x"
+ ) % attn % attn_code % (_rx_pga0_attn_iobits & RX_ATTN_MASK) % RX_ATTN_MASK << std::endl;
+}
+
+void wbx_xcvr::set_tx_pga0_gain(float gain){
+ //clip the input
+ gain = std::clip<float>(gain, 0, _max_tx_pga0_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)/_max_rx_pga0_gain;
+
+ //calculate the voltage for the aux dac
+ float dac_volts = gain*slope + min_volts;
+
+ if (wbx_debug) std::cerr << boost::format(
+ "WBX TX Gain: %f dB, dac_volts: %f V"
+ ) % gain % dac_volts << std::endl;
+
+ //write the new voltage to the aux dac
+ this->get_iface()->write_aux_dac(dboard_iface::UNIT_TX, 0, dac_volts);
+
+ //shadow the setting (does not account for precision loss)
+ _tx_pga0_gain = gain;
+}
+
+double wbx_xcvr::set_lo_freq(
+ dboard_iface::unit_t unit,
+ double target_freq
+){
+ if (wbx_debug) std::cerr << boost::format(
+ "WBX tune: target frequency %f Mhz"
+ ) % (target_freq/1e6) << std::endl;
+
+ //clip the input
+ target_freq = std::clip(target_freq, _freq_range.min, _freq_range.max);
+
+ //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler)
+ static const uhd::dict<int, int> prescaler_to_min_int_div = map_list_of
+ (0,23) //adf4350_regs_t::PRESCALER_4_5
+ (1,75) //adf4350_regs_t::PRESCALER_8_9
+ ;
+
+ //map rf divider select output dividers to enums
+ static const uhd::dict<int, adf4350_regs_t::rf_divider_select_t> rfdivsel_to_enum = map_list_of
+ (1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1)
+ (2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2)
+ (4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4)
+ (8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8)
+ (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16)
+ ;
+
+ double actual_freq, pfd_freq;
+ double ref_freq = this->get_iface()->get_clock_rate(unit);
+ int R, BS, N, FRAC, MOD;
+ int RFdiv = 1;
+ adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED;
+ adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED;
+
+ //Reference doubler for 50% duty cycle
+ // if ref_freq < 12.5MHz enable regs.reference_divide_by_2
+ if(ref_freq <= 12.5e6) D = adf4350_regs_t::REFERENCE_DOUBLER_ENABLED;
+
+ //increase RF divider until acceptable VCO frequency
+ //start with target_freq*2 because mixer has divide by 2
+ double vco_freq = target_freq*2;
+ while (vco_freq < 2.2e9) {
+ vco_freq *= 2;
+ RFdiv *= 2;
+ }
+
+ //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler)
+ adf4350_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5;
+
+ /*
+ * The goal here is to loop though possible R dividers,
+ * band select clock dividers, N (int) dividers, and FRAC
+ * (frac) dividers.
+ *
+ * Calculate the N and F dividers for each set of values.
+ * The loop exists when it meets all of the constraints.
+ * The resulting loop values are loaded into the registers.
+ *
+ * from pg.21
+ *
+ * f_pfd = f_ref*(1+D)/(R*(1+T))
+ * f_vco = (N + (FRAC/MOD))*f_pfd
+ * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD
+ * f_rf = f_vco/RFdiv)
+ * f_actual = f_rf/2
+ */
+ for(R = 1; R <= 1023; R+=1){
+ //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T)
+ pfd_freq = ref_freq*(1+D)/(R*(1+T));
+
+ //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth)
+ if (pfd_freq > 25e6) continue;
+
+ //ignore fractional part of tuning
+ N = int(std::floor(vco_freq/pfd_freq));
+
+ //keep N > minimum int divider requirement
+ if (N < prescaler_to_min_int_div[prescaler]) continue;
+
+ for(BS=1; BS <= 255; BS+=1){
+ //keep the band select frequency at or below 100KHz
+ //constraint on band select clock
+ if (pfd_freq/BS > 100e3) continue;
+ goto done_loop;
+ }
+ } done_loop:
+
+ //Fractional-N calculation
+ MOD = 4095; //max fractional accuracy
+ FRAC = int((vco_freq/pfd_freq - N)*MOD);
+
+ //Reference divide-by-2 for 50% duty cycle
+ // if R even, move one divide by 2 to to regs.reference_divide_by_2
+ if(R % 2 == 0){
+ T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED;
+ R /= 2;
+ }
+
+ //actual frequency calculation
+ actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv/2);
+
+
+ if (wbx_debug) {
+ std::cerr << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl;
+
+ std::cerr << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d"
+ ) % R % BS % N % FRAC % MOD % T % D % RFdiv % get_locked(unit)<< std::endl
+ << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f"
+ ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl;
+ }
+
+ //load the register values
+ adf4350_regs_t regs;
+
+ regs.frac_12_bit = FRAC;
+ regs.int_16_bit = N;
+ regs.mod_12_bit = MOD;
+ regs.prescaler = prescaler;
+ regs.r_counter_10_bit = R;
+ regs.reference_divide_by_2 = T;
+ regs.reference_doubler = D;
+ regs.band_select_clock_div = BS;
+ regs.rf_divider_select = rfdivsel_to_enum[RFdiv];
+
+ //write the registers
+ //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0)
+ int addr;
+
+ for(addr=5; addr>=0; addr--){
+ if (wbx_debug) std::cerr << boost::format(
+ "WBX SPI Reg (0x%02x): 0x%08x"
+ ) % addr % regs.get_reg(addr) << std::endl;
+ this->get_iface()->write_spi(
+ unit, spi_config_t::EDGE_RISE,
+ regs.get_reg(addr), 32
+ );
+ }
+
+ //return the actual frequency
+ if (wbx_debug) std::cerr << boost::format(
+ "WBX tune: actual frequency %f Mhz"
+ ) % (actual_freq/1e6) << std::endl;
+ return actual_freq;
+}
+
+/***********************************************************************
+ * RX Get and Set
+ **********************************************************************/
+void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
+ wax::obj key; std::string name;
+ boost::tie(key, name) = extract_named_prop(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<subdev_prop_t>()){
+ case SUBDEV_PROP_NAME:
+ val = get_rx_id().to_pp_string();
+ return;
+
+ case SUBDEV_PROP_OTHERS:
+ val = prop_names_t(); //empty
+ return;
+
+ case SUBDEV_PROP_GAIN:
+ UHD_ASSERT_THROW(name == "PGA0");
+ val = _rx_pga0_gain;
+ return;
+
+ case SUBDEV_PROP_GAIN_RANGE:
+ UHD_ASSERT_THROW(name == "PGA0");
+ val = gain_range_t(0, _max_rx_pga0_gain, float(0.5));
+ return;
+
+ case SUBDEV_PROP_GAIN_NAMES:
+ val = prop_names_t(1, "PGA0");
+ return;
+
+ case SUBDEV_PROP_FREQ:
+ val = _rx_lo_freq;
+ return;
+
+ case SUBDEV_PROP_FREQ_RANGE:
+ val = _freq_range;
+ return;
+
+ case SUBDEV_PROP_ANTENNA:
+ val = _rx_ant;
+ return;
+
+ case SUBDEV_PROP_ANTENNA_NAMES:{
+ prop_names_t ants = list_of("TX/RX")("RX2");
+ val = ants;
+ }
+ return;
+
+ case SUBDEV_PROP_QUADRATURE:
+ val = true;
+ return;
+
+ case SUBDEV_PROP_IQ_SWAPPED:
+ val = false;
+ return;
+
+ case SUBDEV_PROP_SPECTRUM_INVERTED:
+ val = false;
+ return;
+
+ case SUBDEV_PROP_USE_LO_OFFSET:
+ val = false;
+ return;
+
+ case SUBDEV_PROP_LO_LOCKED:
+ val = this->get_locked(dboard_iface::UNIT_RX);
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+}
+
+void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
+ wax::obj key; std::string name;
+ boost::tie(key, name) = extract_named_prop(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<subdev_prop_t>()){
+
+ case SUBDEV_PROP_FREQ:
+ set_rx_lo_freq(val.as<double>());
+ return;
+
+ case SUBDEV_PROP_GAIN:
+ UHD_ASSERT_THROW(name == "PGA0");
+ set_rx_pga0_gain(val.as<float>());
+ return;
+
+ case SUBDEV_PROP_ANTENNA:
+ set_rx_ant(val.as<std::string>());
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+}
+
+/***********************************************************************
+ * TX Get and Set
+ **********************************************************************/
+void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
+ wax::obj key; std::string name;
+ boost::tie(key, name) = extract_named_prop(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<subdev_prop_t>()){
+ case SUBDEV_PROP_NAME:
+ val = get_tx_id().to_pp_string();
+ return;
+
+ case SUBDEV_PROP_OTHERS:
+ val = prop_names_t(); //empty
+ return;
+
+ case SUBDEV_PROP_GAIN:
+ UHD_ASSERT_THROW(name == "PGA0");
+ val = _tx_pga0_gain;
+ return;
+
+ case SUBDEV_PROP_GAIN_RANGE:
+ UHD_ASSERT_THROW(name == "PGA0");
+ val = gain_range_t(0, _max_tx_pga0_gain, float(0.05));
+ return;
+
+ case SUBDEV_PROP_GAIN_NAMES:
+ val = prop_names_t(1, "PGA0");
+ return;
+
+ case SUBDEV_PROP_FREQ:
+ val = _tx_lo_freq;
+ return;
+
+ case SUBDEV_PROP_FREQ_RANGE:
+ val = _freq_range;
+ return;
+
+ case SUBDEV_PROP_ANTENNA:
+ val = std::string("TX/RX");
+ return;
+
+ case SUBDEV_PROP_ANTENNA_NAMES:
+ val = prop_names_t(1, "TX/RX");
+ return;
+
+ case SUBDEV_PROP_QUADRATURE:
+ val = true;
+ return;
+
+ case SUBDEV_PROP_IQ_SWAPPED:
+ val = false;
+ return;
+
+ case SUBDEV_PROP_SPECTRUM_INVERTED:
+ val = false;
+ return;
+
+ case SUBDEV_PROP_USE_LO_OFFSET:
+ val = false;
+ return;
+
+ case SUBDEV_PROP_LO_LOCKED:
+ val = this->get_locked(dboard_iface::UNIT_TX);
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+}
+
+void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){
+ wax::obj key; std::string name;
+ boost::tie(key, name) = extract_named_prop(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<subdev_prop_t>()){
+
+ case SUBDEV_PROP_FREQ:
+ set_tx_lo_freq(val.as<double>());
+ return;
+
+ case SUBDEV_PROP_GAIN:
+ UHD_ASSERT_THROW(name == "PGA0");
+ set_tx_pga0_gain(val.as<float>());
+ return;
+
+ case SUBDEV_PROP_ANTENNA:
+ //its always set to tx/rx, so we only allow this value
+ UHD_ASSERT_THROW(val.as<std::string>() == "TX/RX");
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+}
diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp
index 0dfef2a0a..3472229f4 100644
--- a/host/lib/usrp/dboard/db_xcvr2450.cpp
+++ b/host/lib/usrp/dboard/db_xcvr2450.cpp
@@ -89,7 +89,7 @@ static const uhd::dict<std::string, gain_range_t> xcvr_rx_gain_ranges = map_list
**********************************************************************/
class xcvr2450 : public xcvr_dboard_base{
public:
- xcvr2450(ctor_args_t const& args);
+ xcvr2450(ctor_args_t args);
~xcvr2450(void);
void rx_get(const wax::obj &key, wax::obj &val);
@@ -152,7 +152,7 @@ private:
/***********************************************************************
* Register the XCVR 2450 dboard
**********************************************************************/
-static dboard_base::sptr make_xcvr2450(dboard_base::ctor_args_t const& args){
+static dboard_base::sptr make_xcvr2450(dboard_base::ctor_args_t args){
return dboard_base::sptr(new xcvr2450(args));
}
@@ -165,7 +165,7 @@ UHD_STATIC_BLOCK(reg_xcvr2450_dboard){
/***********************************************************************
* Structors
**********************************************************************/
-xcvr2450::xcvr2450(ctor_args_t const& args) : xcvr_dboard_base(args){
+xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){
//enable only the clocks we need
this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true);
@@ -373,8 +373,7 @@ static max2829_regs_t::tx_baseband_gain_t gain_to_tx_bb_reg(float &gain){
gain = 5;
return max2829_regs_t::TX_BASEBAND_GAIN_5DB;
}
- BOOST_THROW_EXCEPTION(std::runtime_error("should not get here"));
- return max2829_regs_t::TX_BASEBAND_GAIN_0DB;
+ UHD_ASSERT_THROW(false);
}
/*!
@@ -444,7 +443,7 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_NAME:
- val = dboard_id::to_string(get_rx_id());
+ val = get_rx_id().to_pp_string();
return;
case SUBDEV_PROP_OTHERS:
@@ -542,7 +541,7 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_NAME:
- val = dboard_id::to_string(get_tx_id());
+ val = get_tx_id().to_pp_string();
return;
case SUBDEV_PROP_OTHERS:
diff --git a/host/lib/usrp/dboard_base.cpp b/host/lib/usrp/dboard_base.cpp
index 68e4743d1..bd4b37ef3 100644
--- a/host/lib/usrp/dboard_base.cpp
+++ b/host/lib/usrp/dboard_base.cpp
@@ -15,6 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
+#include "dboard_ctor_args.hpp"
#include <uhd/usrp/dboard_base.hpp>
#include <boost/format.hpp>
#include <stdexcept>
@@ -24,43 +25,48 @@ using namespace uhd::usrp;
/***********************************************************************
* dboard_base dboard dboard_base class
**********************************************************************/
-dboard_base::dboard_base(ctor_args_t const& args){
- boost::tie(_subdev_name, _dboard_iface, _rx_id, _tx_id) = args;
+struct dboard_base::dboard_base_impl{
+ ctor_args_impl args;
+ dboard_base_impl(ctor_args_t args) : args(*args){}
+};
+
+dboard_base::dboard_base(ctor_args_t args){
+ _impl = new dboard_base_impl(args);
}
dboard_base::~dboard_base(void){
- /* NOP */
+ delete _impl;
}
std::string dboard_base::get_subdev_name(void){
- return _subdev_name;
+ return _impl->args.sd_name;
}
dboard_iface::sptr dboard_base::get_iface(void){
- return _dboard_iface;
+ return _impl->args.db_iface;
}
dboard_id_t dboard_base::get_rx_id(void){
- return _rx_id;
+ return _impl->args.rx_id;
}
dboard_id_t dboard_base::get_tx_id(void){
- return _tx_id;
+ return _impl->args.tx_id;
}
/***********************************************************************
* xcvr dboard dboard_base class
**********************************************************************/
-xcvr_dboard_base::xcvr_dboard_base(ctor_args_t const& args) : dboard_base(args){
- if (get_rx_id() == dboard_id::NONE){
+xcvr_dboard_base::xcvr_dboard_base(ctor_args_t args) : dboard_base(args){
+ if (get_rx_id() == dboard_id_t::none()){
throw std::runtime_error(str(boost::format(
"cannot create xcvr board when the rx id is \"%s\""
- ) % dboard_id::to_string(dboard_id::NONE)));
+ ) % dboard_id_t::none().to_pp_string()));
}
- if (get_tx_id() == dboard_id::NONE){
+ if (get_tx_id() == dboard_id_t::none()){
throw std::runtime_error(str(boost::format(
"cannot create xcvr board when the tx id is \"%s\""
- ) % dboard_id::to_string(dboard_id::NONE)));
+ ) % dboard_id_t::none().to_pp_string()));
}
}
@@ -71,12 +77,12 @@ xcvr_dboard_base::~xcvr_dboard_base(void){
/***********************************************************************
* rx dboard dboard_base class
**********************************************************************/
-rx_dboard_base::rx_dboard_base(ctor_args_t const& args) : dboard_base(args){
- if (get_tx_id() != dboard_id::NONE){
+rx_dboard_base::rx_dboard_base(ctor_args_t args) : dboard_base(args){
+ if (get_tx_id() != dboard_id_t::none()){
throw std::runtime_error(str(boost::format(
"cannot create rx board when the tx id is \"%s\""
" -> expected a tx id of \"%s\""
- ) % dboard_id::to_string(get_tx_id()) % dboard_id::to_string(dboard_id::NONE)));
+ ) % get_tx_id().to_pp_string() % dboard_id_t::none().to_pp_string()));
}
}
@@ -95,12 +101,12 @@ void rx_dboard_base::tx_set(const wax::obj &, const wax::obj &){
/***********************************************************************
* tx dboard dboard_base class
**********************************************************************/
-tx_dboard_base::tx_dboard_base(ctor_args_t const& args) : dboard_base(args){
- if (get_rx_id() != dboard_id::NONE){
+tx_dboard_base::tx_dboard_base(ctor_args_t args) : dboard_base(args){
+ if (get_rx_id() != dboard_id_t::none()){
throw std::runtime_error(str(boost::format(
"cannot create tx board when the rx id is \"%s\""
" -> expected a rx id of \"%s\""
- ) % dboard_id::to_string(get_rx_id()) % dboard_id::to_string(dboard_id::NONE)));
+ ) % get_rx_id().to_pp_string() % dboard_id_t::none().to_pp_string()));
}
}
diff --git a/host/lib/usrp/dboard_ctor_args.hpp b/host/lib/usrp/dboard_ctor_args.hpp
new file mode 100644
index 000000000..13abe79e8
--- /dev/null
+++ b/host/lib/usrp/dboard_ctor_args.hpp
@@ -0,0 +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_DBOARD_CTOR_ARGS_HPP
+#define INCLUDED_DBOARD_CTOR_ARGS_HPP
+
+#include <uhd/usrp/dboard_id.hpp>
+#include <uhd/usrp/dboard_base.hpp>
+#include <uhd/usrp/dboard_iface.hpp>
+#include <string>
+
+struct uhd::usrp::dboard_base::ctor_args_impl{
+ std::string sd_name;
+ dboard_iface::sptr db_iface;
+ dboard_id_t rx_id, tx_id;
+};
+
+#endif /* INCLUDED_DBOARD_CTOR_ARGS_HPP */
diff --git a/host/lib/usrp/dboard_eeprom.cpp b/host/lib/usrp/dboard_eeprom.cpp
index 54e7a4fd9..fa3631948 100644
--- a/host/lib/usrp/dboard_eeprom.cpp
+++ b/host/lib/usrp/dboard_eeprom.cpp
@@ -80,19 +80,20 @@ dboard_eeprom_t::dboard_eeprom_t(const byte_vector_t &bytes){
UHD_ASSERT_THROW(bytes.size() >= DB_EEPROM_CLEN);
UHD_ASSERT_THROW(bytes[DB_EEPROM_MAGIC] == DB_EEPROM_MAGIC_VALUE);
UHD_ASSERT_THROW(bytes[DB_EEPROM_CHKSUM] == checksum(bytes));
- id = \
- (boost::uint16_t(bytes[DB_EEPROM_ID_LSB]) << 0) |
- (boost::uint16_t(bytes[DB_EEPROM_ID_MSB]) << 8) ;
+ id = dboard_id_t::from_uint16(0
+ | (boost::uint16_t(bytes[DB_EEPROM_ID_LSB]) << 0)
+ | (boost::uint16_t(bytes[DB_EEPROM_ID_MSB]) << 8)
+ );
}catch(const uhd::assert_error &){
- id = dboard_id::NONE;
+ id = dboard_id_t::none();
}
}
byte_vector_t dboard_eeprom_t::get_eeprom_bytes(void){
byte_vector_t bytes(DB_EEPROM_CLEN, 0); //defaults to all zeros
bytes[DB_EEPROM_MAGIC] = DB_EEPROM_MAGIC_VALUE;
- bytes[DB_EEPROM_ID_LSB] = boost::uint8_t(id >> 0);
- bytes[DB_EEPROM_ID_MSB] = boost::uint8_t(id >> 8);
+ bytes[DB_EEPROM_ID_LSB] = boost::uint8_t(id.to_uint16() >> 0);
+ bytes[DB_EEPROM_ID_MSB] = boost::uint8_t(id.to_uint16() >> 8);
bytes[DB_EEPROM_CHKSUM] = checksum(bytes);
return bytes;
}
diff --git a/host/lib/usrp/dboard_id.cpp b/host/lib/usrp/dboard_id.cpp
new file mode 100644
index 000000000..3028d2a3b
--- /dev/null
+++ b/host/lib/usrp/dboard_id.cpp
@@ -0,0 +1,68 @@
+//
+// 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/usrp/dboard_id.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/format.hpp>
+#include <sstream>
+#include <iostream>
+
+using namespace uhd::usrp;
+
+dboard_id_t::dboard_id_t(boost::uint16_t id){
+ _id = id;
+}
+
+dboard_id_t dboard_id_t::none(void){
+ return dboard_id_t();
+}
+
+dboard_id_t dboard_id_t::from_uint16(boost::uint16_t uint16){
+ return dboard_id_t(uint16);
+}
+
+boost::uint16_t dboard_id_t::to_uint16(void) const{
+ return _id;
+}
+
+//used with lexical cast to parse a hex string
+template <class T> struct to_hex{
+ T value;
+ operator T() const {return value;}
+ friend std::istream& operator>>(std::istream& in, to_hex& out){
+ in >> std::hex >> out.value;
+ return in;
+ }
+};
+
+dboard_id_t dboard_id_t::from_string(const std::string &string){
+ if (string.substr(0, 2) == "0x"){
+ return dboard_id_t::from_uint16(boost::lexical_cast<to_hex<boost::uint16_t> >(string));
+ }
+ return dboard_id_t::from_uint16(boost::lexical_cast<boost::uint16_t>(string));
+}
+
+std::string dboard_id_t::to_string(void) const{
+ return str(boost::format("0x%04x") % this->to_uint16());
+}
+
+//Note: to_pp_string is implemented in the dboard manager
+//because it needs access to the dboard registration table
+
+bool uhd::usrp::operator==(const dboard_id_t &lhs, const dboard_id_t &rhs){
+ return lhs.to_uint16() == rhs.to_uint16();
+}
diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp
index 390c1d3c9..8161727e5 100644
--- a/host/lib/usrp/dboard_manager.cpp
+++ b/host/lib/usrp/dboard_manager.cpp
@@ -15,6 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
+#include "dboard_ctor_args.hpp"
#include <uhd/usrp/dboard_manager.hpp>
#include <uhd/usrp/subdev_props.hpp>
#include <uhd/utils/gain_handler.hpp>
@@ -26,6 +27,7 @@
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/assign/list_of.hpp>
+#include <iostream>
using namespace uhd;
using namespace uhd::usrp;
@@ -49,15 +51,18 @@ void dboard_manager::register_dboard(
//std::cout << "registering: " << name << std::endl;
if (get_id_to_args_map().has_key(dboard_id)){
throw std::runtime_error(str(boost::format(
- "The dboard id 0x%04x is already registered to %s."
- ) % dboard_id % dboard_id::to_string(dboard_id)));
+ "The dboard id %s is already registered to %s."
+ ) % dboard_id.to_string() % dboard_id.to_pp_string()));
}
get_id_to_args_map()[dboard_id] = args_t(dboard_ctor, name, subdev_names);
}
-std::string dboard_id::to_string(const dboard_id_t &id){
- std::string name = (get_id_to_args_map().has_key(id))? get_id_to_args_map()[id].get<1>() : "unknown";
- return str(boost::format("%s (0x%04x)") % name % id);
+std::string dboard_id_t::to_pp_string(void) const{
+ std::string name = "unknown";
+ if (get_id_to_args_map().has_key(*this)){
+ name = get_id_to_args_map()[*this].get<1>();
+ }
+ return str(boost::format("%s (%s)") % name % this->to_string());
}
/***********************************************************************
@@ -162,26 +167,27 @@ dboard_manager::sptr dboard_manager::make(
* implementation class methods
**********************************************************************/
static args_t get_dboard_args(
- dboard_id_t dboard_id,
- std::string const& xx_type
+ dboard_iface::unit_t unit,
+ dboard_id_t dboard_id
){
- //special case, its rx and the none id (0xffff)
- if (xx_type == "rx" and dboard_id == dboard_id::NONE){
- return get_dboard_args(0x0001, xx_type);
- }
-
- //special case, its tx and the none id (0xffff)
- if (xx_type == "tx" and dboard_id == dboard_id::NONE){
- return get_dboard_args(0x0000, xx_type);
+ //special case, the none id was provided, use the following ids
+ if (dboard_id == dboard_id_t::none()){
+ std::cerr << boost::format(
+ "Warning: unregistered dboard id: %s"
+ " -> defaulting to a basic board"
+ ) % dboard_id.to_pp_string() << std::endl;
+ UHD_ASSERT_THROW(get_id_to_args_map().has_key(0x0001));
+ UHD_ASSERT_THROW(get_id_to_args_map().has_key(0x0000));
+ switch(unit){
+ case dboard_iface::UNIT_RX: return get_dboard_args(unit, 0x0001);
+ case dboard_iface::UNIT_TX: return get_dboard_args(unit, 0x0000);
+ default: UHD_ASSERT_THROW(false);
+ }
}
//verify that there is a registered constructor for this id
if (not get_id_to_args_map().has_key(dboard_id)){
- /*throw std::runtime_error(str(
- boost::format("Unregistered %s dboard id: %s")
- % xx_type % dboard_id::to_string(dboard_id)
- ));*/
- return get_dboard_args(dboard_id::NONE, xx_type);
+ return get_dboard_args(unit, dboard_id_t::none());
}
//return the dboard args for this id
@@ -196,21 +202,26 @@ dboard_manager_impl::dboard_manager_impl(
_iface = iface;
dboard_ctor_t rx_dboard_ctor; std::string rx_name; prop_names_t rx_subdevs;
- boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_dboard_args(rx_dboard_id, "rx");
+ boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_dboard_args(dboard_iface::UNIT_RX, rx_dboard_id);
dboard_ctor_t tx_dboard_ctor; std::string tx_name; prop_names_t tx_subdevs;
- boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_dboard_args(tx_dboard_id, "tx");
+ boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_dboard_args(dboard_iface::UNIT_TX, tx_dboard_id);
//initialize the gpio pins before creating subdevs
set_nice_dboard_if();
+ //dboard constructor args
+ dboard_base::ctor_args_impl db_ctor_args;
+ db_ctor_args.db_iface = iface;
+
//make xcvr subdevs (make one subdev for both rx and tx dboards)
if (rx_dboard_ctor == tx_dboard_ctor){
UHD_ASSERT_THROW(rx_subdevs == tx_subdevs);
BOOST_FOREACH(const std::string &subdev, rx_subdevs){
- dboard_base::sptr xcvr_dboard = rx_dboard_ctor(
- dboard_base::ctor_args_t(subdev, iface, rx_dboard_id, tx_dboard_id)
- );
+ db_ctor_args.sd_name = subdev;
+ db_ctor_args.rx_id = rx_dboard_id;
+ db_ctor_args.tx_id = tx_dboard_id;
+ dboard_base::sptr xcvr_dboard = rx_dboard_ctor(&db_ctor_args);
//create a rx proxy for this xcvr board
_rx_dboards[subdev] = subdev_proxy::sptr(
new subdev_proxy(xcvr_dboard, subdev_proxy::RX_TYPE)
@@ -226,9 +237,10 @@ dboard_manager_impl::dboard_manager_impl(
else{
//make the rx subdevs
BOOST_FOREACH(const std::string &subdev, rx_subdevs){
- dboard_base::sptr rx_dboard = rx_dboard_ctor(
- dboard_base::ctor_args_t(subdev, iface, rx_dboard_id, dboard_id::NONE)
- );
+ db_ctor_args.sd_name = subdev;
+ db_ctor_args.rx_id = rx_dboard_id;
+ db_ctor_args.tx_id = dboard_id_t::none();
+ dboard_base::sptr rx_dboard = rx_dboard_ctor(&db_ctor_args);
//create a rx proxy for this rx board
_rx_dboards[subdev] = subdev_proxy::sptr(
new subdev_proxy(rx_dboard, subdev_proxy::RX_TYPE)
@@ -236,9 +248,10 @@ dboard_manager_impl::dboard_manager_impl(
}
//make the tx subdevs
BOOST_FOREACH(const std::string &subdev, tx_subdevs){
- dboard_base::sptr tx_dboard = tx_dboard_ctor(
- dboard_base::ctor_args_t(subdev, iface, dboard_id::NONE, tx_dboard_id)
- );
+ db_ctor_args.sd_name = subdev;
+ db_ctor_args.rx_id = dboard_id_t::none();
+ db_ctor_args.tx_id = tx_dboard_id;
+ dboard_base::sptr tx_dboard = tx_dboard_ctor(&db_ctor_args);
//create a tx proxy for this tx board
_tx_dboards[subdev] = subdev_proxy::sptr(
new subdev_proxy(tx_dboard, subdev_proxy::TX_TYPE)
diff --git a/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt
new file mode 100644
index 000000000..f9907e21e
--- /dev/null
+++ b/host/lib/usrp/usrp2/CMakeLists.txt
@@ -0,0 +1,29 @@
+#
+# 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/>.
+#
+
+#This file will be included by cmake, use absolute paths!
+
+LIBUHD_APPEND_SOURCES(
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/clock_control.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_iface.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dsp_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/io_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/mboard_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_iface.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_impl.cpp
+)
diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp
index 74d80163c..372a5af07 100644
--- a/host/lib/usrp/usrp2/dboard_iface.cpp
+++ b/host/lib/usrp/usrp2/dboard_iface.cpp
@@ -29,6 +29,7 @@
using namespace uhd;
using namespace uhd::usrp;
+using namespace boost::assign;
class usrp2_dboard_iface : public dboard_iface{
public:
@@ -122,49 +123,42 @@ double usrp2_dboard_iface::get_clock_rate(unit_t){
void usrp2_dboard_iface::set_clock_enabled(unit_t unit, bool enb){
switch(unit){
- case UNIT_RX:
- _clk_ctrl->enable_rx_dboard_clock(enb);
- return;
- case UNIT_TX:
- _clk_ctrl->enable_tx_dboard_clock(enb);
- return;
+ case UNIT_RX: _clk_ctrl->enable_rx_dboard_clock(enb); return;
+ case UNIT_TX: _clk_ctrl->enable_tx_dboard_clock(enb); return;
}
}
/***********************************************************************
* GPIO
**********************************************************************/
-static int unit_to_shift(dboard_iface::unit_t unit){
- switch(unit){
- case dboard_iface::UNIT_RX: return 0;
- case dboard_iface::UNIT_TX: return 16;
- }
- throw std::runtime_error("unknown unit type");
-}
+static const uhd::dict<dboard_iface::unit_t, int> unit_to_shift = map_list_of
+ (dboard_iface::UNIT_RX, 0)
+ (dboard_iface::UNIT_TX, 16)
+;
void usrp2_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){
_ddr_shadow = \
- (_ddr_shadow & ~(0xffff << unit_to_shift(unit))) |
- (boost::uint32_t(value) << unit_to_shift(unit));
+ (_ddr_shadow & ~(0xffff << unit_to_shift[unit])) |
+ (boost::uint32_t(value) << unit_to_shift[unit]);
_iface->poke32(FR_GPIO_DDR, _ddr_shadow);
}
boost::uint16_t usrp2_dboard_iface::read_gpio(unit_t unit){
- return boost::uint16_t(_iface->peek32(FR_GPIO_IO) >> unit_to_shift(unit));
+ return boost::uint16_t(_iface->peek32(FR_GPIO_IO) >> unit_to_shift[unit]);
}
void usrp2_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){
//define mapping of unit to atr regs to register address
static const uhd::dict<
unit_t, uhd::dict<atr_reg_t, boost::uint32_t>
- > unit_to_atr_to_addr = boost::assign::map_list_of
- (UNIT_RX, boost::assign::map_list_of
+ > unit_to_atr_to_addr = map_list_of
+ (UNIT_RX, map_list_of
(ATR_REG_IDLE, FR_ATR_IDLE_RXSIDE)
(ATR_REG_TX_ONLY, FR_ATR_INTX_RXSIDE)
(ATR_REG_RX_ONLY, FR_ATR_INRX_RXSIDE)
(ATR_REG_FULL_DUPLEX, FR_ATR_FULL_RXSIDE)
)
- (UNIT_TX, boost::assign::map_list_of
+ (UNIT_TX, map_list_of
(ATR_REG_IDLE, FR_ATR_IDLE_TXSIDE)
(ATR_REG_TX_ONLY, FR_ATR_INTX_TXSIDE)
(ATR_REG_RX_ONLY, FR_ATR_INRX_TXSIDE)
@@ -177,19 +171,10 @@ void usrp2_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t
/***********************************************************************
* SPI
**********************************************************************/
-/*!
- * Static function to convert a unit type enum
- * to an over-the-wire value for the spi device.
- * \param unit the dboard interface unit type enum
- * \return an over the wire representation
- */
-static boost::uint8_t unit_to_otw_spi_dev(dboard_iface::unit_t unit){
- switch(unit){
- case dboard_iface::UNIT_TX: return SPI_SS_TX_DB;
- case dboard_iface::UNIT_RX: return SPI_SS_RX_DB;
- }
- throw std::invalid_argument("unknown unit type");
-}
+static const uhd::dict<dboard_iface::unit_t, int> unit_to_spi_dev = map_list_of
+ (dboard_iface::UNIT_TX, SPI_SS_TX_DB)
+ (dboard_iface::UNIT_RX, SPI_SS_RX_DB)
+;
void usrp2_dboard_iface::write_spi(
unit_t unit,
@@ -197,7 +182,7 @@ void usrp2_dboard_iface::write_spi(
boost::uint32_t data,
size_t num_bits
){
- _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/);
+ _iface->transact_spi(unit_to_spi_dev[unit], config, data, num_bits, false /*no rb*/);
}
boost::uint32_t usrp2_dboard_iface::read_write_spi(
@@ -206,7 +191,7 @@ boost::uint32_t usrp2_dboard_iface::read_write_spi(
boost::uint32_t data,
size_t num_bits
){
- return _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, true /*rb*/);
+ return _iface->transact_spi(unit_to_spi_dev[unit], config, data, num_bits, true /*rb*/);
}
/***********************************************************************
@@ -224,7 +209,7 @@ byte_vector_t usrp2_dboard_iface::read_i2c(boost::uint8_t addr, size_t num_bytes
* Aux DAX/ADC
**********************************************************************/
void usrp2_dboard_iface::_write_aux_dac(unit_t unit){
- static const uhd::dict<unit_t, int> unit_to_spi_dac = boost::assign::map_list_of
+ static const uhd::dict<unit_t, int> unit_to_spi_dac = map_list_of
(UNIT_RX, SPI_SS_RX_DAC)
(UNIT_TX, SPI_SS_TX_DAC)
;
@@ -248,7 +233,7 @@ void usrp2_dboard_iface::write_aux_dac(unit_t unit, int which, float value){
}
float usrp2_dboard_iface::read_aux_adc(unit_t unit, int which){
- static const uhd::dict<unit_t, int> unit_to_spi_adc = boost::assign::map_list_of
+ 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)
;
diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp
index bd61ac376..195a9bc53 100644
--- a/host/lib/usrp/usrp2/dsp_impl.cpp
+++ b/host/lib/usrp/usrp2/dsp_impl.cpp
@@ -52,6 +52,23 @@ static boost::uint32_t calculate_freq_word_and_update_actual_freq(double &freq,
return freq_word;
}
+// Check if requested decim/interp rate is:
+// multiple of 4, enable two halfband filters
+// multiple of 2, enable one halfband filter
+// handle remainder in CIC
+static boost::uint32_t calculate_cic_word(size_t rate){
+ int hb0 = 0, hb1 = 0;
+ if (not (rate & 0x1)){
+ hb0 = 1;
+ rate /= 2;
+ }
+ if (not (rate & 0x1)){
+ hb1 = 1;
+ rate /= 2;
+ }
+ return (hb1 << 9) | (hb0 << 8) | (rate & 0xff);
+}
+
static boost::uint32_t calculate_iq_scale_word(boost::int16_t i, boost::int16_t q){
return (boost::uint16_t(i) << 16) | (boost::uint16_t(q) << 0);
}
@@ -81,7 +98,7 @@ void usrp2_impl::init_ddc_config(void){
void usrp2_impl::update_ddc_config(void){
//set the decimation
- _iface->poke32(FR_DSP_RX_DECIM_RATE, _ddc_decim);
+ _iface->poke32(FR_DSP_RX_DECIM_RATE, calculate_cic_word(_ddc_decim));
//set the scaling
static const boost::int16_t default_rx_scale_iq = 1024;
@@ -160,15 +177,14 @@ void usrp2_impl::init_duc_config(void){
void usrp2_impl::update_duc_config(void){
// Calculate CIC interpolation (i.e., without halfband interpolators)
- size_t tmp_interp = _duc_interp;
- while(tmp_interp > 128) tmp_interp /= 2;
+ size_t tmp_interp = calculate_cic_word(_duc_interp) & 0xff;
// Calculate closest multiplier constant to reverse gain absent scale multipliers
double interp_cubed = std::pow(double(tmp_interp), 3);
boost::int16_t scale = rint((4096*std::pow(2, ceil(log2(interp_cubed))))/(1.65*interp_cubed));
//set the interpolation
- _iface->poke32(FR_DSP_TX_INTERP_RATE, _ddc_decim);
+ _iface->poke32(FR_DSP_TX_INTERP_RATE, calculate_cic_word(_duc_interp));
//set the scaling
_iface->poke32(FR_DSP_TX_SCALE_IQ, calculate_iq_scale_word(scale, scale));
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index a2e99c824..7c9d003ce 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -39,6 +39,9 @@ void usrp2_impl::io_init(void){
//initially empty copy buffer
_rx_copy_buff = asio::buffer("", 0);
+ //init the expected rx seq number
+ _rx_stream_id_to_packet_seq[0] = 0;
+
//send a small data packet so the usrp2 knows the udp source port
managed_send_buffer::sptr send_buff = _data_transport->get_send_buff();
boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER);
diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp
index 2b974fb9b..1dde8c054 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.cpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.cpp
@@ -113,31 +113,23 @@ device::sptr usrp2::make(const device_addr_t &device_addr){
device_addr["addr"], num2str(USRP2_UDP_CTRL_PORT)
);
- //create a data transport
- udp_zero_copy::sptr data_transport = udp_zero_copy::make(
- device_addr["addr"], num2str(USRP2_UDP_DATA_PORT)
- );
-
- //resize the recv data transport buffers
+ //extract the receive and send buffer sizes
+ size_t recv_buff_size = 0, send_buff_size= 0 ;
if (device_addr.has_key("recv_buff_size")){
- size_t num_byes = size_t(boost::lexical_cast<double>(device_addr["recv_buff_size"]));
- size_t actual_bytes = data_transport->resize_recv_buff_size(num_byes);
- if (num_byes != actual_bytes) std::cout << boost::format(
- "Target recv buffer size: %d\n"
- "Actual recv byffer size: %d"
- ) % num_byes % actual_bytes << std::endl;
+ recv_buff_size = size_t(boost::lexical_cast<double>(device_addr["recv_buff_size"]));
}
-
- //resize the send data transport buffers
if (device_addr.has_key("send_buff_size")){
- size_t num_byes = size_t(boost::lexical_cast<double>(device_addr["send_buff_size"]));
- size_t actual_bytes = data_transport->resize_send_buff_size(num_byes);
- if (num_byes != actual_bytes) std::cout << boost::format(
- "Target send buffer size: %d\n"
- "Actual send byffer size: %d"
- ) % num_byes % actual_bytes << std::endl;
+ send_buff_size = size_t(boost::lexical_cast<double>(device_addr["send_buff_size"]));
}
+ //create a data transport
+ udp_zero_copy::sptr data_transport = udp_zero_copy::make(
+ device_addr["addr"],
+ num2str(USRP2_UDP_DATA_PORT),
+ recv_buff_size,
+ send_buff_size
+ );
+
//create the usrp2 implementation guts
return device::sptr(
new usrp2_impl(ctrl_transport, data_transport)
diff --git a/host/lib/utils.cpp b/host/lib/utils.cpp
index 3a1e5aa3f..d2f4dfc6e 100644
--- a/host/lib/utils.cpp
+++ b/host/lib/utils.cpp
@@ -15,11 +15,20 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
+#include <uhd/utils/assert.hpp>
#include <uhd/utils/props.hpp>
+#include <stdexcept>
using namespace uhd;
/***********************************************************************
+ * Assert
+ **********************************************************************/
+assert_error::assert_error(const std::string &what) : std::runtime_error(what){
+ /* NOP */
+}
+
+/***********************************************************************
* Props
**********************************************************************/
named_prop_t::named_prop_t(
diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt
index 1791d9082..61b0b503d 100644
--- a/host/test/CMakeLists.txt
+++ b/host/test/CMakeLists.txt
@@ -21,6 +21,8 @@
ADD_EXECUTABLE(main_test
main_test.cpp
addr_test.cpp
+ dict_test.cpp
+ error_test.cpp
gain_handler_test.cpp
vrt_test.cpp
wax_test.cpp
diff --git a/host/test/addr_test.cpp b/host/test/addr_test.cpp
index 93b7cc0df..0c50200d6 100644
--- a/host/test/addr_test.cpp
+++ b/host/test/addr_test.cpp
@@ -18,6 +18,7 @@
#include <boost/test/unit_test.hpp>
#include <uhd/types/mac_addr.hpp>
#include <uhd/types/device_addr.hpp>
+#include <uhd/usrp/dboard_id.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>
#include <algorithm>
@@ -41,8 +42,8 @@ BOOST_AUTO_TEST_CASE(test_device_addr){
dev_addr["key2"] = "val2";
//convert to and from args string
- std::cout << "Pretty Print: " << std::endl << dev_addr.to_string();
- std::string args_str = dev_addr.to_args_str();
+ std::cout << "Pretty Print: " << std::endl << dev_addr.to_pp_string();
+ std::string args_str = dev_addr.to_string();
std::cout << "Args String: " << args_str << std::endl;
uhd::device_addr_t new_dev_addr(args_str);
@@ -65,3 +66,15 @@ BOOST_AUTO_TEST_CASE(test_device_addr){
new_dev_addr_vals.begin(), new_dev_addr_vals.end()
);
}
+
+BOOST_AUTO_TEST_CASE(test_dboard_id){
+ std::cout << "Testing dboard id..." << std::endl;
+
+ using namespace uhd::usrp;
+
+ BOOST_CHECK(dboard_id_t() == dboard_id_t::none());
+ BOOST_CHECK_EQUAL(dboard_id_t().to_uint16(), dboard_id_t::none().to_uint16());
+ BOOST_CHECK_EQUAL(dboard_id_t::from_string("0x1234").to_uint16(), 0x1234);
+ BOOST_CHECK_EQUAL(dboard_id_t::from_string("1234").to_uint16(), 1234);
+ std::cout << "Pretty Print: " << std::endl << dboard_id_t::none().to_pp_string();
+}
diff --git a/host/test/dict_test.cpp b/host/test/dict_test.cpp
new file mode 100644
index 000000000..0501a7878
--- /dev/null
+++ b/host/test/dict_test.cpp
@@ -0,0 +1,72 @@
+//
+// 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 <boost/test/unit_test.hpp>
+#include <uhd/types/dict.hpp>
+#include <boost/assign/list_of.hpp>
+
+BOOST_AUTO_TEST_CASE(test_dict_init){
+ uhd::dict<int, int> d;
+ d[-1] = 3;
+ d[0] = 4;
+ d[1] = 5;
+ BOOST_CHECK(d.has_key(0));
+ BOOST_CHECK(not d.has_key(2));
+ BOOST_CHECK(d.keys()[1] == 0);
+ BOOST_CHECK(d.vals()[1] == 4);
+ BOOST_CHECK_EQUAL(d[-1], 3);
+}
+
+BOOST_AUTO_TEST_CASE(test_dict_assign){
+ uhd::dict<int, int> d = boost::assign::map_list_of
+ (-1, 3)
+ (0, 4)
+ (1, 5)
+ ;
+ BOOST_CHECK(d.has_key(0));
+ BOOST_CHECK(not d.has_key(2));
+ BOOST_CHECK(d.keys()[1] == 0);
+ BOOST_CHECK(d.vals()[1] == 4);
+ BOOST_CHECK_EQUAL(d[-1], 3);
+}
+
+BOOST_AUTO_TEST_CASE(test_const_dict){
+ const uhd::dict<int, int> d = boost::assign::map_list_of
+ (-1, 3)
+ (0, 4)
+ (1, 5)
+ ;
+ BOOST_CHECK(d.has_key(0));
+ BOOST_CHECK(not d.has_key(2));
+ BOOST_CHECK(d.keys()[1] == 0);
+ BOOST_CHECK(d.vals()[1] == 4);
+ BOOST_CHECK_EQUAL(d[-1], 3);
+ BOOST_CHECK_THROW(d[2], std::exception);
+}
+
+BOOST_AUTO_TEST_CASE(test_dict_pop){
+ uhd::dict<int, int> d = boost::assign::map_list_of
+ (-1, 3)
+ (0, 4)
+ (1, 5)
+ ;
+ BOOST_CHECK(d.has_key(0));
+ BOOST_CHECK_EQUAL(d.pop(0), 4);
+ BOOST_CHECK(not d.has_key(0));
+ BOOST_CHECK(d.keys()[0] == -1);
+ BOOST_CHECK(d.keys()[1] == 1);
+}
diff --git a/host/test/error_test.cpp b/host/test/error_test.cpp
new file mode 100644
index 000000000..c76a15ab7
--- /dev/null
+++ b/host/test/error_test.cpp
@@ -0,0 +1,48 @@
+//
+// 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 <boost/test/unit_test.hpp>
+#include <uhd/utils/assert.hpp>
+#include <vector>
+#include <iostream>
+
+BOOST_AUTO_TEST_CASE(test_assert_has){
+ std::vector<int> vec;
+ vec.push_back(2);
+ vec.push_back(3);
+ vec.push_back(5);
+
+ //verify the std::has utility
+ BOOST_CHECK(std::has(vec, 2));
+ BOOST_CHECK(not std::has(vec, 1));
+
+ std::cout << "The output of the assert_has error:" << std::endl;
+ try{
+ uhd::assert_has(vec, 1, "prime");
+ }catch(const std::exception &e){
+ std::cout << e.what() << std::endl;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_assert_throw){
+ std::cout << "The output of the assert throw error:" << std::endl;
+ try{
+ UHD_ASSERT_THROW(2 + 2 == 5);
+ }catch(const std::exception &e){
+ std::cout << e.what() << std::endl;
+ }
+}
diff --git a/host/utils/uhd_burn_db_eeprom.cpp b/host/utils/uhd_burn_db_eeprom.cpp
index c07b43f16..dfd9decba 100644
--- a/host/utils/uhd_burn_db_eeprom.cpp
+++ b/host/utils/uhd_burn_db_eeprom.cpp
@@ -24,11 +24,9 @@
#include <uhd/usrp/mboard_props.hpp>
#include <uhd/usrp/dboard_props.hpp>
#include <boost/program_options.hpp>
-#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#include <boost/assign.hpp>
#include <iostream>
-#include <sstream>
using namespace uhd;
using namespace uhd::usrp;
@@ -89,14 +87,14 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
if (vm.count("id") == 0){
std::cout << boost::format("Getting dbid on %s dboard...") % prefix << std::endl;
dboard_id_t id = dboard[DBOARD_PROP_DBOARD_ID].as<dboard_id_t>();
- std::cout << boost::format(" Current dbid: %s") % dboard_id::to_string(id) << std::endl;
+ std::cout << boost::format(" Current dbid: %s") % id.to_pp_string() << std::endl;
}
//write a new dboard id to eeprom
else{
- dboard_id_t id = boost::lexical_cast<to_hex<dboard_id_t> >(vm["id"].as<std::string>());
+ dboard_id_t id = dboard_id_t::from_string(vm["id"].as<std::string>());
std::cout << boost::format("Setting dbid on %s dboard...") % prefix << std::endl;
- std::cout << boost::format(" New dbid: %s") % dboard_id::to_string(id) << std::endl;
+ std::cout << boost::format(" New dbid: %s") % id.to_pp_string() << std::endl;
dboard[DBOARD_PROP_DBOARD_ID] = id;
}
diff --git a/host/utils/uhd_find_devices.cpp b/host/utils/uhd_find_devices.cpp
index 69e550fd4..b778eeb68 100644
--- a/host/utils/uhd_find_devices.cpp
+++ b/host/utils/uhd_find_devices.cpp
@@ -52,7 +52,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::cout << "--------------------------------------------------" << std::endl;
std::cout << "-- UHD Device " << i << std::endl;
std::cout << "--------------------------------------------------" << std::endl;
- std::cout << device_addrs[i].to_string() << std::endl << std::endl;
+ std::cout << device_addrs[i].to_pp_string() << std::endl << std::endl;
//uhd::device::make(device_addrs[i]); //test make
}