From 9cb9e7d52255d3e14e57867eee76b555f705954c Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Fri, 13 Aug 2010 16:20:41 -0700 Subject: usrp1: Add usrp1 implementation --- host/lib/usrp/usrp1/dsp_impl.cpp | 197 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 host/lib/usrp/usrp1/dsp_impl.cpp (limited to 'host/lib/usrp/usrp1/dsp_impl.cpp') diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp new file mode 100644 index 000000000..e9900131f --- /dev/null +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -0,0 +1,197 @@ +// +// 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 . +// + +#include "usrp1_impl.hpp" +#include "fpga_regs_standard.h" +#include "../dsp_utils.hpp" +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; + +/*********************************************************************** + * RX DDC Initialization + **********************************************************************/ +void usrp1_impl::rx_ddc_init(void) +{ + _rx_ddc_proxy = wax_obj_proxy::make( + boost::bind(&usrp1_impl::rx_ddc_get, this, _1, _2), + boost::bind(&usrp1_impl::rx_ddc_set, this, _1, _2)); + + rx_ddc_set(DSP_PROP_HOST_RATE, double(64e6/10)); +} + +/*********************************************************************** + * RX DDC Get + **********************************************************************/ +void usrp1_impl::rx_ddc_get(const wax::obj &key, wax::obj &val) +{ + switch(key.as()){ + case DSP_PROP_NAME: + val = std::string("usrp1 ddc0"); + return; + + case DSP_PROP_OTHERS: + val = prop_names_t(); + return; + + case DSP_PROP_FREQ_SHIFT: + val = _ddc_freq; + return; + + case DSP_PROP_CODEC_RATE: + val = _clock_ctrl->get_master_clock_freq(); + return; + + case DSP_PROP_HOST_RATE: + val = _clock_ctrl->get_master_clock_freq()/_ddc_decim; + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } + +} + +/*********************************************************************** + * RX DDC Set + **********************************************************************/ +unsigned int compute_freq_word(double master, double target) +{ + static const int NBITS = 14; + int v = (int) rint (target / master * pow(2.0, 32.0)); + + if (0) + v = (v >> (32 - NBITS)) << (32 - NBITS); // keep only top NBITS + + double actual_freq = v * master / pow(2.0, 32.0); + + if (0) + fprintf (stderr, + "compute_freq_control_word_fpga: target = %g actual = %g delta = %g\n", + target, actual_freq, actual_freq - target); + + return (unsigned int) v; +} + +void usrp1_impl::rx_ddc_set(const wax::obj &key, const wax::obj &val) +{ + switch(key.as()) { + case DSP_PROP_FREQ_SHIFT: { + double new_freq = val.as(); + _iface->poke32(FR_RX_FREQ_0, compute_freq_word(64e6, new_freq)); + _ddc_freq = new_freq; + return; + } + case DSP_PROP_HOST_RATE: { + //FIXME: Stop and resume streaming during set? + unsigned int rate = + _clock_ctrl->get_master_clock_freq() / val.as(); + + if ((rate & 0x01) || (rate < 4) || (rate > 256)) { + std::cerr << "Decimation must be even and between 4 and 256" + << std::endl; + return; + } + + _ddc_decim = rate; + _iface->poke32(FR_DECIM_RATE, _ddc_decim/2 - 1); + } + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } + +} + +/*********************************************************************** + * TX DUC Initialization + **********************************************************************/ +void usrp1_impl::tx_duc_init(void) +{ + _tx_duc_proxy = wax_obj_proxy::make( + boost::bind(&usrp1_impl::tx_duc_get, this, _1, _2), + boost::bind(&usrp1_impl::tx_duc_set, this, _1, _2)); + + //initial config and update + tx_duc_set(DSP_PROP_HOST_RATE, double(64e6/10)); +} + +/*********************************************************************** + * TX DUC Get + **********************************************************************/ +void usrp1_impl::tx_duc_get(const wax::obj &key, wax::obj &val) +{ + switch(key.as()) { + case DSP_PROP_NAME: + val = std::string("usrp1 duc0"); + return; + + case DSP_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case DSP_PROP_FREQ_SHIFT: + val = _duc_freq; + return; + + case DSP_PROP_CODEC_RATE: + val = MASTER_CLOCK_RATE; + return; + + case DSP_PROP_HOST_RATE: + val = _clock_ctrl->get_master_clock_freq() * 2 / _duc_interp; + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } + +} + +/*********************************************************************** + * TX DUC Set + **********************************************************************/ +void usrp1_impl::tx_duc_set(const wax::obj &key, const wax::obj &val) +{ + switch(key.as()) { + + case DSP_PROP_FREQ_SHIFT: { + double new_freq = val.as(); + _codec_ctrl->set_duc_freq(new_freq); + _duc_freq = new_freq; + return; + } + case DSP_PROP_HOST_RATE: { + unsigned int rate = + _clock_ctrl->get_master_clock_freq() * 2 / val.as(); + + if ((rate & 0x01) || (rate < 8) || (rate > 512)) { + std::cerr << "Interpolation rate must be even and between 8 and 512" + << std::endl; + return; + } + + _duc_interp = rate; + _iface->poke32(FR_INTERP_RATE, _duc_interp / 4 - 1); + return; + } + default: UHD_THROW_PROP_SET_ERROR(); + } + +} -- cgit v1.2.3 From 5c0d3d30606b25c72c98785d49c13cc27ad49ec1 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 15 Aug 2010 18:49:06 -0700 Subject: usrp1: created daughterboard duality everything that should have two is now stored into a dictionary of slot to type the set and get functions are now bound with a third argument for dboard slot the dboard iface has yet to be completed with the correct registers for a vs b --- host/lib/usrp/usrp1/codec_ctrl.cpp | 16 ++-- host/lib/usrp/usrp1/codec_ctrl.hpp | 3 +- host/lib/usrp/usrp1/codec_impl.cpp | 42 +++++----- host/lib/usrp/usrp1/dboard_iface.cpp | 28 +++++-- host/lib/usrp/usrp1/dboard_impl.cpp | 148 +++++++++++++++++++---------------- host/lib/usrp/usrp1/dsp_impl.cpp | 55 +++++++------ host/lib/usrp/usrp1/mboard_impl.cpp | 21 +++-- host/lib/usrp/usrp1/usrp1_impl.cpp | 13 ++- host/lib/usrp/usrp1/usrp1_impl.hpp | 103 +++++++++++++----------- 9 files changed, 246 insertions(+), 183 deletions(-) (limited to 'host/lib/usrp/usrp1/dsp_impl.cpp') diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp index d0576a769..01617de94 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.cpp +++ b/host/lib/usrp/usrp1/codec_ctrl.cpp @@ -17,8 +17,6 @@ #include "codec_ctrl.hpp" #include "usrp_commands.h" -#include "fpga_regs_standard.h" -#include "usrp_spi_defs.h" #include "ad9862_regs.hpp" #include #include @@ -45,7 +43,7 @@ const gain_range_t usrp1_codec_ctrl::rx_pga_gain_range(0, 20, 1); class usrp1_codec_ctrl_impl : public usrp1_codec_ctrl { public: //structors - usrp1_codec_ctrl_impl(usrp1_iface::sptr iface); + usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, int spi_slave); ~usrp1_codec_ctrl_impl(void); //aux adc and dac control @@ -63,6 +61,7 @@ public: private: usrp1_iface::sptr _iface; + int _spi_slave; ad9862_regs_t _ad9862_regs; aux_adc_t _last_aux_adc_a, _last_aux_adc_b; void send_reg(boost::uint8_t addr); @@ -78,9 +77,10 @@ private: /*********************************************************************** * Codec Control Structors **********************************************************************/ -usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface) +usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, int spi_slave) { _iface = iface; + _spi_slave = spi_slave; //soft reset _ad9862_regs.soft_reset = 1; @@ -295,7 +295,7 @@ void usrp1_codec_ctrl_impl::send_reg(boost::uint8_t addr) std::cout << "codec control write reg: 0x"; std::cout << std::setw(8) << std::hex << reg << std::endl; } - _iface->transact_spi(SPI_ENABLE_CODEC_A, + _iface->transact_spi(_spi_slave, spi_config_t::EDGE_RISE, reg, 16, false); } @@ -309,7 +309,7 @@ void usrp1_codec_ctrl_impl::recv_reg(boost::uint8_t addr) std::cout << std::setw(8) << std::hex << reg << std::endl; } - boost::uint32_t ret = _iface->transact_spi(SPI_ENABLE_CODEC_A, + boost::uint32_t ret = _iface->transact_spi(_spi_slave, spi_config_t::EDGE_RISE, reg, 16, true); if (codec_debug) { @@ -435,7 +435,7 @@ bool usrp1_codec_ctrl_impl::set_duc_freq(double freq) /*********************************************************************** * Codec Control Make **********************************************************************/ -usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface) +usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface, int spi_slave) { - return sptr(new usrp1_codec_ctrl_impl(iface)); + return sptr(new usrp1_codec_ctrl_impl(iface, spi_slave)); } diff --git a/host/lib/usrp/usrp1/codec_ctrl.hpp b/host/lib/usrp/usrp1/codec_ctrl.hpp index 0605e3228..6440f97d1 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.hpp +++ b/host/lib/usrp/usrp1/codec_ctrl.hpp @@ -38,9 +38,10 @@ public: /*! * Make a new clock control object. * \param iface the usrp1 iface object + * \param spi_slave which spi device * \return the clock control object */ - static sptr make(usrp1_iface::sptr iface); + static sptr make(usrp1_iface::sptr iface, int spi_slave); //! aux adc identifier constants enum aux_adc_t{ diff --git a/host/lib/usrp/usrp1/codec_impl.cpp b/host/lib/usrp/usrp1/codec_impl.cpp index 7bf5631fb..766a7948f 100644 --- a/host/lib/usrp/usrp1/codec_impl.cpp +++ b/host/lib/usrp/usrp1/codec_impl.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include using namespace uhd; using namespace uhd::usrp; @@ -29,13 +31,15 @@ using namespace uhd::usrp; void usrp1_impl::codec_init(void) { //make proxies - _rx_codec_proxy = wax_obj_proxy::make( - boost::bind(&usrp1_impl::rx_codec_get, this, _1, _2), - boost::bind(&usrp1_impl::rx_codec_set, this, _1, _2)); - - _tx_codec_proxy = wax_obj_proxy::make( - boost::bind(&usrp1_impl::tx_codec_get, this, _1, _2), - boost::bind(&usrp1_impl::tx_codec_set, this, _1, _2)); + BOOST_FOREACH(dboard_slot_t dboard_slot, _dboard_slots){ + _rx_codec_proxies[dboard_slot] = wax_obj_proxy::make( + boost::bind(&usrp1_impl::rx_codec_get, this, _1, _2, dboard_slot), + boost::bind(&usrp1_impl::rx_codec_set, this, _1, _2, dboard_slot)); + + _tx_codec_proxies[dboard_slot] = wax_obj_proxy::make( + boost::bind(&usrp1_impl::tx_codec_get, this, _1, _2, dboard_slot), + boost::bind(&usrp1_impl::tx_codec_set, this, _1, _2, dboard_slot)); + } } /*********************************************************************** @@ -43,14 +47,14 @@ void usrp1_impl::codec_init(void) **********************************************************************/ static const std::string ad9862_pga_gain_name = "ad9862 pga"; -void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val) +void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot) { named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()) { case CODEC_PROP_NAME: - val = std::string("usrp1 adc - ad9862"); + val = str(boost::format("usrp1 adc - ad9862 - slot %c") % dboard_slot); return; case CODEC_PROP_OTHERS: @@ -68,19 +72,19 @@ void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val) case CODEC_PROP_GAIN_I: UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - val = _codec_ctrl->get_rx_pga_gain('A'); + 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); - val = _codec_ctrl->get_rx_pga_gain('B'); + val = _codec_ctrls[dboard_slot]->get_rx_pga_gain('B'); return; default: UHD_THROW_PROP_GET_ERROR(); } } -void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val) +void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_slot_t dboard_slot) { named_prop_t key = named_prop_t::extract(key_); @@ -88,12 +92,12 @@ void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val) switch(key.as()) { case CODEC_PROP_GAIN_I: UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - _codec_ctrl->set_rx_pga_gain(val.as(), 'A'); + _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); - _codec_ctrl->set_rx_pga_gain(val.as(), 'B'); + _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as(), 'B'); return; default: UHD_THROW_PROP_SET_ERROR(); @@ -103,14 +107,14 @@ void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val) /*********************************************************************** * TX Codec Properties **********************************************************************/ -void usrp1_impl::tx_codec_get(const wax::obj &key_, wax::obj &val) +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_); //handle the get request conditioned on the key switch(key.as()) { case CODEC_PROP_NAME: - val = std::string("usrp1 dac - ad9862"); + val = str(boost::format("usrp1 dac - ad9862 - slot %c") % dboard_slot); return; case CODEC_PROP_OTHERS: @@ -129,14 +133,14 @@ void usrp1_impl::tx_codec_get(const wax::obj &key_, wax::obj &val) case CODEC_PROP_GAIN_I: //only one gain for I and Q case CODEC_PROP_GAIN_Q: UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - val = _codec_ctrl->get_tx_pga_gain(); + val = _codec_ctrls[dboard_slot]->get_tx_pga_gain(); return; default: UHD_THROW_PROP_GET_ERROR(); } } -void usrp1_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val) +void usrp1_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_slot_t dboard_slot) { named_prop_t key = named_prop_t::extract(key_); @@ -145,7 +149,7 @@ void usrp1_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val) case CODEC_PROP_GAIN_I: //only one gain for I and Q case CODEC_PROP_GAIN_Q: UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name); - _codec_ctrl->set_tx_pga_gain(val.as()); + _codec_ctrls[dboard_slot]->set_tx_pga_gain(val.as()); return; default: UHD_THROW_PROP_SET_ERROR(); diff --git a/host/lib/usrp/usrp1/dboard_iface.cpp b/host/lib/usrp/usrp1/dboard_iface.cpp index ef6a1e67b..82ef9e65b 100644 --- a/host/lib/usrp/usrp1/dboard_iface.cpp +++ b/host/lib/usrp/usrp1/dboard_iface.cpp @@ -16,6 +16,7 @@ // #include "usrp1_iface.hpp" +#include "usrp1_impl.hpp" #include "fpga_regs_common.h" #include "usrp_spi_defs.h" #include "clock_ctrl.hpp" @@ -30,16 +31,27 @@ using namespace uhd; using namespace uhd::usrp; using namespace boost::assign; +/*********************************************************************** + * TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + * TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + * TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + * TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + * + * check the _dboard_slot and handle conditionally... + **********************************************************************/ + class usrp1_dboard_iface : public dboard_iface { public: usrp1_dboard_iface(usrp1_iface::sptr iface, usrp1_clock_ctrl::sptr clock, - usrp1_codec_ctrl::sptr codec) - { + usrp1_codec_ctrl::sptr codec, + usrp1_impl::dboard_slot_t dboard_slot + ){ _iface = iface; _clock = clock; _codec = codec; + _dboard_slot = dboard_slot; //init the clock rate shadows this->set_clock_rate(UNIT_RX, _clock->get_master_clock_freq()); @@ -55,7 +67,7 @@ public: { special_props_t props; props.soft_clock_divider = true; - props.mangle_i2c_addrs = false; //TODO true on side B + props.mangle_i2c_addrs = (_dboard_slot == usrp1_impl::DBOARD_SLOT_B); return props; } @@ -91,16 +103,18 @@ private: usrp1_clock_ctrl::sptr _clock; usrp1_codec_ctrl::sptr _codec; uhd::dict _clock_rates; + usrp1_impl::dboard_slot_t _dboard_slot; }; /*********************************************************************** * Make Function **********************************************************************/ -dboard_iface::sptr make_usrp1_dboard_iface(usrp1_iface::sptr iface, +dboard_iface::sptr usrp1_impl::make_dboard_iface(usrp1_iface::sptr iface, usrp1_clock_ctrl::sptr clock, - usrp1_codec_ctrl::sptr codec) -{ - return dboard_iface::sptr(new usrp1_dboard_iface(iface, clock, codec)); + usrp1_codec_ctrl::sptr codec, + usrp1_impl::dboard_slot_t dboard_slot +){ + return dboard_iface::sptr(new usrp1_dboard_iface(iface, clock, codec, dboard_slot)); } /*********************************************************************** diff --git a/host/lib/usrp/usrp1/dboard_impl.cpp b/host/lib/usrp/usrp1/dboard_impl.cpp index 9df87432d..ba826d2f5 100644 --- a/host/lib/usrp/usrp1/dboard_impl.cpp +++ b/host/lib/usrp/usrp1/dboard_impl.cpp @@ -23,96 +23,107 @@ #include #include #include +#include +#include #include using namespace uhd; using namespace uhd::usrp; /*********************************************************************** - * Dboard Initialization + * Helper Functions **********************************************************************/ -void usrp1_impl::dboard_init(void) -{ - _rx_db_eeprom = dboard_eeprom_t( - _iface->read_eeprom(I2C_ADDR_RX_A, 0, dboard_eeprom_t::num_bytes())); - - _tx_db_eeprom = dboard_eeprom_t( - _iface->read_eeprom(I2C_ADDR_TX_A, 0, dboard_eeprom_t::num_bytes())); - - - //create a new dboard interface and manager - _dboard_iface = make_usrp1_dboard_iface(_iface, _clock_ctrl, _codec_ctrl); - - _dboard_manager = dboard_manager::make(_rx_db_eeprom.id, - _tx_db_eeprom.id, - _dboard_iface); - - //setup the dboard proxies - _rx_dboard_proxy = wax_obj_proxy::make( - boost::bind(&usrp1_impl::rx_dboard_get, this, _1, _2), - boost::bind(&usrp1_impl::rx_dboard_set, this, _1, _2)); - - _tx_dboard_proxy = wax_obj_proxy::make( - boost::bind(&usrp1_impl::tx_dboard_get, this, _1, _2), - boost::bind(&usrp1_impl::tx_dboard_set, this, _1, _2)); +static boost::uint8_t get_rx_ee_addr(usrp1_impl::dboard_slot_t dboard_slot){ + switch(dboard_slot){ + case usrp1_impl::DBOARD_SLOT_A: return I2C_ADDR_RX_A; + case usrp1_impl::DBOARD_SLOT_B: return I2C_ADDR_RX_B; + default: UHD_THROW_INVALID_CODE_PATH(); + } +} +static boost::uint8_t get_tx_ee_addr(usrp1_impl::dboard_slot_t dboard_slot){ + switch(dboard_slot){ + case usrp1_impl::DBOARD_SLOT_A: return I2C_ADDR_TX_A; + case usrp1_impl::DBOARD_SLOT_B: return I2C_ADDR_TX_B; + default: UHD_THROW_INVALID_CODE_PATH(); + } } + /*********************************************************************** - * Helper functions + * Dboard Initialization **********************************************************************/ -//static int slot_to_i2c_addr (int slot) -//{ -// switch (slot) { -// case SLOT_TX_A: -// return I2C_ADDR_TX_A; -// case SLOT_RX_A: -// return I2C_ADDR_RX_A; -// case SLOT_TX_B: -// return I2C_ADDR_TX_B; -// case SLOT_RX_B: -// return I2C_ADDR_RX_B; -// default: -// return -1; -// } -//} +void usrp1_impl::dboard_init(void) +{ + BOOST_FOREACH(dboard_slot_t dboard_slot, _dboard_slots){ + + //read the tx and rx dboard eeproms + _rx_db_eeproms[dboard_slot] = dboard_eeprom_t(_iface->read_eeprom( + get_rx_ee_addr(dboard_slot), 0, dboard_eeprom_t::num_bytes() + )); + + _tx_db_eeproms[dboard_slot] = dboard_eeprom_t(_iface->read_eeprom( + get_tx_ee_addr(dboard_slot), 0, dboard_eeprom_t::num_bytes() + )); + + //create a new dboard interface and manager + _dboard_ifaces[dboard_slot] = make_dboard_iface( + _iface, _clock_ctrl, _codec_ctrls[dboard_slot], dboard_slot + ); + + _dboard_managers[dboard_slot] = dboard_manager::make( + _rx_db_eeproms[dboard_slot].id, + _tx_db_eeproms[dboard_slot].id, + _dboard_ifaces[dboard_slot] + ); + + //setup the dboard proxies + _rx_dboard_proxies[dboard_slot] = wax_obj_proxy::make( + boost::bind(&usrp1_impl::rx_dboard_get, this, _1, _2, dboard_slot), + boost::bind(&usrp1_impl::rx_dboard_set, this, _1, _2, dboard_slot)); + + _tx_dboard_proxies[dboard_slot] = wax_obj_proxy::make( + boost::bind(&usrp1_impl::tx_dboard_get, this, _1, _2, dboard_slot), + boost::bind(&usrp1_impl::tx_dboard_set, this, _1, _2, dboard_slot)); + } +} /*********************************************************************** * RX Dboard Get **********************************************************************/ -void usrp1_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val) +void usrp1_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot) { named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()){ case DBOARD_PROP_NAME: - val = std::string("usrp1 dboard (rx unit)"); + val = str(boost::format("usrp1 dboard (rx unit) - %c") % dboard_slot); return; case DBOARD_PROP_SUBDEV: - val = _dboard_manager->get_rx_subdev(key.name); + val = _dboard_managers[dboard_slot]->get_rx_subdev(key.name); return; case DBOARD_PROP_SUBDEV_NAMES: - val = _dboard_manager->get_rx_subdev_names(); + val = _dboard_managers[dboard_slot]->get_rx_subdev_names(); return; case DBOARD_PROP_DBOARD_ID: - val = _rx_db_eeprom.id; + val = _rx_db_eeproms[dboard_slot].id; return; case DBOARD_PROP_DBOARD_IFACE: - val = _dboard_iface; + val = _dboard_ifaces[dboard_slot]; return; case DBOARD_PROP_CODEC: - val = _rx_codec_proxy->get_link(); + val = _rx_codec_proxies[dboard_slot]->get_link(); return; case DBOARD_PROP_GAIN_GROUP: - val = make_gain_group(_dboard_manager->get_rx_subdev(key.name), - _rx_codec_proxy->get_link()); + val = make_gain_group(_dboard_managers[dboard_slot]->get_rx_subdev(key.name), + _rx_codec_proxies[dboard_slot]->get_link()); return; default: UHD_THROW_PROP_GET_ERROR(); @@ -122,13 +133,15 @@ void usrp1_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val) /*********************************************************************** * RX Dboard Set **********************************************************************/ -void usrp1_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val) +void usrp1_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val, dboard_slot_t dboard_slot) { switch(key.as()) { case DBOARD_PROP_DBOARD_ID: - _rx_db_eeprom.id = val.as(); - _iface->write_eeprom(I2C_ADDR_RX_A, 0, - _rx_db_eeprom.get_eeprom_bytes()); + _rx_db_eeproms[dboard_slot].id = val.as(); + _iface->write_eeprom( + get_rx_ee_addr(dboard_slot), 0, + _rx_db_eeproms[dboard_slot].get_eeprom_bytes() + ); return; default: @@ -139,39 +152,39 @@ void usrp1_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val) /*********************************************************************** * TX Dboard Get **********************************************************************/ -void usrp1_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val) +void usrp1_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot) { named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()){ case DBOARD_PROP_NAME: - val = std::string("usrp1 dboard (tx unit)"); + val = str(boost::format("usrp1 dboard (tx unit) - %c") % dboard_slot); return; case DBOARD_PROP_SUBDEV: - val = _dboard_manager->get_tx_subdev(key.name); + val = _dboard_managers[dboard_slot]->get_tx_subdev(key.name); return; case DBOARD_PROP_SUBDEV_NAMES: - val = _dboard_manager->get_tx_subdev_names(); + val = _dboard_managers[dboard_slot]->get_tx_subdev_names(); return; case DBOARD_PROP_DBOARD_ID: - val = _tx_db_eeprom.id; + val = _tx_db_eeproms[dboard_slot].id; return; case DBOARD_PROP_DBOARD_IFACE: - val = _dboard_iface; + val = _dboard_ifaces[dboard_slot]; return; case DBOARD_PROP_CODEC: - val = _tx_codec_proxy->get_link(); + val = _tx_codec_proxies[dboard_slot]->get_link(); return; case DBOARD_PROP_GAIN_GROUP: - val = make_gain_group(_dboard_manager->get_tx_subdev(key.name), - _tx_codec_proxy->get_link()); + val = make_gain_group(_dboard_managers[dboard_slot]->get_tx_subdev(key.name), + _tx_codec_proxies[dboard_slot]->get_link()); return; default: UHD_THROW_PROP_GET_ERROR(); @@ -181,12 +194,15 @@ void usrp1_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val) /*********************************************************************** * TX Dboard Set **********************************************************************/ -void usrp1_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val) +void usrp1_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val, dboard_slot_t dboard_slot) { switch(key.as()) { case DBOARD_PROP_DBOARD_ID: - _tx_db_eeprom.id = val.as(); - _iface->write_eeprom(I2C_ADDR_TX_A, 0, _tx_db_eeprom.get_eeprom_bytes()); + _tx_db_eeproms[dboard_slot].id = val.as(); + _iface->write_eeprom( + get_tx_ee_addr(dboard_slot), 0, + _tx_db_eeproms[dboard_slot].get_eeprom_bytes() + ); return; default: UHD_THROW_PROP_SET_ERROR(); diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index e9900131f..1a8993a01 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -29,19 +29,19 @@ using namespace uhd::usrp; /*********************************************************************** * RX DDC Initialization **********************************************************************/ -void usrp1_impl::rx_ddc_init(void) +void usrp1_impl::rx_dsp_init(void) { - _rx_ddc_proxy = wax_obj_proxy::make( - boost::bind(&usrp1_impl::rx_ddc_get, this, _1, _2), - boost::bind(&usrp1_impl::rx_ddc_set, this, _1, _2)); + _rx_dsp_proxy = wax_obj_proxy::make( + boost::bind(&usrp1_impl::rx_dsp_get, this, _1, _2), + boost::bind(&usrp1_impl::rx_dsp_set, this, _1, _2)); - rx_ddc_set(DSP_PROP_HOST_RATE, double(64e6/10)); + rx_dsp_set(DSP_PROP_HOST_RATE, double(64e6/10)); //FIXME magic number } /*********************************************************************** * RX DDC Get **********************************************************************/ -void usrp1_impl::rx_ddc_get(const wax::obj &key, wax::obj &val) +void usrp1_impl::rx_dsp_get(const wax::obj &key, wax::obj &val) { switch(key.as()){ case DSP_PROP_NAME: @@ -53,7 +53,7 @@ void usrp1_impl::rx_ddc_get(const wax::obj &key, wax::obj &val) return; case DSP_PROP_FREQ_SHIFT: - val = _ddc_freq; + val = _rx_dsp_freq; return; case DSP_PROP_CODEC_RATE: @@ -61,7 +61,7 @@ void usrp1_impl::rx_ddc_get(const wax::obj &key, wax::obj &val) return; case DSP_PROP_HOST_RATE: - val = _clock_ctrl->get_master_clock_freq()/_ddc_decim; + val = _clock_ctrl->get_master_clock_freq()/_rx_dsp_decim; return; default: UHD_THROW_PROP_GET_ERROR(); @@ -90,13 +90,13 @@ unsigned int compute_freq_word(double master, double target) return (unsigned int) v; } -void usrp1_impl::rx_ddc_set(const wax::obj &key, const wax::obj &val) +void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val) { switch(key.as()) { case DSP_PROP_FREQ_SHIFT: { double new_freq = val.as(); - _iface->poke32(FR_RX_FREQ_0, compute_freq_word(64e6, new_freq)); - _ddc_freq = new_freq; + _iface->poke32(FR_RX_FREQ_0, compute_freq_word(64e6, new_freq)); //FIXME magic rate + _tx_dsp_freq = new_freq; return; } case DSP_PROP_HOST_RATE: { @@ -110,8 +110,8 @@ void usrp1_impl::rx_ddc_set(const wax::obj &key, const wax::obj &val) return; } - _ddc_decim = rate; - _iface->poke32(FR_DECIM_RATE, _ddc_decim/2 - 1); + _rx_dsp_decim = rate; + _iface->poke32(FR_DECIM_RATE, _rx_dsp_decim/2 - 1); } return; @@ -123,20 +123,20 @@ void usrp1_impl::rx_ddc_set(const wax::obj &key, const wax::obj &val) /*********************************************************************** * TX DUC Initialization **********************************************************************/ -void usrp1_impl::tx_duc_init(void) +void usrp1_impl::tx_dsp_init(void) { - _tx_duc_proxy = wax_obj_proxy::make( - boost::bind(&usrp1_impl::tx_duc_get, this, _1, _2), - boost::bind(&usrp1_impl::tx_duc_set, this, _1, _2)); + _tx_dsp_proxy = wax_obj_proxy::make( + boost::bind(&usrp1_impl::tx_dsp_get, this, _1, _2), + boost::bind(&usrp1_impl::tx_dsp_set, this, _1, _2)); //initial config and update - tx_duc_set(DSP_PROP_HOST_RATE, double(64e6/10)); + tx_dsp_set(DSP_PROP_HOST_RATE, double(64e6/10)); //FIXME magic number } /*********************************************************************** * TX DUC Get **********************************************************************/ -void usrp1_impl::tx_duc_get(const wax::obj &key, wax::obj &val) +void usrp1_impl::tx_dsp_get(const wax::obj &key, wax::obj &val) { switch(key.as()) { case DSP_PROP_NAME: @@ -148,7 +148,7 @@ void usrp1_impl::tx_duc_get(const wax::obj &key, wax::obj &val) return; case DSP_PROP_FREQ_SHIFT: - val = _duc_freq; + val = _tx_dsp_freq; return; case DSP_PROP_CODEC_RATE: @@ -156,7 +156,7 @@ void usrp1_impl::tx_duc_get(const wax::obj &key, wax::obj &val) return; case DSP_PROP_HOST_RATE: - val = _clock_ctrl->get_master_clock_freq() * 2 / _duc_interp; + val = _clock_ctrl->get_master_clock_freq() * 2 / _tx_dsp_interp; return; default: UHD_THROW_PROP_GET_ERROR(); @@ -167,16 +167,19 @@ void usrp1_impl::tx_duc_get(const wax::obj &key, wax::obj &val) /*********************************************************************** * TX DUC Set **********************************************************************/ -void usrp1_impl::tx_duc_set(const wax::obj &key, const wax::obj &val) +void usrp1_impl::tx_dsp_set(const wax::obj &key, const wax::obj &val) { switch(key.as()) { case DSP_PROP_FREQ_SHIFT: { double new_freq = val.as(); - _codec_ctrl->set_duc_freq(new_freq); - _duc_freq = new_freq; + _codec_ctrls[DBOARD_SLOT_A]->set_duc_freq(new_freq); + _tx_dsp_freq = new_freq; return; } + + //TODO freq prop secondary: DBOARD_SLOT_B codec... + case DSP_PROP_HOST_RATE: { unsigned int rate = _clock_ctrl->get_master_clock_freq() * 2 / val.as(); @@ -187,8 +190,8 @@ void usrp1_impl::tx_duc_set(const wax::obj &key, const wax::obj &val) return; } - _duc_interp = rate; - _iface->poke32(FR_INTERP_RATE, _duc_interp / 4 - 1); + _tx_dsp_interp = rate; + _iface->poke32(FR_INTERP_RATE, _tx_dsp_interp / 4 - 1); return; } default: UHD_THROW_PROP_SET_ERROR(); diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index 2514072e0..e0a7fefb1 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -19,6 +19,7 @@ #include "usrp_commands.h" #include #include +#include #include #include @@ -109,6 +110,8 @@ void usrp1_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd) /*********************************************************************** * Mboard Get **********************************************************************/ +static prop_names_t dboard_names = boost::assign::list_of("A")("B"); + void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val) { named_prop_t key = named_prop_t::extract(key_); @@ -124,26 +127,28 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val) return; case MBOARD_PROP_RX_DBOARD: - UHD_ASSERT_THROW(key.name == ""); - val = _rx_dboard_proxy->get_link(); + uhd::assert_has(dboard_names, key.name, "dboard name"); + if (key.name == "A") val = _rx_dboard_proxies[DBOARD_SLOT_A]->get_link(); + if (key.name == "B") val = _rx_dboard_proxies[DBOARD_SLOT_B]->get_link(); return; case MBOARD_PROP_RX_DBOARD_NAMES: - val = prop_names_t(1, ""); //vector of size 1 with empty string + val = dboard_names; return; case MBOARD_PROP_TX_DBOARD: - UHD_ASSERT_THROW(key.name == ""); - val = _tx_dboard_proxy->get_link(); + uhd::assert_has(dboard_names, key.name, "dboard name"); + if (key.name == "A") val = _tx_dboard_proxies[DBOARD_SLOT_A]->get_link(); + if (key.name == "B") val = _tx_dboard_proxies[DBOARD_SLOT_B]->get_link(); return; case MBOARD_PROP_TX_DBOARD_NAMES: - val = prop_names_t(1, ""); //vector of size 1 with empty string + val = dboard_names; return; case MBOARD_PROP_RX_DSP: UHD_ASSERT_THROW(key.name == ""); - val = _rx_ddc_proxy->get_link(); + val = _rx_dsp_proxy->get_link(); return; case MBOARD_PROP_RX_DSP_NAMES: @@ -152,7 +157,7 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val) case MBOARD_PROP_TX_DSP: UHD_ASSERT_THROW(key.name == ""); - val = _tx_duc_proxy->get_link(); + val = _tx_dsp_proxy->get_link(); return; case MBOARD_PROP_TX_DSP_NAMES: diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 1435b981c..ece5f1dea 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -18,11 +18,13 @@ #include "usrp1_impl.hpp" #include "usrp1_ctrl.hpp" #include "fpga_regs_standard.h" +#include "usrp_spi_defs.h" #include #include #include #include #include +#include #include #include @@ -30,6 +32,10 @@ using namespace uhd; using namespace uhd::usrp; using namespace uhd::transport; +const std::vector usrp1_impl::_dboard_slots = boost::assign::list_of + (usrp1_impl::DBOARD_SLOT_A)(usrp1_impl::DBOARD_SLOT_B) +; + /*********************************************************************** * Discovery **********************************************************************/ @@ -132,7 +138,8 @@ usrp1_impl::usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport, _clock_ctrl = usrp1_clock_ctrl::make(_iface); //create codec interface - _codec_ctrl = usrp1_codec_ctrl::make(_iface); + _codec_ctrls[DBOARD_SLOT_A] = usrp1_codec_ctrl::make(_iface, SPI_ENABLE_CODEC_A); + _codec_ctrls[DBOARD_SLOT_B] = usrp1_codec_ctrl::make(_iface, SPI_ENABLE_CODEC_B); //initialize the codecs codec_init(); @@ -144,10 +151,10 @@ usrp1_impl::usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport, dboard_init(); //initialize the dsps - rx_ddc_init(); + rx_dsp_init(); //initialize the dsps - tx_duc_init(); + tx_dsp_init(); //initialize the send/recv io_init(); diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 5abc37c7f..84ec26827 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -21,6 +21,7 @@ #include "codec_ctrl.hpp" #include #include +#include #include #include #include @@ -33,17 +34,6 @@ static const double MASTER_CLOCK_RATE = 64e6; //TODO get from clock control -/*! - * Make a usrp1 dboard interface. - * \param iface the usrp1 interface object - * \param clock the clock control interface - * \param codec the codec control interface - * \return a sptr to a new dboard interface - */ -uhd::usrp::dboard_iface::sptr make_usrp1_dboard_iface(usrp1_iface::sptr iface, - usrp1_clock_ctrl::sptr clock, - usrp1_codec_ctrl::sptr codec); - /*! * Simple wax obj proxy class: * Provides a wax obj interface for a set and a get function. @@ -75,6 +65,14 @@ private: */ class usrp1_impl : public uhd::device { public: + //! used everywhere to differentiate slots/sides... + enum dboard_slot_t{ + DBOARD_SLOT_A = 'A', + DBOARD_SLOT_B = 'B' + }; + //and a way to enumerate through a list of the above... + static const std::vector _dboard_slots; + //structors usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport, usrp_ctrl::sptr ctrl_transport); @@ -97,9 +95,27 @@ public: size_t get_max_send_samps_per_packet(void) const { return 0; } size_t get_max_recv_samps_per_packet(void) const { return 0; } - bool recv_async_msg(uhd::async_metadata_t &, size_t) { return true; } + bool recv_async_msg(uhd::async_metadata_t &, size_t) { + //TODO sleep the number of ms supplied (dont want to hog CPU) + return false; + } private: + /*! + * Make a usrp1 dboard interface. + * \param iface the usrp1 interface object + * \param clock the clock control interface + * \param codec the codec control interface + * \param dboard_slot the slot identifier + * \return a sptr to a new dboard interface + */ + static uhd::usrp::dboard_iface::sptr make_dboard_iface( + usrp1_iface::sptr iface, + usrp1_clock_ctrl::sptr clock, + usrp1_codec_ctrl::sptr codec, + dboard_slot_t dboard_slot + ); + //interface to ioctls and file descriptor usrp1_iface::sptr _iface; @@ -120,16 +136,15 @@ private: usrp1_clock_ctrl::sptr _clock_ctrl; //ad9862 codec control interface - usrp1_codec_ctrl::sptr _codec_ctrl; + uhd::dict _codec_ctrls; //codec properties interfaces void codec_init(void); - void rx_codec_get(const wax::obj &, wax::obj &); - void rx_codec_set(const wax::obj &, const wax::obj &); - void tx_codec_get(const wax::obj &, wax::obj &); - void tx_codec_set(const wax::obj &, const wax::obj &); - wax_obj_proxy::sptr _rx_codec_proxy; - wax_obj_proxy::sptr _tx_codec_proxy; + void rx_codec_get(const wax::obj &, wax::obj &, dboard_slot_t); + void rx_codec_set(const wax::obj &, const wax::obj &, dboard_slot_t); + void tx_codec_get(const wax::obj &, wax::obj &, dboard_slot_t); + void tx_codec_set(const wax::obj &, const wax::obj &, dboard_slot_t); + uhd::dict _rx_codec_proxies, _tx_codec_proxies; //device functions and settings void get(const wax::obj &, wax::obj &); @@ -143,36 +158,34 @@ private: //xx dboard functions and settings void dboard_init(void); - uhd::usrp::dboard_manager::sptr _dboard_manager; - uhd::usrp::dboard_iface::sptr _dboard_iface; + uhd::dict _dboard_managers; + uhd::dict _dboard_ifaces; //rx dboard functions and settings - uhd::usrp::dboard_eeprom_t _rx_db_eeprom; - void rx_dboard_get(const wax::obj &, wax::obj &); - void rx_dboard_set(const wax::obj &, const wax::obj &); - uhd::prop_names_t _rx_subdevs_in_use; - wax_obj_proxy::sptr _rx_dboard_proxy; + uhd::dict _rx_db_eeproms; + void rx_dboard_get(const wax::obj &, wax::obj &, dboard_slot_t); + void rx_dboard_set(const wax::obj &, const wax::obj &, dboard_slot_t); + uhd::dict _rx_dboard_proxies; //tx dboard functions and settings - uhd::usrp::dboard_eeprom_t _tx_db_eeprom; - void tx_dboard_get(const wax::obj &, wax::obj &); - void tx_dboard_set(const wax::obj &, const wax::obj &); - uhd::prop_names_t _tx_subdevs_in_use; - wax_obj_proxy::sptr _tx_dboard_proxy; - - //rx ddc functions and settings - void rx_ddc_init(void); - void rx_ddc_get(const wax::obj &, wax::obj &); - void rx_ddc_set(const wax::obj &, const wax::obj &); - double _ddc_freq; size_t _ddc_decim; - wax_obj_proxy::sptr _rx_ddc_proxy; - - //tx duc functions and settings - void tx_duc_init(void); - void tx_duc_get(const wax::obj &, wax::obj &); - void tx_duc_set(const wax::obj &, const wax::obj &); - double _duc_freq; size_t _duc_interp; - wax_obj_proxy::sptr _tx_duc_proxy; + uhd::dict _tx_db_eeproms; + void tx_dboard_get(const wax::obj &, wax::obj &, dboard_slot_t); + void tx_dboard_set(const wax::obj &, const wax::obj &, dboard_slot_t); + uhd::dict _tx_dboard_proxies; + + //rx dsp functions and settings + void rx_dsp_init(void); + void rx_dsp_get(const wax::obj &, wax::obj &); + void rx_dsp_set(const wax::obj &, const wax::obj &); + double _rx_dsp_freq; size_t _rx_dsp_decim; + wax_obj_proxy::sptr _rx_dsp_proxy; + + //tx dsp functions and settings + void tx_dsp_init(void); + void tx_dsp_get(const wax::obj &, wax::obj &); + void tx_dsp_set(const wax::obj &, const wax::obj &); + double _tx_dsp_freq; size_t _tx_dsp_interp; + wax_obj_proxy::sptr _tx_dsp_proxy; //transports uhd::transport::usb_zero_copy::sptr _data_transport; -- cgit v1.2.3 From 564bfee0389d0274e7cd128d61dcbe50ca6a6cdd Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 16 Aug 2010 00:09:47 -0700 Subject: usrp1: compiling with the latest next --- host/lib/usrp/usrp1/dboard_impl.cpp | 18 ++++++++++++------ host/lib/usrp/usrp1/dsp_impl.cpp | 12 ++++++------ host/lib/usrp/usrp1/mboard_impl.cpp | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) (limited to 'host/lib/usrp/usrp1/dsp_impl.cpp') diff --git a/host/lib/usrp/usrp1/dboard_impl.cpp b/host/lib/usrp/usrp1/dboard_impl.cpp index ba826d2f5..c8d9c55dd 100644 --- a/host/lib/usrp/usrp1/dboard_impl.cpp +++ b/host/lib/usrp/usrp1/dboard_impl.cpp @@ -17,8 +17,8 @@ #include "usrp1_impl.hpp" #include "usrp_i2c_addr.h" -#include "../dsp_utils.hpp" -#include "../misc_utils.hpp" +#include +#include #include #include #include @@ -122,8 +122,11 @@ void usrp1_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_ return; case DBOARD_PROP_GAIN_GROUP: - val = make_gain_group(_dboard_managers[dboard_slot]->get_rx_subdev(key.name), - _rx_codec_proxies[dboard_slot]->get_link()); + val = make_gain_group( + _dboard_managers[dboard_slot]->get_rx_subdev(key.name), + _rx_codec_proxies[dboard_slot]->get_link(), + GAIN_GROUP_POLICY_RX + ); return; default: UHD_THROW_PROP_GET_ERROR(); @@ -183,8 +186,11 @@ void usrp1_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_ return; case DBOARD_PROP_GAIN_GROUP: - val = make_gain_group(_dboard_managers[dboard_slot]->get_tx_subdev(key.name), - _tx_codec_proxies[dboard_slot]->get_link()); + val = make_gain_group( + _dboard_managers[dboard_slot]->get_tx_subdev(key.name), + _tx_codec_proxies[dboard_slot]->get_link(), + GAIN_GROUP_POLICY_TX + ); return; default: UHD_THROW_PROP_GET_ERROR(); diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index 1a8993a01..260c01ea8 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -17,11 +17,12 @@ #include "usrp1_impl.hpp" #include "fpga_regs_standard.h" -#include "../dsp_utils.hpp" +#include #include #include +#include #include -#include +#include using namespace uhd; using namespace uhd::usrp; @@ -82,10 +83,9 @@ unsigned int compute_freq_word(double master, double target) double actual_freq = v * master / pow(2.0, 32.0); - if (0) - fprintf (stderr, - "compute_freq_control_word_fpga: target = %g actual = %g delta = %g\n", - target, actual_freq, actual_freq - target); + if (0) std::cerr << boost::format( + "compute_freq_control_word_fpga: target = %g actual = %g delta = %g\n" + ) % target % actual_freq % (actual_freq - target); return (unsigned int) v; } diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index 5e0285dfd..ede9b2681 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -17,7 +17,7 @@ #include "usrp1_impl.hpp" #include "usrp_commands.h" -#include "../misc_utils.hpp" +#include #include #include #include -- cgit v1.2.3 From 43e5480dee9f6068ffe84bf1b86526189043ee87 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Mon, 16 Aug 2010 17:03:06 -0700 Subject: usrp1: Remove hard coded clock values Get clock values from clock control, where the master setting lives. --- host/lib/usrp/usrp1/dsp_impl.cpp | 10 ++++++---- host/lib/usrp/usrp1/usrp1_impl.hpp | 2 -- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'host/lib/usrp/usrp1/dsp_impl.cpp') diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index 260c01ea8..0db3cb473 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -36,7 +36,7 @@ void usrp1_impl::rx_dsp_init(void) boost::bind(&usrp1_impl::rx_dsp_get, this, _1, _2), boost::bind(&usrp1_impl::rx_dsp_set, this, _1, _2)); - rx_dsp_set(DSP_PROP_HOST_RATE, double(64e6/10)); //FIXME magic number + rx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() / 16); } /*********************************************************************** @@ -95,7 +95,9 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val) switch(key.as()) { case DSP_PROP_FREQ_SHIFT: { double new_freq = val.as(); - _iface->poke32(FR_RX_FREQ_0, compute_freq_word(64e6, new_freq)); //FIXME magic rate + boost::uint32_t hw_freq_word = compute_freq_word( + _clock_ctrl->get_master_clock_freq(), new_freq); + _iface->poke32(FR_RX_FREQ_0, hw_freq_word); _tx_dsp_freq = new_freq; return; } @@ -130,7 +132,7 @@ void usrp1_impl::tx_dsp_init(void) boost::bind(&usrp1_impl::tx_dsp_set, this, _1, _2)); //initial config and update - tx_dsp_set(DSP_PROP_HOST_RATE, double(64e6/10)); //FIXME magic number + tx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() * 2 / 16); } /*********************************************************************** @@ -152,7 +154,7 @@ void usrp1_impl::tx_dsp_get(const wax::obj &key, wax::obj &val) return; case DSP_PROP_CODEC_RATE: - val = MASTER_CLOCK_RATE; + val = _clock_ctrl->get_master_clock_freq() * 2; return; case DSP_PROP_HOST_RATE: diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 5166f989f..f57f9a09a 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -33,8 +33,6 @@ #ifndef INCLUDED_USRP1_IMPL_HPP #define INCLUDED_USRP1_IMPL_HPP -static const double MASTER_CLOCK_RATE = 64e6; //TODO get from clock control - /*! * Simple wax obj proxy class: * Provides a wax obj interface for a set and a get function. -- cgit v1.2.3 From 024377afa9628c282a5f7584ca5cc8991dd1296f Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Wed, 18 Aug 2010 11:06:57 -0700 Subject: usrp1: Refactor mboard tuning code --- host/lib/usrp/usrp1/codec_ctrl.cpp | 164 +++++++++++++++++-------------------- host/lib/usrp/usrp1/codec_ctrl.hpp | 8 +- host/lib/usrp/usrp1/dsp_impl.cpp | 26 +----- host/lib/usrp/usrp1/usrp1_impl.cpp | 8 +- 4 files changed, 92 insertions(+), 114 deletions(-) (limited to 'host/lib/usrp/usrp1/dsp_impl.cpp') diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp index 01617de94..419e4c5e2 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.cpp +++ b/host/lib/usrp/usrp1/codec_ctrl.cpp @@ -17,6 +17,7 @@ #include "codec_ctrl.hpp" #include "usrp_commands.h" +#include "clock_ctrl.hpp" #include "ad9862_regs.hpp" #include #include @@ -43,7 +44,9 @@ const gain_range_t usrp1_codec_ctrl::rx_pga_gain_range(0, 20, 1); class usrp1_codec_ctrl_impl : public usrp1_codec_ctrl { public: //structors - usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, int spi_slave); + usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, + usrp1_clock_ctrl::sptr clock, + int spi_slave); ~usrp1_codec_ctrl_impl(void); //aux adc and dac control @@ -51,7 +54,7 @@ public: void write_aux_dac(aux_dac_t which, float volts); //duc control - bool set_duc_freq(double freq); + void set_duc_freq(double freq); //pga gain control void set_tx_pga_gain(float); @@ -61,25 +64,26 @@ public: private: usrp1_iface::sptr _iface; + usrp1_clock_ctrl::sptr _clock_ctrl; int _spi_slave; ad9862_regs_t _ad9862_regs; aux_adc_t _last_aux_adc_a, _last_aux_adc_b; void send_reg(boost::uint8_t addr); void recv_reg(boost::uint8_t addr); - //FIXME: poison - double _tx_freq[4]; - unsigned int compute_freq_control_word_9862 (double master_freq, - double target_freq, - double *actual_freq); + double coarse_tune(double codec_rate, double freq); + double fine_tune(double codec_rate, double freq); }; /*********************************************************************** * Codec Control Structors **********************************************************************/ -usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, int spi_slave) +usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface, + usrp1_clock_ctrl::sptr clock, + int spi_slave) { _iface = iface; + _clock_ctrl = clock; _spi_slave = spi_slave; //soft reset @@ -324,118 +328,102 @@ void usrp1_codec_ctrl_impl::recv_reg(boost::uint8_t addr) /*********************************************************************** * DUC tuning **********************************************************************/ -unsigned int usrp1_codec_ctrl_impl::compute_freq_control_word_9862( - double master_freq, double target_freq, double *actual_freq) +double usrp1_codec_ctrl_impl::coarse_tune(double codec_rate, double freq) { - double sign = 1.0; - - if (target_freq < 0) - sign = -1.0; - - int v = (int) rint (fabs (target_freq) / master_freq * pow (2.0, 24.0)); - *actual_freq = v * master_freq / pow (2.0, 24.0) * sign; - - std::cout << boost::format( - "compute_freq_control_word_9862: target = %g actual = %g delta = %g v = %8d\n" - ) % target_freq % *actual_freq % (*actual_freq - target_freq) % v; - - return (unsigned int) v; -} + double coarse_freq; -bool usrp1_codec_ctrl_impl::set_duc_freq(double freq) -{ - int channel = 0; - float dac_rate = 128e6; - - double coarse; - - std::cout << "duc_freq: " << freq << std::endl; - - // First coarse frequency - double coarse_freq_1 = dac_rate / 8; - // Second coarse frequency - double coarse_freq_2 = dac_rate / 4; - // Midpoint of [0 , freq1] range + double coarse_freq_1 = codec_rate / 8; + double coarse_freq_2 = codec_rate / 4; double coarse_limit_1 = coarse_freq_1 / 2; - // Midpoint of [freq1 , freq2] range double coarse_limit_2 = (coarse_freq_1 + coarse_freq_2) / 2; - // Highest meaningful frequency - double high_limit = (double) 44e6 / 128e6 * dac_rate; + double max_freq = coarse_freq_2 + .09375 * codec_rate; - if (freq < -high_limit) { // too low + if (freq < -max_freq) { return false; } - else if (freq < -coarse_limit_2) { // For 64MHz: [-44, -24) + else if (freq < -coarse_limit_2) { _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_NEG_SHIFT; _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_4; - coarse = -coarse_freq_2; + coarse_freq = -coarse_freq_2; } - else if (freq < -coarse_limit_1) { // For 64MHz: [-24, -8) + else if (freq < -coarse_limit_1) { _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_NEG_SHIFT; _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_8; - coarse = -coarse_freq_1; + coarse_freq = -coarse_freq_1; } - else if (freq < coarse_limit_1) { // For 64MHz: [-8, 8) + else if (freq < coarse_limit_1) { _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS; - coarse = 0; + coarse_freq = 0; } - else if (freq < coarse_limit_2) { // For 64MHz: [8, 24) + else if (freq < coarse_limit_2) { _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_POS_SHIFT; _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_8; - coarse = coarse_freq_1; + coarse_freq = coarse_freq_1; } - else if (freq <= high_limit) { // For 64MHz: [24, 44] + else if (freq <= max_freq) { _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_POS_SHIFT; _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_4; - coarse = coarse_freq_2; + coarse_freq = coarse_freq_2; } - else { // too high - return false; + else { + return 0; } - - double fine = freq - coarse; - - // Compute fine tuning word... - // This assumes we're running the 4x on-chip interpolator. - // (This is required to use the fine modulator.) - - unsigned int v = compute_freq_control_word_9862 (dac_rate / 4, fine, - &_tx_freq[channel]); - - _tx_freq[channel] += coarse; // adjust actual - - boost::uint8_t high; - boost::uint8_t mid; - boost::uint8_t low; - - high = (v >> 16) & 0xff; - mid = (v >> 8) & 0xff; - low = (v >> 0) & 0xff; - - // write the fine tuning word - _ad9862_regs.ftw_23_16 = high; - _ad9862_regs.ftw_15_8 = mid; - _ad9862_regs.ftw_7_0 = low; - - _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_NCO; - - if (fine < 0) + + return coarse_freq; +} + +double usrp1_codec_ctrl_impl::fine_tune(double codec_rate, double target_freq) +{ + static const double scale_factor = std::pow(2.0, 24); + + boost::uint32_t freq_word = boost::uint32_t( + boost::math::round(abs((target_freq / codec_rate) * scale_factor))); + + double actual_freq = freq_word * codec_rate / scale_factor; + + if (target_freq < 0) { _ad9862_regs.neg_fine_tune = ad9862_regs_t::NEG_FINE_TUNE_NEG_SHIFT; - else + actual_freq = -actual_freq; + } + else { _ad9862_regs.neg_fine_tune = ad9862_regs_t::NEG_FINE_TUNE_POS_SHIFT; - + } + + _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_NCO; + _ad9862_regs.ftw_23_16 = (freq_word >> 16) & 0xff; + _ad9862_regs.ftw_15_8 = (freq_word >> 8) & 0xff; + _ad9862_regs.ftw_7_0 = (freq_word >> 0) & 0xff; + + return actual_freq; +} + +void usrp1_codec_ctrl_impl::set_duc_freq(double freq) +{ + double codec_rate = _clock_ctrl->get_master_clock_freq() * 2; + double coarse_freq = coarse_tune(codec_rate, freq); + double fine_freq = fine_tune(codec_rate / 4, freq - coarse_freq); + + if (codec_debug) { + std::cout << "ad9862 tuning result:" << std::endl; + std::cout << " requested: " << freq << std::endl; + std::cout << " actual: " << coarse_freq + fine_freq << std::endl; + std::cout << " coarse freq: " << coarse_freq << std::endl; + std::cout << " fine freq: " << fine_freq << std::endl; + std::cout << " codec rate: " << codec_rate << std::endl; + } + this->send_reg(20); this->send_reg(21); this->send_reg(22); this->send_reg(23); - - return true; } /*********************************************************************** * Codec Control Make **********************************************************************/ -usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface, int spi_slave) +usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface, + usrp1_clock_ctrl::sptr clock, + int spi_slave) { - return sptr(new usrp1_codec_ctrl_impl(iface, spi_slave)); + return sptr(new usrp1_codec_ctrl_impl(iface, clock, spi_slave)); } diff --git a/host/lib/usrp/usrp1/codec_ctrl.hpp b/host/lib/usrp/usrp1/codec_ctrl.hpp index 6440f97d1..259d10ef4 100644 --- a/host/lib/usrp/usrp1/codec_ctrl.hpp +++ b/host/lib/usrp/usrp1/codec_ctrl.hpp @@ -19,6 +19,7 @@ #define INCLUDED_USRP1_CODEC_CTRL_HPP #include "usrp1_iface.hpp" +#include "clock_ctrl.hpp" #include #include #include @@ -41,7 +42,9 @@ public: * \param spi_slave which spi device * \return the clock control object */ - static sptr make(usrp1_iface::sptr iface, int spi_slave); + static sptr make(usrp1_iface::sptr iface, + usrp1_clock_ctrl::sptr clock, int spi_slave + ); //! aux adc identifier constants enum aux_adc_t{ @@ -87,7 +90,8 @@ public: //! Get the RX PGA gain ('A' or 'B') virtual float get_rx_pga_gain(char which) = 0; - virtual bool set_duc_freq(double freq) = 0; + //! Set the TX modulator frequency + virtual void set_duc_freq(double freq) = 0; }; #endif /* INCLUDED_USRP1_CODEC_CTRL_HPP */ diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index 0db3cb473..ce0c12e4b 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -73,31 +73,13 @@ void usrp1_impl::rx_dsp_get(const wax::obj &key, wax::obj &val) /*********************************************************************** * RX DDC Set **********************************************************************/ -unsigned int compute_freq_word(double master, double target) -{ - static const int NBITS = 14; - int v = (int) rint (target / master * pow(2.0, 32.0)); - - if (0) - v = (v >> (32 - NBITS)) << (32 - NBITS); // keep only top NBITS - - double actual_freq = v * master / pow(2.0, 32.0); - - if (0) std::cerr << boost::format( - "compute_freq_control_word_fpga: target = %g actual = %g delta = %g\n" - ) % target % actual_freq % (actual_freq - target); - - return (unsigned int) v; -} - void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val) { switch(key.as()) { case DSP_PROP_FREQ_SHIFT: { double new_freq = val.as(); - boost::uint32_t hw_freq_word = compute_freq_word( - _clock_ctrl->get_master_clock_freq(), new_freq); - _iface->poke32(FR_RX_FREQ_0, hw_freq_word); + _iface->poke32(FR_RX_FREQ_0, + -dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_master_clock_freq())); _tx_dsp_freq = new_freq; return; } @@ -173,15 +155,15 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key, const wax::obj &val) { switch(key.as()) { + // TODO: Set both codec frequencies until we have duality properties case DSP_PROP_FREQ_SHIFT: { double new_freq = val.as(); _codec_ctrls[DBOARD_SLOT_A]->set_duc_freq(new_freq); + _codec_ctrls[DBOARD_SLOT_B]->set_duc_freq(new_freq); _tx_dsp_freq = new_freq; return; } - //TODO freq prop secondary: DBOARD_SLOT_B codec... - case DSP_PROP_HOST_RATE: { unsigned int rate = _clock_ctrl->get_master_clock_freq() * 2 / val.as(); diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index ece5f1dea..ee6fe6e99 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -138,8 +138,12 @@ usrp1_impl::usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport, _clock_ctrl = usrp1_clock_ctrl::make(_iface); //create codec interface - _codec_ctrls[DBOARD_SLOT_A] = usrp1_codec_ctrl::make(_iface, SPI_ENABLE_CODEC_A); - _codec_ctrls[DBOARD_SLOT_B] = usrp1_codec_ctrl::make(_iface, SPI_ENABLE_CODEC_B); + _codec_ctrls[DBOARD_SLOT_A] = usrp1_codec_ctrl::make( + _iface, _clock_ctrl, SPI_ENABLE_CODEC_A + ); + _codec_ctrls[DBOARD_SLOT_B] = usrp1_codec_ctrl::make( + _iface, _clock_ctrl, SPI_ENABLE_CODEC_B + ); //initialize the codecs codec_init(); -- cgit v1.2.3 From 4021779856d6b971fa8add5f617528158bf727a2 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Mon, 23 Aug 2010 15:13:44 -0700 Subject: usrp1: Refactor I/O implementation --- host/lib/usrp/usrp1/dsp_impl.cpp | 4 + host/lib/usrp/usrp1/io_impl.cpp | 337 +++++++++++++++++++++++-------------- host/lib/usrp/usrp1/usrp1_impl.hpp | 4 + 3 files changed, 215 insertions(+), 130 deletions(-) (limited to 'host/lib/usrp/usrp1/dsp_impl.cpp') diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index ce0c12e4b..ddd1e811b 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -95,6 +95,8 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val) } _rx_dsp_decim = rate; + _rx_samps_per_poll_interval = 0.1 * _clock_ctrl->get_master_clock_freq() / rate; + _iface->poke32(FR_DECIM_RATE, _rx_dsp_decim/2 - 1); } return; @@ -175,6 +177,8 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key, const wax::obj &val) } _tx_dsp_interp = rate; + _tx_samps_per_poll_interval = 0.1 * _clock_ctrl->get_master_clock_freq() * 2 / rate; + _iface->poke32(FR_INTERP_RATE, _tx_dsp_interp / 4 - 1); return; } diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 71b2c4fc5..33a04ffe6 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -35,41 +35,53 @@ namespace asio = boost::asio; static const float poll_interval = 0.1; //100ms -/* - * The FX2 firmware bursts data to the FPGA in 512 byte chunks so - * maintain send state to make sure that happens. - */ struct usrp1_send_state { uhd::transport::managed_send_buffer::sptr send_buff; - size_t bytes_used; + size_t bytes_written; size_t bytes_free; + size_t underrun_poll_samp_count; +}; + +struct usrp1_recv_state { + uhd::transport::managed_recv_buffer::sptr recv_buff; + size_t bytes_read; + size_t bytes_avail; + size_t overrun_poll_samp_count; }; /*********************************************************************** * IO Implementation Details **********************************************************************/ struct usrp1_impl::io_impl { - io_impl(zero_copy_if::sptr zc_if); + io_impl(); ~io_impl(void); - bool get_recv_buff(managed_recv_buffer::sptr buff); - - //state management for the vrt packet handler code - vrt_packet_handler::recv_state packet_handler_recv_state; + //state handling for buffer management + usrp1_recv_state recv_state; usrp1_send_state send_state; - zero_copy_if::sptr data_transport; - - //overun-underrun values - unsigned int tx_underrun_count; - unsigned int rx_overrun_count; + //send transport management + bool get_send_buffer(zero_copy_if::sptr zc_if); + size_t copy_convert_send_samps(const void *buff, size_t num_samps, + size_t sample_offset, const io_type_t io_type, + otw_type_t otw_type); + bool conditional_buff_commit(bool force); + bool check_underrun(usrp_ctrl::sptr ctrl_if, + size_t poll_interval, bool force); + + //recv transport management + bool get_recv_buffer(zero_copy_if::sptr zc_if); + size_t copy_convert_recv_samps(void *buff, size_t num_samps, + size_t sample_offset, const io_type_t io_type, + otw_type_t otw_type); + bool check_overrun(usrp_ctrl::sptr ctrl_if, + size_t poll_interval, bool force); }; -usrp1_impl::io_impl::io_impl(zero_copy_if::sptr zc_if) - : packet_handler_recv_state(1), data_transport(zc_if), - tx_underrun_count(0), rx_overrun_count(0) +usrp1_impl::io_impl::io_impl() { - /* NOP */ + send_state.send_buff = uhd::transport::managed_send_buffer::sptr(); + recv_state.recv_buff = uhd::transport::managed_recv_buffer::sptr(); } usrp1_impl::io_impl::~io_impl(void) @@ -87,12 +99,94 @@ void usrp1_impl::io_init(void) _tx_otw_type.shift = 0; _tx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transport)); + _io_impl = UHD_PIMPL_MAKE(io_impl, ()); } /*********************************************************************** * Data Send **********************************************************************/ +bool usrp1_impl::io_impl::get_send_buffer(zero_copy_if::sptr zc_if) +{ + if (send_state.send_buff == NULL) { + + send_state.send_buff = zc_if->get_send_buff(); + if (send_state.send_buff == NULL) + return false; + + send_state.bytes_free = send_state.send_buff->size(); + send_state.bytes_written = 0; + } + + return true; +} + +size_t usrp1_impl::io_impl::copy_convert_send_samps(const void *buff, + size_t num_samps, + size_t sample_offset, + const io_type_t io_type, + otw_type_t otw_type) +{ + UHD_ASSERT_THROW(send_state.bytes_free % otw_type.get_sample_size() == 0); + + size_t samps_free = send_state.bytes_free / otw_type.get_sample_size(); + size_t copy_samps = std::min(num_samps - sample_offset, samps_free); + + const boost::uint8_t *io_mem = + reinterpret_cast(buff); + + boost::uint8_t *otw_mem = send_state.send_buff->cast(); + + convert_io_type_to_otw_type(io_mem + sample_offset * io_type.size, + io_type, + otw_mem + send_state.bytes_written, + otw_type, + copy_samps); + + send_state.bytes_written += copy_samps * otw_type.get_sample_size(); + send_state.bytes_free -= copy_samps * otw_type.get_sample_size(); + send_state.underrun_poll_samp_count += copy_samps; + + return copy_samps; +} + +bool usrp1_impl::io_impl::conditional_buff_commit(bool force) +{ + if (send_state.bytes_written % 512) + return false; + + if (force || send_state.bytes_free == 0) { + send_state.send_buff->commit(send_state.bytes_written); + send_state.send_buff = uhd::transport::managed_send_buffer::sptr(); + return true; + } + + return false; +} + +bool usrp1_impl::io_impl::check_underrun(usrp_ctrl::sptr ctrl_if, + size_t poll_interval, + bool force) +{ + unsigned char underrun = 0; + + bool ready_to_poll = send_state.underrun_poll_samp_count > poll_interval; + + if (force || ready_to_poll) { + int ret = ctrl_if->usrp_control_read(VRQ_GET_STATUS, + 0, + GS_TX_UNDERRUN, + &underrun, sizeof(char)); + if (ret < 0) + std::cerr << "USRP: underrun check failed" << std::endl; + if (underrun) + std::cerr << "U" << std::endl; + + send_state.underrun_poll_samp_count = 0; + } + + return (bool) underrun; +} + size_t usrp1_impl::send(const std::vector &buffs, size_t num_samps, const tx_metadata_t &, @@ -104,57 +198,21 @@ size_t usrp1_impl::send(const std::vector &buffs, size_t total_samps_sent = 0; while (total_samps_sent < num_samps) { - - if (_io_impl->send_state.send_buff == NULL) { - _io_impl->send_state.send_buff = _data_transport->get_send_buff(); - if (_io_impl->send_state.send_buff == NULL) { - return 0; - } - _io_impl->send_state.bytes_used = 0; - _io_impl->send_state.bytes_free = _io_impl->send_state.send_buff->size(); - } - - size_t copy_samps = - std::min(num_samps - total_samps_sent, _io_impl->send_state.bytes_free / _tx_otw_type.get_sample_size()); - - const boost::uint8_t *io_mem = - reinterpret_cast(buffs[0]); - - boost::uint8_t *otw_mem = _io_impl->send_state.send_buff->cast(); - - // Type conversion and copy - convert_io_type_to_otw_type( - io_mem + total_samps_sent * io_type.size, - io_type, - otw_mem + _io_impl->send_state.bytes_used, - _tx_otw_type, - copy_samps); - - _io_impl->send_state.bytes_used += copy_samps * _tx_otw_type.get_sample_size(); - _io_impl->send_state.bytes_free -= copy_samps * _tx_otw_type.get_sample_size(); - - if (_io_impl->send_state.bytes_free == 0) { - _io_impl->send_state.send_buff->commit(_io_impl->send_state.bytes_used); - _io_impl->send_state.send_buff = uhd::transport::managed_send_buffer::sptr(); - } - - total_samps_sent += copy_samps; - _io_impl->tx_underrun_count += copy_samps * _tx_otw_type.get_sample_size(); - - //check for underruns - if (!(_io_impl->tx_underrun_count > _tx_dsp_freq * poll_interval * _tx_otw_type.get_sample_size())) { - unsigned char underrun; - int ret = _ctrl_transport->usrp_control_read(VRQ_GET_STATUS, - 0, - GS_TX_UNDERRUN, - &underrun, sizeof(char)); - if (ret < 0) - std::cerr << "error: underrun check failed" << std::endl; - if (underrun) - std::cerr << "U" << std::endl; - - _io_impl->tx_underrun_count = 0; - } + if (!_io_impl->get_send_buffer(_data_transport)) + return 0; + + total_samps_sent += _io_impl->copy_convert_send_samps(buffs[0], + num_samps, + total_samps_sent, + io_type, + _tx_otw_type); + if (total_samps_sent == num_samps) + _io_impl->conditional_buff_commit(true); + else + _io_impl->conditional_buff_commit(false); + + _io_impl->check_underrun(_ctrl_transport, + _tx_samps_per_poll_interval, false); } return total_samps_sent; @@ -163,17 +221,72 @@ size_t usrp1_impl::send(const std::vector &buffs, /*********************************************************************** * Data Recv **********************************************************************/ -void _recv_helper(vrt_packet_handler::recv_state &state) +bool usrp1_impl::io_impl::get_recv_buffer(zero_copy_if::sptr zc_if) +{ + if ((recv_state.recv_buff == NULL) || (recv_state.bytes_avail == 0)) { + + recv_state.recv_buff = zc_if->get_recv_buff(); + if (recv_state.recv_buff == NULL) + return false; + + recv_state.bytes_read = 0; + recv_state.bytes_avail = recv_state.recv_buff->size(); + } + + return true; +} + +size_t usrp1_impl::io_impl::copy_convert_recv_samps(void *buff, + size_t num_samps, + size_t sample_offset, + const io_type_t io_type, + otw_type_t otw_type) +{ + UHD_ASSERT_THROW(recv_state.bytes_avail % otw_type.get_sample_size() == 0); + + size_t samps_avail = recv_state.bytes_avail / otw_type.get_sample_size(); + size_t copy_samps = std::min(num_samps - sample_offset, samps_avail); + + const boost::uint8_t *otw_mem = + recv_state.recv_buff->cast(); + + boost::uint8_t *io_mem = reinterpret_cast(buff); + + convert_otw_type_to_io_type(otw_mem + recv_state.bytes_read, + otw_type, + io_mem + sample_offset * io_type.size, + io_type, + copy_samps); + + recv_state.bytes_read += copy_samps * otw_type.get_sample_size(); + recv_state.bytes_avail -= copy_samps * otw_type.get_sample_size(); + recv_state.overrun_poll_samp_count += copy_samps; + + return copy_samps; +} + +bool usrp1_impl::io_impl::check_overrun(usrp_ctrl::sptr ctrl_if, + size_t poll_interval, + bool force) { - size_t num_packet_words32 = - state.managed_buffs[0]->size() / sizeof(boost::uint32_t); + unsigned char overrun = 0; + + bool ready_to_poll = recv_state.overrun_poll_samp_count > poll_interval; - const boost::uint32_t *data = - state.managed_buffs[0]->cast(); + if (force || ready_to_poll) { + int ret = ctrl_if->usrp_control_read(VRQ_GET_STATUS, + 0, + GS_RX_OVERRUN, + &overrun, sizeof(char)); + if (ret < 0) + std::cerr << "USRP: overrrun check failed" << std::endl; + if (overrun) + std::cerr << "O" << std::endl; + + recv_state.overrun_poll_samp_count = 0; + } - state.copy_buffs[0] = reinterpret_cast(data); - size_t num_payload_bytes = num_packet_words32 * sizeof(boost::uint32_t); - state.size_of_copy_buffs = num_payload_bytes; + return (bool) overrun; } size_t usrp1_impl::recv(const std::vector &buffs, @@ -183,59 +296,23 @@ size_t usrp1_impl::recv(const std::vector &buffs, recv_mode_t, size_t) { - UHD_ASSERT_THROW(_io_impl->packet_handler_recv_state.width == 1); UHD_ASSERT_THROW(buffs.size() == 1); - size_t sent_samps = 0; - size_t nsamps_to_copy = 0;; - - while (sent_samps < num_samps) { - if (_io_impl->packet_handler_recv_state.size_of_copy_buffs == 0) { - _io_impl->packet_handler_recv_state.fragment_offset_in_samps = 0; - _io_impl->packet_handler_recv_state.managed_buffs[0] = - _io_impl->data_transport->get_recv_buff(); - - //timeout or something bad returns zero - if (!_io_impl->packet_handler_recv_state.managed_buffs[0].get()) - return 0; - - _recv_helper(_io_impl->packet_handler_recv_state); - } - - size_t bytes_per_item = _rx_otw_type.get_sample_size(); - size_t nsamps_available = - _io_impl->packet_handler_recv_state.size_of_copy_buffs / bytes_per_item; - nsamps_to_copy = std::min(num_samps, nsamps_available); - size_t bytes_to_copy = nsamps_to_copy * bytes_per_item; - - convert_otw_type_to_io_type( - _io_impl->packet_handler_recv_state.copy_buffs[0], - _rx_otw_type, - reinterpret_cast(buffs[0]) + sent_samps * io_type.size, - io_type, - nsamps_to_copy); - - _io_impl->packet_handler_recv_state.copy_buffs[0] += bytes_to_copy; - _io_impl->packet_handler_recv_state.size_of_copy_buffs -= bytes_to_copy; - _io_impl->rx_overrun_count += nsamps_to_copy; - - sent_samps += nsamps_to_copy; - - //check for overruns - if (_io_impl->rx_overrun_count > (8e6 * poll_interval)) { - unsigned char overrun; - int ret = _ctrl_transport->usrp_control_read(VRQ_GET_STATUS, - 0, - GS_RX_OVERRUN, - &overrun, sizeof(char)); - if (ret < 0) - std::cerr << "error: overrun check failed" << std::endl; - if (overrun) - std::cerr << "O" << std::endl; - - _io_impl->rx_overrun_count = 0; - } + size_t total_samps_recv = 0; + + while (total_samps_recv < num_samps) { + + if (!_io_impl->get_recv_buffer(_data_transport)) + return 0; + + total_samps_recv += _io_impl->copy_convert_recv_samps(buffs[0], + num_samps, + total_samps_recv, + io_type, + _rx_otw_type); + _io_impl->check_overrun(_ctrl_transport, + _rx_samps_per_poll_interval, false); } - return sent_samps; + return total_samps_recv; } diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index f57f9a09a..5934d1779 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -124,6 +124,10 @@ private: void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd); void handle_overrun(size_t); + //underrun and overrun poll intervals + size_t _rx_samps_per_poll_interval; + size_t _tx_samps_per_poll_interval; + //otw types uhd::otw_type_t _rx_otw_type; uhd::otw_type_t _tx_otw_type; -- cgit v1.2.3 From 273a10487699f8c2748a62b55f6f11f34b078f03 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Fri, 27 Aug 2010 11:44:38 -0700 Subject: usrp1: Add TODO comments --- host/lib/usrp/usrp1/dsp_impl.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'host/lib/usrp/usrp1/dsp_impl.cpp') diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index ddd1e811b..ab2eed91c 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -95,6 +95,7 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val) } _rx_dsp_decim = rate; + //TODO Poll every 100ms. Make it selectable? _rx_samps_per_poll_interval = 0.1 * _clock_ctrl->get_master_clock_freq() / rate; _iface->poke32(FR_DECIM_RATE, _rx_dsp_decim/2 - 1); @@ -157,7 +158,11 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key, const wax::obj &val) { switch(key.as()) { - // TODO: Set both codec frequencies until we have duality properties + //TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + // + // Set both codec frequencies until we have duality properties + // + //TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO case DSP_PROP_FREQ_SHIFT: { double new_freq = val.as(); _codec_ctrls[DBOARD_SLOT_A]->set_duc_freq(new_freq); @@ -177,6 +182,8 @@ void usrp1_impl::tx_dsp_set(const wax::obj &key, const wax::obj &val) } _tx_dsp_interp = rate; + + //TODO Poll every 100ms. Make it selectable? _tx_samps_per_poll_interval = 0.1 * _clock_ctrl->get_master_clock_freq() * 2 / rate; _iface->poke32(FR_INTERP_RATE, _tx_dsp_interp / 4 - 1); -- cgit v1.2.3 From ab068598b62b5c05dc56df0e2a2a54cc0b37cdf2 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Thu, 26 Aug 2010 18:42:29 -0700 Subject: usrp1: Fix DDC rate storage value and comments for multiple channel support --- host/lib/usrp/usrp1/dsp_impl.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'host/lib/usrp/usrp1/dsp_impl.cpp') diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp index ab2eed91c..d5a88fa2d 100644 --- a/host/lib/usrp/usrp1/dsp_impl.cpp +++ b/host/lib/usrp/usrp1/dsp_impl.cpp @@ -78,13 +78,23 @@ void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val) switch(key.as()) { case DSP_PROP_FREQ_SHIFT: { double new_freq = val.as(); - _iface->poke32(FR_RX_FREQ_0, - -dsp_type1::calc_cordic_word_and_update(new_freq, _clock_ctrl->get_master_clock_freq())); - _tx_dsp_freq = new_freq; + boost::uint32_t reg_word = dsp_type1::calc_cordic_word_and_update( + new_freq, _clock_ctrl->get_master_clock_freq()); + + //TODO TODO TODO TODO TODO TODO TODO TODO TODO + // + // Handle multiple receive channels / DDC's + // + //TODO TODO TODO TODO TODO TODO TODO TODO TODO + _iface->poke32(FR_RX_FREQ_0, reg_word); + _iface->poke32(FR_RX_FREQ_1, reg_word); + _iface->poke32(FR_RX_FREQ_2, reg_word); + _iface->poke32(FR_RX_FREQ_3, reg_word); + + _rx_dsp_freq = new_freq; return; } case DSP_PROP_HOST_RATE: { - //FIXME: Stop and resume streaming during set? unsigned int rate = _clock_ctrl->get_master_clock_freq() / val.as(); -- cgit v1.2.3