diff options
-rw-r--r-- | mpm/python/usrp_mpm/cores/tdc_sync.py | 19 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/magnesium.py | 37 |
2 files changed, 49 insertions, 7 deletions
diff --git a/mpm/python/usrp_mpm/cores/tdc_sync.py b/mpm/python/usrp_mpm/cores/tdc_sync.py index bb4695cb6..e8e3262d1 100644 --- a/mpm/python/usrp_mpm/cores/tdc_sync.py +++ b/mpm/python/usrp_mpm/cores/tdc_sync.py @@ -196,7 +196,7 @@ class ClockSynchronizer(object): meas_clk_freq = 170.542641116e6 measure_offset = lambda: self.read_tdc_meas( - 1/meas_clk_freq, 1/self.ref_clk_freq, 1/self.radio_clk_freq + 1.0/meas_clk_freq, 1.0/self.ref_clk_freq, 1.0/self.radio_clk_freq ) # Retrieve the first measurement, but throw it away since it won't align with # all the re-run measurements. @@ -208,7 +208,14 @@ class ClockSynchronizer(object): self.log.trace("Reading {} TDC measurements from device...".format(num_meas)) current_value = mean([measure_offset() for _ in range(num_meas)]) - if (current_value < 120e-9) or (current_value > 150e-9): + # The high and low bounds for this are set programmatically based on the + # Reference and Sample Frequencies and the TDC structure. The bounds are: + # Low = T_refclk + T_sampleclk*(3) + # High = T_refclk + T_sampleclk*(4) + # For slop, we add in another T_sampleclk on either side. + low_bound = 1.0/self.ref_clk_freq + (1.0/self.radio_clk_freq)*2 + high_bound = 1.0/self.ref_clk_freq + (1.0/self.radio_clk_freq)*5 + if (current_value < low_bound) or (current_value > high_bound): self.log.error("Clock synchronizer measured a " "current value of {:.3f} ns!".format( current_value*1e9 @@ -245,9 +252,9 @@ class ClockSynchronizer(object): def read_tdc_meas( self, - meas_clk_period=1/170.542641116e6, - ref_clk_period=1/10e6, - radio_clk_period=1/104e6 + meas_clk_period=1.0/170.542641116e6, + ref_clk_period=1.0/10e6, + radio_clk_period=1.0/104e6 ): """ Return the offset (in seconds) the whatever what measured and whatever @@ -307,7 +314,7 @@ class ClockSynchronizer(object): )) # Determine the sign. sign = 1 if distance_to_target >= 0 else -1 - coarse_step_size = 1/lmk_vco_freq + coarse_step_size = 1.0/lmk_vco_freq # For negative input values, divmod occasionally returns coarse steps -1 from # the correct value. To combat this blatent crime, I just give it a positive value # and then sign-correct afterwards. diff --git a/mpm/python/usrp_mpm/dboard_manager/magnesium.py b/mpm/python/usrp_mpm/dboard_manager/magnesium.py index f5d17a3f4..7cc1ca965 100644 --- a/mpm/python/usrp_mpm/dboard_manager/magnesium.py +++ b/mpm/python/usrp_mpm/dboard_manager/magnesium.py @@ -173,6 +173,23 @@ class Magnesium(DboardManagerBase): pdac_spi.poke16(0x0, init_phase_dac_word) self.spi_lock = self._device.get_spi_lock() return LMK04828Mg(lmk_spi, self.spi_lock, ref_clk_freq, slot_idx) + def _sync_db_clock(synchronizer): + " Synchronizes the DB clock to the common reference " + synchronizer.run_sync(measurement_only=False) + offset_error = synchronizer.run_sync(measurement_only=True) + if offset_error > 100e-12: + self.log.error("Clock synchronizer measured an offset of {:.1f} ps!".format( + offset_error*1e12 + )) + raise RuntimeError("Clock synchronizer measured an offset of {:.1f} ps!".format( + offset_error*1e12 + )) + else: + self.log.debug("Residual DAC offset error: {:.1f} ps.".format( + offset_error*1e12 + )) + self.log.info("Sample Clock Synchronization Complete!") + self.log.info("init() called with args `{}'".format( @@ -184,7 +201,6 @@ class Magnesium(DboardManagerBase): self._spi_ifaces = _init_spi_devices() self.log.info("Loaded SPI interfaces!") self.dboard_clk_control = _init_clock_control(self.radio_regs) - self.lmk = _init_lmk( self.slot_idx, self._spi_ifaces['lmk'], @@ -194,6 +210,25 @@ class Magnesium(DboardManagerBase): ) self.dboard_clk_control.enable_mmcm() self.log.info("Sample Clocks and Phase DAC Configured Successfully!") + # Synchronize DB Clocks + self.clock_synchronizer = ClockSynchronizer( + self.radio_regs, + self.dboard_clk_control, + self.lmk, + self._spi_ifaces['phase_dac'], + 0, # TODO this might not actually be zero + 125e6, # TODO don't hardcode + self.ref_clock_freq, + 860E-15, # TODO don't hardcode. This should live in the EEPROM + self.INIT_PHASE_DAC_WORD, + 3e9, # lmk_vco_freq + [128e-9,], # target_values + 0x0, # spi_addr TODO: make this a constant and replace in _sync_db_clock as well + self.log + ) + _sync_db_clock(self.clock_synchronizer) + # Clocks and PPS are now fully active! + self.init_jesd(self.radio_regs) |