commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r7352 - in gnuradio/trunk: gr-usrp/src usrp/host/apps


From: jcorgan
Subject: [Commit-gnuradio] r7352 - in gnuradio/trunk: gr-usrp/src usrp/host/apps usrp/host/lib/legacy
Date: Fri, 4 Jan 2008 21:35:42 -0700 (MST)

Author: jcorgan
Date: 2008-01-04 21:35:41 -0700 (Fri, 04 Jan 2008)
New Revision: 7352

Modified:
   gnuradio/trunk/gr-usrp/src/db_xcvr2450.py
   gnuradio/trunk/gr-usrp/src/usrp.py
   gnuradio/trunk/usrp/host/apps/burn-db-eeprom
   gnuradio/trunk/usrp/host/lib/legacy/usrp_dbid.dat
Log:
Merged r7323:7349 from jcorgan/xcvr2450 into trunk.  Ads XCVR 2450 
daughterboard code.  Not fully tested.

Modified: gnuradio/trunk/gr-usrp/src/db_xcvr2450.py
===================================================================
--- gnuradio/trunk/gr-usrp/src/db_xcvr2450.py   2008-01-05 04:14:20 UTC (rev 
7351)
+++ gnuradio/trunk/gr-usrp/src/db_xcvr2450.py   2008-01-05 04:35:41 UTC (rev 
7352)
@@ -19,19 +19,17 @@
 # Boston, MA 02110-1301, USA.
 # 
 
-from gnuradio import usrp1
-import time,math
+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 *
 
-debug_using_gui = False                  # Must be set to True or False
+# Convenience function
+n2s = eng_notation.num_to_str
 
-#if debug_using_gui:
-#    import flexrf_debug_gui
-
 # d'board i/o pin defs
 
 # TX IO Pins
@@ -40,6 +38,8 @@
 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
+TX_OE_MASK = HB_PA_OFF|LB_PA_OFF|ANTSEL_TX1_RX2|ANTSEL_TX2_RX1|TX_EN
+TX_SAFE_IO = HB_PA_OFF|LB_PA_OFF|ANTSEL_TX1_RX2
 
 # RX IO Pins
 LOCKDET = (1 << 15)         # This is an INPUT!!!
@@ -53,65 +53,94 @@
 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.
-"""
 
-class xcvr2450_base(db_base.db_base):
-    """
-    Abstract base class for all xcvr2450 boards.
+# ------------------------------------------------------------------------
+# 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.
 
-    Derive board specific subclasses from db_xcvr2450_base_{tx,rx}
-    """
+_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):
-        """
-        @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)
+        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]
 
-        # FIXME -- the write reg functions don't work with 0xffff for masks
-        self._rx_write_oe(int(), 0x7fff)
-        self._rx_write_io((), ())
+        # 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._tx_write_oe((), 0x7fff)
-        self._tx_write_io((), ())
-        
-        self.mimo = 1
-        self.cp_current = 0  # 0 = 2mA, 1 = 4mA
-        self.ref_div = 4  # 1 to 7
+        self.txgain = 63           # 0 = min, 63 = max
 
-        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.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 = 0 # 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
+        # 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)
         
-        self.rxgain = 64
-        self.txgain = 32
-
-        self.set_freq(2.45e6)
-        self.set_auto_tr(True)
-        
-        #  SPI reset here
+        # Initialize chipset
+        # TODO: perform reset sequence to ensure power up defaults
         self.set_reg_standby()
         self.set_reg_bandselpll()
         self.set_reg_cal()
@@ -121,472 +150,363 @@
         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)
         
-    def set_reg_standby(self):   # reg 2
-        self.reg_standby = (self.mimo<<17)|(1<<16)|(1<<6)|(1<<5)|(1<<4)|2
+
+    # --------------------------------------------------------------------
+    # 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)
         
-    def set_reg_bandselpll(self):   # reg 5
-        if self.freq > 5.4e9:
-            self.highband = 1
-            self.five_gig = 1
-        else if self.freq > 3e9:
-            self.highband = 0
-            self.five_gig = 1
-        else:
-            self.highband = 0
-            self.five_gig = 0
-        self.reg_bandselpll = 
(self.mimo<<17)|(1<<16)|(1<<15)|(1<<11)|(self.highband<<10)| \
-                              
(self.cp_current<<9)|(self.cp_current<<5)|(self.five_gig<<4)|5
+    # 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)
-        
-    def set_reg_cal(self):   # reg 6
-        # FIXME  do calibration
+     
+
+    # 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<<9)|(self.rxlpf_bw<<7)|(self.rxlpf_fine<<4)|7
+        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_serial<<16)|(1<<15)|(1<<14)|(1<<9)|(1<<4)|8
+        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.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.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.rxgain<<4)|11
+        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.reg_txgain = (self.txgain<<4) | 12
         self.send_reg(self.reg_txgain)
