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