From 275b29e07f97cdf638ecb22c602d26b7d340547a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 2 Apr 2010 17:54:06 -0700 Subject: some work on rfx board code --- host/lib/usrp/dboard/db_rfx.cpp | 300 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 host/lib/usrp/dboard/db_rfx.cpp (limited to 'host/lib/usrp/dboard/db_rfx.cpp') diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp new file mode 100644 index 000000000..4fb036d38 --- /dev/null +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -0,0 +1,300 @@ +// +// 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 + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + +/*********************************************************************** + * The RFX series of dboards + **********************************************************************/ +class rfx_xcvr : public xcvr_dboard_base{ +public: + rfx_xcvr(ctor_args_t const& args, const freq_range_t &freq_range); + ~rfx_xcvr(void); + + void rx_get(const wax::obj &key, wax::obj &val); + void rx_set(const wax::obj &key, const wax::obj &val); + + void tx_get(const wax::obj &key, wax::obj &val); + void tx_set(const wax::obj &key, const wax::obj &val); + +private: + freq_range_t _freq_range; + double _lo_freq; + std::string _rx_ant; + float _rx_pga0_gain; + + void set_lo_freq(double freq); + void set_rx_ant(const std::string &ant); + void set_rx_pga0_gain(float gain); +}; + +/*********************************************************************** + * Register the RFX dboards + **********************************************************************/ +static dboard_base::sptr make_rfx_flex400(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(400e6, 500e6))); +} + +static dboard_base::sptr make_rfx_flex900(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(750e6, 1050e6))); +} + +static dboard_base::sptr make_rfx_flex1200(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(1150e6, 1450e6))); +} + +static dboard_base::sptr make_rfx_flex1800(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(1500e6, 2100e6))); +} + +static dboard_base::sptr make_rfx_flex2400(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(2300e6, 2900e6))); +} + +UHD_STATIC_BLOCK(reg_rfx_dboards){ + dboard_manager::register_dboard(0x0024, &make_rfx_flex400, "Flex 400 Rx MIMO B"); + dboard_manager::register_dboard(0x0028, &make_rfx_flex400, "Flex 400 Tx MIMO B"); + + dboard_manager::register_dboard(0x0025, &make_rfx_flex900, "Flex 900 Rx MIMO B"); + dboard_manager::register_dboard(0x0029, &make_rfx_flex900, "Flex 900 Tx MIMO B"); + + dboard_manager::register_dboard(0x0026, &make_rfx_flex1200, "Flex 1200 Rx MIMO B"); + dboard_manager::register_dboard(0x002a, &make_rfx_flex1200, "Flex 1200 Tx MIMO B"); + + dboard_manager::register_dboard(0x0034, &make_rfx_flex1800, "Flex 1800 Rx MIMO B"); + dboard_manager::register_dboard(0x0035, &make_rfx_flex1800, "Flex 1800 Tx MIMO B"); + + dboard_manager::register_dboard(0x0027, &make_rfx_flex2400, "Flex 2400 Rx MIMO B"); + dboard_manager::register_dboard(0x002b, &make_rfx_flex2400, "Flex 2400 Tx MIMO B"); +} + +/*********************************************************************** + * Structors + **********************************************************************/ +rfx_xcvr::rfx_xcvr( + ctor_args_t const& args, + const freq_range_t &freq_range +) : xcvr_dboard_base(args){ + _freq_range = freq_range; + set_lo_freq((_freq_range.min + _freq_range.max)/2.0); + set_rx_ant("rx2"); + set_rx_pga0_gain(0); +} + +rfx_xcvr::~rfx_xcvr(void){ + /* NOP */ +} + +/*********************************************************************** + * Helper Methods + **********************************************************************/ +void rfx_xcvr::set_lo_freq(double freq){ + /* NOP */ +} + +void rfx_xcvr::set_rx_ant(const std::string &ant){ + /* NOP */ +} + +void rfx_xcvr::set_rx_pga0_gain(float gain){ + /* NOP */ +} + +/*********************************************************************** + * RX Get and Set + **********************************************************************/ +void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + 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: + val = _rx_pga0_gain; + return; + + case SUBDEV_PROP_GAIN_RANGE: + val = gain_range_t(0, 45, float(0.022)); + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(1, "pga0"); + return; + + case SUBDEV_PROP_FREQ: + val = _lo_freq; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = _freq_range; + return; + + case SUBDEV_PROP_ANTENNA: + val = _rx_ant; + return; + + case SUBDEV_PROP_ANTENNA_NAMES:{ + prop_names_t ants = list_of("tx/rx")("rx2"); + val = ants; + } + return; + + case SUBDEV_PROP_QUADRATURE: + val = true; + return; + + case SUBDEV_PROP_IQ_SWAPPED: + val = true; + return; + + case SUBDEV_PROP_SPECTRUM_INVERTED: + val = false; + return; + + case SUBDEV_PROP_LO_INTERFERES: + val = false; + return; + } +} + +void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + + case SUBDEV_PROP_GAIN: + ASSERT_THROW(name == "pga0"); + set_rx_pga0_gain(val.as()); + return; + + case SUBDEV_PROP_ANTENNA: + 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 rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + 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: + val = float(0); + return; + + case SUBDEV_PROP_GAIN_RANGE: + val = gain_range_t(0, 0, 0); + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_FREQ: + val = _lo_freq; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = _freq_range; + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string("tx/rx"); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = prop_names_t(1, "tx/rx"); + return; + + case SUBDEV_PROP_QUADRATURE: + val = true; + return; + + case SUBDEV_PROP_IQ_SWAPPED: + val = false; + return; + + case SUBDEV_PROP_SPECTRUM_INVERTED: + val = false; + return; + + case SUBDEV_PROP_LO_INTERFERES: + val = true; + return; + } +} + +void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + + case SUBDEV_PROP_GAIN: + //no gains to set! + return; + + case SUBDEV_PROP_ANTENNA: + //its always set to tx/rx, so we only allow this value + ASSERT_THROW(val.as() == "tx/rx"); + 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 e6151334096167d1d26609f7233105020af91f40 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 6 Apr 2010 19:05:02 -0700 Subject: added code for adf4360 chip --- host/lib/usrp/dboard/adf4360_regs.hpp | 185 +++++++++++++++++++++++++++++++ host/lib/usrp/dboard/db_rfx.cpp | 29 ++++- host/lib/usrp/dboard/gen_adf4360_regs.py | 168 ++++++++++++++++++++++++++++ 3 files changed, 380 insertions(+), 2 deletions(-) create mode 100644 host/lib/usrp/dboard/adf4360_regs.hpp create mode 100755 host/lib/usrp/dboard/gen_adf4360_regs.py (limited to 'host/lib/usrp/dboard/db_rfx.cpp') diff --git a/host/lib/usrp/dboard/adf4360_regs.hpp b/host/lib/usrp/dboard/adf4360_regs.hpp new file mode 100644 index 000000000..309ff50e9 --- /dev/null +++ b/host/lib/usrp/dboard/adf4360_regs.hpp @@ -0,0 +1,185 @@ + + +/*********************************************************************** + * This file was generated by gen_adf4360_regs.py on Tue Apr 6 18:40:51 2010 + **********************************************************************/ + +#ifndef INCLUDED_ADF4360_REGS_HPP +#define INCLUDED_ADF4360_REGS_HPP + +#include + +struct adf4360_regs_t{ + enum core_power_level_t{ + CORE_POWER_LEVEL_5MA = 0, + CORE_POWER_LEVEL_10MA = 1, + CORE_POWER_LEVEL_15MA = 2, + CORE_POWER_LEVEL_20MA = 3 + } core_power_level; + enum counter_reset_t{ + COUNTER_RESET_NORMAL = 0, + COUNTER_RESET_RESET = 1 + } counter_reset; + enum muxout_control_t{ + MUXOUT_CONTROL_3STATE = 0, + MUXOUT_CONTROL_DLD = 1, + MUXOUT_CONTROL_NDIV = 2, + MUXOUT_CONTROL_DVDD = 3, + MUXOUT_CONTROL_RDIV = 4, + MUXOUT_CONTROL_NCHAN_OD_LD = 5, + MUXOUT_CONTROL_SDO = 6, + MUXOUT_CONTROL_DGND = 7 + } muxout_control; + enum phase_detector_polarity_t{ + PHASE_DETECTOR_POLARITY_NEG = 0, + PHASE_DETECTOR_POLARITY_POS = 1 + } phase_detector_polarity; + enum cp_three_state_t{ + CP_THREE_STATE_NORMAL = 0, + CP_THREE_STATE_3STATE = 1 + } cp_three_state; + enum cp_gain_0_t{ + CP_GAIN_0_SET1 = 0, + CP_GAIN_0_SET2 = 1 + } cp_gain_0; + enum mute_till_ld_t{ + MUTE_TILL_LD_DIS = 0, + MUTE_TILL_LD_ENB = 1 + } mute_till_ld; + enum output_power_level_t{ + OUTPUT_POWER_LEVEL_3_5MA = 0, + OUTPUT_POWER_LEVEL_5_0MA = 1, + OUTPUT_POWER_LEVEL_7_5MA = 2, + OUTPUT_POWER_LEVEL_11_0MA = 3 + } output_power_level; + enum current_setting1_t{ + CURRENT_SETTING1_0_31 = 0, + CURRENT_SETTING1_0_62 = 1, + CURRENT_SETTING1_0_93 = 2, + CURRENT_SETTING1_1_25 = 3, + CURRENT_SETTING1_1_56 = 4, + CURRENT_SETTING1_1_87 = 5, + CURRENT_SETTING1_2_18 = 6, + CURRENT_SETTING1_2_50 = 7 + } current_setting1; + enum current_setting2_t{ + CURRENT_SETTING2_0_31 = 0, + CURRENT_SETTING2_0_62 = 1, + CURRENT_SETTING2_0_93 = 2, + CURRENT_SETTING2_1_25 = 3, + CURRENT_SETTING2_1_56 = 4, + CURRENT_SETTING2_1_87 = 5, + CURRENT_SETTING2_2_18 = 6, + CURRENT_SETTING2_2_50 = 7 + } current_setting2; + enum power_down_t{ + POWER_DOWN_NORMAL_OP = 0, + POWER_DOWN_ASYNC_PD = 1, + POWER_DOWN_SYNC_PD = 3 + } power_down; + enum prescaler_value_t{ + PRESCALER_VALUE_8_9 = 0, + PRESCALER_VALUE_16_17 = 1, + PRESCALER_VALUE_32_33 = 2 + } prescaler_value; + boost::uint8_t a_counter; + boost::uint16_t b_counter; + enum cp_gain_1_t{ + CP_GAIN_1_SET1 = 0, + CP_GAIN_1_SET2 = 1 + } cp_gain_1; + enum divide_by_2_output_t{ + DIVIDE_BY_2_OUTPUT_FUND = 0, + DIVIDE_BY_2_OUTPUT_DIV2 = 1 + } divide_by_2_output; + enum divide_by_2_prescaler_t{ + DIVIDE_BY_2_PRESCALER_FUND = 0, + DIVIDE_BY_2_PRESCALER_DIV2 = 1 + } divide_by_2_prescaler; + boost::uint16_t r_counter; + enum ablpw_t{ + ABLPW_3_0NS = 0, + ABLPW_1_3NS = 1, + ABLPW_6_0NS = 2 + } ablpw; + enum lock_detect_precision_t{ + LOCK_DETECT_PRECISION_3CYCLES = 0, + LOCK_DETECT_PRECISION_5CYCLES = 1 + } lock_detect_precision; + boost::uint8_t test_mode_bit; + enum band_select_clock_div_t{ + BAND_SELECT_CLOCK_DIV_1 = 0, + BAND_SELECT_CLOCK_DIV_2 = 1, + BAND_SELECT_CLOCK_DIV_4 = 2, + BAND_SELECT_CLOCK_DIV_8 = 3 + } band_select_clock_div; + + adf4360_regs_t(void){ + core_power_level = CORE_POWER_LEVEL_5MA; + counter_reset = COUNTER_RESET_NORMAL; + muxout_control = MUXOUT_CONTROL_3STATE; + phase_detector_polarity = PHASE_DETECTOR_POLARITY_NEG; + cp_three_state = CP_THREE_STATE_NORMAL; + cp_gain_0 = CP_GAIN_0_SET1; + mute_till_ld = MUTE_TILL_LD_DIS; + output_power_level = OUTPUT_POWER_LEVEL_3_5MA; + current_setting1 = CURRENT_SETTING1_0_31; + current_setting2 = CURRENT_SETTING2_0_31; + power_down = POWER_DOWN_NORMAL_OP; + prescaler_value = PRESCALER_VALUE_8_9; + a_counter = 0; + b_counter = 0; + cp_gain_1 = CP_GAIN_1_SET1; + divide_by_2_output = DIVIDE_BY_2_OUTPUT_FUND; + divide_by_2_prescaler = DIVIDE_BY_2_PRESCALER_FUND; + r_counter = 0; + ablpw = ABLPW_3_0NS; + lock_detect_precision = LOCK_DETECT_PRECISION_3CYCLES; + test_mode_bit = 0; + band_select_clock_div = BAND_SELECT_CLOCK_DIV_1; + } + + enum addr_t{ + ADDR_CONTROL = 0, + ADDR_NCOUNTER = 2, + ADDR_RCOUNTER = 1 + }; + + boost::uint32_t get_reg(addr_t addr){ + boost::uint32_t reg = addr & 0x3; + switch(addr){ + case 0: + reg |= (boost::uint32_t(core_power_level) & 0x3) << 2; + reg |= (boost::uint32_t(counter_reset) & 0x1) << 4; + reg |= (boost::uint32_t(muxout_control) & 0x7) << 5; + reg |= (boost::uint32_t(phase_detector_polarity) & 0x1) << 8; + reg |= (boost::uint32_t(cp_three_state) & 0x1) << 9; + reg |= (boost::uint32_t(cp_gain_0) & 0x1) << 10; + reg |= (boost::uint32_t(mute_till_ld) & 0x1) << 11; + reg |= (boost::uint32_t(output_power_level) & 0x3) << 12; + reg |= (boost::uint32_t(current_setting1) & 0x7) << 14; + reg |= (boost::uint32_t(current_setting2) & 0x7) << 17; + reg |= (boost::uint32_t(power_down) & 0x3) << 20; + reg |= (boost::uint32_t(prescaler_value) & 0x3) << 22; + break; + case 1: + reg |= (boost::uint32_t(r_counter) & 0x3fff) << 2; + reg |= (boost::uint32_t(ablpw) & 0x3) << 16; + reg |= (boost::uint32_t(lock_detect_precision) & 0x1) << 18; + reg |= (boost::uint32_t(test_mode_bit) & 0x1) << 19; + reg |= (boost::uint32_t(band_select_clock_div) & 0x3) << 20; + break; + case 2: + reg |= (boost::uint32_t(a_counter) & 0x1f) << 2; + reg |= (boost::uint32_t(b_counter) & 0x1fff) << 8; + reg |= (boost::uint32_t(cp_gain_1) & 0x1) << 21; + reg |= (boost::uint32_t(divide_by_2_output) & 0x1) << 22; + reg |= (boost::uint32_t(divide_by_2_prescaler) & 0x1) << 23; + break; + } + return reg; + } +}; + +#endif /* INCLUDED_ADF4360_REGS_HPP */ + diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 4fb036d38..57ea03da5 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -15,6 +15,7 @@ // along with this program. If not, see . // +#include "adf4360_regs.hpp" #include #include #include @@ -47,10 +48,12 @@ private: double _lo_freq; std::string _rx_ant; float _rx_pga0_gain; + adf4360_regs_t _adf4360_regs; void set_lo_freq(double freq); void set_rx_ant(const std::string &ant); void set_rx_pga0_gain(float gain); + void reload_adf4360_regs(void); }; /*********************************************************************** @@ -115,6 +118,7 @@ rfx_xcvr::~rfx_xcvr(void){ **********************************************************************/ void rfx_xcvr::set_lo_freq(double freq){ /* NOP */ + reload_adf4360_regs(); } void rfx_xcvr::set_rx_ant(const std::string &ant){ @@ -125,6 +129,27 @@ void rfx_xcvr::set_rx_pga0_gain(float gain){ /* NOP */ } +void rfx_xcvr::reload_adf4360_regs(void){ + std::vector addrs = list_of + (adf4360_regs_t::ADDR_CONTROL) + (adf4360_regs_t::ADDR_NCOUNTER) + (adf4360_regs_t::ADDR_RCOUNTER) + ; + BOOST_FOREACH(adf4360_regs_t::addr_t addr, addrs){ + boost::uint32_t reg = _adf4360_regs.get_reg(addr); + dboard_interface::byte_vector_t spi_bytes = list_of + ((reg >> 16) & 0xff) + ((reg >> 8) & 0xff) + ((reg >> 0) & 0xff) + ; + //this->get_interface.write_spi( + // dboard_interface::SPI_DEV_TX, + // dboard_interface::SPI_EDGE_FALL, + // spi_bytes + //); + } +} + /*********************************************************************** * RX Get and Set **********************************************************************/ @@ -184,7 +209,7 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ val = false; return; - case SUBDEV_PROP_LO_INTERFERES: + case SUBDEV_PROP_USE_LO_OFFSET: val = false; return; } @@ -270,7 +295,7 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ val = false; return; - case SUBDEV_PROP_LO_INTERFERES: + case SUBDEV_PROP_USE_LO_OFFSET: val = true; return; } diff --git a/host/lib/usrp/dboard/gen_adf4360_regs.py b/host/lib/usrp/dboard/gen_adf4360_regs.py new file mode 100755 index 000000000..f16e59e2a --- /dev/null +++ b/host/lib/usrp/dboard/gen_adf4360_regs.py @@ -0,0 +1,168 @@ +#!/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 re +from Cheetah.Template import Template +def parse_tmpl(_tmpl_text, **kwargs): + return str(Template(_tmpl_text, kwargs)) + +######################################################################## +# Template for raw text data describing registers +# name addr[bit range inclusive] default optional enums +######################################################################## +REGS_DATA_TMPL="""\ +######################################################################## +## address 0 +######################################################################## +core_power_level 0[2:3] 0 5ma, 10ma, 15ma, 20ma +counter_reset 0[4] 0 normal, reset +muxout_control 0[5:7] 0 3state, dld, ndiv, dvdd, rdiv, nchan_od_ld, sdo, dgnd +phase_detector_polarity 0[8] 0 neg, pos +cp_three_state 0[9] 0 normal, 3state +cp_gain_0 0[10] 0 set1, set2 +mute_till_ld 0[11] 0 dis, enb +output_power_level 0[12:13] 0 3_5ma, 5_0ma, 7_5ma, 11_0ma +#set $current_setting_enums = "0_31, 0_62, 0_93, 1_25, 1_56, 1_87, 2_18, 2_50" +current_setting1 0[14:16] 0 $current_setting_enums +current_setting2 0[17:19] 0 $current_setting_enums +power_down 0[20:21] 0 normal_op=0, async_pd=1, sync_pd=3 +prescaler_value 0[22:23] 0 8_9, 16_17, 32_33 +######################################################################## +## address 2 +######################################################################## +a_counter 2[2:6] 0 +b_counter 2[8:20] 0 +cp_gain_1 2[21] 0 set1, set2 +divide_by_2_output 2[22] 0 fund, div2 +divide_by_2_prescaler 2[23] 0 fund, div2 +######################################################################## +## address 1 +######################################################################## +r_counter 1[2:15] 0 +ablpw 1[16:17] 0 3_0ns, 1_3ns, 6_0ns +lock_detect_precision 1[18] 0 3cycles, 5cycles +test_mode_bit 1[19] 0 +band_select_clock_div 1[20:21] 0 1, 2, 4, 8 +""" + +######################################################################## +# Header and Source templates below +######################################################################## +HEADER_TEXT=""" +#import time + +/*********************************************************************** + * This file was generated by $file on $time.strftime("%c") + **********************************************************************/ + +\#ifndef INCLUDED_ADF4360_REGS_HPP +\#define INCLUDED_ADF4360_REGS_HPP + +\#include + +struct adf4360_regs_t{ +#for $reg in $regs + #if $reg.get_enums() + enum $(reg.get_name())_t{ + #for $i, $enum in enumerate($reg.get_enums()) + #set $end_comma = ',' if $i < len($reg.get_enums())-1 else '' + $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma + #end for + } $reg.get_name(); + #else + boost::$reg.get_stdint_type() $reg.get_name(); + #end if +#end for + + adf4360_regs_t(void){ +#for $reg in $regs + $reg.get_name() = $reg.get_default(); +#end for + } + + enum addr_t{ + ADDR_CONTROL = 0, + ADDR_NCOUNTER = 2, + ADDR_RCOUNTER = 1 + }; + + boost::uint32_t get_reg(addr_t addr){ + boost::uint32_t reg = addr & 0x3; + switch(addr){ + #for $addr in (0, 1, 2) + case $addr: + #for $reg in filter(lambda r: r.get_addr() == addr, $regs) + reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); + #end for + break; + #end for + } + return reg; + } +}; + +\#endif /* INCLUDED_ADF4360_REGS_HPP */ +""" + +class reg: + def __init__(self, reg_des): + x = re.match('^(\w*)\s*(\w*)\[(.*)\]\s*(\w*)\s*(.*)$', reg_des) + name, addr, bit_range, default, enums = x.groups() + + #store variables + self._name = name + self._addr = int(addr) + if ':' in bit_range: self._addr_spec = map(int, bit_range.split(':')) + else: self._addr_spec = int(bit_range), int(bit_range) + self._default = int(default) + + #extract enum + self._enums = list() + if enums: + enum_val = 0 + for enum_str in map(str.strip, enums.split(',')): + if '=' in enum_str: + enum_name, enum_val = enum_str.split('=') + enum_val = int(enum_val) + else: enum_name = enum_str + self._enums.append((enum_name, enum_val)) + enum_val += 1 + + def get_addr(self): return self._addr + def get_enums(self): return self._enums + def get_name(self): return self._name + def get_default(self): + for key, val in self.get_enums(): + if val == self._default: return str.upper('%s_%s'%(self.get_name(), key)) + return self._default + def get_stdint_type(self): + if self.get_bit_width() <= 8: return 'uint8_t' + if self.get_bit_width() <= 16: return 'uint16_t' + if self.get_bit_width() <= 32: return 'uint32_t' + if self.get_bit_width() <= 64: return 'uint64_t' + raise Exception, 'too damn big' + def get_shift(self): return self._addr_spec[0] + def get_mask(self): return hex(int('1'*self.get_bit_width(), 2)) + def get_bit_width(self): return self._addr_spec[1] - self._addr_spec[0] + 1 + +if __name__ == '__main__': + regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines()) + print parse_tmpl(HEADER_TEXT, regs=regs, file=__file__) -- cgit v1.2.3 From b66a74ff1f629af714e26040b410d472c08be522 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 7 Apr 2010 00:46:42 -0700 Subject: Reworked the spi part of the dboard interface. It turns out to be more complicated. The integer type is better for holding the bits. The edges can be different, so the spi config hold 2 edge setting for mosi and miso. --- firmware/microblaze/apps/txrx.c | 25 ++------ host/include/uhd/usrp/dboard_interface.hpp | 100 ++++++++++++++++------------- host/lib/CMakeLists.txt | 1 - host/lib/usrp/dboard/db_rfx.cpp | 16 ++--- host/lib/usrp/dboard_interface.cpp | 53 --------------- host/lib/usrp/usrp2/dboard_interface.cpp | 95 ++++++++++++++++----------- host/lib/usrp/usrp2/fw_common.h | 7 +- 7 files changed, 128 insertions(+), 169 deletions(-) delete mode 100644 host/lib/usrp/dboard_interface.cpp (limited to 'host/lib/usrp/dboard/db_rfx.cpp') diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index 69a04d771..561f3148f 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -253,29 +253,18 @@ void handle_udp_ctrl_packet( * SPI ******************************************************************/ case USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO:{ - uint8_t num_bytes = ctrl_data_in->data.spi_args.bytes; - - //load the data from the array of bytes - uint32_t data = 0x0; - for (size_t i = 0; i < num_bytes; i++){ - data = (data << 8) | ctrl_data_in->data.spi_args.data[i]; - } - //transact uint32_t result = spi_transact( (ctrl_data_in->data.spi_args.readback == 0)? SPI_TXONLY : SPI_TXRX, - ctrl_data_in->data.spi_args.dev, - data, num_bytes*8, //length in bits - (ctrl_data_in->data.spi_args.edge == USRP2_CLK_EDGE_RISE)? SPIF_PUSH_RISE : SPIF_PUSH_FALL | - (ctrl_data_in->data.spi_args.edge == USRP2_CLK_EDGE_RISE)? SPIF_LATCH_RISE : SPIF_LATCH_FALL + ctrl_data_in->data.spi_args.dev, //which device + ctrl_data_in->data.spi_args.data, //32 bit data + ctrl_data_in->data.spi_args.num_bits, //length in bits + (ctrl_data_in->data.spi_args.mosi_edge == USRP2_CLK_EDGE_RISE)? SPIF_PUSH_FALL : SPIF_PUSH_RISE | + (ctrl_data_in->data.spi_args.miso_edge == USRP2_CLK_EDGE_RISE)? SPIF_LATCH_RISE : SPIF_LATCH_FALL ); - //load the result into the array of bytes - for (size_t i = 0; i < num_bytes; i++){ - uint8_t byte_shift = num_bytes - i - 1; - ctrl_data_out.data.spi_args.data[i] = (result >> (byte_shift*8)) & 0xff; - } - ctrl_data_out.data.spi_args.bytes = num_bytes; + //load output + ctrl_data_out.data.spi_args.data = result; ctrl_data_out.id = USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE; } break; diff --git a/host/include/uhd/usrp/dboard_interface.hpp b/host/include/uhd/usrp/dboard_interface.hpp index b3bab131d..dab5a2281 100644 --- a/host/include/uhd/usrp/dboard_interface.hpp +++ b/host/include/uhd/usrp/dboard_interface.hpp @@ -42,16 +42,31 @@ public: UNIT_TYPE_TX = 't' }; - //tells the host which device to use - enum spi_dev_t{ - SPI_DEV_RX = 'r', - SPI_DEV_TX = 't' - }; - - //args for spi format - enum spi_edge_t{ - SPI_EDGE_RISE = 'r', - SPI_EDGE_FALL = 'f' + //spi configuration struct + struct UHD_API spi_config_t{ + /*! + * The edge type specifies when data is valid + * relative to the edge of the serial clock. + */ + enum edge_t{ + EDGE_RISE = 'r', + EDGE_FALL = 'f' + }; + + //! on what edge is the mosi data valid? + edge_t mosi_edge; + + //! on what edge is the miso data valid? + edge_t miso_edge; + + /*! + * Create a new spi config. + * \param edge the default edge for mosi and miso + */ + spi_config_t(edge_t edge = EDGE_RISE){ + mosi_edge = edge; + miso_edge = edge; + } }; //tell the host which gpio bank @@ -68,10 +83,6 @@ public: ATR_REG_FULL_DUPLEX = 'f' }; - //structors - dboard_interface(void); - virtual ~dboard_interface(void); - /*! * Write to an aux dac. * \param unit which unit rx or tx @@ -131,61 +142,60 @@ public: /*! * \brief Write data to SPI bus peripheral. * - * \param dev which spi device - * \param edge args for format - * \param buf the data to write + * \param unit which unit, rx or tx + * \param config configuration settings + * \param data the bits to write LSB first + * \param num_bits the number of bits in data */ - void write_spi(spi_dev_t dev, spi_edge_t edge, const byte_vector_t &buf); + virtual void write_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ) = 0; /*! * \brief Read data to SPI bus peripheral. * - * \param dev which spi device - * \param edge args for format - * \param num_bytes number of bytes to read + * \param unit which unit, rx or tx + * \param config configuration settings + * \param num_bits the number of bits * \return the data that was read */ - byte_vector_t read_spi(spi_dev_t dev, spi_edge_t edge, size_t num_bytes); + virtual boost::uint32_t read_spi( + unit_type_t unit, + const spi_config_t &config, + size_t num_bits + ) = 0; /*! * \brief Read and write data to SPI bus peripheral. * The data read back will be the same length as the input buffer. * - * \param dev which spi device - * \param edge args for format - * \param buf the data to write + * \param unit which unit, rx or tx + * \param config configuration settings + * \param data the bits to write LSB first + * \param num_bits the number of bits in data * \return the data that was read */ - byte_vector_t read_write_spi(spi_dev_t dev, spi_edge_t edge, const byte_vector_t &buf); + virtual boost::uint32_t read_write_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ) = 0; /*! * \brief Get the rate of the rx dboard clock. - * \return the clock rate + * \return the clock rate in Hz */ virtual double get_rx_clock_rate(void) = 0; /*! * \brief Get the rate of the tx dboard clock. - * \return the clock rate + * \return the clock rate in Hz */ virtual double get_tx_clock_rate(void) = 0; - -private: - /*! - * \brief Read and write data to SPI bus peripheral. - * - * \param dev which spi device - * \param edge args for format - * \param buf the data to write - * \param readback false for write only - * \return the data that was read - */ - virtual byte_vector_t transact_spi( - spi_dev_t dev, - spi_edge_t edge, - const byte_vector_t &buf, - bool readback - ) = 0; }; }} //namespace diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index a4bf46f1a..f21a4a491 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -30,7 +30,6 @@ SET(libuhd_sources usrp/dboard/db_basic_and_lf.cpp usrp/dboard/db_rfx.cpp usrp/dboard_base.cpp - usrp/dboard_interface.cpp usrp/simple_usrp.cpp usrp/dboard_manager.cpp usrp/tune_helper.cpp diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 57ea03da5..68fa51144 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -136,17 +136,11 @@ void rfx_xcvr::reload_adf4360_regs(void){ (adf4360_regs_t::ADDR_RCOUNTER) ; BOOST_FOREACH(adf4360_regs_t::addr_t addr, addrs){ - boost::uint32_t reg = _adf4360_regs.get_reg(addr); - dboard_interface::byte_vector_t spi_bytes = list_of - ((reg >> 16) & 0xff) - ((reg >> 8) & 0xff) - ((reg >> 0) & 0xff) - ; - //this->get_interface.write_spi( - // dboard_interface::SPI_DEV_TX, - // dboard_interface::SPI_EDGE_FALL, - // spi_bytes - //); + this->get_interface()->write_spi( + dboard_interface::UNIT_TYPE_TX, + dboard_interface::spi_config_t::EDGE_RISE, + _adf4360_regs.get_reg(addr), 24 + ); } } diff --git a/host/lib/usrp/dboard_interface.cpp b/host/lib/usrp/dboard_interface.cpp deleted file mode 100644 index c40c9b398..000000000 --- a/host/lib/usrp/dboard_interface.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include - -using namespace uhd::usrp; - -dboard_interface::dboard_interface(void){ - /* NOP */ -} - -dboard_interface::~dboard_interface(void){ - /* NOP */ -} - -void dboard_interface::write_spi( - spi_dev_t dev, - spi_edge_t edge, - const byte_vector_t &buf -){ - transact_spi(dev, edge, buf, false); //dont readback -} - -dboard_interface::byte_vector_t dboard_interface::read_spi( - spi_dev_t dev, - spi_edge_t edge, - size_t num_bytes -){ - byte_vector_t buf(num_bytes, 0x00); //dummy data - return transact_spi(dev, edge, buf, true); //readback -} - -dboard_interface::byte_vector_t dboard_interface::read_write_spi( - spi_dev_t dev, - spi_edge_t edge, - const byte_vector_t &buf -){ - return transact_spi(dev, edge, buf, true); //readback -} diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp index 6dd756420..eee7c087a 100644 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ b/host/lib/usrp/usrp2/dboard_interface.cpp @@ -42,9 +42,35 @@ public: double get_rx_clock_rate(void); double get_tx_clock_rate(void); + void write_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ){ + transact_spi(unit, config, data, num_bits, false /*no rb*/); + } + + boost::uint32_t read_spi( + unit_type_t unit, + const spi_config_t &config, + size_t num_bits + ){ + return transact_spi(unit, config, 0, num_bits, true /*rb*/); + } + + boost::uint32_t read_write_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ){ + return transact_spi(unit, config, data, num_bits, true /*rb*/); + } + private: - byte_vector_t transact_spi( - spi_dev_t, spi_edge_t, const byte_vector_t &, bool + boost::uint32_t transact_spi( + unit_type_t, const spi_config_t &, boost::uint32_t, size_t, bool ); usrp2_impl *_impl; @@ -136,17 +162,17 @@ void usrp2_dboard_interface::set_atr_reg(gpio_bank_t bank, atr_reg_t atr, boost: * SPI **********************************************************************/ /*! - * Static function to convert a spi dev enum - * to an over-the-wire value for the usrp2 control. - * \param dev the dboard interface spi dev enum + * Static function to convert a unit type enum + * to an over-the-wire value for the spi device. + * \param unit the dboard interface unit type enum * \return an over the wire representation */ -static boost::uint8_t spi_dev_to_otw(dboard_interface::spi_dev_t dev){ - switch(dev){ - case uhd::usrp::dboard_interface::SPI_DEV_TX: return SPI_SS_TX_DB; - case uhd::usrp::dboard_interface::SPI_DEV_RX: return SPI_SS_RX_DB; +static boost::uint8_t unit_to_otw_dev(dboard_interface::unit_type_t unit){ + switch(unit){ + case dboard_interface::UNIT_TYPE_TX: return SPI_SS_TX_DB; + case dboard_interface::UNIT_TYPE_RX: return SPI_SS_RX_DB; } - throw std::invalid_argument("unknown spi device type"); + throw std::invalid_argument("unknown unit type type"); } /*! @@ -155,43 +181,36 @@ static boost::uint8_t spi_dev_to_otw(dboard_interface::spi_dev_t dev){ * \param edge the dboard interface spi edge enum * \return an over the wire representation */ -static boost::uint8_t spi_edge_to_otw(dboard_interface::spi_edge_t edge){ +static boost::uint8_t spi_edge_to_otw(dboard_interface::spi_config_t::edge_t edge){ switch(edge){ - case uhd::usrp::dboard_interface::SPI_EDGE_RISE: return USRP2_CLK_EDGE_RISE; - case uhd::usrp::dboard_interface::SPI_EDGE_FALL: return USRP2_CLK_EDGE_FALL; + case dboard_interface::spi_config_t::EDGE_RISE: return USRP2_CLK_EDGE_RISE; + case dboard_interface::spi_config_t::EDGE_FALL: return USRP2_CLK_EDGE_FALL; } throw std::invalid_argument("unknown spi edge type"); } -dboard_interface::byte_vector_t usrp2_dboard_interface::transact_spi( - spi_dev_t dev, - spi_edge_t edge, - const byte_vector_t &buf, +boost::uint32_t usrp2_dboard_interface::transact_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits, bool readback ){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO); - out_data.data.spi_args.dev = spi_dev_to_otw(dev); - out_data.data.spi_args.edge = spi_edge_to_otw(edge); + out_data.data.spi_args.dev = unit_to_otw_dev(unit); + out_data.data.spi_args.miso_edge = spi_edge_to_otw(config.miso_edge); + out_data.data.spi_args.mosi_edge = spi_edge_to_otw(config.mosi_edge); out_data.data.spi_args.readback = (readback)? 1 : 0; - out_data.data.spi_args.bytes = buf.size(); - - //limitation of spi transaction size - ASSERT_THROW(buf.size() <= sizeof(out_data.data.spi_args.data)); - - //copy in the data - std::copy(buf.begin(), buf.end(), out_data.data.spi_args.data); + out_data.data.spi_args.num_bits = num_bits; + out_data.data.spi_args.data = htonl(data); //send and recv usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE); - ASSERT_THROW(in_data.data.spi_args.bytes == buf.size()); - //copy out the data - byte_vector_t result(buf.size()); - std::copy(in_data.data.spi_args.data, in_data.data.spi_args.data + buf.size(), result.begin()); - return result; + return ntohl(out_data.data.spi_args.data); } /*********************************************************************** @@ -245,19 +264,19 @@ dboard_interface::byte_vector_t usrp2_dboard_interface::read_i2c(int i2c_addr, s * \param unit the dboard interface unit type enum * \return an over the wire representation */ -static boost::uint8_t spi_dev_to_otw(dboard_interface::unit_type_t unit){ +static boost::uint8_t unit_to_otw(dboard_interface::unit_type_t unit){ switch(unit){ - case uhd::usrp::dboard_interface::UNIT_TYPE_TX: return USRP2_DIR_TX; - case uhd::usrp::dboard_interface::UNIT_TYPE_RX: return USRP2_DIR_RX; + case dboard_interface::UNIT_TYPE_TX: return USRP2_DIR_TX; + case dboard_interface::UNIT_TYPE_RX: return USRP2_DIR_RX; } throw std::invalid_argument("unknown unit type type"); } -void usrp2_dboard_interface::write_aux_dac(dboard_interface::unit_type_t unit, int which, int value){ +void usrp2_dboard_interface::write_aux_dac(unit_type_t unit, int which, int value){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_WRITE_THIS_TO_THE_AUX_DAC_BRO); - out_data.data.aux_args.dir = spi_dev_to_otw(unit); + out_data.data.aux_args.dir = unit_to_otw(unit); out_data.data.aux_args.which = which; out_data.data.aux_args.value = htonl(value); @@ -266,11 +285,11 @@ void usrp2_dboard_interface::write_aux_dac(dboard_interface::unit_type_t unit, i ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE); } -int usrp2_dboard_interface::read_aux_adc(dboard_interface::unit_type_t unit, int which){ +int usrp2_dboard_interface::read_aux_adc(unit_type_t unit, int which){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_READ_FROM_THIS_AUX_ADC_BRO); - out_data.data.aux_args.dir = spi_dev_to_otw(unit); + out_data.data.aux_args.dir = unit_to_otw(unit); out_data.data.aux_args.which = which; //send and recv diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 019f3b931..b600a2a70 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -110,10 +110,11 @@ typedef struct{ } dboard_ids; struct { _SINS_ uint8_t dev; - _SINS_ uint8_t edge; + _SINS_ uint8_t miso_edge; + _SINS_ uint8_t mosi_edge; _SINS_ uint8_t readback; - _SINS_ uint8_t bytes; - _SINS_ uint8_t data[sizeof(_SINS_ uint32_t)]; + _SINS_ uint32_t data; + _SINS_ uint8_t num_bits; } spi_args; struct { _SINS_ uint8_t addr; -- cgit v1.2.3 From 40c231937e1ab4fb70ffb241a5ddb2455db0e907 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 12 Apr 2010 16:10:29 -0700 Subject: moved spi transact to usrp2 impl, and removed spi read --- host/include/uhd/usrp/dboard_interface.hpp | 68 ++++++++++++------------------ host/lib/usrp/dboard/db_rfx.cpp | 2 +- host/lib/usrp/usrp2/dboard_interface.cpp | 60 ++++++-------------------- host/lib/usrp/usrp2/usrp2_impl.cpp | 32 +++++++++++++- host/lib/usrp/usrp2/usrp2_impl.hpp | 9 ++++ 5 files changed, 80 insertions(+), 91 deletions(-) (limited to 'host/lib/usrp/dboard/db_rfx.cpp') diff --git a/host/include/uhd/usrp/dboard_interface.hpp b/host/include/uhd/usrp/dboard_interface.hpp index dab5a2281..43fd1f143 100644 --- a/host/include/uhd/usrp/dboard_interface.hpp +++ b/host/include/uhd/usrp/dboard_interface.hpp @@ -25,6 +25,33 @@ namespace uhd{ namespace usrp{ +//spi configuration struct +struct UHD_API spi_config_t{ + /*! + * The edge type specifies when data is valid + * relative to the edge of the serial clock. + */ + enum edge_t{ + EDGE_RISE = 'r', + EDGE_FALL = 'f' + }; + + //! on what edge is the mosi data valid? + edge_t mosi_edge; + + //! on what edge is the miso data valid? + edge_t miso_edge; + + /*! + * Create a new spi config. + * \param edge the default edge for mosi and miso + */ + spi_config_t(edge_t edge = EDGE_RISE){ + mosi_edge = edge; + miso_edge = edge; + } +}; + /*! * The daughter board dboard_interface to be subclassed. * A dboard instance dboard_interfaces with the mboard though this api. @@ -42,33 +69,6 @@ public: UNIT_TYPE_TX = 't' }; - //spi configuration struct - struct UHD_API spi_config_t{ - /*! - * The edge type specifies when data is valid - * relative to the edge of the serial clock. - */ - enum edge_t{ - EDGE_RISE = 'r', - EDGE_FALL = 'f' - }; - - //! on what edge is the mosi data valid? - edge_t mosi_edge; - - //! on what edge is the miso data valid? - edge_t miso_edge; - - /*! - * Create a new spi config. - * \param edge the default edge for mosi and miso - */ - spi_config_t(edge_t edge = EDGE_RISE){ - mosi_edge = edge; - miso_edge = edge; - } - }; - //tell the host which gpio bank enum gpio_bank_t{ GPIO_BANK_RX = 'r', @@ -154,20 +154,6 @@ public: size_t num_bits ) = 0; - /*! - * \brief Read data to SPI bus peripheral. - * - * \param unit which unit, rx or tx - * \param config configuration settings - * \param num_bits the number of bits - * \return the data that was read - */ - virtual boost::uint32_t read_spi( - unit_type_t unit, - const spi_config_t &config, - size_t num_bits - ) = 0; - /*! * \brief Read and write data to SPI bus peripheral. * The data read back will be the same length as the input buffer. diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 68fa51144..4bf931660 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -138,7 +138,7 @@ void rfx_xcvr::reload_adf4360_regs(void){ BOOST_FOREACH(adf4360_regs_t::addr_t addr, addrs){ this->get_interface()->write_spi( dboard_interface::UNIT_TYPE_TX, - dboard_interface::spi_config_t::EDGE_RISE, + spi_config_t::EDGE_RISE, _adf4360_regs.get_reg(addr), 24 ); } diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp index eee7c087a..d10cfa37e 100644 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ b/host/lib/usrp/usrp2/dboard_interface.cpp @@ -47,32 +47,16 @@ public: const spi_config_t &config, boost::uint32_t data, size_t num_bits - ){ - transact_spi(unit, config, data, num_bits, false /*no rb*/); - } - - boost::uint32_t read_spi( - unit_type_t unit, - const spi_config_t &config, - size_t num_bits - ){ - return transact_spi(unit, config, 0, num_bits, true /*rb*/); - } + ); boost::uint32_t read_write_spi( unit_type_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits - ){ - return transact_spi(unit, config, data, num_bits, true /*rb*/); - } - -private: - boost::uint32_t transact_spi( - unit_type_t, const spi_config_t &, boost::uint32_t, size_t, bool ); +private: usrp2_impl *_impl; boost::uint32_t _ddr_shadow; }; @@ -175,42 +159,22 @@ static boost::uint8_t unit_to_otw_dev(dboard_interface::unit_type_t unit){ throw std::invalid_argument("unknown unit type type"); } -/*! - * Static function to convert a spi edge enum - * to an over-the-wire value for the usrp2 control. - * \param edge the dboard interface spi edge enum - * \return an over the wire representation - */ -static boost::uint8_t spi_edge_to_otw(dboard_interface::spi_config_t::edge_t edge){ - switch(edge){ - case dboard_interface::spi_config_t::EDGE_RISE: return USRP2_CLK_EDGE_RISE; - case dboard_interface::spi_config_t::EDGE_FALL: return USRP2_CLK_EDGE_FALL; - } - throw std::invalid_argument("unknown spi edge type"); +void usrp2_dboard_interface::write_spi( + unit_type_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits +){ + _impl->transact_spi(unit_to_otw_dev(unit), config, data, num_bits, false /*no rb*/); } -boost::uint32_t usrp2_dboard_interface::transact_spi( +boost::uint32_t usrp2_dboard_interface::read_write_spi( unit_type_t unit, const spi_config_t &config, boost::uint32_t data, - size_t num_bits, - bool readback + size_t num_bits ){ - //setup the out data - usrp2_ctrl_data_t out_data; - out_data.id = htonl(USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO); - out_data.data.spi_args.dev = unit_to_otw_dev(unit); - out_data.data.spi_args.miso_edge = spi_edge_to_otw(config.miso_edge); - out_data.data.spi_args.mosi_edge = spi_edge_to_otw(config.mosi_edge); - out_data.data.spi_args.readback = (readback)? 1 : 0; - out_data.data.spi_args.num_bits = num_bits; - out_data.data.spi_args.data = htonl(data); - - //send and recv - usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data); - ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE); - - return ntohl(out_data.data.spi_args.data); + return _impl->transact_spi(unit_to_otw_dev(unit), config, data, num_bits, true /*rb*/); } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index a7be2da8c..6d8c1a86c 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -15,15 +15,16 @@ // along with this program. If not, see . // +#include "usrp2_impl.hpp" #include #include #include #include +#include #include #include #include #include -#include "usrp2_impl.hpp" using namespace uhd; using namespace uhd::usrp; @@ -217,6 +218,35 @@ boost::uint16_t usrp2_impl::peek16(boost::uint32_t addr){ return impl_peek(this, addr); } +boost::uint32_t usrp2_impl::transact_spi( + int which_slave, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits, + bool readback +){ + static const uhd::dict spi_edge_to_otw = boost::assign::map_list_of + (spi_config_t::EDGE_RISE, USRP2_CLK_EDGE_RISE) + (spi_config_t::EDGE_FALL, USRP2_CLK_EDGE_FALL) + ; + + //setup the out data + usrp2_ctrl_data_t out_data; + out_data.id = htonl(USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO); + out_data.data.spi_args.dev = which_slave; + out_data.data.spi_args.miso_edge = spi_edge_to_otw[config.miso_edge]; + out_data.data.spi_args.mosi_edge = spi_edge_to_otw[config.mosi_edge]; + out_data.data.spi_args.readback = (readback)? 1 : 0; + out_data.data.spi_args.num_bits = num_bits; + out_data.data.spi_args.data = htonl(data); + + //send and recv + usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data); + ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE); + + return ntohl(out_data.data.spi_args.data); +} + /*********************************************************************** * Control Send/Recv **********************************************************************/ diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 4e7154afa..5a02b33dc 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -110,6 +110,15 @@ public: void poke16(boost::uint32_t addr, boost::uint16_t data); boost::uint16_t peek16(boost::uint32_t addr); + //spi read and write + boost::uint32_t transact_spi( + int which_slave, + const uhd::usrp::spi_config_t &config, + boost::uint32_t data, + size_t num_bits, + bool readback + ); + //misc access methods double get_master_clock_freq(void); -- cgit v1.2.3 From 389a72ef592d9826eac67ab001da5734909dbfcd Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 12 Apr 2010 16:52:18 -0700 Subject: merged unit type and gpio bank for dboard interface into one type, expanded dboard clock config api --- host/include/uhd/usrp/dboard_interface.hpp | 79 ++++++++++++++----------- host/lib/usrp/dboard/db_rfx.cpp | 2 +- host/lib/usrp/dboard_manager.cpp | 8 +-- host/lib/usrp/usrp2/dboard_interface.cpp | 93 ++++++++++++++++-------------- host/lib/usrp/usrp2/io_impl.cpp | 1 - 5 files changed, 98 insertions(+), 85 deletions(-) (limited to 'host/lib/usrp/dboard/db_rfx.cpp') diff --git a/host/include/uhd/usrp/dboard_interface.hpp b/host/include/uhd/usrp/dboard_interface.hpp index 43fd1f143..2fa05c09d 100644 --- a/host/include/uhd/usrp/dboard_interface.hpp +++ b/host/include/uhd/usrp/dboard_interface.hpp @@ -56,7 +56,7 @@ struct UHD_API spi_config_t{ * The daughter board dboard_interface to be subclassed. * A dboard instance dboard_interfaces with the mboard though this api. * This dboard_interface provides i2c, spi, gpio, atr, aux dac/adc access. - * Each mboard should have a specially tailored dboard dboard_interface. + * Each mboard should have a specially tailored interface for its dboard. */ class UHD_API dboard_interface{ public: @@ -64,15 +64,9 @@ public: typedef std::vector byte_vector_t; //tells the host which unit to use - enum unit_type_t{ - UNIT_TYPE_RX = 'r', - UNIT_TYPE_TX = 't' - }; - - //tell the host which gpio bank - enum gpio_bank_t{ - GPIO_BANK_RX = 'r', - GPIO_BANK_TX = 't' + enum unit_t{ + UNIT_RX = 'r', + UNIT_TX = 't' }; //possible atr registers @@ -85,54 +79,58 @@ public: /*! * Write to an aux dac. + * * \param unit which unit rx or tx * \param which_dac the dac index 0, 1, 2, 3... * \param value the value to write */ - virtual void write_aux_dac(unit_type_t unit, int which_dac, int value) = 0; + virtual void write_aux_dac(unit_t unit, int which_dac, int value) = 0; /*! * Read from an aux adc. + * * \param unit which unit rx or tx * \param which_adc the adc index 0, 1, 2, 3... * \return the value that was read */ - virtual int read_aux_adc(unit_type_t unit, int which_adc) = 0; + virtual int read_aux_adc(unit_t unit, int which_adc) = 0; /*! * Set a daughterboard ATR register. * - * \param bank GPIO_TX_BANK or GPIO_RX_BANK - * \param reg which ATR register to set - * \param value 16-bits, 0=FPGA output low, 1=FPGA output high + * \param unit which unit rx or tx + * \param reg which ATR register to set + * \param value 16-bits, 0=FPGA output low, 1=FPGA output high */ - virtual void set_atr_reg(gpio_bank_t bank, atr_reg_t reg, boost::uint16_t value) = 0; + virtual void set_atr_reg(unit_t unit, atr_reg_t reg, boost::uint16_t value) = 0; /*! * Set daughterboard GPIO data direction register. * - * \param bank GPIO_TX_BANK or GPIO_RX_BANK - * \param value 16-bits, 0=FPGA input, 1=FPGA output + * \param unit which unit rx or tx + * \param value 16-bits, 0=FPGA input, 1=FPGA output */ - virtual void set_gpio_ddr(gpio_bank_t bank, boost::uint16_t value) = 0; + virtual void set_gpio_ddr(unit_t unit, boost::uint16_t value) = 0; /*! - * Read daughterboard GPIO pin values + * Read daughterboard GPIO pin values. * - * \param bank GPIO_TX_BANK or GPIO_RX_BANK - * \return the value of the gpio bank + * \param unit which unit rx or tx + * \return the value of the gpio unit */ - virtual boost::uint16_t read_gpio(gpio_bank_t bank) = 0; + virtual boost::uint16_t read_gpio(unit_t unit) = 0; /*! - * \brief Write to I2C peripheral + * Write to an I2C peripheral. + * * \param i2c_addr I2C bus address (7-bits) * \param buf the data to write */ virtual void write_i2c(int i2c_addr, const byte_vector_t &buf) = 0; /*! - * \brief Read from I2C peripheral + * Read from an I2C peripheral. + * * \param i2c_addr I2C bus address (7-bits) * \param num_bytes number of bytes to read * \return the data read if successful, else a zero length string. @@ -140,7 +138,7 @@ public: virtual byte_vector_t read_i2c(int i2c_addr, size_t num_bytes) = 0; /*! - * \brief Write data to SPI bus peripheral. + * Write data to SPI bus peripheral. * * \param unit which unit, rx or tx * \param config configuration settings @@ -148,15 +146,14 @@ public: * \param num_bits the number of bits in data */ virtual void write_spi( - unit_type_t unit, + unit_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits ) = 0; /*! - * \brief Read and write data to SPI bus peripheral. - * The data read back will be the same length as the input buffer. + * Read and write data to SPI bus peripheral. * * \param unit which unit, rx or tx * \param config configuration settings @@ -165,23 +162,35 @@ public: * \return the data that was read */ virtual boost::uint32_t read_write_spi( - unit_type_t unit, + unit_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits ) = 0; /*! - * \brief Get the rate of the rx dboard clock. + * Get the rate of a dboard clock. + * + * \param unit which unit rx or tx * \return the clock rate in Hz */ - virtual double get_rx_clock_rate(void) = 0; + virtual double get_clock_rate(unit_t unit) = 0; /*! - * \brief Get the rate of the tx dboard clock. - * \return the clock rate in Hz + * Enable or disable a dboard clock. + * + * \param unit which unit rx or tx + * \param enb true for enabled + */ + virtual void set_clock_enabled(unit_t unit, bool enb) = 0; + + /*! + * Get the enabled status of a dboard block. + * + * \param unit which unit rx or tx + * \return true for enabled */ - virtual double get_tx_clock_rate(void) = 0; + virtual bool get_clock_enabled(unit_t unit) = 0; }; }} //namespace diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 4bf931660..60f6b1a60 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -137,7 +137,7 @@ void rfx_xcvr::reload_adf4360_regs(void){ ; BOOST_FOREACH(adf4360_regs_t::addr_t addr, addrs){ this->get_interface()->write_spi( - dboard_interface::UNIT_TYPE_TX, + dboard_interface::UNIT_TX, spi_config_t::EDGE_RISE, _adf4360_regs.get_reg(addr), 24 ); diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 4cf2e5820..f8ff38c39 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -276,9 +276,9 @@ wax::obj dboard_manager_impl::get_tx_subdev(const std::string &subdev_name){ void dboard_manager_impl::set_nice_gpio_pins(void){ //std::cout << "Set nice GPIO pins" << std::endl; - _interface->set_gpio_ddr(dboard_interface::GPIO_BANK_RX, 0x0000); //all inputs - _interface->set_atr_reg(dboard_interface::GPIO_BANK_RX, dboard_interface::ATR_REG_IDLE, 0x0000); //all low + _interface->set_gpio_ddr(dboard_interface::UNIT_RX, 0x0000); //all inputs + _interface->set_atr_reg(dboard_interface::UNIT_RX, dboard_interface::ATR_REG_IDLE, 0x0000); //all low - _interface->set_gpio_ddr(dboard_interface::GPIO_BANK_TX, 0x0000); //all inputs - _interface->set_atr_reg(dboard_interface::GPIO_BANK_TX, dboard_interface::ATR_REG_IDLE, 0x0000); //all low + _interface->set_gpio_ddr(dboard_interface::UNIT_TX, 0x0000); //all inputs + _interface->set_atr_reg(dboard_interface::UNIT_TX, dboard_interface::ATR_REG_IDLE, 0x0000); //all low } diff --git a/host/lib/usrp/usrp2/dboard_interface.cpp b/host/lib/usrp/usrp2/dboard_interface.cpp index d10cfa37e..db8679b9b 100644 --- a/host/lib/usrp/usrp2/dboard_interface.cpp +++ b/host/lib/usrp/usrp2/dboard_interface.cpp @@ -29,28 +29,29 @@ public: usrp2_dboard_interface(usrp2_impl *impl); ~usrp2_dboard_interface(void); - void write_aux_dac(unit_type_t, int, int); - int read_aux_adc(unit_type_t, int); + void write_aux_dac(unit_t, int, int); + int read_aux_adc(unit_t, int); - void set_atr_reg(gpio_bank_t, atr_reg_t, boost::uint16_t); - void set_gpio_ddr(gpio_bank_t, boost::uint16_t); - boost::uint16_t read_gpio(gpio_bank_t); + void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t); + void set_gpio_ddr(unit_t, boost::uint16_t); + boost::uint16_t read_gpio(unit_t); void write_i2c(int, const byte_vector_t &); byte_vector_t read_i2c(int, size_t); - double get_rx_clock_rate(void); - double get_tx_clock_rate(void); + double get_clock_rate(unit_t); + void set_clock_enabled(unit_t, bool); + bool get_clock_enabled(unit_t); void write_spi( - unit_type_t unit, + unit_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits ); boost::uint32_t read_write_spi( - unit_type_t unit, + unit_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits @@ -89,57 +90,61 @@ usrp2_dboard_interface::~usrp2_dboard_interface(void){ } /*********************************************************************** - * Clock Rates + * Clocks **********************************************************************/ -double usrp2_dboard_interface::get_rx_clock_rate(void){ +double usrp2_dboard_interface::get_clock_rate(unit_t){ return _impl->get_master_clock_freq(); } -double usrp2_dboard_interface::get_tx_clock_rate(void){ - return _impl->get_master_clock_freq(); +void usrp2_dboard_interface::set_clock_enabled(unit_t, bool){ + //TODO +} + +bool usrp2_dboard_interface::get_clock_enabled(unit_t){ + return false; //TODO } /*********************************************************************** * GPIO **********************************************************************/ -static int bank_to_shift(dboard_interface::gpio_bank_t bank){ - switch(bank){ - case dboard_interface::GPIO_BANK_RX: return 0; - case dboard_interface::GPIO_BANK_TX: return 16; +static int unit_to_shift(dboard_interface::unit_t unit){ + switch(unit){ + case dboard_interface::UNIT_RX: return 0; + case dboard_interface::UNIT_TX: return 16; } - throw std::runtime_error("unknown gpio bank type"); + throw std::runtime_error("unknown unit type"); } -void usrp2_dboard_interface::set_gpio_ddr(gpio_bank_t bank, boost::uint16_t value){ +void usrp2_dboard_interface::set_gpio_ddr(unit_t unit, boost::uint16_t value){ _ddr_shadow = \ - (_ddr_shadow & ~(0xffff << bank_to_shift(bank))) | - (boost::uint32_t(value) << bank_to_shift(bank)); + (_ddr_shadow & ~(0xffff << unit_to_shift(unit))) | + (boost::uint32_t(value) << unit_to_shift(unit)); _impl->poke32(FR_GPIO_DDR, _ddr_shadow); } -boost::uint16_t usrp2_dboard_interface::read_gpio(gpio_bank_t bank){ - return boost::uint16_t(_impl->peek32(FR_GPIO_IO) >> bank_to_shift(bank)); +boost::uint16_t usrp2_dboard_interface::read_gpio(unit_t unit){ + return boost::uint16_t(_impl->peek32(FR_GPIO_IO) >> unit_to_shift(unit)); } -void usrp2_dboard_interface::set_atr_reg(gpio_bank_t bank, atr_reg_t atr, boost::uint16_t value){ - //define mapping of bank to atr regs to register address +void usrp2_dboard_interface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ + //define mapping of unit to atr regs to register address static const uhd::dict< - gpio_bank_t, uhd::dict - > bank_to_atr_to_addr = boost::assign::map_list_of - (GPIO_BANK_RX, boost::assign::map_list_of + unit_t, uhd::dict + > unit_to_atr_to_addr = boost::assign::map_list_of + (UNIT_RX, boost::assign::map_list_of (ATR_REG_IDLE, FR_ATR_IDLE_RXSIDE) (ATR_REG_TX_ONLY, FR_ATR_INTX_RXSIDE) (ATR_REG_RX_ONLY, FR_ATR_INRX_RXSIDE) (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_RXSIDE) ) - (GPIO_BANK_TX, boost::assign::map_list_of + (UNIT_TX, boost::assign::map_list_of (ATR_REG_IDLE, FR_ATR_IDLE_TXSIDE) (ATR_REG_TX_ONLY, FR_ATR_INTX_TXSIDE) (ATR_REG_RX_ONLY, FR_ATR_INRX_TXSIDE) (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_TXSIDE) ) ; - _impl->poke16(bank_to_atr_to_addr[bank][atr], value); + _impl->poke16(unit_to_atr_to_addr[unit][atr], value); } /*********************************************************************** @@ -151,30 +156,30 @@ void usrp2_dboard_interface::set_atr_reg(gpio_bank_t bank, atr_reg_t atr, boost: * \param unit the dboard interface unit type enum * \return an over the wire representation */ -static boost::uint8_t unit_to_otw_dev(dboard_interface::unit_type_t unit){ +static boost::uint8_t unit_to_otw_spi_dev(dboard_interface::unit_t unit){ switch(unit){ - case dboard_interface::UNIT_TYPE_TX: return SPI_SS_TX_DB; - case dboard_interface::UNIT_TYPE_RX: return SPI_SS_RX_DB; + case dboard_interface::UNIT_TX: return SPI_SS_TX_DB; + case dboard_interface::UNIT_RX: return SPI_SS_RX_DB; } - throw std::invalid_argument("unknown unit type type"); + throw std::invalid_argument("unknown unit type"); } void usrp2_dboard_interface::write_spi( - unit_type_t unit, + unit_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits ){ - _impl->transact_spi(unit_to_otw_dev(unit), config, data, num_bits, false /*no rb*/); + _impl->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/); } boost::uint32_t usrp2_dboard_interface::read_write_spi( - unit_type_t unit, + unit_t unit, const spi_config_t &config, boost::uint32_t data, size_t num_bits ){ - return _impl->transact_spi(unit_to_otw_dev(unit), config, data, num_bits, true /*rb*/); + return _impl->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, true /*rb*/); } /*********************************************************************** @@ -228,15 +233,15 @@ dboard_interface::byte_vector_t usrp2_dboard_interface::read_i2c(int i2c_addr, s * \param unit the dboard interface unit type enum * \return an over the wire representation */ -static boost::uint8_t unit_to_otw(dboard_interface::unit_type_t unit){ +static boost::uint8_t unit_to_otw(dboard_interface::unit_t unit){ switch(unit){ - case dboard_interface::UNIT_TYPE_TX: return USRP2_DIR_TX; - case dboard_interface::UNIT_TYPE_RX: return USRP2_DIR_RX; + case dboard_interface::UNIT_TX: return USRP2_DIR_TX; + case dboard_interface::UNIT_RX: return USRP2_DIR_RX; } - throw std::invalid_argument("unknown unit type type"); + throw std::invalid_argument("unknown unit type"); } -void usrp2_dboard_interface::write_aux_dac(unit_type_t unit, int which, int value){ +void usrp2_dboard_interface::write_aux_dac(unit_t unit, int which, int value){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_WRITE_THIS_TO_THE_AUX_DAC_BRO); @@ -249,7 +254,7 @@ void usrp2_dboard_interface::write_aux_dac(unit_type_t unit, int which, int valu ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE); } -int usrp2_dboard_interface::read_aux_adc(unit_type_t unit, int which){ +int usrp2_dboard_interface::read_aux_adc(unit_t unit, int which){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_READ_FROM_THIS_AUX_ADC_BRO); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index a760cbe3d..87fc88ceb 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -18,7 +18,6 @@ #include "usrp2_impl.hpp" #include #include -#include #include using namespace uhd; -- cgit v1.2.3 From 91319520a5bd2b4cd875988b6c173435df1dbc47 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 13 Apr 2010 18:48:16 -0700 Subject: work on rfx atr regs --- host/lib/usrp/dboard/db_rfx.cpp | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'host/lib/usrp/dboard/db_rfx.cpp') diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 60f6b1a60..1cb39f83c 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -15,6 +15,12 @@ // along with this program. If not, see . // +// IO Pin functions +#define POWER_UP (1 << 7) // Low enables power supply +#define ANT_SW (1 << 6) // On TX DB, 0 = TX, 1 = RX, on RX DB 0 = main ant, 1 = RX2 +#define MIX_EN (1 << 5) // Enable appropriate mixer +#define LOCKDET_MASK (1 << 2) // Input pin + #include "adf4360_regs.hpp" #include #include @@ -104,6 +110,23 @@ rfx_xcvr::rfx_xcvr( const freq_range_t &freq_range ) : xcvr_dboard_base(args){ _freq_range = freq_range; + + //enable the clocks that we need + this->get_interface()->set_clock_enabled(dboard_interface::UNIT_TX, true); + this->get_interface()->set_clock_enabled(dboard_interface::UNIT_RX, true); + + //set the gpio directions + boost::uint16_t output_enables = POWER_UP | ANT_SW | MIX_EN; + this->get_interface()->set_gpio_ddr(dboard_interface::UNIT_TX, output_enables); + this->get_interface()->set_gpio_ddr(dboard_interface::UNIT_RX, output_enables); + + //setup the tx atr (this does not change with antenna) + this->get_interface()->set_atr_reg(dboard_interface::UNIT_TX, dboard_interface::ATR_REG_IDLE, POWER_UP | ANT_SW); + this->get_interface()->set_atr_reg(dboard_interface::UNIT_TX, dboard_interface::ATR_REG_RX_ONLY, POWER_UP | ANT_SW); + this->get_interface()->set_atr_reg(dboard_interface::UNIT_TX, dboard_interface::ATR_REG_TX_ONLY, POWER_UP | MIX_EN); + this->get_interface()->set_atr_reg(dboard_interface::UNIT_TX, dboard_interface::ATR_REG_FULL_DUPLEX, POWER_UP | MIX_EN); + + //set some default values set_lo_freq((_freq_range.min + _freq_range.max)/2.0); set_rx_ant("rx2"); set_rx_pga0_gain(0); @@ -122,7 +145,13 @@ void rfx_xcvr::set_lo_freq(double freq){ } void rfx_xcvr::set_rx_ant(const std::string &ant){ - /* NOP */ + boost::uint16_t ant_val = (ant == "tx/rx")? 0 : ANT_SW; + + //set the rx atr regs + this->get_interface()->set_atr_reg(dboard_interface::UNIT_RX, dboard_interface::ATR_REG_IDLE, POWER_UP | ant_val); + this->get_interface()->set_atr_reg(dboard_interface::UNIT_RX, dboard_interface::ATR_REG_RX_ONLY, POWER_UP | ant_val | MIX_EN); + this->get_interface()->set_atr_reg(dboard_interface::UNIT_RX, dboard_interface::ATR_REG_TX_ONLY, POWER_UP | ant_val); + this->get_interface()->set_atr_reg(dboard_interface::UNIT_RX, dboard_interface::ATR_REG_FULL_DUPLEX, POWER_UP | ant_val | MIX_EN); } void rfx_xcvr::set_rx_pga0_gain(float gain){ -- cgit v1.2.3 From e2a9419385bee4d08862553ddd0a637964557272 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 14 Apr 2010 08:41:13 -0700 Subject: renamed dboard interface to dboard iface, the lengthy name was getting to be a burden --- host/include/uhd/usrp/dboard_base.hpp | 10 +- host/include/uhd/usrp/dboard_iface.hpp | 190 +++++++++++++++++++++++++++++ host/include/uhd/usrp/dboard_interface.hpp | 190 ----------------------------- host/include/uhd/usrp/dboard_manager.hpp | 6 +- host/lib/usrp/dboard/db_rfx.cpp | 28 ++--- host/lib/usrp/dboard_base.cpp | 6 +- host/lib/usrp/dboard_manager.cpp | 34 +++--- host/lib/usrp/usrp2/dboard_iface.cpp | 26 ++-- host/lib/usrp/usrp2/dboard_impl.cpp | 4 +- host/lib/usrp/usrp2/usrp2_iface.hpp | 2 +- host/lib/usrp/usrp2/usrp2_impl.hpp | 2 +- 11 files changed, 249 insertions(+), 249 deletions(-) create mode 100644 host/include/uhd/usrp/dboard_iface.hpp delete mode 100644 host/include/uhd/usrp/dboard_interface.hpp (limited to 'host/lib/usrp/dboard/db_rfx.cpp') diff --git a/host/include/uhd/usrp/dboard_base.hpp b/host/include/uhd/usrp/dboard_base.hpp index 907a7814a..2025760ee 100644 --- a/host/include/uhd/usrp/dboard_base.hpp +++ b/host/include/uhd/usrp/dboard_base.hpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include namespace uhd{ namespace usrp{ @@ -35,10 +35,10 @@ namespace uhd{ namespace usrp{ class UHD_API dboard_base : boost::noncopyable{ public: typedef boost::shared_ptr sptr; - //the constructor args consist of a subdev name and an interface + //the constructor args consist of a subdev name, interface, and ids //derived classes should pass the args into the dboard_base class ctor //but should not have to deal with the internals of the args - typedef boost::tuple ctor_args_t; + typedef boost::tuple ctor_args_t; //structors dboard_base(ctor_args_t const&); @@ -52,13 +52,13 @@ public: protected: std::string get_subdev_name(void); - dboard_interface::sptr get_interface(void); + dboard_iface::sptr get_iface(void); dboard_id_t get_rx_id(void); dboard_id_t get_tx_id(void); private: std::string _subdev_name; - dboard_interface::sptr _dboard_interface; + dboard_iface::sptr _dboard_iface; dboard_id_t _rx_id, _tx_id; }; diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp new file mode 100644 index 000000000..ca40bf778 --- /dev/null +++ b/host/include/uhd/usrp/dboard_iface.hpp @@ -0,0 +1,190 @@ +// +// 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 . +// + +#ifndef INCLUDED_UHD_USRP_DBOARD_IFACE_HPP +#define INCLUDED_UHD_USRP_DBOARD_IFACE_HPP + +#include +#include +#include +#include + +namespace uhd{ namespace usrp{ + +//spi configuration struct +struct UHD_API spi_config_t{ + /*! + * The edge type specifies when data is valid + * relative to the edge of the serial clock. + */ + enum edge_t{ + EDGE_RISE = 'r', + EDGE_FALL = 'f' + }; + + //! on what edge is the mosi data valid? + edge_t mosi_edge; + + //! on what edge is the miso data valid? + edge_t miso_edge; + + /*! + * Create a new spi config. + * \param edge the default edge for mosi and miso + */ + spi_config_t(edge_t edge = EDGE_RISE){ + mosi_edge = edge; + miso_edge = edge; + } +}; + +/*! + * The daughter board dboard interface to be subclassed. + * A dboard instance interfaces with the mboard though this api. + * This interface provides i2c, spi, gpio, atr, aux dac/adc access. + * Each mboard should have a specially tailored iface for its dboard. + */ +class UHD_API dboard_iface{ +public: + typedef boost::shared_ptr sptr; + typedef std::vector byte_vector_t; + + //tells the host which unit to use + enum unit_t{ + UNIT_RX = 'r', + UNIT_TX = 't' + }; + + //possible atr registers + enum atr_reg_t{ + ATR_REG_IDLE = 'i', + ATR_REG_TX_ONLY = 't', + ATR_REG_RX_ONLY = 'r', + ATR_REG_FULL_DUPLEX = 'f' + }; + + /*! + * Write to an aux dac. + * + * \param unit which unit rx or tx + * \param which_dac the dac index 0, 1, 2, 3... + * \param value the value to write + */ + virtual void write_aux_dac(unit_t unit, int which_dac, int value) = 0; + + /*! + * Read from an aux adc. + * + * \param unit which unit rx or tx + * \param which_adc the adc index 0, 1, 2, 3... + * \return the value that was read + */ + virtual int read_aux_adc(unit_t unit, int which_adc) = 0; + + /*! + * Set a daughterboard ATR register. + * + * \param unit which unit rx or tx + * \param reg which ATR register to set + * \param value 16-bits, 0=FPGA output low, 1=FPGA output high + */ + virtual void set_atr_reg(unit_t unit, atr_reg_t reg, boost::uint16_t value) = 0; + + /*! + * Set daughterboard GPIO data direction register. + * + * \param unit which unit rx or tx + * \param value 16-bits, 0=FPGA input, 1=FPGA output + */ + virtual void set_gpio_ddr(unit_t unit, boost::uint16_t value) = 0; + + /*! + * Read daughterboard GPIO pin values. + * + * \param unit which unit rx or tx + * \return the value of the gpio unit + */ + virtual boost::uint16_t read_gpio(unit_t unit) = 0; + + /*! + * Write to an I2C peripheral. + * + * \param i2c_addr I2C bus address (7-bits) + * \param buf the data to write + */ + virtual void write_i2c(int i2c_addr, const byte_vector_t &buf) = 0; + + /*! + * Read from an I2C peripheral. + * + * \param i2c_addr I2C bus address (7-bits) + * \param num_bytes number of bytes to read + * \return the data read if successful, else a zero length string. + */ + virtual byte_vector_t read_i2c(int i2c_addr, size_t num_bytes) = 0; + + /*! + * Write data to SPI bus peripheral. + * + * \param unit which unit, rx or tx + * \param config configuration settings + * \param data the bits to write LSB first + * \param num_bits the number of bits in data + */ + virtual void write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ) = 0; + + /*! + * Read and write data to SPI bus peripheral. + * + * \param unit which unit, rx or tx + * \param config configuration settings + * \param data the bits to write LSB first + * \param num_bits the number of bits in data + * \return the data that was read + */ + virtual boost::uint32_t read_write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ) = 0; + + /*! + * Get the rate of a dboard clock. + * + * \param unit which unit rx or tx + * \return the clock rate in Hz + */ + virtual double get_clock_rate(unit_t unit) = 0; + + /*! + * Enable or disable a dboard clock. + * + * \param unit which unit rx or tx + * \param enb true for enabled + */ + virtual void set_clock_enabled(unit_t unit, bool enb) = 0; +}; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_IFACE_HPP */ diff --git a/host/include/uhd/usrp/dboard_interface.hpp b/host/include/uhd/usrp/dboard_interface.hpp deleted file mode 100644 index c4e822751..000000000 --- a/host/include/uhd/usrp/dboard_interface.hpp +++ /dev/null @@ -1,190 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef INCLUDED_UHD_USRP_DBOARD_INTERFACE_HPP -#define INCLUDED_UHD_USRP_DBOARD_INTERFACE_HPP - -#include -#include -#include -#include - -namespace uhd{ namespace usrp{ - -//spi configuration struct -struct UHD_API spi_config_t{ - /*! - * The edge type specifies when data is valid - * relative to the edge of the serial clock. - */ - enum edge_t{ - EDGE_RISE = 'r', - EDGE_FALL = 'f' - }; - - //! on what edge is the mosi data valid? - edge_t mosi_edge; - - //! on what edge is the miso data valid? - edge_t miso_edge; - - /*! - * Create a new spi config. - * \param edge the default edge for mosi and miso - */ - spi_config_t(edge_t edge = EDGE_RISE){ - mosi_edge = edge; - miso_edge = edge; - } -}; - -/*! - * The daughter board dboard_interface to be subclassed. - * A dboard instance dboard_interfaces with the mboard though this api. - * This dboard_interface provides i2c, spi, gpio, atr, aux dac/adc access. - * Each mboard should have a specially tailored interface for its dboard. - */ -class UHD_API dboard_interface{ -public: - typedef boost::shared_ptr sptr; - typedef std::vector byte_vector_t; - - //tells the host which unit to use - enum unit_t{ - UNIT_RX = 'r', - UNIT_TX = 't' - }; - - //possible atr registers - enum atr_reg_t{ - ATR_REG_IDLE = 'i', - ATR_REG_TX_ONLY = 't', - ATR_REG_RX_ONLY = 'r', - ATR_REG_FULL_DUPLEX = 'f' - }; - - /*! - * Write to an aux dac. - * - * \param unit which unit rx or tx - * \param which_dac the dac index 0, 1, 2, 3... - * \param value the value to write - */ - virtual void write_aux_dac(unit_t unit, int which_dac, int value) = 0; - - /*! - * Read from an aux adc. - * - * \param unit which unit rx or tx - * \param which_adc the adc index 0, 1, 2, 3... - * \return the value that was read - */ - virtual int read_aux_adc(unit_t unit, int which_adc) = 0; - - /*! - * Set a daughterboard ATR register. - * - * \param unit which unit rx or tx - * \param reg which ATR register to set - * \param value 16-bits, 0=FPGA output low, 1=FPGA output high - */ - virtual void set_atr_reg(unit_t unit, atr_reg_t reg, boost::uint16_t value) = 0; - - /*! - * Set daughterboard GPIO data direction register. - * - * \param unit which unit rx or tx - * \param value 16-bits, 0=FPGA input, 1=FPGA output - */ - virtual void set_gpio_ddr(unit_t unit, boost::uint16_t value) = 0; - - /*! - * Read daughterboard GPIO pin values. - * - * \param unit which unit rx or tx - * \return the value of the gpio unit - */ - virtual boost::uint16_t read_gpio(unit_t unit) = 0; - - /*! - * Write to an I2C peripheral. - * - * \param i2c_addr I2C bus address (7-bits) - * \param buf the data to write - */ - virtual void write_i2c(int i2c_addr, const byte_vector_t &buf) = 0; - - /*! - * Read from an I2C peripheral. - * - * \param i2c_addr I2C bus address (7-bits) - * \param num_bytes number of bytes to read - * \return the data read if successful, else a zero length string. - */ - virtual byte_vector_t read_i2c(int i2c_addr, size_t num_bytes) = 0; - - /*! - * Write data to SPI bus peripheral. - * - * \param unit which unit, rx or tx - * \param config configuration settings - * \param data the bits to write LSB first - * \param num_bits the number of bits in data - */ - virtual void write_spi( - unit_t unit, - const spi_config_t &config, - boost::uint32_t data, - size_t num_bits - ) = 0; - - /*! - * Read and write data to SPI bus peripheral. - * - * \param unit which unit, rx or tx - * \param config configuration settings - * \param data the bits to write LSB first - * \param num_bits the number of bits in data - * \return the data that was read - */ - virtual boost::uint32_t read_write_spi( - unit_t unit, - const spi_config_t &config, - boost::uint32_t data, - size_t num_bits - ) = 0; - - /*! - * Get the rate of a dboard clock. - * - * \param unit which unit rx or tx - * \return the clock rate in Hz - */ - virtual double get_clock_rate(unit_t unit) = 0; - - /*! - * Enable or disable a dboard clock. - * - * \param unit which unit rx or tx - * \param enb true for enabled - */ - virtual void set_clock_enabled(unit_t unit, bool enb) = 0; -}; - -}} //namespace - -#endif /* INCLUDED_UHD_USRP_DBOARD_INTERFACE_HPP */ diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp index ed8ee73ef..6de64b02d 100644 --- a/host/include/uhd/usrp/dboard_manager.hpp +++ b/host/include/uhd/usrp/dboard_manager.hpp @@ -59,16 +59,16 @@ public: * Make a new dboard manager. * \param rx_dboard_id the id of the rx dboard * \param tx_dboard_id the id of the tx dboard - * \param interface the custom dboard interface + * \param iface the custom dboard interface * \return an sptr to the new dboard manager */ static sptr make( dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id, - dboard_interface::sptr interface + dboard_iface::sptr iface ); - //dboard_interface + //dboard manager interface virtual prop_names_t get_rx_subdev_names(void) = 0; virtual prop_names_t get_tx_subdev_names(void) = 0; virtual wax::obj get_rx_subdev(const std::string &subdev_name) = 0; diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 1cb39f83c..e5dc16808 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -112,19 +112,19 @@ rfx_xcvr::rfx_xcvr( _freq_range = freq_range; //enable the clocks that we need - this->get_interface()->set_clock_enabled(dboard_interface::UNIT_TX, true); - this->get_interface()->set_clock_enabled(dboard_interface::UNIT_RX, true); + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); //set the gpio directions boost::uint16_t output_enables = POWER_UP | ANT_SW | MIX_EN; - this->get_interface()->set_gpio_ddr(dboard_interface::UNIT_TX, output_enables); - this->get_interface()->set_gpio_ddr(dboard_interface::UNIT_RX, output_enables); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, output_enables); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, output_enables); //setup the tx atr (this does not change with antenna) - this->get_interface()->set_atr_reg(dboard_interface::UNIT_TX, dboard_interface::ATR_REG_IDLE, POWER_UP | ANT_SW); - this->get_interface()->set_atr_reg(dboard_interface::UNIT_TX, dboard_interface::ATR_REG_RX_ONLY, POWER_UP | ANT_SW); - this->get_interface()->set_atr_reg(dboard_interface::UNIT_TX, dboard_interface::ATR_REG_TX_ONLY, POWER_UP | MIX_EN); - this->get_interface()->set_atr_reg(dboard_interface::UNIT_TX, dboard_interface::ATR_REG_FULL_DUPLEX, POWER_UP | MIX_EN); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, POWER_UP | ANT_SW); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, POWER_UP | ANT_SW); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, POWER_UP | MIX_EN); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP | MIX_EN); //set some default values set_lo_freq((_freq_range.min + _freq_range.max)/2.0); @@ -148,10 +148,10 @@ void rfx_xcvr::set_rx_ant(const std::string &ant){ boost::uint16_t ant_val = (ant == "tx/rx")? 0 : ANT_SW; //set the rx atr regs - this->get_interface()->set_atr_reg(dboard_interface::UNIT_RX, dboard_interface::ATR_REG_IDLE, POWER_UP | ant_val); - this->get_interface()->set_atr_reg(dboard_interface::UNIT_RX, dboard_interface::ATR_REG_RX_ONLY, POWER_UP | ant_val | MIX_EN); - this->get_interface()->set_atr_reg(dboard_interface::UNIT_RX, dboard_interface::ATR_REG_TX_ONLY, POWER_UP | ant_val); - this->get_interface()->set_atr_reg(dboard_interface::UNIT_RX, dboard_interface::ATR_REG_FULL_DUPLEX, POWER_UP | ant_val | MIX_EN); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, POWER_UP | ant_val); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, POWER_UP | ant_val | MIX_EN); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, POWER_UP | ant_val); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP | ant_val | MIX_EN); } void rfx_xcvr::set_rx_pga0_gain(float gain){ @@ -165,8 +165,8 @@ void rfx_xcvr::reload_adf4360_regs(void){ (adf4360_regs_t::ADDR_RCOUNTER) ; BOOST_FOREACH(adf4360_regs_t::addr_t addr, addrs){ - this->get_interface()->write_spi( - dboard_interface::UNIT_TX, + this->get_iface()->write_spi( + dboard_iface::UNIT_TX, spi_config_t::EDGE_RISE, _adf4360_regs.get_reg(addr), 24 ); diff --git a/host/lib/usrp/dboard_base.cpp b/host/lib/usrp/dboard_base.cpp index 09d3bbfd4..68e4743d1 100644 --- a/host/lib/usrp/dboard_base.cpp +++ b/host/lib/usrp/dboard_base.cpp @@ -25,7 +25,7 @@ using namespace uhd::usrp; * dboard_base dboard dboard_base class **********************************************************************/ dboard_base::dboard_base(ctor_args_t const& args){ - boost::tie(_subdev_name, _dboard_interface, _rx_id, _tx_id) = args; + boost::tie(_subdev_name, _dboard_iface, _rx_id, _tx_id) = args; } dboard_base::~dboard_base(void){ @@ -36,8 +36,8 @@ std::string dboard_base::get_subdev_name(void){ return _subdev_name; } -dboard_interface::sptr dboard_base::get_interface(void){ - return _dboard_interface; +dboard_iface::sptr dboard_base::get_iface(void){ + return _dboard_iface; } dboard_id_t dboard_base::get_rx_id(void){ diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 5e62b5564..06f8c55b6 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -125,11 +125,11 @@ public: dboard_manager_impl( dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id, - dboard_interface::sptr interface + dboard_iface::sptr iface ); ~dboard_manager_impl(void); - //dboard_interface + //dboard_iface prop_names_t get_rx_subdev_names(void); prop_names_t get_tx_subdev_names(void); wax::obj get_rx_subdev(const std::string &subdev_name); @@ -141,7 +141,7 @@ private: //the subdevice proxy is internal to the cpp file uhd::dict _rx_dboards; uhd::dict _tx_dboards; - dboard_interface::sptr _interface; + dboard_iface::sptr _iface; void set_nice_dboard_if(void); }; @@ -151,10 +151,10 @@ private: dboard_manager::sptr dboard_manager::make( dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id, - dboard_interface::sptr interface + dboard_iface::sptr iface ){ return dboard_manager::sptr( - new dboard_manager_impl(rx_dboard_id, tx_dboard_id, interface) + new dboard_manager_impl(rx_dboard_id, tx_dboard_id, iface) ); } @@ -190,9 +190,9 @@ static args_t get_dboard_args( dboard_manager_impl::dboard_manager_impl( dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id, - dboard_interface::sptr interface + dboard_iface::sptr iface ){ - _interface = interface; + _iface = iface; dboard_ctor_t rx_dboard_ctor; std::string rx_name; prop_names_t rx_subdevs; boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_dboard_args(rx_dboard_id, "rx"); @@ -208,7 +208,7 @@ dboard_manager_impl::dboard_manager_impl( ASSERT_THROW(rx_subdevs == tx_subdevs); BOOST_FOREACH(const std::string &subdev, rx_subdevs){ dboard_base::sptr xcvr_dboard = rx_dboard_ctor( - dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, tx_dboard_id) + dboard_base::ctor_args_t(subdev, iface, rx_dboard_id, tx_dboard_id) ); //create a rx proxy for this xcvr board _rx_dboards[subdev] = subdev_proxy::sptr( @@ -226,7 +226,7 @@ dboard_manager_impl::dboard_manager_impl( //make the rx subdevs BOOST_FOREACH(const std::string &subdev, rx_subdevs){ dboard_base::sptr rx_dboard = rx_dboard_ctor( - dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, dboard_id::NONE) + dboard_base::ctor_args_t(subdev, iface, rx_dboard_id, dboard_id::NONE) ); //create a rx proxy for this rx board _rx_dboards[subdev] = subdev_proxy::sptr( @@ -236,7 +236,7 @@ dboard_manager_impl::dboard_manager_impl( //make the tx subdevs BOOST_FOREACH(const std::string &subdev, tx_subdevs){ dboard_base::sptr tx_dboard = tx_dboard_ctor( - dboard_base::ctor_args_t(subdev, interface, dboard_id::NONE, tx_dboard_id) + dboard_base::ctor_args_t(subdev, iface, dboard_id::NONE, tx_dboard_id) ); //create a tx proxy for this tx board _tx_dboards[subdev] = subdev_proxy::sptr( @@ -276,15 +276,15 @@ wax::obj dboard_manager_impl::get_tx_subdev(const std::string &subdev_name){ void dboard_manager_impl::set_nice_dboard_if(void){ //make a list of possible unit types - std::vector units = boost::assign::list_of - (dboard_interface::UNIT_RX) - (dboard_interface::UNIT_TX) + std::vector units = boost::assign::list_of + (dboard_iface::UNIT_RX) + (dboard_iface::UNIT_TX) ; //set nice settings on each unit - BOOST_FOREACH(dboard_interface::unit_t unit, units){ - _interface->set_gpio_ddr(unit, 0x0000); //all inputs - _interface->set_atr_reg(unit, dboard_interface::ATR_REG_IDLE, 0x0000); //all low - _interface->set_clock_enabled(unit, false); //clock off + BOOST_FOREACH(dboard_iface::unit_t unit, units){ + _iface->set_gpio_ddr(unit, 0x0000); //all inputs + _iface->set_atr_reg(unit, dboard_iface::ATR_REG_IDLE, 0x0000); //all low + _iface->set_clock_enabled(unit, false); //clock off } } diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index d0c4bf6c1..f77dfc495 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -26,7 +26,7 @@ using namespace uhd::usrp; -class usrp2_dboard_iface : public dboard_interface{ +class usrp2_dboard_iface : public dboard_iface{ public: usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::sptr clk_ctrl); ~usrp2_dboard_iface(void); @@ -68,11 +68,11 @@ private: /*********************************************************************** * Make Function **********************************************************************/ -dboard_interface::sptr make_usrp2_dboard_iface( +dboard_iface::sptr make_usrp2_dboard_iface( usrp2_iface::sptr iface, clock_control::sptr clk_ctrl ){ - return dboard_interface::sptr(new usrp2_dboard_iface(iface, clk_ctrl)); + return dboard_iface::sptr(new usrp2_dboard_iface(iface, clk_ctrl)); } /*********************************************************************** @@ -117,10 +117,10 @@ void usrp2_dboard_iface::set_clock_enabled(unit_t unit, bool enb){ /*********************************************************************** * GPIO **********************************************************************/ -static int unit_to_shift(dboard_interface::unit_t unit){ +static int unit_to_shift(dboard_iface::unit_t unit){ switch(unit){ - case dboard_interface::UNIT_RX: return 0; - case dboard_interface::UNIT_TX: return 16; + case dboard_iface::UNIT_RX: return 0; + case dboard_iface::UNIT_TX: return 16; } throw std::runtime_error("unknown unit type"); } @@ -166,10 +166,10 @@ void usrp2_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t * \param unit the dboard interface unit type enum * \return an over the wire representation */ -static boost::uint8_t unit_to_otw_spi_dev(dboard_interface::unit_t unit){ +static boost::uint8_t unit_to_otw_spi_dev(dboard_iface::unit_t unit){ switch(unit){ - case dboard_interface::UNIT_TX: return SPI_SS_TX_DB; - case dboard_interface::UNIT_RX: return SPI_SS_RX_DB; + case dboard_iface::UNIT_TX: return SPI_SS_TX_DB; + case dboard_iface::UNIT_RX: return SPI_SS_RX_DB; } throw std::invalid_argument("unknown unit type"); } @@ -213,7 +213,7 @@ void usrp2_dboard_iface::write_i2c(int i2c_addr, const byte_vector_t &buf){ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE); } -dboard_interface::byte_vector_t usrp2_dboard_iface::read_i2c(int i2c_addr, size_t num_bytes){ +dboard_iface::byte_vector_t usrp2_dboard_iface::read_i2c(int i2c_addr, size_t num_bytes){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO); @@ -243,10 +243,10 @@ dboard_interface::byte_vector_t usrp2_dboard_iface::read_i2c(int i2c_addr, size_ * \param unit the dboard interface unit type enum * \return an over the wire representation */ -static boost::uint8_t unit_to_otw(dboard_interface::unit_t unit){ +static boost::uint8_t unit_to_otw(dboard_iface::unit_t unit){ switch(unit){ - case dboard_interface::UNIT_TX: return USRP2_DIR_TX; - case dboard_interface::UNIT_RX: return USRP2_DIR_RX; + case dboard_iface::UNIT_TX: return USRP2_DIR_TX; + case dboard_iface::UNIT_RX: return USRP2_DIR_RX; } throw std::invalid_argument("unknown unit type"); } diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 4b300de68..fe74219d6 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -44,11 +44,11 @@ void usrp2_impl::dboard_init(void){ dboard_id_t tx_dboard_id = ntohs(in_data.data.dboard_ids.tx_id); //create a new dboard interface and manager - dboard_interface::sptr _dboard_interface( + dboard_iface::sptr _dboard_iface( make_usrp2_dboard_iface(_iface, _clk_ctrl) ); _dboard_manager = dboard_manager::make( - rx_dboard_id, tx_dboard_id, _dboard_interface + rx_dboard_id, tx_dboard_id, _dboard_iface ); //load dboards diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp index 7b4321c0b..1298d87f1 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.hpp +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -19,7 +19,7 @@ #define INCLUDED_USRP2_IFACE_HPP #include -#include //spi config +#include //spi config #include #include #include diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 7eea1e250..dbcee367b 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -37,7 +37,7 @@ * \param clk_ctrl the clock control object * \return a sptr to a new dboard interface */ -uhd::usrp::dboard_interface::sptr make_usrp2_dboard_iface( +uhd::usrp::dboard_iface::sptr make_usrp2_dboard_iface( usrp2_iface::sptr iface, clock_control::sptr clk_ctrl ); -- cgit v1.2.3 From 6d0a60b95777ba6f99a00b4e5ef63f845dfa0aec Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 14 Apr 2010 15:28:59 -0700 Subject: work on atr bits in rfx board --- host/lib/usrp/dboard/db_rfx.cpp | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'host/lib/usrp/dboard/db_rfx.cpp') diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index e5dc16808..b86546248 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -21,6 +21,13 @@ #define MIX_EN (1 << 5) // Enable appropriate mixer #define LOCKDET_MASK (1 << 2) // Input pin +// Antenna constants +#define ANT_TX 0 //the tx line is transmitting +#define ANT_RX ANT_SW //the tx line is receiving +#define ANT_TXRX 0 //the rx line is on txrx +#define ANT_RX2 ANT_SW //the rx line in on rx2 +#define ANT_XX 0 //dont care how the antenna is set + #include "adf4360_regs.hpp" #include #include @@ -121,10 +128,15 @@ rfx_xcvr::rfx_xcvr( this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, output_enables); //setup the tx atr (this does not change with antenna) - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, POWER_UP | ANT_SW); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, POWER_UP | ANT_SW); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, POWER_UP | MIX_EN); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP | MIX_EN); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, POWER_UP | ANT_XX); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, POWER_UP | ANT_RX); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, POWER_UP | ANT_TX | MIX_EN); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP | ANT_TX | MIX_EN); + + //setup the rx atr (this does not change with antenna) + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, POWER_UP | ANT_XX); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, POWER_UP | ANT_XX); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP | ANT_RX2 | MIX_EN); //set some default values set_lo_freq((_freq_range.min + _freq_range.max)/2.0); @@ -145,13 +157,11 @@ void rfx_xcvr::set_lo_freq(double freq){ } void rfx_xcvr::set_rx_ant(const std::string &ant){ - boost::uint16_t ant_val = (ant == "tx/rx")? 0 : ANT_SW; - - //set the rx atr regs - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, POWER_UP | ant_val); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, POWER_UP | ant_val | MIX_EN); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, POWER_UP | ant_val); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP | ant_val | MIX_EN); + //set the rx atr regs that change with antenna setting + this->get_iface()->set_atr_reg( + dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, + POWER_UP | MIX_EN | ((ant == "tx/rx")? ANT_TXRX : ANT_RX2) + ); } void rfx_xcvr::set_rx_pga0_gain(float gain){ -- cgit v1.2.3 From f57f616cfd6406cd67681813d464695c8c160f9e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 14 Apr 2010 17:19:27 -0700 Subject: Added gain control to rfx. Switched string constants to caps (gains, antennas, subdevs). Made dboard interface for aux dac and adc use volts. --- host/include/uhd/usrp/dboard_iface.hpp | 8 +++--- host/include/uhd/utils/algorithm.hpp | 6 +++- host/lib/usrp/dboard/db_basic_and_lf.cpp | 6 ++-- host/lib/usrp/dboard/db_rfx.cpp | 47 ++++++++++++++++++++++++-------- host/lib/usrp/usrp2/dboard_iface.cpp | 13 +++++---- 5 files changed, 55 insertions(+), 25 deletions(-) (limited to 'host/lib/usrp/dboard/db_rfx.cpp') diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp index ca40bf778..71c7be200 100644 --- a/host/include/uhd/usrp/dboard_iface.hpp +++ b/host/include/uhd/usrp/dboard_iface.hpp @@ -82,18 +82,18 @@ public: * * \param unit which unit rx or tx * \param which_dac the dac index 0, 1, 2, 3... - * \param value the value to write + * \param value the value in volts */ - virtual void write_aux_dac(unit_t unit, int which_dac, int value) = 0; + virtual void write_aux_dac(unit_t unit, int which_dac, float value) = 0; /*! * Read from an aux adc. * * \param unit which unit rx or tx * \param which_adc the adc index 0, 1, 2, 3... - * \return the value that was read + * \return the value in volts */ - virtual int read_aux_adc(unit_t unit, int which_adc) = 0; + virtual float read_aux_adc(unit_t unit, int which_adc) = 0; /*! * Set a daughterboard ATR register. diff --git a/host/include/uhd/utils/algorithm.hpp b/host/include/uhd/utils/algorithm.hpp index 6635c8a4a..cc935b226 100644 --- a/host/include/uhd/utils/algorithm.hpp +++ b/host/include/uhd/utils/algorithm.hpp @@ -49,12 +49,16 @@ namespace std{ return has(iterable.begin(), iterable.end(), elem); } - template T signum(T n){ + template T signum(T n){ if (n < 0) return -1; if (n > 0) return 1; return 0; } + template T clip(T val, T1 minVal, T2 maxVal){ + return std::min(std::max(val, minVal), maxVal); + } + }//namespace std #endif /* INCLUDED_UHD_UTILS_ALGORITHM_HPP */ diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 5a992339b..aad2398d8 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -77,9 +77,9 @@ static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t const& args){ UHD_STATIC_BLOCK(reg_basic_and_lf_dboards){ dboard_manager::register_dboard(0x0000, &make_basic_tx, "Basic TX"); - dboard_manager::register_dboard(0x0001, &make_basic_rx, "Basic RX", list_of("ab")("a")("b")); + dboard_manager::register_dboard(0x0001, &make_basic_rx, "Basic RX", list_of("AB")("A")("B")); dboard_manager::register_dboard(0x000e, &make_lf_tx, "LF TX"); - dboard_manager::register_dboard(0x000f, &make_lf_rx, "LF RX", list_of("ab")("a")("b")); + dboard_manager::register_dboard(0x000f, &make_lf_rx, "LF RX", list_of("AB")("A")("B")); } /*********************************************************************** @@ -139,7 +139,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_QUADRATURE: - val = (get_subdev_name() == "ab"); //only quadrature in ab mode + val = (get_subdev_name() == "AB"); //only quadrature in ab mode return; case SUBDEV_PROP_IQ_SWAPPED: diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index b86546248..3f318d3ed 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,8 @@ using namespace boost::assign; /*********************************************************************** * The RFX series of dboards **********************************************************************/ +static const float _max_rx_pga0_gain = 45; + class rfx_xcvr : public xcvr_dboard_base{ public: rfx_xcvr(ctor_args_t const& args, const freq_range_t &freq_range); @@ -140,7 +143,7 @@ rfx_xcvr::rfx_xcvr( //set some default values set_lo_freq((_freq_range.min + _freq_range.max)/2.0); - set_rx_ant("rx2"); + set_rx_ant("RX2"); set_rx_pga0_gain(0); } @@ -152,20 +155,40 @@ rfx_xcvr::~rfx_xcvr(void){ * Helper Methods **********************************************************************/ void rfx_xcvr::set_lo_freq(double freq){ - /* NOP */ + //TODO !!! reload_adf4360_regs(); } void rfx_xcvr::set_rx_ant(const std::string &ant){ + //validate input + ASSERT_THROW(ant == "TX/RX" or ant == "RX2"); + //set the rx atr regs that change with antenna setting this->get_iface()->set_atr_reg( dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, - POWER_UP | MIX_EN | ((ant == "tx/rx")? ANT_TXRX : ANT_RX2) + POWER_UP | MIX_EN | ((ant == "TX/RX")? ANT_TXRX : ANT_RX2) ); + + //shadow the setting + _rx_ant = ant; } void rfx_xcvr::set_rx_pga0_gain(float gain){ - /* NOP */ + //clip the input + gain = std::clip(gain, 0, _max_rx_pga0_gain); + + //voltage level constants + static const float max_volts = .2, min_volts = 1.2; + static const float slope = (max_volts-min_volts)/_max_rx_pga0_gain; + + //calculate the voltage for the aux dac + float dac_volts = gain*slope + min_volts; + + //write the new voltage to the aux dac + this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, 1, dac_volts); + + //shadow the setting (does not account for precision loss) + _rx_pga0_gain = gain; } void rfx_xcvr::reload_adf4360_regs(void){ @@ -201,15 +224,17 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_GAIN: + ASSERT_THROW(name == "PGA0"); val = _rx_pga0_gain; return; case SUBDEV_PROP_GAIN_RANGE: - val = gain_range_t(0, 45, float(0.022)); + ASSERT_THROW(name == "PGA0"); + val = gain_range_t(0, _max_rx_pga0_gain, float(0.022)); return; case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(1, "pga0"); + val = prop_names_t(1, "PGA0"); return; case SUBDEV_PROP_FREQ: @@ -225,7 +250,7 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_ANTENNA_NAMES:{ - prop_names_t ants = list_of("tx/rx")("rx2"); + prop_names_t ants = list_of("TX/RX")("RX2"); val = ants; } return; @@ -256,7 +281,7 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ switch(key.as()){ case SUBDEV_PROP_GAIN: - ASSERT_THROW(name == "pga0"); + ASSERT_THROW(name == "PGA0"); set_rx_pga0_gain(val.as()); return; @@ -309,11 +334,11 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_ANTENNA: - val = std::string("tx/rx"); + val = std::string("TX/RX"); return; case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, "tx/rx"); + val = prop_names_t(1, "TX/RX"); return; case SUBDEV_PROP_QUADRATURE: @@ -347,7 +372,7 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ANTENNA: //its always set to tx/rx, so we only allow this value - ASSERT_THROW(val.as() == "tx/rx"); + ASSERT_THROW(val.as() == "TX/RX"); return; default: diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index f77dfc495..2859a7981 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -22,6 +22,7 @@ #include #include #include //htonl and ntohl +#include #include using namespace uhd::usrp; @@ -31,8 +32,8 @@ public: usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::sptr clk_ctrl); ~usrp2_dboard_iface(void); - void write_aux_dac(unit_t, int, int); - int read_aux_adc(unit_t, int); + void write_aux_dac(unit_t, int, float); + float read_aux_adc(unit_t, int); void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t); void set_gpio_ddr(unit_t, boost::uint16_t); @@ -251,20 +252,20 @@ static boost::uint8_t unit_to_otw(dboard_iface::unit_t unit){ throw std::invalid_argument("unknown unit type"); } -void usrp2_dboard_iface::write_aux_dac(unit_t unit, int which, int value){ +void usrp2_dboard_iface::write_aux_dac(unit_t unit, int which, float value){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_WRITE_THIS_TO_THE_AUX_DAC_BRO); out_data.data.aux_args.dir = unit_to_otw(unit); out_data.data.aux_args.which = which; - out_data.data.aux_args.value = htonl(value); + out_data.data.aux_args.value = htonl(boost::math::iround(4095*value/3.3)); //send and recv usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE); } -int usrp2_dboard_iface::read_aux_adc(unit_t unit, int which){ +float usrp2_dboard_iface::read_aux_adc(unit_t unit, int which){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_READ_FROM_THIS_AUX_ADC_BRO); @@ -274,5 +275,5 @@ int usrp2_dboard_iface::read_aux_adc(unit_t unit, int which){ //send and recv usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_ADC_DUDE); - return ntohl(in_data.data.aux_args.value); + return float(3.3*ntohl(in_data.data.aux_args.value)/4095); } -- cgit v1.2.3 From b9e7e38a84046fc345bcac12611205fbea0bef19 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 14 Apr 2010 17:42:39 -0700 Subject: removed some windows warnings --- host/include/uhd/utils/algorithm.hpp | 4 ++-- host/lib/ic_reg_maps/gen_ad9777_regs.py | 6 +++--- host/lib/usrp/dboard/db_rfx.cpp | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'host/lib/usrp/dboard/db_rfx.cpp') diff --git a/host/include/uhd/utils/algorithm.hpp b/host/include/uhd/utils/algorithm.hpp index cc935b226..8fe9cde82 100644 --- a/host/include/uhd/utils/algorithm.hpp +++ b/host/include/uhd/utils/algorithm.hpp @@ -55,8 +55,8 @@ namespace std{ return 0; } - template T clip(T val, T1 minVal, T2 maxVal){ - return std::min(std::max(val, minVal), maxVal); + template T clip(T val, T minVal, T maxVal){ + return std::min(std::max(val, minVal), maxVal); } }//namespace std diff --git a/host/lib/ic_reg_maps/gen_ad9777_regs.py b/host/lib/ic_reg_maps/gen_ad9777_regs.py index 135d5c724..6077b61b6 100644 --- a/host/lib/ic_reg_maps/gen_ad9777_regs.py +++ b/host/lib/ic_reg_maps/gen_ad9777_regs.py @@ -129,13 +129,13 @@ struct ad9777_regs_t{ #end for } - boost::uint32_t get_reg(boost::uint8_t addr){ - boost::uint32_t reg = 0; + boost::uint8_t get_reg(boost::uint8_t addr){ + boost::uint8_t reg = 0; switch(addr){ #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs))) case $addr: #for $reg in filter(lambda r: r.get_addr() == addr, $regs) - reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); + reg |= (boost::uint8_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); #end for break; #end for diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 3f318d3ed..11a689b20 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -175,10 +175,10 @@ void rfx_xcvr::set_rx_ant(const std::string &ant){ void rfx_xcvr::set_rx_pga0_gain(float gain){ //clip the input - gain = std::clip(gain, 0, _max_rx_pga0_gain); + gain = std::clip(gain, 0, _max_rx_pga0_gain); //voltage level constants - static const float max_volts = .2, min_volts = 1.2; + static const float max_volts = float(.2), min_volts = float(1.2); static const float slope = (max_volts-min_volts)/_max_rx_pga0_gain; //calculate the voltage for the aux dac -- cgit v1.2.3 From cbf7a0916f0455743d8446a8edc0f0775e3e63ed Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 14 Apr 2010 19:16:38 -0700 Subject: work on tuning rfx tx and rx LOs --- host/lib/usrp/dboard/db_rfx.cpp | 102 +++++++++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 27 deletions(-) (limited to 'host/lib/usrp/dboard/db_rfx.cpp') diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 11a689b20..c38b006b0 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -29,6 +29,7 @@ #define ANT_XX 0 //dont care how the antenna is set #include "adf4360_regs.hpp" +#include #include #include #include @@ -50,7 +51,11 @@ static const float _max_rx_pga0_gain = 45; class rfx_xcvr : public xcvr_dboard_base{ public: - rfx_xcvr(ctor_args_t const& args, const freq_range_t &freq_range); + rfx_xcvr( + ctor_args_t const& args, + const freq_range_t &freq_range, + bool rx_div2, bool tx_div2 + ); ~rfx_xcvr(void); void rx_get(const wax::obj &key, wax::obj &val); @@ -61,38 +66,46 @@ public: private: freq_range_t _freq_range; - double _lo_freq; + uhd::dict _div2; + double _rx_lo_freq, _tx_lo_freq; std::string _rx_ant; float _rx_pga0_gain; - adf4360_regs_t _adf4360_regs; - void set_lo_freq(double freq); + void set_rx_lo_freq(double freq); + void set_tx_lo_freq(double freq); void set_rx_ant(const std::string &ant); void set_rx_pga0_gain(float gain); - void reload_adf4360_regs(void); + + /*! + * Set the LO frequency for the particular dboard unit. + * \param unit which unit rx or tx + * \param target_freq the desired frequency in Hz + * \return the actual frequency in Hz + */ + double set_lo_freq(dboard_iface::unit_t unit, double target_freq); }; /*********************************************************************** - * Register the RFX dboards + * Register the RFX dboards (min freq, max freq, rx div2, tx div2) **********************************************************************/ static dboard_base::sptr make_rfx_flex400(dboard_base::ctor_args_t const& args){ - return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(400e6, 500e6))); + return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(400e6, 500e6), false, true)); } static dboard_base::sptr make_rfx_flex900(dboard_base::ctor_args_t const& args){ - return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(750e6, 1050e6))); + return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(750e6, 1050e6), true, true)); } -static dboard_base::sptr make_rfx_flex1200(dboard_base::ctor_args_t const& args){ - return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(1150e6, 1450e6))); +static dboard_base::sptr make_rfx_flex1800(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(1500e6, 2100e6), false, false)); } -static dboard_base::sptr make_rfx_flex1800(dboard_base::ctor_args_t const& args){ - return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(1500e6, 2100e6))); +static dboard_base::sptr make_rfx_flex1200(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(1150e6, 1450e6), true, true)); } static dboard_base::sptr make_rfx_flex2400(dboard_base::ctor_args_t const& args){ - return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(2300e6, 2900e6))); + return dboard_base::sptr(new rfx_xcvr(args, freq_range_t(2300e6, 2900e6), false, false)); } UHD_STATIC_BLOCK(reg_rfx_dboards){ @@ -102,12 +115,12 @@ UHD_STATIC_BLOCK(reg_rfx_dboards){ dboard_manager::register_dboard(0x0025, &make_rfx_flex900, "Flex 900 Rx MIMO B"); dboard_manager::register_dboard(0x0029, &make_rfx_flex900, "Flex 900 Tx MIMO B"); - dboard_manager::register_dboard(0x0026, &make_rfx_flex1200, "Flex 1200 Rx MIMO B"); - dboard_manager::register_dboard(0x002a, &make_rfx_flex1200, "Flex 1200 Tx MIMO B"); - dboard_manager::register_dboard(0x0034, &make_rfx_flex1800, "Flex 1800 Rx MIMO B"); dboard_manager::register_dboard(0x0035, &make_rfx_flex1800, "Flex 1800 Tx MIMO B"); + dboard_manager::register_dboard(0x0026, &make_rfx_flex1200, "Flex 1200 Rx MIMO B"); + dboard_manager::register_dboard(0x002a, &make_rfx_flex1200, "Flex 1200 Tx MIMO B"); + dboard_manager::register_dboard(0x0027, &make_rfx_flex2400, "Flex 2400 Rx MIMO B"); dboard_manager::register_dboard(0x002b, &make_rfx_flex2400, "Flex 2400 Tx MIMO B"); } @@ -117,9 +130,12 @@ UHD_STATIC_BLOCK(reg_rfx_dboards){ **********************************************************************/ rfx_xcvr::rfx_xcvr( ctor_args_t const& args, - const freq_range_t &freq_range + const freq_range_t &freq_range, + bool rx_div2, bool tx_div2 ) : xcvr_dboard_base(args){ _freq_range = freq_range; + _div2[dboard_iface::UNIT_RX] = rx_div2; + _div2[dboard_iface::UNIT_TX] = tx_div2; //enable the clocks that we need this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); @@ -142,7 +158,8 @@ rfx_xcvr::rfx_xcvr( this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP | ANT_RX2 | MIX_EN); //set some default values - set_lo_freq((_freq_range.min + _freq_range.max)/2.0); + set_rx_lo_freq((_freq_range.min + _freq_range.max)/2.0); + set_tx_lo_freq((_freq_range.min + _freq_range.max)/2.0); set_rx_ant("RX2"); set_rx_pga0_gain(0); } @@ -154,9 +171,12 @@ rfx_xcvr::~rfx_xcvr(void){ /*********************************************************************** * Helper Methods **********************************************************************/ -void rfx_xcvr::set_lo_freq(double freq){ - //TODO !!! - reload_adf4360_regs(); +void rfx_xcvr::set_rx_lo_freq(double freq){ + _rx_lo_freq = set_lo_freq(dboard_iface::UNIT_RX, freq); +} + +void rfx_xcvr::set_tx_lo_freq(double freq){ + _tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, freq); } void rfx_xcvr::set_rx_ant(const std::string &ant){ @@ -191,7 +211,25 @@ void rfx_xcvr::set_rx_pga0_gain(float gain){ _rx_pga0_gain = gain; } -void rfx_xcvr::reload_adf4360_regs(void){ +double rfx_xcvr::set_lo_freq( + dboard_iface::unit_t unit, + double target_freq +){ + //clip the input + target_freq = std::clip(target_freq, _freq_range.min, _freq_range.max); + + //load the registers + adf4360_regs_t regs; + + if (_div2[unit]) target_freq *= 2; + regs.divide_by_2_output = (_div2[unit])? + adf4360_regs_t::DIVIDE_BY_2_OUTPUT_DIV2 : + adf4360_regs_t::DIVIDE_BY_2_OUTPUT_FUND ; + + //TODO + + + //write the registers std::vector addrs = list_of (adf4360_regs_t::ADDR_CONTROL) (adf4360_regs_t::ADDR_NCOUNTER) @@ -199,11 +237,13 @@ void rfx_xcvr::reload_adf4360_regs(void){ ; BOOST_FOREACH(adf4360_regs_t::addr_t addr, addrs){ this->get_iface()->write_spi( - dboard_iface::UNIT_TX, - spi_config_t::EDGE_RISE, - _adf4360_regs.get_reg(addr), 24 + unit, spi_config_t::EDGE_RISE, + regs.get_reg(addr), 24 ); } + + //return the actual frequency + return target_freq; //TODO... and remember to check div2 } /*********************************************************************** @@ -238,7 +278,7 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_FREQ: - val = _lo_freq; + val = _rx_lo_freq; return; case SUBDEV_PROP_FREQ_RANGE: @@ -280,6 +320,10 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ //handle the get request conditioned on the key switch(key.as()){ + case SUBDEV_PROP_FREQ: + set_rx_lo_freq(val.as()); + return; + case SUBDEV_PROP_GAIN: ASSERT_THROW(name == "PGA0"); set_rx_pga0_gain(val.as()); @@ -326,7 +370,7 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_FREQ: - val = _lo_freq; + val = _tx_lo_freq; return; case SUBDEV_PROP_FREQ_RANGE: @@ -366,6 +410,10 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ //handle the get request conditioned on the key switch(key.as()){ + case SUBDEV_PROP_FREQ: + set_tx_lo_freq(val.as()); + return; + case SUBDEV_PROP_GAIN: //no gains to set! return; -- cgit v1.2.3 From 0718961ed11dc82b9430d9fa5da985f7ffcd5d2a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 15 Apr 2010 16:11:42 -0700 Subject: work on rfx registers --- host/lib/ic_reg_maps/gen_adf4360_regs.py | 6 +-- host/lib/usrp/dboard/db_rfx.cpp | 88 ++++++++++++++++++++++++++++---- 2 files changed, 81 insertions(+), 13 deletions(-) (limited to 'host/lib/usrp/dboard/db_rfx.cpp') diff --git a/host/lib/ic_reg_maps/gen_adf4360_regs.py b/host/lib/ic_reg_maps/gen_adf4360_regs.py index e7c2c9435..bcad1ffd3 100755 --- a/host/lib/ic_reg_maps/gen_adf4360_regs.py +++ b/host/lib/ic_reg_maps/gen_adf4360_regs.py @@ -37,14 +37,14 @@ REGS_DATA_TMPL="""\ ## address 0 ######################################################################## core_power_level 0[2:3] 0 5ma, 10ma, 15ma, 20ma -counter_reset 0[4] 0 normal, reset +counter_operation 0[4] 0 normal, reset muxout_control 0[5:7] 0 3state, dld, ndiv, dvdd, rdiv, nchan_od_ld, sdo, dgnd phase_detector_polarity 0[8] 0 neg, pos -cp_three_state 0[9] 0 normal, 3state +charge_pump_output 0[9] 0 normal, 3state cp_gain_0 0[10] 0 set1, set2 mute_till_ld 0[11] 0 dis, enb output_power_level 0[12:13] 0 3_5ma, 5_0ma, 7_5ma, 11_0ma -#set $current_setting_enums = "0_31, 0_62, 0_93, 1_25, 1_56, 1_87, 2_18, 2_50" +#set $current_setting_enums = ', '.join(map(lambda x: x+"ma", "0_31 0_62 0_93 1_25 1_56 1_87 2_18 2_50".split())) current_setting1 0[14:16] 0 $current_setting_enums current_setting2 0[17:19] 0 $current_setting_enums power_down 0[20:21] 0 normal_op=0, async_pd=1, sync_pd=3 diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index c38b006b0..4a5786aa4 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -15,6 +15,8 @@ // along with this program. If not, see . // +static const bool rfx_debug = true; + // IO Pin functions #define POWER_UP (1 << 7) // Low enables power supply #define ANT_SW (1 << 6) // On TX DB, 0 = TX, 1 = RX, on RX DB 0 = main ant, 1 = RX2 @@ -39,6 +41,7 @@ #include #include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -215,25 +218,85 @@ double rfx_xcvr::set_lo_freq( dboard_iface::unit_t unit, double target_freq ){ + if (rfx_debug) std::cerr << boost::format( + "RFX tune: target frequency %f Mhz" + ) % (target_freq/100e6) << std::endl; + //clip the input target_freq = std::clip(target_freq, _freq_range.min, _freq_range.max); + if (_div2[unit]) target_freq *= 2; - //load the registers - adf4360_regs_t regs; + //map prescalers to the register enums + static const uhd::dict prescaler_to_enum = map_list_of + (8, adf4360_regs_t::PRESCALER_VALUE_8_9) + (16, adf4360_regs_t::PRESCALER_VALUE_16_17) + (32, adf4360_regs_t::PRESCALER_VALUE_32_33) + ; - if (_div2[unit]) target_freq *= 2; - regs.divide_by_2_output = (_div2[unit])? - adf4360_regs_t::DIVIDE_BY_2_OUTPUT_DIV2 : - adf4360_regs_t::DIVIDE_BY_2_OUTPUT_FUND ; + //calculate the following values + // fvco = [P*B + A] * fref/R + // fvco*R/fref = P*B + A = N + int A, B, P, R; double N; + static const int + B_min = 3, B_max = 8191, + A_min = 0, A_max = 31, + P_min = 8, P_max = 32; + static const int + N_min = P_min*B_min + A_min, + N_max = P_max*B_max + A_max; + double ref_freq = this->get_iface()->get_clock_rate(unit); + double ratio = target_freq/ref_freq; + + for(R = 1; R < 11; R++){ + //increment R and see if this allows for a large enough N + N = ratio*R; + if (N < N_min) continue; + N = std::clip(N, N_min, N_max); + break; + } - //TODO + //discover the best value for P, B, and A + BOOST_FOREACH(P, prescaler_to_enum.keys()){ + B = int(std::floor(N/P)); + if (B > B_max) continue; + B = std::clip(B, B_min, B_max); + A = boost::math::iround(N - P*B); + A = std::clip(A, A_min, A_max); + break; + } + //load the register values + adf4360_regs_t regs; + regs.core_power_level = adf4360_regs_t::CORE_POWER_LEVEL_10MA; + regs.counter_operation = adf4360_regs_t::COUNTER_OPERATION_NORMAL; + regs.muxout_control = adf4360_regs_t::MUXOUT_CONTROL_DLD; + regs.phase_detector_polarity = adf4360_regs_t::PHASE_DETECTOR_POLARITY_POS; + regs.charge_pump_output = adf4360_regs_t::CHARGE_PUMP_OUTPUT_NORMAL; + regs.cp_gain_0 = adf4360_regs_t::CP_GAIN_0_SET1; + regs.mute_till_ld = adf4360_regs_t::MUTE_TILL_LD_ENB; + regs.output_power_level = adf4360_regs_t::OUTPUT_POWER_LEVEL_3_5MA; + regs.current_setting1 = adf4360_regs_t::CURRENT_SETTING1_0_31MA; + regs.current_setting2 = adf4360_regs_t::CURRENT_SETTING2_0_31MA; + regs.power_down = adf4360_regs_t::POWER_DOWN_NORMAL_OP; + regs.prescaler_value = prescaler_to_enum[P]; + regs.a_counter = A; + regs.b_counter = B; + regs.cp_gain_1 = adf4360_regs_t::CP_GAIN_1_SET1; + regs.divide_by_2_output = (_div2[unit])? + adf4360_regs_t::DIVIDE_BY_2_OUTPUT_DIV2 : + adf4360_regs_t::DIVIDE_BY_2_OUTPUT_FUND ; + regs.divide_by_2_prescaler = adf4360_regs_t::DIVIDE_BY_2_PRESCALER_FUND; + regs.r_counter = R; + regs.ablpw = adf4360_regs_t::ABLPW_3_0NS; + regs.lock_detect_precision = adf4360_regs_t::LOCK_DETECT_PRECISION_5CYCLES; + regs.test_mode_bit = 0; + regs.band_select_clock_div = adf4360_regs_t::BAND_SELECT_CLOCK_DIV_8; //write the registers - std::vector addrs = list_of + std::vector addrs = list_of //correct power-up sequence to write registers (R, C, N) + (adf4360_regs_t::ADDR_RCOUNTER) (adf4360_regs_t::ADDR_CONTROL) (adf4360_regs_t::ADDR_NCOUNTER) - (adf4360_regs_t::ADDR_RCOUNTER) ; BOOST_FOREACH(adf4360_regs_t::addr_t addr, addrs){ this->get_iface()->write_spi( @@ -243,7 +306,12 @@ double rfx_xcvr::set_lo_freq( } //return the actual frequency - return target_freq; //TODO... and remember to check div2 + double actual_freq = double(P*B + A) * ref_freq / double(R); + if (_div2[unit]) actual_freq /= 2; + if (rfx_debug) std::cerr << boost::format( + "RFX tune: actual frequency %f Mhz" + ) % (actual_freq/100e6) << std::endl; + return actual_freq; } /*********************************************************************** -- cgit v1.2.3 From 067491b58676cbdaa754334949a8ffc2daf32979 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 16 Apr 2010 11:05:54 -0700 Subject: RFX seems to be tuning. Added some code to dsp to check for valid range. --- host/lib/usrp/dboard/db_rfx.cpp | 116 ++++++++++++++++++++++----------------- host/lib/usrp/usrp2/dsp_impl.cpp | 15 ++--- 2 files changed, 73 insertions(+), 58 deletions(-) (limited to 'host/lib/usrp/dboard/db_rfx.cpp') diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 4a5786aa4..cd5b8447b 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -15,19 +15,27 @@ // along with this program. If not, see . // -static const bool rfx_debug = true; +static const bool rfx_debug = false; // IO Pin functions -#define POWER_UP (1 << 7) // Low enables power supply -#define ANT_SW (1 << 6) // On TX DB, 0 = TX, 1 = RX, on RX DB 0 = main ant, 1 = RX2 -#define MIX_EN (1 << 5) // Enable appropriate mixer +#define POWER_IO (1 << 7) // Low enables power supply +#define ANTSW_IO (1 << 6) // On TX DB, 0 = TX, 1 = RX, on RX DB 0 = main ant, 1 = RX2 +#define MIXER_IO (1 << 5) // Enable appropriate mixer #define LOCKDET_MASK (1 << 2) // Input pin +// Mixer constants +#define MIXER_ENB MIXER_IO +#define MIXER_DIS 0 + +// Power constants +#define POWER_UP 0 +#define POWER_DOWN POWER_IO + // Antenna constants #define ANT_TX 0 //the tx line is transmitting -#define ANT_RX ANT_SW //the tx line is receiving +#define ANT_RX ANTSW_IO //the tx line is receiving #define ANT_TXRX 0 //the rx line is on txrx -#define ANT_RX2 ANT_SW //the rx line in on rx2 +#define ANT_RX2 ANTSW_IO //the rx line in on rx2 #define ANT_XX 0 //dont care how the antenna is set #include "adf4360_regs.hpp" @@ -145,20 +153,20 @@ rfx_xcvr::rfx_xcvr( this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); //set the gpio directions - boost::uint16_t output_enables = POWER_UP | ANT_SW | MIX_EN; + boost::uint16_t output_enables = POWER_IO | ANTSW_IO | MIXER_IO; this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, output_enables); this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, output_enables); //setup the tx atr (this does not change with antenna) - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, POWER_UP | ANT_XX); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, POWER_UP | ANT_RX); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, POWER_UP | ANT_TX | MIX_EN); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP | ANT_TX | MIX_EN); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, POWER_UP | ANT_XX | MIXER_DIS); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, POWER_UP | ANT_RX | MIXER_DIS); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, POWER_UP | ANT_TX | MIXER_ENB); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP | ANT_TX | MIXER_ENB); //setup the rx atr (this does not change with antenna) - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, POWER_UP | ANT_XX); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, POWER_UP | ANT_XX); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP | ANT_RX2 | MIX_EN); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, POWER_UP | ANT_XX | MIXER_DIS); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, POWER_UP | ANT_XX | MIXER_DIS); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, POWER_UP | ANT_RX2| MIXER_ENB); //set some default values set_rx_lo_freq((_freq_range.min + _freq_range.max)/2.0); @@ -189,7 +197,7 @@ void rfx_xcvr::set_rx_ant(const std::string &ant){ //set the rx atr regs that change with antenna setting this->get_iface()->set_atr_reg( dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, - POWER_UP | MIX_EN | ((ant == "TX/RX")? ANT_TXRX : ANT_RX2) + POWER_UP | MIXER_ENB | ((ant == "TX/RX")? ANT_TXRX : ANT_RX2) ); //shadow the setting @@ -220,7 +228,7 @@ double rfx_xcvr::set_lo_freq( ){ if (rfx_debug) std::cerr << boost::format( "RFX tune: target frequency %f Mhz" - ) % (target_freq/100e6) << std::endl; + ) % (target_freq/1e6) << std::endl; //clip the input target_freq = std::clip(target_freq, _freq_range.min, _freq_range.max); @@ -233,37 +241,48 @@ double rfx_xcvr::set_lo_freq( (32, adf4360_regs_t::PRESCALER_VALUE_32_33) ; - //calculate the following values - // fvco = [P*B + A] * fref/R - // fvco*R/fref = P*B + A = N - int A, B, P, R; double N; - static const int - B_min = 3, B_max = 8191, - A_min = 0, A_max = 31, - P_min = 8, P_max = 32; - static const int - N_min = P_min*B_min + A_min, - N_max = P_max*B_max + A_max; - double ref_freq = this->get_iface()->get_clock_rate(unit); - double ratio = target_freq/ref_freq; - - for(R = 1; R < 11; R++){ - //increment R and see if this allows for a large enough N - N = ratio*R; - if (N < N_min) continue; - N = std::clip(N, N_min, N_max); - break; - } + //map band select clock dividers to enums + static const uhd::dict bandsel_to_enum = map_list_of + (1, adf4360_regs_t::BAND_SELECT_CLOCK_DIV_1) + (2, adf4360_regs_t::BAND_SELECT_CLOCK_DIV_2) + (4, adf4360_regs_t::BAND_SELECT_CLOCK_DIV_4) + (8, adf4360_regs_t::BAND_SELECT_CLOCK_DIV_8) + ; - //discover the best value for P, B, and A - BOOST_FOREACH(P, prescaler_to_enum.keys()){ - B = int(std::floor(N/P)); - if (B > B_max) continue; - B = std::clip(B, B_min, B_max); - A = boost::math::iround(N - P*B); - A = std::clip(A, A_min, A_max); - break; - } + double actual_freq, ref_freq = this->get_iface()->get_clock_rate(unit); + int R, BS, P, B, A; + + /* + * The goal here to to loop though possible R dividers, + * band select clock dividers, and prescaler values. + * Calculate the A and B counters for each set of values. + * The loop exists when it meets all of the constraints. + * The resulting loop values are loaded into the registers. + * + * fvco = [P*B + A] * fref/R + * fvco*R/fref = P*B + A = N + */ + for(R = 2; R <= 32; R+=2){ + BOOST_FOREACH(BS, bandsel_to_enum.keys()){ + if (ref_freq/R/BS > 1e6) continue; //constraint on band select clock + BOOST_FOREACH(P, prescaler_to_enum.keys()){ + //calculate B and A from N + double N = target_freq*R/ref_freq; + B = int(std::floor(N/P)); + A = boost::math::iround(N - P*B); + if (B < A or B > 8191 or B < 3 or A > 31) continue; //constraints on A, B + //calculate the actual frequency + actual_freq = double(P*B + A)*ref_freq/R; + if (actual_freq/P > 300e6) continue; //constraint on prescaler output + //constraints met: exit loop + goto done_loop; + } + } + } done_loop: + + if (rfx_debug) std::cerr << boost::format( + "RFX tune: R=%d, BS=%d, P=%d, B=%d, A=%d" + ) % R % BS % P % B % A << std::endl; //load the register values adf4360_regs_t regs; @@ -290,7 +309,7 @@ double rfx_xcvr::set_lo_freq( regs.ablpw = adf4360_regs_t::ABLPW_3_0NS; regs.lock_detect_precision = adf4360_regs_t::LOCK_DETECT_PRECISION_5CYCLES; regs.test_mode_bit = 0; - regs.band_select_clock_div = adf4360_regs_t::BAND_SELECT_CLOCK_DIV_8; + regs.band_select_clock_div = bandsel_to_enum[BS]; //write the registers std::vector addrs = list_of //correct power-up sequence to write registers (R, C, N) @@ -306,11 +325,10 @@ double rfx_xcvr::set_lo_freq( } //return the actual frequency - double actual_freq = double(P*B + A) * ref_freq / double(R); if (_div2[unit]) actual_freq /= 2; if (rfx_debug) std::cerr << boost::format( "RFX tune: actual frequency %f Mhz" - ) % (actual_freq/100e6) << std::endl; + ) % (actual_freq/1e6) << std::endl; return actual_freq; } diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 664d69948..204277ba7 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -40,7 +40,8 @@ template T log2(T num){ * DDC Helper Methods **********************************************************************/ static boost::uint32_t calculate_freq_word_and_update_actual_freq(double &freq, double clock_freq){ - double scale_factor = std::pow(2.0, 32); + ASSERT_THROW(std::abs(freq) < clock_freq/2.0); + static const double scale_factor = std::pow(2.0, 32); //calculate the freq register word boost::uint32_t freq_word = rint((freq / clock_freq) * scale_factor); @@ -124,12 +125,10 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ case DSP_PROP_FREQ_SHIFT:{ double new_freq = val.as(); - ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0); - ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0); - _ddc_freq = new_freq; //shadow _iface->poke32(FR_DSP_RX_FREQ, - calculate_freq_word_and_update_actual_freq(_ddc_freq, get_master_clock_freq()) + calculate_freq_word_and_update_actual_freq(new_freq, get_master_clock_freq()) ); + _ddc_freq = new_freq; //shadow } return; @@ -209,12 +208,10 @@ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){ case DSP_PROP_FREQ_SHIFT:{ double new_freq = val.as(); - ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0); - ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0); - _duc_freq = new_freq; //shadow _iface->poke32(FR_DSP_TX_FREQ, - calculate_freq_word_and_update_actual_freq(_duc_freq, get_master_clock_freq()) + calculate_freq_word_and_update_actual_freq(new_freq, get_master_clock_freq()) ); + _duc_freq = new_freq; //shadow } return; -- cgit v1.2.3