Half duplex set_auto_tx timing problems

Hi Guys!

I am trying to develop a half duplex application with N210 and SBX
daughterboard with the latest (git head) gnuradio that needs precise
TX/RX switching times (like in TDMA) in the order of a few samples
(nanoseconds). I have played with the tx_time, tx_sob, tx_eob tags and
they do not seem to solve the problem. My findings so far are:

  1. tx_sob/tx_eob does not influence anything related to the TX/RX
    switch, it only controls the grouping of the TX data stream into UDP
    packets (tx_sob starts a new UDP packet, tx_eof pushes out the last
    UDP packet even if it is not full). The same is true for USRP1 but
    that uses USB packets.

  2. tx_time is translated into the metadata_t struct in the host code
    and then it is translated into VITA packet time stamps (converts the
    fractional second part into sample numbers). The integer part of
    tx_time seems to be discarded, but I still get “L” (timestamp in the
    past error), so I do not understand why the FPGA will not wait a
    little if only the factional part is considered.

  3. I have found this discussion online about TX/RX switch:

http://lists.gnu.org/archive/html/discuss-gnuradio/2009-03/msg00034.html

where Matt E. said that “The act of transmitting turns off the
receiver, so no amount of software will ever change that.” in
discussing half duplex operation. Now it is not clear if that comment
is also applicable to the N210 and SBX, and what does he mean by “the
act of transmitting”. Specifically, if I send a packet with tx_time in
the future, does the FPGA switches to RX mode while it is waiting?

  1. We have looked up the FPGA code, and it seems that the timing is
    implemented in a short FIFO when handling the VITA UDP packets. I
    could not trace the code further, and I do not see the logic in the
    FPGA code that does the automatic switching between RX and TX. Where
    is that implemented?

  2. Is it true that to switch between RX and TX then the host has to
    issue a command (poke register) to update the appropriate pin on the
    FPGA? If so, then how can you time the update of that pin to specific
    sample numbers?

  3. Is it true that the firmware soft core has nothing to do with the
    time sensitive data and control handling, so in particular the
    provided register access features (if I saw them correctly) are not
    used in timing sensitive paths?

  4. It is not clear how the gnuradio UHD sink block handles the sample
    rate value in the presence of tx_time tags. For example, if I generate
    10 small packets each of which has a tx_sob,tx_time and tx_eob and 0.1
    sec delay between the times, and all of these small packets are put
    into the transmit fifo at once, then what happens? What is the rate
    that the UHD sink block will consume this data? It cannot be the
    sample rate, because these tags point to the future, so the
    consumption rate should be reduced, but is it what happens? Will the
    code switch the TX/RX switch to RX between the small packets if all
    those are already in the queue?

I hope someone has answers to these questions. Searching the internet
turned up next to nothing on these subjects.

Miklos

If you choose TX/RX as both your transmit and receive antenna, the FPGA
will switch between TX and RX automatically. It’ll switch to TX when it
receives samples to send.

-John

packets (tx_sob starts a new UDP packet, tx_eof pushes out the last
3) I have found this discussion online about TX/RX switch:
4) We have looked up the FPGA code, and it seems that the timing is
6) Is it true that the firmware soft core has nothing to do with the
sample rate, because these tags point to the future, so the
Discuss-gnuradio mailing list
[email protected]
Discuss-gnuradio Info Page

Some very quick comments.

I don’t think you’re going to achieve nanosecond-scale TX/RX switching
times, no matter how much you tweak the FPGA. The switches themselves
introduce, I’m estimating, a 50nsec delay all by themselves.

In UHD, the ATR state machine is programmed during daughtercard setup by
the “driver” for a given daughtercard – this allows somewhat different
behaviour for cards that are hardware-constrained to be half-duplex
(like XCVR2450). In the daughtercard drivers, you’ll see things like:

this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX,
dboard_iface::ATR_REG_IDLE, band_sel | ad9515div | TX_DIS_TXIO);

Which are setting up ATR registers.

But that being said, I think you’re best to run in a mode where you have
a separate RX antenna if you require nanosecond-scale turnaround times.
You’ll end up receiving your own transmissions, but that’s fairly
easy to cope with, I imagine.

