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 -- usrp-users@lists.ettus.com To unsubscribe send an email to usrp-users-le...@lists.ettus.com