From d91c18e6d061cf4584e271508a7a4475d8224663 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 21 Apr 2010 15:46:16 -0700 Subject: xcvr work, skeleton layout --- host/lib/usrp/dboard/db_rfx.cpp | 2 +- host/lib/usrp/dboard/db_xcvr2450.cpp | 331 +++++++++++++++++++++++++++++++++++ 2 files changed, 332 insertions(+), 1 deletion(-) create mode 100644 host/lib/usrp/dboard/db_xcvr2450.cpp (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index cd5b8447b..76b2c6d7a 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -430,7 +430,7 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ * TX Get and Set **********************************************************************/ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ - wax::obj key; std::string name; + wax::obj key; std::string name; boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp new file mode 100644 index 000000000..7242fd96c --- /dev/null +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -0,0 +1,331 @@ +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + +/*********************************************************************** + * The XCVR 2450 dboard + **********************************************************************/ +static const freq_range_t xcvr_freq_range(2.4e9, 6.0e9); + +class xcvr2450 : public xcvr_dboard_base{ +public: + xcvr2450(ctor_args_t const& args); + ~xcvr2450(void); + + void rx_get(const wax::obj &key, wax::obj &val); + void rx_set(const wax::obj &key, const wax::obj &val); + + void tx_get(const wax::obj &key, wax::obj &val); + void tx_set(const wax::obj &key, const wax::obj &val); + +private: + double _lo_freq; + uhd::dict _tx_gains, _rx_gains; + std::string _tx_ant, _rx_ant; + + void set_lo_freq(double target_freq){} + void set_tx_ant(const std::string &ant){} + void set_rx_ant(const std::string &ant){} + void set_tx_gain(float gain, const std::string &name){} + void set_rx_gain(float gain, const std::string &name){} +}; + +/*********************************************************************** + * Register the XCVR dboard + **********************************************************************/ +static dboard_base::sptr make_xcvr2450(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new xcvr2450(args)); +} + +UHD_STATIC_BLOCK(reg_xcvr2450_dboard){ + //register the factory function for the rx and tx dbids + dboard_manager::register_dboard(0x0060, &make_xcvr2450, "XCVR2450 TX"); + dboard_manager::register_dboard(0x0061, &make_xcvr2450, "XCVR2450 RX"); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +xcvr2450::xcvr2450(ctor_args_t const& args) : xcvr_dboard_base(args){ + /* NOP */ +} + +xcvr2450::~xcvr2450(void){ + /* NOP */ +} + +/*********************************************************************** + * Antenna Handling + **********************************************************************/ +static const prop_names_t xcvr_antennas = list_of("J1")("J2"); + +/*********************************************************************** + * Gain Handling + **********************************************************************/ +static const uhd::dict xcvr_tx_gain_ranges = map_list_of + ("VGA", gain_range_t(0, 30, 0.5)) +; +static const uhd::dict xcvr_rx_gain_ranges = map_list_of + ("RF LNA", gain_range_t(0, 30.5, 15)) + ("BB VGA", gain_range_t(0, 62, 2.0)) +; + +/*! + * Convert a requested gain for the tx 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 6 bit the register value + */ +static int gain_to_tx_vga_reg(float &gain){ + //calculate the register value + int reg = std::clip(boost::math::iround(gain*60/30.0) + 3, 0, 63); + + //calculate the actual gain value + if (reg < 4) gain = 0; + else if (reg < 48) gain = reg/2 - 1; + else gain = reg/2.0 - 1.5; + + //return register value + return reg; +} + +/*! + * Convert a requested gain for the rx 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 + */ +static int gain_to_rx_bb_vga_reg(float &gain){ + int reg = std::clip(boost::math::iround(gain/2.0), 0, 31); + gain = reg*2; + return reg; +} + +/*! + * Convert a requested gain for the rx lna 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 2 bit the register value + */ +static int gain_to_rx_rf_lna_reg(float &gain){ + int reg = std::clip(boost::math::iround(gain*2/30.5) + 1, 0, 3); + switch(reg){ + case 0: + case 1: gain = 0; break; + case 2: gain = 15; break; + case 3: gain = 30.5; break; + } + return reg; +} + +/*********************************************************************** + * RX Get and Set + **********************************************************************/ +void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_NAME: + val = dboard_id::to_string(get_rx_id()); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + assert_has(_rx_gains.keys(), name, "xcvr rx gain name"); + val = _rx_gains[name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(xcvr_rx_gain_ranges.keys(), name, "xcvr rx gain name"); + val = xcvr_rx_gain_ranges[name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(xcvr_rx_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = _lo_freq; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = xcvr_freq_range; + return; + + case SUBDEV_PROP_ANTENNA: + val = _rx_ant; + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = xcvr_antennas; + return; + + case SUBDEV_PROP_QUADRATURE: + val = true; + return; + + case SUBDEV_PROP_IQ_SWAPPED: + val = false; + return; + + case SUBDEV_PROP_SPECTRUM_INVERTED: + val = false; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = false; + return; + } +} + +void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + + case SUBDEV_PROP_FREQ: + this->set_lo_freq(val.as()); + return; + + case SUBDEV_PROP_GAIN: + this->set_rx_gain(val.as(), name); + return; + + case SUBDEV_PROP_ANTENNA: + this->set_rx_ant(val.as()); + return; + + default: + throw std::runtime_error(str(boost::format( + "Error: trying to set read-only property on %s subdev" + ) % dboard_id::to_string(get_rx_id()))); + } +} + +/*********************************************************************** + * TX Get and Set + **********************************************************************/ +void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_NAME: + val = dboard_id::to_string(get_tx_id()); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + assert_has(_tx_gains.keys(), name, "xcvr tx gain name"); + val = _tx_gains[name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(xcvr_tx_gain_ranges.keys(), name, "xcvr tx gain name"); + val = xcvr_tx_gain_ranges[name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(xcvr_tx_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = _lo_freq; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = xcvr_freq_range; + return; + + case SUBDEV_PROP_ANTENNA: + val = _tx_ant; + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = xcvr_antennas; + return; + + case SUBDEV_PROP_QUADRATURE: + val = true; + return; + + case SUBDEV_PROP_IQ_SWAPPED: + val = true; + return; + + case SUBDEV_PROP_SPECTRUM_INVERTED: + val = false; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = false; + return; + } +} + +void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + + case SUBDEV_PROP_FREQ: + set_lo_freq(val.as()); + return; + + case SUBDEV_PROP_GAIN: + this->set_tx_gain(val.as(), name); + return; + + case SUBDEV_PROP_ANTENNA: + this->set_tx_ant(val.as()); + return; + + default: + throw std::runtime_error(str(boost::format( + "Error: trying to set read-only property on %s subdev" + ) % dboard_id::to_string(get_tx_id()))); + } +} -- cgit v1.2.3 From d73db2cc560f975512db7748f0e82865285c76e8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 21 Apr 2010 18:40:53 -0700 Subject: work on atr registers and filling in functions --- host/lib/usrp/dboard/db_xcvr2450.cpp | 122 +++++++++++++++++++++++++++++++---- 1 file changed, 108 insertions(+), 14 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 7242fd96c..3f00b2539 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -15,6 +15,38 @@ // along with this program. If not, see . // +// TX IO Pins +#define HB_PA_OFF_TXIO (1 << 15) // 5GHz PA, 1 = off, 0 = on +#define LB_PA_OFF_TXIO (1 << 14) // 2.4GHz PA, 1 = off, 0 = on +#define ANTSEL_TX1_RX2_TXIO (1 << 13) // 1 = Ant 1 to TX, Ant 2 to RX +#define ANTSEL_TX2_RX1_TXIO (1 << 12) // 1 = Ant 2 to TX, Ant 1 to RX +#define TX_EN_TXIO (1 << 11) // 1 = TX on, 0 = TX off +#define AD9515DIV_TXIO (1 << 4) // 1 = Div by 3, 0 = Div by 2 + +#define TXIO_MASK (HB_PA_OFF_TXIO | LB_PA_OFF_TXIO | ANTSEL_TX1_RX2_TXIO | ANTSEL_TX2_RX1_TXIO | TX_EN_TXIO | AD9515DIV_TXIO) + +// TX IO Functions +#define HB_PA_TXIO LB_PA_OFF_TXIO +#define LB_PA_TXIO HB_PA_OFF_TXIO +#define TX_ENB_TXIO TX_EN_TXIO +#define TX_DIS_TXIO 0 +#define AD9515DIV_3_TXIO AD9515DIV_TXIO +#define AD9515DIV_2_TXIO 0 + +// RX IO Pins +#define LOCKDET_RXIO (1 << 15) // This is an INPUT!!! +#define EN_RXIO (1 << 14) +#define RX_EN_RXIO (1 << 13) // 1 = RX on, 0 = RX off +#define RX_HP_RXIO (1 << 12) // 0 = Fc set by rx_hpf, 1 = 600 KHz + +#define RXIO_MASK (EN_RXIO | RX_EN_RXIO | RX_HP_RXIO) + +// RX IO Functions +#define ALL_ENB_RXIO EN_RXIO +#define ALL_DIS_RXIO 0 +#define RX_ENB_RXIO RX_EN_RXIO +#define RX_DIS_RXIO 0 + #include #include #include @@ -52,12 +84,15 @@ private: double _lo_freq; uhd::dict _tx_gains, _rx_gains; std::string _tx_ant, _rx_ant; + int _ad9515div; + + void set_lo_freq(double target_freq); + void set_tx_ant(const std::string &ant); + void set_rx_ant(const std::string &ant); + void set_tx_gain(float gain, const std::string &name); + void set_rx_gain(float gain, const std::string &name); - void set_lo_freq(double target_freq){} - void set_tx_ant(const std::string &ant){} - void set_rx_ant(const std::string &ant){} - void set_tx_gain(float gain, const std::string &name){} - void set_rx_gain(float gain, const std::string &name){} + void update_atr(void); }; /*********************************************************************** @@ -77,18 +112,69 @@ UHD_STATIC_BLOCK(reg_xcvr2450_dboard){ * Structors **********************************************************************/ xcvr2450::xcvr2450(ctor_args_t const& args) : xcvr_dboard_base(args){ - /* NOP */ + //enable only the clocks we need + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + + //set the gpio directions + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TXIO_MASK); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RXIO_MASK); + + //set defaults for LO, gains, antennas + set_lo_freq(2.45e9); + set_rx_ant("J1"); + set_tx_ant("J2"); + set_rx_gain(0, "RF LNA"); + set_rx_gain(0, "BB VGA"); + set_tx_gain(0, "VGA"); } xcvr2450::~xcvr2450(void){ /* NOP */ } +void xcvr2450::update_atr(void){ + //calculate tx atr pins + int band_sel = (_lo_freq > 4e9)? HB_PA_TXIO : LB_PA_TXIO; + int tx_ant_sel = (_tx_ant == "J1")? ANTSEL_TX1_RX2_TXIO : ANTSEL_TX2_RX1_TXIO; + int rx_ant_sel = (_rx_ant == "J1")? ANTSEL_TX1_RX2_TXIO : ANTSEL_TX2_RX1_TXIO; + int ad9515div = (_ad9515div == 3)? AD9515DIV_3_TXIO : AD9515DIV_2_TXIO; + + //set the tx registers + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, band_sel | ad9515div | TX_DIS_TXIO); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, band_sel | ad9515div | TX_DIS_TXIO | rx_ant_sel); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, band_sel | ad9515div | TX_ENB_TXIO | tx_ant_sel); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, band_sel | ad9515div | TX_ENB_TXIO); + + //set the rx registers + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, ALL_ENB_RXIO | RX_DIS_RXIO); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, ALL_ENB_RXIO | RX_ENB_RXIO); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, ALL_ENB_RXIO | RX_DIS_RXIO); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, ALL_ENB_RXIO | RX_ENB_RXIO); +} + +/*********************************************************************** + * Tuning + **********************************************************************/ +void xcvr2450::set_lo_freq(double target_freq){ + //TODO + //set _ad9515div +} + /*********************************************************************** * Antenna Handling **********************************************************************/ static const prop_names_t xcvr_antennas = list_of("J1")("J2"); +void xcvr2450::set_tx_ant(const std::string &ant){ + assert_has(xcvr_antennas, ant, "xcvr antenna name"); + //TODO +} + +void xcvr2450::set_rx_ant(const std::string &ant){ + assert_has(xcvr_antennas, ant, "xcvr antenna name"); + //TODO +} + /*********************************************************************** * Gain Handling **********************************************************************/ @@ -148,6 +234,16 @@ static int gain_to_rx_rf_lna_reg(float &gain){ return reg; } +void xcvr2450::set_tx_gain(float gain, const std::string &name){ + assert_has(xcvr_tx_gain_ranges.keys(), name, "xcvr tx gain name"); + //TODO +} + +void xcvr2450::set_rx_gain(float gain, const std::string &name){ + assert_has(xcvr_rx_gain_ranges.keys(), name, "xcvr rx gain name"); + //TODO +} + /*********************************************************************** * RX Get and Set **********************************************************************/ @@ -232,10 +328,9 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ this->set_rx_ant(val.as()); return; - default: - throw std::runtime_error(str(boost::format( - "Error: trying to set read-only property on %s subdev" - ) % dboard_id::to_string(get_rx_id()))); + default: throw std::runtime_error(str(boost::format( + "Error: trying to set read-only property on %s subdev" + ) % dboard_id::to_string(get_rx_id()))); } } @@ -323,9 +418,8 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ this->set_tx_ant(val.as()); return; - default: - throw std::runtime_error(str(boost::format( - "Error: trying to set read-only property on %s subdev" - ) % dboard_id::to_string(get_tx_id()))); + default: throw std::runtime_error(str(boost::format( + "Error: trying to set read-only property on %s subdev" + ) % dboard_id::to_string(get_tx_id()))); } } -- cgit v1.2.3 From 70b6144543596816e5df19009777294ce5e500ae Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 22 Apr 2010 12:04:00 -0700 Subject: added dboard app notes --- host/docs/CMakeLists.txt | 4 ++- host/docs/dboards.rst | 64 ++++++++++++++++++++++++++++++++++++ host/docs/index.rst | 12 ++++--- host/docs/style.css | 4 +-- host/docs/usrp2.rst | 8 ++--- host/lib/usrp/dboard/db_xcvr2450.cpp | 3 +- 6 files changed, 82 insertions(+), 13 deletions(-) create mode 100644 host/docs/dboards.rst (limited to 'host/lib/usrp') diff --git a/host/docs/CMakeLists.txt b/host/docs/CMakeLists.txt index 1bbd52fee..61eede8b7 100644 --- a/host/docs/CMakeLists.txt +++ b/host/docs/CMakeLists.txt @@ -22,6 +22,7 @@ SET(manual_sources index.rst build.rst coding.rst + dboards.rst usrp2.rst ) @@ -38,8 +39,9 @@ ELSE(${RST2HTML} STREQUAL "RST2HTML-NOTFOUND") MESSAGE(STATUS " Enabled generation of HTML manual.") #setup rst2html options + SET(stylesheet ${CMAKE_CURRENT_SOURCE_DIR}/style.css) SET(rst2html_options - --stylesheet=${CMAKE_CURRENT_SOURCE_DIR}/style.css + --stylesheet=${stylesheet} --no-toc-backlinks --date --time ) diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst new file mode 100644 index 000000000..d08b752a6 --- /dev/null +++ b/host/docs/dboards.rst @@ -0,0 +1,64 @@ +======================================================================== +UHD - Daughterboard Application Notes +======================================================================== + +.. contents:: Table of Contents + +------------------------------------------------------------------------ +Daughterboard Properties +------------------------------------------------------------------------ + +The following contains interesting notes about each daughterboard. +Eventually, this page will be expanded to list out the full +properties of each board as well. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Basic RX and and LFRX +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The Basic RX and LFRX boards have 3 subdevices: + +* **Subdevice A:** real signal on antenna RXA +* **Subdevice B:** real signal on antenna RXB +* **Subdevice AB:** quadrature subdevice using both antennas + +The boards have no tunable elements or programmable gains. +Though the magic of aliasing, you can down-convert signals +greater than the nyquist rate of the ADC. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Basic TX and and LFTX +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The Basic TX and LFTX boards have 1 quadrature subdevice using both antennas. + +The boards have no tunable elements or programmable gains. +Though the magic of aliasing, you can up-convert signals +greater than the nyquist rate of the DAC. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +RFX Series +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Transmit Antennas: **TX/RX** + +Receive Antennas: **TX/RX** or **RX2** + +The user may set the receive antenna to be TX/RX or RX2. +However, when using an RFX board in full-duplex mode, +the receive antenna will always be set to RX2, regardless of the settings. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +XCVR 2450 +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The XCVR2450 has a non-contiguous tuning range consiting of a high band and a low band. +The high band consists of frequencies between...TODO + +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. diff --git a/host/docs/index.rst b/host/docs/index.rst index 37853b0b6..3dc7a2d98 100644 --- a/host/docs/index.rst +++ b/host/docs/index.rst @@ -13,17 +13,19 @@ Contents ------------------------------------------------------------------------ ^^^^^^^^^^^^^^^^^^^^^ -API Documentation +Building the UHD ^^^^^^^^^^^^^^^^^^^^^ -* `Doxygen <./../../doxygen/html/index.html>`_ -* `Using the API <./coding.html>`_ +* `Build Guide <./build.html>`_ ^^^^^^^^^^^^^^^^^^^^^ Supported Devices ^^^^^^^^^^^^^^^^^^^^^ * `USRP2 App Notes <./usrp2.html>`_ +* `Daughterboard App Notes <./dboards.html>`_ ^^^^^^^^^^^^^^^^^^^^^ -Building the UHD +API Documentation ^^^^^^^^^^^^^^^^^^^^^ -* `Build Guide <./build.html>`_ +* `Doxygen <./../../doxygen/html/index.html>`_ +* `Using the API <./coding.html>`_ + diff --git a/host/docs/style.css b/host/docs/style.css index 7bd84c9c7..bf97bf007 100644 --- a/host/docs/style.css +++ b/host/docs/style.css @@ -1,8 +1,8 @@ body{ font-family:Arial, Helvetica, sans-serif; -font-size:10pt; +font-size:11pt; color:black; -background-color:#FEFEFE; +background-color:white; width:90%; margin:0 auto 0 auto; } diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index 48ef60683..32e7374c8 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -1,5 +1,5 @@ ======================================================================== -UHD - USRP2 App Notes +UHD - USRP2 Application Notes ======================================================================== .. contents:: Table of Contents @@ -36,7 +36,7 @@ Run the following commands: cd /firmware/microblaze ./boostrap - ./configure host=mb + ./configure --host=mb make *The image file will be ./apps/txrx.bin* @@ -112,7 +112,7 @@ Run the following commands: :: cd /share/uhd/utils - ./usrp2 recovery.py --ifc=eth0 --new-ip=192.168.10.3 + ./usrp2_recovery.py --ifc=eth0 --new-ip=192.168.10.3 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Debugging networking problems @@ -125,4 +125,4 @@ The microcontroller prints useful information about IP addresses, MAC addresses, control packets, and fast-path settings. **Monitor the host network traffic:** -Use wireshark to monitor packets send to and received from the USRP2. +Use wireshark to monitor packets sent to and received from the USRP2. diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 3f00b2539..44921d7d4 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -137,13 +137,14 @@ void xcvr2450::update_atr(void){ int band_sel = (_lo_freq > 4e9)? HB_PA_TXIO : LB_PA_TXIO; int tx_ant_sel = (_tx_ant == "J1")? ANTSEL_TX1_RX2_TXIO : ANTSEL_TX2_RX1_TXIO; int rx_ant_sel = (_rx_ant == "J1")? ANTSEL_TX1_RX2_TXIO : ANTSEL_TX2_RX1_TXIO; + int xx_ant_sel = tx_ant_sel; //prefer the tx antenna selection for full duplex (rx will get the other antenna) int ad9515div = (_ad9515div == 3)? AD9515DIV_3_TXIO : AD9515DIV_2_TXIO; //set the tx registers this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, band_sel | ad9515div | TX_DIS_TXIO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, band_sel | ad9515div | TX_DIS_TXIO | rx_ant_sel); this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, band_sel | ad9515div | TX_ENB_TXIO | tx_ant_sel); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, band_sel | ad9515div | TX_ENB_TXIO); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, band_sel | ad9515div | TX_ENB_TXIO | xx_ant_sel); //set the rx registers this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, ALL_ENB_RXIO | RX_DIS_RXIO); -- cgit v1.2.3 From fd1067907d6e19249129d52bb7dcfd3f7b21d7d1 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 22 Apr 2010 15:55:01 -0700 Subject: added regs for max2829 --- host/README | 1 + host/lib/CMakeLists.txt | 5 + host/lib/ic_reg_maps/gen_max2829_regs.py | 169 +++++++++++++++++++++++++++++++ host/lib/usrp/dboard/db_xcvr2450.cpp | 29 +++--- 4 files changed, 192 insertions(+), 12 deletions(-) create mode 100755 host/lib/ic_reg_maps/gen_max2829_regs.py (limited to 'host/lib/usrp') diff --git a/host/README b/host/README index 05a53b197..e67bb25f8 100644 --- a/host/README +++ b/host/README @@ -16,6 +16,7 @@ Basic TX LF RX LF TX RFX Series +XCVR 2450 ######################################################################## # Documentation diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index d43a61010..5495620ec 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -111,6 +111,11 @@ UHD_PYTHON_GEN_SOURCE_FILE( ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/ad7922_regs.hpp ) +UHD_PYTHON_GEN_SOURCE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/gen_max2829_regs.py + ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/max2829_regs.hpp +) + ######################################################################## # Add dboard sources ######################################################################## diff --git a/host/lib/ic_reg_maps/gen_max2829_regs.py b/host/lib/ic_reg_maps/gen_max2829_regs.py new file mode 100755 index 000000000..91a711ecc --- /dev/null +++ b/host/lib/ic_reg_maps/gen_max2829_regs.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python +# +# Copyright 2008,2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio 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 asversion 3, or (at your option) +# any later version. +# +# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +import sys +from common import * + +######################################################################## +# Template for raw text data describing registers +# name addr[bit range inclusive] default optional enums +######################################################################## +REGS_DATA_TMPL="""\ +######################################################################## +## Note: offsets given from perspective of data bits (excludes address) +######################################################################## +## +######################################################################## +## Standby (2) +######################################################################## +_set_to_1_2_0 2[0] 1 +_set_to_1_2_1 2[1] 1 +_set_to_1_2_2 2[2] 1 +pa_bias_dac 2[10] 0 +voltage_ref 2[11] 0 +_set_to_1_2_12 2[12] 1 +mimo_select 2[13] 0 normal, mimo +######################################################################## +## Integer Divider Ratio (3) +######################################################################## +id_ratio_word 3[0:7] a2 +frac_div_ratio_lsb 3[12:13] 0 +######################################################################## +## Fractional Divider Ratio (4) +######################################################################## +frac_div_ratio_msb 4[0:13] 0 +######################################################################## +## Band Select and PLL (5) +######################################################################## +band_select 5[0] 0 2_4ghz, 5ghz +ref_divider 5[1:3] 1 +pll_cp_select 5[5] 1 2ma, 4ma +band_select_802_11a 5[6] 0 4_9ghz_to_5_35ghz, 5_47ghz_to_5_875ghz +vco_bandswitch 5[7] 0 disable, automatic +vco_spi_bandswitch 5[8] 0 fsm, spi +vco_sub_band 5[9:10] 0 +_set_to_1_5_11 5[11] 1 +_set_to_1_5_12 5[12] 1 +band_sel_mimo 5[13] 0 normal, mimo +######################################################################## +## Calibration (6) +######################################################################## +rx_cal_mode 6[0] 0 dis, enb +tx_cal_mode 6[1] 0 dis, enb +_set_to_1_6_10 6[10] 1 +iq_cal_gain 6[11:12] 3 8db, 18db, 24db, 34db +######################################################################## +## Lopass Filter (7) +######################################################################## +rx_lpf_fine_adj 7[0:2] 2 90, 95, 100, 105, 110 +rx_lpf_coarse_adj 7[3:4] 1 7_5mhz, 9_5mhz, 14mhz, 18mhz +tx_lpf_coarse_adj 7[5:6] 1 12mhz=1, 18mhz=2, 24mhz=3 +rssi_high_bw 7[11] 0 2mhz, 6mhz +######################################################################## +## Rx Control/RSSI (8) +######################################################################## +_set_to_1_8_0 8[0] 1 +rx_highpass 8[2] 1 100hz, 30khz +_set_to_1_8_5 8[5] 1 +rssi_pin_fcn 8[8] 0 rssi, temp +rssi_op_mode 8[10] 0 rssi_rxhp, enabled +rssi_output_range 8[11] 0 low, high +rx_vga_gain_spi 8[12] 0 io, spi +######################################################################## +## Tx Linearity/Baseband Gain (9) +######################################################################## +tx_baseband_gain 9[0:1] 0 0db, 2db, 3_5db, 5db +tx_upconv_linearity 9[2:3] 0 50, 63, 78, 100 +tx_vga_linearity 9[6:7] 0 50, 63, 78, 100 +pa_driver_linearity 9[8:9] 2 50, 63, 78, 100 +tx_vga_gain_spi 9[10] 0 io, spi +######################################################################## +## PA Bias DAC (10) +######################################################################## +pa_bias_dac_out_curr a[0:5] 0 +pa_bias_dac_delay a[6:9] f +######################################################################## +## Rx Gain (11) +######################################################################## +rx_vga_gain b[0:4] 1f +rx_lna_gain b[5:6] 3 +######################################################################## +## Tx VGA Gain (12) +######################################################################## +tx_vga_gain c[0:5] 0 +""" + +######################################################################## +# Header and Source templates below +######################################################################## +HEADER_TEXT=""" +#import time + +/*********************************************************************** + * This file was generated by $file on $time.strftime("%c") + **********************************************************************/ + +\#ifndef INCLUDED_MAX2829_REGS_HPP +\#define INCLUDED_MAX2829_REGS_HPP + +\#include + +struct max2829_regs_t{ +#for $reg in $regs + #if $reg.get_enums() + enum $(reg.get_name())_t{ + #for $i, $enum in enumerate($reg.get_enums()) + #set $end_comma = ',' if $i < len($reg.get_enums())-1 else '' + $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma + #end for + } $reg.get_name(); + #else + boost::$reg.get_stdint_type() $reg.get_name(); + #end if +#end for + + max2829_regs_t(void){ +#for $reg in $regs + $reg.get_name() = $reg.get_default(); +#end for + } + + boost::uint32_t get_reg(boost::uint8_t addr){ + boost::uint16_t reg = 0; + switch(addr){ + #for $addr in range(2, 12+1) + case $addr: + #for $reg in filter(lambda r: r.get_addr() == addr, $regs) + reg |= (boost::uint16_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); + #end for + break; + #end for + } + return (boost::uint32_t(reg) << 4) | (addr & 0xf); + } +}; + +\#endif /* INCLUDED_MAX2829_REGS_HPP */ +""" + +if __name__ == '__main__': + regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines()) + open(sys.argv[1], 'w').write(parse_tmpl(HEADER_TEXT, regs=regs, file=__file__)) diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 44921d7d4..8002acc01 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -47,6 +47,7 @@ #define RX_ENB_RXIO RX_EN_RXIO #define RX_DIS_RXIO 0 +#include "max2829_regs.hpp" #include #include #include @@ -65,10 +66,23 @@ using namespace uhd::usrp; using namespace boost::assign; /*********************************************************************** - * The XCVR 2450 dboard + * The XCVR 2450 constants **********************************************************************/ static const freq_range_t xcvr_freq_range(2.4e9, 6.0e9); +static const prop_names_t xcvr_antennas = list_of("J1")("J2"); + +static const uhd::dict xcvr_tx_gain_ranges = map_list_of + ("VGA", gain_range_t(0, 30, 0.5)) +; +static const uhd::dict xcvr_rx_gain_ranges = map_list_of + ("RF LNA", gain_range_t(0, 30.5, 15)) + ("BB VGA", gain_range_t(0, 62, 2.0)) +; + +/*********************************************************************** + * The XCVR 2450 dboard class + **********************************************************************/ class xcvr2450 : public xcvr_dboard_base{ public: xcvr2450(ctor_args_t const& args); @@ -85,6 +99,7 @@ private: uhd::dict _tx_gains, _rx_gains; std::string _tx_ant, _rx_ant; int _ad9515div; + max2829_regs_t _max2829_regs; void set_lo_freq(double target_freq); void set_tx_ant(const std::string &ant); @@ -96,7 +111,7 @@ private: }; /*********************************************************************** - * Register the XCVR dboard + * Register the XCVR 2450 dboard **********************************************************************/ static dboard_base::sptr make_xcvr2450(dboard_base::ctor_args_t const& args){ return dboard_base::sptr(new xcvr2450(args)); @@ -164,8 +179,6 @@ void xcvr2450::set_lo_freq(double target_freq){ /*********************************************************************** * Antenna Handling **********************************************************************/ -static const prop_names_t xcvr_antennas = list_of("J1")("J2"); - void xcvr2450::set_tx_ant(const std::string &ant){ assert_has(xcvr_antennas, ant, "xcvr antenna name"); //TODO @@ -179,14 +192,6 @@ void xcvr2450::set_rx_ant(const std::string &ant){ /*********************************************************************** * Gain Handling **********************************************************************/ -static const uhd::dict xcvr_tx_gain_ranges = map_list_of - ("VGA", gain_range_t(0, 30, 0.5)) -; -static const uhd::dict xcvr_rx_gain_ranges = map_list_of - ("RF LNA", gain_range_t(0, 30.5, 15)) - ("BB VGA", gain_range_t(0, 62, 2.0)) -; - /*! * Convert a requested gain for the tx vga into the integer register value. * The gain passed into the function will be set to the actual value. -- cgit v1.2.3 From 3551ef506737576d15b86b151bce3ae225d36092 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 22 Apr 2010 18:18:44 -0700 Subject: filled in xcvr tuning, set gain, spi reset --- host/lib/ic_reg_maps/gen_max2829_regs.py | 2 +- host/lib/usrp/dboard/db_xcvr2450.cpp | 165 ++++++++++++++++++++++++++++--- 2 files changed, 152 insertions(+), 15 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/ic_reg_maps/gen_max2829_regs.py b/host/lib/ic_reg_maps/gen_max2829_regs.py index 91a711ecc..46b48dfe7 100755 --- a/host/lib/ic_reg_maps/gen_max2829_regs.py +++ b/host/lib/ic_reg_maps/gen_max2829_regs.py @@ -44,7 +44,7 @@ mimo_select 2[13] 0 normal, mimo ######################################################################## ## Integer Divider Ratio (3) ######################################################################## -id_ratio_word 3[0:7] a2 +int_div_ratio_word 3[0:7] a2 frac_div_ratio_lsb 3[12:13] 0 ######################################################################## ## Fractional Divider Ratio (4) diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 8002acc01..fbce4b932 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -68,16 +68,19 @@ using namespace boost::assign; /*********************************************************************** * The XCVR 2450 constants **********************************************************************/ +static const bool xcvr2450_debug = true; + static const freq_range_t xcvr_freq_range(2.4e9, 6.0e9); static const prop_names_t xcvr_antennas = list_of("J1")("J2"); static const uhd::dict xcvr_tx_gain_ranges = map_list_of ("VGA", gain_range_t(0, 30, 0.5)) + ("BB", gain_range_t(0, 5, 1.5)) ; static const uhd::dict xcvr_rx_gain_ranges = map_list_of - ("RF LNA", gain_range_t(0, 30.5, 15)) - ("BB VGA", gain_range_t(0, 62, 2.0)) + ("LNA", gain_range_t(0, 30.5, 15)) + ("VGA", gain_range_t(0, 62, 2.0)) ; /*********************************************************************** @@ -108,6 +111,14 @@ private: void set_rx_gain(float gain, const std::string &name); void update_atr(void); + void spi_reset(void); + void send_reg(boost::uint8_t addr){ + this->get_iface()->write_spi( + dboard_iface::UNIT_RX, + spi_config_t::EDGE_RISE, + _max2829_regs.get_reg(addr), 24 + ); + } }; /*********************************************************************** @@ -134,22 +145,54 @@ xcvr2450::xcvr2450(ctor_args_t const& args) : xcvr_dboard_base(args){ this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TXIO_MASK); this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RXIO_MASK); + spi_reset(); //prepare the spi + + //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; + _max2829_regs.pll_cp_select = max2829_regs_t::PLL_CP_SELECT_4MA; + _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_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; + _max2829_regs.rssi_pin_fcn = max2829_regs_t::RSSI_PIN_FCN_RSSI; + _max2829_regs.rx_highpass = max2829_regs_t::RX_HIGHPASS_100HZ; + _max2829_regs.tx_vga_gain_spi = max2829_regs_t::TX_VGA_GAIN_SPI_SPI; + _max2829_regs.pa_driver_linearity = max2829_regs_t::PA_DRIVER_LINEARITY_78; + _max2829_regs.tx_vga_linearity = max2829_regs_t::TX_VGA_LINEARITY_78; + _max2829_regs.tx_upconv_linearity = max2829_regs_t::TX_UPCONV_LINEARITY_78; + + //send initial register settings + for(boost::uint8_t reg = 0; reg <= 0xC; reg++){ + this->send_reg(reg); + } + //set defaults for LO, gains, antennas set_lo_freq(2.45e9); set_rx_ant("J1"); set_tx_ant("J2"); - set_rx_gain(0, "RF LNA"); - set_rx_gain(0, "BB VGA"); + set_rx_gain(0, "LNA"); + set_rx_gain(0, "VGA"); set_tx_gain(0, "VGA"); + set_tx_gain(0, "BB"); } xcvr2450::~xcvr2450(void){ - /* NOP */ + spi_reset(); +} + +void xcvr2450::spi_reset(void){ + //spi reset mode: global enable = off, tx and rx enable = on + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, TX_ENB_TXIO); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, RX_ENB_RXIO); } void xcvr2450::update_atr(void){ //calculate tx atr pins - int band_sel = (_lo_freq > 4e9)? HB_PA_TXIO : LB_PA_TXIO; + int band_sel = (_lo_freq > 3e9)? HB_PA_TXIO : LB_PA_TXIO; int tx_ant_sel = (_tx_ant == "J1")? ANTSEL_TX1_RX2_TXIO : ANTSEL_TX2_RX1_TXIO; int rx_ant_sel = (_rx_ant == "J1")? ANTSEL_TX1_RX2_TXIO : ANTSEL_TX2_RX1_TXIO; int xx_ant_sel = tx_ant_sel; //prefer the tx antenna selection for full duplex (rx will get the other antenna) @@ -172,8 +215,57 @@ void xcvr2450::update_atr(void){ * Tuning **********************************************************************/ void xcvr2450::set_lo_freq(double target_freq){ - //TODO - //set _ad9515div + //variables used in the calculation below + double scaler = (_lo_freq > 3e9)? (4.0/5.0) : (4.0/3.0); + double ref_freq = this->get_iface()->get_clock_rate(dboard_iface::UNIT_TX); + int R, intdiv, fracdiv; + + //loop through values until we get a match + for(R = 1; R <= 7; R++){ + for(_ad9515div = 2; _ad9515div <= 3; _ad9515div++){ + double N = (target_freq*scaler*R*_ad9515div)/ref_freq; + intdiv = int(std::floor(N)); + fracdiv = (N - intdiv)*double(1 << 16); + //actual minimum is 128, but most chips seems to require higher to lock + if (intdiv < 131 or intdiv > 255) continue; + //constraints met: exit loop + goto done_loop; + } + } done_loop: + + //calculate the actual freq from the values above + double N = double(intdiv) + double(fracdiv)/double(1 << 16); + _lo_freq = (scaler*R*_ad9515div)/(N*ref_freq); + + if (xcvr2450_debug) std::cerr << boost::format( + "XCVR2450 tune: R=%d, N=%f, ad9515=%d, scaler=%f\n" + " Target Freq=%fMHz, Actual Freq=%fMHz" + ) % R % N % _ad9515div % scaler % (target_freq/1e6) % (_lo_freq/1e6) << std::endl; + + //high-high band or low-high band? + if(_lo_freq > (5.35e9 + 4.47e9)/2.0){ + _max2829_regs.band_select_802_11a = max2829_regs_t::BAND_SELECT_802_11A_5_47GHZ_TO_5_875GHZ; + }else{ + _max2829_regs.band_select_802_11a = max2829_regs_t::BAND_SELECT_802_11A_4_9GHZ_TO_5_35GHZ; + } + + //new band select settings and ad9515 divider + this->update_atr(); + + //load new counters into registers + _max2829_regs.int_div_ratio_word = intdiv; + _max2829_regs.frac_div_ratio_lsb = fracdiv & 0x3; + _max2829_regs.frac_div_ratio_msb = fracdiv >> 2; + this->send_reg(0x3); //integer + this->send_reg(0x4); //fractional + + //load the reference divider and band select into registers + //toggle the bandswitch from off to automatic (which really means start) + _max2829_regs.ref_divider = R; + _max2829_regs.vco_bandswitch = max2829_regs_t::VCO_BANDSWITCH_DISABLE; + this->send_reg(0x5); + _max2829_regs.vco_bandswitch = max2829_regs_t::VCO_BANDSWITCH_AUTOMATIC;; + this->send_reg(0x5); } /*********************************************************************** @@ -181,12 +273,14 @@ void xcvr2450::set_lo_freq(double target_freq){ **********************************************************************/ void xcvr2450::set_tx_ant(const std::string &ant){ assert_has(xcvr_antennas, ant, "xcvr antenna name"); - //TODO + _tx_ant = ant; + this->update_atr(); //sets the atr to the new antenna setting } void xcvr2450::set_rx_ant(const std::string &ant){ assert_has(xcvr_antennas, ant, "xcvr antenna name"); - //TODO + _rx_ant = ant; + this->update_atr(); //sets the atr to the new antenna setting } /*********************************************************************** @@ -211,13 +305,38 @@ static int gain_to_tx_vga_reg(float &gain){ return reg; } +/*! + * Convert a requested gain for the tx bb 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 gain enum value + */ +static max2829_regs_t::tx_baseband_gain_t gain_to_tx_bb_reg(float &gain){ + int reg = std::clip(boost::math::iround(gain*3/5.0), 0, 3); + switch(reg){ + case 0: + gain = 0; + return max2829_regs_t::TX_BASEBAND_GAIN_0DB; + case 1: + gain = 2; + return max2829_regs_t::TX_BASEBAND_GAIN_2DB; + case 2: + gain = 3.5; + return max2829_regs_t::TX_BASEBAND_GAIN_3_5DB; + case 3: + gain = 5; + return max2829_regs_t::TX_BASEBAND_GAIN_5DB; + } + ASSERT_THROW(false); +} + /*! * Convert a requested gain for the rx 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 */ -static int gain_to_rx_bb_vga_reg(float &gain){ +static int gain_to_rx_vga_reg(float &gain){ int reg = std::clip(boost::math::iround(gain/2.0), 0, 31); gain = reg*2; return reg; @@ -229,7 +348,7 @@ static int gain_to_rx_bb_vga_reg(float &gain){ * \param gain the requested gain in dB * \return 2 bit the register value */ -static int gain_to_rx_rf_lna_reg(float &gain){ +static int gain_to_rx_lna_reg(float &gain){ int reg = std::clip(boost::math::iround(gain*2/30.5) + 1, 0, 3); switch(reg){ case 0: @@ -242,12 +361,30 @@ static int gain_to_rx_rf_lna_reg(float &gain){ void xcvr2450::set_tx_gain(float gain, const std::string &name){ assert_has(xcvr_tx_gain_ranges.keys(), name, "xcvr tx gain name"); - //TODO + if (name == "VGA"){ + _max2829_regs.tx_vga_gain = gain_to_tx_vga_reg(gain); + send_reg(0xC); + } + else if(name == "BB"){ + _max2829_regs.tx_baseband_gain = gain_to_tx_bb_reg(gain); + send_reg(0x9); + } + else ASSERT_THROW(false); + _tx_gains[name] = gain; } void xcvr2450::set_rx_gain(float gain, const std::string &name){ assert_has(xcvr_rx_gain_ranges.keys(), name, "xcvr rx gain name"); - //TODO + if (name == "VGA"){ + _max2829_regs.rx_vga_gain = gain_to_rx_vga_reg(gain); + send_reg(0xB); + } + else if(name == "LNA"){ + _max2829_regs.rx_lna_gain = gain_to_rx_lna_reg(gain); + send_reg(0xB); + } + else ASSERT_THROW(false); + _rx_gains[name] = gain; } /*********************************************************************** -- cgit v1.2.3 From df5212a793e5d250bfcc7955049b1e1f1eb2af03 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 22 Apr 2010 18:50:37 -0700 Subject: xcvr tweaks and fixes, needs real testing --- host/lib/usrp/dboard/db_xcvr2450.cpp | 42 ++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index fbce4b932..f69d88dca 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -35,15 +35,15 @@ // RX IO Pins #define LOCKDET_RXIO (1 << 15) // This is an INPUT!!! -#define EN_RXIO (1 << 14) +#define POWER_RXIO (1 << 14) // 1 = power on, 0 = shutdown #define RX_EN_RXIO (1 << 13) // 1 = RX on, 0 = RX off #define RX_HP_RXIO (1 << 12) // 0 = Fc set by rx_hpf, 1 = 600 KHz -#define RXIO_MASK (EN_RXIO | RX_EN_RXIO | RX_HP_RXIO) +#define RXIO_MASK (POWER_RXIO | RX_EN_RXIO | RX_HP_RXIO) // RX IO Functions -#define ALL_ENB_RXIO EN_RXIO -#define ALL_DIS_RXIO 0 +#define POWER_UP_RXIO POWER_RXIO +#define POWER_DOWN_RXIO 0 #define RX_ENB_RXIO RX_EN_RXIO #define RX_DIS_RXIO 0 @@ -187,7 +187,7 @@ xcvr2450::~xcvr2450(void){ void xcvr2450::spi_reset(void){ //spi reset mode: global enable = off, tx and rx enable = on this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, TX_ENB_TXIO); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, RX_ENB_RXIO); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, RX_ENB_RXIO | POWER_DOWN_RXIO); } void xcvr2450::update_atr(void){ @@ -205,24 +205,27 @@ void xcvr2450::update_atr(void){ this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, band_sel | ad9515div | TX_ENB_TXIO | xx_ant_sel); //set the rx registers - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, ALL_ENB_RXIO | RX_DIS_RXIO); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, ALL_ENB_RXIO | RX_ENB_RXIO); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, ALL_ENB_RXIO | RX_DIS_RXIO); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, ALL_ENB_RXIO | RX_ENB_RXIO); + 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); } /*********************************************************************** * Tuning **********************************************************************/ void xcvr2450::set_lo_freq(double target_freq){ + 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 = (_lo_freq > 3e9)? (4.0/5.0) : (4.0/3.0); + double scaler = (target_freq > 3e9)? (4.0/5.0) : (4.0/3.0); double ref_freq = this->get_iface()->get_clock_rate(dboard_iface::UNIT_TX); int R, intdiv, fracdiv; //loop through values until we get a match - for(R = 1; R <= 7; R++){ - for(_ad9515div = 2; _ad9515div <= 3; _ad9515div++){ + for(_ad9515div = 2; _ad9515div <= 3; _ad9515div++){ + for(R = 1; R <= 7; R++){ double N = (target_freq*scaler*R*_ad9515div)/ref_freq; intdiv = int(std::floor(N)); fracdiv = (N - intdiv)*double(1 << 16); @@ -235,12 +238,15 @@ void xcvr2450::set_lo_freq(double target_freq){ //calculate the actual freq from the values above double N = double(intdiv) + double(fracdiv)/double(1 << 16); - _lo_freq = (scaler*R*_ad9515div)/(N*ref_freq); - - if (xcvr2450_debug) std::cerr << boost::format( - "XCVR2450 tune: R=%d, N=%f, ad9515=%d, scaler=%f\n" - " Target Freq=%fMHz, Actual Freq=%fMHz" - ) % R % N % _ad9515div % scaler % (target_freq/1e6) % (_lo_freq/1e6) << std::endl; + _lo_freq = (N*ref_freq)/(scaler*R*_ad9515div); + + if (xcvr2450_debug) std::cerr + << boost::format("XCVR2450 tune:\n") + << boost::format(" R=%d, N=%f, ad9515=%d, scaler=%f\n") % R % N % _ad9515div % scaler + << boost::format(" Ref Freq=%fMHz\n") % (ref_freq/1e6) + << boost::format(" Target Freq=%fMHz\n") % (target_freq/1e6) + << boost::format(" Actual Freq=%fMHz\n") % (_lo_freq/1e6) + << std::endl; //high-high band or low-high band? if(_lo_freq > (5.35e9 + 4.47e9)/2.0){ -- cgit v1.2.3 From 3df2b2fc7c9d3a1824025c2576e89f950abae212 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 23 Apr 2010 14:45:30 -0700 Subject: XCVR tweaks, working in highband and lowband. Also, fixed the tx mux calculation. --- host/lib/usrp/dboard/db_xcvr2450.cpp | 23 +++++++++++++++++------ host/lib/usrp/usrp2/dboard_impl.cpp | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index f69d88dca..4df40e980 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -113,12 +113,18 @@ private: void update_atr(void); void spi_reset(void); void send_reg(boost::uint8_t addr){ + boost::uint32_t value = _max2829_regs.get_reg(addr); + if(xcvr2450_debug) std::cerr << boost::format( + "XCVR2450: send reg 0x%02x, value 0x%05x" + ) % int(addr) % value << std::endl; this->get_iface()->write_spi( dboard_iface::UNIT_RX, spi_config_t::EDGE_RISE, - _max2829_regs.get_reg(addr), 24 + value, 24 ); } + + static bool is_highband(double freq){return freq > 3e9;} }; /*********************************************************************** @@ -166,7 +172,7 @@ xcvr2450::xcvr2450(ctor_args_t const& args) : xcvr_dboard_base(args){ _max2829_regs.tx_upconv_linearity = max2829_regs_t::TX_UPCONV_LINEARITY_78; //send initial register settings - for(boost::uint8_t reg = 0; reg <= 0xC; reg++){ + for(boost::uint8_t reg = 0x2; reg <= 0xC; reg++){ this->send_reg(reg); } @@ -192,9 +198,9 @@ void xcvr2450::spi_reset(void){ void xcvr2450::update_atr(void){ //calculate tx atr pins - int band_sel = (_lo_freq > 3e9)? HB_PA_TXIO : LB_PA_TXIO; + int band_sel = (xcvr2450::is_highband(_lo_freq))? HB_PA_TXIO : LB_PA_TXIO; int tx_ant_sel = (_tx_ant == "J1")? ANTSEL_TX1_RX2_TXIO : ANTSEL_TX2_RX1_TXIO; - int rx_ant_sel = (_rx_ant == "J1")? ANTSEL_TX1_RX2_TXIO : ANTSEL_TX2_RX1_TXIO; + int rx_ant_sel = (_rx_ant == "J2")? ANTSEL_TX1_RX2_TXIO : ANTSEL_TX2_RX1_TXIO; int xx_ant_sel = tx_ant_sel; //prefer the tx antenna selection for full duplex (rx will get the other antenna) int ad9515div = (_ad9515div == 3)? AD9515DIV_3_TXIO : AD9515DIV_2_TXIO; @@ -219,7 +225,7 @@ void xcvr2450::set_lo_freq(double target_freq){ //TODO: clip for highband and lowband //variables used in the calculation below - double scaler = (target_freq > 3e9)? (4.0/5.0) : (4.0/3.0); + double scaler = xcvr2450::is_highband(target_freq)? (4.0/5.0) : (4.0/3.0); double ref_freq = this->get_iface()->get_clock_rate(dboard_iface::UNIT_TX); int R, intdiv, fracdiv; @@ -249,9 +255,11 @@ void xcvr2450::set_lo_freq(double target_freq){ << std::endl; //high-high band or low-high band? - if(_lo_freq > (5.35e9 + 4.47e9)/2.0){ + if(_lo_freq > (5.35e9 + 5.47e9)/2.0){ + if (xcvr2450_debug) std::cerr << "XCVR2450 tune: Using high-high band" << std::endl; _max2829_regs.band_select_802_11a = max2829_regs_t::BAND_SELECT_802_11A_5_47GHZ_TO_5_875GHZ; }else{ + if (xcvr2450_debug) std::cerr << "XCVR2450 tune: Using low-high band" << std::endl; _max2829_regs.band_select_802_11a = max2829_regs_t::BAND_SELECT_802_11A_4_9GHZ_TO_5_35GHZ; } @@ -268,6 +276,9 @@ void xcvr2450::set_lo_freq(double target_freq){ //load the reference divider and band select into registers //toggle the bandswitch from off to automatic (which really means start) _max2829_regs.ref_divider = R; + _max2829_regs.band_select = (xcvr2450::is_highband(_lo_freq))? + max2829_regs_t::BAND_SELECT_5GHZ : + max2829_regs_t::BAND_SELECT_2_4GHZ ; _max2829_regs.vco_bandswitch = max2829_regs_t::VCO_BANDSWITCH_DISABLE; this->send_reg(0x5); _max2829_regs.vco_bandswitch = max2829_regs_t::VCO_BANDSWITCH_AUTOMATIC;; diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index fe74219d6..ee23dc83a 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -94,7 +94,7 @@ void usrp2_impl::update_tx_mux_config(void){ wax::obj tx_subdev = _dboard_manager->get_tx_subdev(_tx_subdevs_in_use.at(0)); std::cout << "Using: " << tx_subdev[SUBDEV_PROP_NAME].as() << std::endl; if (tx_subdev[SUBDEV_PROP_IQ_SWAPPED].as()){ - tx_mux = (((tx_mux >> 0) & 0x1) << 1) | (((tx_mux >> 1) & 0x1) << 0); + tx_mux = (((tx_mux >> 0) & 0xf) << 4) | (((tx_mux >> 4) & 0xf) << 0); } _iface->poke32(FR_DSP_TX_MUX, tx_mux); -- cgit v1.2.3 From a29b30fdf17b5703c9b5c5dd015f11ecd44fbdfe Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 23 Apr 2010 15:59:22 -0700 Subject: XCVR seems to be working, fixed the spi reset routine. --- host/lib/ic_reg_maps/gen_max2829_regs.py | 2 +- host/lib/usrp/dboard/db_xcvr2450.cpp | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/ic_reg_maps/gen_max2829_regs.py b/host/lib/ic_reg_maps/gen_max2829_regs.py index 33dc3e641..7fef302a8 100755 --- a/host/lib/ic_reg_maps/gen_max2829_regs.py +++ b/host/lib/ic_reg_maps/gen_max2829_regs.py @@ -68,7 +68,7 @@ tx_cal_mode 6[1] 0 dis, enb _set_to_1_6_10 6[10] 1 iq_cal_gain 6[11:12] 3 8db, 18db, 24db, 34db ######################################################################## -## Lopass Filter (7) +## Lowpass Filter (7) ######################################################################## rx_lpf_fine_adj 7[0:2] 2 90, 95, 100, 105, 110 rx_lpf_coarse_adj 7[3:4] 1 7_5mhz, 9_5mhz, 14mhz, 18mhz diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 4df40e980..2c2843d3a 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -58,6 +58,7 @@ #include #include #include +#include #include #include @@ -68,7 +69,7 @@ using namespace boost::assign; /*********************************************************************** * The XCVR 2450 constants **********************************************************************/ -static const bool xcvr2450_debug = true; +static const bool xcvr2450_debug = false; static const freq_range_t xcvr_freq_range(2.4e9, 6.0e9); @@ -178,12 +179,14 @@ xcvr2450::xcvr2450(ctor_args_t const& args) : xcvr_dboard_base(args){ //set defaults for LO, gains, antennas set_lo_freq(2.45e9); - set_rx_ant("J1"); - set_tx_ant("J2"); - set_rx_gain(0, "LNA"); - set_rx_gain(0, "VGA"); - set_tx_gain(0, "VGA"); - set_tx_gain(0, "BB"); + set_rx_ant(xcvr_antennas.at(0)); + set_tx_ant(xcvr_antennas.at(1)); + BOOST_FOREACH(const std::string &name, xcvr_tx_gain_ranges.keys()){ + set_tx_gain(xcvr_tx_gain_ranges[name].min, name); + } + BOOST_FOREACH(const std::string &name, xcvr_rx_gain_ranges.keys()){ + set_rx_gain(xcvr_rx_gain_ranges[name].min, name); + } } xcvr2450::~xcvr2450(void){ @@ -194,6 +197,11 @@ void xcvr2450::spi_reset(void){ //spi reset mode: global enable = off, tx and rx enable = on this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, TX_ENB_TXIO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, RX_ENB_RXIO | POWER_DOWN_RXIO); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + + //take it back out of spi reset mode and wait a bit + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, RX_DIS_RXIO | POWER_UP_RXIO); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); } void xcvr2450::update_atr(void){ -- cgit v1.2.3