If you setup to use (WBX example) RX2 for RX and TX/RX for TX, then
there’s no switching involved. You just have to ignore your own
transmissions.


Marcus L.
Principal Investigator
Shirleys Bay Radio Astronomy Consortium

Hi John,

Thanks for you quick reply, but you did not answer any of my
questions. Will the FPGA switch from TX to RX when it has already
received from the host a UDP packet with a timestamp tag (tx_time)
that is in the future? Also, when exactly will the RX to TX switch
occur?

Miklos

introduce deterministic delays, I can cope with that.

You mention that the state machine is set up in the daughter card
setup driver. Is this the file in
“host/lib/usrp/dboard/db_sbx_common.cpp” for the SBX board? Is this
code used for USRP2 and not only for USRP1?

Best,
Miklos

Yes, as far as I know. Josh could probably comment in more detail, but
he’s at a conference today.

I wouldn’t recommend mucking about too much with the ATR code, since I
think it’s possible to end up in a “TX connected to RX” state if you’re
not careful.


Marcus L.
Principal Investigator
Shirleys Bay Radio Astronomy Consortium

Hi Marcus,

Thanks for the quick comments. Yes, I totally agree that using full
duplex with RX2 and TX/RX would be the ideal way to go, and as you say
I can easily ignore and synchronize with my own transmissions. The
problem is that I am required to use a single antenna, so I have to do
a half duplex solution with all its warts and synchronization
problems.

As for the switching time, I do not care if the switches (or the FPGA)
introduce deterministic delays, I can cope with that.

You mention that the state machine is set up in the daughter card
setup driver. Is this the file in
“host/lib/usrp/dboard/db_sbx_common.cpp” for the SBX board? Is this
code used for USRP2 and not only for USRP1?

Best,
Miklos

" It’ll switch to TX when it receives samples to send."

There may be some small [intentional] delays, but the FPGA will switch
to
Tx on the first sample to be sent. Josh can specify the timing in more
detail.

You see “L” because you are sending your bursts far enough advance. In
my
applications, the bursts are sent to the USRP about ~5ms before the
actual
transmission. And as far as I know you can’t just use the fractional
seconds. The FPGA won’t switch to TX when it hits tx_time and starts
clock
out the samples.

-John

Hi Marcus,

Thanks for the quick comments. Yes, I totally agree that using full
duplex with RX2 and TX/RX would be the ideal way to go, and as you say
I can easily ignore and synchronize with my own transmissions. The
problem is that I am required to use a single antenna, so I have to do
a half duplex solution with all its warts and synchronization
problems.

As for the switching time, I do not care if the switches (or the FPGA)
introduce deterministic delays, I can cope with that.

You mention that the state machine is set up in the daughter card
setup driver. Is this the file in
“host/lib/usrp/dboard/db_sbx_common.cpp” for the SBX board? Is this
code used for USRP2 and not only for USRP1?

Best,
Miklos

You see “L” because you are sending your bursts far enough advance

should have read:

“aren’t sending your bursts far enough in advance”

Hi John,

On Mon, Jun 3, 2013 at 8:00 PM, John M. [email protected]
wrote:

" It’ll switch to TX when it receives samples to send."

There may be some small [intentional] delays, but the FPGA will switch to
Tx on the first sample to be sent. Josh can specify the timing in more
detail.

You say that it switch from TX to RX if the next timestamp is in the
future and switch from RX to TX just when the timestamp is triggered.

You see “L” because you are sending your bursts far enough advance. In my
applications, the bursts are sent to the USRP about ~5ms before the actual
transmission.

Ok, I will try to send them 5ms before transmit time, that should
work. But then synchronizing the FPGA clock with the PC clock will be
more trouble.

And as far as I know you can’t just use the fractional
seconds. The FPGA won’t switch to TX when it hits tx_time and starts clock
out the samples.

You say that the FPGA will NOT change from RX to TX? This contradicts
the other sentences you wrote.

Miklos

You say that it switch from TX to RX if the next timestamp is in the
future and switch from RX to TX just when the timestamp is triggered.

You see “L” because you are sending your bursts far enough advance. In my
applications, the bursts are sent to the USRP about ~5ms before the actual
transmission.
Ok, I will try to send them 5ms before transmit time, that should
work. But then synchronizing the FPGA clock with the PC clock will be
more trouble.

