fixed behavior around VCO changeover point (5.275GHz), and commented out debugging...
[debian/gnuradio] / gr-usrp / src / db_wbx.py
index 7bc0090627c83fdba3f960130cc24d06a915c85f..72b3e35c13c09c14869c50dd46cb4871027140e5 100644 (file)
@@ -34,11 +34,12 @@ debug_using_gui = False                  # Must be set to True or False
 #    import flexrf_debug_gui
 
 # d'board i/o pin defs
-# Tx and Rx have shared defs, but different i/o regs
 
 # 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
@@ -59,6 +60,17 @@ 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.
@@ -77,8 +89,14 @@ class wbx_base(db_base.db_base):
         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
+        # 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)
         
@@ -91,9 +109,8 @@ class wbx_base(db_base.db_base):
 
 
     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._enable_refclk(False)                       # turn off refclk
+        #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):
@@ -101,14 +118,43 @@ class wbx_base(db_base.db_base):
         @returns: the value of the VCO/PLL lock detect bit.
         @rtype: 0 or 1
         """
-        if self._u.read_io(self._which) & PLL_LOCK_DETECT:
+        if self._rx_read_io() & PLL_LOCK_DETECT:
             return True
         else:      # Give it a second chance
-            if self._u.read_io(self._which) & PLL_LOCK_DETECT:
+            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.
@@ -131,6 +177,8 @@ class wbx_base(db_base.db_base):
         """
         return 1
     
+    # ----------------------------------------------------------------
+    
     def set_freq(self, freq):
         """
         @returns (ok, actual_baseband_freq) where:
@@ -182,11 +230,9 @@ class wbx_base_tx(wbx_base):
         @param which: 0 or 1 corresponding to side TX_A or TX_B respectively.
         """
         wbx_base.__init__(self, usrp, which)
-        self.spi_enable = (SPI_ENABLE_TX_A, SPI_ENABLE_TX_B)[which]
 
-        # power up the transmit side, but set antenna to receive
-        self._u._write_oe(self._which,(TX_POWER|RX_TXN), 0xffff)
-        self._u.write_io(self._which, (TX_POWER|RX_TXN), (TX_POWER|RX_TXN))
+        # 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
@@ -194,7 +240,7 @@ class wbx_base_tx(wbx_base):
 
     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))
+        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):
@@ -211,11 +257,13 @@ class wbx_base_tx(wbx_base):
         """
         Enable transmitter if on is True
         """
+        mask = RX_TXN|TX_ENB_MIX|TX_ENB_VGA
+        print "HERE!!!!"
         if on:
-            v = 0
+            self._u.write_io(self._which, TX_ENB_MIX|TX_ENB_VGA, mask)
         else:
-            v = RX_TXN
-        self._u.write_io(self._which, v, RX_TXN)
+            self._u.write_io(self._which, RX_TXN, mask)
+
 
     def set_lo_offset(self, offset):
        """
@@ -240,17 +288,13 @@ class wbx_base_rx(wbx_base):
         @param which: 0 or 1 corresponding to side RX_A or RX_B respectively.
         """
         wbx_base.__init__(self, usrp, which)
-        self.spi_enable = (SPI_ENABLE_RX_A, SPI_ENABLE_RX_B)[which]
         
-        self._u._write_oe(self._which, (RX2_RX1N|RXENABLE), 0xffff)
-        self._u.write_io(self._which,  (0|RXENABLE), (RX2_RX1N|RXENABLE))
-
         # set up for RX on TX/RX port
         self.select_rx_antenna('TX/RX')
 
         self.bypass_adc_buffers(True)
 
-        self._lo_offset = -4e6
+        self._lo_offset = 0.0
 
     def __del__(self):
         # Power down
@@ -318,7 +362,13 @@ class wbx_base_rx(wbx_base):
        @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
 
 # ----------------------------------------------------------------
 
@@ -337,12 +387,12 @@ class _ADF410X_common(object):
         # 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 = 7      # bits 20,19,18 CP Gain = 5mA
-        self.CP1 = 7      # bits 17,16,15 CP Gain = 5mA
+        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 = 1      # bit 7         Phase detector polarity, Positive=1
+        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
@@ -353,16 +403,20 @@ class _ADF410X_common(object):
         
         @param freq: target frequency in Hz
         @type freq: float
-        @returns: (R, control, N, actual_freq)
+        @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
@@ -398,8 +452,8 @@ class _ADF410X_common(object):
         @type control: int
         """
         self._write_R(R)
-        self._write_func(func)
-        self._write_init(init)
+        self._write_func(control)
+        self._write_init(control)
         if self.first:
             time.sleep(0.010)
             self.first = False
@@ -415,7 +469,7 @@ class _ADF410X_common(object):
         self._write_it((func & ~0x3) | 2)
 
     def _write_init(self, init):
-        self._write_it((func & ~0x3) | 3)
+        self._write_it((init & ~0x3) | 3)
 
     def _write_it(self, v):
         s = ''.join((chr((v >> 16) & 0xff),
@@ -428,8 +482,12 @@ class _ADF410X_common(object):
             return 8
         elif self.P == 1:
             return 16
-        else:
+        elif self.P == 2:
             return 32
+        elif self.P == 3:
+            return 64
+        else:
+            raise ValueError, "Prescaler out of range"
 
 #----------------------------------------------------------------------
 class _lo_common(_ADF410X_common):
@@ -437,12 +495,12 @@ class _lo_common(_ADF410X_common):
         _ADF410X_common.__init__(self)
 
         # Band-specific R-Register Values
-        self.R_DIV = 16  # bits 15:2
+        self.R_DIV = 4  # 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
+        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
@@ -450,6 +508,9 @@ class _lo_common(_ADF410X_common):
         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)
 
@@ -457,26 +518,50 @@ class _lo_common(_ADF410X_common):
         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 value not in (1,2,4,8):
+            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 value not in (2,4,8,18):
+            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
-        
-        self._u.write_io(self._which, ((self.main_div<<SELA0) | (self.aux_div<<SELB0)),
-                         (SELA0|SELA1|SELB0|SELB1))   # only works on RX
 
+        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):
-        self.power_on = ~POWER_UP
-        self.power_off = ~POWER_UP    # powering it off kills the serial bus
         wbx_base_tx.__init__(self, usrp, which)
         _lo_common.__init__(self)
         
@@ -502,19 +587,21 @@ class db_wbx_lo_tx(_lo_common, wbx_base_tx):
         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*(V_maxgain-V_mingain)/(maxgain-mingain) + V_mingain)*4096/V_fullscale
+        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):
-        self.power_on = ~POWER_UP
-        self.power_off = ~POWER_UP   # Powering it off kills the serial bus
         wbx_base_rx.__init__(self, usrp, which)
         _lo_common.__init__(self)
 
@@ -533,11 +620,3 @@ db_instantiator.add(usrp_dbid.WBX_LO_TX, lambda usrp, which : (db_wbx_lo_tx(usrp
 db_instantiator.add(usrp_dbid.WBX_LO_RX, lambda usrp, which : (db_wbx_lo_rx(usrp, which),))
 
 
-#        freq += self._lo_offset
-#        
-#        R, N, control, actual_freq = self._compute_regs(freq)
-#        if R==0:
-#            return(False,0)
-#        self._write_all(R, N, control)
-#        return (self._lock_detect(), actual_freq)
-