I am trying to setup a multi-channel phase coherent receiver using X310s with
TwinRXs installed. I have set up my radios such that the LO1 and LO2 signals
from TwinRX 0 (channels 0 and 1) are put into splitters and then shared to
TwinRX 1, 2 and 3 (channels 2 and 3, etc.). Both radios (USRP 0 and USRP 1) are
connected to the same 10 MHz reference clock and PPS sources. I am using
GNURadio and set all the required settings to enable LO sharing and
multi-radio. The GNURadio generated Python file contains all these settings as:
self.uhd_usrp_source_0.set_clock_source('external', 0)
self.uhd_usrp_source_0.set_time_source('external', 0)
self.uhd_usrp_source_0.set_clock_source('external', 1)
self.uhd_usrp_source_0.set_time_source('external', 1)
...
_last_pps_time = self.uhd_usrp_source_0.get_time_last_pps().get_real_secs()
\# Poll get_time_last_pps() every 50 ms until a change is seen
while(self.uhd_usrp_source_0.get_time_last_pps().get_real_secs() ==
_last_pps_time):
time.sleep(0.05)
\# Set the time to PC time on next PPS
self.uhd_usrp_source_0.set_time_next_pps(uhd.time_spec(int(time.time()) + 1.0))
\# Sleep 1 second to ensure next PPS has come
time.sleep(1)
...
self.uhd_usrp_source_0.set_lo_source('internal', uhd.ALL_LOS, 0)\
self.uhd_usrp_source_0.set_lo_export_enabled(True, uhd.ALL_LOS, 0)
...
self.uhd_usrp_source_0.set_lo_source('companion', uhd.ALL_LOS, 1)\
self.uhd_usrp_source_0.set_lo_export_enabled(False, uhd.ALL_LOS, 1)
...
self.uhd_usrp_source_0.set_lo_source('external', uhd.ALL_LOS, 2)\
self.uhd_usrp_source_0.set_lo_export_enabled(False, uhd.ALL_LOS, 2)
...
self.uhd_usrp_source_0.set_lo_source('external', uhd.ALL_LOS, 3)\
self.uhd_usrp_source_0.set_lo_export_enabled(False, uhd.ALL_LOS, 3)
...
self.uhd_usrp_source_0.set_lo_source('external', uhd.ALL_LOS, 4)\
self.uhd_usrp_source_0.set_lo_export_enabled(False, uhd.ALL_LOS, 4)
...
... etc.
...
self.uhd_usrp_source_0.set_lo_source('external', uhd.ALL_LOS, 7)\
self.uhd_usrp_source_0.set_lo_export_enabled(False, uhd.ALL_LOS, 7)
According to several guides, the next step is to make sure rx frequency tuning
happens synchronously using timed commands. I converted this from C++ to python
and implemented it in my set_fc() function as:
def set_fc(self, fc):
self.fc = fc
# get the actual tune frequency by tuning the first channel
tune_resp = self.uhd_usrp_source_0.set_center_freq(self.fc,0)
tune_req = uhd.tune_request(rf_freq=self.fc,
rf_freq_policy=uhd.tune_request.POLICY_MANUAL,
dsp_freq=tune_resp.actual_dsp_freq,
dsp_freq_policy=uhd.tune_request.POLICY_MANUAL)
# all other channels anyway
self.uhd_usrp_source_0.set_center_freq(tune_req, 1)
self.uhd_usrp_source_0.set_center_freq(tune_req, 2)
self.uhd_usrp_source_0.set_center_freq(tune_req, 3)
self.uhd_usrp_source_0.set_center_freq(tune_req, 4)
self.uhd_usrp_source_0.set_center_freq(tune_req, 5)
self.uhd_usrp_source_0.set_center_freq(tune_req, 6)
self.uhd_usrp_source_0.set_center_freq(tune_req, 7)
# self.uhd_usrp_source_0.set_center_freq(tune_req)
# create a time (from mboard 0) when following commands will happen
simultaneously
cmd_time = self.uhd_usrp_source_0.get_time_now() + uhd.time_spec(0.1)
# tell usrp to perform all following commands at cmd_time
self.uhd_usrp_source_0.set_command_time(cmd_time)
# commands tuning all all channels to the same frequency, ready to be
executed
#self.uhd_usrp_source_0.set_center_freq(tune_req) # tune all freqs at
once
self.uhd_usrp_source_0.set_center_freq(tune_req, 0)
self.uhd_usrp_source_0.set_center_freq(tune_req, 1)
self.uhd_usrp_source_0.set_center_freq(tune_req, 2)
self.uhd_usrp_source_0.set_center_freq(tune_req, 3)
self.uhd_usrp_source_0.set_center_freq(tune_req, 4)
self.uhd_usrp_source_0.set_center_freq(tune_req, 5)
self.uhd_usrp_source_0.set_center_freq(tune_req, 6)
self.uhd_usrp_source_0.set_center_freq(tune_req, 7)
# sleep and allow tunes to happen without interfering commands (50ms
after syncronuous retune occurs)
time.sleep(0.15)
# clear command time so future commands are sent ASAP
self.uhd_usrp_source_0.clear_command_time()
Running this code, (with a call to set_fc() at the start to synchronize) grants
perfect phase alignment on channels 0 through 3, all on the first USRP.
However, channels 4 through 7 have arbitrary multiples of 90 degree phase
offset between channels after tuning.
To explore this, I configured each USRP to share the first channel LO signals
with only the channels on that radio as you would for single radio LO sharing
but kept them under the same usrp object in the code. Sure enough, the same
error occurs where the first radio listed in
"addr0=192.168.40.2,addr1=192.168.40.3" is perfect but the second radio has
ambiguous phase between channels. Switching the addr number of the IP addresses
("addr0=192.168.40.3,addr1=192.168.40.2") gives the same result, where addr0 is
perfect and addr1 has the ambiguity.
I suspect there is a problem with my use of timed commands in the frequency
tuning section. Maybe I am missing an important line which ensured USRP 0 and
USRP 1 are governed by the same timed command.
\-- UPDATE --
If I separate the timed command tunings for each mboard as:
cmd_time0 = self.uhd_usrp_source_0.get_time_now(0) + uhd.time_spec(0.1)
cmd_time1 = self.uhd_usrp_source_0.get_time_now(1) + uhd.time_spec(0.1)
self.uhd_usrp_source_0.set_command_time(cmd_time0,0)
self.uhd_usrp_source_0.set_command_time(cmd_time1,1)
…
self.uhd_usrp_source_0.clear_command_time(0)
self.uhd_usrp_source_0.clear_command_time(1)
Then the second radio on addr1 now retunes synchronously for channels on that
radio. However, there still exists random 90 degree phase ambiguity between
mboard 0 and mboard1 after retunes. Perhaps mboard0 and mboard1 are not synced?
_______________________________________________
USRP-users mailing list -- [email protected]
To unsubscribe send an email to [email protected]