You can use set_time_now() to set the FPGA clock to whatever you want.

In fact, without such synchronization of ideas of time, it’s pretty hard
to build a TDMA-type system. The USRP and the host delivering
time-stamped
samples have to agree on what time it is. If you have 1PPS pulses
going in, you can use set_time_next_pps() to align times on the next PPS
pulse.


Marcus L.
Principal Investigator
Shirleys Bay Radio Astronomy Consortium

Hi Marcus,

On Mon, Jun 3, 2013 at 8:15 PM, Marcus D. Leech [email protected]
wrote:

work. But then synchronizing the FPGA clock with the PC clock will be
more trouble.

You can use set_time_now() to set the FPGA clock to whatever you want.

In fact, without such synchronization of ideas of time, it’s pretty hard to
build a TDMA-type system. The USRP and the host delivering time-stamped
samples have to agree on what time it is. If you have 1PPS pulses going
in, you can use set_time_next_pps() to align times on the next PPS pulse.

Thanks for the idea of using set_time_now(). Setting the time to zero
(at the start of the flowgraph) makes a lot of sense (by the way,
USRP1 resets the time automatically when you start the flowgraph, but
USRP2 does not). However, you cannot use the set_time_now
periodically, because you will loose synchronization between host and
fpga. I do not think 1PPS would help either if you want to achive
cycle correct TX/RX switch. I want to let the FPGA to use its internal
timer and count everything in FPGA cycles on the host and do an
implicit time sync between the host and FPGA in order to send the next
packet 5ms before it times comes on the FPGA.

Best,
Miklos

Wont switch until txtime occurs. Sorry.

John

In a low power setup with a matched antenna using a circulator will to
the
job to combine RX and TX into one antenna…

Ralph.

Thanks for the quick comments. Yes, I totally agree that using full duplex
with
RX2 and TX/RX would be the ideal way to go, and as you say I can easily
ignore and synchronize with my own transmissions. The problem is that I am
required to use a single antenna, so I have to do a half duplex solution
with
all its warts and synchronization problems.

As for the switching time, I do not care if the switches (or the FPGA)
introduce deterministic delays, I can cope with that.

You mention that the state machine is set up in the daughter card setup
driver. Is this the file in “host/lib/usrp/dboard/db_sbx_common.cpp” for
the

times, no matter how much you tweak the FPGA. The switches themselves
this->dboard_iface::ATR_REG_IDLE, band_sel | ad9515div | TX_DIS_TXIO);

Which are setting up ATR registers.

But that being said, I think you’re best to run in a mode where you
have a separate RX antenna if you require nanosecond-scale turnaround
times. You’ll end up receiving your own transmissions, but that’s fairly
easy to

Hi Ian,

Wow, thanks for the technical explanation! That makes a whole lot of
sense (see below for further questions).

On Mon, Jun 3, 2013 at 8:19 PM, Ian B. [email protected] wrote:

Miklos,
Here’s a little bit more information about how the half-duplex operation works
from the H/W side.
The verilog module “gpio_atr” contains 5 32bit configuration registers that are
programmed by the driver.
This block connects to the radio daughter cards via the “io_rx” and “io_tx”
buses (which together have 32signals), and each daughter board uses theses signals
in a different way depending on the specific radio design.

Yes, I got this far in understanding the verilog code.

One of the registers programs each of the 32signals to determine if they are
inputs or outputs from the FPGA.
The remaining 4 registers contain the state that is driven out onto signals
(configured as outputs) in each of four states:
IDLE, RX only, TX only, TX and RX. The current state is detemined from
inspection of the “run_rx” and “run_tx” signals that you will find in
u2plus_core.v.
The state of these signals in turn is driven from UHD commands that are sent
from the host. When they are asserted then the respective DSP is enabled and
samples are delivered to/from the host.
No switching of TX and RX data streams is done on the host to implement
half-duplex operation, the only switch is analog and very close to the TX/RX
antenna connection, and this switch is controlled by some of the GPIO bits I have
referred to.

Excellent! I will look into this.

