From ba658f4d2cac9fb0f9d22060da989c9078cc4d1e Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 21 Sep 2010 10:41:05 -0700 Subject: added db_tvrx, regmap gen_dtt75403_regs.py --- host/lib/usrp/dboard/db_tvrx.cpp | 316 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 host/lib/usrp/dboard/db_tvrx.cpp (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp new file mode 100644 index 000000000..5582dbe33 --- /dev/null +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -0,0 +1,316 @@ +// +// 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 . +// + +// No RX IO Pins Used + +// RX IO Functions + +//ADC/DAC functions: +//DAC 1: RF AGC +//DAC 2: IF AGC + +//min freq: 50e6 +//max freq: 860e6 +//gain range: [0:1dB:115dB] + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + +/*********************************************************************** + * The tvrx constants + **********************************************************************/ +static const bool tvrx_debug = true; + +static const freq_range_t tvrx_freq_range(50e6, 860e6); + +static const prop_names_t tvrx_antennas = ""; //only got one + +static const uhd::dict tvrx_gain_ranges = map_list_of + ("RF", gain_range_t(0, 60, float(60.0/4096))) //both gains are analog and controlled by DAC + ("IF", gain_range_t(0, 35, float(35.0/4096))) //the old driver used 1dB for both; i don't think that's right? +; + +static const uhd::dict tvrx_freq_ranges = map_list_of + ("VHFLO", freq_range_t(50e6, 158e6)) //this isn't used outside this driver. just for us. + ("VHFHI", freq_range_t(158e6, 454e6)) + ("UHF" , freq_range_t(454e6, 860e6)) +; + +//we might need to spec the various bands for band selection. + +static const double tvrx_lo_freq = 36e6; //LO freq of TVRX module + +/*********************************************************************** + * The tvrx dboard class + **********************************************************************/ +class tvrx : public rx_dboard_base{ +public: + tvrx(ctor_args_t args); + ~tvrx(void); + + void rx_get(const wax::obj &key, wax::obj &val); + void rx_set(const wax::obj &key, const wax::obj &val); + +private: + uhd::dict _gains; + dtt75403_regs_t _dtt75403_regs; + boost::uint8_t _dtt75403_addr(void){ + return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x60 : 0x61; //ok really? we could rename that call + }; + + void set_gain(float gain, const std::string &name); + + void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ + //why is this an inline anyway? bring this out + start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0x5)); + stop_reg = boost::uint8_t(std::clip(int(stop_reg), 0x0, 0x5)); + + for(boost::uint8_t start_addr=start_reg; start_addr <= stop_reg; start_addr += sizeof(boost::uint32_t) - 1){ + int num_bytes = int(stop_reg - start_addr + 1) > int(sizeof(boost::uint32_t)) - 1 ? sizeof(boost::uint32_t) - 1 : stop_reg - start_addr + 1; + + //create buffer for register data (+1 for start address) + byte_vector_t regs_vector(num_bytes + 1); + + //first byte is the address of first register + regs_vector[0] = start_addr; + + //get the register data + for(int i=0; iget_iface()->write_i2c( + _max2118_addr(), regs_vector + ); + } + } + +}; + +/*********************************************************************** + * Register the tvrx dboard + **********************************************************************/ +static dboard_base::sptr make_tvrx(dboard_base::ctor_args_t args){ + return dboard_base::sptr(new tvrx(args)); +} + +UHD_STATIC_BLOCK(reg_tvrx_dboard){ + //register the factory function for the rx dbid + dboard_manager::register_dboard(0x0003, &make_tvrx, "tvrx"); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){ + //enable only the clocks we need + + //TODO: YOU GOT SOME CLOCK SETUP TO DO HERE, DOGGGG + + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + + //set the gpio directions and atr controls (identically) + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0); // All unused in atr + if (this->get_iface()->get_special_props().soft_clock_divider){ + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x1); // GPIO0 is clock + } + else{ + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs + } + + //send initial register settings + //HAAAAY GUYYYYYSSS + + //set default gains + BOOST_FOREACH(const std::string &name, tvrx_gain_ranges.keys()){ + set_gain(tvrx_gain_ranges[name].min, name); + } +} + +tvrx::~tvrx(void){ +} + +/*********************************************************************** + * Gain Handling + **********************************************************************/ +/*! + * Convert a requested gain for the GC2 vga into the integer register value. + * The gain passed into the function will be set to the actual value. + * \param gain the requested gain in dB + * \return 5 bit the register value + */ + +//yo this should look the same as the below one for the IF, dogg +static int gain_to_gc2_vga_reg(float &gain){ + int reg = 0; + gain = std::clip(float(boost::math::iround(gain)), tvrx_gain_ranges["GC2"].min, tvrx_gain_ranges["GC2"].max); + + // Half dB steps from 0-5dB, 1dB steps from 5-24dB + if (gain < 5) { + reg = boost::math::iround(31.0 - gain/0.5); + gain = float(boost::math::iround(gain) * 0.5); + } else { + reg = boost::math::iround(22.0 - (gain - 4.0)); + gain = float(boost::math::iround(gain)); + } + + if (tvrx_debug) std::cerr << boost::format( + "tvrx GC2 Gain: %f dB, reg: %d" + ) % gain % reg << std::endl; + + return reg; +} + +/*! + * Convert a requested gain for the RF gain into the dac_volts value. + * The gain passed into the function will be set to the actual value. + * \param gain the requested gain in dB + * \return dac voltage value + */ + +//yo what about the 1.22 opamp gain of the USRP1 -- is this replicated on U2? +static float gain_to_rfgain_dac(float &gain){ + //clip the input + gain = std::clip(gain, tvrx_gain_ranges["RF"].min, tvrx_gain_ranges["RF"].max); + + //voltage level constants + static const float max_volts = float(0), min_volts = float(3.3); + static const float slope = (max_volts-min_volts)/tvrx_gain_ranges["RF"].max; + + //calculate the voltage for the aux dac + float dac_volts = gain*slope + min_volts; + + if (tvrx_debug) std::cerr << boost::format( + "tvrx RFAGC Gain: %f dB, dac_volts: %f V" + ) % gain % dac_volts << std::endl; + + //the actual gain setting + gain = (dac_volts - min_volts)/slope; + + return dac_volts; +} + +void tvrx::set_gain(float gain, const std::string &name){ + assert_has(tvrx_gain_ranges.keys(), name, "tvrx gain name"); + if (name == "RF"){ +//should look the same as below + } + else if(name == "IF"){ + //write the new voltage to the aux dac CHECK THIS + this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, gain_to_gc1_rfvga_dac(gain)); + } + else UHD_THROW_INVALID_CODE_PATH(); + _gains[name] = gain; +} + +/*********************************************************************** + * RX Get and Set + **********************************************************************/ +void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + 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: + assert_has(_gains.keys(), key.name, "tvrx gain name"); + val = _gains[key.name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(tvrx_gain_ranges.keys(), key.name, "tvrx gain name"); + val = tvrx_gain_ranges[key.name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(tvrx_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = tvrx_lo_freq; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = tvrx_freq_range; + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string(tvrx_antennas); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = tvrx_antennas; + return; + + case SUBDEV_PROP_CONNECTION: + val = SUBDEV_CONN_COMPLEX_IQ; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = false; + return; + + case SUBDEV_PROP_LO_LOCKED: + val = true; + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +//for smaaht kids to use to set advanced props +void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_GAIN: + this->set_gain(val.as(), key.name); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } +} + -- cgit v1.2.3 From a6f60ab4911fa756656a62ebe3a1093d52836a6e Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Mon, 27 Sep 2010 19:19:55 -0700 Subject: TVRX: not done yet but getting there. gain linearization framework in place. --- host/lib/ic_reg_maps/CMakeLists.txt | 4 +- host/lib/ic_reg_maps/gen_dtt75403_regs.py | 85 ---------- host/lib/ic_reg_maps/gen_tuner_4937di5_regs.py | 75 +++++++++ host/lib/usrp/dboard/db_tvrx.cpp | 218 +++++++++++++++++-------- 4 files changed, 225 insertions(+), 157 deletions(-) delete mode 100755 host/lib/ic_reg_maps/gen_dtt75403_regs.py create mode 100644 host/lib/ic_reg_maps/gen_tuner_4937di5_regs.py (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/ic_reg_maps/CMakeLists.txt b/host/lib/ic_reg_maps/CMakeLists.txt index b396db4ca..25f34a280 100644 --- a/host/lib/ic_reg_maps/CMakeLists.txt +++ b/host/lib/ic_reg_maps/CMakeLists.txt @@ -70,6 +70,6 @@ LIBUHD_PYTHON_GEN_SOURCE( ) LIBUHD_PYTHON_GEN_SOURCE( - ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_dtt75403_regs.py - ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/dtt75403_regs.py + ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_tuner_4937di5_regs.py + ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/tuner_4937di5_regs.hpp ) diff --git a/host/lib/ic_reg_maps/gen_dtt75403_regs.py b/host/lib/ic_reg_maps/gen_dtt75403_regs.py deleted file mode 100755 index fe64bd92a..000000000 --- a/host/lib/ic_reg_maps/gen_dtt75403_regs.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2010 Ettus Research LLC -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - -######################################################################## -# Template for raw text data describing registers -# name addr[bit range inclusive] default optional enums -######################################################################## -REGS_TMPL="""\ -######################################################################## -## Note: offsets given from perspective of data bits (excludes address) -######################################################################## -## -######################################################################## -## Address byte -######################################################################## -adb 0[1:2] 0 -######################################################################## -## Divider byte 1 -######################################################################## -db1 1[0:6] 0x00 -######################################################################## -## Divider byte 2 -######################################################################## -db2 2[0:7] 0x00 -######################################################################## -## Control byte 1 -######################################################################## -atp 3[3:5] 0 112, 109, 106, 103, 100, 94, 94, disable -refdiv 3[0:2] 0 166.667khz, 142.857khz, 80khz, 62.5khz, 31.25khz, 50khz -######################################################################## -## Band switch byte -######################################################################## -cpsel 4[6:7] 0 -filterbw 4[4] 0 8mhz, 7mhz -bandsel 4[0:3] 0 -######################################################################## -## Control byte 2 -######################################################################## -atc 5[5] 0 low, high -stby 5[4] 0 standby, on -xto 5[0] 0 disable, enable -""" - -######################################################################## -# Template for methods in the body of the struct -######################################################################## -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 - break; - #end for - } - return boost::uint8_t(reg); -} - -""" - -if __name__ == '__main__': - import common; common.generate( - name='dtt75403_regs', - regs_tmpl=REGS_TMPL, - body_tmpl=BODY_TMPL, - file=__file__, - ) diff --git a/host/lib/ic_reg_maps/gen_tuner_4937di5_regs.py b/host/lib/ic_reg_maps/gen_tuner_4937di5_regs.py new file mode 100644 index 000000000..73f7aa3db --- /dev/null +++ b/host/lib/ic_reg_maps/gen_tuner_4937di5_regs.py @@ -0,0 +1,75 @@ +#!/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 . +# + +######################################################################## +# Template for raw text data describing registers +# name addr[bit range inclusive] default optional enums +######################################################################## +REGS_TMPL="""\ +######################################################################## +## Note: offsets given from perspective of data bits (excludes address) +######################################################################## +## Divider byte 1 +######################################################################## +db1 0[0:6] 0x00 +######################################################################## +## Divider byte 2 +######################################################################## +db2 1[0:7] 0x00 +######################################################################## +## Control byte 1 +######################################################################## +cb7 2[7] 0x01 +cp 2[6] 0x00 low,high +os 2[0] 0x00 on,off +rs 2[1:2] 0x00 d512=3,d640=0,d1024=1 +test 2[3:5] 0x01 normal=0x01,cpoff=0x02,cpsink=0x06,cpsrc=0x07,cptest1=0x04,cptest2=0x05 +######################################################################## +## Control byte 2 +######################################################################## +bandsel 3[4:7] 0x03 uhf=0x03,vhfhi=0x09,vhflo=0x0a +power 3[3] 0x00 on,off +""" + +######################################################################## +# Template for methods in the body of the struct +######################################################################## +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 + break; + #end for + } + return boost::uint8_t(reg); +} + +""" + +if __name__ == '__main__': + import common; common.generate( + name='tuner_4937di5_regs', + regs_tmpl=REGS_TMPL, + body_tmpl=BODY_TMPL, + file=__file__, + ) diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 5582dbe33..ed6025433 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -42,6 +42,7 @@ #include #include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -57,19 +58,73 @@ static const freq_range_t tvrx_freq_range(50e6, 860e6); static const prop_names_t tvrx_antennas = ""; //only got one static const uhd::dict tvrx_gain_ranges = map_list_of - ("RF", gain_range_t(0, 60, float(60.0/4096))) //both gains are analog and controlled by DAC - ("IF", gain_range_t(0, 35, float(35.0/4096))) //the old driver used 1dB for both; i don't think that's right? + ("RF", gain_range_t(-13.3, 50.3, float(50.3/4096))) //both gains are analog and controlled by DAC + ("IF", gain_range_t(-1.5, 32.5, float(32.5/4096))) //the old driver used 1dB for both; i don't think that's right? ; static const uhd::dict tvrx_freq_ranges = map_list_of - ("VHFLO", freq_range_t(50e6, 158e6)) //this isn't used outside this driver. just for us. + ("VHFLO", freq_range_t(50e6, 158e6)) ("VHFHI", freq_range_t(158e6, 454e6)) ("UHF" , freq_range_t(454e6, 860e6)) ; -//we might need to spec the various bands for band selection. +//gain linearization data +//this is from the datasheet and is dB vs. volts (below) +//i tried to curve fit this, but it's really just so nonlinear that you'd +//need dang near as many coefficients as to just map it like this and interp. +//these numbers are culled from the 4937DI5 datasheet and are probably totally inaccurate +//but if it's better than the old linear fit i'm happy +static const uhd::dict > tvrx_rf_gains_db = map_list_of + ("VHFLO", std::vector(-6.00000, -6.00000, -6.00000, -4.00000, 0.00000, + 5.00000, 10.00000, 17.40000, 26.30000, 36.00000, + 43.00000, 48.00000, 49.50000, 50.10000, 50.30000, + 50.30000, 50.30000)) + ("VHFHI", std::vector(-13.3000, -13.3000, -13.3000, -1.0000, 7.7000, + 11.0000, 14.7000, 19.3000, 26.1000, 36.0000, + 42.7000, 46.0000, 47.0000, 47.8000, 48.2000, + 48.2000, 48.2000)) + ("UHF" , std::vector(-8.0000, -8.0000, -7.0000, 4.0000, 10.2000, + 14.5000, 17.5000, 20.0000, 24.5000, 30.8000, + 37.0000, 39.8000, 40.7000, 41.6000, 42.6000, + 43.2000, 43.8000)) +; + +static const std::vector tvrx_if_gains_db = + std::vector(-1.50000, -1.50000, -1.50000, -1.00000, 0.20000, + 2.10000, 4.30000, 6.40000, 9.00000, 12.00000, + 14.80000, 18.20000, 26.10000, 32.50000, 32.50000, + 32.50000, 32.50000) +; + +//sample voltages for the above points +static const std::vector tvrx_rf_gains_volts = + std::vector(0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0); -static const double tvrx_lo_freq = 36e6; //LO freq of TVRX module + +/*! + * Execute a linear interpolation to find the voltage corresponding to a desired gain + * \param gain the desired gain in dB + * \param db_vector the vector of dB readings + * \param volts_vector the corresponding vector of voltages db_vector was sampled at + * \return a voltage to feed the TVRX analog gain + */ + +static float gain_interp(float gain, std::vector db_vector, std::vector volts_vector) { + float volts; + gain = std::clip(gain, db_vector.front(), db_vector.back()); //let's not get carried away here + + boost::uint8_t gain_step = 0; + for(int i = 0; i < db_vector.size()-1; i++) { + if(gain > db_vector[i] && gain < db_vector.[i+1]) gain_step = i; + } + + + return volts; +} + +static const double opamp_gain = 1.22; //onboard DAC opamp gain +static const double tvrx_lo_freq = 43.75e6; //LO freq of TVRX module +static const boost::uint16_t reference_divider = 640; //clock reference divider to use /*********************************************************************** * The tvrx dboard class @@ -84,40 +139,28 @@ public: private: uhd::dict _gains; - dtt75403_regs_t _dtt75403_regs; - boost::uint8_t _dtt75403_addr(void){ + tuner_4937di5_regs_t _tuner_4937di5_regs; + boost::uint8_t _tuner_4937di5_addr(void){ return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x60 : 0x61; //ok really? we could rename that call }; void set_gain(float gain, const std::string &name); - void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ - //why is this an inline anyway? bring this out - start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0x5)); - stop_reg = boost::uint8_t(std::clip(int(stop_reg), 0x0, 0x5)); - - for(boost::uint8_t start_addr=start_reg; start_addr <= stop_reg; start_addr += sizeof(boost::uint32_t) - 1){ - int num_bytes = int(stop_reg - start_addr + 1) > int(sizeof(boost::uint32_t)) - 1 ? sizeof(boost::uint32_t) - 1 : stop_reg - start_addr + 1; - - //create buffer for register data (+1 for start address) - byte_vector_t regs_vector(num_bytes + 1); + void update_regs(void){ + byte_vector_t regs_vector(4); - //first byte is the address of first register - regs_vector[0] = start_addr; - - //get the register data - for(int i=0; iget_iface()->write_i2c( - _max2118_addr(), regs_vector - ); + //get the register data + for(int i=0; i<4; i++){ + regs_vector[i] = _tuner_4937di5_regs.get_reg(i); + if(tvrx_debug) std::cerr << boost::format( + "tvrx: send reg 0x%02x, value 0x%04x" + ) % int(i) % int(regs_vector[i]) << std::endl; } + + //send the data + this->get_iface()->write_i2c( + _tuner_4937di5_addr(), regs_vector + ); } }; @@ -138,10 +181,6 @@ UHD_STATIC_BLOCK(reg_tvrx_dboard){ * Structors **********************************************************************/ tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){ - //enable only the clocks we need - - //TODO: YOU GOT SOME CLOCK SETUP TO DO HERE, DOGGGG - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); //set the gpio directions and atr controls (identically) @@ -165,77 +204,114 @@ tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){ tvrx::~tvrx(void){ } +/*! Return a string corresponding to the relevant band + * \param freq the frequency of interest + * \return a string corresponding to the band + */ + +static std::string get_band(double freq) { + BOOST_FOREACH(const std::string &band, tvrx_freq_ranges.keys()) { + if(freq >= tvrx_freq_ranges[band].min && freq <= tvrx_freq_ranges[band].max) + return name; + } + UHD_THROW_INVALID_CODE_PATH(); +} + /*********************************************************************** * Gain Handling **********************************************************************/ +/* + * Gain accuracy on this thing is basically a crap shoot. In other words, there is none. + * The old driver basically picked a linear approximation of the median gain, but the actual + * gain slope is heavily nonlinear and varies both with gain and with frequency. + * It also probably varies markedly over temperature, but there's only so much we can do. + * The best approximation to the RF gain data is fifth-order. If we ignore the curve portions + * below 0dB (yes, it's a pad below a certain gain value) and if we ignore the curve portions + * near the max-gain asymptotes, it looks pretty close to third-order. This is less insane to + * approximate. + */ + /*! - * Convert a requested gain for the GC2 vga into the integer register value. + * Convert a requested gain for the RF gain into a DAC voltage. * The gain passed into the function will be set to the actual value. * \param gain the requested gain in dB - * \return 5 bit the register value + * \return dac voltage value */ -//yo this should look the same as the below one for the IF, dogg -static int gain_to_gc2_vga_reg(float &gain){ - int reg = 0; - gain = std::clip(float(boost::math::iround(gain)), tvrx_gain_ranges["GC2"].min, tvrx_gain_ranges["GC2"].max); - - // Half dB steps from 0-5dB, 1dB steps from 5-24dB - if (gain < 5) { - reg = boost::math::iround(31.0 - gain/0.5); - gain = float(boost::math::iround(gain) * 0.5); - } else { - reg = boost::math::iround(22.0 - (gain - 4.0)); - gain = float(boost::math::iround(gain)); - } +static float rf_gain_to_voltage(float &gain){ + //clip the input + gain = std::clip(gain, tvrx_gain_ranges["RF"].min, tvrx_gain_ranges["RF"].max); + + //voltage level constants + static const float max_volts = float(4.0), min_volts = float(0.6); + static const float slope = (max_volts-min_volts)/tvrx_gain_ranges["RF"].max; + + //this is the voltage at the TVRX gain input + float gain_volts = gain*slope + min_volts + //this is the voltage at the USRP DAC output + float dac_volts = gain_volts / opamp_gain; + + //the actual gain setting + gain = (dac_volts - min_volts)/slope; if (tvrx_debug) std::cerr << boost::format( - "tvrx GC2 Gain: %f dB, reg: %d" - ) % gain % reg << std::endl; + "tvrx RF AGC gain: %f dB, dac_volts: %f V" + ) % gain % dac_volts << std::endl; - return reg; + return dac_volts; } /*! - * Convert a requested gain for the RF gain into the dac_volts value. + * Convert a requested gain for the IF gain into a DAC voltage. * The gain passed into the function will be set to the actual value. * \param gain the requested gain in dB * \return dac voltage value */ -//yo what about the 1.22 opamp gain of the USRP1 -- is this replicated on U2? -static float gain_to_rfgain_dac(float &gain){ +static float if_gain_to_voltage(float &gain){ //clip the input - gain = std::clip(gain, tvrx_gain_ranges["RF"].min, tvrx_gain_ranges["RF"].max); + gain = std::clip(gain, tvrx_gain_ranges["IF"].min, tvrx_gain_ranges["IF"].max); //voltage level constants - static const float max_volts = float(0), min_volts = float(3.3); - static const float slope = (max_volts-min_volts)/tvrx_gain_ranges["RF"].max; + static const float max_volts = float(4.0), min_volts = float(0.0); + static const float slope = (max_volts-min_volts)/tvrx_gain_ranges["IF"].max; - //calculate the voltage for the aux dac - float dac_volts = gain*slope + min_volts; - - if (tvrx_debug) std::cerr << boost::format( - "tvrx RFAGC Gain: %f dB, dac_volts: %f V" - ) % gain % dac_volts << std::endl; + //this is the voltage at the TVRX gain input + float gain_volts = gain*slope + 1.25; + //this is the voltage at the USRP DAC output + float dac_volts = gain_volts / opamp_gain; //the actual gain setting gain = (dac_volts - min_volts)/slope; + if (tvrx_debug) std::cerr << boost::format( + "tvrx IF AGC gain: %f dB, dac_volts: %f V" + ) % gain % dac_volts << std::endl; + return dac_volts; } void tvrx::set_gain(float gain, const std::string &name){ assert_has(tvrx_gain_ranges.keys(), name, "tvrx gain name"); if (name == "RF"){ -//should look the same as below + this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, rf_gain_to_voltage(gain)); } else if(name == "IF"){ - //write the new voltage to the aux dac CHECK THIS - this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, gain_to_gc1_rfvga_dac(gain)); + this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_B, if_gain_to_voltage(gain)); } else UHD_THROW_INVALID_CODE_PATH(); _gains[name] = gain; +} + +/*! + * Set the tuner to center the desired frequency at 43.75MHz + * \param freq the requested frequency + */ + +void tvrx::set_freq(double freq) { + + + } /*********************************************************************** @@ -300,7 +376,6 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ } } -//for smaaht kids to use to set advanced props void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); @@ -309,6 +384,9 @@ void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_GAIN: this->set_gain(val.as(), key.name); return; + case SUBDEV_PROP_FREQ: + this->set_freq(val.as()); + return; default: UHD_THROW_PROP_SET_ERROR(); } -- cgit v1.2.3 From 15eacbd920a0527ec16c24baeb1d6b87f29d9110 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 28 Sep 2010 13:52:09 -0700 Subject: TVRX: Don't have mboard impl modified for ADC buffer disable. The rest of TVRX should be in there. Not debugged. --- host/lib/usrp/dboard/CMakeLists.txt | 1 + host/lib/usrp/dboard/db_tvrx.cpp | 219 +++++++++++++++++++++--------------- host/lib/usrp/usrp1/codec_ctrl.cpp | 13 +++ host/lib/usrp/usrp1/codec_ctrl.hpp | 3 + 4 files changed, 147 insertions(+), 89 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index 3e995009e..8d3d11530 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -24,5 +24,6 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_wbx.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_dbsrx.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_unknown.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/dboard/db_tvrx.cpp ) diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index ed6025433..2988367e2 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -39,9 +39,11 @@ #include #include #include +#include #include #include #include +#include #include using namespace uhd; @@ -55,12 +57,11 @@ static const bool tvrx_debug = true; static const freq_range_t tvrx_freq_range(50e6, 860e6); -static const prop_names_t tvrx_antennas = ""; //only got one +static const std::string tvrx_antennas = std::string(""); //only got one -static const uhd::dict tvrx_gain_ranges = map_list_of - ("RF", gain_range_t(-13.3, 50.3, float(50.3/4096))) //both gains are analog and controlled by DAC - ("IF", gain_range_t(-1.5, 32.5, float(32.5/4096))) //the old driver used 1dB for both; i don't think that's right? -; +//a note on these: the gain of the TVRX varies over frequency. the gain ranges +//below correspond to the maximum and minimum gains over the entire frequency range. +//specifying a gain higher or lower than the TVRX can accomplish will of course just clip. static const uhd::dict tvrx_freq_ranges = map_list_of ("VHFLO", freq_range_t(50e6, 158e6)) @@ -68,63 +69,68 @@ static const uhd::dict tvrx_freq_ranges = map_list_of ("UHF" , freq_range_t(454e6, 860e6)) ; +static const boost::array vhflo_gains_db = + {{-6.00000, -6.00000, -6.00000, -4.00000, 0.00000, + 5.00000, 10.00000, 17.40000, 26.30000, 36.00000, + 43.00000, 48.00000, 49.50000, 50.10000, 50.30000, + 50.30000, 50.30000}}; + +static const boost::array vhfhi_gains_db = + {{13.3000, -13.3000, -13.3000, -1.0000, 7.7000, + 11.0000, 14.7000, 19.3000, 26.1000, 36.0000, + 42.7000, 46.0000, 47.0000, 47.8000, 48.2000, + 48.2000, 48.2000}}; + +static const boost::array uhf_gains_db = + {{-8.0000, -8.0000, -7.0000, 4.0000, 10.2000, + 14.5000, 17.5000, 20.0000, 24.5000, 30.8000, + 37.0000, 39.8000, 40.7000, 41.6000, 42.6000, + 43.2000, 43.8000}}; + +static const boost::array tvrx_if_gains_db = + {{-1.50000, -1.50000, -1.50000, -1.00000, 0.20000, + 2.10000, 4.30000, 6.40000, 9.00000, 12.00000, + 14.80000, 18.20000, 26.10000, 32.50000, 32.50000, + 32.50000, 32.50000}}; + //gain linearization data //this is from the datasheet and is dB vs. volts (below) //i tried to curve fit this, but it's really just so nonlinear that you'd //need dang near as many coefficients as to just map it like this and interp. //these numbers are culled from the 4937DI5 datasheet and are probably totally inaccurate //but if it's better than the old linear fit i'm happy -static const uhd::dict > tvrx_rf_gains_db = map_list_of - ("VHFLO", std::vector(-6.00000, -6.00000, -6.00000, -4.00000, 0.00000, - 5.00000, 10.00000, 17.40000, 26.30000, 36.00000, - 43.00000, 48.00000, 49.50000, 50.10000, 50.30000, - 50.30000, 50.30000)) - ("VHFHI", std::vector(-13.3000, -13.3000, -13.3000, -1.0000, 7.7000, - 11.0000, 14.7000, 19.3000, 26.1000, 36.0000, - 42.7000, 46.0000, 47.0000, 47.8000, 48.2000, - 48.2000, 48.2000)) - ("UHF" , std::vector(-8.0000, -8.0000, -7.0000, 4.0000, 10.2000, - 14.5000, 17.5000, 20.0000, 24.5000, 30.8000, - 37.0000, 39.8000, 40.7000, 41.6000, 42.6000, - 43.2000, 43.8000)) -; - -static const std::vector tvrx_if_gains_db = - std::vector(-1.50000, -1.50000, -1.50000, -1.00000, 0.20000, - 2.10000, 4.30000, 6.40000, 9.00000, 12.00000, - 14.80000, 18.20000, 26.10000, 32.50000, 32.50000, - 32.50000, 32.50000) +static const uhd::dict > tvrx_rf_gains_db = map_list_of + ("VHFLO", vhflo_gains_db) + ("VHFHI", vhfhi_gains_db) + ("UHF" , uhf_gains_db) ; //sample voltages for the above points -static const std::vector tvrx_rf_gains_volts = - std::vector(0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0); - - -/*! - * Execute a linear interpolation to find the voltage corresponding to a desired gain - * \param gain the desired gain in dB - * \param db_vector the vector of dB readings - * \param volts_vector the corresponding vector of voltages db_vector was sampled at - * \return a voltage to feed the TVRX analog gain - */ - -static float gain_interp(float gain, std::vector db_vector, std::vector volts_vector) { - float volts; - gain = std::clip(gain, db_vector.front(), db_vector.back()); //let's not get carried away here - - boost::uint8_t gain_step = 0; - for(int i = 0; i < db_vector.size()-1; i++) { - if(gain > db_vector[i] && gain < db_vector.[i+1]) gain_step = i; +static const boost::array tvrx_gains_volts = + {{0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0}}; + +static uhd::dict get_tvrx_gain_ranges(void) { + float rfmax = 0.0, rfmin = FLT_MAX; + BOOST_FOREACH(const std::string range, tvrx_rf_gains_db.keys()) { + float my_max = tvrx_rf_gains_db[range].back(); //we're assuming it's monotonic + float my_min = tvrx_rf_gains_db[range].front(); //if it's not this is wrong wrong wrong + if(my_max > rfmax) rfmax = my_max; + if(my_min < rfmin) rfmin = my_min; } - - return volts; + float ifmin = tvrx_if_gains_db.front(); + float ifmax = tvrx_if_gains_db.back(); + + return map_list_of + ("RF", gain_range_t(rfmin, rfmax, (rfmax-rfmin)/4096.0)) + ("IF", gain_range_t(ifmin, ifmax, (ifmax-ifmin)/4096.0)) + ; } static const double opamp_gain = 1.22; //onboard DAC opamp gain -static const double tvrx_lo_freq = 43.75e6; //LO freq of TVRX module +static const double tvrx_if_freq = 43.75e6; //IF freq of TVRX module static const boost::uint16_t reference_divider = 640; //clock reference divider to use +static const double reference_freq = 4.0e6; /*********************************************************************** * The tvrx dboard class @@ -139,12 +145,14 @@ public: private: uhd::dict _gains; + double _lo_freq; tuner_4937di5_regs_t _tuner_4937di5_regs; boost::uint8_t _tuner_4937di5_addr(void){ return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x60 : 0x61; //ok really? we could rename that call }; void set_gain(float gain, const std::string &name); + void set_freq(double freq); void update_regs(void){ byte_vector_t regs_vector(4); @@ -192,12 +200,14 @@ tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){ this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs } - //send initial register settings - //HAAAAY GUYYYYYSSS + //send initial register settings if necessary + + //set default freq + set_freq(tvrx_freq_range.min); //set default gains - BOOST_FOREACH(const std::string &name, tvrx_gain_ranges.keys()){ - set_gain(tvrx_gain_ranges[name].min, name); + BOOST_FOREACH(const std::string &name, get_tvrx_gain_ranges().keys()){ + set_gain(get_tvrx_gain_ranges()[name].min, name); } } @@ -212,7 +222,7 @@ tvrx::~tvrx(void){ static std::string get_band(double freq) { BOOST_FOREACH(const std::string &band, tvrx_freq_ranges.keys()) { if(freq >= tvrx_freq_ranges[band].min && freq <= tvrx_freq_ranges[band].max) - return name; + return band; } UHD_THROW_INVALID_CODE_PATH(); } @@ -220,17 +230,34 @@ static std::string get_band(double freq) { /*********************************************************************** * Gain Handling **********************************************************************/ -/* - * Gain accuracy on this thing is basically a crap shoot. In other words, there is none. - * The old driver basically picked a linear approximation of the median gain, but the actual - * gain slope is heavily nonlinear and varies both with gain and with frequency. - * It also probably varies markedly over temperature, but there's only so much we can do. - * The best approximation to the RF gain data is fifth-order. If we ignore the curve portions - * below 0dB (yes, it's a pad below a certain gain value) and if we ignore the curve portions - * near the max-gain asymptotes, it looks pretty close to third-order. This is less insane to - * approximate. +/*! + * Execute a linear interpolation to find the voltage corresponding to a desired gain + * \param gain the desired gain in dB + * \param db_vector the vector of dB readings + * \param volts_vector the corresponding vector of voltages db_vector was sampled at + * \return a voltage to feed the TVRX analog gain */ +static float gain_interp(float gain, boost::array db_vector, boost::array volts_vector) { + float volts; + gain = std::clip(gain, db_vector.front(), db_vector.back()); //let's not get carried away here + + boost::uint8_t gain_step = 0; + //find which bin we're in + for(size_t i = 0; i < db_vector.size()-1; i++) { + if(gain > db_vector[i] && gain < db_vector[i+1]) gain_step = i; + } + + //find the current slope for linear interpolation + float slope = (volts_vector[gain_step + 1] - volts_vector[gain_step]) + / (db_vector[gain_step + 1] - db_vector[gain_step]); + + //use the volts per dB slope to find the final interpolated voltage + volts = volts_vector[gain_step] + (slope * (gain - db_vector[gain_step])); + + return volts; +} + /*! * Convert a requested gain for the RF gain into a DAC voltage. * The gain passed into the function will be set to the actual value. @@ -238,22 +265,18 @@ static std::string get_band(double freq) { * \return dac voltage value */ -static float rf_gain_to_voltage(float &gain){ +static float rf_gain_to_voltage(float gain, double lo_freq){ //clip the input - gain = std::clip(gain, tvrx_gain_ranges["RF"].min, tvrx_gain_ranges["RF"].max); + gain = std::clip(gain, get_tvrx_gain_ranges()["RF"].min, get_tvrx_gain_ranges()["RF"].max); - //voltage level constants - static const float max_volts = float(4.0), min_volts = float(0.6); - static const float slope = (max_volts-min_volts)/tvrx_gain_ranges["RF"].max; + //first we need to find out what band we're in, because gains are different across different bands + std::string band = get_band(lo_freq + tvrx_if_freq); //this is the voltage at the TVRX gain input - float gain_volts = gain*slope + min_volts + float gain_volts = gain_interp(gain, tvrx_rf_gains_db[band], tvrx_gains_volts); //this is the voltage at the USRP DAC output float dac_volts = gain_volts / opamp_gain; - //the actual gain setting - gain = (dac_volts - min_volts)/slope; - if (tvrx_debug) std::cerr << boost::format( "tvrx RF AGC gain: %f dB, dac_volts: %f V" ) % gain % dac_volts << std::endl; @@ -268,22 +291,13 @@ static float rf_gain_to_voltage(float &gain){ * \return dac voltage value */ -static float if_gain_to_voltage(float &gain){ +static float if_gain_to_voltage(float gain){ //clip the input - gain = std::clip(gain, tvrx_gain_ranges["IF"].min, tvrx_gain_ranges["IF"].max); - - //voltage level constants - static const float max_volts = float(4.0), min_volts = float(0.0); - static const float slope = (max_volts-min_volts)/tvrx_gain_ranges["IF"].max; - - //this is the voltage at the TVRX gain input - float gain_volts = gain*slope + 1.25; - //this is the voltage at the USRP DAC output + gain = std::clip(gain, get_tvrx_gain_ranges()["IF"].min, get_tvrx_gain_ranges()["IF"].max); + + float gain_volts = gain_interp(gain, tvrx_if_gains_db, tvrx_gains_volts); float dac_volts = gain_volts / opamp_gain; - //the actual gain setting - gain = (dac_volts - min_volts)/slope; - if (tvrx_debug) std::cerr << boost::format( "tvrx IF AGC gain: %f dB, dac_volts: %f V" ) % gain % dac_volts << std::endl; @@ -292,9 +306,9 @@ static float if_gain_to_voltage(float &gain){ } void tvrx::set_gain(float gain, const std::string &name){ - assert_has(tvrx_gain_ranges.keys(), name, "tvrx gain name"); + assert_has(get_tvrx_gain_ranges().keys(), name, "tvrx gain name"); if (name == "RF"){ - this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, rf_gain_to_voltage(gain)); + this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, rf_gain_to_voltage(gain, _lo_freq)); } else if(name == "IF"){ this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_B, if_gain_to_voltage(gain)); @@ -309,9 +323,36 @@ void tvrx::set_gain(float gain, const std::string &name){ */ void tvrx::set_freq(double freq) { + freq = std::clip(freq, tvrx_freq_range.min, tvrx_freq_range.max); + std::string prev_band = get_band(_lo_freq + tvrx_if_freq); + std::string new_band = get_band(freq); + double lo_freq = freq + tvrx_if_freq; //the desired LO freq for high-side mixing + double f_ref = reference_freq / double(reference_divider); //your tuning step size + int divisor = int(lo_freq + (f_ref * 4.0)) / (f_ref * 8); //the divisor we'll use + double actual_lo_freq = (f_ref * 8 * divisor); //the LO freq we'll actually get + + if((divisor & ~0x7fff)) UHD_THROW_INVALID_CODE_PATH(); + + //now we update the registers + _tuner_4937di5_regs.db1 = (divisor >> 8) & 0xff; + _tuner_4937di5_regs.db2 = divisor & 0xff; + + if(new_band == "VHFLO") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_VHFLO; + else if(new_band == "VHFHI") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_VHFHI; + else if(new_band == "UHF") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_UHF; + else UHD_THROW_INVALID_CODE_PATH(); + + _tuner_4937di5_regs.power = tuner_4937di5_regs_t::POWER_ON; + update_regs(); + + //ok don't forget to reset RF gain here if the new band != the old band + //we do this because the gains are different for different band settings + //not FAR off, but we do this to be consistent + if(prev_band != new_band) set_gain(_gains["RF"], "RF"); + _lo_freq = actual_lo_freq; //for rx props } /*********************************************************************** @@ -336,16 +377,16 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_GAIN_RANGE: - assert_has(tvrx_gain_ranges.keys(), key.name, "tvrx gain name"); - val = tvrx_gain_ranges[key.name]; + assert_has(get_tvrx_gain_ranges().keys(), key.name, "tvrx gain name"); + val = get_tvrx_gain_ranges()[key.name]; return; case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(tvrx_gain_ranges.keys()); + val = prop_names_t(get_tvrx_gain_ranges().keys()); return; case SUBDEV_PROP_FREQ: - val = tvrx_lo_freq; + val = _lo_freq - tvrx_if_freq; return; case SUBDEV_PROP_FREQ_RANGE: diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp index 08f2d2a8e..3ab02eeeb 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.cpp +++ b/host/lib/usrp/usrp1/codec_ctrl.cpp @@ -61,6 +61,9 @@ public: float get_tx_pga_gain(void); void set_rx_pga_gain(float, char); float get_rx_pga_gain(char); + + //rx adc buffer control + void bypass_adc_buffers(bool bypass); private: usrp1_iface::sptr _iface; @@ -418,6 +421,16 @@ void usrp1_codec_ctrl_impl::set_duc_freq(double freq) this->send_reg(23); } +/*********************************************************************** + * Codec Control ADC buffer bypass + * Enable this for DC-coupled daughterboards (TVRX) + **********************************************************************/ +void usrp1_codec_ctrl_impl::bypass_adc_buffers(bool bypass) { + _ad9862_regs.byp_buffer_a = bypass; + _ad9862_regs.byp_buffer_b = bypass; + this->send_reg(2); +} + /*********************************************************************** * Codec Control Make **********************************************************************/ diff --git a/host/lib/usrp/usrp1/codec_ctrl.hpp b/host/lib/usrp/usrp1/codec_ctrl.hpp index 259d10ef4..e2e8a010d 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.hpp +++ b/host/lib/usrp/usrp1/codec_ctrl.hpp @@ -92,6 +92,9 @@ public: //! Set the TX modulator frequency virtual void set_duc_freq(double freq) = 0; + + //! Enable or disable ADC buffer bypass + virtual void bypass_adc_buffers(bool bypass) = 0; }; #endif /* INCLUDED_USRP1_CODEC_CTRL_HPP */ -- cgit v1.2.3 From b70d4430d4a898fe99b54740a1c4821ed9a1077b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 28 Sep 2010 15:31:38 -0700 Subject: wbx: fix for id swap typo --- host/lib/usrp/dboard/db_wbx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index ccd897674..e473ce41e 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -154,7 +154,7 @@ static dboard_base::sptr make_wbx(dboard_base::ctor_args_t args){ } UHD_STATIC_BLOCK(reg_wbx_dboards){ - dboard_manager::register_dboard(0x0052, 0x0053, &make_wbx, "WBX"); + dboard_manager::register_dboard(0x0053, 0x0052, &make_wbx, "WBX"); } /*********************************************************************** -- cgit v1.2.3 From 7cb95203f8d7173e3d7070d24f68358be67d0b29 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 28 Sep 2010 17:45:07 -0700 Subject: TVRX: First version that works. The gain linearity is still borked. I'll probably give up on the complicated linearizing stuff and just use the values from the old driver. The tuner's gain-vs-voltage is nothing like the datasheet. --- host/lib/usrp/dboard/db_tvrx.cpp | 44 ++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 13 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 2988367e2..f5b544c18 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include using namespace uhd; @@ -59,10 +60,6 @@ static const freq_range_t tvrx_freq_range(50e6, 860e6); static const std::string tvrx_antennas = std::string(""); //only got one -//a note on these: the gain of the TVRX varies over frequency. the gain ranges -//below correspond to the maximum and minimum gains over the entire frequency range. -//specifying a gain higher or lower than the TVRX can accomplish will of course just clip. - static const uhd::dict tvrx_freq_ranges = map_list_of ("VHFLO", freq_range_t(50e6, 158e6)) ("VHFHI", freq_range_t(158e6, 454e6)) @@ -148,7 +145,7 @@ private: double _lo_freq; tuner_4937di5_regs_t _tuner_4937di5_regs; boost::uint8_t _tuner_4937di5_addr(void){ - return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x60 : 0x61; //ok really? we could rename that call + return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x61 : 0x60; //ok really? we could rename that call }; void set_gain(float gain, const std::string &name); @@ -182,7 +179,7 @@ static dboard_base::sptr make_tvrx(dboard_base::ctor_args_t args){ UHD_STATIC_BLOCK(reg_tvrx_dboard){ //register the factory function for the rx dbid - dboard_manager::register_dboard(0x0003, &make_tvrx, "tvrx"); + dboard_manager::register_dboard(0x0040, &make_tvrx, "tvrx"); } /*********************************************************************** @@ -203,6 +200,7 @@ tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){ //send initial register settings if necessary //set default freq + _lo_freq = tvrx_freq_range.min + tvrx_if_freq; //init _lo_freq to a sane default set_freq(tvrx_freq_range.min); //set default gains @@ -220,9 +218,12 @@ tvrx::~tvrx(void){ */ static std::string get_band(double freq) { + std::cout << "get_band called with freq " << freq << std::endl; BOOST_FOREACH(const std::string &band, tvrx_freq_ranges.keys()) { - if(freq >= tvrx_freq_ranges[band].min && freq <= tvrx_freq_ranges[band].max) + if(freq >= tvrx_freq_ranges[band].min && freq <= tvrx_freq_ranges[band].max){ + std::cout << "Holy poop you're in band " << band << std::endl; return band; + } } UHD_THROW_INVALID_CODE_PATH(); } @@ -245,15 +246,25 @@ static float gain_interp(float gain, boost::array db_vector, boost::a boost::uint8_t gain_step = 0; //find which bin we're in for(size_t i = 0; i < db_vector.size()-1; i++) { - if(gain > db_vector[i] && gain < db_vector[i+1]) gain_step = i; + if(gain >= db_vector[i] && gain <= db_vector[i+1]) gain_step = i; } //find the current slope for linear interpolation float slope = (volts_vector[gain_step + 1] - volts_vector[gain_step]) / (db_vector[gain_step + 1] - db_vector[gain_step]); + + //the problem here is that for gains approaching the maximum, the voltage slope becomes infinite + //i.e., a small change in gain requires an infinite change in voltage + //to cope, we limit the slope + + if(slope == std::numeric_limits::infinity()) + return volts_vector[gain_step]; //use the volts per dB slope to find the final interpolated voltage volts = volts_vector[gain_step] + (slope * (gain - db_vector[gain_step])); + + if(tvrx_debug) + std::cout << "Gain interp: gain: " << gain << ", gain_step: " << int(gain_step) << ", slope: " << slope << ", volts: " << volts << std::endl; return volts; } @@ -276,6 +287,8 @@ static float rf_gain_to_voltage(float gain, double lo_freq){ float gain_volts = gain_interp(gain, tvrx_rf_gains_db[band], tvrx_gains_volts); //this is the voltage at the USRP DAC output float dac_volts = gain_volts / opamp_gain; + + dac_volts = std::clip(dac_volts, 0.0, 3.3); if (tvrx_debug) std::cerr << boost::format( "tvrx RF AGC gain: %f dB, dac_volts: %f V" @@ -297,6 +310,8 @@ static float if_gain_to_voltage(float gain){ float gain_volts = gain_interp(gain, tvrx_if_gains_db, tvrx_gains_volts); float dac_volts = gain_volts / opamp_gain; + + dac_volts = std::clip(dac_volts, 0.0, 3.3); if (tvrx_debug) std::cerr << boost::format( "tvrx IF AGC gain: %f dB, dac_volts: %f V" @@ -324,13 +339,13 @@ void tvrx::set_gain(float gain, const std::string &name){ void tvrx::set_freq(double freq) { freq = std::clip(freq, tvrx_freq_range.min, tvrx_freq_range.max); - std::string prev_band = get_band(_lo_freq + tvrx_if_freq); + std::string prev_band = get_band(_lo_freq - tvrx_if_freq); std::string new_band = get_band(freq); - double lo_freq = freq + tvrx_if_freq; //the desired LO freq for high-side mixing + double target_lo_freq = freq + tvrx_if_freq; //the desired LO freq for high-side mixing double f_ref = reference_freq / double(reference_divider); //your tuning step size - int divisor = int(lo_freq + (f_ref * 4.0)) / (f_ref * 8); //the divisor we'll use + int divisor = int((target_lo_freq + (f_ref * 4.0)) / (f_ref * 8)); //the divisor we'll use double actual_lo_freq = (f_ref * 8 * divisor); //the LO freq we'll actually get if((divisor & ~0x7fff)) UHD_THROW_INVALID_CODE_PATH(); @@ -344,7 +359,7 @@ void tvrx::set_freq(double freq) { else if(new_band == "UHF") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_UHF; else UHD_THROW_INVALID_CODE_PATH(); - _tuner_4937di5_regs.power = tuner_4937di5_regs_t::POWER_ON; + _tuner_4937di5_regs.power = tuner_4937di5_regs_t::POWER_OFF; update_regs(); //ok don't forget to reset RF gain here if the new band != the old band @@ -352,6 +367,9 @@ void tvrx::set_freq(double freq) { //not FAR off, but we do this to be consistent if(prev_band != new_band) set_gain(_gains["RF"], "RF"); + if(tvrx_debug) + std::cout << boost::format("set_freq: target LO: %f f_ref: %f divisor: %i actual LO: %f") % target_lo_freq % f_ref % divisor % actual_lo_freq << std::endl; + _lo_freq = actual_lo_freq; //for rx props } @@ -386,7 +404,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_FREQ: - val = _lo_freq - tvrx_if_freq; + val = _lo_freq - 2*tvrx_if_freq; return; case SUBDEV_PROP_FREQ_RANGE: -- cgit v1.2.3 From 560cbf9a2900a02391f025a3fd50a1616893c8c7 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 28 Sep 2010 18:04:35 -0700 Subject: TVRX: Fixed spectrum inversion (derp derp derp). Removed debug printing. --- host/lib/usrp/dboard/db_tvrx.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index f5b544c18..83a638810 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -54,7 +54,7 @@ using namespace boost::assign; /*********************************************************************** * The tvrx constants **********************************************************************/ -static const bool tvrx_debug = true; +static const bool tvrx_debug = false; static const freq_range_t tvrx_freq_range(50e6, 860e6); @@ -218,10 +218,9 @@ tvrx::~tvrx(void){ */ static std::string get_band(double freq) { - std::cout << "get_band called with freq " << freq << std::endl; BOOST_FOREACH(const std::string &band, tvrx_freq_ranges.keys()) { if(freq >= tvrx_freq_ranges[band].min && freq <= tvrx_freq_ranges[band].max){ - std::cout << "Holy poop you're in band " << band << std::endl; + if(tvrx_debug) std::cout << "Band: " << band << std::endl; return band; } } @@ -404,7 +403,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_FREQ: - val = _lo_freq - 2*tvrx_if_freq; + val = _lo_freq; return; case SUBDEV_PROP_FREQ_RANGE: -- cgit v1.2.3 From 6fe533e19a29ea6cd241b70c38081499a8f3ba55 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 28 Sep 2010 18:09:04 -0700 Subject: TVRX: Mixed up DAC channels. Gain is much more linear now. --- host/lib/usrp/dboard/db_tvrx.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 83a638810..71aff1680 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -322,10 +322,10 @@ static float if_gain_to_voltage(float gain){ void tvrx::set_gain(float gain, const std::string &name){ assert_has(get_tvrx_gain_ranges().keys(), name, "tvrx gain name"); if (name == "RF"){ - this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, rf_gain_to_voltage(gain, _lo_freq)); + this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_B, rf_gain_to_voltage(gain, _lo_freq)); } else if(name == "IF"){ - this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_B, if_gain_to_voltage(gain)); + this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, if_gain_to_voltage(gain)); } else UHD_THROW_INVALID_CODE_PATH(); _gains[name] = gain; -- cgit v1.2.3 From 56751efbe6e0751a2b8cd0f7a31d5dfd07fec5dd Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Wed, 29 Sep 2010 18:27:08 -0700 Subject: TVRX: works for USRP and USRP2. --- host/lib/usrp/dboard/db_tvrx.cpp | 11 ++++++++++- host/lib/usrp/usrp1/codec_ctrl.cpp | 3 ++- host/lib/usrp/usrp1/dboard_iface.cpp | 6 ++++++ 3 files changed, 18 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 71aff1680..6b71a3c6e 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -377,6 +377,7 @@ void tvrx::set_freq(double freq) { **********************************************************************/ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); + int codec_rate; //handle the get request conditioned on the key switch(key.as()){ @@ -403,7 +404,15 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_FREQ: - val = _lo_freq; + /* + * so here we have to do some magic. because the TVRX uses a relatively high IF, + * we have to watch the sample rate to see if the IF will be aliased + * or if it will fall within Nyquist. + */ + codec_rate = this->get_iface()->get_codec_rate(dboard_iface::UNIT_RX); + if(codec_rate/2 > tvrx_if_freq) val = _lo_freq; + //ok take a deep breath i am positive there is an easier way to get this number + else val = _lo_freq - tvrx_if_freq - (tvrx_if_freq-codec_rate)*int(tvrx_if_freq / (codec_rate/2)); return; case SUBDEV_PROP_FREQ_RANGE: diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp index 33b18b196..4aa730573 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.cpp +++ b/host/lib/usrp/usrp1/codec_ctrl.cpp @@ -423,7 +423,8 @@ void usrp1_codec_ctrl_impl::set_duc_freq(double freq) /*********************************************************************** * Codec Control ADC buffer bypass - * Enable this for DC-coupled daughterboards (TVRX) + * Disable this for AC-coupled daughterboards (TVRX) + * By default it is initialized TRUE. **********************************************************************/ void usrp1_codec_ctrl_impl::bypass_adc_buffers(bool bypass) { _ad9862_regs.byp_buffer_a = bypass; diff --git a/host/lib/usrp/usrp1/dboard_iface.cpp b/host/lib/usrp/usrp1/dboard_iface.cpp index 4f0549a37..1ac15a46a 100644 --- a/host/lib/usrp/usrp1/dboard_iface.cpp +++ b/host/lib/usrp/usrp1/dboard_iface.cpp @@ -32,6 +32,8 @@ using namespace uhd; using namespace uhd::usrp; using namespace boost::assign; +static const dboard_id_t tvrx_id(0x0040); + class usrp1_dboard_iface : public dboard_iface { public: @@ -51,6 +53,10 @@ public: //init the clock rate shadows this->set_clock_rate(UNIT_RX, this->get_clock_rates(UNIT_RX).front()); this->set_clock_rate(UNIT_TX, this->get_clock_rates(UNIT_TX).front()); + + //yes this is evil but it's necessary for TVRX to work on USRP1 + if(_rx_dboard_id == tvrx_id) _codec->bypass_adc_buffers(false); + //else _codec->bypass_adc_buffers(false); //don't think this is necessary } ~usrp1_dboard_iface() -- cgit v1.2.3 From a4f8ad59b2abc6d4b1a6c65aa2652083486e3065 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 30 Sep 2010 11:05:33 -0700 Subject: usrp: added subdev enabled property the dboard manager will disable all subdevs at startup and shutdown setting the subdev spec will enable only the subdevs in use all dboards are currently implemented as always enabled nothing tested --- host/include/uhd/usrp/subdev_props.hpp | 1 + host/include/uhd/usrp/subdev_spec.hpp | 6 +++++- host/lib/usrp/dboard/db_basic_and_lf.cpp | 14 ++++++++++++++ host/lib/usrp/dboard/db_dbsrx.cpp | 7 +++++++ host/lib/usrp/dboard/db_rfx.cpp | 14 ++++++++++++++ host/lib/usrp/dboard/db_unknown.cpp | 14 ++++++++++++++ host/lib/usrp/dboard/db_wbx.cpp | 14 ++++++++++++++ host/lib/usrp/dboard/db_xcvr2450.cpp | 14 ++++++++++++++ host/lib/usrp/dboard_manager.cpp | 12 +++++++++++- host/lib/usrp/misc_utils.cpp | 17 +++++++++++++++++ host/lib/usrp/subdev_spec.cpp | 4 ++++ 11 files changed, 115 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/include/uhd/usrp/subdev_props.hpp b/host/include/uhd/usrp/subdev_props.hpp index cd07cb7a8..8f096ffe4 100644 --- a/host/include/uhd/usrp/subdev_props.hpp +++ b/host/include/uhd/usrp/subdev_props.hpp @@ -53,6 +53,7 @@ namespace uhd{ namespace usrp{ SUBDEV_PROP_ANTENNA_NAMES = 'A', //ro, prop_names_t SUBDEV_PROP_LO_LOCKED = 'L', //ro, bool SUBDEV_PROP_CONNECTION = 'c', //ro, subdev_conn_t + SUBDEV_PROP_ENABLED = 'e', //rw, bool SUBDEV_PROP_USE_LO_OFFSET = 'l', //ro, bool SUBDEV_PROP_RSSI = 'R', //ro, float SUBDEV_PROP_BANDWIDTH = 'B' //rw, double diff --git a/host/include/uhd/usrp/subdev_spec.hpp b/host/include/uhd/usrp/subdev_spec.hpp index 2f32509b9..5de3bb3b8 100644 --- a/host/include/uhd/usrp/subdev_spec.hpp +++ b/host/include/uhd/usrp/subdev_spec.hpp @@ -19,6 +19,7 @@ #define INCLUDED_UHD_USRP_SUBDEV_SPEC_HPP #include +#include #include #include @@ -27,7 +28,7 @@ namespace uhd{ namespace usrp{ /*! * A subdevice specification (daughterboard, subdevice) name pairing. */ - struct UHD_API subdev_spec_pair_t{ + struct UHD_API subdev_spec_pair_t : boost::equality_comparable{ //! The daughterboard name std::string db_name; @@ -45,6 +46,9 @@ namespace uhd{ namespace usrp{ ); }; + //! overloaded comparison operator for subdev_spec_pair_t + UHD_API bool operator==(const subdev_spec_pair_t &, const subdev_spec_pair_t &); + /*! * A list of (daughterboard name, subdevice name) pairs: * diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 4b0d8bf27..41f6f8002 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -149,6 +149,10 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ val = sd_name_to_conn[get_subdev_name()]; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -178,6 +182,9 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -241,6 +248,10 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ val = sd_name_to_conn[get_subdev_name()]; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -270,6 +281,9 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 81434f054..23cafea53 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -551,6 +551,10 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -587,6 +591,9 @@ void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_gain(val.as(), key.name); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + case SUBDEV_PROP_BANDWIDTH: this->set_bandwidth(val.as()); return; diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index c3ab96e59..cfc34381e 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -444,6 +444,10 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_QI; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -474,6 +478,9 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_rx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -524,6 +531,10 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = true; return; @@ -554,6 +565,9 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ this->set_tx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp index f6f4f4a61..ec7ab440b 100644 --- a/host/lib/usrp/dboard/db_unknown.cpp +++ b/host/lib/usrp/dboard/db_unknown.cpp @@ -122,6 +122,10 @@ void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -151,6 +155,9 @@ void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -211,6 +218,10 @@ void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -240,6 +251,9 @@ void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_FREQ: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index e473ce41e..907268aac 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -513,6 +513,10 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -543,6 +547,9 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_rx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -597,6 +604,10 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -627,6 +638,9 @@ void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ this->set_tx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + 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 798ff74a3..0ee133f3d 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -484,6 +484,10 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -518,6 +522,9 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_rx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -572,6 +579,10 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_QI; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -602,6 +613,9 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ this->set_tx_ant(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 181f843a0..78daa1b4d 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -86,7 +86,7 @@ std::string dboard_id_t::to_pp_string(void) const{ } /*********************************************************************** - * internal helper classe + * internal helper classes **********************************************************************/ /*! * A special wax proxy object that forwards calls to a subdev. @@ -330,4 +330,14 @@ void dboard_manager_impl::set_nice_dboard_if(void){ _iface->set_pin_ctrl(unit, 0x0000); //all gpio _iface->set_clock_enabled(unit, false); //clock off } + + //disable all rx subdevices + BOOST_FOREACH(const std::string &sd_name, this->get_rx_subdev_names()){ + this->get_rx_subdev(sd_name)[SUBDEV_PROP_ENABLED] = false; + } + + //disable all tx subdevices + BOOST_FOREACH(const std::string &sd_name, this->get_tx_subdev_names()){ + this->get_tx_subdev(sd_name)[SUBDEV_PROP_ENABLED] = false; + } } diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp index 5cfcdc8d3..05308baba 100644 --- a/host/lib/usrp/misc_utils.cpp +++ b/host/lib/usrp/misc_utils.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -186,6 +187,22 @@ static void verify_xx_subdev_spec( "Validate %s subdev spec failed: %s\n %s" ) % xx_type % subdev_spec.to_string() % e.what())); } + + //now use the subdev spec to enable the subdevices in use and vice-versa + BOOST_FOREACH(const std::string &db_name, mboard[dboard_names_prop].as()){ + wax::obj dboard = mboard[named_prop_t(dboard_prop, db_name)]; + BOOST_FOREACH(const std::string &sd_name, dboard[DBOARD_PROP_SUBDEV_NAMES].as()){ + try{ + bool enable = std::has(subdev_spec, subdev_spec_pair_t(db_name, sd_name)); + dboard[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)][SUBDEV_PROP_ENABLED] = enable; + } + catch(const std::exception &e){ + throw std::runtime_error(str(boost::format( + "Cannot set enabled property on subdevice %s:%s\n %s" + ) % db_name % sd_name % e.what())); + } + } + } } void usrp::verify_rx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard){ diff --git a/host/lib/usrp/subdev_spec.cpp b/host/lib/usrp/subdev_spec.cpp index 7a3e72867..95d2cbb12 100644 --- a/host/lib/usrp/subdev_spec.cpp +++ b/host/lib/usrp/subdev_spec.cpp @@ -34,6 +34,10 @@ subdev_spec_pair_t::subdev_spec_pair_t( /* NOP */ } +bool usrp::operator==(const subdev_spec_pair_t &lhs, const subdev_spec_pair_t &rhs){ + return (lhs.db_name == rhs.db_name) and (lhs.sd_name == rhs.sd_name); +} + subdev_spec_t::subdev_spec_t(const std::string &markup){ BOOST_FOREACH(const std::string &pair, std::split_string(markup)){ if (pair == "") continue; -- cgit v1.2.3 From 046d8a9a5a5b0addb7e6c8bfde7973f3051d48b1 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Thu, 30 Sep 2010 11:57:40 -0700 Subject: TVRX: Fixed to properly calculate alias frequencies. --- host/lib/usrp/dboard/db_tvrx.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 6b71a3c6e..1cb74c5ae 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -372,12 +372,30 @@ void tvrx::set_freq(double freq) { _lo_freq = actual_lo_freq; //for rx props } +/*********************************************************************** + * Get the alias frequency of frequency freq when sampled at fs. + * \param freq the frequency of interest + * \param fs the sample rate + * \return the alias frequency + **********************************************************************/ + +static double get_alias(double freq, double fs) { + double alias; + freq = fmod(freq, fs); + if(freq >= (fs/2)) { + alias = fs - freq; + } else { + alias = freq; + } + return alias; +} + /*********************************************************************** * RX Get and Set **********************************************************************/ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ named_prop_t key = named_prop_t::extract(key_); - int codec_rate; + double codec_rate; //handle the get request conditioned on the key switch(key.as()){ @@ -410,9 +428,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ * or if it will fall within Nyquist. */ codec_rate = this->get_iface()->get_codec_rate(dboard_iface::UNIT_RX); - if(codec_rate/2 > tvrx_if_freq) val = _lo_freq; - //ok take a deep breath i am positive there is an easier way to get this number - else val = _lo_freq - tvrx_if_freq - (tvrx_if_freq-codec_rate)*int(tvrx_if_freq / (codec_rate/2)); + val = (_lo_freq - tvrx_if_freq) + get_alias(tvrx_if_freq, codec_rate); return; case SUBDEV_PROP_FREQ_RANGE: -- cgit v1.2.3 From 67e302ee255922c021ce2c12efdbbaad46a787dc Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Fri, 1 Oct 2010 11:07:11 -0700 Subject: TVRX: fixed antenna prop enumeration --- host/lib/usrp/dboard/db_tvrx.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 1cb74c5ae..41c52fbf5 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -58,7 +58,7 @@ static const bool tvrx_debug = false; static const freq_range_t tvrx_freq_range(50e6, 860e6); -static const std::string tvrx_antennas = std::string(""); //only got one +static const prop_names_t tvrx_antennas = list_of(""); //only got one static const uhd::dict tvrx_freq_ranges = map_list_of ("VHFLO", freq_range_t(50e6, 158e6)) @@ -436,7 +436,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_ANTENNA: - val = std::string(tvrx_antennas); + val = std::string(""); return; case SUBDEV_PROP_ANTENNA_NAMES: -- cgit v1.2.3 From 4c3b5212b1b91b30b44af72365448ea6af66c408 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 7 Oct 2010 12:37:42 -0700 Subject: tvrx: converted floats to doubles to avoid msvc warnings --- host/lib/usrp/dboard/db_tvrx.cpp | 110 +++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 55 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 41c52fbf5..33507acaa 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -66,25 +66,25 @@ static const uhd::dict tvrx_freq_ranges = map_list_of ("UHF" , freq_range_t(454e6, 860e6)) ; -static const boost::array vhflo_gains_db = +static const boost::array vhflo_gains_db = {{-6.00000, -6.00000, -6.00000, -4.00000, 0.00000, 5.00000, 10.00000, 17.40000, 26.30000, 36.00000, 43.00000, 48.00000, 49.50000, 50.10000, 50.30000, 50.30000, 50.30000}}; - -static const boost::array vhfhi_gains_db = + +static const boost::array vhfhi_gains_db = {{13.3000, -13.3000, -13.3000, -1.0000, 7.7000, 11.0000, 14.7000, 19.3000, 26.1000, 36.0000, 42.7000, 46.0000, 47.0000, 47.8000, 48.2000, 48.2000, 48.2000}}; - -static const boost::array uhf_gains_db = + +static const boost::array uhf_gains_db = {{-8.0000, -8.0000, -7.0000, 4.0000, 10.2000, 14.5000, 17.5000, 20.0000, 24.5000, 30.8000, 37.0000, 39.8000, 40.7000, 41.6000, 42.6000, 43.2000, 43.8000}}; - -static const boost::array tvrx_if_gains_db = + +static const boost::array tvrx_if_gains_db = {{-1.50000, -1.50000, -1.50000, -1.00000, 0.20000, 2.10000, 4.30000, 6.40000, 9.00000, 12.00000, 14.80000, 18.20000, 26.10000, 32.50000, 32.50000, @@ -96,32 +96,32 @@ static const boost::array tvrx_if_gains_db = //need dang near as many coefficients as to just map it like this and interp. //these numbers are culled from the 4937DI5 datasheet and are probably totally inaccurate //but if it's better than the old linear fit i'm happy -static const uhd::dict > tvrx_rf_gains_db = map_list_of +static const uhd::dict > tvrx_rf_gains_db = map_list_of ("VHFLO", vhflo_gains_db) ("VHFHI", vhfhi_gains_db) ("UHF" , uhf_gains_db) ; //sample voltages for the above points -static const boost::array tvrx_gains_volts = +static const boost::array tvrx_gains_volts = {{0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0}}; static uhd::dict get_tvrx_gain_ranges(void) { - float rfmax = 0.0, rfmin = FLT_MAX; + double rfmax = 0.0, rfmin = FLT_MAX; BOOST_FOREACH(const std::string range, tvrx_rf_gains_db.keys()) { - float my_max = tvrx_rf_gains_db[range].back(); //we're assuming it's monotonic - float my_min = tvrx_rf_gains_db[range].front(); //if it's not this is wrong wrong wrong + double my_max = tvrx_rf_gains_db[range].back(); //we're assuming it's monotonic + double my_min = tvrx_rf_gains_db[range].front(); //if it's not this is wrong wrong wrong if(my_max > rfmax) rfmax = my_max; if(my_min < rfmin) rfmin = my_min; } - - float ifmin = tvrx_if_gains_db.front(); - float ifmax = tvrx_if_gains_db.back(); - + + double ifmin = tvrx_if_gains_db.front(); + double ifmax = tvrx_if_gains_db.back(); + return map_list_of - ("RF", gain_range_t(rfmin, rfmax, (rfmax-rfmin)/4096.0)) - ("IF", gain_range_t(ifmin, ifmax, (ifmax-ifmin)/4096.0)) - ; + ("RF", gain_range_t(float(rfmin), float(rfmax), float((rfmax-rfmin)/4096.0))) + ("IF", gain_range_t(float(ifmin), float(ifmax), float((ifmax-ifmin)/4096.0))) + ; } static const double opamp_gain = 1.22; //onboard DAC opamp gain @@ -136,7 +136,7 @@ class tvrx : public rx_dboard_base{ public: tvrx(ctor_args_t args); ~tvrx(void); - + void rx_get(const wax::obj &key, wax::obj &val); void rx_set(const wax::obj &key, const wax::obj &val); @@ -198,11 +198,11 @@ tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){ } //send initial register settings if necessary - + //set default freq _lo_freq = tvrx_freq_range.min + tvrx_if_freq; //init _lo_freq to a sane default set_freq(tvrx_freq_range.min); - + //set default gains BOOST_FOREACH(const std::string &name, get_tvrx_gain_ranges().keys()){ set_gain(get_tvrx_gain_ranges()[name].min, name); @@ -238,33 +238,33 @@ static std::string get_band(double freq) { * \return a voltage to feed the TVRX analog gain */ -static float gain_interp(float gain, boost::array db_vector, boost::array volts_vector) { - float volts; - gain = std::clip(gain, db_vector.front(), db_vector.back()); //let's not get carried away here - +static double gain_interp(double gain, boost::array db_vector, boost::array volts_vector) { + double volts; + gain = std::clip(gain, db_vector.front(), db_vector.back()); //let's not get carried away here + boost::uint8_t gain_step = 0; //find which bin we're in for(size_t i = 0; i < db_vector.size()-1; i++) { if(gain >= db_vector[i] && gain <= db_vector[i+1]) gain_step = i; } - + //find the current slope for linear interpolation - float slope = (volts_vector[gain_step + 1] - volts_vector[gain_step]) + double slope = (volts_vector[gain_step + 1] - volts_vector[gain_step]) / (db_vector[gain_step + 1] - db_vector[gain_step]); - + //the problem here is that for gains approaching the maximum, the voltage slope becomes infinite //i.e., a small change in gain requires an infinite change in voltage //to cope, we limit the slope - - if(slope == std::numeric_limits::infinity()) + + if(slope == std::numeric_limits::infinity()) return volts_vector[gain_step]; //use the volts per dB slope to find the final interpolated voltage volts = volts_vector[gain_step] + (slope * (gain - db_vector[gain_step])); - + if(tvrx_debug) std::cout << "Gain interp: gain: " << gain << ", gain_step: " << int(gain_step) << ", slope: " << slope << ", volts: " << volts << std::endl; - + return volts; } @@ -283,17 +283,17 @@ static float rf_gain_to_voltage(float gain, double lo_freq){ std::string band = get_band(lo_freq + tvrx_if_freq); //this is the voltage at the TVRX gain input - float gain_volts = gain_interp(gain, tvrx_rf_gains_db[band], tvrx_gains_volts); + double gain_volts = gain_interp(gain, tvrx_rf_gains_db[band], tvrx_gains_volts); //this is the voltage at the USRP DAC output - float dac_volts = gain_volts / opamp_gain; - - dac_volts = std::clip(dac_volts, 0.0, 3.3); + double dac_volts = gain_volts / opamp_gain; + + dac_volts = std::clip(dac_volts, 0.0, 3.3); if (tvrx_debug) std::cerr << boost::format( "tvrx RF AGC gain: %f dB, dac_volts: %f V" ) % gain % dac_volts << std::endl; - return dac_volts; + return float(dac_volts); } /*! @@ -306,17 +306,17 @@ static float rf_gain_to_voltage(float gain, double lo_freq){ static float if_gain_to_voltage(float gain){ //clip the input gain = std::clip(gain, get_tvrx_gain_ranges()["IF"].min, get_tvrx_gain_ranges()["IF"].max); - - float gain_volts = gain_interp(gain, tvrx_if_gains_db, tvrx_gains_volts); - float dac_volts = gain_volts / opamp_gain; - - dac_volts = std::clip(dac_volts, 0.0, 3.3); + + double gain_volts = gain_interp(gain, tvrx_if_gains_db, tvrx_gains_volts); + double dac_volts = gain_volts / opamp_gain; + + dac_volts = std::clip(dac_volts, 0.0, 3.3); if (tvrx_debug) std::cerr << boost::format( "tvrx IF AGC gain: %f dB, dac_volts: %f V" ) % gain % dac_volts << std::endl; - return dac_volts; + return float(dac_volts); } void tvrx::set_gain(float gain, const std::string &name){ @@ -337,27 +337,27 @@ void tvrx::set_gain(float gain, const std::string &name){ */ void tvrx::set_freq(double freq) { - freq = std::clip(freq, tvrx_freq_range.min, tvrx_freq_range.max); + freq = std::clip(freq, tvrx_freq_range.min, tvrx_freq_range.max); std::string prev_band = get_band(_lo_freq - tvrx_if_freq); std::string new_band = get_band(freq); - + double target_lo_freq = freq + tvrx_if_freq; //the desired LO freq for high-side mixing double f_ref = reference_freq / double(reference_divider); //your tuning step size - + int divisor = int((target_lo_freq + (f_ref * 4.0)) / (f_ref * 8)); //the divisor we'll use double actual_lo_freq = (f_ref * 8 * divisor); //the LO freq we'll actually get - + if((divisor & ~0x7fff)) UHD_THROW_INVALID_CODE_PATH(); - + //now we update the registers _tuner_4937di5_regs.db1 = (divisor >> 8) & 0xff; _tuner_4937di5_regs.db2 = divisor & 0xff; - + if(new_band == "VHFLO") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_VHFLO; else if(new_band == "VHFHI") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_VHFHI; else if(new_band == "UHF") _tuner_4937di5_regs.bandsel = tuner_4937di5_regs_t::BANDSEL_UHF; else UHD_THROW_INVALID_CODE_PATH(); - + _tuner_4937di5_regs.power = tuner_4937di5_regs_t::POWER_OFF; update_regs(); @@ -365,10 +365,10 @@ void tvrx::set_freq(double freq) { //we do this because the gains are different for different band settings //not FAR off, but we do this to be consistent if(prev_band != new_band) set_gain(_gains["RF"], "RF"); - - if(tvrx_debug) + + if(tvrx_debug) std::cout << boost::format("set_freq: target LO: %f f_ref: %f divisor: %i actual LO: %f") % target_lo_freq % f_ref % divisor % actual_lo_freq << std::endl; - + _lo_freq = actual_lo_freq; //for rx props } @@ -422,7 +422,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_FREQ: - /* + /* * so here we have to do some magic. because the TVRX uses a relatively high IF, * we have to watch the sample rate to see if the IF will be aliased * or if it will fall within Nyquist. -- cgit v1.2.3 From 4b5792d2a5c6d101f602b5854fb2e7cfb3acf602 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 8 Oct 2010 14:00:56 -0700 Subject: tvrx: added enabled prop to set and get --- host/lib/usrp/dboard/db_tvrx.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 33507acaa..b1fc2ea76 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -447,6 +447,10 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ val = SUBDEV_CONN_COMPLEX_IQ; return; + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; @@ -467,10 +471,14 @@ void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_GAIN: this->set_gain(val.as(), key.name); return; + case SUBDEV_PROP_FREQ: this->set_freq(val.as()); return; + case SUBDEV_PROP_ENABLED: + return; //always enabled + default: UHD_THROW_PROP_SET_ERROR(); } } -- cgit v1.2.3 From 86d6bceb0d37197d0fd8ace19fdedc957c5dfb84 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Fri, 8 Oct 2010 17:03:27 -0700 Subject: Fixed Assertions to better document tuning failures --- host/lib/usrp/dboard/db_dbsrx.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 23cafea53..327cb5f75 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -277,15 +277,17 @@ void dbsrx::set_lo_freq(double target_freq){ } } - //Assert because we failed to find a suitable combination of ref_clock, R and N - UHD_ASSERT_THROW(ref_clock/(1 << m) < 1e6 or ref_clock/(1 << m) > 2.5e6); - UHD_ASSERT_THROW((pfd_freq < dbsrx_pfd_freq_range.min) or (pfd_freq > dbsrx_pfd_freq_range.max)); - UHD_ASSERT_THROW((N < 256) or (N > 32768)); done_loop: + //Assert because we failed to find a suitable combination of ref_clock, R and N + UHD_ASSERT_THROW(ref_clock < 27.0e6 and ref_clock > 0.0); + UHD_ASSERT_THROW(ref_clock/m > 1e6 and ref_clock/m < 2.5e6); + UHD_ASSERT_THROW((pfd_freq > dbsrx_pfd_freq_range.min) and (pfd_freq < dbsrx_pfd_freq_range.max)); + UHD_ASSERT_THROW((N > 256) and (N < 32768)); + if(dbsrx_debug) std::cerr << boost::format( - "DBSRX: choose ref_clock %f and m_divider %d" - ) % (this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX)) % m << std::endl; + "DBSRX: choose ref_clock (current: %f, new: %f) and m_divider %d" + ) % (this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX)) % ref_clock % m << std::endl; //if ref_clock or m divider changed, we need to update the filter settings if (ref_clock != this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX) or m != _max2118_write_regs.m_divider) update_filter_settings = true; -- cgit v1.2.3 From 8aac27fa3e427e0ff09c111127da162356d2bac5 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Fri, 8 Oct 2010 17:54:01 -0700 Subject: TVRX documentation and a bugfix in the cal table. Named the antenna "RX". --- host/docs/dboards.rst | 9 +++++++++ host/lib/usrp/dboard/db_tvrx.cpp | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst index 738a0696d..4ad724c82 100644 --- a/host/docs/dboards.rst +++ b/host/docs/dboards.rst @@ -107,6 +107,15 @@ Transmit Gains: **PGA0**, Range: 0-25dB Recieve Gains: **PGA0**, Range: 0-31.5dB +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +TVRX +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Receive Antennas: RX + +Receive Gains: + * **RF**, Range: -13.3-50.3dB (frequency-dependent) + * **IF**, Range: -1.5-32.5dB + ------------------------------------------------------------------------ Daughterboard Modifications ------------------------------------------------------------------------ diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index b1fc2ea76..10be8d1c3 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -58,7 +58,7 @@ static const bool tvrx_debug = false; static const freq_range_t tvrx_freq_range(50e6, 860e6); -static const prop_names_t tvrx_antennas = list_of(""); //only got one +static const prop_names_t tvrx_antennas = list_of("RX"); static const uhd::dict tvrx_freq_ranges = map_list_of ("VHFLO", freq_range_t(50e6, 158e6)) @@ -73,7 +73,7 @@ static const boost::array vhflo_gains_db = 50.30000, 50.30000}}; static const boost::array vhfhi_gains_db = - {{13.3000, -13.3000, -13.3000, -1.0000, 7.7000, + {{-13.3000, -13.3000, -13.3000, -1.0000, 7.7000, 11.0000, 14.7000, 19.3000, 26.1000, 36.0000, 42.7000, 46.0000, 47.0000, 47.8000, 48.2000, 48.2000, 48.2000}}; @@ -436,7 +436,7 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_ANTENNA: - val = std::string(""); + val = tvrx_antennas.front(); //there's only one return; case SUBDEV_PROP_ANTENNA_NAMES: -- cgit v1.2.3 From 5898d378522905208bc49b2a4a30a5c04fba639b Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Mon, 11 Oct 2010 16:25:15 -0700 Subject: DBSRX: Fixed some ASSERT statements. --- host/lib/usrp/dboard/db_dbsrx.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 327cb5f75..99137dda3 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -239,7 +239,6 @@ void dbsrx::set_lo_freq(double target_freq){ double actual_freq=0.0, pfd_freq=0.0, ref_clock=0.0; int R=0, N=0, r=0, m=0; bool update_filter_settings = false; - //choose refclock std::vector clock_rates = this->get_iface()->get_clock_rates(dboard_iface::UNIT_RX); BOOST_FOREACH(ref_clock, std::reversed(std::sorted(clock_rates))){ @@ -251,7 +250,7 @@ void dbsrx::set_lo_freq(double target_freq){ if(dbsrx_debug) std::cerr << boost::format( "DBSRX: trying ref_clock %f and m_divider %d" - ) % (this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX)) % m << std::endl; + ) % (ref_clock) % m << std::endl; if (m >= 32) continue; @@ -280,10 +279,10 @@ void dbsrx::set_lo_freq(double target_freq){ done_loop: //Assert because we failed to find a suitable combination of ref_clock, R and N - UHD_ASSERT_THROW(ref_clock < 27.0e6 and ref_clock > 0.0); - UHD_ASSERT_THROW(ref_clock/m > 1e6 and ref_clock/m < 2.5e6); - UHD_ASSERT_THROW((pfd_freq > dbsrx_pfd_freq_range.min) and (pfd_freq < dbsrx_pfd_freq_range.max)); - UHD_ASSERT_THROW((N > 256) and (N < 32768)); + UHD_ASSERT_THROW(ref_clock <= 27.0e6 and ref_clock >= 0.0); + UHD_ASSERT_THROW(ref_clock/m >= 1e6 and ref_clock/m <= 2.5e6); + UHD_ASSERT_THROW((pfd_freq >= dbsrx_pfd_freq_range.min) and (pfd_freq <= dbsrx_pfd_freq_range.max)); + UHD_ASSERT_THROW((N >= 256) and (N <= 32768)); if(dbsrx_debug) std::cerr << boost::format( "DBSRX: choose ref_clock (current: %f, new: %f) and m_divider %d" @@ -351,7 +350,7 @@ void dbsrx::set_lo_freq(double target_freq){ "DBSRX: Tuning exceeded vco range, _max2118_write_regs.osc_band == %d\n" ) % int(_max2118_write_regs.osc_band)) ); - UHD_ASSERT_THROW(_max2118_read_regs.adc == 0); + UHD_ASSERT_THROW(_max2118_read_regs.adc != 0); //just to cause a throw } if (_max2118_write_regs.osc_band <= 0) break; _max2118_write_regs.osc_band -= 1; @@ -365,7 +364,7 @@ void dbsrx::set_lo_freq(double target_freq){ "DBSRX: Tuning exceeded vco range, _max2118_write_regs.osc_band == %d\n" ) % int(_max2118_write_regs.osc_band)) ); - UHD_ASSERT_THROW(_max2118_read_regs.adc == 0); + UHD_ASSERT_THROW(_max2118_read_regs.adc != 7); //just to cause a throw } if (_max2118_write_regs.osc_band >= 7) break; _max2118_write_regs.osc_band += 1; @@ -403,6 +402,7 @@ void dbsrx::set_lo_freq(double target_freq){ << boost::format(" Ref Freq=%fMHz\n") % (ref_clock/1e6) << boost::format(" Target Freq=%fMHz\n") % (target_freq/1e6) << boost::format(" Actual Freq=%fMHz\n") % (_lo_freq/1e6) + << boost::format(" VCO Freq=%fMHz\n") % (vco_freq/1e6) << std::endl; if (update_filter_settings) set_bandwidth(_bandwidth); -- cgit v1.2.3 From 8c0ca70d24f87ccc617ce79f2eedcc272a895204 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Tue, 12 Oct 2010 12:57:30 -0700 Subject: Enhance XCVR2450 to clip for high/low band tuning and add bandwidth property --- host/docs/dboards.rst | 11 ++- host/lib/usrp/dboard/db_xcvr2450.cpp | 147 ++++++++++++++++++++++++++++++++++- 2 files changed, 149 insertions(+), 9 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst index 4ad724c82..f3d7d95b0 100644 --- a/host/docs/dboards.rst +++ b/host/docs/dboards.rst @@ -69,21 +69,20 @@ Recieve Gains: **PGA0**, Range: 0-70dB (except RFX400 range is 0-45dB) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ XCVR 2450 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The XCVR2450 has a non-contiguous tuning range consisting of a high band and a low band. -The high band consists of frequencies between...TODO +The XCVR2450 has a non-contiguous tuning range consisting of a +high band (4.9-6.0GHz) and a low band (2.4-2.5GHz). Transmit Antennas: **J1** or **J2** Receive Antennas: **J1** or **J2** -When using the XCVR2450 in full-duplex mode, -the user must set the receive antenna and the transmit antenna to be different; -not doing so will yeild undefined results. - The XCVR2450 uses a common LO for both receive and transmit. Even though the API allows the RX and TX LOs to be individually set, a change of one LO setting will be reflected in the other LO setting. +The XCVR2450 does not support full-duplex mode, attempting to operate +in full-duplex will result in transmit-only operation. + Transmit Gains: * **VGA**, Range: 0-30dB * **BB**, Range: 0-5dB diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 0ee133f3d..314c85a69 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,7 @@ using namespace boost::assign; static const bool xcvr2450_debug = false; static const freq_range_t xcvr_freq_range(2.4e9, 6.0e9); +static const freq_range_t xcvr_freq_band_seperation(2.5e9, 4.9e9); static const prop_names_t xcvr_antennas = list_of("J1")("J2"); @@ -100,6 +102,7 @@ public: private: double _lo_freq; + float _rx_bandwidth, _tx_bandwidth; uhd::dict _tx_gains, _rx_gains; std::string _tx_ant, _rx_ant; int _ad9515div; @@ -110,6 +113,8 @@ private: void set_rx_ant(const std::string &ant); void set_tx_gain(float gain, const std::string &name); void set_rx_gain(float gain, const std::string &name); + void set_rx_bandwidth(float bandwidth); + void set_tx_bandwidth(float bandwidth); void update_atr(void); void spi_reset(void); @@ -176,6 +181,9 @@ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){ spi_reset(); //prepare the spi + _rx_bandwidth = 9.5e6; + _tx_bandwidth = 12.0e6; + //setup the misc max2829 registers _max2829_regs.mimo_select = max2829_regs_t::MIMO_SELECT_MIMO; _max2829_regs.band_sel_mimo = max2829_regs_t::BAND_SEL_MIMO_MIMO; @@ -183,7 +191,7 @@ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){ _max2829_regs.rssi_high_bw = max2829_regs_t::RSSI_HIGH_BW_6MHZ; _max2829_regs.tx_lpf_coarse_adj = max2829_regs_t::TX_LPF_COARSE_ADJ_12MHZ; _max2829_regs.rx_lpf_coarse_adj = max2829_regs_t::RX_LPF_COARSE_ADJ_9_5MHZ; - _max2829_regs.rx_lpf_fine_adj = max2829_regs_t::RX_LPF_FINE_ADJ_95; + _max2829_regs.rx_lpf_fine_adj = max2829_regs_t::RX_LPF_FINE_ADJ_100; _max2829_regs.rx_vga_gain_spi = max2829_regs_t::RX_VGA_GAIN_SPI_SPI; _max2829_regs.rssi_output_range = max2829_regs_t::RSSI_OUTPUT_RANGE_HIGH; _max2829_regs.rssi_op_mode = max2829_regs_t::RSSI_OP_MODE_ENABLED; @@ -244,15 +252,24 @@ void xcvr2450::update_atr(void){ this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, POWER_UP_RXIO | RX_DIS_RXIO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, POWER_UP_RXIO | RX_ENB_RXIO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, POWER_UP_RXIO | RX_DIS_RXIO); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP_RXIO | RX_ENB_RXIO); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP_RXIO | RX_DIS_RXIO); } /*********************************************************************** * Tuning **********************************************************************/ void xcvr2450::set_lo_freq(double target_freq){ + //clip for highband and lowband + if((target_freq > xcvr_freq_band_seperation.min) and (target_freq < xcvr_freq_band_seperation.max)){ + if(target_freq - xcvr_freq_band_seperation.min < xcvr_freq_band_seperation.max - target_freq){ + target_freq = xcvr_freq_band_seperation.min; + }else{ + target_freq = xcvr_freq_band_seperation.max; + } + } + + //clip for max and min target_freq = std::clip(target_freq, xcvr_freq_range.min, xcvr_freq_range.max); - //TODO: clip for highband and lowband //variables used in the calculation below double scaler = xcvr2450::is_highband(target_freq)? (4.0/5.0) : (4.0/3.0); @@ -434,6 +451,114 @@ void xcvr2450::set_rx_gain(float gain, const std::string &name){ _rx_gains[name] = gain; } + +/*********************************************************************** + * Bandwidth Handling + **********************************************************************/ +static max2829_regs_t::tx_lpf_coarse_adj_t bandwidth_to_tx_lpf_coarse_reg(float &bandwidth){ + int reg = std::clip(boost::math::iround((bandwidth-6.0e6)/6.0e6), 1, 3); + + switch(reg){ + case 1: // bandwidth < 15MHz + bandwidth = 12e6; + return max2829_regs_t::TX_LPF_COARSE_ADJ_12MHZ; + case 2: // 15MHz < bandwidth < 21MHz + bandwidth = 18e6; + return max2829_regs_t::TX_LPF_COARSE_ADJ_18MHZ; + case 3: // bandwidth > 21MHz + bandwidth = 24e6; + return max2829_regs_t::TX_LPF_COARSE_ADJ_24MHZ; + } + UHD_THROW_INVALID_CODE_PATH(); +} + +static max2829_regs_t::rx_lpf_fine_adj_t bandwidth_to_rx_lpf_fine_reg(float &bandwidth, float requested_bandwidth){ + int reg = std::clip(boost::math::iround((requested_bandwidth/bandwidth)/0.05), 18, 22); + + switch(reg){ + case 18: // requested_bandwidth < 92.5% + bandwidth = 0.9 * bandwidth; + return max2829_regs_t::RX_LPF_FINE_ADJ_90; + case 19: // 92.5% < requested_bandwidth < 97.5% + bandwidth = 0.95 * bandwidth; + return max2829_regs_t::RX_LPF_FINE_ADJ_95; + case 20: // 97.5% < requested_bandwidth < 102.5% + bandwidth = 1.0 * bandwidth; + return max2829_regs_t::RX_LPF_FINE_ADJ_100; + case 21: // 102.5% < requested_bandwidth < 107.5% + bandwidth = 1.05 * bandwidth; + return max2829_regs_t::RX_LPF_FINE_ADJ_105; + case 22: // 107.5% < requested_bandwidth + bandwidth = 1.1 * bandwidth; + return max2829_regs_t::RX_LPF_FINE_ADJ_110; + } + UHD_THROW_INVALID_CODE_PATH(); +} + +static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(float &bandwidth){ + int reg = std::clip(boost::math::iround((bandwidth-7.0e6)/1.0e6), 0, 11); + + switch(reg){ + case 0: // bandwidth < 7.5MHz + case 1: // 7.5MHz < bandwidth < 8.5MHz + bandwidth = 7.5e6; + return max2829_regs_t::RX_LPF_COARSE_ADJ_7_5MHZ; + case 2: // 8.5MHz < bandwidth < 9.5MHz + case 3: // 9.5MHz < bandwidth < 10.5MHz + case 4: // 10.5MHz < bandwidth < 11.5MHz + bandwidth = 9.5e6; + return max2829_regs_t::RX_LPF_COARSE_ADJ_9_5MHZ; + case 5: // 11.5MHz < bandwidth < 12.5MHz + case 6: // 12.5MHz < bandwidth < 13.5MHz + case 7: // 13.5MHz < bandwidth < 14.5MHz + case 8: // 14.5MHz < bandwidth < 15.5MHz + bandwidth = 14e6; + return max2829_regs_t::RX_LPF_COARSE_ADJ_14MHZ; + case 9: // 15.5MHz < bandwidth < 16.5MHz + case 10: // 16.5MHz < bandwidth < 17.5MHz + case 11: // 17.5MHz < bandwidth + bandwidth = 18e6; + return max2829_regs_t::RX_LPF_COARSE_ADJ_18MHZ; + } + UHD_THROW_INVALID_CODE_PATH(); +} + +void xcvr2450::set_rx_bandwidth(float bandwidth){ + float requested_bandwidth = bandwidth; + + //compute coarse low pass cutoff frequency setting + _max2829_regs.rx_lpf_coarse_adj = bandwidth_to_rx_lpf_coarse_reg(bandwidth); + + //compute fine low pass cutoff frequency setting + _max2829_regs.rx_lpf_fine_adj = bandwidth_to_rx_lpf_fine_reg(bandwidth, requested_bandwidth); + + //shadow bandwidth setting + _rx_bandwidth = bandwidth; + + //update register + send_reg(0x7); + + if (xcvr2450_debug) std::cerr << boost::format( + "XCVR2450 RX Bandwidth (lp_fc): %f Hz, coarse reg: %d, fine reg: %d" + ) % _rx_bandwidth % (int(_max2829_regs.rx_lpf_coarse_adj)) % (int(_max2829_regs.rx_lpf_fine_adj)) << std::endl; +} + +void xcvr2450::set_tx_bandwidth(float bandwidth){ + //compute coarse low pass cutoff frequency setting + _max2829_regs.tx_lpf_coarse_adj = bandwidth_to_tx_lpf_coarse_reg(bandwidth); + + //shadow bandwidth setting + _tx_bandwidth = bandwidth; + + //update register + send_reg(0x7); + + if (xcvr2450_debug) std::cerr << boost::format( + "XCVR2450 TX Bandwidth (lp_fc): %f Hz, coarse reg: %d" + ) % _tx_bandwidth % (int(_max2829_regs.tx_lpf_coarse_adj)) << std::endl; +} + + /*********************************************************************** * RX Get and Set **********************************************************************/ @@ -500,6 +625,10 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){ val = this->get_rssi(); return; + case SUBDEV_PROP_BANDWIDTH: + val = _rx_bandwidth; + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -522,6 +651,10 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_rx_ant(val.as()); return; + case SUBDEV_PROP_BANDWIDTH: + this->set_rx_bandwidth(val.as()); + return; + case SUBDEV_PROP_ENABLED: return; //always enabled @@ -591,6 +724,10 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){ val = this->get_locked(); return; + case SUBDEV_PROP_BANDWIDTH: + val = _tx_bandwidth; + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -609,6 +746,10 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ this->set_tx_gain(val.as(), key.name); return; + case SUBDEV_PROP_BANDWIDTH: + this->set_tx_bandwidth(val.as()); + return; + case SUBDEV_PROP_ANTENNA: this->set_tx_ant(val.as()); return; -- cgit v1.2.3 From 799d5059bae77a24267cfc33b33c4af1c0de8c5b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 19 Oct 2010 15:42:21 -0700 Subject: usrp: change the bandwidth param to a double (its a frequency), add set and gets for BW in the wrappers --- host/include/uhd/usrp/multi_usrp.hpp | 8 ++++++-- host/include/uhd/usrp/single_usrp.hpp | 8 ++++++-- host/lib/usrp/dboard/db_dbsrx.cpp | 18 ++++++------------ host/lib/usrp/dboard/db_xcvr2450.cpp | 20 ++++++++++---------- host/lib/usrp/multi_usrp.cpp | 20 ++++++++++++++++---- host/lib/usrp/single_usrp.cpp | 20 ++++++++++++++++---- 6 files changed, 60 insertions(+), 34 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 65c7e9044..dcec0c515 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -201,6 +201,9 @@ public: virtual bool get_rx_lo_locked(size_t chan) = 0; + virtual void set_rx_bandwidth(double bandwidth, size_t chan) = 0; + virtual double get_rx_bandwidth(size_t chan) = 0; + /*! * Read the RSSI value from a usrp device. * Or throw if the dboard does not support an RSSI readback. @@ -209,8 +212,6 @@ public: virtual float read_rssi(size_t chan) = 0; virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan) = 0; - - virtual void set_rx_bandwidth(float bandwidth, size_t chan) = 0; /******************************************************************* * TX methods @@ -251,6 +252,9 @@ public: virtual bool get_tx_lo_locked(size_t chan) = 0; + virtual void set_tx_bandwidth(double bandwidth, size_t chan) = 0; + virtual double get_tx_bandwidth(size_t chan) = 0; + virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan) = 0; }; diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp index 2266e7f2c..9b2fd7ccf 100644 --- a/host/include/uhd/usrp/single_usrp.hpp +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -144,6 +144,9 @@ public: virtual bool get_rx_lo_locked(size_t chan = 0) = 0; + virtual void set_rx_bandwidth(double bandwidth, size_t chan = 0) = 0; + virtual double get_rx_bandwidth(size_t chan = 0) = 0; + /*! * Read the RSSI value from a usrp device. * Or throw if the dboard does not support an RSSI readback. @@ -152,8 +155,6 @@ public: virtual float read_rssi(size_t chan = 0) = 0; virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan = 0) = 0; - - virtual void set_rx_bandwidth(float bandwidth, size_t chan = 0) = 0; /******************************************************************* * TX methods @@ -186,6 +187,9 @@ public: virtual bool get_tx_lo_locked(size_t chan = 0) = 0; + virtual void set_tx_bandwidth(double bandwidth, size_t chan = 0) = 0; + virtual double get_tx_bandwidth(size_t chan = 0) = 0; + virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan = 0) = 0; }; diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 99137dda3..939a79e58 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -69,7 +69,7 @@ public: private: double _lo_freq; - float _bandwidth; + double _bandwidth; uhd::dict _gains; max2118_write_regs_t _max2118_write_regs; max2118_read_regs_t _max2118_read_regs; @@ -79,7 +79,7 @@ private: void set_lo_freq(double target_freq); void set_gain(float gain, const std::string &name); - void set_bandwidth(float bandwidth); + void set_bandwidth(double bandwidth); void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ start_reg = boost::uint8_t(std::clip(int(start_reg), 0x0, 0x5)); @@ -482,9 +482,9 @@ void dbsrx::set_gain(float gain, const std::string &name){ /*********************************************************************** * Bandwidth Handling **********************************************************************/ -void dbsrx::set_bandwidth(float bandwidth){ +void dbsrx::set_bandwidth(double bandwidth){ //clip the input - bandwidth = std::clip(bandwidth, 4e6, 33e6); + bandwidth = std::clip(bandwidth, 4e6, 33e6); double ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX); @@ -494,7 +494,7 @@ void dbsrx::set_bandwidth(float bandwidth){ _max2118_write_regs.f_dac = std::clip(int((((bandwidth*_max2118_write_regs.m_divider)/ref_clock) - 4)/0.145),0,127); //determine actual bandwidth - _bandwidth = float((ref_clock/(_max2118_write_regs.m_divider))*(4+0.145*_max2118_write_regs.f_dac)); + _bandwidth = double((ref_clock/(_max2118_write_regs.m_divider))*(4+0.145*_max2118_write_regs.f_dac)); if (dbsrx_debug) std::cerr << boost::format( "DBSRX Filter Bandwidth: %f MHz, m: %d, f_dac: %d\n" @@ -565,12 +565,6 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){ val = this->get_locked(); return; -/* - case SUBDEV_PROP_RSSI: - val = this->get_rssi(); - return; -*/ - case SUBDEV_PROP_BANDWIDTH: val = _bandwidth; return; @@ -597,7 +591,7 @@ void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - this->set_bandwidth(val.as()); + this->set_bandwidth(val.as()); 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 314c85a69..99f2a231c 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -102,7 +102,7 @@ public: private: double _lo_freq; - float _rx_bandwidth, _tx_bandwidth; + double _rx_bandwidth, _tx_bandwidth; uhd::dict _tx_gains, _rx_gains; std::string _tx_ant, _rx_ant; int _ad9515div; @@ -113,8 +113,8 @@ private: void set_rx_ant(const std::string &ant); void set_tx_gain(float gain, const std::string &name); void set_rx_gain(float gain, const std::string &name); - void set_rx_bandwidth(float bandwidth); - void set_tx_bandwidth(float bandwidth); + void set_rx_bandwidth(double bandwidth); + void set_tx_bandwidth(double bandwidth); void update_atr(void); void spi_reset(void); @@ -455,7 +455,7 @@ void xcvr2450::set_rx_gain(float gain, const std::string &name){ /*********************************************************************** * Bandwidth Handling **********************************************************************/ -static max2829_regs_t::tx_lpf_coarse_adj_t bandwidth_to_tx_lpf_coarse_reg(float &bandwidth){ +static max2829_regs_t::tx_lpf_coarse_adj_t bandwidth_to_tx_lpf_coarse_reg(double &bandwidth){ int reg = std::clip(boost::math::iround((bandwidth-6.0e6)/6.0e6), 1, 3); switch(reg){ @@ -472,7 +472,7 @@ static max2829_regs_t::tx_lpf_coarse_adj_t bandwidth_to_tx_lpf_coarse_reg(float UHD_THROW_INVALID_CODE_PATH(); } -static max2829_regs_t::rx_lpf_fine_adj_t bandwidth_to_rx_lpf_fine_reg(float &bandwidth, float requested_bandwidth){ +static max2829_regs_t::rx_lpf_fine_adj_t bandwidth_to_rx_lpf_fine_reg(double &bandwidth, double requested_bandwidth){ int reg = std::clip(boost::math::iround((requested_bandwidth/bandwidth)/0.05), 18, 22); switch(reg){ @@ -495,7 +495,7 @@ static max2829_regs_t::rx_lpf_fine_adj_t bandwidth_to_rx_lpf_fine_reg(float &ban UHD_THROW_INVALID_CODE_PATH(); } -static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(float &bandwidth){ +static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(double &bandwidth){ int reg = std::clip(boost::math::iround((bandwidth-7.0e6)/1.0e6), 0, 11); switch(reg){ @@ -523,7 +523,7 @@ static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(float UHD_THROW_INVALID_CODE_PATH(); } -void xcvr2450::set_rx_bandwidth(float bandwidth){ +void xcvr2450::set_rx_bandwidth(double bandwidth){ float requested_bandwidth = bandwidth; //compute coarse low pass cutoff frequency setting @@ -543,7 +543,7 @@ void xcvr2450::set_rx_bandwidth(float bandwidth){ ) % _rx_bandwidth % (int(_max2829_regs.rx_lpf_coarse_adj)) % (int(_max2829_regs.rx_lpf_fine_adj)) << std::endl; } -void xcvr2450::set_tx_bandwidth(float bandwidth){ +void xcvr2450::set_tx_bandwidth(double bandwidth){ //compute coarse low pass cutoff frequency setting _max2829_regs.tx_lpf_coarse_adj = bandwidth_to_tx_lpf_coarse_reg(bandwidth); @@ -652,7 +652,7 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - this->set_rx_bandwidth(val.as()); + this->set_rx_bandwidth(val.as()); return; case SUBDEV_PROP_ENABLED: @@ -747,7 +747,7 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - this->set_tx_bandwidth(val.as()); + this->set_tx_bandwidth(val.as()); return; case SUBDEV_PROP_ANTENNA: diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 6df3afbf8..027530f31 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -256,6 +256,14 @@ public: return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); } + void set_rx_bandwidth(double bandwidth, size_t chan){ + _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + double get_rx_bandwidth(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as(); + } + float read_rssi(size_t chan){ return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); } @@ -263,10 +271,6 @@ public: dboard_iface::sptr get_rx_dboard_iface(size_t chan){ return _rx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); } - - void set_rx_bandwidth(float bandwidth, size_t chan) { - _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; - } /******************************************************************* * TX methods @@ -352,6 +356,14 @@ public: return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); } + void set_tx_bandwidth(double bandwidth, size_t chan){ + _tx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + double get_tx_bandwidth(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as(); + } + dboard_iface::sptr get_tx_dboard_iface(size_t chan){ return _tx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); } diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp index 7a4df3eb5..2faa1280c 100644 --- a/host/lib/usrp/single_usrp.cpp +++ b/host/lib/usrp/single_usrp.cpp @@ -192,6 +192,14 @@ public: return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); } + void set_rx_bandwidth(double bandwidth, size_t chan){ + _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + double get_rx_bandwidth(size_t chan){ + return _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as(); + } + float read_rssi(size_t chan){ return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); } @@ -199,10 +207,6 @@ public: dboard_iface::sptr get_rx_dboard_iface(size_t chan){ return _rx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); } - - void set_rx_bandwidth(float bandwidth, size_t chan) { - _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; - } /******************************************************************* * TX methods @@ -276,6 +280,14 @@ public: return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); } + void set_tx_bandwidth(double bandwidth, size_t chan){ + _tx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; + } + + double get_tx_bandwidth(size_t chan){ + return _tx_subdev(chan)[SUBDEV_PROP_BANDWIDTH].as(); + } + dboard_iface::sptr get_tx_dboard_iface(size_t chan){ return _tx_dboard(chan)[DBOARD_PROP_DBOARD_IFACE].as(); } -- cgit v1.2.3 From b405abf883a5b37de1468cde679644927d89abce Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 19 Oct 2010 17:13:56 -0700 Subject: uhd: remove some warnings in MSVC and with typo in xcvr2450 --- host/include/uhd/config.hpp | 5 +++-- host/lib/usrp/dboard/db_xcvr2450.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp index dacd3a96b..2918c2340 100644 --- a/host/include/uhd/config.hpp +++ b/host/include/uhd/config.hpp @@ -31,11 +31,12 @@ # pragma warning(disable: 4251) // class 'A' needs to have dll-interface to be used by clients of class 'B' //# pragma warning(disable: 4127) // conditional expression is constant //# pragma warning(disable: 4290) // C++ exception specification ignored except to ... -# pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored +//# pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored # pragma warning(disable: 4275) // non dll-interface class ... used as base for dll-interface class ... //# pragma warning(disable: 4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data //# pragma warning(disable: 4511) // 'class' : copy constructor could not be generated -# pragma warning(disable: 4250) // 'class' : inherits 'method' via dominance +//# pragma warning(disable: 4250) // 'class' : inherits 'method' via dominance +# pragma warning(disable: 4200) // nonstandard extension used : zero-sized array in struct/union #endif // define logical operators diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 99f2a231c..fb1367113 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -524,7 +524,7 @@ static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(double } void xcvr2450::set_rx_bandwidth(double bandwidth){ - float requested_bandwidth = bandwidth; + double requested_bandwidth = bandwidth; //compute coarse low pass cutoff frequency setting _max2829_regs.rx_lpf_coarse_adj = bandwidth_to_rx_lpf_coarse_reg(bandwidth); -- cgit v1.2.3 From d96b2e7587962c43c1db895b3340f9d868cbd704 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 20 Oct 2010 17:41:59 -0700 Subject: usrp: use the dboard id to prefix the subdev gain group names --- host/include/uhd/usrp/dboard_id.hpp | 6 ++++++ host/include/uhd/usrp/misc_utils.hpp | 3 +++ host/lib/usrp/dboard/db_dbsrx.cpp | 9 ++------- host/lib/usrp/dboard/db_rfx.cpp | 12 ++++++------ host/lib/usrp/dboard/db_tvrx.cpp | 2 +- host/lib/usrp/dboard_manager.cpp | 11 ++++++----- host/lib/usrp/misc_utils.cpp | 7 +++++-- host/lib/usrp/usrp1/codec_impl.cpp | 24 +++++++++++++----------- host/lib/usrp/usrp1/dboard_impl.cpp | 2 ++ host/lib/usrp/usrp2/dboard_impl.cpp | 2 ++ 10 files changed, 46 insertions(+), 32 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp index 4c45e4334..1fda8182e 100644 --- a/host/include/uhd/usrp/dboard_id.hpp +++ b/host/include/uhd/usrp/dboard_id.hpp @@ -66,6 +66,12 @@ namespace uhd{ namespace usrp{ */ std::string to_string(void) const; + /*! + * Get the dboard id represented as a canonical name. + * \return the canonical string representation + */ + std::string to_cname(void) const; + /*! * Get the pretty print representation of this dboard id. * \return a string with the dboard name and id number diff --git a/host/include/uhd/usrp/misc_utils.hpp b/host/include/uhd/usrp/misc_utils.hpp index 2af9f5b40..37860a1a5 100644 --- a/host/include/uhd/usrp/misc_utils.hpp +++ b/host/include/uhd/usrp/misc_utils.hpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -35,11 +36,13 @@ namespace uhd{ namespace usrp{ /*! * Create a gain group that represents the subdevice and its codec. + * \param dboard_id the dboard id for this subdevice * \param subdev the object with subdevice properties * \param codec the object with codec properties * \param gain_group_policy the policy to use */ UHD_API gain_group::sptr make_gain_group( + const dboard_id_t &dboard_id, wax::obj subdev, wax::obj codec, gain_group_policy_t gain_group_policy ); diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 939a79e58..0b8b4db83 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -162,15 +162,10 @@ static dboard_base::sptr make_dbsrx(dboard_base::ctor_args_t args){ return dboard_base::sptr(new dbsrx(args)); } -//dbid for USRP2 version UHD_STATIC_BLOCK(reg_dbsrx_dboard){ - //register the factory function for the rx dbid + //register the factory function for the rx dbid (others version) dboard_manager::register_dboard(0x000D, &make_dbsrx, "DBSRX"); -} - -//dbid for USRP1 version -UHD_STATIC_BLOCK(reg_dbsrx_on_usrp1_dboard){ - //register the factory function for the rx dbid + //register the factory function for the rx dbid (USRP1 version) dboard_manager::register_dboard(0x0002, &make_dbsrx, "DBSRX"); } diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index cfc34381e..3c24d90db 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -152,12 +152,12 @@ static dboard_base::sptr make_rfx_flex2400(dboard_base::ctor_args_t args){ } UHD_STATIC_BLOCK(reg_rfx_dboards){ - dboard_manager::register_dboard(0x0024, 0x0028, &make_rfx_flex400, "Flex 400 MIMO B"); - dboard_manager::register_dboard(0x0025, 0x0029, &make_rfx_flex900, "Flex 900 MIMO B"); - dboard_manager::register_dboard(0x0034, 0x0035, &make_rfx_flex1800, "Flex 1800 MIMO B"); - dboard_manager::register_dboard(0x0026, 0x002a, &make_rfx_flex1200, "Flex 1200 MIMO B"); - dboard_manager::register_dboard(0x002c, 0x002d, &make_rfx_flex2200, "Flex 2200 MIMO B"); - dboard_manager::register_dboard(0x0027, 0x002b, &make_rfx_flex2400, "Flex 2400 MIMO B"); + dboard_manager::register_dboard(0x0024, 0x0028, &make_rfx_flex400, "RFX400"); + dboard_manager::register_dboard(0x0025, 0x0029, &make_rfx_flex900, "RFX900"); + dboard_manager::register_dboard(0x0034, 0x0035, &make_rfx_flex1800, "RFX1800"); + dboard_manager::register_dboard(0x0026, 0x002a, &make_rfx_flex1200, "RFX1200"); + dboard_manager::register_dboard(0x002c, 0x002d, &make_rfx_flex2200, "RFX2200"); + dboard_manager::register_dboard(0x0027, 0x002b, &make_rfx_flex2400, "RFX2400"); } /*********************************************************************** diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 10be8d1c3..d39dc3bf8 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -179,7 +179,7 @@ static dboard_base::sptr make_tvrx(dboard_base::ctor_args_t args){ UHD_STATIC_BLOCK(reg_tvrx_dboard){ //register the factory function for the rx dbid - dboard_manager::register_dboard(0x0040, &make_tvrx, "tvrx"); + dboard_manager::register_dboard(0x0040, &make_tvrx, "TVRX"); } /*********************************************************************** diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 78daa1b4d..d7e7943c4 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -77,12 +77,13 @@ void dboard_manager::register_dboard( get_xcvr_id_to_id_map()[tx_dboard_id] = rx_dboard_id; } +std::string dboard_id_t::to_cname(void) const{ + if (not get_id_to_args_map().has_key(*this)) return "Unknown"; + return get_id_to_args_map()[*this].get<1>(); +} + 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()); + return str(boost::format("%s (%s)") % this->to_cname() % this->to_string()); } /*********************************************************************** diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp index 499a6ebfb..e95af45bd 100644 --- a/host/lib/usrp/misc_utils.cpp +++ b/host/lib/usrp/misc_utils.cpp @@ -80,6 +80,7 @@ static void set_subdev_gain(wax::obj subdev, const std::string &name, float gain * gain group factory function for usrp **********************************************************************/ gain_group::sptr usrp::make_gain_group( + const dboard_id_t &dboard_id, wax::obj subdev, wax::obj codec, gain_group_policy_t gain_group_policy ){ @@ -87,6 +88,8 @@ gain_group::sptr usrp::make_gain_group( const size_t codec_gain_priority = (gain_group_policy == GAIN_GROUP_POLICY_RX)? (subdev_gain_priority - 1): //RX policy, codec gains fill last (lower priority) (subdev_gain_priority + 1); //TX policy, codec gains fill first (higher priority) + const std::string subdev_prefix = dboard_id.to_cname() + " "; + const std::string codec_prefix = (gain_group_policy == GAIN_GROUP_POLICY_RX)? "ADC " : "DAC "; gain_group::sptr gg = gain_group::make(); gain_fcns_t fcns; @@ -95,7 +98,7 @@ gain_group::sptr usrp::make_gain_group( fcns.get_range = boost::bind(&get_subdev_gain_range, subdev, name); fcns.get_value = boost::bind(&get_subdev_gain, subdev, name); fcns.set_value = boost::bind(&set_subdev_gain, subdev, name, _1); - gg->register_fcns(name, fcns, subdev_gain_priority); + gg->register_fcns(subdev_prefix+name, fcns, subdev_gain_priority); } //add all the codec gains last (antenna to dsp order) BOOST_FOREACH(const std::string &name, codec[CODEC_PROP_GAIN_NAMES].as()){ @@ -119,7 +122,7 @@ gain_group::sptr usrp::make_gain_group( fcns.set_value = boost::bind(&set_codec_gain_q, codec, name, _1); break; } - gg->register_fcns(name, fcns, codec_gain_priority); + gg->register_fcns(codec_prefix+name, fcns, codec_gain_priority); } return gg; } diff --git a/host/lib/usrp/usrp1/codec_impl.cpp b/host/lib/usrp/usrp1/codec_impl.cpp index 1756c1ed4..db53be53e 100644 --- a/host/lib/usrp/usrp1/codec_impl.cpp +++ b/host/lib/usrp/usrp1/codec_impl.cpp @@ -45,7 +45,7 @@ void usrp1_impl::codec_init(void) /*********************************************************************** * RX Codec Properties **********************************************************************/ -static const std::string ad9862_pga_gain_name = "ad9862 pga"; +static const std::string adc_pga_gain_name = "PGA"; void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot) { @@ -62,21 +62,21 @@ void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t return; case CODEC_PROP_GAIN_NAMES: - val = prop_names_t(1, ad9862_pga_gain_name); + val = prop_names_t(1, adc_pga_gain_name); return; case CODEC_PROP_GAIN_RANGE: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); val = usrp1_codec_ctrl::rx_pga_gain_range; return; case CODEC_PROP_GAIN_I: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); val = _codec_ctrls[dboard_slot]->get_rx_pga_gain('A'); return; case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); val = _codec_ctrls[dboard_slot]->get_rx_pga_gain('B'); return; @@ -91,12 +91,12 @@ void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_ //handle the set request conditioned on the key switch(key.as()) { case CODEC_PROP_GAIN_I: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as(), 'A'); return; case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == adc_pga_gain_name); _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as(), 'B'); return; @@ -107,6 +107,8 @@ void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_ /*********************************************************************** * TX Codec Properties **********************************************************************/ +static const std::string dac_pga_gain_name = "PGA"; + void usrp1_impl::tx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot) { named_prop_t key = named_prop_t::extract(key_); @@ -122,17 +124,17 @@ void usrp1_impl::tx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t return; case CODEC_PROP_GAIN_NAMES: - val = prop_names_t(1, ad9862_pga_gain_name); + val = prop_names_t(1, dac_pga_gain_name); return; case CODEC_PROP_GAIN_RANGE: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == dac_pga_gain_name); val = usrp1_codec_ctrl::tx_pga_gain_range; return; case CODEC_PROP_GAIN_I: //only one gain for I and Q case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == dac_pga_gain_name); val = _codec_ctrls[dboard_slot]->get_tx_pga_gain(); return; @@ -148,7 +150,7 @@ void usrp1_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_ switch(key.as()){ case CODEC_PROP_GAIN_I: //only one gain for I and Q case CODEC_PROP_GAIN_Q: - UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); + UHD_ASSERT_THROW(key.name == dac_pga_gain_name); _codec_ctrls[dboard_slot]->set_tx_pga_gain(val.as()); return; diff --git a/host/lib/usrp/usrp1/dboard_impl.cpp b/host/lib/usrp/usrp1/dboard_impl.cpp index 3a8480e1b..2a2762a82 100644 --- a/host/lib/usrp/usrp1/dboard_impl.cpp +++ b/host/lib/usrp/usrp1/dboard_impl.cpp @@ -124,6 +124,7 @@ void usrp1_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _rx_db_eeproms[dboard_slot].id, _dboard_managers[dboard_slot]->get_rx_subdev(key.name), _rx_codec_proxies[dboard_slot]->get_link(), GAIN_GROUP_POLICY_RX @@ -188,6 +189,7 @@ void usrp1_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _tx_db_eeproms[dboard_slot].id, _dboard_managers[dboard_slot]->get_tx_subdev(key.name), _tx_codec_proxies[dboard_slot]->get_link(), GAIN_GROUP_POLICY_TX diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index a462b93c2..540c9fefb 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -89,6 +89,7 @@ void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _rx_db_eeprom.id, _dboard_manager->get_rx_subdev(key.name), _rx_codec_proxy->get_link(), GAIN_GROUP_POLICY_RX @@ -145,6 +146,7 @@ void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ case DBOARD_PROP_GAIN_GROUP: val = make_gain_group( + _tx_db_eeprom.id, _dboard_manager->get_tx_subdev(key.name), _tx_codec_proxy->get_link(), GAIN_GROUP_POLICY_TX -- cgit v1.2.3 From 3974e544393bd5a720838cbf4790c532bca2aae4 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 22 Oct 2010 16:59:12 -0700 Subject: dbsrx: reject asymmetric clocks (odd divisors) --- host/lib/usrp/dboard/db_dbsrx.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 0b8b4db83..aecd7249d 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -236,8 +236,10 @@ void dbsrx::set_lo_freq(double target_freq){ bool update_filter_settings = false; //choose refclock std::vector clock_rates = this->get_iface()->get_clock_rates(dboard_iface::UNIT_RX); + const double max_clock_rate = std::sorted(clock_rates).back(); BOOST_FOREACH(ref_clock, std::reversed(std::sorted(clock_rates))){ if (ref_clock > 27.0e6) continue; + if (size_t(max_clock_rate/ref_clock)%2 == 1) continue; //reject asymmetric clocks (odd divisors) //choose m_divider such that filter tuning constraint is met m = 31; -- cgit v1.2.3 From bb82453a77c4bb8ff585fc498b300cd83bb62314 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Mon, 25 Oct 2010 15:42:08 -0700 Subject: Added bandwidth property to all daughterboards Updated existing bandwidth property to reflect double-sided bandwidth rather than lowpass bandwidth --- host/lib/usrp/dboard/db_basic_and_lf.cpp | 29 +++++++++++++++++++++++++++-- host/lib/usrp/dboard/db_dbsrx.cpp | 4 ++-- host/lib/usrp/dboard/db_rfx.cpp | 21 +++++++++++++++++++++ host/lib/usrp/dboard/db_tvrx.cpp | 10 ++++++++++ host/lib/usrp/dboard/db_unknown.cpp | 23 ++++++++++++++++++++++- host/lib/usrp/dboard/db_wbx.cpp | 21 +++++++++++++++++++++ host/lib/usrp/dboard/db_xcvr2450.cpp | 8 ++++---- 7 files changed, 107 insertions(+), 9 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 41f6f8002..5a87f4ecf 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -68,11 +69,11 @@ static const uhd::dict sd_name_to_conn = map_list_of * Register the basic and LF dboards **********************************************************************/ static dboard_base::sptr make_basic_rx(dboard_base::ctor_args_t args){ - return dboard_base::sptr(new basic_rx(args, 90e9)); + return dboard_base::sptr(new basic_rx(args, 250e6)); } static dboard_base::sptr make_basic_tx(dboard_base::ctor_args_t args){ - return dboard_base::sptr(new basic_tx(args, 90e9)); + return dboard_base::sptr(new basic_tx(args, 250e6)); } static dboard_base::sptr make_lf_rx(dboard_base::ctor_args_t args){ @@ -161,6 +162,10 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ val = true; //there is no LO, so it must be true! return; + case SUBDEV_PROP_BANDWIDTH: + val = 2*_max_freq; //we want complex double-sided + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -185,6 +190,14 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("%s: No tunable bandwidth, fixed filtered to %0.2fMHz") + % get_rx_id().to_pp_string() % _max_freq + ) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -260,6 +273,10 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ val = true; //there is no LO, so it must be true! return; + case SUBDEV_PROP_BANDWIDTH: + val = 2*_max_freq; //we want complex double-sided + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -284,6 +301,14 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("%s: No tunable bandwidth, fixed filtered to %0.2fMHz") + % get_tx_id().to_pp_string() % _max_freq + ) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index aecd7249d..10e7f292b 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -563,7 +563,7 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - val = _bandwidth; + val = 2*_bandwidth; //_bandwidth is low-pass, we want complex double-sided return; default: UHD_THROW_PROP_GET_ERROR(); @@ -588,7 +588,7 @@ void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - this->set_bandwidth(val.as()); + this->set_bandwidth(val.as()/2.0); //complex double-sided, we want low-pass return; default: UHD_THROW_PROP_SET_ERROR(); diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 3c24d90db..0eeb0bfdf 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -456,6 +457,10 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ val = this->get_locked(dboard_iface::UNIT_RX); return; + case SUBDEV_PROP_BANDWIDTH: + val = 2*20.0e6; //30MHz low-pass, we want complex double-sided + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -481,6 +486,12 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("RFX: No tunable bandwidth, fixed filtered to 40MHz")) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -543,6 +554,10 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ val = this->get_locked(dboard_iface::UNIT_TX); return; + case SUBDEV_PROP_BANDWIDTH: + val = 2*20.0e6; //30MHz low-pass, we want complex double-sided + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -568,6 +583,12 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("RFX: No tunable bandwidth, fixed filtered to 40MHz")) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index d39dc3bf8..c7aecf195 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -459,6 +459,10 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ val = true; return; + case SUBDEV_PROP_BANDWIDTH: + val = 6.0e6; //30MHz low-pass, we want complex double-sided + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -479,6 +483,12 @@ void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("TVRX: No tunable bandwidth, fixed filtered to 6MHz")) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp index ec7ab440b..11293a1ba 100644 --- a/host/lib/usrp/dboard/db_unknown.cpp +++ b/host/lib/usrp/dboard/db_unknown.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -134,6 +135,10 @@ void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){ val = true; //there is no LO, so it must be true! return; + case SUBDEV_PROP_BANDWIDTH: + val = 0.0; + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -158,12 +163,18 @@ void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz")) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } /*********************************************************************** - * Basic and LF TX dboard + * Unknown TX dboard **********************************************************************/ unknown_tx::unknown_tx(ctor_args_t args) : tx_dboard_base(args){ /* NOP */ @@ -230,6 +241,10 @@ void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){ val = true; //there is no LO, so it must be true! return; + case SUBDEV_PROP_BANDWIDTH: + val = 0.0; + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -254,6 +269,12 @@ void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz")) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index 907268aac..b07f179a3 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -71,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -525,6 +526,10 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ val = this->get_locked(dboard_iface::UNIT_RX); return; + case SUBDEV_PROP_BANDWIDTH: + val = 2*30.0e6; //20MHz low-pass, we want complex double-sided + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -550,6 +555,12 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("WBX: No tunable bandwidth, fixed filtered to 40MHz")) + ); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } @@ -616,6 +627,10 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ val = this->get_locked(dboard_iface::UNIT_TX); return; + case SUBDEV_PROP_BANDWIDTH: + val = 2*30.0e6; //20MHz low-pass, we want complex double-sided + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -641,6 +656,12 @@ void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; //always enabled + case SUBDEV_PROP_BANDWIDTH: + uhd::print_warning( + str(boost::format("WBX: No tunable bandwidth, fixed filtered to 40MHz")) + ); + 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 fb1367113..be0e42b92 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -626,7 +626,7 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - val = _rx_bandwidth; + val = 2*_rx_bandwidth; //_tx_bandwidth is low-pass, we want complex double-sided return; default: UHD_THROW_PROP_GET_ERROR(); @@ -652,7 +652,7 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - this->set_rx_bandwidth(val.as()); + this->set_rx_bandwidth(val.as()/2.0); //complex double-sided, we want low-pass return; case SUBDEV_PROP_ENABLED: @@ -725,7 +725,7 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - val = _tx_bandwidth; + val = 2*_tx_bandwidth; //_tx_bandwidth is low-pass, we want complex double-sided return; default: UHD_THROW_PROP_GET_ERROR(); @@ -747,7 +747,7 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ return; case SUBDEV_PROP_BANDWIDTH: - this->set_tx_bandwidth(val.as()); + this->set_tx_bandwidth(val.as()/2.0); //complex double-sided, we want low-pass return; case SUBDEV_PROP_ANTENNA: -- cgit v1.2.3 From cea3d05095202413be12cd4792ab9f781cbccef7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 26 Oct 2010 14:14:01 -0700 Subject: uhd: replaced print warning with a post warning call and registry renamed print warning calls in the implementation fixed issue with dict::pop so it now works even if the value is not comparable --- host/include/uhd/types/dict.hpp | 23 ++++++++---- host/include/uhd/types/tune_request.hpp | 2 +- host/include/uhd/usrp/mimo_usrp.hpp | 4 +-- host/include/uhd/usrp/simple_usrp.hpp | 2 +- host/include/uhd/utils/warning.hpp | 36 ++++++++++++++++--- host/lib/transport/udp_zero_copy_asio.cpp | 2 +- host/lib/usrp/dboard/db_basic_and_lf.cpp | 4 +-- host/lib/usrp/dboard/db_dbsrx.cpp | 8 ++--- host/lib/usrp/dboard/db_rfx.cpp | 4 +-- host/lib/usrp/dboard/db_tvrx.cpp | 2 +- host/lib/usrp/dboard/db_unknown.cpp | 4 +-- host/lib/usrp/dboard/db_wbx.cpp | 4 +-- host/lib/usrp/dboard_manager.cpp | 4 +-- host/lib/usrp/multi_usrp.cpp | 2 +- host/lib/usrp/usrp1/mboard_impl.cpp | 2 +- host/lib/usrp/usrp1/usrp1_impl.cpp | 2 +- host/lib/usrp/wrapper_utils.hpp | 4 +-- host/lib/utils/thread_priority.cpp | 2 +- host/lib/utils/warning.cpp | 59 ++++++++++++++++++++++++++++--- host/test/warning_test.cpp | 4 +-- 20 files changed, 131 insertions(+), 43 deletions(-) (limited to 'host/lib/usrp/dboard') diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp index de96ea768..3d0acf888 100644 --- a/host/include/uhd/types/dict.hpp +++ b/host/include/uhd/types/dict.hpp @@ -120,10 +120,7 @@ namespace uhd{ BOOST_FOREACH(const pair_t &p, _map){ if (p.first == key) return p.second; } - throw std::invalid_argument(str(boost::format( - "key \"%s\" not found in dict(%s, %s)" - ) % boost::lexical_cast(key) - % typeid(Key).name() % typeid(Val).name())); + throw key_not_found_in_dict(key); } /*! @@ -147,12 +144,24 @@ namespace uhd{ * \throw an exception when not found */ Val pop(const Key &key){ - Val val = (*this)[key]; - _map.remove(pair_t(key, val)); - return val; + typename std::list::iterator it; + for (it = _map.begin(); it != _map.end(); it++){ + if (it->first != key) continue; + Val val = it->second; + _map.erase(it); + return val; + } + throw key_not_found_in_dict(key); } private: + std::exception key_not_found_in_dict(const Key &key) const{ + return std::out_of_range(str(boost::format( + "key \"%s\" not found in dict(%s, %s)" + ) % boost::lexical_cast(key) + % typeid(Key).name() % typeid(Val).name())); + } + std::list _map; //private container }; diff --git a/host/include/uhd/types/tune_request.hpp b/host/include/uhd/types/tune_request.hpp index b05ab5cc7..942b93251 100644 --- a/host/include/uhd/types/tune_request.hpp +++ b/host/include/uhd/types/tune_request.hpp @@ -60,7 +60,7 @@ namespace uhd{ /*! * The target frequency of the overall chain in Hz. - * Use in conjunction with the automatic policies. + * Set this even if all policies are set to manual. */ double target_freq; diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index b5acf84e1..a2092f04f 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -298,7 +298,7 @@ public: time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); time_spec_t time_i = _mboard(chan)[MBOARD_PROP_TIME_NOW].as(); if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "Detected time deviation between board %d and board 0.\n" "Board 0 time is %f seconds.\n" "Board %d time is %f seconds.\n" @@ -512,7 +512,7 @@ namespace uhd{ namespace usrp{ * The Make Function **********************************************************************/ inline mimo_usrp::sptr mimo_usrp::make(const device_addr_t &dev_addr){ - uhd::print_warning( + uhd::warning::post( "The mimo USRP interface has been deprecated.\n" "Please switch to the multi USRP interface.\n" "#include \n" diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index 59fd9bb09..77416dbbd 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -374,7 +374,7 @@ namespace uhd{ namespace usrp{ * The Make Function **********************************************************************/ inline simple_usrp::sptr simple_usrp::make(const device_addr_t &dev_addr){ - uhd::print_warning( + uhd::warning::post( "The simple USRP interface has been deprecated.\n" "Please switch to the single USRP interface.\n" "#include \n" diff --git a/host/include/uhd/utils/warning.hpp b/host/include/uhd/utils/warning.hpp index 91d8400ab..a1e3f0d1e 100644 --- a/host/include/uhd/utils/warning.hpp +++ b/host/include/uhd/utils/warning.hpp @@ -19,16 +19,44 @@ #define INCLUDED_UHD_UTILS_WARNING_HPP #include +#include +#include #include -namespace uhd{ +namespace uhd{ namespace warning{ + + //! Callback function type for a message handler + typedef boost::function handler_t; /*! - * Print a formatted warning string to stderr. + * Post a warning message to all registered handlers. * \param msg the multiline warning message */ - UHD_API void print_warning(const std::string &msg); + UHD_API void post(const std::string &msg); + + /*! + * Register a new handler with this name. + * If the name was already registered for this name, + * the old registered handler will be replaced. + * \param name a unique name for this handler + * \param handler the callback handler function + */ + UHD_API void register_handler(const std::string &name, const handler_t &handler); + + /*! + * Unregister a handler for this name. + * \param name a unique name for a registered handler + * \return the handler that was registered + * \throw error when the name was not found in the registry + */ + UHD_API handler_t unregister_handler(const std::string &name); + + /*! + * Get a list of registered handler names. + * \return a vector of unique string names + */ + UHD_API const std::vector registry_names(void); -} //namespace uhd +}} //namespace uhd::warning #endif /* INCLUDED_UHD_UTILS_WARNING_HPP */ diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index d84aeefdd..ed29864e9 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -336,7 +336,7 @@ template static void resize_buff_helper( else std::cout << boost::format( "Current %s sock buff size: %d bytes" ) % name % actual_size << std::endl; - if (actual_size < target_size) uhd::print_warning(str(boost::format( + if (actual_size < target_size) uhd::warning::post(str(boost::format( "The %s buffer is smaller than the requested size.\n" "The minimum recommended buffer size is %d bytes.\n" "See the transport application notes on buffer resizing.\n%s" diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 5a87f4ecf..4c49b3bff 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -191,7 +191,7 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("%s: No tunable bandwidth, fixed filtered to %0.2fMHz") % get_rx_id().to_pp_string() % _max_freq ) @@ -302,7 +302,7 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("%s: No tunable bandwidth, fixed filtered to %0.2fMHz") % get_tx_id().to_pp_string() % _max_freq ) diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 10e7f292b..85251bdf9 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -175,7 +175,7 @@ UHD_STATIC_BLOCK(reg_dbsrx_dboard){ dbsrx::dbsrx(ctor_args_t args) : rx_dboard_base(args){ //warn user about incorrect DBID on USRP1, requires R193 populated if (this->get_iface()->get_special_props().soft_clock_divider and this->get_rx_id() == 0x000D) - uhd::print_warning( + uhd::warning::post( str(boost::format( "DBSRX: incorrect dbid\n" "Expected dbid 0x0002 and R193\n" @@ -186,7 +186,7 @@ dbsrx::dbsrx(ctor_args_t args) : rx_dboard_base(args){ //warn user about incorrect DBID on non-USRP1, requires R194 populated if (not this->get_iface()->get_special_props().soft_clock_divider and this->get_rx_id() == 0x0002) - uhd::print_warning( + uhd::warning::post( str(boost::format( "DBSRX: incorrect dbid\n" "Expected dbid 0x000D and R194\n" @@ -342,7 +342,7 @@ void dbsrx::set_lo_freq(double target_freq){ //vtune is too low, try lower frequency vco if (_max2118_read_regs.adc == 0){ if (_max2118_write_regs.osc_band == 0){ - uhd::print_warning( + uhd::warning::post( str(boost::format( "DBSRX: Tuning exceeded vco range, _max2118_write_regs.osc_band == %d\n" ) % int(_max2118_write_regs.osc_band)) @@ -356,7 +356,7 @@ void dbsrx::set_lo_freq(double target_freq){ //vtune is too high, try higher frequency vco if (_max2118_read_regs.adc == 7){ if (_max2118_write_regs.osc_band == 7){ - uhd::print_warning( + uhd::warning::post( str(boost::format( "DBSRX: Tuning exceeded vco range, _max2118_write_regs.osc_band == %d\n" ) % int(_max2118_write_regs.osc_band)) diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 0eeb0bfdf..12e458d8c 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -487,7 +487,7 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("RFX: No tunable bandwidth, fixed filtered to 40MHz")) ); return; @@ -584,7 +584,7 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("RFX: No tunable bandwidth, fixed filtered to 40MHz")) ); return; diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index c7aecf195..1f3c76556 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -484,7 +484,7 @@ void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("TVRX: No tunable bandwidth, fixed filtered to 6MHz")) ); return; diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp index 11293a1ba..a342471c4 100644 --- a/host/lib/usrp/dboard/db_unknown.cpp +++ b/host/lib/usrp/dboard/db_unknown.cpp @@ -164,7 +164,7 @@ void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz")) ); return; @@ -270,7 +270,7 @@ void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz")) ); return; diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index b07f179a3..647f1b975 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -556,7 +556,7 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("WBX: No tunable bandwidth, fixed filtered to 40MHz")) ); return; @@ -657,7 +657,7 @@ void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ return; //always enabled case SUBDEV_PROP_BANDWIDTH: - uhd::print_warning( + uhd::warning::post( str(boost::format("WBX: No tunable bandwidth, fixed filtered to 40MHz")) ); return; diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index d73a698ae..5a98bb8eb 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -189,7 +189,7 @@ static args_t get_dboard_args( //verify that there is a registered constructor for this id if (not get_id_to_args_map().has_key(dboard_id)){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "Unknown dboard ID: %s.\n" ) % dboard_id.to_pp_string())); return get_dboard_args(unit, dboard_id, true); @@ -217,7 +217,7 @@ dboard_manager_impl::dboard_manager_impl( //warn for invalid dboard id xcvr combinations if (rx_dboard_is_xcvr != this_dboard_is_xcvr or tx_dboard_is_xcvr != this_dboard_is_xcvr){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "Unknown transceiver board ID combination...\n" "RX dboard ID: %s\n" "TX dboard ID: %s\n" diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 8b82502ba..024a6152d 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -145,7 +145,7 @@ public: time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); time_spec_t time_i = _mboard(m)[MBOARD_PROP_TIME_NOW].as(); if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "Detected time deviation between board %d and board 0.\n" "Board 0 time is %f seconds.\n" "Board %d time is %f seconds.\n" diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index fe3774eb4..669b20efa 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -98,7 +98,7 @@ static boost::uint32_t calc_rx_mux( // for all quadrature sources: Z = 0 // for mixed sources: warning + Z = 0 int Z = (num_quads > 0)? 0 : 1; - if (num_quads != 0 and num_reals != 0) uhd::print_warning( + if (num_quads != 0 and num_reals != 0) uhd::warning::post( "Mixing real and quadrature rx subdevices is not supported.\n" "The Q input to the real source(s) will be non-zero.\n" ); diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 276ca86f6..314384e72 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -64,7 +64,7 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) ); } catch(...){ - uhd::print_warning( + uhd::warning::post( "Could not locate USRP1 firmware.\n" "Please install the images package.\n" ); diff --git a/host/lib/usrp/wrapper_utils.hpp b/host/lib/usrp/wrapper_utils.hpp index aee230fc0..6f9fdbfca 100644 --- a/host/lib/usrp/wrapper_utils.hpp +++ b/host/lib/usrp/wrapper_utils.hpp @@ -40,7 +40,7 @@ static inline void do_samp_rate_warning_message( ){ static const double max_allowed_error = 1.0; //Sps if (std::abs(target_rate - actual_rate) > max_allowed_error){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "The hardware does not support the requested %s sample rate:\n" "Target sample rate: %f MSps\n" "Actual sample rate: %f MSps\n" @@ -55,7 +55,7 @@ static inline void do_tune_freq_warning_message( ){ static const double max_allowed_error = 1.0; //Hz if (std::abs(target_freq - actual_freq) > max_allowed_error){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "The hardware does not support the requested %s frequency:\n" "Target frequency: %f MHz\n" "Actual frequency: %f MHz\n" diff --git a/host/lib/utils/thread_priority.cpp b/host/lib/utils/thread_priority.cpp index f09d1b1d6..40b74f655 100644 --- a/host/lib/utils/thread_priority.cpp +++ b/host/lib/utils/thread_priority.cpp @@ -26,7 +26,7 @@ bool uhd::set_thread_priority_safe(float priority, bool realtime){ set_thread_priority(priority, realtime); return true; }catch(const std::exception &e){ - uhd::print_warning(str(boost::format( + uhd::warning::post(str(boost::format( "%s\n" "Failed to set thread priority %d (%s):\n" "Performance may be negatively affected.\n" diff --git a/host/lib/utils/warning.cpp b/host/lib/utils/warning.cpp index 8a7d35a23..05be7ae4d 100644 --- a/host/lib/utils/warning.cpp +++ b/host/lib/utils/warning.cpp @@ -17,16 +17,67 @@ #include #include +#include +#include #include +#include +#include #include #include using namespace uhd; -void uhd::print_warning(const std::string &msg){ - //print the warning message - std::cerr << std::endl << "Warning:" << std::endl; +/*********************************************************************** + * Registry implementation + **********************************************************************/ +//create the registry for the handlers +typedef uhd::dict registry_t; +UHD_SINGLETON_FCN(registry_t, get_registry) + +//the default warning handler +static void stderr_warning(const std::string &msg){ + std::cerr << msg; +} + +//register a default handler +UHD_STATIC_BLOCK(warning_register_default){ + warning::register_handler("default", &stderr_warning); +} + +/*********************************************************************** + * Post + format + **********************************************************************/ +void warning::post(const std::string &msg){ + std::stringstream ss; + + //format the warning message + ss << std::endl << "Warning:" << std::endl; BOOST_FOREACH(const std::string &line, std::split_string(msg, "\n")){ - std::cerr << " " << line << std::endl; + ss << " " << line << std::endl; + } + + //post the formatted message + BOOST_FOREACH(const std::string &name, get_registry().keys()){ + get_registry()[name](ss.str()); } } + +/*********************************************************************** + * Registry accessor functions + **********************************************************************/ +void warning::register_handler( + const std::string &name, const handler_t &handler +){ + get_registry()[name] = handler; +} + +warning::handler_t warning::unregister_handler(const std::string &name){ + if (not get_registry().has_key(name)) throw std::runtime_error( + "The warning registry does not have a handler registered to " + name + ); + return get_registry().pop(name); +} + +const std::vector warning::registry_names(void){ + return get_registry().keys(); +} diff --git a/host/test/warning_test.cpp b/host/test/warning_test.cpp index 6202c4270..db19955de 100644 --- a/host/test/warning_test.cpp +++ b/host/test/warning_test.cpp @@ -19,9 +19,9 @@ #include #include -BOOST_AUTO_TEST_CASE(test_print_warning){ +BOOST_AUTO_TEST_CASE(test_warning_post){ std::cerr << "---begin print test ---" << std::endl; - uhd::print_warning( + uhd::warning::post( "This is a test print for a warning message.\n" "And this is the second line of the test print.\n" ); -- cgit v1.2.3