diff options
-rw-r--r-- | host/lib/CMakeLists.txt | 9 | ||||
-rwxr-xr-x | host/lib/ic_reg_maps/gen_ad5624_regs.py | 87 | ||||
-rwxr-xr-x | host/lib/ic_reg_maps/gen_ad7922_regs.py | 93 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/dboard_iface.cpp | 98 |
4 files changed, 256 insertions, 31 deletions
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 3a9ac1b08..7b8149802 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -96,6 +96,15 @@ UHD_PYTHON_GEN_SOURCE_FILE( ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/ad9777_regs.hpp ) +UHD_PYTHON_GEN_SOURCE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/gen_ad5624_regs.py + ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/ad5624_regs.hpp +) + +UHD_PYTHON_GEN_SOURCE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/ic_reg_maps/gen_ad7922_regs.py + ${CMAKE_CURRENT_BINARY_DIR}/ic_reg_maps/ad7922_regs.hpp +) ######################################################################## # Add usrp2 sources diff --git a/host/lib/ic_reg_maps/gen_ad5624_regs.py b/host/lib/ic_reg_maps/gen_ad5624_regs.py new file mode 100755 index 000000000..378a6912f --- /dev/null +++ b/host/lib/ic_reg_maps/gen_ad5624_regs.py @@ -0,0 +1,87 @@ +#!/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 os +import sys +from common import * + +######################################################################## +# Template for raw text data describing registers +# name addr[bit range inclusive] default optional enums +######################################################################## +REGS_DATA_TMPL="""\ +data 0[4:15] 0 +addr 0[16:18] 0 DAC_A=0, DAC_B=1, DAC_C=2, DAC_D=3, ALL=7 +cmd 0[19:21] 0 wr_input_n, up_dac_n, wr_input_n_up_all, wr_up_dac_chan_n, power_down, reset, load_ldac +""" + +######################################################################## +# Header and Source templates below +######################################################################## +HEADER_TEXT=""" +#import time + +/*********************************************************************** + * This file was generated by $file on $time.strftime("%c") + **********************************************************************/ + +\#ifndef INCLUDED_AD5624_REGS_HPP +\#define INCLUDED_AD5624_REGS_HPP + +\#include <boost/cstdint.hpp> + +struct ad5624_regs_t{ +#for $reg in $regs + #if $reg.get_enums() + enum $(reg.get_name())_t{ + #for $i, $enum in enumerate($reg.get_enums()) + #set $end_comma = ',' if $i < len($reg.get_enums())-1 else '' + $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma + #end for + } $reg.get_name(); + #else + boost::$reg.get_stdint_type() $reg.get_name(); + #end if +#end for + + ad5624_regs_t(void){ +#for $reg in $regs + $reg.get_name() = $reg.get_default(); +#end for + } + + boost::uint32_t get_reg(void){ + boost::uint32_t reg = 0; + #for $reg in filter(lambda r: r.get_addr() == 0, $regs) + reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); + #end for + return reg; + } + +}; + +\#endif /* INCLUDED_AD5624_REGS_HPP */ +""" + +if __name__ == '__main__': + regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines()) + safe_makedirs(os.path.dirname(sys.argv[1])) + open(sys.argv[1], 'w').write(parse_tmpl(HEADER_TEXT, regs=regs, file=__file__)) diff --git a/host/lib/ic_reg_maps/gen_ad7922_regs.py b/host/lib/ic_reg_maps/gen_ad7922_regs.py new file mode 100755 index 000000000..e1e67d617 --- /dev/null +++ b/host/lib/ic_reg_maps/gen_ad7922_regs.py @@ -0,0 +1,93 @@ +#!/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 os +import sys +from common import * + +######################################################################## +# Template for raw text data describing registers +# name addr[bit range inclusive] default optional enums +######################################################################## +REGS_DATA_TMPL="""\ +result 0[0:11] 0 +mod 0[12] 0 +chn 0[13] 0 +""" + +######################################################################## +# Header and Source templates below +######################################################################## +HEADER_TEXT=""" +#import time + +/*********************************************************************** + * This file was generated by $file on $time.strftime("%c") + **********************************************************************/ + +\#ifndef INCLUDED_AD7922_REGS_HPP +\#define INCLUDED_AD7922_REGS_HPP + +\#include <boost/cstdint.hpp> + +struct ad7922_regs_t{ +#for $reg in $regs + #if $reg.get_enums() + enum $(reg.get_name())_t{ + #for $i, $enum in enumerate($reg.get_enums()) + #set $end_comma = ',' if $i < len($reg.get_enums())-1 else '' + $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma + #end for + } $reg.get_name(); + #else + boost::$reg.get_stdint_type() $reg.get_name(); + #end if +#end for + + ad7922_regs_t(void){ +#for $reg in $regs + $reg.get_name() = $reg.get_default(); +#end for + } + + boost::uint16_t get_reg(void){ + boost::uint16_t reg = 0; + #for $reg in filter(lambda r: r.get_addr() == 0, $regs) + reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); + #end for + return reg; + } + + void set_reg(boost::uint16_t reg){ + #for $reg in filter(lambda r: r.get_addr() == 0, $regs) + $reg.get_name() = (reg >> $reg.get_shift()) & $reg.get_mask(); + #end for + } + +}; + +\#endif /* INCLUDED_AD7922_REGS_HPP */ +""" + +if __name__ == '__main__': + regs = map(reg, parse_tmpl(REGS_DATA_TMPL).splitlines()) + safe_makedirs(os.path.dirname(sys.argv[1])) + open(sys.argv[1], 'w').write(parse_tmpl(HEADER_TEXT, regs=regs, file=__file__)) diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index 5ccb6fa47..591e958cb 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -25,6 +25,8 @@ #include <boost/asio.hpp> //htonl and ntohl #include <boost/math/special_functions/round.hpp> #include <algorithm> +#include "ad7922_regs.hpp" //aux adc +#include "ad5624_regs.hpp" //aux dac using namespace uhd; using namespace uhd::usrp; @@ -66,6 +68,9 @@ private: usrp2_iface::sptr _iface; clock_control::sptr _clk_ctrl; boost::uint32_t _ddr_shadow; + + uhd::dict<unit_t, ad5624_regs_t> _dac_regs; + void _write_aux_dac(unit_t); }; /*********************************************************************** @@ -93,6 +98,16 @@ usrp2_dboard_iface::usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::s } _iface->poke32(FR_GPIO_TX_SEL, new_sels); _iface->poke32(FR_GPIO_RX_SEL, new_sels); + + //reset the aux dacs + _dac_regs[UNIT_RX] = ad5624_regs_t(); + _dac_regs[UNIT_TX] = ad5624_regs_t(); + BOOST_FOREACH(unit_t unit, _dac_regs.keys()){ + _dac_regs[unit].data = 1; + _dac_regs[unit].addr = ad5624_regs_t::ADDR_ALL; + _dac_regs[unit].cmd = ad5624_regs_t::CMD_RESET; + this->_write_aux_dac(unit); + } } usrp2_dboard_iface::~usrp2_dboard_iface(void){ @@ -240,42 +255,63 @@ byte_vector_t usrp2_dboard_iface::read_i2c(int i2c_addr, size_t num_bytes){ /*********************************************************************** * Aux DAX/ADC **********************************************************************/ -/*! - * Static function to convert a unit type enum - * to an over-the-wire value for the usrp2 control. - * \param unit the dboard interface unit type enum - * \return an over the wire representation - */ -static boost::uint8_t unit_to_otw(dboard_iface::unit_t unit){ - switch(unit){ - 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"); +void usrp2_dboard_iface::_write_aux_dac(unit_t unit){ + static const uhd::dict<unit_t, int> unit_to_spi_dac = boost::assign::map_list_of + (UNIT_RX, SPI_SS_RX_DAC) + (UNIT_TX, SPI_SS_TX_DAC) + ; + _iface->transact_spi( + unit_to_spi_dac[unit], spi_config_t::EDGE_FALL, + _dac_regs[unit].get_reg(), 24, false /*no rb*/ + ); } 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(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); + _dac_regs[unit].data = boost::math::iround(4095*value/3.3); + _dac_regs[unit].cmd = ad5624_regs_t::CMD_WR_UP_DAC_CHAN_N; + switch(which){ + case 0: _dac_regs[unit].addr = ad5624_regs_t::ADDR_DAC_A; break; + case 1: _dac_regs[unit].addr = ad5624_regs_t::ADDR_DAC_B; break; + case 2: _dac_regs[unit].addr = ad5624_regs_t::ADDR_DAC_C; break; + case 3: _dac_regs[unit].addr = ad5624_regs_t::ADDR_DAC_D; break; + default: throw std::runtime_error("not a possible aux dac, must be 0, 1, 2, or 3"); + } + this->_write_aux_dac(unit); } 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); - out_data.data.aux_args.dir = unit_to_otw(unit); - out_data.data.aux_args.which = which; + static const uhd::dict<unit_t, int> unit_to_spi_adc = boost::assign::map_list_of + (UNIT_RX, SPI_SS_RX_ADC) + (UNIT_TX, SPI_SS_TX_ADC) + ; + + //setup spi config args + spi_config_t config; + config.mosi_edge = spi_config_t::EDGE_FALL; + config.miso_edge = spi_config_t::EDGE_RISE; + + //setup the spi registers + ad7922_regs_t ad7922_regs; + ad7922_regs.mod = which; //normal mode: mod == chn + ad7922_regs.chn = which; + + //write and read spi + _iface->transact_spi( + unit_to_spi_adc[unit], config, + ad7922_regs.get_reg(), 16, false /*no rb*/ + ); + boost::uint16_t reg = _iface->transact_spi( + unit_to_spi_adc[unit], config, + ad7922_regs.get_reg(), 16, true /*rb*/ + ); + ad7922_regs.set_reg(reg); + + //convert to voltage and return + return float(3.3*ad7922_regs.result/4095); + + + + + - //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 float(3.3*ntohl(in_data.data.aux_args.value)/4095); } |