External Time and Clock Reference¶
Clock Reference¶
Many AIR-T models support receiving an external 10 MHz reference clock to act as the device clock for applications that require synchronization between multiple AIR-Ts. This can be accomplished via piping in a signal to the REF input on the AIR-T. For details on the specifications of the external signal, please see the Product Guide for your hardware.
To enable this feature in software, you will need to either set the clk_src
device argument or call setClockSource()
via the SoapySDR API (e.g., sdr.setClockSource(“external”)
). The clk_src
parameter can be set via the device constructor (e.g., sdr = SoapySDR.Device(dict(driver="SoapyAIRT", clk_src="external"))
) or if you are using GNU Radio, simply add clk_src=”external"
to the Device arguments
field in the sink or source block.
The AIR-T model 8201 comes with a GPS module that can be used as a reference clock if desired. To enable this functionality, follow the same software steps as for the external reference, except replace external
with GPS
. No hardware modifications are required on the 8201 to use the GPS reference, simply enable this feature via software. Note that the GPS clock may not function if there is not a clear GPS signal to the device. As a result, it is recommended to revert back to the internal clock in the event of a transient GPS signal, as shown in the Python code example below.
sdr = SoapySDR.Device(dict(driver="SoapyAIRT"))
try:
sdr.setClockSource("GPS")
except RuntimeError as e:
print("GPS Clock Reference Failed!")
print(e)
sdr.setClockSource("internal")
Time Reference¶
Similar to the clock reference, an external PPS input port is present on all AIR-T models. In AirStack 1.0 and later, the time reference (i.e., PPS) can be enabled similarly to the clock (i.e., 10 MHz) reference. This can be accomplished via the SoapySDR Time API ( e.g., sdr.setTimeSource("external")
) or via the time_src
device argument ( e.g., sdr = SoapySDR.Device(dict(driver="SoapyAIRT", time_src="external"))
). Note that users of GNU Radio can also set the time_src
device argument in their source or sink block. Also, as with the clock reference, the AIR-T model 8201 has a GPS
option to use the PPS from the GPS module as the time reference.
One important thing to test when setting the time reference is the presence or absence of the PPS when using an external
or GPS
time source. The following class provides a simplified interface to ensuring the PPS is present.
class TimeSourceValidator:
def __init__(self, sdr):
if not sdr.hasHardwareTime("pps"):
raise ValueError("SDR hardware does not support PPS!")
self._sdr = sdr
self._init_pps_count = self._read_pps_count()
def pps_detected(self):
return self._init_pps_count != self._read_pps_count()
def _read_pps_count(self):
return int(self._sdr.getHardwareTime("pps") / 1e9)
The following example shows how this class can be leveraged to detect the presence or absence of a time reference.
sdr = SoapySDR.Device(dict(driver="SoapyAIRT"))
sdr.setTimeSource("external")
time_src_check = TimeSourceValidator(sdr)
# At this point, perform some operation that takes at least a whole second. That
# is, call the pps_detected() method once you are sure a whole second has passed
# and that the PPS time should have incremented. setupStream() is a good choice
# here as it generally takes a good amount of time to initialize the hardware to
# begin streaming.
rx_stream = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [0])
# setupStream() has returned, so a good amount of time has passed, PPS should
# have incremented.
if not time_src_check.pps_detected():
raise RuntimeError("PPS not detected!")
Independent APIs, Dependent Settings¶
The above two subsections showed how both the clock and time reference can be set on the AIR-T. It should be noted that these settings are controlled via two separate APIs, but in most cases an application will set both of these references to the same value. For example, it would be strange for an application to use an internal
time source with a GPS
clock source.