-        
-    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() & LOCKDET:
-            return True
-        else:      # Give it a second chance
-            if self._rx_read_io() & LOCKDET:
-                return True
-            else:
-                return False
 
-    def send_reg(self,s):
-        self._u._write_spi(0, self.spi_enable, self.spi_format, s)
-        print "Set Reg %d: Value %x: \n" % ((s&15),s)
-        
-    # Both sides need access to the Rx pins.
-    # Write them directly, bypassing the convenience routines.
-    # (Sort of breaks modularity, but will work...)
+    # 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)
 
-    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))
+    # --------------------------------------------------------------------
+    # 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 _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_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 _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_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 _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_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])
+    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 _refclk_freq(self):
-        return float(self._u.fpga_master_clock_freq())/self._refclk_divisor()
+    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 _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 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 _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 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 is_quadrature(self):
-        """
-        Return True if this board requires both I & Q analog channels.
+    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))
 
-        This bit of info is useful when setting up the USRP Rx mux register.
-        """
-        return True
+    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))
 
-class xcvr2450_tx(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.
-        """
-        xcvr2450_base.__init__(self, usrp, which)
+    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.
 
-        # 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
+        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
+        io_tx_while_tx = tx_pa_sel|tx_antsel|TX_EN
+        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)
 
-        set_atr_mask(v)
-        set_atr_txval(v)
-        set_atr_rxval(v)
-        set_atr_tx_delay(v)
-        set_atr_rx_delay(v)
+    # --------------------------------------------------------------------
+    # These methods set control the high-level operating parameters.
 
-        #  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
-        xcvr2450_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)
+    def set_freq(self, target_freq):
+        if target_freq > 3e9:
+            self.five_gig = 1
+            self.ref_div = 3
+            scaler = 4.0/5.0
         else:
-            self.set_atr_mask (0)
-            self.set_atr_txval(0)
-            self.set_atr_rxval(0)
+            self.five_gig = 0
+            self.ref_div = 4
+            scaler = 4.0/3.0;
 
-    def set_enable(self, on):
-        """
-        Enable transmitter if on is True
-        """
-        if on:
-            v = 0
+        if target_freq > 5.4e9:
+            self.highband = 1
         else:
-            v = RX_TXN
-        self._u.write_io(self._which, v, RX_TXN)
+            self.highband = 0
 
-    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
+        vco_freq = target_freq*scaler;
+        ref_clk = self.u.fpga_master_clock_freq()  # Assumes AD9515 is bypassed
+        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
 
-    def lo_offset(self):
-       """
-       Get amount by which LO is offset from requested tuning frequency.
-       
-       @returns Offset in Hz
-       """
-       return self._lo_offset
-       
-    def gain_range(self):
-        """
-        Return range of gain that can be set by this d'board.
+        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))
 
-        @returns (min_gain, max_gain, step_size)
-        Where gains are expressed in decibels (your mileage may vary)
+        self.set_gpio()
+        self.set_reg_int_divider()
+        self.set_reg_frac_divider()
+        self.set_reg_bandselpll()
 
-        Gain is controlled by a VGA in the output amplifier, not the PGA
-        """
-        return (0, 63, 0.1)
+        ok = self.lock_detect()
+        print "lock detect:", ok
+        return (ok, actual_freq)
 
-    def set_gain(self, gain):
+    def lock_detect(self):
         """
-        Set the gain.
-        
-        @param gain:  gain in decibels
-        @returns True/False
+        @returns: the value of the VCO/PLL lock detect bit.
+        @rtype: 0 or 1
         """
-        gain = int(gain)
-        if (gain>gain_range()[1]) or (gain<gain_range()[0]):
-            raise ValueError, "TX Gain out of range."
-        
+        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
 
-class xcvr2450_rx(wbx_base):
+    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: 0 or 1 corresponding to side RX_A or RX_B respectively.
+        @param which: which side: 0 or 1 corresponding to side A or B 
respectively
+        @type which: int
         """
-        wbx_base.__init__(self, usrp, which)
+        # sets _u  _which _tx and _slot
+        db_base.db_base.__init__(self, usrp, which)
+        self.xcvr = _get_or_make_xcvr2450(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):
+    def set_freq(self, target_freq):
         """
-        Specify which antenna port to use for reception.
-        @param which_antenna: either 'TX/RX' or 'RX2'
+        @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 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'"
+        return self.xcvr.set_freq(target_freq)
 
-    def set_gain(self, gain):
+    def is_quadrature(self):
         """
