@@ -103,10 +103,9 @@ def __init__(self, si, idx, denominator_max = DENOMINATOR_MAX):
103
103
self ._si = si
104
104
self ._idx = idx
105
105
106
- # set divider first, source second.
107
106
self .denominator_max = denominator_max
108
- self ._set_divider (self .DIVIDER_DEFAULT )
109
107
self ._source = None
108
+ self ._set_divider (self .DIVIDER_DEFAULT )
110
109
# self.set_input_source() # need implement
111
110
112
111
@@ -244,7 +243,14 @@ def _set_parameters(self, p1, p2, p3):
244
243
245
244
246
245
def _post_set_divider (self ):
247
- pass
246
+ self ._maintain_phase_offset ()
247
+
248
+
249
+ def _maintain_phase_offset (self ):
250
+ if self .pll :
251
+ # https://groups.io/g/BITX20/topic/si5351a_facts_and_myths/5430607
252
+ # need to reset PLL in order to synch phases of outputs.
253
+ self .pll .reset ()
248
254
249
255
250
256
class _PLL (_MultisynthBase ):
@@ -264,7 +270,7 @@ class _PLL(_MultisynthBase):
264
270
265
271
def __init__ (self , si , name , xtal_as_source = True ):
266
272
self ._name = name
267
- super ().__init__ (si , self .NAMES [name ])
273
+ super ().__init__ (si , idx = self .NAMES [name ])
268
274
self ._xtal_as_source = xtal_as_source
269
275
self .init ()
270
276
@@ -463,9 +469,6 @@ def _set_divided_by_4(self, value = True):
463
469
464
470
self ._post_set_divider ()
465
471
466
- if self .pll :
467
- self .pll .reset () # need to reset PLL after switching mode.
468
-
469
472
470
473
class _Clock (_MultisynthBase ):
471
474
@@ -490,6 +493,7 @@ def __init__(self, si, idx,
490
493
self ._set_disable_state (disable_state )
491
494
self .set_input_source (source )
492
495
self .set_frequency (self ._si .FREQ_REF if freq is None else freq )
496
+ self .set_phase (PHASE_DEFAULT )
493
497
494
498
495
499
@property
@@ -672,16 +676,6 @@ def _set_divider(self, divider = 1):
672
676
self ._si ._write_element_by_name ('R{}_DIV' .format (self ._idx ), self .R_DIVIDERs [divider ])
673
677
674
678
675
- def _post_set_divider (self ):
676
- self ._maintain_phase_offset ()
677
-
678
-
679
- def _maintain_phase_offset (self ):
680
- if self .phase_offset_enabled : # https://groups.io/g/BITX20/topic/si5351a_facts_and_myths/5430607
681
- if self .pll :
682
- self .pll .reset ()
683
-
684
-
685
679
@property
686
680
def phase_offset_enabled (self ):
687
681
if self ._idx in range (self .N_MULTISYNTHS_WITH_OUTPUT_SKEW ):
@@ -691,13 +685,6 @@ def phase_offset_enabled(self):
691
685
692
686
def set_phase (self , phase ):
693
687
self ._action = 'set_phase {} idx {}' .format (phase , self ._idx )
694
- my_period = 1 / self .freq
695
- offset_seconds = (phase % DEGREES_IN_PI2 ) / DEGREES_IN_PI2 * my_period
696
- self .set_phase_offset (offset_seconds )
697
-
698
-
699
- def set_phase_offset (self , offset_seconds = 0 ):
700
- self ._si ._action = 'set_phase_offset {}' .format (offset_seconds )
701
688
702
689
# Set offset_seconds = 0 to disable it.
703
690
#
@@ -713,18 +700,33 @@ def set_phase_offset(self, offset_seconds = 0):
713
700
# CLKx_PHOFF[4:0] = Round(DesiredOffset(sec) * 4 * FVCO)
714
701
# ==> typo, should be [6:0]
715
702
716
- if self ._idx in range (self .N_MULTISYNTHS_WITH_OUTPUT_SKEW ):
717
- if self .multisynth is not None :
718
- self ._si .multisynths [self ._idx ]._set_integer_mode (False )
703
+ if self ._idx in range (self .N_MULTISYNTHS_WITH_OUTPUT_SKEW ) and self .multisynth is not None :
719
704
720
- freq_vco = self .pll .freq # PLL
721
- offset = int (round (offset_seconds * 4 * freq_vco ))
722
- self ._set_phase_offset (offset )
705
+ cycle = (phase % DEGREES_IN_PI2 ) / DEGREES_IN_PI2
706
+ freq_vco = self .pll .freq # PLL
707
+
708
+ freq_min = cycle * freq_vco * 4 / (2 ** 7 - 0.5 ) # CLKx_PHOFF has 7 bits, must < 128 after rounded.
709
+ assert self .freq > freq_min , \
710
+ 'my freq must be greater than {:0.3e} to have {} degree phase offset.' .format (freq_min , phase )
711
+
712
+ my_period = 1 / self .freq
713
+ offset_seconds = cycle * my_period
714
+ offset = int (round (offset_seconds * 4 * freq_vco ))
715
+ self ._set_phase_offset (offset )
716
+
717
+ if phase != 0 :
718
+ self .multisynth ._set_integer_mode (False )
719
+ else :
720
+ self .multisynth .restore_frequency () # restore integer mode if applicable.
721
+
722
+ self ._maintain_phase_offset () # need to reset PLL
723
723
724
724
725
725
@property
726
726
def phase_offset (self ):
727
- return self ._si .map .elements ['CLK{}_PHOFF' .format (self ._idx )]['element' ].value
727
+ if self ._idx in range (self .N_MULTISYNTHS_WITH_OUTPUT_SKEW ) and self .multisynth is not None :
728
+ return self ._si .map .elements ['CLK{}_PHOFF' .format (self ._idx )]['element' ].value
729
+ return 0
728
730
729
731
730
732
@property
@@ -740,6 +742,8 @@ def _set_phase_offset(self, offset = 0):
740
742
# CLKx_PHOFF[6:0] is an unsigned integer with one LSB equivalent to a time delay of
741
743
# Tvco/4, where Tvco is the period of the VCO/PLL associated with this output.
742
744
745
+ # assert 0 <= offset < 2 ** 7, 'offset ({}) should be less than 128.'.format(offset)
746
+
743
747
self ._si ._write_element_by_name ('CLK{}_PHOFF' .format (self ._idx ), offset & 0x7F )
744
748
745
749
@@ -926,8 +930,8 @@ def init(self):
926
930
for i in self .channels_in_use :
927
931
self .clocks [i ].power_down (False ) # Just power up clocks in use.
928
932
929
- self .reset_plls ()
930
933
self .start ()
934
+ self .reset_plls ()
931
935
932
936
933
937
def reset_plls (self ):
0 commit comments