aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-04-19 18:24:03 -0700
committerJosh Blum <josh@joshknows.com>2010-04-19 18:24:03 -0700
commitb3116c8ccf188c2abd7c709e0f1a436c513de1f1 (patch)
treea225b6e152b01b2d2b1b3bfb140f87274f6d7082 /host/lib
parent5ae48902712912456307772b372a50c89791cab3 (diff)
downloaduhd-b3116c8ccf188c2abd7c709e0f1a436c513de1f1.tar.gz
uhd-b3116c8ccf188c2abd7c709e0f1a436c513de1f1.tar.bz2
uhd-b3116c8ccf188c2abd7c709e0f1a436c513de1f1.zip
added support for aux dac and adc control in host
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/CMakeLists.txt9
-rwxr-xr-xhost/lib/ic_reg_maps/gen_ad5624_regs.py87
-rwxr-xr-xhost/lib/ic_reg_maps/gen_ad7922_regs.py93
-rw-r--r--host/lib/usrp/usrp2/dboard_iface.cpp98
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);
}