-        Set the gain.
+        Return True if this board requires both I & Q analog channels.
 
-        @param gain:  gain in decibels
-        @returns True/False
+        This bit of info is useful when setting up the USRP Rx mux register.
         """
-        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))
+        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 freq_range(self):
+       return (2.4e9, 6e9, 1e6)
 
-    def lo_offset(self):
-       """
-       Get amount by which LO is offset from requested tuning frequency.
-       
-       @returns Offset in Hz
-       """
-       return self._lo_offset
+    def set_freq(self, target_freq):
+        return self.xcvr.set_freq(target_freq)
 
+# ----------------------------------------------------------------
 
-    def i_and_q_swapped(self):
+class db_xcvr2450_tx(db_xcvr2450_base):
+    def __init__(self, usrp, which):
         """
-        Return True if this is a quadrature device and ADC 0 is Q.
+        @param usrp: instance of usrp.sink_c
+        @param which: 0 or 1 corresponding to side TX_A or TX_B respectively.
         """
-        return True    
+       print "db_xcvr2450_tx: __init__"
+        db_xcvr2450_base.__init__(self, usrp, which)
 
-    def __init__(self):
-        pass
+    def gain_range(self):
+       return (0, 30, (30.0/63.0))
 
-    def _compute_regs(self, freq):
-        """
-        Determine values of R, control, and N registers, along with actual 
freq.
+    def set_gain(self, gain):
+        return self.xcvr.set_tx_gain(gain)
         
-        @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):
+class db_xcvr2450_rx(db_xcvr2450_base):
+    def __init__(self, usrp, which):
         """
-        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
+        @param usrp: instance of usrp.source_c
+        @param which: 0 or 1 corresponding to side RX_A or RX_B respectively.
         """
-        self._write_R(R)
-        self._write_func(control)
-        self._write_init(control)
-        self._write_N(N)
+       print "db_xcvr2450_rx: __init__"
+        db_xcvr2450_base.__init__(self, usrp, which)
 
-    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"
-
     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)
+       return (0.0, 92.0, 1)
 
-#----------------------------------------------------------------------
-class _lo_common(_ADF410X_common):
-
-    def freq_range(self):           # FIXME
-        return (50e6, 1000e6, 16e6)
-
-    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', 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)
-
+    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),))
-
-# ------------------------------------------------------------------------
-# 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.
-
-

Modified: gnuradio/trunk/gr-usrp/src/usrp.py
===================================================================
--- gnuradio/trunk/gr-usrp/src/usrp.py  2008-01-05 04:14:20 UTC (rev 7351)
+++ gnuradio/trunk/gr-usrp/src/usrp.py  2008-01-05 04:35:41 UTC (rev 7352)
@@ -60,6 +60,7 @@
 import db_flexrf_mimo
 import db_tv_rx
 import db_wbx
+import db_xcvr2450
 
 def _look_for_usrp(which):
     """

Modified: gnuradio/trunk/usrp/host/apps/burn-db-eeprom
===================================================================
--- gnuradio/trunk/usrp/host/apps/burn-db-eeprom        2008-01-05 04:14:20 UTC 
(rev 7351)
+++ gnuradio/trunk/usrp/host/apps/burn-db-eeprom        2008-01-05 04:35:41 UTC 
(rev 7352)
@@ -64,6 +64,7 @@
     'lftx'            : ((LF_TX, 0x0000),           None),
     'lfrx'            : (None,                      (LF_RX, 0x0000)),
     'wbx_lo'          : ((WBX_LO_TX, 0x0000),       (WBX_LO_RX, 0x0000)),
+    'xcvr2450'        : ((XCVR2450_TX, 0x0000),       (XCVR2450_RX, 0x0000)),
     'experimental_tx' : ((EXPERIMENTAL_TX, 0x0000), None),
     'experimental_rx' : (None,                      (EXPERIMENTAL_RX, 0x0000)),
     }

Modified: gnuradio/trunk/usrp/host/lib/legacy/usrp_dbid.dat
===================================================================
--- gnuradio/trunk/usrp/host/lib/legacy/usrp_dbid.dat   2008-01-05 04:14:20 UTC 
(rev 7351)
+++ gnuradio/trunk/usrp/host/lib/legacy/usrp_dbid.dat   2008-01-05 04:35:41 UTC 
(rev 7352)
@@ -73,5 +73,8 @@
 "WBX LO TX"            0x0050
 "WBX LO RX"            0x0051
 
+"XCVR2450 Tx"          0x0060
+"XCVR2450 Rx"          0x0061
+
 "Experimental Tx"      0xfffe
 "Experimental Rx"      0xffff





reply via email to

[Prev in Thread] Current Thread [Next in Thread]