diff options
Diffstat (limited to 'gr-usrp/src')
41 files changed, 2234 insertions, 6368 deletions
diff --git a/gr-usrp/src/Makefile.am b/gr-usrp/src/Makefile.am index 03ca34db0..122f977be 100644 --- a/gr-usrp/src/Makefile.am +++ b/gr-usrp/src/Makefile.am @@ -21,107 +21,116 @@ include $(top_srcdir)/Makefile.common +# ---------------------------------------------------------------- +# The straight C++ library + +AM_CPPFLAGS = \ + $(STD_DEFINES_AND_INCLUDES) \ + $(PYTHON_CPPFLAGS) \ + $(USRP_INCLUDES) \ + $(WITH_INCLUDES) + +lib_LTLIBRARIES = \ + libgnuradio-usrp.la + +libgnuradio_usrp_la_SOURCES = \ + usrp_base.cc \ + usrp_sink_base.cc \ + usrp_sink_c.cc \ + usrp_sink_s.cc \ + usrp_source_base.cc \ + usrp_source_c.cc \ + usrp_source_s.cc + +libgnuradio_usrp_la_LIBADD = \ + $(GNURADIO_CORE_LA) \ + $(USRP_LA) + +libgnuradio_usrp_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0 + +grinclude_HEADERS = \ + usrp_base.h \ + usrp_sink_base.h \ + usrp_sink_c.h \ + usrp_sink_s.h \ + usrp_source_base.h \ + usrp_source_c.h \ + usrp_source_s.h + +# ---------------------------------------------------------------- +# The SWIG library and Python modules +# # Install this stuff so that it ends up as the gnuradio.usrp module # This usually ends up at: -# ${prefix}/lib/python${python_version}/site-packages/gnuradio - -ourpythondir = $(grpythondir) -ourlibdir = $(grpyexecdir) - -EXTRA_DIST = run_tests.in -TESTS = run_tests - -LOCAL_IFILES = \ - $(top_srcdir)/gr-usrp/src/usrp1.i - -NON_LOCAL_IFILES = $(GNURADIO_I) - -ALL_IFILES = \ - $(LOCAL_IFILES) \ +# ${prefix}/lib/python${python_version}/site-packages/gnuradio/usrp + +ourpythondir = $(grpythondir)/usrp +ourlibdir = $(grpyexecdir)/usrp + +BUILT_SOURCES = \ + usrp_swig.cc \ + usrp_swig.py + +LOCAL_IFILES = \ + $(srcdir)/usrp.i \ + $(srcdir)/usrp_base.i \ + $(srcdir)/usrp_source_base.i \ + $(srcdir)/usrp_source_c.i \ + $(srcdir)/usrp_source_s.i \ + $(srcdir)/usrp_sink_base.i \ + $(srcdir)/usrp_sink_c.i \ + $(srcdir)/usrp_sink_s.i \ + $(srcdir)/usrp_standard.i + +NON_LOCAL_IFILES = \ + $(GNURADIO_I) + +ALL_IFILES = \ + $(LOCAL_IFILES) \ $(NON_LOCAL_IFILES) -BUILT_SOURCES = \ - usrp1.cc \ - usrp1.py - -ourpython_PYTHON = \ - db_base.py \ - db_basic.py \ - db_dbs_rx.py \ - db_flexrf.py \ - db_flexrf_mimo.py \ - db_wbx.py \ - db_xcvr2450.py \ - db_instantiator.py \ - db_tv_rx.py \ - db_dtt754.py \ - db_dtt768.py \ - flexrf_debug_gui.py \ - tx_debug_gui.py \ - usrp.py \ - usrp1.py \ - usrp_multi.py - - -AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) \ - $(PYTHON_CPPFLAGS) \ - $(USRP_INCLUDES) \ - $(WITH_INCLUDES) - -SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) \ - $(STD_DEFINES_AND_INCLUDES) \ - $(USRP_INCLUDES) \ - $(WITH_INCLUDES) \ - $(WITH_SWIG_INCLUDES) - -grinclude_HEADERS = \ - usrp1_sink_base.h \ - usrp1_sink_c.h \ - usrp1_sink_s.h \ - usrp1_source_base.h \ - usrp1_source_c.h \ - usrp1_source_s.h - -swiginclude_HEADERS = \ - $(LOCAL_IFILES) - +ourlib_LTLIBRARIES = \ + _usrp_swig.la -ourlib_LTLIBRARIES = _usrp1.la +ourlib_PYTHON = \ + __init__.py \ + usrp_swig.py +_usrp_swig_la_SOURCES = \ + usrp_swig.cc -_usrp1_la_SOURCES = \ - usrp1.cc \ - usrp1_sink_base.cc \ - usrp1_sink_c.cc \ - usrp1_sink_s.cc \ - usrp1_source_base.cc \ - usrp1_source_c.cc \ - usrp1_source_s.cc +_usrp_swig_la_LIBADD = \ + $(PYTHON_LDFLAGS) \ + libgnuradio-usrp.la +_usrp_swig_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version -_usrp1_la_LIBADD = \ - $(PYTHON_LDFLAGS) \ - $(GNURADIO_CORE_LA) \ - $(USRP_LA) \ - -lstdc++ +_usrp_swig_la_CXXFLAGS = @swig_CXXFLAGS@ +SWIGPYTHONARGS = \ + $(SWIGPYTHONFLAGS) \ + $(STD_DEFINES_AND_INCLUDES) \ + $(USRP_INCLUDES) \ + $(WITH_INCLUDES) \ + $(WITH_SWIG_INCLUDES) -_usrp1_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version +usrp_swig.cc usrp_swig.py: $(ALL_IFILES) + $(SWIG) $(SWIGPYTHONARGS) -module usrp_swig -o usrp_swig.cc $(srcdir)/usrp.i -_usrp1_la_CXXFLAGS = @swig_CXXFLAGS@ - -usrp1.cc usrp1.py: usrp1.i $(NON_LOCAL_IFILES) $(LOCAL_IFILES) - $(SWIG) $(SWIGPYTHONARGS) -module usrp1 -o usrp1.cc $(LOCAL_IFILES) - - -noinst_PYTHON = \ +noinst_PYTHON = \ qa_usrp.py -MOSTLYCLEANFILES = \ - $(BUILT_SOURCES) *~ *.pyc - +swiginclude_HEADERS = \ + $(LOCAL_IFILES) # Don't distribute output of swig dist-hook: @for file in $(BUILT_SOURCES); do echo $(RM) $(distdir)/$$file; done @for file in $(BUILT_SOURCES); do $(RM) $(distdir)/$$file; done + +# ---------------------------------------------------------------- +# Misc. build/installation activities + +MOSTLYCLEANFILES = $(BUILT_SOURCES) *~ *.pyc +EXTRA_DIST = run_tests.in +TESTS = run_tests diff --git a/gr-usrp/src/db_instantiator.py b/gr-usrp/src/__init__.py index b76cdeee3..c81b2f2b0 100644 --- a/gr-usrp/src/db_instantiator.py +++ b/gr-usrp/src/__init__.py @@ -1,5 +1,5 @@ # -# Copyright 2005 Free Software Foundation, Inc. +# Copyright 2008 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -19,13 +19,10 @@ # Boston, MA 02110-1301, USA. # -_instantiator_map = {} +# The presence of this file turns this directory into a Python package -def add(dbid, instantiator): - _instantiator_map[dbid] = instantiator +# Add SWIG generated code to this namespace +from usrp_swig import * + +# Add other content from pure-Python modules here -def instantiate(usrp, which): - dbid = usrp.daughterboard_id(which) - if _instantiator_map.has_key(dbid): - return _instantiator_map[dbid](usrp, which) - raise ValueError, "No class defined to handle daughterboard (dbid = %d)" % (dbid,) diff --git a/gr-usrp/src/db_base.py b/gr-usrp/src/db_base.py deleted file mode 100644 index 947f81559..000000000 --- a/gr-usrp/src/db_base.py +++ /dev/null @@ -1,264 +0,0 @@ -# -# Copyright 2005,2006,2007 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 version 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 weakref -from usrpm import usrp_prims -from usrpm.usrp_fpga_regs import * - -class db_base(object): - """ - Abstract base class for all daughterboards. - - This defines the required operations and interfaces for all d'boards. - """ - def __init__(self, usrp, which): - """ - Initialize daughterboard interface. - - @param usrp: instance of usrp - @param which: which daughterboard side: A = 0, B = 1 - @type which: int - """ - - if not (which in (0, 1)): - raise ValueError, "Invalid value of which: %s" % (which,) - - self._u = weakref.proxy(usrp) - - self._which = which - if hasattr(self._u, 'tx_freq'): # is this a tx or rx daughterboard? - self._tx = True - self._slot = which * 2 - else: - self._tx = False - self._slot = which * 2 + 1 - - self._refclk_reg = (FR_TX_A_REFCLK,FR_RX_A_REFCLK,FR_TX_B_REFCLK,FR_RX_B_REFCLK)[self._slot] - - def dbid(self): - return self._u.daughterboard_id(self._which) - - def name(self): - return usrp_prims.usrp_dbid_to_string(self.dbid()) - - def side_and_name(self): - return "AB"[self._which] + ': ' + self.name() - - # Function to bypass ADC buffers. Any board which is DC-coupled should bypass the buffers - def bypass_adc_buffers(self,bypass): - if self._tx: - raise RuntimeError, "TX Board has no adc buffers" - if self._which==0: - self._u.set_adc_buffer_bypass(0, bypass) - self._u.set_adc_buffer_bypass(1, bypass) - else: - self._u.set_adc_buffer_bypass(2, bypass) - self._u.set_adc_buffer_bypass(3, bypass) - - # ------------------------------------------------------------------------ - # Reference Clock section - - # Control whether a reference clock is sent to the daughterboards, - # and what frequency - # - # Bit 7 -- 1 turns on refclk, 0 allows IO use - # Bits 6:0 Divider value - # - - def _refclk_freq(self): - return self._u.fpga_master_clock_freq()/self._refclk_divisor() - - def _enable_refclk(self,enable): - CLOCK_OUT = 1 # Clock is on lowest bit - REFCLK_ENABLE = 0x80 - REFCLK_DIVISOR_MASK = 0x7f - if enable: - self._u._write_oe(self._which, CLOCK_OUT, CLOCK_OUT) # output enable - self._u._write_fpga_reg(self._refclk_reg, - ((self._refclk_divisor() & REFCLK_DIVISOR_MASK) - | REFCLK_ENABLE)) - else: - self._u._write_fpga_reg(self._refclk_reg, 0) - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - raise NotImplementedError - - # ------------------------------------------------------------------------ - # Automatic Transmit/Receive switching - # - # The presence or absence of data in the FPGA transmit fifo - # selects between two sets of values for each of the 4 banks of - # daughterboard i/o pins. - # - # Each daughterboard slot has 3 16-bit registers associated with it: - # FR_ATR_MASK_*, FR_ATR_TXVAL_* and FR_ATR_RXVAL_* - # - # FR_ATR_MASK_{0,1,2,3}: - # - # These registers determine which of the daugherboard i/o pins are - # affected by ATR switching. If a bit in the mask is set, the - # corresponding i/o bit is controlled by ATR, else it's output - # value comes from the normal i/o pin output register: - # FR_IO_{0,1,2,3}. - # - # FR_ATR_TXVAL_{0,1,2,3}: - # FR_ATR_RXVAL_{0,1,2,3}: - # - # If the Tx fifo contains data, then the bits from TXVAL that are - # selected by MASK are output. Otherwise, the bits from RXVAL that - # are selected by MASK are output. - - def set_atr_mask(self, v): - """ - Set Auto T/R mask. - """ - return self._u._write_fpga_reg(FR_ATR_MASK_0 + 3 * self._slot, v) - - def set_atr_txval(self, v): - """ - Set Auto T/R register value to be used when transmitting. - """ - return self._u._write_fpga_reg(FR_ATR_TXVAL_0 + 3 * self._slot, v) - - def set_atr_rxval(self, v): - """ - Set Auto T/R register value to be used when receiving. - """ - return self._u._write_fpga_reg(FR_ATR_RXVAL_0 + 3 * self._slot, v) - - def set_atr_tx_delay(self, v): - """ - Set Auto T/R delay (in clock ticks) from when Tx fifo gets data to - when T/R switches. - """ - return self._u._write_fpga_reg(FR_ATR_TX_DELAY, v) - - def set_atr_rx_delay(self, v): - """ - Set Auto T/R delay (in clock ticks) from when Tx fifo goes empty to - when T/R switches. - """ - return self._u._write_fpga_reg(FR_ATR_RX_DELAY, v) - - # derived classes should override the following methods - - def freq_range(self): - """ - Return range of frequencies in Hz that can be tuned by this d'board. - - @returns (min_freq, max_freq, step_size) - @rtype tuple - """ - raise NotImplementedError - - def set_freq(self, target_freq): - """ - Set the frequency. - - @param freq: target RF frequency in Hz - @type freq: float - - @returns (ok, actual_baseband_freq) where: - ok is True or False and indicates success or failure, - actual_baseband_freq is the RF frequency that corresponds to DC in the IF. - """ - raise NotImplementedError - - def gain_range(self): - """ - Return range of gain that can be set by this d'board. - - @returns (min_gain, max_gain, step_size) - Where gains are expressed in decibels (your mileage may vary) - """ - raise NotImplementedError - - def set_gain(self, gain): - """ - Set the gain. - - @param gain: gain in decibels - @returns True/False - """ - raise NotImplementedError - - def is_quadrature(self): - """ - Return True if this daughterboard does quadrature up or down conversion. - That is, return True if this board requires both I & Q analog channels. - - This bit of info is useful when setting up the USRP Rx mux register. - """ - raise NotImplementedError - - def i_and_q_swapped(self): - """ - Return True if this is a quadrature device and (for RX) ADC 0 is Q - or (for TX) DAC 0 is Q - """ - return False - - def spectrum_inverted(self): - """ - Return True if the dboard gives an inverted spectrum - """ - return False - - def set_enable(self, on): - """ - For tx daughterboards, this controls the transmitter enable. - """ - pass - - def set_auto_tr(self,on): - """ - Enable automatic Transmit/Receive switching (ATR). - - Should be overridden in subclasses that care. This will typically - set the atr_mask, txval and rxval. - """ - pass - - def set_lo_offset(self, offset): - """ - Set how much LO is offset from requested frequency - - Should be overriden by daughterboards that care. - """ - pass - - def lo_offset(self, offset): - """ - Get how much LO is offset from requested frequency - - Should be overriden by daughterboards that care. - """ - return 0.0 - - def select_rx_antenna(self, which_antenna): - """ - Specify which antenna port to use for reception. - Should be overriden by daughterboards that care. - """ - pass diff --git a/gr-usrp/src/db_basic.py b/gr-usrp/src/db_basic.py deleted file mode 100644 index c9947aa0b..000000000 --- a/gr-usrp/src/db_basic.py +++ /dev/null @@ -1,252 +0,0 @@ -# -# Copyright 2005 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 version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import sys -from usrpm import usrp_dbid -import db_base -import db_instantiator - -class db_basic_tx(db_base.db_base): - def __init__(self, usrp, which): - """ - Handler for Basic Tx daughterboards. - - @param usrp: instance of usrp.source_c - @param which: which side: 0 or 1 corresponding to TX_A or TX_B respectively - """ - # sets _u and _which - db_base.db_base.__init__(self, usrp, which) - - if 0: # Doing this would give us a different default than the historical values... - g = self.gain_range() # initialize gain - self.set_gain(float(g[0]+g[1]) / 2) - - - def freq_range(self): - """ - Return range of frequencies in Hz that can be tuned by this d'board. - - @returns (min_freq, max_freq, step_size) - @rtype tuple - - We say we can do pretty much anything... - """ - return (-90e9, 90e9, 1e-6) - - def set_freq(self, target_freq): - """ - Set the frequency. - - @param freq: target RF frequency in Hz - @type freq: float - - @returns (ok, actual_baseband_freq) where: - ok is True or False and indicates success or failure, - actual_baseband_freq is the RF frequency that corresponds to DC in the IF. - """ - return (True, 0) - - def gain_range(self): - """ - Return range of gain that can be set by this d'board. - - @returns (min_gain, max_gain, step_size) - Where gains are expressed in decibels (your mileage may vary) - """ - return (self._u.pga_min(), self._u.pga_max(), self._u.pga_db_per_step()) - - def set_gain(self, gain): - """ - Set the gain. - - @param gain: gain in decibels - @returns True/False - """ - ok = self._u.set_pga(self._which * 2 + 0, gain) - ok = ok and self._u.set_pga(self._which * 2 + 1, gain) - return ok - - def is_quadrature(self): - """ - Return True if this board requires both I & Q analog channels. - """ - return True - - -class db_basic_rx(db_base.db_base): - def __init__(self, usrp, which, subdev): - """ - Handler for Basic Rx daughterboards. - - @param usrp: instance of usrp.source_c - @param which: which side: 0 or 1 corresponding to RX_A or RX_B respectively - @param subdev: which analog i/o channel: 0 or 1 - @type subdev: int - """ - # sets _u and _which - db_base.db_base.__init__(self, usrp, which) - self._subdev = subdev - - self.bypass_adc_buffers(True) - - if 0: # Doing this would give us a different default than the historical values... - g = self.gain_range() # initialize gain - self.set_gain(float(g[0]+g[1]) / 2) - - - def freq_range(self): - """ - Return range of frequencies in Hz that can be tuned by this d'board. - - @returns (min_freq, max_freq, step_size) - @rtype tuple - - We say we can do pretty much anything... - """ - return (0, 90e9, 1e-6) - - def set_freq(self, target_freq): - """ - Set the frequency. - - @param freq: target RF frequency in Hz - @type freq: float - - @returns (ok, actual_baseband_freq) where: - ok is True or False and indicates success or failure, - actual_baseband_freq is the RF frequency that corresponds to DC in the IF. - """ - return (True, 0) - - - def gain_range(self): - """ - Return range of gain that can be set by this d'board. - - @returns (min_gain, max_gain, step_size) - Where gains are expressed in decibels (your mileage may vary) - """ - return (self._u.pga_min(), self._u.pga_max(), self._u.pga_db_per_step()) - - def set_gain(self, gain): - """ - Set the gain. - - @param gain: gain in decibels - @returns True/False - """ - return self._u.set_pga(self._which * 2 + self._subdev, gain) - - def is_quadrature(self): - """ - Return True if this board requires both I & Q analog channels. - - This bit of info is useful when setting up the USRP Rx mux register. - """ - return False - -class db_lf_rx(db_basic_rx): - def __init__(self, usrp, which, subdev): - """ - Handler for Low Freq Rx daughterboards. - - @param usrp: instance of usrp.source_c - @param which: which side: 0 or 1 corresponding to RX_A or RX_B respectively - @param subdev: which analog i/o channel: 0 or 1 - @type subdev: int - """ - # sets _u and _which - db_basic_rx.__init__(self, usrp, which, subdev) - - def freq_range(self): - """ - Return range of frequencies in Hz that can be tuned by this d'board. - - @returns (min_freq, max_freq, step_size) - @rtype tuple - - We cover the first nyquist zone only - """ - return (0, 32e6, 1e-6) - -class db_lf_tx(db_basic_tx): - def __init__(self, usrp, which): - """ - Handler for Low Freq Tx daughterboards. - - @param usrp: instance of usrp.source_c - @param which: which side: 0 or 1 corresponding to RX_A or RX_B respectively - """ - # sets _u and _which - db_basic_tx.__init__(self, usrp, which) - - def freq_range(self): - """ - Return range of frequencies in Hz that can be tuned by this d'board. - - @returns (min_freq, max_freq, step_size) - @rtype tuple - - We cover the first nyquist zone only - """ - return (-32e6, 32e6, 1e-6) - - -# hook these daughterboard classes into the auto-instantiation framework - -def _basic_rx_instantiator(usrp, which): - # two single channel subdevices - return (db_basic_rx(usrp, which, 0), db_basic_rx(usrp, which, 1)) - -def _lf_rx_instantiator(usrp, which): - # two single channel subdevices - return (db_lf_rx(usrp, which, 0), db_lf_rx(usrp, which, 1)) - -def _basic_tx_instantiator(usrp, which): - # one quadrature subdevice - return (db_basic_tx(usrp, which),) - -def _lf_tx_instantiator(usrp, which): - # one quadrature subdevice - return (db_lf_tx(usrp, which),) - -def _no_db_instantiator(usrp, which): - if hasattr(usrp, 'tx_freq'): # is this a tx or rx daughterboard? - return (_basic_tx_instantiator(usrp, which)) - else: - return (_basic_rx_instantiator(usrp, which)) - -def _invalid_instantiator(usrp, which): - if hasattr(usrp, 'tx_freq'): # is this a tx or rx daughterboard? - sys.stderr.write('\n\aWarning: Treating daughterboard with invalid EEPROM contents as if it were a "Basic Tx."\n') - sys.stderr.write('Warning: This is almost certainly wrong... Use appropriate burn-*-eeprom utility.\n\n') - return _basic_tx_instantiator(usrp, which) - else: - sys.stderr.write('\n\aWarning: Treating daughterboard with invalid EEPROM contents as if it were a "Basic Rx."\n') - sys.stderr.write('Warning: This is almost certainly wrong... Use appropriate burn-*-eeprom utility.\n\n') - return _basic_rx_instantiator(usrp, which) - -db_instantiator.add(-1, _no_db_instantiator) # no daughterboard -db_instantiator.add(-2, _invalid_instantiator) # invalid eeprom contents -db_instantiator.add(usrp_dbid.BASIC_TX, _basic_tx_instantiator) -db_instantiator.add(usrp_dbid.BASIC_RX, _basic_rx_instantiator) -db_instantiator.add(usrp_dbid.LF_TX, _lf_tx_instantiator) -db_instantiator.add(usrp_dbid.LF_RX, _lf_rx_instantiator) diff --git a/gr-usrp/src/db_dbs_rx.py b/gr-usrp/src/db_dbs_rx.py deleted file mode 100644 index 699753aa8..000000000 --- a/gr-usrp/src/db_dbs_rx.py +++ /dev/null @@ -1,345 +0,0 @@ -# -# Copyright 2005 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 version 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 math -from usrpm import usrp_dbid -import db_base -import db_instantiator - -def int_seq_to_str (seq): - """convert a sequence of integers into a string""" - return ''.join (map (chr, seq)) - -def str_to_int_seq (str): - """convert a string to a list of integers""" - return map (ord, str) - -class db_dbs_rx (db_base.db_base): - def __init__ (self, usrp, which): - """ - Control DBS receiver based USRP daughterboard. - - @param usrp: instance of usrp.source_c - @param which: which side: 0 or 1 corresponding to RX_A or RX_B respectively - @type which: int - """ - # sets _u and _which - db_base.db_base.__init__(self, usrp, which) - - self._u._write_oe(self._which,0x0001,0x0001) - self.i2c_addr = (0x67, 0x65)[self._which] - # set basic parameters - # set default values - self.n = 950 - self.div2 = 0 - self.osc = 5 - self.cp = 3 - self.r = 4 - self.r_int = 1 - self.fdac = 127 - self.m = 2 - self.dl = 0 - self.ade = 0 - self.adl = 0 - self.gc2 = 31 - self.diag = 0 - - # FIXME this should be in the core dboard class - self.refclk_divisor = 16 - self._enable_refclk(True) - - g = self.gain_range() - self.set_gain(float(g[0]+g[1]) / 2) - self.bypass_adc_buffers(True) - - def __del__(self): - if self._u: - self._enable_refclk(False) - - def _write_reg (self, regno, v): - """regno is in [0,5], v is value to write to register""" - assert (0 <= regno and regno <= 5) - self._u.write_i2c (self.i2c_addr, int_seq_to_str ((regno, v))) - - def _write_regs (self, starting_regno, vals): - """starting_regno is in [0,5], - vals is a seq of integers to write to consecutive registers""" - self._u.write_i2c (self.i2c_addr, - int_seq_to_str ((starting_regno,) + tuple (vals))) - - def _read_status (self): - """If successful, return list of two ints: [status_info, filter_DAC]""" - s = self._u.read_i2c (self.i2c_addr, 2) - if len (s) != 2: - return None - return str_to_int_seq (s) - - def _send_reg(self,regno): - assert (0 <= regno and regno <= 5) - if regno == 0: - self._write_reg(0,(self.div2<<7) + (self.n>>8)) - if regno == 1: - self._write_reg(1,self.n & 255) - if regno == 2: - self._write_reg(2,self.osc + (self.cp<<3) + (self.r_int<<5)) - if regno == 3: - self._write_reg(3,self.fdac) - if regno == 4: - self._write_reg(4,self.m + (self.dl<<5) + (self.ade<<6) + (self.adl<<7)) - if regno == 5: - self._write_reg(5,self.gc2 + (self.diag<<5)) - - # BW setting - def _set_m(self,m): - assert m>0 and m<32 - self.m = m - self._send_reg(4) - - def _set_fdac(self,fdac): - assert fdac>=0 and fdac<128 - self.fdac = fdac - self._send_reg(3) - - def set_bw (self, bw): - #assert (bw>=4e6 and bw<=33e6) - assert (bw>=1e6 and bw<=33e6) - if bw >= 4e6: - m_max = int(min(31,math.floor(self._refclk_freq()/1e6))) - elif bw >= 2e6: # Outside of Specs! - m_max = int(min(31,math.floor(self._refclk_freq()/.5e6))) - else: # Way outside of Specs! - m_max = int(min(31,math.floor(self._refclk_freq()/.25e6))) - - m_min = int(math.ceil(self._refclk_freq()/2.5e6)) - m_test = m_max - while m_test >= m_min: - fdac_test = int(round(((bw * m_test / self._refclk_freq())-4)/.145)) - if fdac_test>127: - m_test = m_test - 1 - else: - break - if (m_test>=m_min and fdac_test >=0): - self._set_m(m_test) - self._set_fdac(fdac_test) - return (self.m,self.fdac,self._refclk_freq()/self.m*(4+0.145*self.fdac)) - else: - print "Failed to set bw" - - # Gain setting - def _set_dl(self,dl): - assert dl == 0 or dl == 1 - self.dl = dl - self._send_reg(4) - - def _set_gc2(self,gc2): - assert gc2<32 and gc2>=0 - self.gc2 = gc2 - self._send_reg(5) - - def _set_gc1(self,gc1): - assert gc1>=0 and gc1<4096 - self.gc1 = gc1 - self._u.write_aux_dac(self._which,0,int(gc1)) - - def _set_pga(self, pga_gain): - assert pga_gain >=0 and pga_gain <=20 - if(self._which == 0): - self._u.set_pga (0, pga_gain) - self._u.set_pga (1, pga_gain) - else: - self._u.set_pga (2, pga_gain) - self._u.set_pga (3, pga_gain) - - def gain_range(self): - return (0, 104, 1) - - def set_gain(self,gain): - if not (gain>=0 and gain<105): - raise ValueError, "gain out of range" - gc1 = 0 - gc2 = 0 - dl = 0 - pga = 0 - if gain <56: - gc1 = int((-gain*1.85/56.0 + 2.6)*4096.0/3.3) - gain = 0 - else: - gc1 = 0 - gain = gain - 56 - if gain < 24: - gc2 = int(round(31.0 * (1-gain/24.0))) - gain = 0 - else: - gc2 = 0 - gain = gain - 24 - if gain >= 4.58: - dl = 1 - gain = gain - 4.58 - pga = gain - self._set_gc1(gc1) - self._set_gc2(gc2) - self._set_dl(dl) - self._set_pga(pga) - - # Frequency setting - def _set_osc(self,osc): - assert osc>=0 and osc<8 - self.osc = osc - self._send_reg(2) - - def _set_cp(self,cp): - assert cp>=0 and cp<4 - self.cp = cp - self._send_reg(2) - - def _set_n(self,n): - assert n>256 and n<32768 - self.n = n - self._send_reg(0) - self._send_reg(1) - - def _set_div2(self,div2): - assert div2 == 0 or div2 == 1 - self.div2 = div2 - self._send_reg(0) - - def _set_r(self,r): - assert r>=0 and r<128 - self.r = r - self.r_int = int(round(math.log10(r)/math.log10(2)) - 1) - self._send_reg(2) - - # FIXME How do we handle ADE and ADL properly? - def _set_ade(self,ade): - assert ade == 0 or ade == 1 - self.ade = ade - self._send_reg(4) - - def freq_range(self): - return (500e6, 2.6e9, 1e6) - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 16 - - def set_freq(self, freq): - """ - Set the frequency. - - @param freq: target frequency in Hz - @type freq: float - - @returns (ok, actual_baseband_freq) where: - ok is True or False and indicates success or failure, - actual_baseband_freq is the RF frequency that corresponds to DC in the IF. - """ - if not (freq>=500e6 and freq<=2.6e9): - return (False, 0) - - if(freq<1150e6): - self._set_div2(0) - vcofreq = 4 * freq - else: - self._set_div2(1) - vcofreq = 2 * freq - self._set_ade(1) - rmin=max(2,self._refclk_freq()/2e6) - rmax=min(128,self._refclk_freq()/500e3) - r = 2 - n=0 - best_r = 2 - best_n =0 - best_delta = 10e6 - while r <= rmax: - n = round(freq/(self._refclk_freq()/r)) - if r<rmin or n<256: - r = r * 2 - continue - delta = abs(n*self._refclk_freq()/r - freq) - if delta < 75e3: - best_r = r - best_n = n - break - if delta < best_delta*0.9: - best_r = r - best_n = n - best_delta = delta - r = r * 2 - self._set_r(int(best_r)) - - self._set_n(int(round(best_n))) - - if vcofreq < 2433e6: - vco = 0 - elif vcofreq < 2711e6: - vco=1 - elif vcofreq < 3025e6: - vco=2 - elif vcofreq < 3341e6: - vco=3 - elif vcofreq < 3727e6: - vco=4 - elif vcofreq < 4143e6: - vco=5 - elif vcofreq < 4493e6: - vco=6 - else: - vco=7 - - self._set_osc(vco) - - # Set CP current - adc_val = 0 - while adc_val == 0 or adc_val == 7: - (byte1,byte2) = self._read_status() - adc_val = byte1 >> 2 - if(adc_val == 0): - if vco <= 0: - return (False, 0) - else: - vco = vco - 1 - elif(adc_val == 7): - if(vco >= 7): - return (False, 0) - else: - vco = vco + 1 - self._set_osc(vco) - if adc_val == 1 or adc_val == 2: - self._set_cp(1) - elif adc_val == 3 or adc_val == 4: - self._set_cp(2) - else: - self._set_cp(3) - - return (True, self.n * self._refclk_freq() / self.r) - - def is_quadrature(self): - """ - Return True if this board requires both I & Q analog channels. - - This bit of info is useful when setting up the USRP Rx mux register. - """ - return True - -# hook this daughterboard class into the auto-instantiation framework -db_instantiator.add(usrp_dbid.DBS_RX, lambda usrp, which : (db_dbs_rx(usrp, which),)) diff --git a/gr-usrp/src/db_dtt754.py b/gr-usrp/src/db_dtt754.py deleted file mode 100644 index 019eae6a5..000000000 --- a/gr-usrp/src/db_dtt754.py +++ /dev/null @@ -1,229 +0,0 @@ -# -# Copyright 2005 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 version 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. -# - -__all__ = ['tv_rx'] - -import math -from usrpm import usrp_dbid -import db_base -import db_instantiator - -def int_seq_to_str(seq): - """convert a sequence of integers into a string""" - return ''.join (map (chr, seq)) - -def str_to_int_seq(str): - """convert a string to a list of integers""" - return map (ord, str) - -def control_byte_1(): - RS = 0 # 0 = 166.66kHz reference - ATP = 7 # Disable internal AGC - return 0x80 | ATP<<3 | RS - -def control_byte_2(): - STBY = 0 # powered on - XTO = 1 # turn off xtal out, which we don't have - ATC = 0 # not clear exactly, possibly speeds up or slows down AGC, which we are not using - - c = 0xc2 | ATC<<5 | STBY<<4 | XTO - return c - -def bandswitch_byte(freq,bw): - if(bw>7.5e6): - P5 = 1 - else: - P5 = 0 - - if freq < 121e6: - CP = 0 - BS = 1 - elif freq < 141e6: - CP = 1 - BS = 1 - elif freq < 166e6: - CP = 2 - BS = 1 - elif freq < 182e6: - CP = 3 - BS = 1 - elif freq < 286e6: - CP = 0 - BS = 2 - elif freq < 386e6: - CP = 1 - BS = 2 - elif freq < 446e6: - CP = 2 - BS = 2 - elif freq < 466e6: - CP = 3 - BS = 2 - elif freq < 506e6: - CP = 0 - BS = 8 - elif freq < 761e6: - CP = 1 - BS = 8 - elif freq < 846e6: - CP = 2 - BS = 8 - else: # limit is ~905 MHz - CP = 3 - BS = 8 - return CP<<6 | P5 << 4 | BS - -class db_dtt754(db_base.db_base): - def __init__(self, usrp, which): - """ - Control custom DTT75403-based daughterboard. - - @param usrp: instance of usrp.source_c - @param which: which side: 0 or 1 corresponding to RX_A or RX_B respectively - @type which: int - """ - # sets _u and _which - db_base.db_base.__init__(self, usrp, which) - - self._i2c_addr = (0x60, 0x62)[which] - self.bw = 7e6 - self._IF = 36e6 - - self.f_ref = 166.6666e3 - self._inverted = False - - g = self.gain_range() # initialize gain - self.set_gain(float(g[0]+g[1]) / 2) - - self.bypass_adc_buffers(False) - - # Gain setting - def _set_rfagc(self,gain): - assert gain <= 60 and gain >= 0 - # FIXME this has a 0.5V step between gain = 60 and gain = 59. - # Why are there two cases instead of a single linear case? - if gain == 60: - voltage = 4 - else: - voltage = gain/60.0 * 2.25 + 1.25 - dacword = int(4096*voltage/1.22/3.3) # 1.22 = opamp gain - - assert dacword>=0 and dacword<4096 - self._u.write_aux_dac(self._which, 1, dacword) - - def _set_ifagc(self,gain): - assert gain <= 35 and gain >= 0 - voltage = gain/35.0 * 2.1 + 1.4 - dacword = int(4096*voltage/1.22/3.3) # 1.22 = opamp gain - - assert dacword>=0 and dacword<4096 - self._u.write_aux_dac(self._which, 0, dacword) - - def _set_pga(self,pga_gain): - assert pga_gain >=0 and pga_gain <=20 - if(self._which == 0): - self._u.set_pga (0, pga_gain) - else: - self._u.set_pga (2, pga_gain) - - def gain_range(self): - return (0, 115, 1) - - def set_gain(self,gain): - assert gain>=0 and gain<=115 - if gain>60: - rfgain = 60 - gain = gain - 60 - else: - rfgain = gain - gain = 0 - if gain > 35: - ifgain = 35 - gain = gain - 35 - else: - ifgain = gain - gain = 0 - pgagain = gain - self._set_rfagc(rfgain) - self._set_ifagc(ifgain) - self._set_pga(pgagain) - - def freq_range(self): - return (44e6, 900e6, 10e3) - - def set_freq(self, target_freq): - """ - @returns (ok, actual_baseband_freq) where: - ok is True or False and indicates success or failure, - actual_baseband_freq is the RF frequency that corresponds to DC in the IF. - """ - r = self.freq_range() - if target_freq < r[0] or target_freq > r[1]: - return (False, 0) - - target_lo_freq = target_freq + self._IF; # High side mixing - - divisor = int(0.5+(target_lo_freq / self.f_ref)) - actual_lo_freq = self.f_ref*divisor - - if (divisor & ~0x7fff) != 0: # must be 15-bits or less - return (False, 0) - - # build i2c command string - buf = [0] * 5 - buf[0] = (divisor >> 8) & 0xff # DB1 - buf[1] = divisor & 0xff # DB2 - buf[2] = control_byte_1() - buf[3] = bandswitch_byte(actual_lo_freq,self.bw) - buf[4] = control_byte_2() - - ok = self._u.write_i2c(self._i2c_addr, int_seq_to_str (buf)) - - self.freq = actual_lo_freq - self._IF - - return (ok, actual_lo_freq) - - def is_quadrature(self): - """ - Return True if this board requires both I & Q analog channels. - - This bit of info is useful when setting up the USRP Rx mux register. - """ - return False - - def spectrum_inverted(self): - """ - The 43.75 MHz version is inverted - """ - return self._inverted - - def set_bw(self,bw): - """ - Choose the SAW filter bandwidth, either 7MHz or 8MHz) - """ - self.bw = bw - self.set_freq(self.freq) - -# hook this daughterboard class into the auto-instantiation framework - -# With DTT75403 -db_instantiator.add(usrp_dbid.DTT754, - lambda usrp, which : (db_dtt754(usrp, which),)) diff --git a/gr-usrp/src/db_dtt768.py b/gr-usrp/src/db_dtt768.py deleted file mode 100644 index dd342bd20..000000000 --- a/gr-usrp/src/db_dtt768.py +++ /dev/null @@ -1,203 +0,0 @@ -# -# Copyright 2005 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 version 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. -# - -__all__ = ['tv_rx'] - -import math -from usrpm import usrp_dbid -import db_base -import db_instantiator - -def int_seq_to_str(seq): - """convert a sequence of integers into a string""" - return ''.join (map (chr, seq)) - -def str_to_int_seq(str): - """convert a string to a list of integers""" - return map (ord, str) - -def control_byte_4(): - C = 0 # Charge Pump Current, no info on how to choose - R = 4 # 125 kHz fref - - - ATP = 7 # Disable internal AGC - return 0x80 | C<<5 | R - -def control_byte_5(freq,agcmode = 1): - if(agcmode): - if freq < 150e6: - return 0x3B - elif freq < 420e6: - return 0x7E - else: - return 0xB7 - else: - if freq < 150e6: - return 0x39 - elif freq < 420e6: - return 0x7C - else: - return 0xB5 - -def control_byte_6(): - ATC = 0 # AGC time constant = 100ms, 1 = 3S - IFE = 1 # IF AGC amplifier enable - AT = 0 # AGC control, ??? - - return ATC << 5 | IFE << 4 | AT - -def control_byte_7(): - SAS = 1 # SAW Digital mode - AGD = 1 # AGC disable - ADS = 0 # AGC detector into ADC converter - T = 0 # Test mode, undocumented - return SAS << 7 | AGD << 5 | ADS << 4 | T - -class db_dtt768(db_base.db_base): - def __init__(self, usrp, which): - """ - Control custom DTT76803-based daughterboard. - - @param usrp: instance of usrp.source_c - @param which: which side: 0 or 1 corresponding to RX_A or RX_B respectively - @type which: int - """ - # sets _u and _which - db_base.db_base.__init__(self, usrp, which) - - self._i2c_addr = (0x60, 0x62)[which] - self._IF = 44e6 - - self.f_ref = 125e3 - self._inverted = False - - g = self.gain_range() # initialize gain - self.set_gain(float(g[0]+g[1]) / 2) - - self.bypass_adc_buffers(False) - - # Gain setting - def _set_rfagc(self,gain): - assert gain <= 60 and gain >= 0 - # FIXME this has a 0.5V step between gain = 60 and gain = 59. - # Why are there two cases instead of a single linear case? - if gain == 60: - voltage = 4 - else: - voltage = gain/60.0 * 2.25 + 1.25 - dacword = int(4096*voltage/1.22/3.3) # 1.22 = opamp gain - - assert dacword>=0 and dacword<4096 - self._u.write_aux_dac(self._which, 1, dacword) - - def _set_ifagc(self,gain): - assert gain <= 35 and gain >= 0 - voltage = gain/35.0 * 2.1 + 1.4 - dacword = int(4096*voltage/1.22/3.3) # 1.22 = opamp gain - - assert dacword>=0 and dacword<4096 - self._u.write_aux_dac(self._which, 0, dacword) - - def _set_pga(self,pga_gain): - assert pga_gain >=0 and pga_gain <=20 - if(self._which == 0): - self._u.set_pga (0, pga_gain) - else: - self._u.set_pga (2, pga_gain) - - def gain_range(self): - return (0, 115, 1) - - def set_gain(self,gain): - assert gain>=0 and gain<=115 - if gain>60: - rfgain = 60 - gain = gain - 60 - else: - rfgain = gain - gain = 0 - if gain > 35: - ifgain = 35 - gain = gain - 35 - else: - ifgain = gain - gain = 0 - pgagain = gain - self._set_rfagc(rfgain) - self._set_ifagc(ifgain) - self._set_pga(pgagain) - - def freq_range(self): - return (44e6, 900e6, 10e3) - - def set_freq(self, target_freq): - """ - @returns (ok, actual_baseband_freq) where: - ok is True or False and indicates success or failure, - actual_baseband_freq is the RF frequency that corresponds to DC in the IF. - """ - r = self.freq_range() - if target_freq < r[0] or target_freq > r[1]: - return (False, 0) - - target_lo_freq = target_freq + self._IF; # High side mixing - - divisor = int(0.5+(target_lo_freq / self.f_ref)) - actual_lo_freq = self.f_ref*divisor - - if (divisor & ~0x7fff) != 0: # must be 15-bits or less - return (False, 0) - - # build i2c command string - buf = [0] * 6 - buf[0] = (divisor >> 8) & 0xff # DB1 - buf[1] = divisor & 0xff # DB2 - buf[2] = control_byte_4() - buf[3] = control_byte_5(target_freq) - buf[4] = control_byte_6() - buf[5] = control_byte_7() - - ok = self._u.write_i2c(self._i2c_addr, int_seq_to_str (buf)) - - self.freq = actual_lo_freq - self._IF - - return (ok, actual_lo_freq) - - def is_quadrature(self): - """ - Return True if this board requires both I & Q analog channels. - - This bit of info is useful when setting up the USRP Rx mux register. - """ - return False - - def spectrum_inverted(self): - """ - The 43.75 MHz version is inverted - """ - return self._inverted - -# hook this daughterboard class into the auto-instantiation framework - -# With DTT76803 -db_instantiator.add(usrp_dbid.DTT768, - lambda usrp, which : (db_dtt768(usrp, which),)) diff --git a/gr-usrp/src/db_flexrf.py b/gr-usrp/src/db_flexrf.py deleted file mode 100644 index b5a0cab13..000000000 --- a/gr-usrp/src/db_flexrf.py +++ /dev/null @@ -1,701 +0,0 @@ -# -# Copyright 2005,2007 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 version 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. -# - -from gnuradio import usrp1 -import time,math - -from usrpm import usrp_dbid -import db_base -import db_instantiator -from usrpm.usrp_fpga_regs import * - -#debug_using_gui = True # Must be set to True or False -debug_using_gui = False # Must be set to True or False - -if debug_using_gui: - import flexrf_debug_gui - -# d'board i/o pin defs -# Tx and Rx have shared defs, but different i/o regs -AUX_RXAGC = (1 << 8) -POWER_UP = (1 << 7) # enables power supply -RX_TXN = (1 << 6) # Tx only: T/R antenna switch for TX/RX port -RX2_RX1N = (1 << 6) # Rx only: antenna switch between RX2 and TX/RX port -ENABLE = (1 << 5) # enables mixer -AUX_SEN = (1 << 4) -AUX_SCLK = (1 << 3) -PLL_LOCK_DETECT = (1 << 2) -AUX_SDO = (1 << 1) -CLOCK_OUT = (1 << 0) - -SPI_ENABLE_TX_A = usrp1.SPI_ENABLE_TX_A -SPI_ENABLE_TX_B = usrp1.SPI_ENABLE_TX_B -SPI_ENABLE_RX_A = usrp1.SPI_ENABLE_RX_A -SPI_ENABLE_RX_B = usrp1.SPI_ENABLE_RX_B - -class flexrf_base(db_base.db_base): - """ - Abstract base class for all flexrf boards. - - Derive board specific subclasses from db_flexrf_base_{tx,rx} - """ - def __init__(self, usrp, which): - """ - @param usrp: instance of usrp.source_c - @param which: which side: 0 or 1 corresponding to side A or B respectively - @type which: int - """ - # sets _u _which _tx and _slot - db_base.db_base.__init__(self, usrp, which) - - self.first = True - self.spi_format = usrp1.SPI_FMT_MSB | usrp1.SPI_FMT_HDR_0 - - self._u._write_oe(self._which, 0, 0xffff) # turn off all outputs - self._enable_refclk(False) # disable refclk - - g = self.gain_range() # initialize gain - self.set_gain(float(g[0]+g[1]) / 2) - - self.set_auto_tr(False) - - if debug_using_gui: - title = "FlexRF Debug Rx" - if self._tx: - title = "FlexRF Debug Tx" - self.gui = flexrf_debug_gui.flexrf_debug_gui(self, title) - self.gui.Show(True) - - - def __del__(self): - #print "flexrf_base.__del__" - self._u.write_io(self._which, self.power_off, POWER_UP) # turn off power to board - # Power down VCO/PLL - self.PD = 3 - self._write_control(self._compute_control_reg()) - self._enable_refclk(False) # turn off refclk - self.set_auto_tr(False) - - def _write_all(self, R, control, N): - """ - Write R counter latch, control latch and N counter latch to VCO. - - Adds 10ms delay between writing control and N if this is first call. - This is the required power-up sequence. - - @param R: 24-bit R counter latch - @type R: int - @param control: 24-bit control latch - @type control: int - @param N: 24-bit N counter latch - @type N: int - """ - self._write_R(R) - self._write_control( control) - if self.first: - time.sleep(0.010) - self.first = False - self._write_N(N) - - def _write_control(self, control): - self._write_it((control & ~0x3) | 0) - - def _write_R(self, R): - self._write_it((R & ~0x3) | 1) - - def _write_N(self, N): - self._write_it((N & ~0x3) | 2) - - def _write_it(self, v): - s = ''.join((chr((v >> 16) & 0xff), - chr((v >> 8) & 0xff), - chr(v & 0xff))) - self._u._write_spi(0, self.spi_enable, self.spi_format, s) - - def _lock_detect(self): - """ - @returns: the value of the VCO/PLL lock detect bit. - @rtype: 0 or 1 - """ - if self._u.read_io(self._which) & PLL_LOCK_DETECT: - return True - else: # Give it a second chance - if self._u.read_io(self._which) & PLL_LOCK_DETECT: - return True - else: - return False - - def _compute_regs(self, freq): - """ - Determine values of R, control, and N registers, along with actual freq. - - @param freq: target frequency in Hz - @type freq: float - @returns: (R, control, N, actual_freq) - @rtype: tuple(int, int, int, float) - - Override this in derived classes. - """ - raise NotImplementedError - - def _refclk_freq(self): - # return float(self._u.fpga_master_clock_freq())/self._refclk_divisor() - return 64e6/self._refclk_divisor() - - def set_freq(self, freq): - """ - @returns (ok, actual_baseband_freq) where: - ok is True or False and indicates success or failure, - actual_baseband_freq is the RF frequency that corresponds to DC in the IF. - """ - - # Offsetting the LO helps get the Tx carrier leakage out of the way. - # This also ensures that on Rx, we're not getting hosed by the - # FPGA's DC removal loop's time constant. We were seeing a - # problem when running with discontinuous transmission. - # Offsetting the LO made the problem go away. - freq += self._lo_offset - - R, control, N, actual_freq = self._compute_regs(freq) - if R==0: - return(False,0) - self._write_all(R, control, N) - return (self._lock_detect(), actual_freq) - - def gain_range(self): - """ - Return range of gain that can be set by this d'board. - - @returns (min_gain, max_gain, step_size) - Where gains are expressed in decibels (your mileage may vary) - """ - return (self._u.pga_min(), self._u.pga_max(), self._u.pga_db_per_step()) - - def set_gain(self, gain): - """ - Set the gain. - - @param gain: gain in decibels - @returns True/False - """ - return self._set_pga(gain) - - def _set_pga(self, pga_gain): - if(self._which == 0): - self._u.set_pga (0, pga_gain) - self._u.set_pga (1, pga_gain) - else: - self._u.set_pga (2, pga_gain) - self._u.set_pga (3, pga_gain) - - def is_quadrature(self): - """ - Return True if this board requires both I & Q analog channels. - - This bit of info is useful when setting up the USRP Rx mux register. - """ - return True - - def set_lo_offset(self, offset): - """ - Set amount by which LO is offset from requested tuning frequency. - - @param offset: offset in Hz - """ - self._lo_offset = offset - - def lo_offset(self): - """ - Get amount by which LO is offset from requested tuning frequency. - - @returns Offset in Hz - """ - return self._lo_offset - -# ---------------------------------------------------------------- - -class flexrf_base_tx(flexrf_base): - def __init__(self, usrp, which): - """ - @param usrp: instance of usrp.sink_c - @param which: 0 or 1 corresponding to side TX_A or TX_B respectively. - """ - flexrf_base.__init__(self, usrp, which) - self.spi_enable = (SPI_ENABLE_TX_A, SPI_ENABLE_TX_B)[which] - - # power up the transmit side, but don't enable the mixer - self._u._write_oe(self._which,(POWER_UP|RX_TXN|ENABLE), 0xffff) - self._u.write_io(self._which, (self.power_on|RX_TXN), (POWER_UP|RX_TXN|ENABLE)) - self.set_lo_offset(4e6) - - def __del__(self): - #print "flexrf_base_tx.__del__" - # Power down and leave the T/R switch in the R position - self._u.write_io(self._which, (self.power_off|RX_TXN), (POWER_UP|RX_TXN|ENABLE)) - flexrf_base.__del__(self) - - def set_auto_tr(self, on): - if on: - self.set_atr_mask (RX_TXN | ENABLE) - self.set_atr_txval(0 | ENABLE) - self.set_atr_rxval(RX_TXN | 0) - else: - self.set_atr_mask (0) - self.set_atr_txval(0) - self.set_atr_rxval(0) - - def set_enable(self, on): - """ - Enable transmitter if on is True - """ - mask = RX_TXN | ENABLE - if on: - v = ENABLE - else: - v = RX_TXN - self._u.write_io(self._which, v, mask) - - def gain_range(self): - """ - Return range of gain that can be set by this d'board. - - @returns (min_gain, max_gain, step_size) - Where gains are expressed in decibels (your mileage may vary) - - Flex Tx boards require that the PGA be maxed out to properly bias their circuitry. - """ - g = self._u.pga_max() - return (g, g, 1.0) - - def set_gain(self, gain): - """ - Set the gain. - - @param gain: gain in decibels - @returns True/False - """ - return self._set_pga(self._u.pga_max()) - -class flexrf_base_rx(flexrf_base): - def __init__(self, usrp, which): - """ - @param usrp: instance of usrp.source_c - @param which: 0 or 1 corresponding to side RX_A or RX_B respectively. - """ - flexrf_base.__init__(self, usrp, which) - self.spi_enable = (SPI_ENABLE_RX_A, SPI_ENABLE_RX_B)[which] - - self._u._write_oe(self._which, (POWER_UP|RX2_RX1N|ENABLE), 0xffff) - self._u.write_io(self._which, (self.power_on|RX2_RX1N|ENABLE), (POWER_UP|RX2_RX1N|ENABLE)) - - # set up for RX on TX/RX port - self.select_rx_antenna('TX/RX') - - self.bypass_adc_buffers(True) - self.set_lo_offset(-4e6) - - def __del__(self): - # print "flexrf_base_rx.__del__" - # Power down - self._u.write_io(self._which, self.power_off, (POWER_UP|ENABLE)) - flexrf_base.__del__(self) - - def set_auto_tr(self, on): - if on: - self.set_atr_mask (ENABLE) - self.set_atr_txval( 0) - self.set_atr_rxval(ENABLE) - else: - self.set_atr_mask (0) - self.set_atr_txval(0) - self.set_atr_rxval(0) - - def select_rx_antenna(self, which_antenna): - """ - Specify which antenna port to use for reception. - @param which_antenna: either 'TX/RX' or 'RX2' - """ - if which_antenna in (0, 'TX/RX'): - self._u.write_io(self._which, 0, RX2_RX1N) - elif which_antenna in (1, 'RX2'): - self._u.write_io(self._which, RX2_RX1N, RX2_RX1N) - else: - raise ValueError, "which_antenna must be either 'TX/RX' or 'RX2'" - - def set_gain(self, gain): - """ - Set the gain. - - @param gain: gain in decibels - @returns True/False - """ - maxgain = self.gain_range()[1] - self._u.pga_max() - mingain = self.gain_range()[0] - if gain > maxgain: - pga_gain = gain-maxgain - assert pga_gain <= self._u.pga_max() - agc_gain = maxgain - else: - pga_gain = 0 - agc_gain = gain - V_maxgain = .2 - V_mingain = 1.2 - V_fullscale = 3.3 - dac_value = (agc_gain*(V_maxgain-V_mingain)/(maxgain-mingain) + V_mingain)*4096/V_fullscale - assert dac_value>=0 and dac_value<4096 - return self._u.write_aux_dac(self._which, 0, int(dac_value)) and \ - self._set_pga(int(pga_gain)) - -# ---------------------------------------------------------------- - -class _AD4360_common(object): - def __init__(self): - # R-Register Common Values - self.R_RSV = 0 # bits 23,22 - self.BSC = 3 # bits 21,20 Div by 8 to be safe - self.TEST = 0 # bit 19 - self.LDP = 1 # bit 18 - self.ABP = 0 # bit 17,16 3ns - - # N-Register Common Values - self.N_RSV = 0 # bit 7 - - # Control Register Common Values - self.PD = 0 # bits 21,20 Normal operation - self.PL = 0 # bits 13,12 11mA - self.MTLD = 1 # bit 11 enabled - self.CPG = 0 # bit 10 CP setting 1 - self.CP3S = 0 # bit 9 Normal - self.PDP = 1 # bit 8 Positive - self.MUXOUT = 1 # bits 7:5 Digital Lock Detect - self.CR = 0 # bit 4 Normal - self.PC = 1 # bits 3,2 Core power 10mA - - def _compute_regs(self, freq): - """ - Determine values of R, control, and N registers, along with actual freq. - - @param freq: target frequency in Hz - @type freq: float - @returns: (R, control, N, actual_freq) - @rtype: tuple(int, int, int, float) - """ - - # Band-specific N-Register Values - phdet_freq = self._refclk_freq()/self.R_DIV - desired_n = round(freq*self.freq_mult/phdet_freq) - actual_freq = desired_n * phdet_freq - B = math.floor(desired_n/self._prescaler()) - A = desired_n - self._prescaler()*B - self.B_DIV = int(B) # bits 20:8 - self.A_DIV = int(A) # bit 6:2 - #assert self.B_DIV >= self.A_DIV - if self.B_DIV < self.A_DIV: - return (0,0,0,0) - R = (self.R_RSV<<22) | (self.BSC<<20) | (self.TEST<<19) | (self.LDP<<18) \ - | (self.ABP<<16) | (self.R_DIV<<2) - - control = self._compute_control_reg() - - N = (self.DIVSEL<<23) | (self.DIV2<<22) | (self.CPGAIN<<21) | (self.B_DIV<<8) | \ - (self.N_RSV<<7) | (self.A_DIV<<2) - - return (R,control,N,actual_freq/self.freq_mult) - - def _compute_control_reg(self): - control = (self.P<<22) | (self.PD<<20) | (self.CP2<<17) | (self.CP1<<14) | (self.PL<<12) \ - | (self.MTLD<<11) | (self.CPG<<10) | (self.CP3S<<9) | (self.PDP<<8) | \ - (self.MUXOUT<<5) | (self.CR<<4) | (self.PC<<2) - return control - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 1 - - def _prescaler(self): - if self.P == 0: - return 8 - elif self.P == 1: - return 16 - else: - return 32 - -#---------------------------------------------------------------------- -class _2400_common(_AD4360_common): - def __init__(self): - _AD4360_common.__init__(self) - - # Band-specific R-Register Values - self.R_DIV = 16 # bits 15:2 - - # Band-specific C-Register values - self.P = 1 # bits 23,22 Div by 16/17 - self.CP2 = 7 # bits 19:17 - self.CP1 = 7 # bits 16:14 - - # Band specifc N-Register Values - self.DIVSEL = 0 # bit 23 - self.DIV2 = 0 # bit 22 - self.CPGAIN = 0 # bit 21 - self.freq_mult = 1 - - def freq_range(self): # FIXME - return (2300e6, 2700e6, 4e6) - -#---------------------------------------------------------------------- -class _1200_common(_AD4360_common): - def __init__(self): - _AD4360_common.__init__(self) - - # Band-specific R-Register Values - self.R_DIV = 16 # bits 15:2 DIV by 16 for a 1 MHz phase detector freq - - # Band-specific C-Register values - self.P = 1 # bits 23,22 Div by 16/17 - self.CP2 = 7 # bits 19:17 1.25 mA - self.CP1 = 7 # bits 16:14 1.25 mA - - # Band specifc N-Register Values - self.DIVSEL = 0 # bit 23 - self.DIV2 = 1 # bit 22 - self.CPGAIN = 0 # bit 21 - self.freq_mult = 2 - - def freq_range(self): # FIXME - return (1150e6, 1350e6, 4e6) - -#------------------------------------------------------------------------- -class _1800_common(_AD4360_common): - def __init__(self): - _AD4360_common.__init__(self) - - # Band-specific R-Register Values - self.R_DIV = 16 # bits 15:2 DIV by 16 for a 1 MHz phase detector freq - - # Band-specific C-Register values - self.P = 1 # bits 23,22 Div by 16/17 - self.CP2 = 7 # bits 19:17 1.25 mA - self.CP1 = 7 # bits 16:14 1.25 mA - - # Band specifc N-Register Values - self.DIVSEL = 0 # bit 23 - self.DIV2 = 0 # bit 22 - self.freq_mult = 1 - self.CPGAIN = 0 # bit 21 - - def freq_range(self): # FIXME - return (1600e6, 2000e6, 4e6) - -#------------------------------------------------------------------------- -class _900_common(_AD4360_common): - def __init__(self): - _AD4360_common.__init__(self) - - # Band-specific R-Register Values - self.R_DIV = 16 # bits 15:2 DIV by 16 for a 1 MHz phase detector freq - - # Band-specific C-Register values - self.P = 1 # bits 23,22 Div by 16/17 - self.CP2 = 7 # bits 19:17 1.25 mA - self.CP1 = 7 # bits 16:14 1.25 mA - - # Band specifc N-Register Values - self.DIVSEL = 0 # bit 23 - self.DIV2 = 1 # bit 22 - self.freq_mult = 2 - self.CPGAIN = 0 # bit 21 - - def freq_range(self): # FIXME - return (800e6, 1000e6, 4e6) - -#------------------------------------------------------------------------- -class _400_common(_AD4360_common): - def __init__(self): - _AD4360_common.__init__(self) - - # Band-specific R-Register Values - self.R_DIV = 16 # bits 15:2 - - # Band-specific C-Register values - self.P = 0 # bits 23,22 Div by 8/9 - self.CP2 = 7 # bits 19:17 1.25 mA - self.CP1 = 7 # bits 16:14 1.25 mA - - # Band specifc N-Register Values These are different for TX/RX - self.DIVSEL = 0 # bit 23 - if self._tx: - self.DIV2 = 1 # bit 22 - else: - self.DIV2 = 0 # bit 22 # RX side has built-in DIV2 in AD8348 - self.freq_mult = 2 - - self.CPGAIN = 0 # bit 21 - - def freq_range(self): - #return (350e6, 465e6, 1e6) # FIXME prototype - return (400e6, 500e6, 1e6) # final version - - -#------------------------------------------------------------ -class db_flexrf_2400_tx(_2400_common, flexrf_base_tx): - def __init__(self, usrp, which): - self.power_on = 0 - self.power_off = 0 # powering it off kills the serial bus - flexrf_base_tx.__init__(self, usrp, which) - _2400_common.__init__(self) - -class db_flexrf_2400_rx(_2400_common, flexrf_base_rx): - def __init__(self, usrp, which): - self.power_on = 0 - self.power_off = 0 # Powering it off kills the serial bus - flexrf_base_rx.__init__(self, usrp, which) - _2400_common.__init__(self) - - def gain_range(self): - """ - Return range of gain that can be set by this d'board. - - @returns (min_gain, max_gain, step_size) - Where gains are expressed in decibels (your mileage may vary) - """ - return (self._u.pga_min(), self._u.pga_max() + 70, 0.05) - - def i_and_q_swapped(self): - return True - -class db_flexrf_1200_tx(_1200_common, flexrf_base_tx): - def __init__(self, usrp, which): - self.power_on = 0 - self.power_off = 0 # powering it off kills the serial bus - flexrf_base_tx.__init__(self, usrp, which) - _1200_common.__init__(self) - -class db_flexrf_1200_rx(_1200_common, flexrf_base_rx): - def __init__(self, usrp, which): - self.power_on = 0 - self.power_off = 0 # powering it off kills the serial bus - flexrf_base_rx.__init__(self, usrp, which) - _1200_common.__init__(self) - - def gain_range(self): - """ - Return range of gain that can be set by this d'board. - - @returns (min_gain, max_gain, step_size) - Where gains are expressed in decibels (your mileage may vary) - """ - return (self._u.pga_min(), self._u.pga_max() + 70, 0.05) - - def i_and_q_swapped(self): - return True - -class db_flexrf_1800_tx(_1800_common, flexrf_base_tx): - def __init__(self, usrp, which): - self.power_on = 0 - self.power_off = 0 # powering it off kills the serial bus - flexrf_base_tx.__init__(self, usrp, which) - _1800_common.__init__(self) - -class db_flexrf_1800_rx(_1800_common, flexrf_base_rx): - def __init__(self, usrp, which): - self.power_on = 0 - self.power_off = 0 # powering it off kills the serial bus - flexrf_base_rx.__init__(self, usrp, which) - _1800_common.__init__(self) - - def gain_range(self): - """ - Return range of gain that can be set by this d'board. - - @returns (min_gain, max_gain, step_size) - Where gains are expressed in decibels (your mileage may vary) - """ - return (self._u.pga_min(), self._u.pga_max() + 70, 0.05) - - def i_and_q_swapped(self): - return True - -class db_flexrf_900_tx(_900_common, flexrf_base_tx): - def __init__(self, usrp, which): - self.power_on = 0 - self.power_off = 0 # powering it off kills the serial bus - flexrf_base_tx.__init__(self, usrp, which) - _900_common.__init__(self) - -class db_flexrf_900_rx(_900_common, flexrf_base_rx): - def __init__(self, usrp, which): - self.power_on = 0 - self.power_off = 0 # powering it off kills the serial bus - flexrf_base_rx.__init__(self, usrp, which) - _900_common.__init__(self) - - def gain_range(self): - """ - Return range of gain that can be set by this d'board. - - @returns (min_gain, max_gain, step_size) - Where gains are expressed in decibels (your mileage may vary) - """ - return (self._u.pga_min(), self._u.pga_max() + 70, 0.05) - - def i_and_q_swapped(self): - return True - -class db_flexrf_400_tx(_400_common, flexrf_base_tx): - def __init__(self, usrp, which): - self.power_on = POWER_UP - self.power_off = 0 - flexrf_base_tx.__init__(self, usrp, which) - _400_common.__init__(self) - -class db_flexrf_400_rx(_400_common, flexrf_base_rx): - def __init__(self, usrp, which): - self.power_on = POWER_UP - self.power_off = 0 - flexrf_base_rx.__init__(self, usrp, which) - _400_common.__init__(self) - - def gain_range(self): - """ - Return range of gain that can be set by this d'board. - - @returns (min_gain, max_gain, step_size) - Where gains are expressed in decibels (your mileage may vary) - """ - return (self._u.pga_min(), self._u.pga_max() + 45, 0.035) - - def i_and_q_swapped(self): - return True - -# hook these daughterboard classes into the auto-instantiation framework - -db_instantiator.add(usrp_dbid.FLEX_2400_TX, lambda usrp, which : (db_flexrf_2400_tx(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_2400_RX, lambda usrp, which : (db_flexrf_2400_rx(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_1200_TX, lambda usrp, which : (db_flexrf_1200_tx(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_1200_RX, lambda usrp, which : (db_flexrf_1200_rx(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_1800_TX, lambda usrp, which : (db_flexrf_1800_tx(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_1800_RX, lambda usrp, which : (db_flexrf_1800_rx(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_900_TX, lambda usrp, which : (db_flexrf_900_tx(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_900_RX, lambda usrp, which : (db_flexrf_900_rx(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_400_TX, lambda usrp, which : (db_flexrf_400_tx(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_400_RX, lambda usrp, which : (db_flexrf_400_rx(usrp, which),)) diff --git a/gr-usrp/src/db_flexrf_mimo.py b/gr-usrp/src/db_flexrf_mimo.py deleted file mode 100644 index 755979bcb..000000000 --- a/gr-usrp/src/db_flexrf_mimo.py +++ /dev/null @@ -1,286 +0,0 @@ -# -# Copyright 2005 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 version 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. -# - -from gnuradio import usrp1 -import time,math - -from usrpm import usrp_dbid -import db_base -import db_instantiator -from usrpm.usrp_fpga_regs import * -from db_flexrf import * - -# self._u.fpga_master_clock_freq() - -# MIMO Classes -class db_flexrf_2400_tx_mimo_a(db_flexrf_2400_tx): - def __init__(self, usrp, which): - db_flexrf_2400_tx.__init__(self, usrp, which) - self._enable_refclk(True) - self.R_DIV = 1 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 16 - -class db_flexrf_2400_rx_mimo_a(db_flexrf_2400_rx): - def __init__(self, usrp, which): - db_flexrf_2400_rx.__init__(self, usrp, which) - self._enable_refclk(True) - self.R_DIV = 1 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 16 - -class db_flexrf_2400_tx_mimo_b(db_flexrf_2400_tx): - def __init__(self, usrp, which): - db_flexrf_2400_tx.__init__(self, usrp, which) - self.R_DIV = 16 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 1 - -class db_flexrf_2400_rx_mimo_b(db_flexrf_2400_rx): - def __init__(self, usrp, which): - db_flexrf_2400_rx.__init__(self, usrp, which) - self.R_DIV = 16 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 1 - -class db_flexrf_1800_tx_mimo_a(db_flexrf_1800_tx): - def __init__(self, usrp, which): - db_flexrf_1800_tx.__init__(self, usrp, which) - self._enable_refclk(True) - self.R_DIV = 1 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 16 - -class db_flexrf_1800_rx_mimo_a(db_flexrf_1800_rx): - def __init__(self, usrp, which): - db_flexrf_1800_rx.__init__(self, usrp, which) - self._enable_refclk(True) - self.R_DIV = 1 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 16 - -class db_flexrf_1800_tx_mimo_b(db_flexrf_1800_tx): - def __init__(self, usrp, which): - db_flexrf_1800_tx.__init__(self, usrp, which) - self.R_DIV = 16 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 1 - -class db_flexrf_1800_rx_mimo_b(db_flexrf_1800_rx): - def __init__(self, usrp, which): - db_flexrf_1800_rx.__init__(self, usrp, which) - self.R_DIV = 16 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 1 - -class db_flexrf_1200_tx_mimo_a(db_flexrf_1200_tx): - def __init__(self, usrp, which): - db_flexrf_1200_tx.__init__(self, usrp, which) - self._enable_refclk(True) - self.R_DIV = 1 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 16 - -class db_flexrf_1200_rx_mimo_a(db_flexrf_1200_rx): - def __init__(self, usrp, which): - db_flexrf_1200_rx.__init__(self, usrp, which) - self._enable_refclk(True) - self.R_DIV = 1 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 16 - -class db_flexrf_1200_tx_mimo_b(db_flexrf_1200_tx): - def __init__(self, usrp, which): - db_flexrf_1200_tx.__init__(self, usrp, which) - self.R_DIV = 16 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 1 - -class db_flexrf_1200_rx_mimo_b(db_flexrf_1200_rx): - def __init__(self, usrp, which): - db_flexrf_1200_rx.__init__(self, usrp, which) - self.R_DIV = 16 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 1 - -class db_flexrf_900_tx_mimo_a(db_flexrf_900_tx): - def __init__(self, usrp, which): - db_flexrf_900_tx.__init__(self, usrp, which) - self._enable_refclk(True) - self.R_DIV = 1 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 16 - -class db_flexrf_900_rx_mimo_a(db_flexrf_900_rx): - def __init__(self, usrp, which): - db_flexrf_900_rx.__init__(self, usrp, which) - self._enable_refclk(True) - self.R_DIV = 1 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 16 - -class db_flexrf_900_tx_mimo_b(db_flexrf_900_tx): - def __init__(self, usrp, which): - db_flexrf_900_tx.__init__(self, usrp, which) - self.R_DIV = 16 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 1 - -class db_flexrf_900_rx_mimo_b(db_flexrf_900_rx): - def __init__(self, usrp, which): - db_flexrf_900_rx.__init__(self, usrp, which) - self.R_DIV = 16 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 1 - -class db_flexrf_400_tx_mimo_a(db_flexrf_400_tx): - def __init__(self, usrp, which): - db_flexrf_400_tx.__init__(self, usrp, which) - self._enable_refclk(True) - self.R_DIV = 1 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 16 - -class db_flexrf_400_rx_mimo_a(db_flexrf_400_rx): - def __init__(self, usrp, which): - db_flexrf_400_rx.__init__(self, usrp, which) - self._enable_refclk(True) - self.R_DIV = 1 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 16 - -class db_flexrf_400_tx_mimo_b(db_flexrf_400_tx): - def __init__(self, usrp, which): - db_flexrf_400_tx.__init__(self, usrp, which) - self.R_DIV = 16 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 1 - -class db_flexrf_400_rx_mimo_b(db_flexrf_400_rx): - def __init__(self, usrp, which): - db_flexrf_400_rx.__init__(self, usrp, which) - self.R_DIV = 16 - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 1 - -# hook these daughterboard classes into the auto-instantiation framework -db_instantiator.add(usrp_dbid.FLEX_2400_TX_MIMO_A, lambda usrp, which : (db_flexrf_2400_tx_mimo_a(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_2400_RX_MIMO_A, lambda usrp, which : (db_flexrf_2400_rx_mimo_a(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_1800_TX_MIMO_A, lambda usrp, which : (db_flexrf_1800_tx_mimo_a(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_1800_RX_MIMO_A, lambda usrp, which : (db_flexrf_1800_rx_mimo_a(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_1200_TX_MIMO_A, lambda usrp, which : (db_flexrf_1200_tx_mimo_a(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_1200_RX_MIMO_A, lambda usrp, which : (db_flexrf_1200_rx_mimo_a(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_900_TX_MIMO_A, lambda usrp, which : (db_flexrf_900_tx_mimo_a(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_900_RX_MIMO_A, lambda usrp, which : (db_flexrf_900_rx_mimo_a(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_400_TX_MIMO_A, lambda usrp, which : (db_flexrf_400_tx_mimo_a(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_400_RX_MIMO_A, lambda usrp, which : (db_flexrf_400_rx_mimo_a(usrp, which),)) - -db_instantiator.add(usrp_dbid.FLEX_2400_TX_MIMO_B, lambda usrp, which : (db_flexrf_2400_tx_mimo_b(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_2400_RX_MIMO_B, lambda usrp, which : (db_flexrf_2400_rx_mimo_b(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_1800_TX_MIMO_B, lambda usrp, which : (db_flexrf_1800_tx_mimo_b(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_1800_RX_MIMO_B, lambda usrp, which : (db_flexrf_1800_rx_mimo_b(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_1200_TX_MIMO_B, lambda usrp, which : (db_flexrf_1200_tx_mimo_b(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_1200_RX_MIMO_B, lambda usrp, which : (db_flexrf_1200_rx_mimo_b(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_900_TX_MIMO_B, lambda usrp, which : (db_flexrf_900_tx_mimo_b(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_900_RX_MIMO_B, lambda usrp, which : (db_flexrf_900_rx_mimo_b(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_400_TX_MIMO_B, lambda usrp, which : (db_flexrf_400_tx_mimo_b(usrp, which),)) -db_instantiator.add(usrp_dbid.FLEX_400_RX_MIMO_B, lambda usrp, which : (db_flexrf_400_rx_mimo_b(usrp, which),)) - diff --git a/gr-usrp/src/db_tv_rx.py b/gr-usrp/src/db_tv_rx.py deleted file mode 100644 index 48fe6ca05..000000000 --- a/gr-usrp/src/db_tv_rx.py +++ /dev/null @@ -1,198 +0,0 @@ -# -# Copyright 2005 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 version 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. -# - -__all__ = ['tv_rx'] - -import math -from usrpm import usrp_dbid -import db_base -import db_instantiator - -def int_seq_to_str(seq): - """convert a sequence of integers into a string""" - return ''.join (map (chr, seq)) - -def str_to_int_seq(str): - """convert a string to a list of integers""" - return map (ord, str) - -def control_byte_1(fast_tuning_p, reference_divisor): - c = 0x88 - if fast_tuning_p: - c |= 0x40 - if reference_divisor == 512: - c |= 0x3 << 1 - elif reference_divisor == 640: - c |= 0x0 << 1 - elif reference_divisor == 1024: - c |= 0x1 << 1 - else: - assert 0 - return c - -def control_byte_2(target_freq, shutdown_tx_PGA): - if target_freq < 158e6: # VHF low - c = 0xa0 - elif target_freq < 464e6: # VHF high - c = 0x90 - else: # UHF - c = 0x30 - if shutdown_tx_PGA: - c |= 0x08 - return c - -class db_tv_rx(db_base.db_base): - def __init__(self, usrp, which, first_IF, second_IF, inverted): - """ - Control Microtune 4937 based USRP daughterboard. - - @param usrp: instance of usrp.source_c - @param which: which side: 0 or 1 corresponding to RX_A or RX_B respectively - @type which: int - """ - # sets _u and _which - db_base.db_base.__init__(self, usrp, which) - - self._i2c_addr = (0x60, 0x61)[which] - - self._first_IF = first_IF - self._second_IF = second_IF - self._reference_divisor = 640 - self._fast_tuning = False - self._inverted = inverted - - g = self.gain_range() - self.set_gain(float(g[0]+g[1]) / 2) # default gain is halfscale - - self.bypass_adc_buffers(False) - - # Gain setting - def _set_rfagc(self,gain): - assert gain <= 60 and gain >= 0 - # FIXME this has a 0.5V step between gain = 60 and gain = 59. - # Why are there two cases instead of a single linear case? - if gain == 60: - voltage = 4 - else: - voltage = gain/60.0 * 2.25 + 1.25 - dacword = int(4096*voltage/1.22/3.3) # 1.22 = opamp gain - - assert dacword>=0 and dacword<4096 - self._u.write_aux_dac(self._which, 1, dacword) - - def _set_ifagc(self,gain): - assert gain <= 35 and gain >= 0 - voltage = gain/35.0 * 2.1 + 1.4 - dacword = int(4096*voltage/1.22/3.3) # 1.22 = opamp gain - - assert dacword>=0 and dacword<4096 - self._u.write_aux_dac(self._which, 0, dacword) - - def _set_pga(self,pga_gain): - assert pga_gain >=0 and pga_gain <=20 - if(self._which == 0): - self._u.set_pga (0, pga_gain) - else: - self._u.set_pga (2, pga_gain) - - def gain_range(self): - return (0, 115, 1) - - def set_gain(self,gain): - assert gain>=0 and gain<=115 - if gain>60: - rfgain = 60 - gain = gain - 60 - else: - rfgain = gain - gain = 0 - if gain > 35: - ifgain = 35 - gain = gain - 35 - else: - ifgain = gain - gain = 0 - pgagain = gain - self._set_rfagc(rfgain) - self._set_ifagc(ifgain) - self._set_pga(pgagain) - - def freq_range(self): - return (50e6, 860e6, 10e3) - - def set_freq(self, target_freq): - """ - @returns (ok, actual_baseband_freq) where: - ok is True or False and indicates success or failure, - actual_baseband_freq is the RF frequency that corresponds to DC in the IF. - """ - r = self.freq_range() - if target_freq < r[0] or target_freq > r[1]: - return (False, 0) - - target_lo_freq = target_freq + self._first_IF; # High side mixing - f_ref = 4e6 / self._reference_divisor # frequency steps - - divisor = int((target_lo_freq + (f_ref * 4)) / (f_ref * 8)) - actual_lo_freq = (f_ref * 8 * divisor) - actual_freq = actual_lo_freq - self._first_IF; - - if (divisor & ~0x7fff) != 0: # must be 15-bits or less - return (False, 0) - - # build i2c command string - buf = [0] * 4 - buf[0] = (divisor >> 8) & 0xff # DB1 - buf[1] = divisor & 0xff # DB2 - buf[2] = control_byte_1(self._fast_tuning, self._reference_divisor) - buf[3] = control_byte_2(actual_freq, True) - - ok = self._u.write_i2c(self._i2c_addr, int_seq_to_str (buf)) - - return (ok, actual_freq - self._second_IF) - - def is_quadrature(self): - """ - Return True if this board requires both I & Q analog channels. - - This bit of info is useful when setting up the USRP Rx mux register. - """ - return False - - def spectrum_inverted(self): - """ - The 43.75 MHz version is inverted - """ - return self._inverted - -# hook this daughterboard class into the auto-instantiation framework - -# With MT4937DI5-3x7702 with second downconversion -db_instantiator.add(usrp_dbid.TV_RX, - lambda usrp, which : (db_tv_rx(usrp, which, 43.75e6, 5.75e6, False),)) - -# With MT4937DI5-3x8680, and 3x8769 without second downconversion -db_instantiator.add(usrp_dbid.TV_RX_REV_2, - lambda usrp, which : (db_tv_rx(usrp, which, 44e6, 44e6, True),)) - -# With MT4937DI5-3x7901 without second downconversion, basically the same as tvrx2 -db_instantiator.add(usrp_dbid.TV_RX_REV_3, - lambda usrp, which : (db_tv_rx(usrp, which, 44e6, 44e6, True),)) diff --git a/gr-usrp/src/db_wbx.py b/gr-usrp/src/db_wbx.py deleted file mode 100644 index 72b3e35c1..000000000 --- a/gr-usrp/src/db_wbx.py +++ /dev/null @@ -1,622 +0,0 @@ -# -# Copyright 2007 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 version 2, 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. -# - -from gnuradio import usrp1 -import time,math - -from usrpm import usrp_dbid -import db_base -import db_instantiator -from usrpm.usrp_fpga_regs import * - -#debug_using_gui = True # Must be set to True or False -debug_using_gui = False # Must be set to True or False - -#if debug_using_gui: -# import flexrf_debug_gui - -# d'board i/o pin defs - -# TX IO Pins -TX_POWER = (1 << 0) # TX Side Power -RX_TXN = (1 << 1) # T/R antenna switch for TX/RX port -TX_ENB_MIX = (1 << 2) # Enable IQ mixer -TX_ENB_VGA = (1 << 3) - -# RX IO Pins -RX2_RX1N = (1 << 0) # antenna switch between RX2 and TX/RX port -RXENABLE = (1 << 1) # enables mixer -PLL_LOCK_DETECT = (1 << 2) # Muxout pin from PLL -- MUST BE INPUT -MReset = (1 << 3) # NB6L239 Master Reset, asserted low -SELA0 = (1 << 4) # NB6L239 SelA0 -SELA1 = (1 << 5) # NB6L239 SelA1 -SELB0 = (1 << 6) # NB6L239 SelB0 -SELB1 = (1 << 7) # NB6L239 SelB1 -PLL_ENABLE = (1 << 8) # CE Pin on PLL -AUX_SCLK = (1 << 9) # ALT SPI SCLK -AUX_SDO = (1 << 10) # ALT SPI SDO -AUX_SEN = (1 << 11) # ALT SPI SEN - -SPI_ENABLE_TX_A = usrp1.SPI_ENABLE_TX_A -SPI_ENABLE_TX_B = usrp1.SPI_ENABLE_TX_B -SPI_ENABLE_RX_A = usrp1.SPI_ENABLE_RX_A -SPI_ENABLE_RX_B = usrp1.SPI_ENABLE_RX_B - - -""" -A few comments about the WBX boards: - They are half-duplex. I.e., transmit and receive are mutually exclusive. - There is a single LO for both the Tx and Rx sides. - The the shared control signals are hung off of the Rx side. - The shared io controls are duplexed onto the Rx side pins. - The wbx_high d'board always needs to be in 'auto_tr_mode' -""" - - -class wbx_base(db_base.db_base): - """ - Abstract base class for all wbx boards. - - Derive board specific subclasses from db_wbx_base_{tx,rx} - """ - def __init__(self, usrp, which): - """ - @param usrp: instance of usrp.source_c - @param which: which side: 0 or 1 corresponding to side A or B respectively - @type which: int - """ - # sets _u _which _tx and _slot - db_base.db_base.__init__(self, usrp, which) - - self.first = True - self.spi_format = usrp1.SPI_FMT_MSB | usrp1.SPI_FMT_HDR_0 - - # FIXME -- the write reg functions don't work with 0xffff for masks - self._rx_write_oe(int(PLL_ENABLE|MReset|SELA0|SELA1|SELB0|SELB1|RX2_RX1N|RXENABLE), 0x7fff) - self._rx_write_io((PLL_ENABLE|MReset|0|RXENABLE), (PLL_ENABLE|MReset|RX2_RX1N|RXENABLE)) - - self._tx_write_oe((TX_POWER|RX_TXN|TX_ENB_MIX|TX_ENB_VGA), 0x7fff) - self._tx_write_io((0|RX_TXN), (TX_POWER|RX_TXN|TX_ENB_MIX|TX_ENB_VGA)) # TX off, TR switch set to RX - - self.spi_enable = (SPI_ENABLE_RX_A, SPI_ENABLE_RX_B)[which] - - self.set_auto_tr(False) - - #if debug_using_gui: - # title = "FlexRF Debug Rx" - # if self._tx: - # title = "FlexRF Debug Tx" - # self.gui = flexrf_debug_gui.flexrf_debug_gui(self, title) - # self.gui.Show(True) - - - def __del__(self): - #self._u.write_io(self._which, self.power_off, POWER_UP) # turn off power to board - #self._u._write_oe(self._which, 0, 0xffff) # turn off all outputs - self.set_auto_tr(False) - - def _lock_detect(self): - """ - @returns: the value of the VCO/PLL lock detect bit. - @rtype: 0 or 1 - """ - if self._rx_read_io() & PLL_LOCK_DETECT: - return True - else: # Give it a second chance - if self._rx_read_io() & PLL_LOCK_DETECT: - return True - else: - return False - - # Both sides need access to the Rx pins. - # Write them directly, bypassing the convenience routines. - # (Sort of breaks modularity, but will work...) - - def _tx_write_oe(self, value, mask): - return self._u._write_fpga_reg((FR_OE_0, FR_OE_2)[self._which], - ((mask & 0xffff) << 16) | (value & 0xffff)) - - def _rx_write_oe(self, value, mask): - return self._u._write_fpga_reg((FR_OE_1, FR_OE_3)[self._which], - ((mask & 0xffff) << 16) | (value & 0xffff)) - - def _tx_write_io(self, value, mask): - return self._u._write_fpga_reg((FR_IO_0, FR_IO_2)[self._which], - ((mask & 0xffff) << 16) | (value & 0xffff)) - - def _rx_write_io(self, value, mask): - return self._u._write_fpga_reg((FR_IO_1, FR_IO_3)[self._which], - ((mask & 0xffff) << 16) | (value & 0xffff)) - - def _rx_read_io(self): - t = self._u._read_fpga_reg((FR_RB_IO_RX_A_IO_TX_A, FR_RB_IO_RX_B_IO_TX_B)[self._which]) - return (t >> 16) & 0xffff - - def _tx_read_io(self): - t = self._u._read_fpga_reg((FR_RB_IO_RX_A_IO_TX_A, FR_RB_IO_RX_B_IO_TX_B)[self._which]) - return t & 0xffff - - - def _compute_regs(self, freq): - """ - Determine values of registers, along with actual freq. - - @param freq: target frequency in Hz - @type freq: float - @returns: (R, N, func, init, actual_freq) - @rtype: tuple(int, int, int, int, float) - - Override this in derived classes. - """ - raise NotImplementedError - - def _refclk_freq(self): - return float(self._u.fpga_master_clock_freq())/self._refclk_divisor() - - def _refclk_divisor(self): - """ - Return value to stick in REFCLK_DIVISOR register - """ - return 1 - - # ---------------------------------------------------------------- - - def set_freq(self, freq): - """ - @returns (ok, actual_baseband_freq) where: - ok is True or False and indicates success or failure, - actual_baseband_freq is the RF frequency that corresponds to DC in the IF. - """ - raise NotImplementedError - - def gain_range(self): - """ - Return range of gain that can be set by this d'board. - - @returns (min_gain, max_gain, step_size) - Where gains are expressed in decibels (your mileage may vary) - """ - raise NotImplementedError - - def set_gain(self, gain): - """ - Set the gain. - - @param gain: gain in decibels - @returns True/False - """ - raise NotImplementedError - - def _set_pga(self, pga_gain): - if(self._which == 0): - self._u.set_pga (0, pga_gain) - self._u.set_pga (1, pga_gain) - else: - self._u.set_pga (2, pga_gain) - self._u.set_pga (3, pga_gain) - - def is_quadrature(self): - """ - Return True if this board requires both I & Q analog channels. - - This bit of info is useful when setting up the USRP Rx mux register. - """ - return True - -# ---------------------------------------------------------------- - -class wbx_base_tx(wbx_base): - def __init__(self, usrp, which): - """ - @param usrp: instance of usrp.sink_c - @param which: 0 or 1 corresponding to side TX_A or TX_B respectively. - """ - wbx_base.__init__(self, usrp, which) - - # power up the transmit side, NO -- but set antenna to receive - self._u.write_io(self._which, (TX_POWER), (TX_POWER|RX_TXN)) - self._lo_offset = 0e6 - - # Gain is not set by the PGA, but the PGA must be set at max gain in the TX - return self._set_pga(self._u.pga_max()) - - def __del__(self): - # Power down and leave the T/R switch in the R position - self._u.write_io(self._which, (RX_TXN), (TX_POWER|RX_TXN|TX_ENB_MIX|TX_ENB_VGA)) - wbx_base.__del__(self) - - def set_auto_tr(self, on): - if on: - self.set_atr_mask (RX_TXN) - self.set_atr_txval(0) - self.set_atr_rxval(RX_TXN) - else: - self.set_atr_mask (0) - self.set_atr_txval(0) - self.set_atr_rxval(0) - - def set_enable(self, on): - """ - Enable transmitter if on is True - """ - mask = RX_TXN|TX_ENB_MIX|TX_ENB_VGA - print "HERE!!!!" - if on: - self._u.write_io(self._which, TX_ENB_MIX|TX_ENB_VGA, mask) - else: - self._u.write_io(self._which, RX_TXN, mask) - - - def set_lo_offset(self, offset): - """ - Set amount by which LO is offset from requested tuning frequency. - - @param offset: offset in Hz - """ - self._lo_offset = offset - - def lo_offset(self): - """ - Get amount by which LO is offset from requested tuning frequency. - - @returns Offset in Hz - """ - return self._lo_offset - -class wbx_base_rx(wbx_base): - def __init__(self, usrp, which): - """ - @param usrp: instance of usrp.source_c - @param which: 0 or 1 corresponding to side RX_A or RX_B respectively. - """ - wbx_base.__init__(self, usrp, which) - - # set up for RX on TX/RX port - self.select_rx_antenna('TX/RX') - - self.bypass_adc_buffers(True) - - self._lo_offset = 0.0 - - def __del__(self): - # Power down - self._u.write_io(self._which, 0, (RXENABLE)) - wbx_base.__del__(self) - - def set_auto_tr(self, on): - if on: - self.set_atr_mask (ENABLE) - self.set_atr_txval( 0) - self.set_atr_rxval(ENABLE) - else: - self.set_atr_mask (0) - self.set_atr_txval(0) - self.set_atr_rxval(0) - - def select_rx_antenna(self, which_antenna): - """ - Specify which antenna port to use for reception. - @param which_antenna: either 'TX/RX' or 'RX2' - """ - if which_antenna in (0, 'TX/RX'): - self._u.write_io(self._which, 0, RX2_RX1N) - elif which_antenna in (1, 'RX2'): - self._u.write_io(self._which, RX2_RX1N, RX2_RX1N) - else: - raise ValueError, "which_antenna must be either 'TX/RX' or 'RX2'" - - def set_gain(self, gain): - """ - Set the gain. - - @param gain: gain in decibels - @returns True/False - """ - maxgain = self.gain_range()[1] - self._u.pga_max() - mingain = self.gain_range()[0] - if gain > maxgain: - pga_gain = gain-maxgain - assert pga_gain <= self._u.pga_max() - agc_gain = maxgain - else: - pga_gain = 0 - agc_gain = gain - V_maxgain = .2 - V_mingain = 1.2 - V_fullscale = 3.3 - dac_value = (agc_gain*(V_maxgain-V_mingain)/(maxgain-mingain) + V_mingain)*4096/V_fullscale - assert dac_value>=0 and dac_value<4096 - return self._u.write_aux_dac(self._which, 0, int(dac_value)) and \ - self._set_pga(int(pga_gain)) - - def set_lo_offset(self, offset): - """ - Set amount by which LO is offset from requested tuning frequency. - - @param offset: offset in Hz - """ - self._lo_offset = offset - - def lo_offset(self): - """ - Get amount by which LO is offset from requested tuning frequency. - - @returns Offset in Hz - """ - return self._lo_offset - - - def i_and_q_swapped(self): - """ - Return True if this is a quadrature device and ADC 0 is Q. - """ - return False - -# ---------------------------------------------------------------- - -class _ADF410X_common(object): - def __init__(self): - # R-Register Common Values - self.R_RSV = 0 # bits 23,22,21 - self.LDP = 1 # bit 20 Lock detect in 5 cycles - self.TEST = 0 # bit 19,18 Normal - self.ABP = 0 # bit 17,16 2.9ns - - # N-Register Common Values - self.N_RSV = 0 # 23,22 - self.CP_GAIN = 0 # 21 - - # Function Register Common Values - self.P = 0 # bits 23,22 0 = 8/9, 1 = 16/17, 2 = 32/33, 3 = 64/65 - self.PD2 = 0 # bit 21 Normal operation - self.CP2 = 4 # bits 20,19,18 CP Gain = 5mA - self.CP1 = 4 # bits 17,16,15 CP Gain = 5mA - self.TC = 0 # bits 14-11 PFD Timeout - self.FL = 0 # bit 10,9 Fastlock Disabled - self.CP3S = 0 # bit 8 CP Enabled - self.PDP = 0 # bit 7 Phase detector polarity, Positive=1 - self.MUXOUT = 1 # bits 6:4 Digital Lock Detect - self.PD1 = 0 # bit 3 Normal operation - self.CR = 0 # bit 2 Normal operation - - def _compute_regs(self, freq): - """ - Determine values of R, control, and N registers, along with actual freq. - - @param freq: target frequency in Hz - @type freq: float - @returns: (R, N, control, actual_freq) - @rtype: tuple(int, int, int, float) - """ - - # Band-specific N-Register Values - phdet_freq = self._refclk_freq()/self.R_DIV - print "phdet_freq = %f" % (phdet_freq,) - desired_n = round(freq*self.freq_mult/phdet_freq) - print "desired_n %f" % (desired_n,) - actual_freq = desired_n * phdet_freq - print "actual freq %f" % (actual_freq,) - B = math.floor(desired_n/self._prescaler()) - A = desired_n - self._prescaler()*B - print "A %d B %d" % (A,B) - self.B_DIV = int(B) # bits 20:8 - self.A_DIV = int(A) # bit 6:2 - #assert self.B_DIV >= self.A_DIV - if self.B_DIV < self.A_DIV: - return (0,0,0,0) - R = (self.R_RSV<<21) | (self.LDP<<20) | (self.TEST<<18) | \ - (self.ABP<<16) | (self.R_DIV<<2) - - N = (self.N_RSV<<22) | (self.CP_GAIN<<21) | (self.B_DIV<<8) | (self.A_DIV<<2) - - control = (self.P<<22) | (self.PD2<<21) | (self.CP2<<18) | (self.CP1<<15) | \ - (self.TC<<11) | (self.FL<<9) | (self.CP3S<<8) | (self.PDP<<7) | \ - (self.MUXOUT<<4) | (self.PD1<<3) | (self.CR<<2) - - return (R,N,control,actual_freq/self.freq_mult) - - def _write_all(self, R, N, control): - """ - Write all PLL registers: - R counter latch, - N counter latch, - Function latch, - Initialization latch - - Adds 10ms delay between writing control and N if this is first call. - This is the required power-up sequence. - - @param R: 24-bit R counter latch - @type R: int - @param N: 24-bit N counter latch - @type N: int - @param control: 24-bit control latch - @type control: int - """ - self._write_R(R) - self._write_func(control) - self._write_init(control) - if self.first: - time.sleep(0.010) - self.first = False - self._write_N(N) - - def _write_R(self, R): - self._write_it((R & ~0x3) | 0) - - def _write_N(self, N): - self._write_it((N & ~0x3) | 1) - - def _write_func(self, func): - self._write_it((func & ~0x3) | 2) - - def _write_init(self, init): - self._write_it((init & ~0x3) | 3) - - def _write_it(self, v): - s = ''.join((chr((v >> 16) & 0xff), - chr((v >> 8) & 0xff), - chr(v & 0xff))) - self._u._write_spi(0, self.spi_enable, self.spi_format, s) - - def _prescaler(self): - if self.P == 0: - return 8 - elif self.P == 1: - return 16 - elif self.P == 2: - return 32 - elif self.P == 3: - return 64 - else: - raise ValueError, "Prescaler out of range" - -#---------------------------------------------------------------------- -class _lo_common(_ADF410X_common): - def __init__(self): - _ADF410X_common.__init__(self) - - # Band-specific R-Register Values - self.R_DIV = 4 # bits 15:2 - - # Band-specific C-Register values - self.P = 0 # bits 23,22 0 = Div by 8/9 - self.CP2 = 4 # bits 19:17 - self.CP1 = 4 # bits 16:14 - - # Band specifc N-Register Values - self.DIVSEL = 0 # bit 23 - self.DIV2 = 0 # bit 22 - self.CPGAIN = 0 # bit 21 - self.freq_mult = 1 - - self.div = 1 - self.aux_div = 2 - - def freq_range(self): # FIXME - return (50e6, 1000e6, 16e6) - - def set_divider(self, main_or_aux, divisor): - if main_or_aux not in (0, 'main', 1, 'aux'): - raise ValueError, "main_or_aux must be 'main' or 'aux'" - if main_or_aux in (0, 'main'): - if divisor not in (1,2,4,8): - raise ValueError, "Main Divider Must be 1, 2, 4, or 8" - for (div,val) in ((1,0),(2,1),(4,2),(8,3)): - if(div == divisor): - self.main_div = val - else: - if divisor not in (2,4,8,16): - raise ValueError, "Aux Divider Must be 2, 4, 8 or 16" - for (div,val) in ((2,0),(4,1),(8,2),(16,3)): - if(div == divisor): - self.aux_div = val - - vala = self.main_div*SELA0 - valb = self.aux_div*SELB0 - mask = SELA0|SELA1|SELB0|SELB1 - - self._rx_write_io(((self.main_div*SELA0) | (self.aux_div*SELB0)), - (SELA0|SELA1|SELB0|SELB1)) - - def set_freq(self, freq): - #freq += self._lo_offset - - if(freq < 20e6 or freq > 1200e6): - raise ValueError, "Requested frequency out of range" - div = 1 - lo_freq = freq * 2 - while lo_freq < 1e9 and div < 8: - div = div * 2 - lo_freq = lo_freq * 2 - print "For RF freq of %f, we set DIV=%d and LO Freq=%f" % (freq, div, lo_freq) - self.set_divider('main', div) - self.set_divider('aux', div*2) - - R, N, control, actual_freq = self._compute_regs(lo_freq) - print "R %d N %d control %d actual freq %f" % (R,N,control,actual_freq) - if R==0: - return(False,0) - self._write_all(R, N, control) - return (self._lock_detect(), actual_freq/div/2) - - -#------------------------------------------------------------ -class db_wbx_lo_tx(_lo_common, wbx_base_tx): - def __init__(self, usrp, which): - wbx_base_tx.__init__(self, usrp, which) - _lo_common.__init__(self) - - def gain_range(self): - """ - Return range of gain that can be set by this d'board. - - @returns (min_gain, max_gain, step_size) - Where gains are expressed in decibels (your mileage may vary) - - Gain is controlled by a VGA in the output amplifier, not the PGA - """ - return (-56, 0, 0.1) - - def set_gain(self, gain): - """ - Set the gain. - - @param gain: gain in decibels - @returns True/False - """ - maxgain = self.gain_range()[1] - mingain = self.gain_range()[0] - if gain > maxgain: - txvga_gain = maxgain - elif gain < mingain: - txvga_gain = mingain - else: - txvga_gain = gain - - V_maxgain = 1.4 - V_mingain = 0.1 - V_fullscale = 3.3 - dac_value = ((txvga_gain-mingain)*(V_maxgain-V_mingain)/(maxgain-mingain) + V_mingain)*4096/V_fullscale - assert dac_value>=0 and dac_value<4096 - print "DAC value %d" % (dac_value,) - return self._u.write_aux_dac(self._which, 1, int(dac_value)) - -class db_wbx_lo_rx(_lo_common, wbx_base_rx): - def __init__(self, usrp, which): - wbx_base_rx.__init__(self, usrp, which) - _lo_common.__init__(self) - - def gain_range(self): - """ - Return range of gain that can be set by this d'board. - - @returns (min_gain, max_gain, step_size) - Where gains are expressed in decibels (your mileage may vary) - """ - return (self._u.pga_min(), self._u.pga_max() + 45, 0.05) - -#------------------------------------------------------------ -# hook these daughterboard classes into the auto-instantiation framework -db_instantiator.add(usrp_dbid.WBX_LO_TX, lambda usrp, which : (db_wbx_lo_tx(usrp, which),)) -db_instantiator.add(usrp_dbid.WBX_LO_RX, lambda usrp, which : (db_wbx_lo_rx(usrp, which),)) - - diff --git a/gr-usrp/src/db_xcvr2450.py b/gr-usrp/src/db_xcvr2450.py deleted file mode 100644 index ec0587635..000000000 --- a/gr-usrp/src/db_xcvr2450.py +++ /dev/null @@ -1,538 +0,0 @@ -# -# Copyright 2007 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 version 2, 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. -# - -from gnuradio import usrp1, gru, eng_notation -import time, math, weakref - -from usrpm import usrp_dbid -import db_base -import db_instantiator -from usrpm.usrp_fpga_regs import * - -# Convenience function -n2s = eng_notation.num_to_str - -# d'board i/o pin defs - -# TX IO Pins -HB_PA_OFF = (1 << 15) # 5GHz PA, 1 = off, 0 = on -LB_PA_OFF = (1 << 14) # 2.4GHz PA, 1 = off, 0 = on -ANTSEL_TX1_RX2 = (1 << 13) # 1 = Ant 1 to TX, Ant 2 to RX -ANTSEL_TX2_RX1 = (1 << 12) # 1 = Ant 2 to TX, Ant 1 to RX -TX_EN = (1 << 11) # 1 = TX on, 0 = TX off -AD9515DIV = (1 << 4) # 1 = Div by 3, 0 = Div by 2 - -TX_OE_MASK = HB_PA_OFF|LB_PA_OFF|ANTSEL_TX1_RX2|ANTSEL_TX2_RX1|TX_EN|AD9515DIV -TX_SAFE_IO = HB_PA_OFF|LB_PA_OFF|ANTSEL_TX1_RX2|AD9515DIV - -# RX IO Pins -LOCKDET = (1 << 15) # This is an INPUT!!! -EN = (1 << 14) -RX_EN = (1 << 13) # 1 = RX on, 0 = RX off -RX_HP = (1 << 12) -B1 = (1 << 11) -B2 = (1 << 10) -B3 = (1 << 9) -B4 = (1 << 8) -B5 = (1 << 7) -B6 = (1 << 6) -B7 = (1 << 5) -RX_OE_MASK = EN|RX_EN|RX_HP|B1|B2|B3|B4|B5|B6|B7 -RX_SAFE_IO = EN - - -# ------------------------------------------------------------------------ -# A few comments about the XCVR2450: -# -# It is half-duplex. I.e., transmit and receive are mutually exclusive. -# There is a single LO for both the Tx and Rx sides. -# For our purposes the board is always either receiving or transmitting. -# -# Each board is uniquely identified by the *USRP hardware* instance and side -# This dictionary holds a weak reference to existing board controller so it -# can be created or retrieved as needed. - -_xcvr2450_inst = weakref.WeakValueDictionary() -def _get_or_make_xcvr2450(usrp, which): - key = (usrp.serial_number(), which) - if not _xcvr2450_inst.has_key(key): - print "Creating new xcvr2450 instance" - inst = xcvr2450(usrp, which) - _xcvr2450_inst[key] = inst - else: - print "Using existing xcvr2450 instance" - inst = _xcvr2450_inst[key] - return inst - -# ------------------------------------------------------------------------ -# Common, shared object for xcvr2450 board. Transmit and receive classes -# operate on an instance of this; one instance is created per physical -# daughterboard. - -class xcvr2450(object): - def __init__(self, usrp, which): - print "xcvr2450: __init__ with %s: %d" % (usrp.serial_number(), which) - self.u = usrp - self.which = which - - # Use MSB with no header - self.spi_format = usrp1.SPI_FMT_MSB | usrp1.SPI_FMT_HDR_0 - self.spi_enable = (usrp1.SPI_ENABLE_RX_A, usrp1.SPI_ENABLE_RX_B)[which] - - # Sane defaults - self.mimo = 1 # 0 = OFF, 1 = ON - self.int_div = 192 # 128 = min, 255 = max - self.frac_div = 0 # 0 = min, 65535 = max - self.highband = 0 # 0 = freq <= 5.4e9, 1 = freq > 5.4e9 - self.five_gig = 0 # 0 = freq <= 3.e9, 1 = freq > 3e9 - self.cp_current = 0 # 0 = 2mA, 1 = 4mA - self.ref_div = 4 # 1 to 7 - self.rssi_hbw = 0 # 0 = 2 MHz, 1 = 6 MHz - self.txlpf_bw = 1 # 1 = 12 MHz, 2 = 18 MHz, 3 = 24 MHz - self.rxlpf_bw = 1 # 0 = 7.5 MHz, 1 = 9.5 MHz, 2 = 14 MHz, 3 = 18 MHz - self.rxlpf_fine = 2 # 0 = 90%, 1 = 95%, 2 = 100%, 3 = 105%, 4 = 110% - self.rxvga_ser = 1 # 0 = RXVGA controlled by B7:1, 1 = controlled serially - self.rssi_range = 1 # 0 = low range (datasheet typo), 1 = high range (0.5V - 2.0V) - self.rssi_mode = 1 # 0 = enable follows RXHP, 1 = enabled - self.rssi_mux = 0 # 0 = RSSI, 1 = TEMP - self.rx_hp_pin = 0 # 0 = Fc set by rx_hpf, 1 = 600 KHz - self.rx_hpf = 0 # 0 = 100Hz, 1 = 30KHz - self.rx_ant = 0 # 0 = Ant. #1, 1 = Ant. #2 - self.tx_ant = 0 # 0 = Ant. #1, 1 = Ant. #2 - self.txvga_ser = 1 # 0 = TXVGA controlled by B6:1, 1 = controlled serially - self.tx_driver_lin = 2 # 0 = 50% (worst linearity), 1 = 63%, 2 = 78%, 3 = 100% (best lin) - self.tx_vga_lin = 2 # 0 = 50% (worst linearity), 1 = 63%, 2 = 78%, 3 = 100% (best lin) - self.tx_upconv_lin = 2 # 0 = 50% (worst linearity), 1 = 63%, 2 = 78%, 3 = 100% (best lin) - self.tx_bb_gain = 3 # 0 = maxgain-5dB, 1 = max-3dB, 2 = max-1.5dB, 3 = max - self.pabias_delay = 15 # 0 = 0, 15 = 7uS - self.pabias = 0 # 0 = 0 uA, 63 = 315uA - self.rx_rf_gain = 0 # 0 = 0dB, 1 = 0dB, 2 = 15dB, 3 = 30dB - self.rx_bb_gain = 16 # 0 = min, 31 = max (0 - 62 dB) - - self.txgain = 63 # 0 = min, 63 = max - - # Initialize GPIO and ATR - self.tx_write_io(TX_SAFE_IO, TX_OE_MASK) - self.tx_write_oe(TX_OE_MASK, ~0) - self.tx_set_atr_txval(TX_SAFE_IO) - self.tx_set_atr_rxval(TX_SAFE_IO) - self.tx_set_atr_mask(TX_OE_MASK) - self.rx_write_io(RX_SAFE_IO, RX_OE_MASK) - self.rx_write_oe(RX_OE_MASK, ~0) - self.rx_set_atr_rxval(RX_SAFE_IO) - self.rx_set_atr_txval(RX_SAFE_IO) - self.rx_set_atr_mask(RX_OE_MASK) - - # Initialize chipset - # TODO: perform reset sequence to ensure power up defaults - self.set_reg_standby() - self.set_reg_bandselpll() - self.set_reg_cal() - self.set_reg_lpf() - self.set_reg_rxrssi_ctrl() - self.set_reg_txlin_gain() - self.set_reg_pabias() - self.set_reg_rxgain() - self.set_reg_txgain() - self.set_freq(2.45e9) - - def __del__(self): - print "xcvr2450: __del__" - self.tx_set_atr_txval(TX_SAFE_IO) - self.tx_set_atr_rxval(TX_SAFE_IO) - self.rx_set_atr_rxval(RX_SAFE_IO) - self.rx_set_atr_txval(RX_SAFE_IO) - - - # -------------------------------------------------------------------- - # These methods set the MAX2829 onboard registers over the SPI bus. - # The SPI format is 18 bits, with the four LSBs holding the register no. - # Thus, the shift values used here are the D0-D13 values from the data - # sheet, *plus* four. - - # Standby (2) - def set_reg_standby(self): - self.reg_standby = ( - (self.mimo<<17) | - (1<<16) | - (1<<6) | - (1<<5) | - (1<<4) | 2) - self.send_reg(self.reg_standby) - - # Integer-Divider Ratio (3) - def set_reg_int_divider(self): - self.reg_int_divider = ( - ((self.frac_div & 0x03)<<16) | - (self.int_div<<4) | 3) - self.send_reg(self.reg_int_divider) - - # Fractional-Divider Ratio (4) - def set_reg_frac_divider(self): - self.reg_frac_divider = ((self.frac_div & 0xfffc)<<2) | 4 - self.send_reg(self.reg_frac_divider) - - # Band Select and PLL (5) - def set_reg_bandselpll(self): - self.reg_bandselpll = ( - (self.mimo<<17) | - (1<<16) | - (1<<15) | - (1<<11) | - (self.highband<<10) | - (self.cp_current<<9) | - (self.ref_div<<5) | - (self.five_gig<<4) | 5) - self.send_reg(self.reg_bandselpll) - - - # Calibration (6) - def set_reg_cal(self): - # FIXME do calibration - self.reg_cal = (1<<14)|6 - self.send_reg(self.reg_cal) - - - # Lowpass Filter (7) - def set_reg_lpf(self): - self.reg_lpf = ( - (self.rssi_hbw<<15) | - (self.txlpf_bw<<10) | - (self.rxlpf_bw<<9) | - (self.rxlpf_fine<<4) | 7) - self.send_reg(self.reg_lpf) - - - # Rx Control/RSSI (8) - def set_reg_rxrssi_ctrl(self): - self.reg_rxrssi_ctrl = ( - (self.rxvga_ser<<16) | - (self.rssi_range<<15) | - (self.rssi_mode<<14) | - (self.rssi_mux<<12) | - (1<<9) | - (self.rx_hpf<<6) | - (1<<4) | 8) - self.send_reg(self.reg_rxrssi_ctrl) - - - # Tx Linearity/Baseband Gain (9) - def set_reg_txlin_gain(self): - self.reg_txlin_gain = ( - (self.txvga_ser<<14) | - (self.tx_driver_lin<<12) | - (self.tx_vga_lin<<10) | - (self.tx_upconv_lin<<6) | - (self.tx_bb_gain<<4) | 9) - self.send_reg(self.reg_txlin_gain) - - - # PA Bias DAC (10) - def set_reg_pabias(self): - self.reg_pabias = ( - (self.pabias_delay<<10) | - (self.pabias<<4) | 10) - self.send_reg(self.reg_pabias) - - - # Rx Gain (11) - def set_reg_rxgain(self): - self.reg_rxgain = ( - (self.rx_rf_gain<<9) | - (self.rx_bb_gain<<4) | 11) - self.send_reg(self.reg_rxgain) - - - # Tx Gain (12) - def set_reg_txgain(self): - self.reg_txgain = (self.txgain<<4) | 12 - self.send_reg(self.reg_txgain) - - - # Send register write to SPI - def send_reg(self, v): - # Send 24 bits, it keeps last 18 clocked in - s = ''.join((chr((v >> 16) & 0xff), - chr((v >> 8) & 0xff), - chr(v & 0xff))) - self.u._write_spi(0, self.spi_enable, self.spi_format, s) - #print "xcvr2450: Setting reg %d to %06X" % ((v&15), v) - - # -------------------------------------------------------------------- - # These methods control the GPIO bus. Since the board has to access - # both the io_rx_* and io_tx_* pins, we define our own methods to do so. - # This bypasses any code in db_base. - # - # The board operates in ATR mode, always. Thus, when the board is first - # initialized, it is in receive mode, until bits show up in the TX FIFO. - # - def tx_write_oe(self, value, mask): - return self.u._write_fpga_reg((FR_OE_0, FR_OE_2)[self.which], - gru.hexint((mask << 16) | value)) - - def tx_write_io(self, value, mask): - return self.u._write_fpga_reg((FR_IO_0, FR_IO_2)[self.which], - gru.hexint((mask << 16) | value)) - - def tx_read_io(self): - t = self.u._read_fpga_reg((FR_RB_IO_RX_A_IO_TX_A, FR_RB_IO_RX_B_IO_TX_B)[self.which]) - return t & 0xffff - - - def rx_write_oe(self, value, mask): - return self.u._write_fpga_reg((FR_OE_1, FR_OE_3)[self.which], - gru.hexint((mask << 16) | value)) - - def rx_write_io(self, value, mask): - return self.u._write_fpga_reg((FR_IO_1, FR_IO_3)[self.which], - gru.hexint((mask << 16) | value)) - - def rx_read_io(self): - t = self.u._read_fpga_reg((FR_RB_IO_RX_A_IO_TX_A, FR_RB_IO_RX_B_IO_TX_B)[self.which]) - return (t >> 16) & 0xffff - - def tx_set_atr_mask(self, v): - return self.u._write_fpga_reg((FR_ATR_MASK_0,FR_ATR_MASK_2)[self.which], - gru.hexint(v)) - - def tx_set_atr_txval(self, v): - return self.u._write_fpga_reg((FR_ATR_TXVAL_0,FR_ATR_TXVAL_2)[self.which], - gru.hexint(v)) - - def tx_set_atr_rxval(self, v): - return self.u._write_fpga_reg((FR_ATR_RXVAL_0,FR_ATR_RXVAL_2)[self.which], - gru.hexint(v)) - - def rx_set_atr_mask(self, v): - return self.u._write_fpga_reg((FR_ATR_MASK_1,FR_ATR_MASK_3)[self.which], - gru.hexint(v)) - - def rx_set_atr_txval(self, v): - return self.u._write_fpga_reg((FR_ATR_TXVAL_1,FR_ATR_TXVAL_3)[self.which], - gru.hexint(v)) - - def rx_set_atr_rxval(self, v): - return self.u._write_fpga_reg((FR_ATR_RXVAL_1,FR_ATR_RXVAL_3)[self.which], - gru.hexint(v)) - - def set_gpio(self): - # We calculate four values: - # - # io_rx_while_rx: what to drive onto io_rx_* when receiving - # io_rx_while_tx: what to drive onto io_rx_* when transmitting - # io_tx_while_rx: what to drive onto io_tx_* when receiving - # io_tx_while_tx: what to drive onto io_tx_* when transmitting - # - # B1-B7 is ignored as gain is set serially for now. - - rx_hp = (0, RX_HP)[self.rx_hp_pin] - tx_antsel = (ANTSEL_TX1_RX2, ANTSEL_TX2_RX1)[self.tx_ant] - rx_antsel = (ANTSEL_TX1_RX2, ANTSEL_TX2_RX1)[self.rx_ant] - tx_pa_sel = (HB_PA_OFF, LB_PA_OFF)[self.five_gig] - io_rx_while_rx = EN|rx_hp|RX_EN - io_rx_while_tx = EN|rx_hp - io_tx_while_rx = HB_PA_OFF|LB_PA_OFF|rx_antsel|AD9515DIV - io_tx_while_tx = tx_pa_sel|tx_antsel|TX_EN|AD9515DIV - self.rx_set_atr_rxval(io_rx_while_rx) - self.rx_set_atr_txval(io_rx_while_tx) - self.tx_set_atr_rxval(io_tx_while_rx) - self.tx_set_atr_txval(io_tx_while_tx) - - #print "GPIO: RXRX=%04X RXTX=%04X TXRX=%04X TXTX=%04X" % ( - #io_rx_while_rx, io_rx_while_tx, io_tx_while_rx, io_tx_while_tx) - - # -------------------------------------------------------------------- - # These methods set control the high-level operating parameters. - - def set_freq(self, target_freq): - if target_freq > 3e9: - self.five_gig = 1 - self.ref_div = 1 - self.ad9515_div = 3 - scaler = 4.0/5.0 - else: - self.five_gig = 0 - self.ref_div = 1 - self.ad9515_div = 3 - scaler = 4.0/3.0; - - if target_freq > 5.275e9: - self.highband = 1 - else: - self.highband = 0 - - vco_freq = target_freq*scaler; - sys_clk = self.u.fpga_master_clock_freq() # Usually 64e6 - ref_clk = sys_clk / self.ad9515_div - - phdet_freq = ref_clk/self.ref_div - div = vco_freq/phdet_freq - self.int_div = int(math.floor(div)) - self.frac_div = int((div-self.int_div)*65536.0) - actual_freq = phdet_freq*(self.int_div+(self.frac_div/65536.0))/scaler - - #print "RF=%s VCO=%s R=%d PHD=%s DIV=%3.5f I=%3d F=%5d ACT=%s" % ( - # n2s(target_freq), n2s(vco_freq), self.ref_div, n2s(phdet_freq), - # div, self.int_div, self.frac_div, n2s(actual_freq)) - - self.set_gpio() - self.set_reg_int_divider() - self.set_reg_frac_divider() - self.set_reg_bandselpll() - - ok = self.lock_detect() - #if(not ok): - # ok = self.lock_detect() - # if ok: - # print "lock detect on 2nd try %f" % (target_freq,) - - if(not ok): - if (target_freq > 5.275e9) and (target_freq <= 5.35e9): - self.highband = 0 - self.set_reg_bandselpll() - ok = self.lock_detect() - print "swap to 0 at %f, ok %d" % (target_freq,ok) - if (target_freq >= 5.25e9) and (target_freq <= 5.275e9): - self.highband = 1 - self.set_reg_bandselpll() - ok = self.lock_detect() - print "swap to 1 at %f, ok %d" % (target_freq,ok) - - if(not ok): - print "Fail %f" % (target_freq,) - return (ok, actual_freq) - - def lock_detect(self): - """ - @returns: the value of the VCO/PLL lock detect bit. - @rtype: 0 or 1 - """ - if self.rx_read_io() & LOCKDET: - return True - else: # Give it a second chance - if self.rx_read_io() & LOCKDET: - return True - else: - return False - - def set_rx_gain(self, gain): - if gain < 0.0: gain = 0.0 - if gain > 92.0: gain = 92.0 - - # Split the gain between RF and baseband - # This is experimental, not prescribed - if gain < 31.0: - self.rx_rf_gain = 0 # 0 dB RF gain - self.rx_bb_gain = int(gain/2.0) - - if gain >= 30.0 and gain < 60.5: - self.rx_rf_gain = 2 # 15 dB RF gain - self.rx_bb_gain = int((gain-15.0)/2.0) - - if gain >= 60.5: - self.rx_rf_gain = 3 # 30.5 dB RF gain - self.rx_bb_gain = int((gain-30.5)/2.0) - - self.set_reg_rxgain() - - def set_tx_gain(self, gain): - if gain < 0.0: gain = 0.0 - if gain > 30.0: gain = 30.0 - self.txgain = int((gain/30.0)*63) - self.set_reg_txgain() - -class db_xcvr2450_base(db_base.db_base): - """ - Abstract base class for all xcvr2450 boards. - - Derive board specific subclasses from db_xcvr2450_base_{tx,rx} - """ - def __init__(self, usrp, which): - """ - @param usrp: instance of usrp.source_c - @param which: which side: 0 or 1 corresponding to side A or B respectively - @type which: int - """ - # sets _u _which _tx and _slot - db_base.db_base.__init__(self, usrp, which) - self.xcvr = _get_or_make_xcvr2450(usrp, which) - - def set_freq(self, target_freq): - """ - @returns (ok, actual_baseband_freq) where: - ok is True or False and indicates success or failure, - actual_baseband_freq is the RF frequency that corresponds to DC in the IF. - """ - return self.xcvr.set_freq(target_freq) - - def is_quadrature(self): - """ - Return True if this board requires both I & Q analog channels. - - This bit of info is useful when setting up the USRP Rx mux register. - """ - return True - - def freq_range(self): - return (2.4e9, 6e9, 1e6) - - def set_freq(self, target_freq): - return self.xcvr.set_freq(target_freq) - -# ---------------------------------------------------------------- - -class db_xcvr2450_tx(db_xcvr2450_base): - def __init__(self, usrp, which): - """ - @param usrp: instance of usrp.sink_c - @param which: 0 or 1 corresponding to side TX_A or TX_B respectively. - """ - print "db_xcvr2450_tx: __init__" - db_xcvr2450_base.__init__(self, usrp, which) - - def gain_range(self): - return (0, 30, (30.0/63.0)) - - def set_gain(self, gain): - return self.xcvr.set_tx_gain(gain) - - def i_and_q_swapped(self): - return True - -class db_xcvr2450_rx(db_xcvr2450_base): - def __init__(self, usrp, which): - """ - @param usrp: instance of usrp.source_c - @param which: 0 or 1 corresponding to side RX_A or RX_B respectively. - """ - print "db_xcvr2450_rx: __init__" - db_xcvr2450_base.__init__(self, usrp, which) - - def gain_range(self): - return (0.0, 92.0, 1) - - def set_gain(self, gain): - return self.xcvr.set_rx_gain(gain) - -#------------------------------------------------------------ -# hook these daughterboard classes into the auto-instantiation framework -db_instantiator.add(usrp_dbid.XCVR2450_TX, lambda usrp, which : (db_xcvr2450_tx(usrp, which),)) -db_instantiator.add(usrp_dbid.XCVR2450_RX, lambda usrp, which : (db_xcvr2450_rx(usrp, which),)) diff --git a/gr-usrp/src/qa_usrp.py b/gr-usrp/src/qa_usrp.py index 99d1cfa6f..db2d32624 100755 --- a/gr-usrp/src/qa_usrp.py +++ b/gr-usrp/src/qa_usrp.py @@ -21,7 +21,7 @@ # from gnuradio import gr, gr_unittest -import usrp1 +import usrp_swig class qa_usrp (gr_unittest.TestCase): diff --git a/gr-usrp/src/usrp.i b/gr-usrp/src/usrp.i new file mode 100644 index 000000000..40fa471b0 --- /dev/null +++ b/gr-usrp/src/usrp.i @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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 version 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. + */ + +%feature("autodoc", "1"); // generate python docstrings + +%include "exception.i" +%import "gnuradio.i" // the common stuff + +%{ +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include <stdexcept> +#include <vector> +%} + +%include <usrp_subdev_spec.h> +%include <db_base.i> +%include <fpga_regs_common.h> +%include <fpga_regs_standard.h> +%include "usrp_standard.i" +%include "usrp_base.i" +%include "usrp_source_base.i" +%include "usrp_source_c.i" +%include "usrp_source_s.i" +%include "usrp_sink_base.i" +%include "usrp_sink_c.i" +%include "usrp_sink_s.i" + +//---Allow a more Pythonic interface +%pythoncode %{ + +# Allow subdev_spec to be tuple +def __selected_subdev(self, subdev_spec): + ss = usrp_subdev_spec(subdev_spec[0], subdev_spec[1]) + return self._real_selected_subdev(ss) + +# Allow subdev_spec to be tuple +def __determine_tx_mux_value(self, subdev_spec): + ss = usrp_subdev_spec(subdev_spec[0], subdev_spec[1]) + return self._real_determine_tx_mux_value(ss) + +# Allow subdev_spec to be tuple +def __determine_rx_mux_value(self, subdev_spec): + ss = usrp_subdev_spec(subdev_spec[0], subdev_spec[1]) + return self._real_determine_rx_mux_value(ss) + +# Allow subdev_spec to be tuple +def __pick_subdev(self, candidates=[]): + ss = self._real_pick_subdev(candidates) + return (ss.side, ss.subdev) + +# Allow subdev_spec to be tuple +def __pick_tx_subdevice(self): + ss = self._real_pick_tx_subdevice() + return (ss.side, ss.subdev) + +# Allow subdev_spec to be tuple +def __pick_rx_subdevice(self): + ss = self._real_pick_rx_subdevice() + return (ss.side, ss.subdev) + +# Make return tune_result or None on failure +def __tune(self, chan, db, target_freq): + tr = usrp_tune_result() + r = self._real_tune(chan, db, target_freq, tr) + if r: + return tr + else: + return None + +# Allow to be called as a free function +def tune(u, chan, subdev, target_freq): + return u.tune(chan, subdev, target_freq) + +# Allow to be called as free function +def determine_tx_mux_value(u, subdev_spec): + return u.determine_tx_mux_value(subdev_spec) + +# Allow to be called as free function +def determine_rx_mux_value(u, subdev_spec): + return u.determine_rx_mux_value(subdev_spec) + +# Allow to be called as free function +def selected_subdev(u, subdev_spec): + return u.selected_subdev(subdev_spec) + +# Allow to be called as free function +def pick_subdev(u, candidates=[]): + return u.pick_subdev(candidates); + +# Allow to be called as free function +def pick_tx_subdevice(u): + return u.pick_tx_subdevice(); + +# Allow to be called as free function +def pick_rx_subdevice(u): + return u.pick_rx_subdevice(); + +# Jam into Python objects +usrp_sink_c_sptr.determine_tx_mux_value = __determine_tx_mux_value +usrp_sink_s_sptr.determine_tx_mux_value = __determine_tx_mux_value + +usrp_source_c_sptr.determine_rx_mux_value = __determine_rx_mux_value +usrp_source_s_sptr.determine_rx_mux_value = __determine_rx_mux_value + +usrp_sink_c_sptr.selected_subdev = __selected_subdev +usrp_sink_s_sptr.selected_subdev = __selected_subdev +usrp_source_c_sptr.selected_subdev = __selected_subdev +usrp_source_s_sptr.selected_subdev = __selected_subdev + +usrp_sink_c_sptr.tune = __tune +usrp_sink_s_sptr.tune = __tune +usrp_source_c_sptr.tune = __tune +usrp_source_s_sptr.tune = __tune + +usrp_sink_c_sptr.pick_subdev = __pick_subdev +usrp_sink_s_sptr.pick_subdev = __pick_subdev +usrp_source_c_sptr.pick_subdev = __pick_subdev +usrp_source_s_sptr.pick_subdev = __pick_subdev + +usrp_sink_c_sptr.pick_tx_subdevice = __pick_tx_subdevice +usrp_sink_s_sptr.pick_tx_subdevice = __pick_tx_subdevice +usrp_source_c_sptr.pick_rx_subdevice = __pick_rx_subdevice +usrp_source_s_sptr.pick_rx_subdevice = __pick_rx_subdevice + +%} diff --git a/gr-usrp/src/usrp.py b/gr-usrp/src/usrp.py deleted file mode 100644 index 0fe6a2c47..000000000 --- a/gr-usrp/src/usrp.py +++ /dev/null @@ -1,482 +0,0 @@ -# -# Copyright 2004,2005,2007 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 version 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. -# - - - -from usrpm import usrp_prims -from usrpm import usrp_dbid -from gnuradio import usrp1 # usrp Rev 1 and later -from gnuradio import gru -from usrpm.usrp_fpga_regs import * -import weakref - -FPGA_MODE_NORMAL = usrp1.FPGA_MODE_NORMAL -FPGA_MODE_LOOPBACK = usrp1.FPGA_MODE_LOOPBACK -FPGA_MODE_COUNTING = usrp1.FPGA_MODE_COUNTING - -SPI_FMT_xSB_MASK = usrp1.SPI_FMT_xSB_MASK -SPI_FMT_LSB = usrp1.SPI_FMT_LSB -SPI_FMT_MSB = usrp1.SPI_FMT_MSB -SPI_FMT_HDR_MASK = usrp1.SPI_FMT_HDR_MASK -SPI_FMT_HDR_0 = usrp1.SPI_FMT_HDR_0 -SPI_FMT_HDR_1 = usrp1.SPI_FMT_HDR_1 -SPI_FMT_HDR_2 = usrp1.SPI_FMT_HDR_2 - -SPI_ENABLE_FPGA = usrp1.SPI_ENABLE_FPGA -SPI_ENABLE_CODEC_A = usrp1.SPI_ENABLE_CODEC_A -SPI_ENABLE_CODEC_B = usrp1.SPI_ENABLE_CODEC_B -SPI_ENABLE_reserved = usrp1.SPI_ENABLE_reserved -SPI_ENABLE_TX_A = usrp1.SPI_ENABLE_TX_A -SPI_ENABLE_RX_A = usrp1.SPI_ENABLE_RX_A -SPI_ENABLE_TX_B = usrp1.SPI_ENABLE_TX_B -SPI_ENABLE_RX_B = usrp1.SPI_ENABLE_RX_B - - -# Import all the daughterboard classes we know about. -# This hooks them into the auto-instantiation framework. - -import db_instantiator - -import db_basic -import db_dbs_rx -import db_flexrf -import db_flexrf_mimo -import db_tv_rx -import db_wbx -import db_xcvr2450 -import db_dtt754 -import db_dtt768 - -def _look_for_usrp(which): - """ - Try to open the specified usrp. - - @param which: int >= 0 specifying which USRP to open - @type which: int - - @return: Returns version number, or raises RuntimeError - @rtype: int - """ - d = usrp_prims.usrp_find_device(which) - if not d: - raise RuntimeError, "Unable to find USRP #%d" % (which,) - - return usrp_prims.usrp_hw_rev(d) - - -def _ensure_rev2(which): - v = _look_for_usrp(which) - if not v in (2, 4): - raise RuntimeError, "Sorry, unsupported USRP revision (rev=%d)" % (v,) - - -class tune_result(object): - """ - Container for intermediate tuning information. - """ - def __init__(self, baseband_freq, dxc_freq, residual_freq, inverted): - self.baseband_freq = baseband_freq - self.dxc_freq = dxc_freq - self.residual_freq = residual_freq - self.inverted = inverted - - -def tune(u, chan, subdev, target_freq): - """ - Set the center frequency we're interested in. - - @param u: instance of usrp.source_* or usrp.sink_* - @param chan: DDC/DUC channel - @type chan: int - @param subdev: daughterboard subdevice - @param target_freq: frequency in Hz - @returns False if failure else tune_result - - Tuning is a two step process. First we ask the front-end to - tune as close to the desired frequency as it can. Then we use - the result of that operation and our target_frequency to - determine the value for the digital down converter. - """ - - # Does this usrp instance do Tx or Rx? - rx_p = True - try: - u.rx_freq - except AttributeError: - rx_p = False - - ok, baseband_freq = subdev.set_freq(target_freq) - dxc_freq, inverted = calc_dxc_freq(target_freq, baseband_freq, u.converter_rate()) - - # If the spectrum is inverted, and the daughterboard doesn't do - # quadrature downconversion, we can fix the inversion by flipping the - # sign of the dxc_freq... (This only happens using the basic_rx board) - - if subdev.spectrum_inverted(): - inverted = not(inverted) - - if inverted and not(subdev.is_quadrature()): - dxc_freq = -dxc_freq - inverted = not(inverted) - - if rx_p: - ok = ok and u.set_rx_freq(chan, dxc_freq) - else: - dxc_freq = -dxc_freq - ok = ok and u.set_tx_freq(chan, dxc_freq) - - if not(ok): - return False - - # residual_freq is the offset left over because of dxc tuning step size - if rx_p: - residual_freq = dxc_freq - u.rx_freq(chan) - else: - residual_freq = dxc_freq - u.tx_freq(chan) - - return tune_result(baseband_freq, dxc_freq, residual_freq, inverted) - - -# ------------------------------------------------------------------------ -# Build subclasses of raw usrp1.* class that add the db attribute -# by automatically instantiating the appropriate daughterboard classes. -# [Also provides keyword args.] -# ------------------------------------------------------------------------ - -class usrp_common(object): - def __init__(self): - # read capability register - r = self._u._read_fpga_reg(FR_RB_CAPS) - if r < 0: - r += 2**32 - if r == 0xaa55ff77: # value of this reg prior to being defined as cap reg - r = ((2 << bmFR_RB_CAPS_NDUC_SHIFT) - | (2 << bmFR_RB_CAPS_NDDC_SHIFT) - | bmFR_RB_CAPS_RX_HAS_HALFBAND) - self._fpga_caps = r - - if False: - print "FR_RB_CAPS = %#08x" % (self._fpga_caps,) - print "has_rx_halfband =", self.has_rx_halfband() - print "nDDCs =", self.nddc() - print "has_tx_halfband =", self.has_tx_halfband() - print "nDUCs =", self.nduc() - - def __getattr__(self, name): - return getattr(self._u, name) - - def tune(self, chan, subdev, target_freq): - return tune(self, chan, subdev, target_freq) - - def has_rx_halfband(self): - return self._fpga_caps & bmFR_RB_CAPS_RX_HAS_HALFBAND != 0 - - def has_tx_halfband(self): - return self._fpga_caps & bmFR_RB_CAPS_TX_HAS_HALFBAND != 0 - - def nddc(self): - """ - Number of Digital Down Converters implemented in FPGA - """ - return (self._fpga_caps & bmFR_RB_CAPS_NDDC_MASK) >> bmFR_RB_CAPS_NDDC_SHIFT - - def nduc(self): - """ - Number of Digital Up Converters implemented in FPGA - """ - return (self._fpga_caps & bmFR_RB_CAPS_NDUC_MASK) >> bmFR_RB_CAPS_NDUC_SHIFT - - -class sink_c(usrp_common): - def __init__(self, which=0, interp_rate=128, nchan=1, mux=0x98, - fusb_block_size=0, fusb_nblocks=0, - fpga_filename="", firmware_filename=""): - _ensure_rev2(which) - self._u = usrp1.sink_c(which, interp_rate, nchan, mux, - fusb_block_size, fusb_nblocks, - fpga_filename, firmware_filename) - # Add the db attribute, which contains a 2-tuple of tuples of daughterboard classes - self.db = (db_instantiator.instantiate(self._u, 0), - db_instantiator.instantiate(self._u, 1)) - usrp_common.__init__(self) - - def __del__(self): - self.db = None # will fire d'board destructors - self._u = None # will fire usrp1.* destructor - - -class sink_s(usrp_common): - def __init__(self, which=0, interp_rate=128, nchan=1, mux=0x98, - fusb_block_size=0, fusb_nblocks=0, - fpga_filename="", firmware_filename=""): - _ensure_rev2(which) - self._u = usrp1.sink_s(which, interp_rate, nchan, mux, - fusb_block_size, fusb_nblocks, - fpga_filename, firmware_filename) - # Add the db attribute, which contains a 2-tuple of tuples of daughterboard classes - self.db = (db_instantiator.instantiate(self._u, 0), - db_instantiator.instantiate(self._u, 1)) - usrp_common.__init__(self) - - def __del__(self): - self.db = None # will fire d'board destructors - self._u = None # will fire usrp1.* destructor - - -class source_c(usrp_common): - def __init__(self, which=0, decim_rate=64, nchan=1, mux=0x32103210, mode=0, - fusb_block_size=0, fusb_nblocks=0, - fpga_filename="", firmware_filename=""): - _ensure_rev2(which) - self._u = usrp1.source_c(which, decim_rate, nchan, mux, mode, - fusb_block_size, fusb_nblocks, - fpga_filename, firmware_filename) - # Add the db attribute, which contains a 2-tuple of tuples of daughterboard classes - self.db = (db_instantiator.instantiate(self._u, 0), - db_instantiator.instantiate(self._u, 1)) - usrp_common.__init__(self) - - def __del__(self): - self.db = None # will fire d'board destructors - self._u = None # will fire usrp1.* destructor - - -class source_s(usrp_common): - def __init__(self, which=0, decim_rate=64, nchan=1, mux=0x32103210, mode=0, - fusb_block_size=0, fusb_nblocks=0, - fpga_filename="", firmware_filename=""): - _ensure_rev2(which) - self._u = usrp1.source_s(which, decim_rate, nchan, mux, mode, - fusb_block_size, fusb_nblocks, - fpga_filename, firmware_filename) - # Add the db attribute, which contains a 2-tuple of tuples of daughterboard classes - self.db = (db_instantiator.instantiate(self._u, 0), - db_instantiator.instantiate(self._u, 1)) - usrp_common.__init__(self) - - def __del__(self): - self.db = None # will fire d'board destructors - self._u = None # will fire usrp1.* destructor - - -# ------------------------------------------------------------------------ -# utilities -# ------------------------------------------------------------------------ - -def determine_rx_mux_value(u, subdev_spec): - """ - Determine appropriate Rx mux value as a function of the subdevice choosen and the - characteristics of the respective daughterboard. - - @param u: instance of USRP source - @param subdev_spec: return value from subdev option parser. - @type subdev_spec: (side, subdev), where side is 0 or 1 and subdev is 0 or 1 - @returns: the Rx mux value - """ - # Figure out which A/D's to connect to the DDC. - # - # Each daughterboard consists of 1 or 2 subdevices. (At this time, - # all but the Basic Rx have a single subdevice. The Basic Rx - # has two independent channels, treated as separate subdevices). - # subdevice 0 of a daughterboard may use 1 or 2 A/D's. We determine this - # by checking the is_quadrature() method. If subdevice 0 uses only a single - # A/D, it's possible that the daughterboard has a second subdevice, subdevice 1, - # and it uses the second A/D. - # - # If the card uses only a single A/D, we wire a zero into the DDC Q input. - # - # (side, 0) says connect only the A/D's used by subdevice 0 to the DDC. - # (side, 1) says connect only the A/D's used by subdevice 1 to the DDC. - # - - side = subdev_spec[0] # side A = 0, side B = 1 - - if not(side in (0, 1)): - raise ValueError, "Invalid subdev_spec: %r:" % (subdev_spec,) - - db = u.db[side] # This is a tuple of length 1 or 2 containing the subdevice - # classes for the selected side. - - # compute bitmasks of used A/D's - - if db[0].is_quadrature(): - subdev0_uses = 0x3 # uses A/D 0 and 1 - else: - subdev0_uses = 0x1 # uses A/D 0 only - - if len(db) > 1: - subdev1_uses = 0x2 # uses A/D 1 only - else: - subdev1_uses = 0x0 # uses no A/D (doesn't exist) - - if subdev_spec[1] == 0: - uses = subdev0_uses - elif subdev_spec[1] == 1: - uses = subdev1_uses - else: - raise ValueError, "Invalid subdev_spec: %r: " % (subdev_spec,) - - if uses == 0: - raise RuntimeError, "Daughterboard doesn't have a subdevice 1: %r: " % (subdev_spec,) - - swap_iq = db[0].i_and_q_swapped() - - truth_table = { - # (side, uses, swap_iq) : mux_val - (0, 0x1, False) : 0xf0f0f0f0, - (0, 0x2, False) : 0xf0f0f0f1, - (0, 0x3, False) : 0x00000010, - (0, 0x3, True) : 0x00000001, - (1, 0x1, False) : 0xf0f0f0f2, - (1, 0x2, False) : 0xf0f0f0f3, - (1, 0x3, False) : 0x00000032, - (1, 0x3, True) : 0x00000023 - } - - return gru.hexint(truth_table[(side, uses, swap_iq)]) - - -def determine_tx_mux_value(u, subdev_spec): - """ - Determine appropriate Tx mux value as a function of the subdevice choosen. - - @param u: instance of USRP source - @param subdev_spec: return value from subdev option parser. - @type subdev_spec: (side, subdev), where side is 0 or 1 and subdev is 0 - @returns: the Rx mux value - """ - # This is simpler than the rx case. Either you want to talk - # to side A or side B. If you want to talk to both sides at once, - # determine the value manually. - - side = subdev_spec[0] # side A = 0, side B = 1 - if not(side in (0, 1)): - raise ValueError, "Invalid subdev_spec: %r:" % (subdev_spec,) - - db = u.db[side] - - if(db[0].i_and_q_swapped()): - return gru.hexint([0x0089, 0x8900][side]) - else: - return gru.hexint([0x0098, 0x9800][side]) - - -def selected_subdev(u, subdev_spec): - """ - Return the user specified daughterboard subdevice. - - @param u: an instance of usrp.source_* or usrp.sink_* - @param subdev_spec: return value from subdev option parser. - @type subdev_spec: (side, subdev), where side is 0 or 1 and subdev is 0 or 1 - @returns: an weakref to an instance derived from db_base - """ - side, subdev = subdev_spec - # Note: This allows db to go out of scope at the right time - return weakref.proxy(u.db[side][subdev]) - - -def calc_dxc_freq(target_freq, baseband_freq, fs): - """ - Calculate the frequency to use for setting the digital up or down converter. - - @param target_freq: desired RF frequency (Hz) - @type target_freq: number - @param baseband_freq: the RF frequency that corresponds to DC in the IF. - @type baseband_freq: number - @param fs: converter sample rate - @type fs: number - - @returns: 2-tuple (ddc_freq, inverted) where ddc_freq is the value - for the ddc and inverted is True if we're operating in an inverted - Nyquist zone. - """ - - delta = target_freq - baseband_freq - - if delta >= 0: - while delta > fs: - delta -= fs - if delta <= fs/2: - return (-delta, False) # non-inverted region - else: - return (delta - fs, True) # inverted region - else: - while delta < -fs: - delta += fs - if delta >= -fs/2: - return (-delta, False) # non-inverted region - else: - return (delta + fs, True) # inverted region - - -# ------------------------------------------------------------------------ -# Utilities -# ------------------------------------------------------------------------ - -def pick_tx_subdevice(u): - """ - The user didn't specify a tx subdevice on the command line. - Try for one of these, in order: FLEX_400, FLEX_900, FLEX_1200, FLEX_2400, - BASIC_TX, whatever's on side A. - - @return a subdev_spec - """ - return pick_subdev(u, (usrp_dbid.FLEX_400_TX, - usrp_dbid.FLEX_900_TX, - usrp_dbid.FLEX_1200_TX, - usrp_dbid.FLEX_2400_TX, - usrp_dbid.BASIC_TX)) - -def pick_rx_subdevice(u): - """ - The user didn't specify an rx subdevice on the command line. - Try for one of these, in order: FLEX_400, FLEX_900, FLEX_1200, FLEX_2400, - TV_RX, DBS_RX, BASIC_RX, whatever's on side A. - - @return a subdev_spec - """ - return pick_subdev(u, (usrp_dbid.FLEX_400_RX, - usrp_dbid.FLEX_900_RX, - usrp_dbid.FLEX_1200_RX, - usrp_dbid.FLEX_2400_RX, - usrp_dbid.TV_RX, - usrp_dbid.TV_RX_REV_2, - usrp_dbid.DBS_RX, - usrp_dbid.DBS_RX_REV_2_1, - usrp_dbid.BASIC_RX)) - -def pick_subdev(u, candidates): - """ - @param u: usrp instance - @param candidates: list of dbids - @returns: subdev specification - """ - db0 = u.db[0][0].dbid() - db1 = u.db[1][0].dbid() - for c in candidates: - if c == db0: return (0, 0) - if c == db1: return (1, 0) - if db0 >= 0: - return (0, 0) - if db1 >= 0: - return (1, 0) - raise RuntimeError, "No suitable daughterboard found!" - diff --git a/gr-usrp/src/usrp1.i b/gr-usrp/src/usrp1.i deleted file mode 100644 index 24d229f51..000000000 --- a/gr-usrp/src/usrp1.i +++ /dev/null @@ -1,657 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 version 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. - */ - -%feature("autodoc", "1"); // generate python docstrings - -%include "exception.i" -%import "gnuradio.i" // the common stuff - -%{ - -#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix -#include "usrp1_sink_c.h" -#include "usrp1_sink_s.h" -#include "usrp1_source_c.h" -#include "usrp1_source_s.h" -#include <stdexcept> -#include <usrp_standard.h> -#include <usrp_spi_defs.h> -%} - -%include <usrp_spi_defs.h> - -%constant int FPGA_MODE_NORMAL = usrp_standard_rx::FPGA_MODE_NORMAL; -%constant int FPGA_MODE_LOOPBACK = usrp_standard_rx::FPGA_MODE_LOOPBACK; -%constant int FPGA_MODE_COUNTING = usrp_standard_rx::FPGA_MODE_COUNTING; - -// ================================================================ -// abstract classes -// ================================================================ - -class usrp1_sink_base : public gr_sync_block { -protected: - usrp1_sink_base (const std::string &name, - gr_io_signature_sptr input_signature, - int which_board, - unsigned int interp_rate, - int nchan, - int mux, - int fusb_block_size, - int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename - ) throw (std::runtime_error); - - virtual void copy_to_usrp_buffer (gr_vector_const_void_star &input_items, - int input_index, - int input_items_available, - int &input_items_consumed, - void *usrp_buffer, - int usrp_buffer_length, - int &bytes_written) = 0; - public: - ~usrp1_sink_base (); - - /*! - * \brief Set interpolator rate. \p rate must be in [4, 1024] and a multiple of 4. - * - * The final complex sample rate across the USB is - * dac_freq () * nchannels () / interp_rate () - */ - bool set_interp_rate (unsigned int rate); - bool set_nchannels (int nchan); - bool set_mux (int mux); - - /*! - * \brief set the frequency of the digital up converter. - * - * \p channel must be 0 or 1. \p freq is the center frequency in Hz. - * It must be in the range [-44M, 44M]. The frequency specified is - * quantized. Use tx_freq to retrieve the actual value used. - */ - bool set_tx_freq (int channel, double freq); - - void set_verbose (bool verbose); - - // ACCESSORS - - long fpga_master_clock_freq() const; - long converter_rate() const; // D/A sample rate - long dac_rate() const; // alias - long dac_freq () const; // deprecated name. Use converter_rate() or dac_rate(). - - unsigned int interp_rate () const; - double tx_freq (int channel) const; - int nunderruns () const { return d_nunderruns; } - - /*! - * \brief Set Programmable Gain Amplifier (PGA) - * - * \param which which D/A [0,3] - * \param gain_in_db gain value (linear in dB) - * - * gain is rounded to closest setting supported by hardware. - * Note that DAC 0 and DAC 1 share a gain setting as do DAC 2 and DAC 3. - * Setting DAC 0 affects DAC 1 and vice versa. Same with DAC 2 and DAC 3. - * - * \returns true iff sucessful. - * - * \sa pga_min(), pga_max(), pga_db_per_step() - */ - bool set_pga (int which, double gain_in_db); - - /*! - * \brief Return programmable gain amplifier gain in dB. - * - * \param which which D/A [0,3] - */ - double pga (int which) const; - - /*! - * \brief Return minimum legal PGA gain in dB. - */ - double pga_min () const; - - /*! - * \brief Return maximum legal PGA gain in dB. - */ - double pga_max () const; - - /*! - * \brief Return hardware step size of PGA (linear in dB). - */ - double pga_db_per_step () const; - - /*! - * \brief Return daughterboard ID for given Tx daughterboard slot [0,1]. - * - * \return daughterboard id >= 0 if successful - * \return -1 if no daugherboard - * \return -2 if invalid EEPROM on daughterboard - */ - int daughterboard_id (int which_dboard) const; - - /*! - * \brief Set ADC offset correction - * \param which which ADC[0,3]: 0 = RX_A I, 1 = RX_A Q... - * \param offset 16-bit value to subtract from raw ADC input. - */ - bool set_adc_offset (int which, int offset); - - /*! - * \brief Set DAC offset correction - * \param which which DAC[0,3]: 0 = TX_A I, 1 = TX_A Q... - * \param offset 10-bit offset value (ambiguous format: See AD9862 datasheet). - * \param offset_pin 1-bit value. If 0 offset applied to -ve differential pin; - * If 1 offset applied to +ve differential pin. - */ - bool set_dac_offset (int which, int offset, int offset_pin); - - /*! - * \brief Control ADC input buffer - * \param which which ADC[0,3] - * \param bypass if non-zero, bypass input buffer and connect input - * directly to switched cap SHA input of RxPGA. - */ - bool set_adc_buffer_bypass (int which, bool bypass); - - /*! - * \brief return the usrp's serial number. - * - * \returns non-zero length string iff successful. - */ - std::string serial_number(); - - /*! - * \brief Write direction register (output enables) for pins that go to daughterboard. - * - * \param which_dboard [0,1] which d'board - * \param value value to write into register - * \param mask which bits of value to write into reg - * - * Each d'board has 16-bits of general purpose i/o. - * Setting the bit makes it an output from the FPGA to the d'board. - * - * This register is initialized based on a value stored in the - * d'board EEPROM. In general, you shouldn't be using this routine - * without a very good reason. Using this method incorrectly will - * kill your USRP motherboard and/or daughterboard. - */ - bool _write_oe (int which_dboard, int value, int mask); - - /*! - * \brief Write daughterboard i/o pin value - * - * \param which_dboard [0,1] which d'board - * \param value value to write into register - * \param mask which bits of value to write into reg - */ - bool write_io (int which_dboard, int value, int mask); - - /*! - * \brief Read daughterboard i/o pin value - * - * \param which_dboard [0,1] which d'board - * \returns register value if successful, else READ_FAILED - */ - int read_io (int which_dboard); - - bool write_aux_dac (int which_dboard, int which_dac, int value); - int read_aux_adc (int which_dboard, int which_adc); - bool write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf); - std::string read_eeprom (int i2c_addr, int eeprom_offset, int len); - bool write_i2c (int i2c_addr, const std::string buf); - std::string read_i2c (int i2c_addr, int len); - - bool _write_fpga_reg (int regno, int value); //< 7-bit regno, 32-bit value - int _read_fpga_reg (int regno); - bool _write_9862 (int which_codec, int regno, unsigned char value); - int _read_9862 (int which_codec, int regno) const; - - /*! - * \brief Write data to SPI bus peripheral. - * - * \param optional_header 0,1 or 2 bytes to write before buf. - * \param enables bitmask of peripherals to write. See usrp_spi_defs.h - * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* - * \param buf the data to write - * \returns true iff successful - * Writes are limited to a maximum of 64 bytes. - * - * If \p format specifies that optional_header bytes are present, they are - * written to the peripheral immediately prior to writing \p buf. - */ - bool _write_spi (int optional_header, int enables, int format, std::string buf); - - /* - * \brief Read data from SPI bus peripheral. - * - * \param optional_header 0,1 or 2 bytes to write before buf. - * \param enables bitmask of peripheral to read. See usrp_spi_defs.h - * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* - * \param len number of bytes to read. Must be in [0,64]. - * \returns the data read if sucessful, else a zero length string. - * - * Reads are limited to a maximum of 64 bytes. - * - * If \p format specifies that optional_header bytes are present, they - * are written to the peripheral first. Then \p len bytes are read from - * the peripheral and returned. - */ - std::string _read_spi (int optional_header, int enables, int format, int len); -}; - -// ---------------------------------------------------------------- - -class usrp1_source_base : public gr_sync_block { - protected: - - usrp1_source_base (const std::string &name, - gr_io_signature_sptr input_signature, - int which_board, - unsigned int interp_rate, - int nchan, - int mux, - int fusb_block_size, - int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename - ) throw (std::runtime_error); - - virtual int ninput_bytes_reqd_for_noutput_items (int noutput_items) = 0; - - virtual void copy_from_usrp_buffer (gr_vector_void_star &output_items, - int output_index, - int output_items_available, - int &output_items_produced, - const void *usrp_buffer, - int usrp_buffer_length, - int &bytes_read) = 0; - public: - ~usrp1_source_base (); - - - /*! - * \brief Set decimator rate. \p rate must be EVEN and in [8, 256]. - * - * The final complex sample rate across the USB is - * adc_freq () / decim_rate () - */ - bool set_decim_rate (unsigned int rate); - bool set_nchannels (int nchan); - bool set_mux (int mux); - - /*! - * \brief set the center frequency of the digital down converter. - * - * \p channel must be 0. \p freq is the center frequency in Hz. - * It must be in the range [-FIXME, FIXME]. The frequency specified is - * quantized. Use rx_freq to retrieve the actual value used. - */ - bool set_rx_freq (int channel, double freq); - - /*! - * \brief set fpga special modes - */ - bool set_fpga_mode (int mode); - - /*! - * \brief Set the digital down converter phase register. - * - * \param channel which ddc channel [0, 3] - * \param phase 32-bit integer phase value. - */ - bool set_ddc_phase(int channel, int phase); - - - void set_verbose (bool verbose); - - // ACCESSORS - - long fpga_master_clock_freq() const; - long converter_rate() const; // A/D sample rate - long adc_rate() const; // alias - long adc_freq() const; // Deprecated name. Use converter_rate() or adc_rate(). - - unsigned int decim_rate () const; - double rx_freq (int channel) const; - int noverruns () const { return d_noverruns; } - - - // PGA stuff - /*! - * \brief Set Programmable Gain Amplifier (PGA) - * - * \param which which A/D [0,3] - * \param gain_in_db gain value (linear in dB) - * - * gain is rounded to closest setting supported by hardware. - * - * \returns true iff sucessful. - * - * \sa pga_min(), pga_max(), pga_db_per_step() - */ - bool set_pga (int which, double gain_in_db); - - /*! - * \brief Return programmable gain amplifier gain setting in dB. - * - * \param which which A/D [0,3] - */ - double pga (int which) const; - - /*! - * \brief Return minimum legal PGA setting in dB. - */ - double pga_min () const; - - /*! - * \brief Return maximum legal PGA setting in dB. - */ - double pga_max () const; - - /*! - * \brief Return hardware step size of PGA (linear in dB). - */ - double pga_db_per_step () const; - - /*! - * \brief Return daughterboard ID for given Rx daughterboard slot [0,1]. - * - * \return daughterboard id >= 0 if successful - * \return -1 if no daugherboard - * \return -2 if invalid EEPROM on daughterboard - */ - int daughterboard_id (int which_dboard) const; - - /*! - * \brief Set ADC offset correction - * \param which which ADC[0,3]: 0 = RX_A I, 1 = RX_A Q... - * \param offset 16-bit value to subtract from raw ADC input. - */ - bool set_adc_offset (int which, int offset); - - /*! - * \brief Set DAC offset correction - * \param which which DAC[0,3]: 0 = TX_A I, 1 = TX_A Q... - * \param offset 10-bit offset value (ambiguous format: See AD9862 datasheet). - * \param offset_pin 1-bit value. If 0 offset applied to -ve differential pin; - * If 1 offset applied to +ve differential pin. - */ - bool set_dac_offset (int which, int offset, int offset_pin); - - /*! - * \brief Control ADC input buffer - * \param which which ADC[0,3] - * \param bypass if non-zero, bypass input buffer and connect input - * directly to switched cap SHA input of RxPGA. - */ - bool set_adc_buffer_bypass (int which, bool bypass); - - /*! - * \brief return the usrp's serial number. - * - * \returns non-zero length string iff successful. - */ - std::string serial_number(); - - /*! - * \brief Write direction register (output enables) for pins that go to daughterboard. - * - * \param which_dboard [0,1] which d'board - * \param value value to write into register - * \param mask which bits of value to write into reg - * - * Each d'board has 16-bits of general purpose i/o. - * Setting the bit makes it an output from the FPGA to the d'board. - * - * This register is initialized based on a value stored in the - * d'board EEPROM. In general, you shouldn't be using this routine - * without a very good reason. Using this method incorrectly will - * kill your USRP motherboard and/or daughterboard. - */ - bool _write_oe (int which_dboard, int value, int mask); - - /*! - * \brief Write daughterboard i/o pin value - * - * \param which_dboard [0,1] which d'board - * \param value value to write into register - * \param mask which bits of value to write into reg - */ - bool write_io (int which_dboard, int value, int mask); - - /*! - * \brief Read daughterboard i/o pin value - * - * \param which_dboard [0,1] which d'board - * \returns register value if successful, else READ_FAILED - */ - int read_io (int which_dboard); - - /*! - * \brief Enable/disable automatic DC offset removal control loop in FPGA - * - * \param bits which control loops to enable - * \param mask which \p bits to pay attention to - * - * If the corresponding bit is set, enable the automatic DC - * offset correction control loop. - * - * <pre> - * The 4 low bits are significant: - * - * ADC0 = (1 << 0) - * ADC1 = (1 << 1) - * ADC2 = (1 << 2) - * ADC3 = (1 << 3) - * </pre> - * - * By default the control loop is enabled on all ADC's. - */ - bool set_dc_offset_cl_enable(int bits, int mask); - - /*! - * \brief Specify Rx data format. - * - * \param format format specifier - * - * Rx data format control register - * - * 3 2 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------------------------------------+-+-+---------+-------+ - * | Reserved (Must be zero) |B|Q| WIDTH | SHIFT | - * +-----------------------------------------+-+-+---------+-------+ - * - * SHIFT specifies arithmetic right shift [0, 15] - * WIDTH specifies bit-width of I & Q samples across the USB [1, 16] (not all valid) - * Q if set deliver both I & Q, else just I - * B if set bypass half-band filter. - * - * Right now the acceptable values are: - * - * B Q WIDTH SHIFT - * 0 1 16 0 - * 0 1 8 8 - * - * More valid combos to come. - * - * Default value is 0x00000300 16-bits, 0 shift, deliver both I & Q. - */ - bool set_format(unsigned int format); - - /*! - * \brief return current format - */ - unsigned int format () const; - - static unsigned int make_format(int width=16, int shift=0, - bool want_q=true, bool bypass_halfband=false); - static int format_width(unsigned int format); - static int format_shift(unsigned int format); - static bool format_want_q(unsigned int format); - static bool format_bypass_halfband(unsigned int format); - - - - - bool write_aux_dac (int which_dboard, int which_dac, int value); - int read_aux_adc (int which_dboard, int which_adc); - bool write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf); - std::string read_eeprom (int i2c_addr, int eeprom_offset, int len); - bool write_i2c (int i2c_addr, const std::string buf); - std::string read_i2c (int i2c_addr, int len); - bool _write_fpga_reg (int regno, int value); //< 7-bit regno, 32-bit value - bool _write_fpga_reg_masked (int regno, int value, int mask); //< 7-bit regno, 16-bit value, 16-bit mask - int _read_fpga_reg (int regno); - bool _write_9862 (int which_codec, int regno, unsigned char value); - int _read_9862 (int which_codec, int regno) const; - - bool _write_spi (int optional_header, int enables, int format, std::string buf); - - /* - * \brief Read data from SPI bus peripheral. - * - * \param optional_header 0,1 or 2 bytes to write before buf. - * \param enables bitmask of peripheral to read. See usrp_spi_defs.h - * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* - * \param len number of bytes to read. Must be in [0,64]. - * \returns the data read if sucessful, else a zero length string. - * - * Reads are limited to a maximum of 64 bytes. - * - * If \p format specifies that optional_header bytes are present, they - * are written to the peripheral first. Then \p len bytes are read from - * the peripheral and returned. - */ - std::string _read_spi (int optional_header, int enables, int format, int len); -}; - - -// ================================================================ -// concrete sinks -// ================================================================ - - -GR_SWIG_BLOCK_MAGIC(usrp1,sink_c) - -usrp1_sink_c_sptr -usrp1_make_sink_c (int which_board, - unsigned int interp_rate, - int nchan, - int mux, - int fusb_block_size, - int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename - ) throw (std::runtime_error); - - -class usrp1_sink_c : public usrp1_sink_base { - protected: - usrp1_sink_c (int which_board, unsigned int interp_rate, - int nchan, int mux); - - public: - ~usrp1_sink_c (); -}; - -// ---------------------------------------------------------------- - -GR_SWIG_BLOCK_MAGIC(usrp1,sink_s) - -usrp1_sink_s_sptr -usrp1_make_sink_s (int which_board, - unsigned int interp_rate, - int nchan, - int mux, - int fusb_block_size, - int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename - ) throw (std::runtime_error); - - -class usrp1_sink_s : public usrp1_sink_base { - protected: - usrp1_sink_s (int which_board, unsigned int interp_rate, - int nchan, int mux); - - public: - ~usrp1_sink_s (); -}; - -// ================================================================ -// concrete sources -// ================================================================ - -GR_SWIG_BLOCK_MAGIC(usrp1,source_c) - - -usrp1_source_c_sptr -usrp1_make_source_c (int which_board, - unsigned int decim_rate, - int nchan, - int mux, - int mode, - int fusb_block_size, - int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename - ) throw (std::runtime_error); - -class usrp1_source_c : public usrp1_source_base { - protected: - usrp1_source_c (int which_board, unsigned int decim_rate, - int nchan, int mux, int mode); - - public: - ~usrp1_source_c (); -}; - -// ---------------------------------------------------------------- - -GR_SWIG_BLOCK_MAGIC(usrp1,source_s) - -usrp1_source_s_sptr -usrp1_make_source_s (int which_board, - unsigned int decim_rate, - int nchan, - int mux, - int mode, - int fusb_block_size, - int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename - ) throw (std::runtime_error); - - -class usrp1_source_s : public usrp1_source_base { - protected: - usrp1_source_s (int which_board, unsigned int decim_rate, - int nchan, int mux, int mode); - - public: - ~usrp1_source_s (); -}; - diff --git a/gr-usrp/src/usrp1_sink_base.cc b/gr-usrp/src/usrp1_sink_base.cc deleted file mode 100644 index 331be5f8c..000000000 --- a/gr-usrp/src/usrp1_sink_base.cc +++ /dev/null @@ -1,359 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 version 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <usrp1_sink_base.h> -#include <gr_io_signature.h> -#include <usrp_standard.h> -#include <assert.h> - -static const int OUTPUT_MULTIPLE_SAMPLES = 128; // DON'T CHANGE THIS VALUE! - -usrp1_sink_base::usrp1_sink_base (const std::string &name, - gr_io_signature_sptr input_signature, - int which_board, - unsigned int interp_rate, - int nchan, - int mux, - int fusb_block_size, - int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename - ) throw (std::runtime_error) - : gr_sync_block (name, - input_signature, - gr_make_io_signature (0, 0, 0)), - d_nunderruns (0) -{ - d_usrp = usrp_standard_tx::make (which_board, - interp_rate, - nchan, mux, - fusb_block_size, - fusb_nblocks, - fpga_filename, - firmware_filename - ); - if (d_usrp == 0) - throw std::runtime_error ("can't open usrp1"); - - // All calls to d_usrp->write must be multiples of 512 bytes. - - set_output_multiple (OUTPUT_MULTIPLE_SAMPLES); -} - -usrp1_sink_base::~usrp1_sink_base () -{ - delete d_usrp; -} - -bool -usrp1_sink_base::start() -{ - return d_usrp->start(); -} - -bool -usrp1_sink_base::stop() -{ - return d_usrp->stop(); -} - -int -usrp1_sink_base::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - static const int BUFSIZE = 16 * (1L << 10); // 16kB - unsigned char outbuf[BUFSIZE]; - int obi = 0; - int input_index = 0; - int input_items_consumed; - int bytes_written; - bool underrun; - - - while (input_index < noutput_items){ - - copy_to_usrp_buffer (input_items, - input_index, - noutput_items - input_index, // input_items_available - input_items_consumed, // [out] - &outbuf[obi], // [out] usrp_buffer - BUFSIZE - obi, // usrp_buffer_length - bytes_written); // [out] - - assert (input_index + input_items_consumed <= noutput_items); - assert (obi + bytes_written <= BUFSIZE); - - input_index += input_items_consumed; - obi += bytes_written; - - if (obi >= BUFSIZE){ // flush - if (d_usrp->write (outbuf, obi, &underrun) != obi) - return -1; // indicate we're done - - if (underrun){ - d_nunderruns++; - // fprintf (stderr, "usrp1_sink: underrun\n"); - fputs ("uU", stderr); - } - obi = 0; - } - } - - if (obi != 0){ - assert (obi % 512 == 0); - if (d_usrp->write (outbuf, obi, &underrun) != obi) - return -1; // indicate we're done - - if (underrun){ - d_nunderruns++; - // fprintf (stderr, "usrp1_sink: underrun\n"); - fputs ("uU", stderr); - } - } - - return noutput_items; -} - -bool -usrp1_sink_base::set_interp_rate (unsigned int rate) -{ - return d_usrp->set_interp_rate (rate); -} - -bool -usrp1_sink_base::set_nchannels (int nchan) -{ - return d_usrp->set_nchannels (nchan); -} - -bool -usrp1_sink_base::set_mux (int mux) -{ - return d_usrp->set_mux (mux); -} - -bool -usrp1_sink_base::set_tx_freq (int channel, double freq) -{ - return d_usrp->set_tx_freq (channel, freq); -} - -long -usrp1_sink_base::fpga_master_clock_freq() const -{ - return d_usrp->fpga_master_clock_freq(); -} - -long -usrp1_sink_base::converter_rate () const -{ - return d_usrp->converter_rate (); -} - -unsigned int -usrp1_sink_base::interp_rate () const -{ - return d_usrp->interp_rate (); -} - -int -usrp1_sink_base::nchannels () const -{ - return d_usrp->nchannels (); -} - -int -usrp1_sink_base::mux () const -{ - return d_usrp->mux (); -} - - -double -usrp1_sink_base::tx_freq (int channel) const -{ - return d_usrp->tx_freq (channel); -} - -void -usrp1_sink_base::set_verbose (bool verbose) -{ - d_usrp->set_verbose (verbose); -} - -bool -usrp1_sink_base::write_aux_dac (int which_dboard, int which_dac, int value) -{ - return d_usrp->write_aux_dac (which_dboard, which_dac, value); -} - -int -usrp1_sink_base::read_aux_adc (int which_dboard, int which_adc) -{ - return d_usrp->read_aux_adc (which_dboard, which_adc); -} - -bool -usrp1_sink_base::write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf) -{ - return d_usrp->write_eeprom (i2c_addr, eeprom_offset, buf); -} - -std::string -usrp1_sink_base::read_eeprom (int i2c_addr, int eeprom_offset, int len) -{ - return d_usrp->read_eeprom (i2c_addr, eeprom_offset, len); -} - -bool -usrp1_sink_base::write_i2c (int i2c_addr, const std::string buf) -{ - return d_usrp->write_i2c (i2c_addr, buf); -} - -std::string -usrp1_sink_base::read_i2c (int i2c_addr, int len) -{ - return d_usrp->read_i2c (i2c_addr, len); -} - -bool -usrp1_sink_base::set_pga (int which, double gain) -{ - return d_usrp->set_pga (which, gain); -} - -double -usrp1_sink_base::pga (int which) const -{ - return d_usrp->pga (which); -} - -double -usrp1_sink_base::pga_min () const -{ - return d_usrp->pga_min (); -} - -double -usrp1_sink_base::pga_max () const -{ - return d_usrp->pga_max (); -} - -double -usrp1_sink_base::pga_db_per_step () const -{ - return d_usrp->pga_db_per_step (); -} - -int -usrp1_sink_base::daughterboard_id (int which) const -{ - return d_usrp->daughterboard_id (which); -} - -bool -usrp1_sink_base::set_adc_offset (int which, int offset) -{ - return d_usrp->set_adc_offset (which, offset); -} - -bool -usrp1_sink_base::set_dac_offset (int which, int offset, int offset_pin) -{ - return d_usrp->set_dac_offset (which, offset, offset_pin); -} - -bool -usrp1_sink_base::set_adc_buffer_bypass (int which, bool bypass) -{ - return d_usrp->set_adc_buffer_bypass (which, bypass); -} - -std::string -usrp1_sink_base::serial_number() -{ - return d_usrp->serial_number(); -} - -bool -usrp1_sink_base::_write_oe (int which_dboard, int value, int mask) -{ - return d_usrp->_write_oe (which_dboard, value, mask); -} - -bool -usrp1_sink_base::write_io (int which_dboard, int value, int mask) -{ - return d_usrp->write_io (which_dboard, value, mask); -} - -int -usrp1_sink_base::read_io (int which_dboard) -{ - return d_usrp->read_io (which_dboard); -} - -// internal routines... - -bool -usrp1_sink_base::_write_fpga_reg (int regno, int value) -{ - return d_usrp->_write_fpga_reg (regno, value); -} - -int -usrp1_sink_base::_read_fpga_reg (int regno) -{ - return d_usrp->_read_fpga_reg (regno); -} - -bool -usrp1_sink_base::_write_9862 (int which_codec, int regno, unsigned char value) -{ - return d_usrp->_write_9862 (which_codec, regno, value); -} - -int -usrp1_sink_base::_read_9862 (int which_codec, int regno) const -{ - return d_usrp->_read_9862 (which_codec, regno); -} - -bool -usrp1_sink_base::_write_spi (int optional_header, int enables, - int format, std::string buf) -{ - return d_usrp->_write_spi (optional_header, enables, format, buf); -} - -std::string -usrp1_sink_base::_read_spi (int optional_header, int enables, int format, int len) -{ - return d_usrp->_read_spi (optional_header, enables, format, len); -} diff --git a/gr-usrp/src/usrp1_sink_base.h b/gr-usrp/src/usrp1_sink_base.h deleted file mode 100644 index c62849474..000000000 --- a/gr-usrp/src/usrp1_sink_base.h +++ /dev/null @@ -1,359 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2006 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 version 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. - */ - -#ifndef INCLUDED_USRP1_SINK_BASE_H -#define INCLUDED_USRP1_SINK_BASE_H - -#include <gr_sync_block.h> -#include <stdexcept> - -class usrp_standard_tx; - - -/*! - * \brief abstract interface to Universal Software Radio Peripheral Tx path (Rev 1) - */ -class usrp1_sink_base : public gr_sync_block { - private: - usrp_standard_tx *d_usrp; - int d_nunderruns; - - protected: - usrp1_sink_base (const std::string &name, - gr_io_signature_sptr input_signature, - int which_board, - unsigned int interp_rate, - int nchan, - int mux, - int fusb_block_size, - int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename - ) throw (std::runtime_error); - - /*! - * \brief convert between input item format and usrp native format - * - * \param input_items[in] stream(s) of input items - * \param input_index[in] starting index in input_items - * \param input_items_available[in] number of items available starting at item[index] - * \param input_items_consumed[out] number of input items consumed by copy - * \param usrp_buffer[out] destination buffer - * \param usrp_buffer_length[in] \p usrp_buffer length in bytes - * \param bytes_written[out] number of bytes written into \p usrp_buffer - */ - virtual void copy_to_usrp_buffer (gr_vector_const_void_star &input_items, - int input_index, - int input_items_available, - int &input_items_consumed, - void *usrp_buffer, - int usrp_buffer_length, - int &bytes_written) = 0; - - public: - //! magic value used on alternate register read interfaces - static const int READ_FAILED = -99999; - - - ~usrp1_sink_base (); - - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - bool start(); - bool stop(); - - /*! - * \brief Set interpolator rate. \p rate must be in [4, 1024] and a multiple of 4. - * - * The final complex sample rate across the USB is - * dac_freq () / interp_rate () * nchannels () - */ - bool set_interp_rate (unsigned int rate); - bool set_nchannels (int nchan); - bool set_mux (int mux); - - /*! - * \brief set the frequency of the digital up converter. - * - * \p channel must be 0. \p freq is the center frequency in Hz. - * It must be in the range [-44M, 44M]. The frequency specified is - * quantized. Use tx_freq to retrieve the actual value used. - */ - bool set_tx_freq (int channel, double freq); - - void set_verbose (bool verbose); - - /*! - * \brief Set Programmable Gain Amplifier (PGA) - * - * \param which which D/A [0,3] - * \param gain_in_db gain value (linear in dB) - * - * gain is rounded to closest setting supported by hardware. - * Note that DAC 0 and DAC 1 share a gain setting as do DAC 2 and DAC 3. - * Setting DAC 0 affects DAC 1 and vice versa. Same with DAC 2 and DAC 3. - * - * \returns true iff sucessful. - * - * \sa pga_min(), pga_max(), pga_db_per_step() - */ - bool set_pga (int which, double gain_in_db); - - /*! - * \brief Return programmable gain amplifier gain in dB. - * - * \param which which D/A [0,3] - */ - double pga (int which) const; - - /*! - * \brief Return minimum legal PGA gain in dB. - */ - double pga_min () const; - - /*! - * \brief Return maximum legal PGA gain in dB. - */ - double pga_max () const; - - /*! - * \brief Return hardware step size of PGA (linear in dB). - */ - double pga_db_per_step () const; - - - // ACCESSORS - - long fpga_master_clock_freq() const; - long converter_rate() const; - long dac_rate() const { return converter_rate(); } // alias - long dac_freq() const { return converter_rate(); } // deprecated alias - - unsigned int interp_rate () const; - int nchannels () const; - int mux () const; - double tx_freq (int channel) const; - int nunderruns () const { return d_nunderruns; } - - /*! - * \brief Return daughterboard ID for given Rx daughterboard slot [0,1]. - * - * \return daughterboard id >= 0 if successful - * \return -1 if no daugherboard - * \return -2 if invalid EEPROM on daughterboard - */ - int daughterboard_id (int which_dboard) const; - - /*! - * \brief Write auxiliary digital to analog converter. - * - * \param which_dboard [0,1] which d'board - * N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's. - * SLOT_TX_B and SLOT_RX_B share the same AUX DAC's. - * \param which_dac [2,3] TX slots must use only 2 and 3. - * \param value [0,4095] - * \returns true iff successful - */ - bool write_aux_dac (int which_board, int which_dac, int value); - - /*! - * \brief Read auxiliary analog to digital converter. - * - * \param which_dboard [0,1] which d'board - * \param which_adc [0,1] - * \returns value in the range [0,4095] if successful, else READ_FAILED. - */ - int read_aux_adc (int which_dboard, int which_adc); - - /*! - * \brief Write EEPROM on motherboard or any daughterboard. - * \param i2c_addr I2C bus address of EEPROM - * \param eeprom_offset byte offset in EEPROM to begin writing - * \param buf the data to write - * \returns true iff sucessful - */ - bool write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf); - - /*! - * \brief Write EEPROM on motherboard or any daughterboard. - * \param i2c_addr I2C bus address of EEPROM - * \param eeprom_offset byte offset in EEPROM to begin reading - * \param len number of bytes to read - * \returns the data read if successful, else a zero length string. - */ - std::string read_eeprom (int i2c_addr, int eeprom_offset, int len); - - /*! - * \brief Write to I2C peripheral - * \param i2c_addr I2C bus address (7-bits) - * \param buf the data to write - * \returns true iff successful - * Writes are limited to a maximum of of 64 bytes. - */ - bool write_i2c (int i2c_addr, const std::string buf); - - /*! - * \brief Read from I2C peripheral - * \param i2c_addr I2C bus address (7-bits) - * \param len number of bytes to read - * \returns the data read if successful, else a zero length string. - * Reads are limited to a maximum of of 64 bytes. - */ - std::string read_i2c (int i2c_addr, int len); - - /*! - * \brief Set ADC offset correction - * \param which which ADC[0,3]: 0 = RX_A I, 1 = RX_A Q... - * \param offset 16-bit value to subtract from raw ADC input. - */ - bool set_adc_offset (int which, int offset); - - /*! - * \brief Set DAC offset correction - * \param which which DAC[0,3]: 0 = TX_A I, 1 = TX_A Q... - * \param offset 10-bit offset value (ambiguous format: See AD9862 datasheet). - * \param offset_pin 1-bit value. If 0 offset applied to -ve differential pin; - * If 1 offset applied to +ve differential pin. - */ - bool set_dac_offset (int which, int offset, int offset_pin); - - /*! - * \brief Control ADC input buffer - * \param which which ADC[0,3] - * \param bypass if non-zero, bypass input buffer and connect input - * directly to switched cap SHA input of RxPGA. - */ - bool set_adc_buffer_bypass (int which, bool bypass); - - /*! - * \brief return the usrp's serial number. - * - * \returns non-zero length string iff successful. - */ - std::string serial_number(); - - /*! - * \brief Write direction register (output enables) for pins that go to daughterboard. - * - * \param which_dboard [0,1] which d'board - * \param value value to write into register - * \param mask which bits of value to write into reg - * - * Each d'board has 16-bits of general purpose i/o. - * Setting the bit makes it an output from the FPGA to the d'board. - * - * This register is initialized based on a value stored in the - * d'board EEPROM. In general, you shouldn't be using this routine - * without a very good reason. Using this method incorrectly will - * kill your USRP motherboard and/or daughterboard. - */ - bool _write_oe (int which_dboard, int value, int mask); - - /*! - * \brief Write daughterboard i/o pin value - * - * \param which_dboard [0,1] which d'board - * \param value value to write into register - * \param mask which bits of value to write into reg - */ - bool write_io (int which_dboard, int value, int mask); - - /*! - * \brief Read daughterboard i/o pin value - * - * \param which_dboard [0,1] which d'board - * \returns register value if successful, else READ_FAILED - */ - int read_io (int which_dboard); - - // - // internal routines... - // You probably shouldn't be using these... - // - /*! - * \brief Write FPGA register. - * \param regno 7-bit register number - * \param value 32-bit value - * \returns true iff successful - */ - bool _write_fpga_reg (int regno, int value); //< 7-bit regno, 32-bit value - - /*! - * \brief Read FPGA register. - * \param regno 7-bit register number - * \returns register value if successful, else READ_FAILED - */ - int _read_fpga_reg (int regno); - - /*! - * \brief Write AD9862 register. - * \param which_codec 0 or 1 - * \param regno 6-bit register number - * \param value 8-bit value - * \returns true iff successful - */ - bool _write_9862 (int which_codec, int regno, unsigned char value); - - /*! - * \brief Read AD9862 register. - * \param which_codec 0 or 1 - * \param regno 6-bit register number - * \returns register value if successful, else READ_FAILED - */ - int _read_9862 (int which_codec, int regno) const; - - /*! - * \brief Write data to SPI bus peripheral. - * - * \param optional_header 0,1 or 2 bytes to write before buf. - * \param enables bitmask of peripherals to write. See usrp_spi_defs.h - * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* - * \param buf the data to write - * \returns true iff successful - * Writes are limited to a maximum of 64 bytes. - * - * If \p format specifies that optional_header bytes are present, they are - * written to the peripheral immediately prior to writing \p buf. - */ - bool _write_spi (int optional_header, int enables, int format, std::string buf); - - /* - * \brief Read data from SPI bus peripheral. - * - * \param optional_header 0,1 or 2 bytes to write before buf. - * \param enables bitmask of peripheral to read. See usrp_spi_defs.h - * \param format transaction format. See usrp_spi_defs.h SPI_FMT_* - * \param len number of bytes to read. Must be in [0,64]. - * \returns the data read if sucessful, else a zero length string. - * - * Reads are limited to a maximum of 64 bytes. - * - * If \p format specifies that optional_header bytes are present, they - * are written to the peripheral first. Then \p len bytes are read from - * the peripheral and returned. - */ - std::string _read_spi (int optional_header, int enables, int format, int len); -}; - -#endif /* INCLUDED_USRP1_SINK_BASE_H */ diff --git a/gr-usrp/src/usrp1_source_base.cc b/gr-usrp/src/usrp1_source_base.cc deleted file mode 100644 index 1aefa8a23..000000000 --- a/gr-usrp/src/usrp1_source_base.cc +++ /dev/null @@ -1,425 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 version 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <usrp1_source_base.h> -#include <gr_io_signature.h> -#include <usrp_standard.h> -#include <assert.h> - -static const int OUTPUT_MULTIPLE_BYTES = 4 * 1024; - -usrp1_source_base::usrp1_source_base (const std::string &name, - gr_io_signature_sptr output_signature, - int which_board, - unsigned int decim_rate, - int nchan, - int mux, - int mode, - int fusb_block_size, - int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename - ) throw (std::runtime_error) - : gr_sync_block (name, - gr_make_io_signature (0, 0, 0), - output_signature), - d_noverruns (0) -{ - d_usrp = usrp_standard_rx::make (which_board, decim_rate, - nchan, mux, mode, - fusb_block_size, - fusb_nblocks, - fpga_filename, - firmware_filename); - if (d_usrp == 0) - throw std::runtime_error ("can't open usrp1"); - - // All calls to d_usrp->read must be multiples of 512 bytes. - // We jack this up to 4k to reduce overhead. - - set_output_multiple (OUTPUT_MULTIPLE_BYTES / output_signature->sizeof_stream_item (0)); -} - -usrp1_source_base::~usrp1_source_base () -{ - delete d_usrp; -} - -unsigned int -usrp1_source_base::sizeof_basic_sample() const -{ - return usrp_standard_rx::format_width(d_usrp->format()) / 8; -} - -bool -usrp1_source_base::start() -{ - return d_usrp->start(); -} - -bool -usrp1_source_base::stop() -{ - return d_usrp->stop(); -} - -int -usrp1_source_base::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - static const int BUFSIZE = 4 * OUTPUT_MULTIPLE_BYTES; - unsigned char buf[BUFSIZE]; - int output_index = 0; - int output_items_produced; - int bytes_read; - bool overrun; - - while (output_index < noutput_items){ - int nbytes = ninput_bytes_reqd_for_noutput_items (noutput_items - output_index); - nbytes = std::min (nbytes, BUFSIZE); - - int result_nbytes = d_usrp->read (buf, nbytes, &overrun); - if (overrun){ - // fprintf (stderr, "usrp1_source: overrun\n"); - fputs ("uO", stderr); - d_noverruns++; - } - - if (result_nbytes < 0) // We've got a problem. Usually board unplugged or powered down. - return -1; // Indicate we're done. - - if (result_nbytes != nbytes){ // not really an error, but unexpected - fprintf (stderr, "usrp1_source: short read. Expected %d, got %d\n", - nbytes, result_nbytes); - } - - copy_from_usrp_buffer (output_items, - output_index, - noutput_items - output_index, // output_items_available - output_items_produced, // [out] - buf, // usrp_buffer - result_nbytes, // usrp_buffer_length - bytes_read); // [out] - - assert (output_index + output_items_produced <= noutput_items); - assert (bytes_read == result_nbytes); - - output_index += output_items_produced; - } - - return noutput_items; -} - - -bool -usrp1_source_base::set_decim_rate (unsigned int rate) -{ - return d_usrp->set_decim_rate (rate); -} - -bool -usrp1_source_base::set_nchannels (int nchan) -{ - return d_usrp->set_nchannels (nchan); -} - -bool -usrp1_source_base::set_mux (int mux) -{ - return d_usrp->set_mux (mux); -} - -bool -usrp1_source_base::set_rx_freq (int channel, double freq) -{ - return d_usrp->set_rx_freq (channel, freq); -} - -long -usrp1_source_base::fpga_master_clock_freq() const -{ - return d_usrp->fpga_master_clock_freq(); -} - -long -usrp1_source_base::converter_rate() const -{ - return d_usrp->converter_rate(); -} - -unsigned int -usrp1_source_base::decim_rate () const -{ - return d_usrp->decim_rate (); -} - -int -usrp1_source_base::nchannels () const -{ - return d_usrp->nchannels (); -} - -int -usrp1_source_base::mux () const -{ - return d_usrp->mux (); -} - -double -usrp1_source_base::rx_freq (int channel) const -{ - return d_usrp->rx_freq (channel); -} - -bool -usrp1_source_base::set_fpga_mode (int mode) -{ - return d_usrp->set_fpga_mode (mode); -} - -bool -usrp1_source_base::set_ddc_phase (int channel, int phase) -{ - return d_usrp->set_ddc_phase(channel, phase); -} - -bool -usrp1_source_base::set_dc_offset_cl_enable(int bits, int mask) -{ - return d_usrp->set_dc_offset_cl_enable(bits, mask); -} - -void -usrp1_source_base::set_verbose (bool verbose) -{ - d_usrp->set_verbose (verbose); -} - -bool -usrp1_source_base::write_aux_dac (int which_dboard, int which_dac, int value) -{ - return d_usrp->write_aux_dac (which_dboard, which_dac, value); -} - -int -usrp1_source_base::read_aux_adc (int which_dboard, int which_adc) -{ - return d_usrp->read_aux_adc (which_dboard, which_adc); -} - -bool -usrp1_source_base::write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf) -{ - return d_usrp->write_eeprom (i2c_addr, eeprom_offset, buf); -} - -std::string -usrp1_source_base::read_eeprom (int i2c_addr, int eeprom_offset, int len) -{ - return d_usrp->read_eeprom (i2c_addr, eeprom_offset, len); -} - -bool -usrp1_source_base::write_i2c (int i2c_addr, const std::string buf) -{ - return d_usrp->write_i2c (i2c_addr, buf); -} - -std::string -usrp1_source_base::read_i2c (int i2c_addr, int len) -{ - return d_usrp->read_i2c (i2c_addr, len); -} - -bool -usrp1_source_base::set_pga (int which, double gain) -{ - return d_usrp->set_pga (which, gain); -} - -double -usrp1_source_base::pga (int which) const -{ - return d_usrp->pga (which); -} - -double -usrp1_source_base::pga_min () const -{ - return d_usrp->pga_min (); -} - -double -usrp1_source_base::pga_max () const -{ - return d_usrp->pga_max (); -} - -double -usrp1_source_base::pga_db_per_step () const -{ - return d_usrp->pga_db_per_step (); -} - -int -usrp1_source_base::daughterboard_id (int which) const -{ - return d_usrp->daughterboard_id (which); -} - - -bool -usrp1_source_base::set_adc_offset (int which, int offset) -{ - return d_usrp->set_adc_offset (which, offset); -} - -bool -usrp1_source_base::set_dac_offset (int which, int offset, int offset_pin) -{ - return d_usrp->set_dac_offset (which, offset, offset_pin); -} - -bool -usrp1_source_base::set_adc_buffer_bypass (int which, bool bypass) -{ - return d_usrp->set_adc_buffer_bypass (which, bypass); -} - -std::string -usrp1_source_base::serial_number() -{ - return d_usrp->serial_number(); -} - -bool -usrp1_source_base::_write_oe (int which_dboard, int value, int mask) -{ - return d_usrp->_write_oe (which_dboard, value, mask); -} - -bool -usrp1_source_base::write_io (int which_dboard, int value, int mask) -{ - return d_usrp->write_io (which_dboard, value, mask); -} - -int -usrp1_source_base::read_io (int which_dboard) -{ - return d_usrp->read_io (which_dboard); -} - - - - -// internal routines... - -bool -usrp1_source_base::_write_fpga_reg (int regno, int value) -{ - return d_usrp->_write_fpga_reg (regno, value); -} - -bool -usrp1_source_base::_write_fpga_reg_masked (int regno, int value, int mask) -{ - return d_usrp->_write_fpga_reg_masked (regno, value, mask); -} - -int -usrp1_source_base::_read_fpga_reg (int regno) -{ - return d_usrp->_read_fpga_reg (regno); -} - -bool -usrp1_source_base::_write_9862 (int which_codec, int regno, unsigned char value) -{ - return d_usrp->_write_9862 (which_codec, regno, value); -} - -int -usrp1_source_base::_read_9862 (int which_codec, int regno) const -{ - return d_usrp->_read_9862 (which_codec, regno); -} - -bool -usrp1_source_base::_write_spi (int optional_header, int enables, - int format, std::string buf) -{ - return d_usrp->_write_spi (optional_header, enables, format, buf); -} - -std::string -usrp1_source_base::_read_spi (int optional_header, int enables, int format, int len) -{ - return d_usrp->_read_spi (optional_header, enables, format, len); -} - -bool -usrp1_source_base::set_format(unsigned int format) -{ - return d_usrp->set_format(format); -} - -unsigned int -usrp1_source_base::format() const -{ - return d_usrp->format(); -} - -unsigned int -usrp1_source_base::make_format(int width, int shift, bool want_q, bool bypass_halfband) -{ - return usrp_standard_rx::make_format(width, shift, want_q, bypass_halfband); -} - -int -usrp1_source_base::format_width(unsigned int format) -{ - return usrp_standard_rx::format_width(format); -} - -int -usrp1_source_base::format_shift(unsigned int format) -{ - return usrp_standard_rx::format_shift(format); -} - -bool -usrp1_source_base::format_want_q(unsigned int format) -{ - return usrp_standard_rx::format_want_q(format); -} - -bool -usrp1_source_base::format_bypass_halfband(unsigned int format) -{ - return usrp_standard_rx::format_bypass_halfband(format); -} diff --git a/gr-usrp/src/usrp_base.cc b/gr-usrp/src/usrp_base.cc new file mode 100644 index 000000000..1709c7a44 --- /dev/null +++ b/gr-usrp/src/usrp_base.cc @@ -0,0 +1,316 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008 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 version 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <usrp_base.h> +#include <usrp_basic.h> + +class truth_table_element_t +{ +public: + truth_table_element_t(int side, unsigned int uses, bool swap_iq, unsigned int mux_val); + bool operator==(const truth_table_element_t &in); + bool operator!=(const truth_table_element_t &in); + + unsigned int mux_val() { return d_mux_val; } + +private: + int d_side; + unsigned int d_uses; + bool d_swap_iq; + unsigned int d_mux_val; +}; + + +usrp_base::~usrp_base() +{ +} + +void +usrp_base::set_usrp_basic(boost::shared_ptr<usrp_basic> u) +{ + d_usrp_basic = u; +} + +std::vector<std::vector<db_base_sptr> > +usrp_base::db() +{ + return d_usrp_basic->db(); +} + +std::vector<db_base_sptr> +usrp_base::db(int which_side) +{ + return d_usrp_basic->db(which_side); +} + +db_base_sptr +usrp_base::db(int which_side, int which_dev) +{ + return d_usrp_basic->selected_subdev(usrp_subdev_spec(which_side, which_dev)); +} + +db_base_sptr +usrp_base::selected_subdev(usrp_subdev_spec ss) +{ + return d_usrp_basic->selected_subdev(ss); +} + +long +usrp_base::fpga_master_clock_freq() const +{ + return d_usrp_basic->fpga_master_clock_freq(); +} + +void +usrp_base::set_verbose (bool verbose) +{ + d_usrp_basic->set_verbose (verbose); +} + +bool +usrp_base::write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf) +{ + return d_usrp_basic->write_eeprom (i2c_addr, eeprom_offset, buf); +} + +std::string +usrp_base::read_eeprom (int i2c_addr, int eeprom_offset, int len) +{ + return d_usrp_basic->read_eeprom (i2c_addr, eeprom_offset, len); +} + +bool +usrp_base::write_i2c (int i2c_addr, const std::string buf) +{ + return d_usrp_basic->write_i2c (i2c_addr, buf); +} + +std::string +usrp_base::read_i2c (int i2c_addr, int len) +{ + return d_usrp_basic->read_i2c (i2c_addr, len); +} + +bool +usrp_base::set_adc_offset (int which, int offset) +{ + return d_usrp_basic->set_adc_offset (which, offset); +} + +bool +usrp_base::set_dac_offset (int which, int offset, int offset_pin) +{ + return d_usrp_basic->set_dac_offset (which, offset, offset_pin); +} + +bool +usrp_base::set_adc_buffer_bypass (int which, bool bypass) +{ + return d_usrp_basic->set_adc_buffer_bypass (which, bypass); +} + +bool +usrp_base::set_dc_offset_cl_enable(int bits, int mask) +{ + return d_usrp_basic->set_dc_offset_cl_enable(bits, mask); +} + +std::string +usrp_base::serial_number() +{ + return d_usrp_basic->serial_number(); +} + +int +usrp_base::daughterboard_id (int which) const +{ + return d_usrp_basic->daughterboard_id (which); +} + +bool +usrp_base::write_atr_tx_delay(int value) +{ + return d_usrp_basic->write_atr_tx_delay(value); +} + +bool +usrp_base::write_atr_rx_delay(int value) +{ + return d_usrp_basic->write_atr_rx_delay(value); +} + +bool +usrp_base::set_pga (int which, double gain) +{ + return d_usrp_basic->set_pga (which, gain); +} + +double +usrp_base::pga (int which) const +{ + return d_usrp_basic->pga (which); +} + +double +usrp_base::pga_min () const +{ + return d_usrp_basic->pga_min (); +} + +double +usrp_base::pga_max () const +{ + return d_usrp_basic->pga_max (); +} + +double +usrp_base::pga_db_per_step () const +{ + return d_usrp_basic->pga_db_per_step (); +} + +bool +usrp_base::_write_oe (int which_dboard, int value, int mask) +{ + return d_usrp_basic->_write_oe (which_dboard, value, mask); +} + +bool +usrp_base::write_io (int which_dboard, int value, int mask) +{ + return d_usrp_basic->write_io (which_dboard, value, mask); +} + +int +usrp_base::read_io (int which_dboard) +{ + return d_usrp_basic->read_io (which_dboard); +} + +bool +usrp_base::write_atr_mask(int which_side, int value) +{ + return d_usrp_basic->write_atr_mask(which_side, value); +} + +bool +usrp_base::write_atr_txval(int which_side, int value) +{ + return d_usrp_basic->write_atr_txval(which_side, value); +} + +bool +usrp_base::write_atr_rxval(int which_side, int value) +{ + return d_usrp_basic->write_atr_rxval(which_side, value); +} + +bool +usrp_base::write_aux_dac (int which_dboard, int which_dac, int value) +{ + return d_usrp_basic->write_aux_dac (which_dboard, which_dac, value); +} + +int +usrp_base::read_aux_adc (int which_dboard, int which_adc) +{ + return d_usrp_basic->read_aux_adc (which_dboard, which_adc); +} + +long +usrp_base::converter_rate() const +{ + return d_usrp_basic->converter_rate(); +} + +bool +usrp_base::_set_led(int which_led, bool on) +{ + return d_usrp_basic->_set_led(which_led, on); +} + +bool +usrp_base::_write_fpga_reg (int regno, int value) +{ + return d_usrp_basic->_write_fpga_reg (regno, value); +} + +bool +usrp_base::_write_fpga_reg_masked (int regno, int value, int mask) +{ + return d_usrp_basic->_write_fpga_reg_masked (regno, value, mask); +} + +int +usrp_base::_read_fpga_reg (int regno) +{ + return d_usrp_basic->_read_fpga_reg (regno); +} + +bool +usrp_base::_write_9862 (int which_codec, int regno, unsigned char value) +{ + return d_usrp_basic->_write_9862 (which_codec, regno, value); +} + +int +usrp_base::_read_9862 (int which_codec, int regno) const +{ + return d_usrp_basic->_read_9862 (which_codec, regno); +} + +bool +usrp_base::_write_spi (int optional_header, int enables, + int format, std::string buf) +{ + return d_usrp_basic->_write_spi (optional_header, enables, format, buf); +} + +std::string +usrp_base::_read_spi (int optional_header, int enables, int format, int len) +{ + return d_usrp_basic->_read_spi (optional_header, enables, format, len); +} + +usrp_subdev_spec +usrp_base::pick_subdev(std::vector<int> candidates) +{ + int dbid0 = db(0, 0)->dbid(); + int dbid1 = db(1, 0)->dbid(); + + for (int i = 0; i < candidates.size(); i++) { + int dbid = candidates[i]; + if (dbid0 == dbid) + return usrp_subdev_spec(0, 0); + if (dbid1 == dbid) + return usrp_subdev_spec(1, 0); + } + + if (dbid0 >= 0) + return usrp_subdev_spec(0, 0); + if (dbid1 >= 0) + return usrp_subdev_spec(1, 0); + + throw std::runtime_error("No suitable daughterboard found!"); +} diff --git a/gr-usrp/src/usrp1_source_base.h b/gr-usrp/src/usrp_base.h index 5d29ba604..83aa699ab 100644 --- a/gr-usrp/src/usrp1_source_base.h +++ b/gr-usrp/src/usrp_base.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2008 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -14,199 +14,96 @@ * 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. + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#ifndef INCLUDED_USRP1_SOURCE_BASE_H -#define INCLUDED_USRP1_SOURCE_BASE_H +#ifndef INCLUDED_USRP_BASE_H +#define INCLUDED_USRP_BASE_H #include <gr_sync_block.h> #include <stdexcept> +#include <boost/shared_ptr.hpp> +#include <db_base.h> +#include <usrp_subdev_spec.h> -class usrp_standard_rx; +class usrp_basic; /*! - * \brief abstract interface to Universal Software Radio Peripheral Rx path (Rev 1) + * \brief base class for GNU Radio interface to the USRP */ -class usrp1_source_base : public gr_sync_block { - private: - usrp_standard_rx *d_usrp; - int d_noverruns; - - protected: - usrp1_source_base (const std::string &name, - gr_io_signature_sptr output_signature, - int which_board, - unsigned int decim_rate, - int nchan, - int mux, - int mode, - int fusb_block_size, - int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename - ) throw (std::runtime_error); - - /*! - * \brief return number of usrp input bytes required to produce noutput items. - */ - virtual int ninput_bytes_reqd_for_noutput_items (int noutput_items) = 0; - - /*! - * \brief number of bytes in a low-level sample - */ - unsigned int sizeof_basic_sample() const; - - /*! - * \brief convert between native usrp format and output item format - * - * \param output_items[out] stream(s) of output items - * \param output_index[in] starting index in output_items - * \param output_items_available[in] number of empty items available at item[index] - * \param output_items_produced[out] number of items produced by copy - * \param usrp_buffer[in] source buffer - * \param usrp_buffer_length[in] number of bytes available in \p usrp_buffer - * \param bytes_read[out] number of bytes read from \p usrp_buffer - * - * The copy must consume all bytes available. That is, \p bytes_read must equal - * \p usrp_buffer_length. - */ - virtual void copy_from_usrp_buffer (gr_vector_void_star &output_items, - int output_index, - int output_items_available, - int &output_items_produced, - const void *usrp_buffer, - int usrp_buffer_length, - int &bytes_read) = 0; - - public: - //! magic value used on alternate register read interfaces - static const int READ_FAILED = -99999; +class usrp_base : public gr_sync_block { +private: + boost::shared_ptr<usrp_basic> d_usrp_basic; - ~usrp1_source_base (); +protected: + usrp_base(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature) + : gr_sync_block(name, input_signature, output_signature) {} + - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + void set_usrp_basic(boost::shared_ptr<usrp_basic> u); - bool start(); - bool stop(); +public: + virtual ~usrp_base(); - /*! - * \brief Set decimator rate. \p rate must be EVEN and in [8, 256]. + /* ! + * Return a vector of vectors of daughterboard instances associated with + * the USRP source or sink. The first dimension of the returned vector + * corresponds to the side of the USRP, the second dimension, the subdevice + * on the particular daughterboard. * - * The final complex sample rate across the USB is - * adc_freq () / decim_rate () + * N.B. To ensure proper lifetime management, the caller should + * continue to hold these as weak pointers, not shared pointers. + * As long as the caller does not attempt to directly use the weak + * pointers after this usrp object has been destroyed, everything + * will work out fine. */ - bool set_decim_rate (unsigned int rate); - bool set_nchannels (int nchan); - bool set_mux (int mux); + std::vector<std::vector<db_base_sptr> > db(); /*! - * \brief set the center frequency of the digital down converter. + * Return a vector of size 1 or 2 that contains shared pointers + * to the daughterboard instance(s) associated with the specified side. * - * \p channel must be 0. \p freq is the center frequency in Hz. - * It must be in the range [-FIXME, FIXME]. The frequency specified is - * quantized. Use rx_freq to retrieve the actual value used. - */ - bool set_rx_freq (int channel, double freq); - - /*! - * \brief set fpga special modes - */ - bool set_fpga_mode (int mode); - - void set_verbose (bool verbose); - - /*! - * \brief Set the digital down converter phase register. + * \param which_side [0,1] which daughterboard * - * \param channel which ddc channel [0, 3] - * \param phase 32-bit integer phase value. + * N.B. To ensure proper lifetime management, the caller should + * continue to hold these as weak pointers, not shared pointers. + * As long as the caller does not attempt to directly use the weak + * pointers after this usrp object has been destroyed, everything + * will work out fine. */ - bool set_ddc_phase(int channel, int phase); + std::vector<db_base_sptr> db(int which_side); /*! - * \brief Set Programmable Gain Amplifier (PGA) - * - * \param which which A/D [0,3] - * \param gain_in_db gain value (linear in dB) - * - * gain is rounded to closest setting supported by hardware. - * - * \returns true iff sucessful. - * - * \sa pga_min(), pga_max(), pga_db_per_step() + * Return the daughterboard instance corresponding to the selected + * side of the USRP and selected daughterboard subdevice. + * N.B. To ensure proper lifetime management, the caller should + * continue to hold these as weak pointers, not shared pointers. + * As long as the caller does not attempt to directly use the weak + * pointers after this usrp object has been destroyed, everything + * will work out fine. */ - bool set_pga (int which, double gain_in_db); + db_base_sptr db(int which_side, int which_dev); /*! - * \brief Return programmable gain amplifier gain setting in dB. + * \brief given a usrp_subdev_spec, return the corresponding daughterboard object. + * \throws std::invalid_argument if ss is invalid. * - * \param which which A/D [0,3] + * \param ss specifies the side and subdevice */ - double pga (int which) const; + db_base_sptr selected_subdev(usrp_subdev_spec ss); /*! - * \brief Return minimum legal PGA setting in dB. + * \brief return frequency of master oscillator on USRP */ - double pga_min () const; + long fpga_master_clock_freq() const; - /*! - * \brief Return maximum legal PGA setting in dB. - */ - double pga_max () const; - - /*! - * \brief Return hardware step size of PGA (linear in dB). - */ - double pga_db_per_step () const; - - // ACCESSORS - - long fpga_master_clock_freq() const; - long converter_rate() const; - long adc_rate() const { return converter_rate(); } // alias - long adc_freq() const { return converter_rate(); } // deprecated alias + void set_verbose (bool on); - unsigned int decim_rate () const; - int nchannels () const; - int mux () const; - double rx_freq (int channel) const; - int noverruns () const { return d_noverruns; } - - /*! - * \brief Return daughterboard ID for given Rx daughterboard slot [0,1]. - * - * \return daughterboard id >= 0 if successful - * \return -1 if no daugherboard - * \return -2 if invalid EEPROM on daughterboard - */ - int daughterboard_id (int which_dboard) const; - - /*! - * \brief Write auxiliary digital to analog converter. - * - * \param which_dboard [0,1] which d'board - * N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's. - * SLOT_TX_B and SLOT_RX_B share the same AUX DAC's. - * \param which_dac [2,3] TX slots must use only 2 and 3. - * \param value [0,4095] - * \returns true iff successful - */ - bool write_aux_dac (int which_board, int which_dac, int value); - - /*! - * \brief Read auxiliary analog to digital converter. - * - * \param which_dboard [0,1] which d'board - * \param which_adc [0,1] - * \returns value in the range [0,4095] if successful, else READ_FAILED. - */ - int read_aux_adc (int which_dboard, int which_adc); + //! magic value used on alternate register read interfaces + static const int READ_FAILED = -99999; /*! * \brief Write EEPROM on motherboard or any daughterboard. @@ -218,7 +115,7 @@ class usrp1_source_base : public gr_sync_block { bool write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf); /*! - * \brief Write EEPROM on motherboard or any daughterboard. + * \brief Read EEPROM on motherboard or any daughterboard. * \param i2c_addr I2C bus address of EEPROM * \param eeprom_offset byte offset in EEPROM to begin reading * \param len number of bytes to read @@ -240,7 +137,7 @@ class usrp1_source_base : public gr_sync_block { * \param i2c_addr I2C bus address (7-bits) * \param len number of bytes to read * \returns the data read if successful, else a zero length string. - * Reads are limited to a maximum of of 64 bytes. + * Reads are limited to a maximum of 64 bytes. */ std::string read_i2c (int i2c_addr, int len); @@ -249,7 +146,7 @@ class usrp1_source_base : public gr_sync_block { * \param which which ADC[0,3]: 0 = RX_A I, 1 = RX_A Q... * \param offset 16-bit value to subtract from raw ADC input. */ - bool set_adc_offset (int which, int offset); + bool set_adc_offset (int which_adc, int offset); /*! * \brief Set DAC offset correction @@ -258,15 +155,37 @@ class usrp1_source_base : public gr_sync_block { * \param offset_pin 1-bit value. If 0 offset applied to -ve differential pin; * If 1 offset applied to +ve differential pin. */ - bool set_dac_offset (int which, int offset, int offset_pin); + bool set_dac_offset (int which_dac, int offset, int offset_pin); /*! * \brief Control ADC input buffer - * \param which which ADC[0,3] + * \param which_adc which ADC[0,3] * \param bypass if non-zero, bypass input buffer and connect input * directly to switched cap SHA input of RxPGA. */ - bool set_adc_buffer_bypass (int which, bool bypass); + bool set_adc_buffer_bypass (int which_adc, bool bypass); + + /*! + * \brief Enable/disable automatic DC offset removal control loop in FPGA + * + * \param bits which control loops to enable + * \param mask which \p bits to pay attention to + * + * If the corresponding bit is set, enable the automatic DC + * offset correction control loop. + * + * <pre> + * The 4 low bits are significant: + * + * ADC0 = (1 << 0) + * ADC1 = (1 << 1) + * ADC2 = (1 << 2) + * ADC3 = (1 << 3) + * </pre> + * + * By default the control loop is enabled on all ADC's. + */ + bool set_dc_offset_cl_enable(int bits, int mask); /*! * \brief return the usrp's serial number. @@ -276,11 +195,70 @@ class usrp1_source_base : public gr_sync_block { std::string serial_number(); /*! + * \brief Return daughterboard ID for given side [0,1]. + * + * \param which_side [0,1] which daughterboard + * + * \return daughterboard id >= 0 if successful + * \return -1 if no daugherboard + * \return -2 if invalid EEPROM on daughterboard + */ + virtual int daughterboard_id (int which_side) const; + + /*! + * \brief Clock ticks to delay rising of T/R signal + * \sa write_atr_mask, write_atr_txval, write_atr_rxval + */ + bool write_atr_tx_delay(int value); + + /*! + * \brief Clock ticks to delay falling edge of T/R signal + * \sa write_atr_mask, write_atr_txval, write_atr_rxval + */ + bool write_atr_rx_delay(int value); + + /*! + * \brief Set Programmable Gain Amplifier (PGA) + * + * \param which_amp which amp [0,3] + * \param gain_in_db gain value (linear in dB) + * + * gain is rounded to closest setting supported by hardware. + * + * \returns true iff sucessful. + * + * \sa pga_min(), pga_max(), pga_db_per_step() + */ + bool set_pga (int which_amp, double gain_in_db); + + /*! + * \brief Return programmable gain amplifier gain setting in dB. + * + * \param which_amp which amp [0,3] + */ + double pga (int which_amp) const; + + /*! + * \brief Return minimum legal PGA gain in dB. + */ + double pga_min () const; + + /*! + * \brief Return maximum legal PGA gain in dB. + */ + double pga_max () const; + + /*! + * \brief Return hardware step size of PGA (linear in dB). + */ + double pga_db_per_step () const; + + /*! * \brief Write direction register (output enables) for pins that go to daughterboard. * - * \param which_dboard [0,1] which d'board - * \param value value to write into register - * \param mask which bits of value to write into reg + * \param which_side [0,1] which size + * \param value value to write into register + * \param mask which bits of value to write into reg * * Each d'board has 16-bits of general purpose i/o. * Setting the bit makes it an output from the FPGA to the d'board. @@ -290,93 +268,84 @@ class usrp1_source_base : public gr_sync_block { * without a very good reason. Using this method incorrectly will * kill your USRP motherboard and/or daughterboard. */ - bool _write_oe (int which_dboard, int value, int mask); + bool _write_oe (int which_side, int value, int mask); /*! * \brief Write daughterboard i/o pin value * - * \param which_dboard [0,1] which d'board - * \param value value to write into register - * \param mask which bits of value to write into reg + * \param which_side [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg */ - bool write_io (int which_dboard, int value, int mask); + bool write_io (int which_side, int value, int mask); /*! * \brief Read daughterboard i/o pin value * - * \param which_dboard [0,1] which d'board + * \param which_side [0,1] which d'board * \returns register value if successful, else READ_FAILED */ - int read_io (int which_dboard); + int read_io (int which_side); /*! - * \brief Enable/disable automatic DC offset removal control loop in FPGA + * \brief Write daughterboard refclk config register * - * \param bits which control loops to enable - * \param mask which \p bits to pay attention to - * - * If the corresponding bit is set, enable the automatic DC - * offset correction control loop. + * \param which_side [0,1] which d'board + * \param value value to write into register, see below * * <pre> - * The 4 low bits are significant: - * - * ADC0 = (1 << 0) - * ADC1 = (1 << 1) - * ADC2 = (1 << 2) - * ADC3 = (1 << 3) + * Control whether a reference clock is sent to the daughterboards, + * and what frequency. The refclk is sent on d'board i/o pin 0. + * + * 3 2 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------------------------------------------+-+------------+ + * | Reserved (Must be zero) |E| DIVISOR | + * +-----------------------------------------------+-+------------+ + * + * Bit 7 -- 1 turns on refclk, 0 allows IO use + * Bits 6:0 Divider value * </pre> - * - * By default the control loop is enabled on all ADC's. */ - bool set_dc_offset_cl_enable(int bits, int mask); + bool write_refclk(int which_side, int value); + + bool write_atr_mask(int which_side, int value); + bool write_atr_txval(int which_side, int value); + bool write_atr_rxval(int which_side, int value); /*! - * \brief Specify Rx data format. - * - * \param format format specifier - * - * Rx data format control register - * - * 3 2 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-----------------------------------------+-+-+---------+-------+ - * | Reserved (Must be zero) |B|Q| WIDTH | SHIFT | - * +-----------------------------------------+-+-+---------+-------+ - * - * SHIFT specifies arithmetic right shift [0, 15] - * WIDTH specifies bit-width of I & Q samples across the USB [1, 16] (not all valid) - * Q if set deliver both I & Q, else just I - * B if set bypass half-band filter. - * - * Right now the acceptable values are: - * - * B Q WIDTH SHIFT - * 0 1 16 0 - * 0 1 8 8 + * \brief Write auxiliary digital to analog converter. * - * More valid combos to come. + * \param which_side [0,1] which d'board + * N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's. + * SLOT_TX_B and SLOT_RX_B share the same AUX DAC's. + * \param which_dac [2,3] TX slots must use only 2 and 3. + * \param value [0,4095] + * \returns true iff successful + */ + bool write_aux_dac (int which_side, int which_dac, int value); + + /*! + * \brief Read auxiliary analog to digital converter. * - * Default value is 0x00000300 16-bits, 0 shift, deliver both I & Q. + * \param which_side [0,1] which d'board + * \param which_adc [0,1] + * \returns value in the range [0,4095] if successful, else READ_FAILED. */ - bool set_format(unsigned int format); + int read_aux_adc (int which_side, int which_adc); /*! - * \brief return current format + * \brief returns A/D or D/A converter rate in Hz */ - unsigned int format () const; + long converter_rate() const; - static unsigned int make_format(int width=16, int shift=0, - bool want_q=true, bool bypass_halfband=false); - static int format_width(unsigned int format); - static int format_shift(unsigned int format); - static bool format_want_q(unsigned int format); - static bool format_bypass_halfband(unsigned int format); // ---------------------------------------------------------------- - // internal routines... + // Low level implementation routines. // You probably shouldn't be using these... - // ---------------------------------------------------------------- + // + + bool _set_led (int which_led, bool on); /*! * \brief Write FPGA register. @@ -387,13 +356,12 @@ class usrp1_source_base : public gr_sync_block { bool _write_fpga_reg (int regno, int value); //< 7-bit regno, 32-bit value /*! - * \brief Write FPGA register masked. + * \brief Read FPGA register. * \param regno 7-bit register number - * \param value 16-bit value - * \param mask 16-bit mask + * \param value 32-bit value * \returns true iff successful */ - bool _write_fpga_reg_masked (int regno, int value, int mask); //< 7-bit regno, 16-bit value, 16-bit mask + bool _read_fpga_reg (int regno, int *value); //< 7-bit regno, 32-bit value /*! * \brief Read FPGA register. @@ -403,6 +371,16 @@ class usrp1_source_base : public gr_sync_block { int _read_fpga_reg (int regno); /*! + * \brief Write FPGA register with mask. + * \param regno 7-bit register number + * \param value 16-bit value + * \param mask 16-bit value + * \returns true if successful + * Only use this for registers who actually implement a mask in the verilog firmware, like FR_RX_MASTER_SLAVE + */ + bool _write_fpga_reg_masked (int regno, int value, int mask); + + /*! * \brief Write AD9862 register. * \param which_codec 0 or 1 * \param regno 6-bit register number @@ -450,6 +428,16 @@ class usrp1_source_base : public gr_sync_block { * the peripheral and returned. */ std::string _read_spi (int optional_header, int enables, int format, int len); + + /*! + * Return an existing daughterboard from list of candidate dbids, or the first found + * on side A or side B. + * + * \param candidates Vector of candidate dbids + * + * Throws std::runtime_error if not found + */ + usrp_subdev_spec pick_subdev(std::vector<int> candidates=std::vector<int>(0)); }; -#endif /* INCLUDED_USRP1_SOURCE_BASE_H */ +#endif /* INCLUDED_USRP_BASE_H */ diff --git a/gr-usrp/src/usrp_base.i b/gr-usrp/src/usrp_base.i new file mode 100644 index 000000000..8f0c8368d --- /dev/null +++ b/gr-usrp/src/usrp_base.i @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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 version 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. + */ + +%{ +#include "usrp_base.h" +%} + +class usrp_base : public gr_sync_block +{ +protected: + usrp_base(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature) + : gr_sync_block(name, input_signature, output_signature) {} + +public: + std::vector<std::vector<db_base_sptr> > db(); + std::vector<db_base_sptr> db(int which_side); + db_base_sptr db(int which_side, int which_dev); + %rename (_real_selected_subdev) selected_subdev; + db_base_sptr selected_subdev(usrp_subdev_spec ss); + long fpga_master_clock_freq() const; + void set_verbose (bool on); + static const int READ_FAILED = -99999; + bool write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf); + std::string read_eeprom (int i2c_addr, int eeprom_offset, int len); + bool write_i2c (int i2c_addr, const std::string buf); + std::string read_i2c (int i2c_addr, int len); + bool set_adc_offset (int which_adc, int offset); + bool set_dac_offset (int which_dac, int offset, int offset_pin); + bool set_adc_buffer_bypass (int which_adc, bool bypass); + bool set_dc_offset_cl_enable(int bits, int mask); + std::string serial_number(); + virtual int daughterboard_id (int which_side) const; + bool write_atr_tx_delay(int value); + bool write_atr_rx_delay(int value); + bool set_pga (int which_amp, double gain_in_db); + double pga (int which_amp) const; + double pga_min () const; + double pga_max () const; + double pga_db_per_step () const; + bool _write_oe (int which_side, int value, int mask); + bool write_io (int which_side, int value, int mask); + int read_io (int which_side); + //bool write_refclk(int which_side, int value); + bool write_atr_mask(int which_side, int value); + bool write_atr_txval(int which_side, int value); + bool write_atr_rxval(int which_side, int value); + bool write_aux_dac (int which_side, int which_dac, int value); + int read_aux_adc (int which_side, int which_adc); + long converter_rate() const; + bool _set_led (int which_led, bool on); + bool _write_fpga_reg (int regno, int value); + //bool _read_fpga_reg (int regno, int *value); + int _read_fpga_reg (int regno); + bool _write_fpga_reg_masked (int regno, int value, int mask); + bool _write_9862 (int which_codec, int regno, unsigned char value); + int _read_9862 (int which_codec, int regno) const; + bool _write_spi (int optional_header, int enables, int format, std::string buf); + std::string _read_spi (int optional_header, int enables, int format, int len); + %rename(_real_pick_subdev) pick_subdev; + usrp_subdev_spec pick_subdev(std::vector<int> candidates=std::vector<int>(0)) + throw (std::runtime_error); +}; diff --git a/gr-usrp/src/usrp_sink_base.cc b/gr-usrp/src/usrp_sink_base.cc new file mode 100644 index 000000000..963f4dd6d --- /dev/null +++ b/gr-usrp/src/usrp_sink_base.cc @@ -0,0 +1,241 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008 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 version 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <usrp_sink_base.h> +#include <gr_io_signature.h> +#include <usrp_standard.h> +#include <assert.h> + +static const int OUTPUT_MULTIPLE_SAMPLES = 128; // DON'T CHANGE THIS VALUE! + +usrp_sink_base::usrp_sink_base (const std::string &name, + gr_io_signature_sptr input_signature, + int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error) + : usrp_base(name, + input_signature, + gr_make_io_signature (0, 0, 0)), + d_nunderruns (0) +{ + d_usrp = usrp_standard_tx::make (which_board, + interp_rate, + nchan, mux, + fusb_block_size, + fusb_nblocks, + fpga_filename, + firmware_filename + ); + if (d_usrp == 0) + throw std::runtime_error ("can't open usrp"); + + set_usrp_basic(d_usrp); + + // All calls to d_usrp->write must be multiples of 512 bytes. + + set_output_multiple (OUTPUT_MULTIPLE_SAMPLES); +} + +usrp_sink_base::~usrp_sink_base () +{ +} + +int +usrp_sink_base::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + static const int BUFSIZE = 16 * (1L << 10); // 16kB + unsigned char outbuf[BUFSIZE]; + int obi = 0; + int input_index = 0; + int input_items_consumed; + int bytes_written; + bool underrun; + + + while (input_index < noutput_items){ + + copy_to_usrp_buffer (input_items, + input_index, + noutput_items - input_index, // input_items_available + input_items_consumed, // [out] + &outbuf[obi], // [out] usrp_buffer + BUFSIZE - obi, // usrp_buffer_length + bytes_written); // [out] + + assert (input_index + input_items_consumed <= noutput_items); + assert (obi + bytes_written <= BUFSIZE); + + input_index += input_items_consumed; + obi += bytes_written; + + if (obi >= BUFSIZE){ // flush + if (d_usrp->write (outbuf, obi, &underrun) != obi) + return -1; // indicate we're done + + if (underrun){ + d_nunderruns++; + // fprintf (stderr, "usrp_sink: underrun\n"); + fputs ("uU", stderr); + } + obi = 0; + } + } + + if (obi != 0){ + assert (obi % 512 == 0); + if (d_usrp->write (outbuf, obi, &underrun) != obi) + return -1; // indicate we're done + + if (underrun){ + d_nunderruns++; + // fprintf (stderr, "usrp_sink: underrun\n"); + fputs ("uU", stderr); + } + } + + return noutput_items; +} + +bool +usrp_sink_base::set_interp_rate (unsigned int rate) +{ + return d_usrp->set_interp_rate (rate); +} + +bool +usrp_sink_base::set_nchannels (int nchan) +{ + return d_usrp->set_nchannels (nchan); +} + +bool +usrp_sink_base::set_mux (int mux) +{ + return d_usrp->set_mux (mux); +} + +int +usrp_sink_base::determine_tx_mux_value(usrp_subdev_spec ss) +{ + return d_usrp->determine_tx_mux_value(ss); +} + +bool +usrp_sink_base::set_tx_freq (int channel, double freq) +{ + return d_usrp->set_tx_freq (channel, freq); +} + +unsigned int +usrp_sink_base::interp_rate () const +{ + return d_usrp->interp_rate (); +} + +int +usrp_sink_base::nchannels () const +{ + return d_usrp->nchannels (); +} + +int +usrp_sink_base::mux () const +{ + return d_usrp->mux (); +} + + +double +usrp_sink_base::tx_freq (int channel) const +{ + return d_usrp->tx_freq (channel); +} + +bool +usrp_sink_base::has_rx_halfband() +{ + return d_usrp->has_rx_halfband(); +} + +bool +usrp_sink_base::has_tx_halfband() +{ + return d_usrp->has_tx_halfband(); +} + +int +usrp_sink_base::nddcs() +{ + return d_usrp->nddcs(); +} + +int +usrp_sink_base::nducs() +{ + return d_usrp->nducs(); +} + +bool +usrp_sink_base::start() +{ + return d_usrp->start(); +} + +bool +usrp_sink_base::stop() +{ + return d_usrp->stop(); +} + + +bool +usrp_sink_base::tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result) +{ + return d_usrp->tune(chan, db, target_freq, result); +} + +usrp_subdev_spec +usrp_sink_base::pick_tx_subdevice() +{ + int dbids[] = { + USRP_DBID_FLEX_400_TX, + USRP_DBID_FLEX_900_TX, + USRP_DBID_FLEX_1200_TX, + USRP_DBID_FLEX_2400_TX, + USRP_DBID_BASIC_TX + }; + + std::vector<int> candidates(dbids, dbids+(sizeof(dbids)/sizeof(int))); + return pick_subdev(candidates); +} diff --git a/gr-usrp/src/usrp_sink_base.h b/gr-usrp/src/usrp_sink_base.h new file mode 100644 index 000000000..12dd51c65 --- /dev/null +++ b/gr-usrp/src/usrp_sink_base.h @@ -0,0 +1,151 @@ + +/* -*- c++ -*- */ +/* + * Copyright 2004,2006,2008 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 version 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. + */ + +#ifndef INCLUDED_USRP_SINK_BASE_H +#define INCLUDED_USRP_SINK_BASE_H + +#include <usrp_base.h> +#include <stdexcept> +#include <usrp_tune_result.h> +#include <usrp_dbid.h> + +class usrp_standard_tx; + +/*! + * \brief abstract interface to Universal Software Radio Peripheral Tx path (Rev 1) + */ +class usrp_sink_base : public usrp_base { + private: + boost::shared_ptr<usrp_standard_tx> d_usrp; + int d_nunderruns; + + protected: + usrp_sink_base (const std::string &name, + gr_io_signature_sptr input_signature, + int which_board, + unsigned int interp_rate, + int nchan, + int mux, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + /*! + * \brief convert between input item format and usrp native format + * + * \param input_items[in] stream(s) of input items + * \param input_index[in] starting index in input_items + * \param input_items_available[in] number of items available starting at item[index] + * \param input_items_consumed[out] number of input items consumed by copy + * \param usrp_buffer[out] destination buffer + * \param usrp_buffer_length[in] \p usrp_buffer length in bytes + * \param bytes_written[out] number of bytes written into \p usrp_buffer + */ + virtual void copy_to_usrp_buffer (gr_vector_const_void_star &input_items, + int input_index, + int input_items_available, + int &input_items_consumed, + void *usrp_buffer, + int usrp_buffer_length, + int &bytes_written) = 0; + + public: + ~usrp_sink_base (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + /*! + * \brief Set interpolator rate. \p rate must be in [4, 1024] and a multiple of 4. + * + * The final complex sample rate across the USB is + * dac_freq () / interp_rate () * nchannels () + */ + bool set_interp_rate (unsigned int rate); + bool set_nchannels (int nchan); + bool set_mux (int mux); + int determine_tx_mux_value(usrp_subdev_spec ss); + + /*! + * \brief set the frequency of the digital up converter. + * + * \p channel must be 0. \p freq is the center frequency in Hz. + * It must be in the range [-44M, 44M]. The frequency specified is + * quantized. Use tx_freq to retrieve the actual value used. + */ + bool set_tx_freq (int channel, double freq); + + long dac_rate() const { return converter_rate(); } // alias + long dac_freq() const { return converter_rate(); } // deprecated alias + + unsigned int interp_rate () const; + int nchannels () const; + int mux () const; + double tx_freq (int channel) const; + int nunderruns () const { return d_nunderruns; } + + bool has_rx_halfband(); + bool has_tx_halfband(); + int nddcs(); + int nducs(); + + /*! + * \brief Called to enable drivers, etc for i/o devices. + * + * This allows a block to enable an associated driver to begin + * transfering data just before we start to execute the scheduler. + * The end result is that this reduces latency in the pipeline when + * dealing with audio devices, usrps, etc. + */ + bool start(); + + /*! + * \brief Called to disable drivers, etc for i/o devices. + */ + bool stop(); + + /*! + * \brief High-level "tune" method. Works for the single channel case. + * + * This method adjusts both the daughterboard LO and the DUC so that + * DC in the complex baseband samples ends up at RF target_freq. + * + * \param chan which DUC channel we're controlling (usually == which_side). + * \param db the daughterboard we're controlling. + * \param target_freq the RF frequency we want our baseband translated to. + * \param[out] tune_result details how the hardware was configured. + * + * \returns true iff everything was successful. + */ + bool tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result); + + /*! + * \brief Select suitable Tx daughterboard + */ + usrp_subdev_spec pick_tx_subdevice(); +}; + +#endif /* INCLUDED_USRP_SINK_BASE_H */ diff --git a/gr-usrp/src/usrp_sink_base.i b/gr-usrp/src/usrp_sink_base.i new file mode 100644 index 000000000..ffc70a984 --- /dev/null +++ b/gr-usrp/src/usrp_sink_base.i @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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 version 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. + */ + +%{ +#include "usrp_sink_base.h" +%} + +class usrp_sink_base : public usrp_base +{ +private: + usrp_sink_base() throw (std::runtime_error); + +public: + bool set_interp_rate (unsigned int rate); + bool set_nchannels (int nchan); + bool set_mux (int mux); + %rename(_real_determine_tx_mux_value) determine_tx_mux_value; + int determine_tx_mux_value(usrp_subdev_spec ss); + bool set_tx_freq (int channel, double freq); + long dac_rate() const { return converter_rate(); } + long dac_freq() const { return converter_rate(); } + unsigned int interp_rate () const; + int nchannels () const; + int mux () const; + double tx_freq (int channel) const; + int nunderruns () const { return d_nunderruns; } + bool has_rx_halfband(); + bool has_tx_halfband(); + int nddcs(); + int nducs(); + %rename(_real_tune) tune; + bool tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result); + %rename(_real_pick_tx_subdevice) pick_tx_subdevice(); + usrp_subdev_spec pick_tx_subdevice(); +}; diff --git a/gr-usrp/src/usrp1_sink_c.cc b/gr-usrp/src/usrp_sink_c.cc index b38306090..363a113fc 100644 --- a/gr-usrp/src/usrp1_sink_c.cc +++ b/gr-usrp/src/usrp_sink_c.cc @@ -24,13 +24,13 @@ #include "config.h" #endif -#include <usrp1_sink_c.h> +#include <usrp_sink_c.h> #include <gr_io_signature.h> #include <usrp_standard.h> #include <usrp_bytesex.h> -usrp1_sink_c_sptr -usrp1_make_sink_c (int which_board, +usrp_sink_c_sptr +usrp_make_sink_c (int which_board, unsigned int interp_rate, int nchan, int mux, @@ -40,7 +40,7 @@ usrp1_make_sink_c (int which_board, const std::string firmware_filename ) throw (std::runtime_error) { - return usrp1_sink_c_sptr (new usrp1_sink_c (which_board, + return usrp_sink_c_sptr (new usrp_sink_c (which_board, interp_rate, nchan, mux, @@ -52,7 +52,7 @@ usrp1_make_sink_c (int which_board, } -usrp1_sink_c::usrp1_sink_c (int which_board, +usrp_sink_c::usrp_sink_c (int which_board, unsigned int interp_rate, int nchan, int mux, @@ -61,7 +61,7 @@ usrp1_sink_c::usrp1_sink_c (int which_board, const std::string fpga_filename, const std::string firmware_filename ) throw (std::runtime_error) - : usrp1_sink_base ("usrp1_sink_c", + : usrp_sink_base ("usrp_sink_c", gr_make_io_signature (1, 1, sizeof (gr_complex)), which_board, interp_rate, nchan, mux, fusb_block_size, fusb_nblocks, @@ -69,7 +69,7 @@ usrp1_sink_c::usrp1_sink_c (int which_board, { } -usrp1_sink_c::~usrp1_sink_c () +usrp_sink_c::~usrp_sink_c () { // NOP } @@ -79,7 +79,7 @@ usrp1_sink_c::~usrp1_sink_c () * for the usrp. */ void -usrp1_sink_c::copy_to_usrp_buffer (gr_vector_const_void_star &input_items, +usrp_sink_c::copy_to_usrp_buffer (gr_vector_const_void_star &input_items, int input_index, int input_items_available, int &input_items_consumed, // out diff --git a/gr-usrp/src/usrp1_sink_c.h b/gr-usrp/src/usrp_sink_c.h index 9e1d3f009..32be5e8bb 100644 --- a/gr-usrp/src/usrp1_sink_c.h +++ b/gr-usrp/src/usrp_sink_c.h @@ -20,27 +20,27 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_USRP1_SINK_C_H -#define INCLUDED_USRP1_SINK_C_H +#ifndef INCLUDED_USRP_SINK_C_H +#define INCLUDED_USRP_SINK_C_H -#include <usrp1_sink_base.h> +#include <usrp_sink_base.h> -class usrp1_sink_c; -typedef boost::shared_ptr<usrp1_sink_c> usrp1_sink_c_sptr; +class usrp_sink_c; +typedef boost::shared_ptr<usrp_sink_c> usrp_sink_c_sptr; // public shared_ptr constructor -usrp1_sink_c_sptr -usrp1_make_sink_c (int which_board, - unsigned int interp_rate, - int nchan, - int mux, - int fusb_block_size, - int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename - ) throw (std::runtime_error); +usrp_sink_c_sptr +usrp_make_sink_c (int which_board=0, + unsigned int interp_rate=32, + int nchan=1, + int mux=-1, + int fusb_block_size=0, + int fusb_nblocks=0, + const std::string fpga_filename="", + const std::string firmware_filename="" + ) throw (std::runtime_error); /*! @@ -48,11 +48,11 @@ usrp1_make_sink_c (int which_board, * * input: gr_complex */ -class usrp1_sink_c : public usrp1_sink_base { +class usrp_sink_c : public usrp_sink_base { private: - friend usrp1_sink_c_sptr - usrp1_make_sink_c (int which_board, + friend usrp_sink_c_sptr + usrp_make_sink_c (int which_board, unsigned int interp_rate, int nchan, int mux, @@ -63,7 +63,7 @@ class usrp1_sink_c : public usrp1_sink_base { ) throw (std::runtime_error); protected: - usrp1_sink_c (int which_board, + usrp_sink_c (int which_board, unsigned int interp_rate, int nchan, int mux, @@ -81,7 +81,7 @@ class usrp1_sink_c : public usrp1_sink_base { int usrp_buffer_length, int &bytes_written); public: - ~usrp1_sink_c (); + ~usrp_sink_c (); }; -#endif /* INCLUDED_USRP1_SINK_C_H */ +#endif /* INCLUDED_USRP_SINK_C_H */ diff --git a/gr-usrp/src/usrp_sink_c.i b/gr-usrp/src/usrp_sink_c.i new file mode 100644 index 000000000..15480883e --- /dev/null +++ b/gr-usrp/src/usrp_sink_c.i @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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 version 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. + */ + +%{ +#include "usrp_sink_c.h" +%} + +GR_SWIG_BLOCK_MAGIC(usrp,sink_c) + +class usrp_sink_c; +typedef boost::shared_ptr<usrp_sink_c> usrp_sink_c_sptr; + +usrp_sink_c_sptr +usrp_make_sink_c(int which=0, + unsigned int interp_rate=32, + int nchan=1, + int mux=-1, + int fusb_block_size=0, + int fusb_nblocks=0, + const std::string fpga_filename="", + const std::string firmware_filename="" + ) throw (std::runtime_error); + +class usrp_sink_c : public usrp_sink_base +{ +private: + usrp_sink_c() throw (std::runtime_error); +}; diff --git a/gr-usrp/src/usrp1_sink_s.cc b/gr-usrp/src/usrp_sink_s.cc index 3ce336328..adbf3acbd 100644 --- a/gr-usrp/src/usrp1_sink_s.cc +++ b/gr-usrp/src/usrp_sink_s.cc @@ -24,13 +24,13 @@ #include "config.h" #endif -#include <usrp1_sink_s.h> +#include <usrp_sink_s.h> #include <gr_io_signature.h> #include <usrp_standard.h> #include <usrp_bytesex.h> -usrp1_sink_s_sptr -usrp1_make_sink_s (int which_board, +usrp_sink_s_sptr +usrp_make_sink_s (int which_board, unsigned int interp_rate, int nchan, int mux, @@ -40,7 +40,7 @@ usrp1_make_sink_s (int which_board, const std::string firmware_filename ) throw (std::runtime_error) { - return usrp1_sink_s_sptr (new usrp1_sink_s (which_board, + return usrp_sink_s_sptr (new usrp_sink_s (which_board, interp_rate, nchan, mux, @@ -52,7 +52,7 @@ usrp1_make_sink_s (int which_board, } -usrp1_sink_s::usrp1_sink_s (int which_board, +usrp_sink_s::usrp_sink_s (int which_board, unsigned int interp_rate, int nchan, int mux, @@ -61,7 +61,7 @@ usrp1_sink_s::usrp1_sink_s (int which_board, const std::string fpga_filename, const std::string firmware_filename ) throw (std::runtime_error) - : usrp1_sink_base ("usrp1_sink_s", + : usrp_sink_base ("usrp_sink_s", gr_make_io_signature (1, 1, sizeof (short)), which_board, interp_rate, nchan, mux, fusb_block_size, fusb_nblocks, @@ -70,7 +70,7 @@ usrp1_sink_s::usrp1_sink_s (int which_board, set_output_multiple (512 / sizeof(short)); // don't change } -usrp1_sink_s::~usrp1_sink_s () +usrp_sink_s::~usrp_sink_s () { // NOP } @@ -80,7 +80,7 @@ usrp1_sink_s::~usrp1_sink_s () * for the usrp. */ void -usrp1_sink_s::copy_to_usrp_buffer (gr_vector_const_void_star &input_items, +usrp_sink_s::copy_to_usrp_buffer (gr_vector_const_void_star &input_items, int input_index, int input_items_available, int &input_items_consumed, // out diff --git a/gr-usrp/src/usrp1_sink_s.h b/gr-usrp/src/usrp_sink_s.h index 2420b1e36..17352a5af 100644 --- a/gr-usrp/src/usrp1_sink_s.h +++ b/gr-usrp/src/usrp_sink_s.h @@ -20,38 +20,38 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_USRP1_SINK_S_H -#define INCLUDED_USRP1_SINK_S_H +#ifndef INCLUDED_USRP_SINK_S_H +#define INCLUDED_USRP_SINK_S_H -#include <usrp1_sink_base.h> +#include <usrp_sink_base.h> -class usrp1_sink_s; -typedef boost::shared_ptr<usrp1_sink_s> usrp1_sink_s_sptr; +class usrp_sink_s; +typedef boost::shared_ptr<usrp_sink_s> usrp_sink_s_sptr; // public shared_ptr constructor -usrp1_sink_s_sptr -usrp1_make_sink_s (int which_board, - unsigned int interp_rate, - int nchan, - int mux, - int fusb_block_size, - int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename - ) throw (std::runtime_error); +usrp_sink_s_sptr +usrp_make_sink_s (int which_board=0, + unsigned int interp_rate=32, + int nchan=1, + int mux=-1, + int fusb_block_size=0, + int fusb_nblocks=0, + const std::string fpga_filename="", + const std::string firmware_filename="" + ) throw (std::runtime_error); /*! * \brief interface to Universal Software Radio Peripheral Tx path (Rev 1) * * input: short */ -class usrp1_sink_s : public usrp1_sink_base { +class usrp_sink_s : public usrp_sink_base { private: - friend usrp1_sink_s_sptr - usrp1_make_sink_s (int which_board, + friend usrp_sink_s_sptr + usrp_make_sink_s (int which_board, unsigned int interp_rate, int nchan, int mux, @@ -62,7 +62,7 @@ class usrp1_sink_s : public usrp1_sink_base { ) throw (std::runtime_error); protected: - usrp1_sink_s (int which_board, + usrp_sink_s (int which_board, unsigned int interp_rate, int nchan, int mux, @@ -80,7 +80,7 @@ class usrp1_sink_s : public usrp1_sink_base { int usrp_buffer_length, int &bytes_written); public: - ~usrp1_sink_s (); + ~usrp_sink_s (); }; -#endif /* INCLUDED_USRP1_SINK_S_H */ +#endif /* INCLUDED_USRP_SINK_S_H */ diff --git a/gr-usrp/src/usrp_sink_s.i b/gr-usrp/src/usrp_sink_s.i new file mode 100644 index 000000000..9993d5214 --- /dev/null +++ b/gr-usrp/src/usrp_sink_s.i @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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 version 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. + */ + +%{ +#include "usrp_sink_s.h" +%} + +GR_SWIG_BLOCK_MAGIC(usrp,sink_s) + +class usrp_sink_s; +typedef boost::shared_ptr<usrp_sink_s> usrp_sink_s_sptr; + +usrp_sink_s_sptr +usrp_make_sink_s(int which=0, + unsigned int interp_rate=32, + int nchan=1, + int mux=-1, + int fusb_block_size=0, + int fusb_nblocks=0, + const std::string fpga_filename="", + const std::string firmware_filename="" + ) throw (std::runtime_error); + +class usrp_sink_s : public usrp_sink_base +{ +private: + usrp_sink_s() throw (std::runtime_error); +}; diff --git a/gr-usrp/src/usrp_source_base.cc b/gr-usrp/src/usrp_source_base.cc new file mode 100644 index 000000000..778fa1017 --- /dev/null +++ b/gr-usrp/src/usrp_source_base.cc @@ -0,0 +1,295 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008 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 version 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <usrp_source_base.h> +#include <gr_io_signature.h> +#include <usrp_standard.h> +#include <assert.h> + +static const int OUTPUT_MULTIPLE_BYTES = 4 * 1024; + +usrp_source_base::usrp_source_base (const std::string &name, + gr_io_signature_sptr output_signature, + int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error) + : usrp_base(name, + gr_make_io_signature (0, 0, 0), + output_signature), + d_noverruns (0) +{ + d_usrp = usrp_standard_rx::make (which_board, decim_rate, + nchan, mux, mode, + fusb_block_size, + fusb_nblocks, + fpga_filename, + firmware_filename); + if (d_usrp == 0) + throw std::runtime_error ("can't open usrp"); + + set_usrp_basic(d_usrp); + + // All calls to d_usrp->read must be multiples of 512 bytes. + // We jack this up to 4k to reduce overhead. + + set_output_multiple (OUTPUT_MULTIPLE_BYTES / output_signature->sizeof_stream_item (0)); +} + +usrp_source_base::~usrp_source_base () +{ +} + +unsigned int +usrp_source_base::sizeof_basic_sample() const +{ + return usrp_standard_rx::format_width(d_usrp->format()) / 8; +} + +int +usrp_source_base::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + static const int BUFSIZE = 4 * OUTPUT_MULTIPLE_BYTES; + unsigned char buf[BUFSIZE]; + int output_index = 0; + int output_items_produced; + int bytes_read; + bool overrun; + + while (output_index < noutput_items){ + int nbytes = ninput_bytes_reqd_for_noutput_items (noutput_items - output_index); + nbytes = std::min (nbytes, BUFSIZE); + + int result_nbytes = d_usrp->read (buf, nbytes, &overrun); + if (overrun){ + // fprintf (stderr, "usrp_source: overrun\n"); + fputs ("uO", stderr); + d_noverruns++; + } + + if (result_nbytes < 0) // We've got a problem. Usually board unplugged or powered down. + return -1; // Indicate we're done. + + if (result_nbytes != nbytes){ // not really an error, but unexpected + fprintf (stderr, "usrp_source: short read. Expected %d, got %d\n", + nbytes, result_nbytes); + } + + copy_from_usrp_buffer (output_items, + output_index, + noutput_items - output_index, // output_items_available + output_items_produced, // [out] + buf, // usrp_buffer + result_nbytes, // usrp_buffer_length + bytes_read); // [out] + + assert (output_index + output_items_produced <= noutput_items); + assert (bytes_read == result_nbytes); + + output_index += output_items_produced; + } + + return noutput_items; +} + + +bool +usrp_source_base::set_decim_rate (unsigned int rate) +{ + return d_usrp->set_decim_rate (rate); +} + +bool +usrp_source_base::set_nchannels (int nchan) +{ + return d_usrp->set_nchannels (nchan); +} + +bool +usrp_source_base::set_mux (int mux) +{ + return d_usrp->set_mux (mux); +} + +int +usrp_source_base::determine_rx_mux_value(usrp_subdev_spec ss) +{ + return d_usrp->determine_rx_mux_value(ss); +} + +bool +usrp_source_base::set_rx_freq (int channel, double freq) +{ + return d_usrp->set_rx_freq (channel, freq); +} + +unsigned int +usrp_source_base::decim_rate () const +{ + return d_usrp->decim_rate (); +} + +int +usrp_source_base::nchannels () const +{ + return d_usrp->nchannels (); +} + +int +usrp_source_base::mux () const +{ + return d_usrp->mux (); +} + +double +usrp_source_base::rx_freq (int channel) const +{ + return d_usrp->rx_freq (channel); +} + +bool +usrp_source_base::set_fpga_mode (int mode) +{ + return d_usrp->set_fpga_mode (mode); +} + +bool +usrp_source_base::set_ddc_phase (int channel, int phase) +{ + return d_usrp->set_ddc_phase(channel, phase); +} + + +bool +usrp_source_base::set_format(unsigned int format) +{ + return d_usrp->set_format(format); +} + +unsigned int +usrp_source_base::format() const +{ + return d_usrp->format(); +} + +unsigned int +usrp_source_base::make_format(int width, int shift, bool want_q, bool bypass_halfband) +{ + return usrp_standard_rx::make_format(width, shift, want_q, bypass_halfband); +} + +int +usrp_source_base::format_width(unsigned int format) +{ + return usrp_standard_rx::format_width(format); +} + +int +usrp_source_base::format_shift(unsigned int format) +{ + return usrp_standard_rx::format_shift(format); +} + +bool +usrp_source_base::format_want_q(unsigned int format) +{ + return usrp_standard_rx::format_want_q(format); +} + +bool +usrp_source_base::format_bypass_halfband(unsigned int format) +{ + return usrp_standard_rx::format_bypass_halfband(format); +} + +bool +usrp_source_base::has_rx_halfband() +{ + return d_usrp->has_rx_halfband(); +} + +bool +usrp_source_base::has_tx_halfband() +{ + return d_usrp->has_tx_halfband(); +} + +int +usrp_source_base::nddcs() +{ + return d_usrp->nddcs(); +} + +int +usrp_source_base::nducs() +{ + return d_usrp->nducs(); +} + +bool +usrp_source_base::start() +{ + return d_usrp->start(); +} + +bool +usrp_source_base::stop() +{ + return d_usrp->stop(); +} + +bool +usrp_source_base::tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result) +{ + return d_usrp->tune(chan, db, target_freq, result); +} + +usrp_subdev_spec +usrp_source_base::pick_rx_subdevice() +{ + int dbids[] = { + USRP_DBID_FLEX_400_RX, + USRP_DBID_FLEX_900_RX, + USRP_DBID_FLEX_1200_RX, + USRP_DBID_FLEX_2400_RX, + USRP_DBID_TV_RX, + USRP_DBID_TV_RX_REV_2, + USRP_DBID_DBS_RX, + USRP_DBID_DBS_RX_REV_2_1, + USRP_DBID_BASIC_RX + }; + + std::vector<int> candidates(dbids, dbids+(sizeof(dbids)/sizeof(int))); + return pick_subdev(candidates); +} diff --git a/gr-usrp/src/usrp_source_base.h b/gr-usrp/src/usrp_source_base.h new file mode 100644 index 000000000..9d8f32ac7 --- /dev/null +++ b/gr-usrp/src/usrp_source_base.h @@ -0,0 +1,219 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008 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 version 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. + */ + +#ifndef INCLUDED_USRP_SOURCE_BASE_H +#define INCLUDED_USRP_SOURCE_BASE_H + +#include <usrp_base.h> +#include <stdexcept> +#include <usrp_tune_result.h> +#include <usrp_dbid.h> + +class usrp_standard_rx; + +/*! + * \brief abstract interface to Universal Software Radio Peripheral Rx path (Rev 1) + */ +class usrp_source_base : public usrp_base { + private: + boost::shared_ptr<usrp_standard_rx> d_usrp; + int d_noverruns; + + protected: + usrp_source_base (const std::string &name, + gr_io_signature_sptr output_signature, + int which_board, + unsigned int decim_rate, + int nchan, + int mux, + int mode, + int fusb_block_size, + int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) throw (std::runtime_error); + + /*! + * \brief return number of usrp input bytes required to produce noutput items. + */ + virtual int ninput_bytes_reqd_for_noutput_items (int noutput_items) = 0; + + /*! + * \brief number of bytes in a low-level sample + */ + unsigned int sizeof_basic_sample() const; + + /*! + * \brief convert between native usrp format and output item format + * + * \param output_items[out] stream(s) of output items + * \param output_index[in] starting index in output_items + * \param output_items_available[in] number of empty items available at item[index] + * \param output_items_produced[out] number of items produced by copy + * \param usrp_buffer[in] source buffer + * \param usrp_buffer_length[in] number of bytes available in \p usrp_buffer + * \param bytes_read[out] number of bytes read from \p usrp_buffer + * + * The copy must consume all bytes available. That is, \p bytes_read must equal + * \p usrp_buffer_length. + */ + virtual void copy_from_usrp_buffer (gr_vector_void_star &output_items, + int output_index, + int output_items_available, + int &output_items_produced, + const void *usrp_buffer, + int usrp_buffer_length, + int &bytes_read) = 0; + + public: + ~usrp_source_base (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + /*! + * \brief Set decimator rate. \p rate must be EVEN and in [8, 256]. + * + * The final complex sample rate across the USB is + * adc_freq () / decim_rate () + */ + bool set_decim_rate (unsigned int rate); + bool set_nchannels (int nchan); + bool set_mux (int mux); + int determine_rx_mux_value(usrp_subdev_spec ss); + + /*! + * \brief set the center frequency of the digital down converter. + * + * \p channel must be 0. \p freq is the center frequency in Hz. + * It must be in the range [-FIXME, FIXME]. The frequency specified is + * quantized. Use rx_freq to retrieve the actual value used. + */ + bool set_rx_freq (int channel, double freq); + + /*! + * \brief set fpga special modes + */ + bool set_fpga_mode (int mode); + + /*! + * \brief Set the digital down converter phase register. + * + * \param channel which ddc channel [0, 3] + * \param phase 32-bit integer phase value. + */ + bool set_ddc_phase(int channel, int phase); + + long adc_rate() const { return converter_rate(); } // alias + long adc_freq() const { return converter_rate(); } // deprecated alias + + unsigned int decim_rate () const; + int nchannels () const; + int mux () const; + double rx_freq (int channel) const; + int noverruns () const { return d_noverruns; } + + bool has_rx_halfband(); + bool has_tx_halfband(); + int nddcs(); + int nducs(); + + /*! + * \brief Called to enable drivers, etc for i/o devices. + * + * This allows a block to enable an associated driver to begin + * transfering data just before we start to execute the scheduler. + * The end result is that this reduces latency in the pipeline when + * dealing with audio devices, usrps, etc. + */ + bool start(); + + /*! + * \brief Called to disable drivers, etc for i/o devices. + */ + bool stop(); + + /*! + * \brief Specify Rx data format. + * + * \param format format specifier + * + * Rx data format control register + * + * 3 2 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-----------------------------------------+-+-+---------+-------+ + * | Reserved (Must be zero) |B|Q| WIDTH | SHIFT | + * +-----------------------------------------+-+-+---------+-------+ + * + * SHIFT specifies arithmetic right shift [0, 15] + * WIDTH specifies bit-width of I & Q samples across the USB [1, 16] (not all valid) + * Q if set deliver both I & Q, else just I + * B if set bypass half-band filter. + * + * Right now the acceptable values are: + * + * B Q WIDTH SHIFT + * 0 1 16 0 + * 0 1 8 8 + * + * More valid combos to come. + * + * Default value is 0x00000300 16-bits, 0 shift, deliver both I & Q. + */ + bool set_format(unsigned int format); + + /*! + * \brief return current format + */ + unsigned int format () const; + + static unsigned int make_format(int width=16, int shift=0, + bool want_q=true, bool bypass_halfband=false); + static int format_width(unsigned int format); + static int format_shift(unsigned int format); + static bool format_want_q(unsigned int format); + static bool format_bypass_halfband(unsigned int format); + + /*! + * \brief High-level "tune" method. Works for the single channel case. + * + * This method adjusts both the daughterboard LO and the DDC so that + * target_freq ends up at DC in the complex baseband samples. + * + * \param chan which DDC channel we're controlling (almost always 0). + * \param db the daughterboard we're controlling. + * \param target_freq the RF frequency we want at DC in the complex baseband. + * \param[out] tune_result details how the hardware was configured. + * + * \returns true iff everything was successful. + */ + bool tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result); + + /*! + * \brief Select suitable Rx daughterboard + */ + usrp_subdev_spec pick_rx_subdevice(); +}; + +#endif /* INCLUDED_USRP_SOURCE_BASE_H */ diff --git a/gr-usrp/src/usrp_source_base.i b/gr-usrp/src/usrp_source_base.i new file mode 100644 index 000000000..6a70c7412 --- /dev/null +++ b/gr-usrp/src/usrp_source_base.i @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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 version 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. + */ + +%{ +#include "usrp_source_base.h" +%} + +class usrp_source_base : public usrp_base +{ +private: + usrp_source_base() throw (std::runtime_error); + +public: + bool set_decim_rate (unsigned int rate); + bool set_nchannels (int nchan); + bool set_mux (int mux); + %rename(_real_determine_rx_mux_value) determine_rx_mux_value; + int determine_rx_mux_value(usrp_subdev_spec ss); + bool set_rx_freq (int channel, double freq); + bool set_fpga_mode (int mode); + bool set_ddc_phase(int channel, int phase); + long adc_rate() const { return converter_rate(); } + long adc_freq() const { return converter_rate(); } + unsigned int decim_rate () const; + int nchannels () const; + int mux () const; + double rx_freq (int channel) const; + int noverruns () const { return d_noverruns; } + bool has_rx_halfband(); + bool has_tx_halfband(); + int nddcs(); + int nducs(); + bool set_format(unsigned int format); + static unsigned int make_format(int width=16, int shift=0, + bool want_q=true, bool bypass_halfband=false); + static int format_width(unsigned int format); + static int format_shift(unsigned int format); + static bool format_want_q(unsigned int format); + static bool format_bypass_halfband(unsigned int format); + %rename(_real_tune) tune; + bool tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result); + %rename(_real_pick_rx_subdevice) pick_rx_subdevice(); + usrp_subdev_spec pick_rx_subdevice(); +}; diff --git a/gr-usrp/src/usrp1_source_c.cc b/gr-usrp/src/usrp_source_c.cc index a5b82ab72..71ca1e0d7 100644 --- a/gr-usrp/src/usrp1_source_c.cc +++ b/gr-usrp/src/usrp_source_c.cc @@ -24,15 +24,15 @@ #include "config.h" #endif -#include <usrp1_source_c.h> +#include <usrp_source_c.h> #include <gr_io_signature.h> #include <usrp_standard.h> #include <usrp_bytesex.h> static const int NBASIC_SAMPLES_PER_ITEM = 2; // I & Q -usrp1_source_c_sptr -usrp1_make_source_c (int which_board, +usrp_source_c_sptr +usrp_make_source_c (int which_board, unsigned int decim_rate, int nchan, int mux, @@ -43,7 +43,7 @@ usrp1_make_source_c (int which_board, const std::string firmware_filename ) throw (std::runtime_error) { - return usrp1_source_c_sptr (new usrp1_source_c (which_board, + return usrp_source_c_sptr (new usrp_source_c (which_board, decim_rate, nchan, mux, @@ -56,7 +56,7 @@ usrp1_make_source_c (int which_board, } -usrp1_source_c::usrp1_source_c (int which_board, +usrp_source_c::usrp_source_c (int which_board, unsigned int decim_rate, int nchan, int mux, @@ -66,7 +66,7 @@ usrp1_source_c::usrp1_source_c (int which_board, const std::string fpga_filename, const std::string firmware_filename ) throw (std::runtime_error) - : usrp1_source_base ("usrp1_source_c", + : usrp_source_base ("usrp_source_c", gr_make_io_signature (1, 1, sizeof (gr_complex)), which_board, decim_rate, nchan, mux, mode, fusb_block_size, fusb_nblocks, @@ -74,13 +74,13 @@ usrp1_source_c::usrp1_source_c (int which_board, { } -usrp1_source_c::~usrp1_source_c () +usrp_source_c::~usrp_source_c () { // NOP } int -usrp1_source_c::ninput_bytes_reqd_for_noutput_items (int noutput_items) +usrp_source_c::ninput_bytes_reqd_for_noutput_items (int noutput_items) { return noutput_items * NBASIC_SAMPLES_PER_ITEM * sizeof_basic_sample(); } @@ -90,7 +90,7 @@ usrp1_source_c::ninput_bytes_reqd_for_noutput_items (int noutput_items) * complex output stream. */ void -usrp1_source_c::copy_from_usrp_buffer (gr_vector_void_star &output_items, +usrp_source_c::copy_from_usrp_buffer (gr_vector_void_star &output_items, int output_index, int output_items_available, int &output_items_produced, diff --git a/gr-usrp/src/usrp1_source_c.h b/gr-usrp/src/usrp_source_c.h index 0d6e50e03..39a282b8d 100644 --- a/gr-usrp/src/usrp1_source_c.h +++ b/gr-usrp/src/usrp_source_c.h @@ -20,40 +20,40 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_USRP1_SOURCE_C_H -#define INCLUDED_USRP1_SOURCE_C_H +#ifndef INCLUDED_USRP_SOURCE_C_H +#define INCLUDED_USRP_SOURCE_C_H -#include <usrp1_source_base.h> +#include <usrp_source_base.h> #include <stdexcept> class usrp_standard_rx; -class usrp1_source_c; -typedef boost::shared_ptr<usrp1_source_c> usrp1_source_c_sptr; +class usrp_source_c; +typedef boost::shared_ptr<usrp_source_c> usrp_source_c_sptr; // public shared_ptr constructor -usrp1_source_c_sptr -usrp1_make_source_c (int which_board, - unsigned int decim_rate, - int nchan, - int mux, - int mode, - int fusb_block_size, - int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename +usrp_source_c_sptr +usrp_make_source_c (int which_board=0, + unsigned int decim_rate=16, + int nchan = 1, + int mux = -1, + int mode = 0, + int fusb_block_size = 0, + int fusb_nblocks = 0, + const std::string fpga_filename = "", + const std::string firmware_filename = "" ) throw (std::runtime_error); /*! * \brief interface to Universal Software Radio Peripheral Rx path (Rev 1) */ -class usrp1_source_c : public usrp1_source_base { +class usrp_source_c : public usrp_source_base { private: - friend usrp1_source_c_sptr - usrp1_make_source_c (int which_board, + friend usrp_source_c_sptr + usrp_make_source_c (int which_board, unsigned int decim_rate, int nchan, int mux, @@ -65,7 +65,7 @@ class usrp1_source_c : public usrp1_source_base { ) throw (std::runtime_error); protected: - usrp1_source_c (int which_board, + usrp_source_c (int which_board, unsigned int decim_rate, int nchan, int mux, @@ -87,7 +87,7 @@ class usrp1_source_c : public usrp1_source_base { int &bytes_read); public: - ~usrp1_source_c (); + ~usrp_source_c (); }; -#endif /* INCLUDED_USRP1_SOURCE_C_H */ +#endif /* INCLUDED_USRP_SOURCE_C_H */ diff --git a/gr-usrp/src/usrp_source_c.i b/gr-usrp/src/usrp_source_c.i new file mode 100644 index 000000000..499f7f740 --- /dev/null +++ b/gr-usrp/src/usrp_source_c.i @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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 version 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. + */ + +%{ +#include "usrp_source_c.h" +%} + +GR_SWIG_BLOCK_MAGIC(usrp,source_c) + +class usrp_source_c; +typedef boost::shared_ptr<usrp_source_c> usrp_source_c_sptr; + +usrp_source_c_sptr +usrp_make_source_c(int which=0, + unsigned int decim_rate=16, + int nchan=1, + int mux=-1, + int mode=0, + int fusb_block_size=0, + int fusb_nblocks=0, + const std::string fpga_filename="", + const std::string firmware_filename="" + ) throw (std::runtime_error); + +class usrp_source_c : public usrp_source_base +{ +private: + usrp_source_c() throw (std::runtime_error); +}; diff --git a/gr-usrp/src/usrp1_source_s.cc b/gr-usrp/src/usrp_source_s.cc index 8295d929b..f20384599 100644 --- a/gr-usrp/src/usrp1_source_s.cc +++ b/gr-usrp/src/usrp_source_s.cc @@ -24,15 +24,15 @@ #include "config.h" #endif -#include <usrp1_source_s.h> +#include <usrp_source_s.h> #include <gr_io_signature.h> #include <usrp_standard.h> #include <usrp_bytesex.h> static const int NBASIC_SAMPLES_PER_ITEM = 1; -usrp1_source_s_sptr -usrp1_make_source_s (int which_board, +usrp_source_s_sptr +usrp_make_source_s (int which_board, unsigned int decim_rate, int nchan, int mux, @@ -43,7 +43,7 @@ usrp1_make_source_s (int which_board, const std::string firmware_filename ) throw (std::runtime_error) { - return usrp1_source_s_sptr (new usrp1_source_s (which_board, + return usrp_source_s_sptr (new usrp_source_s (which_board, decim_rate, nchan, mux, @@ -56,7 +56,7 @@ usrp1_make_source_s (int which_board, } -usrp1_source_s::usrp1_source_s (int which_board, +usrp_source_s::usrp_source_s (int which_board, unsigned int decim_rate, int nchan, int mux, @@ -66,7 +66,7 @@ usrp1_source_s::usrp1_source_s (int which_board, const std::string fpga_filename, const std::string firmware_filename ) throw (std::runtime_error) - : usrp1_source_base ("usrp1_source_s", + : usrp_source_base ("usrp_source_s", gr_make_io_signature (1, 1, sizeof (short)), which_board, decim_rate, nchan, mux, mode, fusb_block_size, @@ -75,13 +75,13 @@ usrp1_source_s::usrp1_source_s (int which_board, { } -usrp1_source_s::~usrp1_source_s () +usrp_source_s::~usrp_source_s () { // NOP } int -usrp1_source_s::ninput_bytes_reqd_for_noutput_items (int noutput_items) +usrp_source_s::ninput_bytes_reqd_for_noutput_items (int noutput_items) { return noutput_items * NBASIC_SAMPLES_PER_ITEM * sizeof_basic_sample(); } @@ -91,7 +91,7 @@ usrp1_source_s::ninput_bytes_reqd_for_noutput_items (int noutput_items) * short output stream. */ void -usrp1_source_s::copy_from_usrp_buffer (gr_vector_void_star &output_items, +usrp_source_s::copy_from_usrp_buffer (gr_vector_void_star &output_items, int output_index, int output_items_available, int &output_items_produced, diff --git a/gr-usrp/src/usrp1_source_s.h b/gr-usrp/src/usrp_source_s.h index 35beb42a8..6f7f98b2b 100644 --- a/gr-usrp/src/usrp1_source_s.h +++ b/gr-usrp/src/usrp_source_s.h @@ -20,42 +20,42 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_USRP1_SOURCE_S_H -#define INCLUDED_USRP1_SOURCE_S_H +#ifndef INCLUDED_USRP_SOURCE_S_H +#define INCLUDED_USRP_SOURCE_S_H -#include <usrp1_source_base.h> +#include <usrp_source_base.h> #include <stdexcept> class usrp_standard_rx; -class usrp1_source_s; -typedef boost::shared_ptr<usrp1_source_s> usrp1_source_s_sptr; +class usrp_source_s; +typedef boost::shared_ptr<usrp_source_s> usrp_source_s_sptr; // public shared_ptr constructor -usrp1_source_s_sptr -usrp1_make_source_s (int which_board, - unsigned int decim_rate, - int nchan, - int mux, - int mode, - int fusb_block_size, - int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename - ) throw (std::runtime_error); +usrp_source_s_sptr +usrp_make_source_s (int which_board=0, + unsigned int decim_rate=16, + int nchan=1, + int mux=-1, + int mode=0, + int fusb_block_size=0, + int fusb_nblocks=0, + const std::string fpga_filename="", + const std::string firmware_filename="" + ) throw (std::runtime_error); /*! * \brief interface to Universal Software Radio Peripheral Rx path (Rev 1) * * output: 1 stream of short */ -class usrp1_source_s : public usrp1_source_base { +class usrp_source_s : public usrp_source_base { private: - friend usrp1_source_s_sptr - usrp1_make_source_s (int which_board, + friend usrp_source_s_sptr + usrp_make_source_s (int which_board, unsigned int decim_rate, int nchan, int mux, @@ -67,7 +67,7 @@ class usrp1_source_s : public usrp1_source_base { ) throw (std::runtime_error); protected: - usrp1_source_s (int which_board, + usrp_source_s (int which_board, unsigned int decim_rate, int nchan, int mux, @@ -88,7 +88,7 @@ class usrp1_source_s : public usrp1_source_base { int usrp_buffer_length, int &bytes_read); public: - ~usrp1_source_s (); + ~usrp_source_s (); }; -#endif /* INCLUDED_USRP1_SOURCE_S_H */ +#endif /* INCLUDED_USRP_SOURCE_S_H */ diff --git a/gr-usrp/src/usrp_source_s.i b/gr-usrp/src/usrp_source_s.i new file mode 100644 index 000000000..d8b285c99 --- /dev/null +++ b/gr-usrp/src/usrp_source_s.i @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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 version 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. + */ + +%{ +#include "usrp_source_s.h" +%} + +GR_SWIG_BLOCK_MAGIC(usrp,source_s) + +class usrp_source_s; +typedef boost::shared_ptr<usrp_source_s> usrp_source_s_sptr; + +usrp_source_s_sptr +usrp_make_source_s(int which=0, + unsigned int decim_rate=16, + int nchan=1, + int mux=-1, + int mode=0, + int fusb_block_size=0, + int fusb_nblocks=0, + const std::string fpga_filename="", + const std::string firmware_filename="" + ) throw (std::runtime_error); + +class usrp_source_s : public usrp_source_base +{ +private: + usrp_source_s() throw (std::runtime_error); +}; diff --git a/gr-usrp/src/usrp_standard.i b/gr-usrp/src/usrp_standard.i new file mode 100644 index 000000000..7d32cdf81 --- /dev/null +++ b/gr-usrp/src/usrp_standard.i @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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 version 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. + */ + +// FIXME: move to usrp/usrpm component + +%{ +#include <usrp_standard.h> +#include <usrp_spi_defs.h> +#include <usrp_dbid.h> +%} + +%include <usrp_spi_defs.h> +%include <usrp_dbid.h> + +%constant int FPGA_MODE_NORMAL = usrp_standard_rx::FPGA_MODE_NORMAL; +%constant int FPGA_MODE_LOOPBACK = usrp_standard_rx::FPGA_MODE_LOOPBACK; +%constant int FPGA_MODE_COUNTING = usrp_standard_rx::FPGA_MODE_COUNTING; |