diff options
Diffstat (limited to 'gr-usrp/src/db_xcvr2450.py')
-rw-r--r-- | gr-usrp/src/db_xcvr2450.py | 538 |
1 files changed, 0 insertions, 538 deletions
diff --git a/gr-usrp/src/db_xcvr2450.py b/gr-usrp/src/db_xcvr2450.py deleted file mode 100644 index ec0587635c..0000000000 --- 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),)) |