Hi Marcus,

Yes, the cables are identical, we also experimented with Phase stable test
cables but did not see any improvement. We understand there will be some
residual phase errors, but the RF coming out with a 2.64ns delta or ~135
degree phase shift @ 144MHz seems like more than that. Is that level of
offset to be expected, if so is there a procedure to calibrate that out to
align the RF?

Understand that the phase drift measurements are the change over time. Do
you know if Measured Performance results, from
https://kb.ettus.com/USRP_N320/N321_LO_Distribution, where generated on Rx
channels (e.g. by injecting a tone to a N321 and a N320 and measuring the
phase difference of the IQ over time) or on Tx channels (e.g. N321 and N320
transmitting a tone and using some type of test equipment to measure the
phase offset of the RF over time) or is there some other way? I'd just like
to repeat the process to see if I can repeat the results or see if there is
something I am doing wrong.

Thanks,

Michael Toussaint


On Thu, Jun 8, 2023 at 6:53 PM Marcus D. Leech <patchvonbr...@gmail.com>
wrote:

> On 08/06/2023 21:41, Michael Toussaint wrote:
>
> Hi Rob,
>
> Yes, 0.57 degrees is definitely within my measurement error. But,
> shouldn't the N321 synchronize the phase of the LO's too?
>
> If you're sharing LOs, there's no "synchronizing the LOs".  A single LO is
> shared through a switching matrix to each of the
>   relevant mixers.  There'll be some residual phase-error, since effective
> path-length will never be precisely matched--even
>   with careful board layout, internal temperature differentials and batch
> differences in electronic components in the switching
>   matrix, and even the mixers involved, will yield (usually small) mutual
> phase errors.
>
> Presumably the length of your LO-sharing cables are all the same, of the
> same type, and from the same manufacturer
>   (and, preferrably, from the same cable batch).
>
>
>
>
> Is there documentation available of how to repeat the results in the
> "Measured Performance" section of
> https://kb.ettus.com/USRP_N320/N321_LO_Distribution (e.g. code examples
> and or test setup to measure the phase drift)? It shows less than 0.1
> degree of phase error, I'd like to just repeat that test to confirm
> everything is working correctly, and see what might be causing the deltas.
>
> Note that phase-drift measurements measure the *change* in relative phase
> between channels over time.  Not, I think, the
>   absolute phase-offset between channels.  In a shared-LO setup (ignoring
> any bugs or mis-configurations of the DUCs, etc), the
>   absolute phase-offset between channels is repeatable and (largely)
> static.  Dominated by physical processes like temperature
>   drift and (worse) differential temperature drift in analog components
> like cables, circuit-board traces, component temperatures,
>   etc.
>
>
>
> Thanks,
>
> Michael
>
>
> On Wed, Jun 7, 2023 at 12:22 PM Rob Kossler <rkoss...@nd.edu> wrote:
>
>> Hi Michael,
>> I don't have any ideas for reducing a time delay offset. But, I still
>> wonder if the problem could actually be just a phase offset.
>>
>> With a relative delay of 2.5ns and a bandwidth of 4 MHz, the amount of
>> phase variation you would see is 0.57 degrees.  That is not easy to see.
>> On the other hand, if your bandwidth increased to 200 MHz, you would see
>> phase variation of 28.6 degrees (if the delay offset is 2.5 ns).
>> Rob
>>
>>
>> On Tue, Jun 6, 2023 at 9:38 PM Michael Toussaint <mtoussa...@chaosinc.com>
>> wrote:
>>
>>> Hi Rob,
>>>
>>> The signal is actually sweeping over 4MHz, but is just super zoomed into
>>> a small piece to show the time delta so it looks CW. The time difference
>>> appears to be the same (within my ability to measure) across the band so I
>>> am assuming it is a time delay offset.
>>>
>>> Any suggestions on how to reduce this time delay offset?
>>>
>>> Thanks,
>>>
>>> Michael Toussaint
>>>
>>>
>>> On Mon, Jun 5, 2023 at 8:51 PM Rob Kossler <rkoss...@nd.edu> wrote:
>>>
>>>> Hi Michael,
>>>> Either a delay offset OR a phase offset will show itself as a relative
>>>> phase.  In order to distinguish between a delay offset and a phase offset,
>>>> your signal must have appreciable bandwidth.  It appears that your signal
>>>> is CW.  It is entirely possible that your delay offset is zero.  Does this
>>>> make sense?
>>>> Rob
>>>>
>>>> On Mon, Jun 5, 2023 at 5:32 PM Michael Toussaint <
>>>> mtoussa...@chaosinc.com> wrote:
>>>>
>>>>> Could you share how you're setting up LO sharing in your code, as well
>>>>> as how you're setting the system clock on the N321?
>>>>>
>>>>> The functions "configure_channels" and "set_lo_hw_exports" are used
>>>>> to set up the LO sharing.
>>>>>
>>>>> The functions "sync_sources" and "sync_all_devices" are used to set
>>>>> up the system clock on the N321.
>>>>>
>>>>> How do you measure the relative delay?
>>>>>
>>>>> We are measuring the offset of the LO's by just measuring the phase
>>>>> difference of ithe RF coming out of the Ettus with an Oscilloscope
>>>>> (picture attached as
>>>>> Scope_Trace_SingleStream_LO.png
>>>>>
>>>>> <https://mail.google.com/mail/u/0?ui=2&ik=34abf4583b&attid=0.1&permmsgid=msg-a:r-1207093291428225864&view=att&disp=safe&realattid=f_lijcykt50>).
>>>>> Yellow is Channel 1, Green is Channel 2; using a single streamer we still
>>>>> appear to have a 2.64ns delta or ~135 degree phase shift.
>>>>>
>>>>> Thanks Marcus and Rob for your assistance.
>>>>>
>>>>> Michael Toussaint
>>>>>
>>>>> def sync_sources(usrp):
>>>>>     logging.info('Setting Sync Sources')
>>>>>
>>>>>     usrp.set_sync_source(clock_source = 'gpsdo',
>>>>>                          time_source = 'gpsdo')
>>>>>
>>>>> def sync_all_devices(hw_info):
>>>>>     logging.info('Syncing All Devices')
>>>>>
>>>>>     mb_with_gps_locked = -1
>>>>>
>>>>>     while 1:
>>>>>         time.sleep(1.0)
>>>>>
>>>>>         all_ref_locked = True
>>>>>
>>>>>         for board in range(hw_info.usrp.get_num_mboards()):
>>>>>             all_ref_locked = all_ref_locked and \
>>>>>                 hw_info.usrp.get_mboard_sensor('ref_locked',
>>>>>                                                board).to_bool()
>>>>>
>>>>>             if (mb_with_gps_locked == -1) and \
>>>>>                 hw_info.usrp.get_mboard_sensor('gps_locked',
>>>>>                                                board).to_bool():
>>>>>                 mb_with_gps_locked = board
>>>>>
>>>>>         if all_ref_locked:
>>>>>             logging.info('All Devices are REF locked')
>>>>>             break
>>>>>
>>>>>     logging.info('GPS Locked on MB #%d', mb_with_gps_locked)
>>>>>
>>>>>     time.sleep(1.0)
>>>>>     hw_info.usrp.set_time_next_pps(
>>>>>         uhd.types.TimeSpec(
>>>>>         hw_info.usrp.get_mboard_sensor('gps_time',
>>>>>                                        mb_with_gps_locked).to_int() +
>>>>>                                        1.0)
>>>>>     )
>>>>>     time.sleep(1.0)
>>>>>
>>>>>
>>>>> def configure_channels(usrp, rf_type, hw_info):
>>>>>     rf_channel_index = None
>>>>>     set_rf_rate = None
>>>>>     set_rf_freq = None
>>>>>     set_rf_gain = None
>>>>>     set_rf_lo_source = None
>>>>>     get_rf_lo_source = None
>>>>>     get_rf_lo_freq = None
>>>>>     get_rf_lo_freq_range = None
>>>>>
>>>>>     if (rf_type == 'rx'):
>>>>>         if (len(hw_info.rx_channel_index) > 0):
>>>>>             rf_channel_index = hw_info.rx_channel_index
>>>>>             set_rf_rate = usrp.set_rx_rate
>>>>>             set_rf_freq = usrp.set_rx_freq
>>>>>             set_rf_gain = usrp.set_rx_gain
>>>>>             set_rf_lo_source = usrp.set_rx_lo_source
>>>>>             get_rf_lo_source = usrp.get_rx_lo_source
>>>>>             get_rf_lo_freq = usrp.get_rx_lo_freq
>>>>>             get_rf_lo_freq_range = usrp.get_rx_lo_freq_range
>>>>>         else:
>>>>>             return
>>>>>     elif (rf_type == 'tx'):
>>>>> i        if (len(hw_info.tx_channel_index) > 0):
>>>>>             rf_channel_index = hw_info.tx_channel_index
>>>>>             set_rf_rate = usrp.set_tx_rate
>>>>>             set_rf_freq = usrp.set_tx_freq
>>>>>             set_rf_gain = usrp.set_tx_gain
>>>>>             set_rf_lo_source = usrp.set_tx_lo_source
>>>>>             get_rf_lo_source = usrp.get_tx_lo_source
>>>>>             get_rf_lo_freq = usrp.get_tx_lo_freq
>>>>>             get_rf_lo_freq_range = usrp.get_tx_lo_freq_range
>>>>> i        else:
>>>>>             return
>>>>>
>>>>>     logging.info('Configuring %s Channels', rf_type.upper())
>>>>>
>>>>>     for rf_ch_name, rf_ch_index in rf_channel_index.items():
>>>>>         logging.info('Configuring %s channel %s (channel #%d)',
>>>>>                      rf_type.upper(), rf_ch_name, rf_ch_index)
>>>>>
>>>>>         ch_def = hw_info.channel_def[rf_ch_name]
>>>>>
>>>>>         # LO Channel Setup
>>>>>         current_lo_name = 'unknown'
>>>>>         current_lo_src = 'unknown'
>>>>>
>>>>>         if ch_def.lo_inputs is not None:
>>>>>             logging.info('  Setting %s LO for Channel %s (#%d)',
>>>>>                          rf_type.upper(), rf_ch_name, rf_ch_index)
>>>>>
>>>>>             set_rf_lo_source(ch_def.lo_inputs.source,
>>>>>                              ch_def.lo_inputs.name,
>>>>>                              rf_ch_index)
>>>>>             current_lo_name = ch_def.lo_inputs.name
>>>>>
>>>>>             logging.info('    (#%d) Requested %s LO name %s, src %s',
>>>>>                          rf_ch_index,
>>>>>                          rf_type.upper(),
>>>>>                          ch_def.lo_inputs.name,
>>>>>                          ch_def.lo_inputs.source)
>>>>>         else:
>>>>>             logging.info('  No %s LO inputs for Channel %s (#%d)',
>>>>>                          rf_type.upper(), rf_ch_name, rf_ch_index)
>>>>>
>>>>>             current_lo_name = 'lo1'
>>>>>
>>>>>         current_lo_src = get_rf_lo_source(current_lo_name,
>>>>>                                           rf_ch_index)
>>>>>
>>>>>         logging.info('    (#%d) Current %s LO name %s, src %s',
>>>>>                      rf_ch_index,
>>>>>                      rf_type.upper(),
>>>>>                      current_lo_name,
>>>>>                      current_lo_src)
>>>>>
>>>>>         rf_lo_freq = get_rf_lo_freq(current_lo_name,
>>>>>                                     rf_ch_index)
>>>>>
>>>>>         logging.info('    (#%d) [%s] Current %s LO freq %d',
>>>>>                          rf_ch_index,
>>>>>                          current_lo_name,
>>>>>                          rf_type.upper(),
>>>>>                          rf_lo_freq)
>>>>>
>>>>>         rf_lo_freq_range = get_rf_lo_freq_range(
>>>>>             current_lo_name, rf_ch_index)
>>>>>
>>>>>         temp = '    (#%d) [%s] Current %s LO freq range' + \
>>>>>             ' [%d, %d] step %d'
>>>>>
>>>>>         logging.info(temp,
>>>>>                      rf_ch_index,
>>>>>                      current_lo_name,
>>>>>                      rf_type.upper(),
>>>>>                      rf_lo_freq_range.start(),
>>>>>                      rf_lo_freq_range.stop(),
>>>>>                      rf_lo_freq_range.step())
>>>>>
>>>>>         logging.info('  Setting Sampling Rate %s', hw_info.fs)
>>>>>         set_rf_rate(hw_info.fs, rf_ch_index)
>>>>>
>>>>>         logging.info('  Setting Center Freq %s', hw_info.fc)
>>>>>         tr = set_rf_freq(uhd.libpyuhd.types.tune_request(hw_info.fc),
>>>>>                          rf_ch_index)
>>>>>
>>>>>         logging.info('    (#%d) %s Tune Result:',
>>>>>                      rf_ch_index, rf_type.upper())
>>>>>         log_tune_result(tr)
>>>>>
>>>>>         logging.info('  Setting %s Gain: %2.3f db',
>>>>>                      rf_type.upper(),
>>>>>                      ch_def.gain)
>>>>>         set_rf_gain(ch_def.gain, rf_ch_index)
>>>>>
>>>>> def set_lo_hw_exports(usrp, node_name, dirx, lo_enabled, output_array):
>>>>>     """Set LO HW Exports"""
>>>>>     if (lo_enabled is None) or (output_array is None):
>>>>>         return
>>>>>
>>>>>     logging.info('Setting %s LO Export Enabled for %s',
>>>>>                  dirx.upper(), node_name)
>>>>>
>>>>>     if dirx.lower() == 'rx':
>>>>>         usrp.set_rx_lo_export_enabled(lo_enabled, 'lo1', 0)
>>>>>         enable_val = usrp.get_rx_lo_export_enabled('lo1')
>>>>>     elif dirx.lower() == 'tx':
>>>>>         usrp.set_tx_lo_export_enabled(lo_enabled, 'lo1', 0)
>>>>>         enable_val = usrp.get_tx_lo_export_enabled('lo1')
>>>>>     else:
>>>>>         logging.warning('Invalid direction %s', dirx)
>>>>>         return
>>>>>
>>>>>     logging.info('  %s LO Export Enabled = %s, requested %s',
>>>>>                  dirx.upper(), enable_val, lo_enabled)
>>>>>
>>>>>     temp_path = 'blocks/0/Radio#0/dboard/' + \
>>>>>         f'{dirx.lower()}_frontends/' + \
>>>>>         '0/los/lo1/lo_distribution/LO_OUT_{}/export'
>>>>>
>>>>>     logging.info('Setting %s LO HW Outputs for %s',
>>>>>                  dirx.upper(), node_name)
>>>>>
>>>>>     for out_num in range(len(output_array)):
>>>>>         hw_lo_export_path = temp_path.format(out_num)
>>>>>
>>>>>         if usrp.get_tree().exists(hw_lo_export_path):
>>>>>             usrp.get_tree().access_bool(hw_lo_export_path).set(
>>>>>                 output_array[out_num])
>>>>>
>>>>>             logging.info('  %s LO HW Export Out[%d] = %s, %s %s',
>>>>>                          dirx.upper(), out_num,
>>>>>                          usrp.get_tree().access_bool(
>>>>>                             hw_lo_export_path).get(),
>>>>>                         'requested',
>>>>>                         output_array[out_num])
>>>>>         else:
>>>>>             logging.warning('  %s LO HW Export Out[%d] does not exist',
>>>>>                             dirx.upper(), out_num)
>>>>>
>>>>>
>>>>> On Thu, May 25, 2023 at 6:45 AM Rob Kossler <rkoss...@nd.edu> wrote:
>>>>>
>>>>>> On Thu, May 25, 2023 at 3:54 AM Michael Toussaint
>>>>>> <mtoussa...@chaosinc.com> wrote:
>>>>>> >
>>>>>> > Used a single streamer and saw the delay slightly improve to
>>>>>> between 2.5 - 3 ns.
>>>>>> >
>>>>>> > Any other suggestions to improve the delay to match the results
>>>>>> from the knowledge base,
>>>>>> https://kb.ettus.com/USRP_N320/N321_LO_Distribution?
>>>>>>
>>>>>> How do you measure the relative delay?
>>>>>>
>>>>>
>>>>>
>>>>>
>>>
>
>
>
_______________________________________________
USRP-users mailing list -- usrp-users@lists.ettus.com
To unsubscribe send an email to usrp-users-le...@lists.ettus.com

Reply via email to