USRP push-to-talk?

Working on interfacing an external 1296 Mhz transverter to one of my
USRPs
with basic RX and basic TX daughter cards. Has anyone already done
something
like this and established a “standard” way of implementing TX/RX
switching?
Or do I just randomly pick one of the controllable bits to drive the
sequencer’s push to talk input?

Bdale

On Fri, Sep 22, 2006 at 10:44:36PM -0600, Bdale Garbee wrote:

Working on interfacing an external 1296 Mhz transverter to one of my USRPs
with basic RX and basic TX daughter cards. Has anyone already done something
like this and established a “standard” way of implementing TX/RX switching?
Or do I just randomly pick one of the controllable bits to drive the
sequencer’s push to talk input?

Bdale

Hi Bdale,

Two ways come to mind:

(1) just grab an i/o pin, output enable it, and wiggle as you please.

Here are the C++ centric docs

/*!

  • \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);

In python it looks like:

u_rx = usrp.source_c(…)
u_rx.subdev = …

make all pins on the RX d’board on selected side outputs

u_rx._write_oe(u_rx.subdev._which, 0xffff, 0xffff)

This works with either the sink or source.

Etc.

(2) Take advantage of the hooks for “auto T/R switching”.
The RFX boards use this, but it’s ignored by the basic tx and rx.

Here are the low level details extracted from
usrp/firmware/include/fpga_regs_common.h:

# 

# 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.

Assuming you’ve opened the USRP as normal, call the selected subdev
methods like this:

u_tx = usrp.sink_c(...)
u_tx.subdev = ...

u_tx.subdev.set_atr_mask (XXX)
u_tx.subdev.set_atr_txval(YYY)
u_tx.subdev.set_atr_rxval(ZZZ)

There are separate regs for the Tx and Rx halves, so depending on
which pins you want to watch, call this on either u_tx or u_rx.

Also, you still have to output enable the relevant pins as above.

Now of course, all this depends on your application “stalling” the
transmit path unless it’s got something to do. I seem to recall
that somebody built a “stall” block, but in looking through “general”,
I don’t see it. Does this sound familiar to anyone? Johnathan,
weren’t you looking at this? (It might have been a mute/squelch
block, with the same idea).

As I recall it was going to work like this:

stall = gr.stall(sizeof_item)


stall.set_stall(True) # Causes the block to consume all input,
# but produce no output


stall.set_stall(False) # block copies input to output, producing
# and consuming in the normal way

Then your “push to talk” button would just call the set_stall method
as appropriate.

Eric