[USRP-users] Exact alignment between gnuradio sample stream and USRP time
lukashaase at gmx.at
Fri Jan 24 02:57:05 EST 2020
> On 01/23/2020 12:32 PM, Lukas Haase via USRP-users wrote:
>> TO MY UNDERSTANDING, the USRP has an internal clock that is different from host clock when running gnuradio (which makes sense because there are buffers etc in between).
>> Example: I transmit a CW at f=1001, receive it at f=1000 and then use gnuradio to downconvert the remaining 1 MHz I run into trouble (tried it...).
>> For this reason, there exist timed commands and the tune_request object with which I can execute commands (LO tuning) at a precice time. For example, with these commands I can phase align tuning between TX/RX at different center frequencies:
>> tune_req_tx = uhd.tune_request(fcenter-1e6, 1e6)
>> tune_req_rx = uhd.tune_request(2*fcenter)
>> tune_req_rx.args=uhd.device_addr(','.join(["mode_n=integer", "int_n_step=1000e3",]))
>> tune_req_tx.args=uhd.device_addr(','.join(["mode_n=integer", "int_n_step=1000e3",]))
>> now = self.uhd_usrp_sink_0.get_time_now()
>> self.uhd_usrp_sink_0.set_command_time(now + uhd.time_spec(0.1))
>> self.uhd_usrp_source_0.set_command_time(now + uhd.time_spec(0.1))
>> self.uhd_usrp_sink_0.set_center_freq( tune_req_tx, 0)
>> self.uhd_usrp_source_0.set_center_freq(tune_req_rx, 0)
>> The commands execute execatly at get_time_now() plus 100ms. As far as I understand, these 100ms are to ensure that the host computer has enough time until the USRP processes the clear_command_time function. But it does not relate the exact point in time with anything that exists in gnuradio.
>> MY QUESTION: What I am unsure is how to align samples in gnuradio with the time on the USRP. For example, suppose I have an ideal clock signal in gnuradio and I want to perform a timed command EXACTLY at a particular sampling point (e.g. rising edge). How would I go about this?
>> The actions I want to execute exactly time aligned with gnuradio include: tuning requests, reading out sensors (PLL sensor when it settled), switching IO pins through the GPIO interface.
>> For example, I would like to switch a GPIO port exactly once per period of a signal in gnuradio and exactly at the same time (clearly there will be delays but that's OK as long as the delay is fixed).
>> As another example, I would like to re-tune exactly once in every period of a gnuradio signal. Then I would like to read out when the PLL has settled and generate a binary indicator signal out of it. Plotting the original signal and the indicator signal should tell me exactly (at least sample accuracy) how long the PLL took to settle *relative* to the signal in gnuradio.
>> Thank you very much,
> Whatever "dance" you're using to set the USRP time, (presumably
> something like set_time_unknown_pps), you need to have it derive the
> USRP time register from the host time. The normal code that is
> emitted in GRC for "unknown_pps" just resets the USRP time to zero.
> But you can arrange for it to be the host time (+1 second or
> something) instead.
> You haven't indicated whether you're using GRC, or "naked" Gnu Radio
> General synchronization "things" are discussed in the knowledge base, here:
Thanks. I went through this page a few times and got synchronization between TX/RX (somewhat) running.
I am using GRC but willing to go "naked" where necessary (my main application will still always be grc+GUI).
I guess I still don't understand what exactly what the "USRP time" is and how it related to sample time.
I do not think it makes sense to lock the USRP time to the host time because the host time is independent from the sample time on the host (in gnuradio). Samples are buffered and depending on CPU load, samples may occur earlier or later than expected by CPU time. Say I generate the signal x[n] and the sample rate is 1kS/s, then in a real-time system I can expect each sample to occur exactly every ms. But on my host with gnuradio this is certainly not the case! x does not necessarily occur 1 seconds (in CPU time) after x.
Again, what I want is I generate x[n] in gnuradio. For every, say, (n mod 1000)==0 I want to execute something on the USRP, for example flipping a GPIO which increases the gain of an amplifier ... exactly at the time when the *USRP* processes this sample. Not the host! Because the USRP, to my understanding, is like a realtime system.
Now say the output of the amplifier is fed again into the USRP RX port and I read it back as y[n] from USRP Source.
I will see the effect of the gain change in y[n] ... many samples after I did the request due to latency. But I want that the relative sample difference between x[n] and y[n] is always constant!
At x --> change gain to 1 --> at y I see gain changes to 1
At x --> change gain to 2 --> at y I see gain changes to 2
At x --> change gain to 3 --> at y I see gain changes to 3
I hope this example makes it more clear what I mean.
This is just a toy example; in reality I would build x[n] in gnuradio to be a control signal that aligns all the actions in a predicable manner.
More information about the USRP-users