# 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
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.
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)
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):
@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.
"""
return 1
+ # ----------------------------------------------------------------
+
def set_freq(self, freq):
"""
@returns (ok, actual_baseband_freq) where:
@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
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):
"""
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):
"""
@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
@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
# ----------------------------------------------------------------
# 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
@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
@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
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),
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):
_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
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)
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)
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)
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)
-