Ptime get_time(void) precision down to millisec microsec nanosec?

Hi Everyone

First, I would like to introduce myself (ourselves) :
VeriSat, Oslo based company (Norway). We are working on a project, using
USRP (N210) platform, which aim is to build a DVB-RCS Terminal
Shortly RCS is for satellite communication, and is Multi Frequencies
TDMA. (http://verisat.no)

So synchronization is an important issue for us.
Now I have a question regarding the use of a USRP N210 with GPSDO kit,
and the use of the UHD function ptime get_time(void) in
/host/lib/usrp/gps_ctrl.cpp @ line 133

According to the implementation of get_time(void), it returns the date
time with precision down to second. It looks like it queries the USRP
waiting for a reply starting with “$GPRMC”. then is parses the reply to
extract year, month, day, hours, min and sec.

Is it possible to extract from the reply the milli ? micro ? and nano
seconds ? For example using toked[2-8] or toked[10-11] (because
UHD_ASSERT_THROW(toked.size() == 12):wink:

If not, is there any way to include more precision in get_time() by
changing code not only in gps_ctrl.cpp, but also in the firmware ?

According to
http://lists.gnu.org/archive/html/discuss-gnuradio/2011-02/msg00162.html
USRP should get 50 ns precision, so I assume it’s possible in some way ?

Best Regards
Bastien

Hi

I think there is a misunderstanding.
I do not want to set the time of the USRP.
I want to use the USRP (with GPSDO) as my time reference.
This is why I want to query the USRP using the UHD function ptime
get_time(void) in
/host/lib/usrp/gps_ctrl.cpp @ line 133

This function only returns date and time down to seconds, and the
toked[] array has a bigger length than what is used :
"
UHD_ASSERT_THROW(toked.size() == 12); //if it’s not we got something
weird in there

now = ptime( date(
greg_year(boost::lexical_cast(toked[9].substr(4, 2)) + 2000),
//just trust me on this one
greg_month(boost::lexical_cast(toked[9].substr(2, 2))),
greg_day(boost::lexical_cast(toked[9].substr(0, 2)))
),
hours( boost::lexical_cast(toked[1].substr(0, 2)))

  • minutes(boost::lexical_cast(toked[1].substr(2, 2)))
  • seconds(boost::lexical_cast(toked[1].substr(4, 2)))
    );
    "

So I would like to know the format of the string returned by the
safe_gps_read(); function,
"
reply = safe_gps_read();
"

or better the description of the toked[] array after it get through
"
tok.assign(reply);
toked.assign(tok.begin(), tok.end());
"

Bastien

I don’t understand why I should do :

Typically, you call get_time() to get the UTC time
in seconds, and then set_time_next_pps() to tell the FPGA to sync its
sample time to the next PPS pulse

why should I use set_time_next_pps() ? Is it needed to init USRP lock to
GPS time ?

My understanding is that USRP is GPS locked because it has GPSDO. then I
use get_time() to ensure that my PC clock will not get delayed by more
than some millisec (+/-) from USRP clock. Taking into account ethernet
delay, and some more internal delay, I was expecting to get some 10 to
20 millisec accuracy. This way I know that I can send all the burst to
USRP with TX_timestamp around 50 millisec in the future.

Without this mechanism, I’m afraid to get the PC clock drifting from
USRP (so GPS) clock, leading to send burst with tx_timestamp in the past

I will then have to use some much bigger margin to send my burst (like
500 millisec) which would add big latency to system

Bastien

On Thu, 2011-05-19 at 17:07 +0000, Bastien Auneau wrote:

toked[] array has a bigger length than what is used :
hours( boost::lexical_cast(toked[1].substr(0, 2)))

  • minutes(boost::lexical_cast(toked[1].substr(2, 2)))
  • seconds(boost::lexical_cast(toked[1].substr(4, 2)))
    );
    "

So I would like to know the format of the string returned by the
safe_gps_read(); function,
"
reply = safe_gps_read();

OK, so 4 things:

  1. Querying the GPS time through the device is going to net you accuracy
    in the 10s of milliseconds, maybe worse. Asking for more precision in
    the GPRMC sentence is meaningless, since the query has to go through
    both the Ethernet transport and the serial port on the N210 on its way
    to you.

  2. The GPSDO PPS output is used in the N210 to synchronize the sample
    time across multiple devices. The PPS edge is the ONLY output of the
    GPSDO which is guaranteed to be synchronized, and its synchronization is
    good to (typical) 50ns. That output goes straight into the FPGA to
    provide a sync pulse. Typically, you call get_time() to get the UTC time
    in seconds, and then set_time_next_pps() to tell the FPGA to sync its
    sample time to the next PPS pulse. Then you know the absolute time, and
    you can calculate the absolute time of any given sample from the N210
    based on the absolute time and the sample count.

  3. The GPRMC sentence provides for decimal time down to the millisecond;
    however, the Jackson Labs Firefly device (like most GPS devices) issues
    sentences on the rising edge of PPS, and so the fractional seconds
    component is always zero.

  4. The toked vector gives you the GPRMC sentence components in order,
    separated by comma or period.

–n

On 19/05/2011 3:13 PM, Bastien Auneau wrote:

why should I use set_time_next_pps() ? Is it needed to init USRP lock to
GPS time ?
Keep in mind that the PPS support pre-dates the existence of an “in
skin” GPSDO, and the
primary purpose of the GPSDO is to provide a stable 10MHz reference
clock for the
PLL synthesizers, ADC clocks, and DSP-chain within the FPGA.

Internal to the FPGA, there’s a clock register that runs at 100MHz
(10ns/tick). The purpose of
set_time_next_pps() is to arrange for that register to be set to
whatever you supply, at the next
1PPS input transition. The purpose is to allow synchronization of
multiple USRP2/N210 so that
they all more-or-less agree on sample timing.

Consider the following scenario:

o A number, greater than one, of USRP2/N2xxx
o All seeing the same 1PPS and 10MHz ref-clocks
o They’ve all just been sent a set_time_next_pps() command from the
host
o The 1PPS pulse arrives some time after you’ve done the
set_time_next_pps()
o Once that 1PPS pulse arrives, on a one-shot basis, the master clock
in all of the the USRP2/N2xx to which you’ve
sent the set_time_next_pps() command all now agree on the current
“time”. But this is a sample time, and it only
has meaning within the context of sample synchronization. It
doesn’t necessarily have any relationship at all to “real” time.

The USRP-family, internally, neither knows, nor really cares, about
absolute time-of-day.

Now, having said that, the UHD protocol allows you to set the “time at
next PPS” or “time right now please” to anything you want, and
it looks (from the FPGA code, Josh could confirm) that the time is
divided into a 32-bit seconds field, and a 32-bit “ticks” field. The
“ticks” field ticks over at the nominal FPGA clock frequency of 100MHz,
which gives 10ns per tick. So you could set the 32-bit seconds
field to the host TOD clock more-or-less directly, after scaling the
ticks appropriately.

My understanding is that USRP is GPS locked because it has GPSDO. then I
use get_time() to ensure that my PC clock will not get delayed by more
than some millisec (+/-) from USRP clock. Taking into account ethernet
delay, and some more internal delay, I was expecting to get some 10 to
20 millisec accuracy. This way I know that I can send all the burst to
USRP with TX_timestamp around 50 millisec in the future.
Again, the USRP2/N2XXX family use the GPSDO primarily to provide a
high-quality 10MHz reference clock, and the 1PPS
for synchronizing the sample timestamping mechanisms. The
USRP2/N2XX does not, at this point, actually parse the
NMEA-0183 GPS sentences and set its internal time-of-day (actually,
sample) clock to GPS time. The “in skin” GPSDO was
primarily regarded (AFAIK) as a convenient substitute for an external
10MHz and 1PPS reference, to simplify packaging.

The “model” is that the host(s) are the primary time-of-day reference.
If you want to make sure the USRP2/N2XXX doesn’t drift
relative to the host, I would make sure the host is running NTPD, and
then have your application occasionally use the
set_time_next_pps() or set_time_now() functions to cause
synchronization between the hosts time-of-day “view” and that
of the USRP2/N2XX.