Internal to the FPGA “vita_time” which is a 64bit count of samples (100MHz on
N210) is used to schedule all DSP operation. When you send a TX stream command
with a time in the future, data is buffered in the FPGA ready to start
transmission, and when “vita_time” matches the time supplied with the TX stream
command, the “run_tx” signal is asserted causing both the DSP to become enabled
(and buffered data to be drawn into it), and also the “gpio_atr” state machine to
change state causing the analog RX/TX switch to toggle. There is a delay of some
10’s of clock cycles for data to pass through the FPGA TX DSP logic and out to the
DAC.

Hope this is enough information to help you understand the code further.

Yup, this is what I needed. One more thing: is it true, that once we
make the switch I can still download packets from the FPGA to the HOST
in the RX channel continuously and undisturbed? If I do not use
tx_time at all, but listen while I transmit, then I will get back the
leaked transmission, so I know exactly how many samples off are the RX
channel with respect to the TX channel. Will the same happen with the
RX/TX switch scheduled with tx_time?

Best,
Miklos

Hi John,

Thanks for the excellent suggestion! It seems to work reliably with
5ms buffering. I did not set the time of the FPGA, nor did I
synchronized the FPGA with the host. I just used the received sample
counter for all timings on the host to determine (the 5ms buffering)
when to send the samples to the board.

One question: It seems to me that when the TX -> RX switch is done,
then actually the N210 will use the RX2 antenna instead of
disconnecting the RX channel completely from the TX/RX antenna. Is it
possible to force half duplex operation, i.e. to completely disconnect
the RX channel. Of course I woulds still see leakage through the
board, but maybe that will not overdrive the LNA. Any ideas?

Miklos

Hi Marcus,

On Mon, Jun 3, 2013 at 9:20 PM, Marcus L. [email protected] wrote:

The 1PPS is used only to latch-in a time-of-day update from the host–it is
used when doing time synchronization across multiple devices, and in fact is
critical for that function to work correctly.

The problem with set_time_now() is that you can’t precisely model the delay
through the TCP/IP stack on the host, across the ethernet, etc.

With set_time_next_pps(), you typically get your local time on the host
(possibly as managed by NTP) and then do a set_time_next_pps(host_time+1).

I understand, but then the precision of your PC clock will be the
limiting factor and still you are going to get cycle slips because if
your FPGA is sometime going to accumulate more a 1 cycle drift, and
the next set_time_next_pps will introduce a cycle shift. If you count
everything in FPGA cycles on the host, then this is not a problem (and
of course you have to keep separate timelines for each FPGA if you
have more than one connected to your host).

Miklos

Hi John,

On Tue, Jun 4, 2013 at 7:38 PM, John M. [email protected]
wrote:

Miklos,

I’m not sure if what you’re saying is correct. Switch U3 may not switch to
RX2 during tx in half-duplex operation. I would double check, but I don’t

Thanks! What I have observed, that adding an antenna to the RX2
connector does change the received samples during transmission, i.e.
it overdrives it more.Maybe I am mistaken somewhere, but would
appreciate if you would double check. From earlier discussions it
seems that ATR state machine controls this behavior, right?

think it matters either way. If this is a half-duplex application, you
don’t want to receive and transmit at the same time. So you should just
ignore samples from the uhd_source, or mute them while tx is enabled. In
this case, it doesn’t matter what the RX path sees while it is switched to
the RX2 path.

That is true, that I have to discard those samples anyways. However, I
am worried that overdriving the receive path during transmission would
have adverse effect on subsequent reception (few samples right after
the TX → RX switch). Do you think that is a real concern?

Miklos

Miklos,

I’m not sure if what you’re saying is correct. Switch U3 may not switch
to
RX2 during tx in half-duplex operation. I would double check, but I
don’t
think it matters either way. If this is a half-duplex application, you
don’t want to receive and transmit at the same time. So you should just
ignore samples from the uhd_source, or mute them while tx is enabled.
In
this case, it doesn’t matter what the RX path sees while it is switched
to
the RX2 path.

-John

Hysteresis in the receive path is negligible and you won’t saturate
anything if the RX2 antenna is disconnected. So just leave RX2
unconnected.

This statement assumes that you don’t have a 1000 dB amplifier somewhere
in
the system. ; )

-John