diff options
author | Daniel Jepson <daniel.jepson@ni.com> | 2017-09-26 09:54:54 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2017-12-22 15:04:01 -0800 |
commit | 3b716315fea52a1c1866c60c5d101e3bfe163560 (patch) | |
tree | f7abcdab937cfe73039cfff58c5ce4fe2690cf0f | |
parent | febfdf27b4f776d1791e6959587b7c0773f6cbf2 (diff) | |
download | uhd-3b716315fea52a1c1866c60c5d101e3bfe163560.tar.gz uhd-3b716315fea52a1c1866c60c5d101e3bfe163560.tar.bz2 uhd-3b716315fea52a1c1866c60c5d101e3bfe163560.zip |
mpm: Update TDC sync code to make it generic for N dboards
-rw-r--r-- | mpm/python/usrp_mpm/cores/tdc_sync.py | 74 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/eiscat.py | 3 |
2 files changed, 65 insertions, 12 deletions
diff --git a/mpm/python/usrp_mpm/cores/tdc_sync.py b/mpm/python/usrp_mpm/cores/tdc_sync.py index cc9981205..bb4695cb6 100644 --- a/mpm/python/usrp_mpm/cores/tdc_sync.py +++ b/mpm/python/usrp_mpm/cores/tdc_sync.py @@ -18,6 +18,7 @@ TDC clock synchronization """ import time +import math from builtins import object from functools import reduce @@ -63,7 +64,7 @@ def rtc_table(radio_clk_freq): Returns a tuple (period, high_time). """ return { - 125e6: (125, 62.5), + 125e6: (125, 63), 122.8e6: (3072, 1536), 156.3e6: (3840, 1920), 104e6: (104, 52), @@ -100,6 +101,9 @@ class ClockSynchronizer(object): ref_clk_freq, fine_delay_step, init_pdac_word, + lmk_vco_freq, + target_values, + dac_spi_addr_val, log ): self._iface = regs_iface @@ -113,6 +117,9 @@ class ClockSynchronizer(object): self.ref_clk_freq = ref_clk_freq self.fine_delay_step = fine_delay_step self.current_phase_dac_word = init_pdac_word + self.lmk_vco_freq = lmk_vco_freq + self.target_values = target_values + self.dac_spi_addr_val = dac_spi_addr_val def run_sync(self, measurement_only=False): """ @@ -203,21 +210,19 @@ class ClockSynchronizer(object): if (current_value < 120e-9) or (current_value > 150e-9): self.log.error("Clock synchronizer measured a " - "current value of {} ns!".format( + "current value of {:.3f} ns!".format( current_value*1e9 )) raise RuntimeError("TDC measurement out of range! " - "Current value: {} ns.".format( + "Current value: {:.3f} ns.".format( current_value*1e9 )) # Run the initial value through the oracle to determine the adjustments to make. - target_values = [135e-9,] # only one target for now that all DBs shift to - lmk_vco_freq = 2.496e9 # LMK VCO = 2.496 GHz coarse_steps_required, dac_word_delta, distance_to_target = self.oracle( - target_values, + self.target_values, current_value, - lmk_vco_freq, + self.lmk_vco_freq, self.fine_delay_step ) @@ -227,10 +232,7 @@ class ClockSynchronizer(object): self.lmk.lmk_shift(coarse_steps_required) self.log.trace("LMK Shift Complete!") # Fine shift with the DAC, then give it time to take effect. - self.current_phase_dac_word = (self.current_phase_dac_word + dac_word_delta) & 0xFFF - self.log.trace("Writing Phase DAC Word: {}".format(self.current_phase_dac_word)) - self.phase_dac.poke16(0x3, self.current_phase_dac_word) - time.sleep(0.5) + self.write_dac_word(self.current_phase_dac_word + dac_word_delta, 0.5) if not self.lmk.check_plls_locked(): raise RuntimeError("LMK PLLs lost lock during clock synchronization!") # After shifting the clocks, we enable the PPS crossing from the @@ -298,7 +300,7 @@ class ClockSynchronizer(object): target_values ) distance_to_target = target_value - current_value - self.log.trace("Target value = {} ns. Current value = {} ns. Distance to target = {} ns.".format( + self.log.trace("Target value = {:.3f} ns. Current value = {:.3f} ns. Distance to target = {:.3f} ns.".format( target_value*1e9, current_value*1e9, distance_to_target*1e9, @@ -316,3 +318,51 @@ class ClockSynchronizer(object): self.log.trace("Fine Steps (DAC): {}".format(dac_word_delta)) return coarse_steps_required, dac_word_delta, distance_to_target + + def write_dac_word(self, word, settling_time=1.0): + """ + Write the word and wait for settling time. + TODO: hard-coded to support 16 bit DACs. do we need to modify to support smaller? + """ + self.current_phase_dac_word = word & 0xFFFF + self.log.trace("Writing Phase DAC Word: {}".format(self.current_phase_dac_word)) + self.phase_dac.poke16(self.dac_spi_addr_val, self.current_phase_dac_word) + time.sleep(settling_time) # settling time. + return self.current_phase_dac_word + + + def test_dac_flatness(self, low_bound, high_bound, middle_samples): + """ + Take several TDC measurements using DAC settings from [low_bound, high_bound]. + Minimum number of measurements is 2, for the low and high bounds, and + middle_samples defines the number of measurements taken between the bounds. + + Writes these samples along with their corresponding DAC values to a file for + post-processing. + """ + results = [] + + self.log.trace("Starting DAC Flatness Test...") + self.log.trace("DAC Low Bound: {}. DAC High Bound: {}".format(low_bound, high_bound)) + + # open file for writing + meas_file = open("dac_flatness_results.txt", "w") + meas_file.write("DAC Word, Distance to Target (ns)\n") + + inc = math.floor((high_bound - low_bound)/(middle_samples + 1.0)) + + for x in range(middle_samples + 2): + self.log.info("Test Progress: {:.2f}%".format(x*100/(middle_samples+2))) + self.write_dac_word(x*inc + low_bound, 0.1) + distance_to_target = self.run_sync(measurement_only=True) + meas_file.write("{}, {:.4f}\n".format(x*inc + low_bound, distance_to_target*1e12)) + results.append(distance_to_target*1e12) + + meas_file.close() + + self.log.info("Results:") + for y in range(middle_samples + 2): + self.log.info("Word: {} Measurement: {:.6f}".format(y*inc + low_bound, results[y])) + + return True + diff --git a/mpm/python/usrp_mpm/dboard_manager/eiscat.py b/mpm/python/usrp_mpm/dboard_manager/eiscat.py index 822923fbf..06b647eec 100644 --- a/mpm/python/usrp_mpm/dboard_manager/eiscat.py +++ b/mpm/python/usrp_mpm/dboard_manager/eiscat.py @@ -571,6 +571,9 @@ class EISCAT(DboardManagerBase): self.ref_clock_freq, 1.9E-12, # TODO don't hardcode. This should live in the EEPROM self.INIT_PHASE_DAC_WORD, + 2.496e9, # lmk_vco_freq + [135e-9,], # target_values + 0x3, # spi_addr self.log ) _sync_db_clock(self.clock_synchronizer) |