From c7e992e26d41494cf64e4d989dc66e900559542d Mon Sep 17 00:00:00 2001 From: Marius Weber Date: Fri, 2 Apr 2021 11:16:14 +0100 Subject: [PATCH 01/13] Phaser: flake8 Signed-off-by: Marius Weber --- artiq/coredevice/dac34h84.py | 3 ++- artiq/coredevice/phaser.py | 4 +++- artiq/coredevice/trf372017.py | 7 ++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/artiq/coredevice/dac34h84.py b/artiq/coredevice/dac34h84.py index 155096a1e..e421851a7 100644 --- a/artiq/coredevice/dac34h84.py +++ b/artiq/coredevice/dac34h84.py @@ -178,7 +178,8 @@ class DAC34H84: (self.collisiongone_ena << 12) | (self.sif4_ena << 7) | (self.mixer_ena << 6) | (self.mixer_gain << 5) | (self.nco_ena << 4) | (self.revbus << 3) | (self.twos << 1)) - mmap.append((0x03 << 16) | (self.coarse_dac << 12) | (self.sif_txenable << 0)) + mmap.append((0x03 << 16) | (self.coarse_dac << 12) | + (self.sif_txenable << 0)) mmap.append( (0x07 << 16) | (self.mask_alarm_from_zerochk << 15) | (1 << 14) | diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index d5acf6501..604649a09 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -1,6 +1,8 @@ +from numpy import int32, int64 + from artiq.language.core import kernel, delay_mu, delay from artiq.coredevice.rtio import rtio_output, rtio_input_data -from artiq.language.units import us, ns, ms, MHz, dB +from artiq.language.units import us, ns, ms, MHz from artiq.language.types import TInt32 from artiq.coredevice.dac34h84 import DAC34H84 from artiq.coredevice.trf372017 import TRF372017 diff --git a/artiq/coredevice/trf372017.py b/artiq/coredevice/trf372017.py index 40957db86..75c153997 100644 --- a/artiq/coredevice/trf372017.py +++ b/artiq/coredevice/trf372017.py @@ -92,9 +92,10 @@ class TRF372017: (self.cal_clk_sel << 27)) mmap.append( 0xa | - (self.ndiv << 5) | (self.pll_div_sel << 21) | (self.prsc_sel << 23) | - (self.vco_sel << 26) | (self.vcosel_mode << 28) | - (self.cal_acc << 29) | (self.en_cal << 31)) + (self.ndiv << 5) | (self.pll_div_sel << 21) | + (self.prsc_sel << 23) | (self.vco_sel << 26) | + (self.vcosel_mode << 28) | (self.cal_acc << 29) | + (self.en_cal << 31)) mmap.append(0xb | (self.nfrac << 5)) mmap.append( 0xc | From eb477ee06b2a516f99353e801def9599f933ff53 Mon Sep 17 00:00:00 2001 From: Marius Weber Date: Sat, 8 May 2021 14:04:35 +0100 Subject: [PATCH 02/13] phaser: print gw_rev in debug mode --- artiq/coredevice/phaser.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index 604649a09..e165ba2f2 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -186,6 +186,9 @@ class Phaser: is_baseband = hw_rev & PHASER_HW_REV_VARIANT gw_rev = self.read8(PHASER_ADDR_GW_REV) + if debug: + print(gw_rev) + self.core.break_realtime() delay(.1*ms) # slack # allow a few errors during startup and alignment since boot From 7404152e4c38a5a061fcb293001300e1b04d02ca Mon Sep 17 00:00:00 2001 From: Marius Weber Date: Fri, 2 Apr 2021 11:18:59 +0100 Subject: [PATCH 03/13] Phaser upconverter: rename `ndiv` -> `nint` to match datasheet (close #1638) Signed-off-by: Marius Weber --- artiq/coredevice/trf372017.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/artiq/coredevice/trf372017.py b/artiq/coredevice/trf372017.py index 75c153997..e4f114847 100644 --- a/artiq/coredevice/trf372017.py +++ b/artiq/coredevice/trf372017.py @@ -11,7 +11,7 @@ class TRF372017: icp_double = 0 cal_clk_sel = 12 # /16, 4b - ndiv = 420 # 16b + nint = 420 # 16b pll_div_sel = 0 # /1, 2b prsc_sel = 1 # 8/9 vco_sel = 2 # 2b @@ -92,7 +92,7 @@ class TRF372017: (self.cal_clk_sel << 27)) mmap.append( 0xa | - (self.ndiv << 5) | (self.pll_div_sel << 21) | + (self.nint << 5) | (self.pll_div_sel << 21) | (self.prsc_sel << 23) | (self.vco_sel << 26) | (self.vcosel_mode << 28) | (self.cal_acc << 29) | (self.en_cal << 31)) From 1c96797de59e9c0c20abb94e9c665df348ea4f15 Mon Sep 17 00:00:00 2001 From: Marius Weber Date: Fri, 2 Apr 2021 14:32:42 +0100 Subject: [PATCH 04/13] Phaser upconverter: Follow datasheet procedure for VCO calibration (close #1643) Signed-off-by: Marius Weber --- artiq/coredevice/phaser.py | 29 +++++++++++++++++++++++++++++ artiq/coredevice/trf372017.py | 9 +++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index e165ba2f2..e122c75c1 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -323,6 +323,7 @@ class Phaser: delay(.2*ms) for data in channel.trf_mmap: channel.trf_write(data) + channel.cal_trf_vco() delay(2*ms) # lock if not (self.get_sta() & (PHASER_STA_TRF0_LD << ch)): @@ -331,6 +332,7 @@ class Phaser: if channel.trf_read(0) & 0x1000: raise ValueError("TRF R_SAT_ERR") delay(.1*ms) + channel.en_trf_out() # enable dac tx self.set_cfg(clk_sel=self.clk_sel) @@ -689,6 +691,7 @@ class PhaserChannel: self.phaser = phaser self.index = index self.trf_mmap = TRF372017(trf).get_mmap() + self.oscillator = [PhaserOscillator(self, osc) for osc in range(5)] @kernel @@ -891,6 +894,32 @@ class PhaserChannel: return self.trf_write(0x00000008 | (cnt_mux_sel << 27), readback=True) + @kernel + def cal_trf_vco(self): + """Start calibration of the upconverter (hardware variant) VCO. + + TRF outputs should be disabled during VCO calibration. + """ + self.trf_write(self.trf_mmap[1] | (1 << 31)) + + @kernel + def en_trf_out(self, rf=1, lo=0): + """Enable the rf/lo outputs of the upconverter (hardware variant). + + :param rf: 1 to enable RF output, 0 to disable + :param lo: 1 to enable LO output, 0 to disable + """ + data = self.trf_read(0xc) + delay(0.1 * ms) + # set RF and LO output bits + data = data | (1 << 12) | (1 << 13) | (1 << 14) + # clear to enable output + if rf == 1: + data = data ^ (1 << 14) + if lo == 1: + data = data ^ ((1 << 12) | (1 << 13)) + self.trf_write(data) + class PhaserOscillator: """Phaser IQ channel oscillator (NCO/DDS). diff --git a/artiq/coredevice/trf372017.py b/artiq/coredevice/trf372017.py index e4f114847..d6edb7313 100644 --- a/artiq/coredevice/trf372017.py +++ b/artiq/coredevice/trf372017.py @@ -17,7 +17,7 @@ class TRF372017: vco_sel = 2 # 2b vcosel_mode = 0 cal_acc = 0b00 # 2b - en_cal = 1 + en_cal = 0 # leave at 0 - calibration is performed in `Phaser.init()` nfrac = 0 # 25b @@ -27,9 +27,9 @@ class TRF372017: pwd_vcomux = 0 pwd_div124 = 0 pwd_presc = 0 - pwd_out_buff = 1 - pwd_lo_div = 1 - pwd_tx_div = 0 + pwd_out_buff = 1 # leave at 1 - only enable outputs after calibration + pwd_lo_div = 1 # leave at 1 - only enable outputs after calibration + pwd_tx_div = 1 # leave at 1 - only enable outputs after calibration pwd_bb_vcm = 0 pwd_dc_off = 0 en_extvco = 0 @@ -84,6 +84,7 @@ class TRF372017: setattr(self, key, value) def get_mmap(self): + """Memory map for TRF372017""" mmap = [] mmap.append( 0x9 | From 75445fe5f0659202590611917d03ea3a454ec57a Mon Sep 17 00:00:00 2001 From: Marius Weber Date: Fri, 2 Apr 2021 16:19:22 +0100 Subject: [PATCH 05/13] Phaser: expose and automate clearing of DAC `sif_sync` (close #1630 and #1650) `sif_sync` must be triggered to apply NCO frequency changes. To achieve per channel frequency tunability exeeding the range of the DUC, the NCO frequeny must adjusted. User code will need to trigger `sif_sync` to achieve this. `sif_sync` can only be triggered if the bit was cleared. To avoid this pitfall, the clearing of `sif_sync` is automated. Signed-off-by: Marius Weber --- artiq/coredevice/dac34h84.py | 2 +- artiq/coredevice/phaser.py | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/artiq/coredevice/dac34h84.py b/artiq/coredevice/dac34h84.py index e421851a7..51b93e6a0 100644 --- a/artiq/coredevice/dac34h84.py +++ b/artiq/coredevice/dac34h84.py @@ -110,7 +110,7 @@ class DAC34H84: syncsel_mixercd = 0b1001 # sif_sync and register write syncsel_nco = 0b1000 # sif_sync syncsel_fifo_input = 0b10 # external lvds istr - sif_sync = 1 + sif_sync = 0 syncsel_fifoin = 0b0010 # istr syncsel_fifoout = 0b0100 # ostr diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index e122c75c1..9626a1b78 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -229,6 +229,8 @@ class Phaser: for data in self.dac_mmap: self.dac_write(data >> 16, data) delay(40*us) + self.dac_sync() + delay(40*us) # pll_ndivsync_ena disable config18 = self.dac_read(0x18) @@ -556,6 +558,15 @@ class Phaser: """ return self.dac_read(0x06, div=257) >> 8 + @kernel + def dac_sync(self): + """Trigger DAC synchronisation for both output channels. + If the DAC-NCO is enabled, this applies NCO frequency changes.""" + config1f = self.dac_read(0x1f) + delay(.1*ms) + self.dac_write(0x1f, config1f & ~int32(1 << 1)) + self.dac_write(0x1f, config1f | (1 << 1)) + @kernel def get_dac_alarms(self): """Read the DAC alarm flags. @@ -768,6 +779,7 @@ class PhaserChannel: @kernel def set_nco_frequency_mu(self, ftw): """Set the NCO frequency. + The frequency is only applied after DAC synchronisation. :param ftw: NCO frequency tuning word (32 bit) """ @@ -777,6 +789,7 @@ class PhaserChannel: @kernel def set_nco_frequency(self, frequency): """Set the NCO frequency in SI units. + The frequency is only applied after DAC synchronisation. :param frequency: NCO frequency in Hz (passband from -400 MHz to 400 MHz, wrapping around at +- 500 MHz) From 407fba232dc10d922d46f218addffb9c158f00c2 Mon Sep 17 00:00:00 2001 From: Marius Weber Date: Fri, 2 Apr 2021 19:50:15 +0100 Subject: [PATCH 06/13] Phaser upconverter: set phase-frequency detector to 62.5 MHz (close #1648) The suitable PFD clock depends on the use case and will likely need to be configured by some users. All things being equal, a higher PFD clock is desirable as is results in lower local oscillator phase-noise. Phaser was designed around a maximum PFD clock of 62.5 MHz. In integer mode, with no local oscillator frequency divisor set, a 62.5 MHz PFD clock results in a 125 MHz local oscillator step size. Given the +-200 MHz range of the DUC (more if using the DAC mixer), this step size will be acceptable to many. This seems like the most appropreate default configuration as it should offer the best phase-noise performance. Signed-off-by: Marius Weber --- artiq/coredevice/trf372017.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/artiq/coredevice/trf372017.py b/artiq/coredevice/trf372017.py index d6edb7313..e09d355c2 100644 --- a/artiq/coredevice/trf372017.py +++ b/artiq/coredevice/trf372017.py @@ -4,16 +4,17 @@ class TRF372017: For possible values, documentation, and explanation, see the datasheet. https://www.ti.com/lit/gpn/trf372017 """ - rdiv = 21 # 13b + rdiv = 2 # 13b - highest valid f_PFD ref_inv = 0 neg_vco = 1 icp = 0 # 1.94 mA, 5b icp_double = 0 - cal_clk_sel = 12 # /16, 4b + cal_clk_sel = 0b1110 # div64, 4b - nint = 420 # 16b - pll_div_sel = 0 # /1, 2b - prsc_sel = 1 # 8/9 + # default f_vco is 2.875 GHz + nint = 23 # 16b - lowest value suitable for fractional & integer mode + pll_div_sel = 0b01 # div2, 2b + prsc_sel = 0 # 4/5 vco_sel = 2 # 2b vcosel_mode = 0 cal_acc = 0b00 # 2b @@ -59,8 +60,8 @@ class TRF372017: ioff = 0x80 # 8b qoff = 0x80 # 8b vref_sel = 4 # 0.85 V, 3b - tx_div_sel = 1 # div2, 2b - lo_div_sel = 3 # div8, 2b + tx_div_sel = 0 # div1, 2b + lo_div_sel = 0 # div1, 2b tx_div_bias = 1 # 37.5 µA, 2b lo_div_bias = 2 # 50 µA, 2b From 4f812cc4ed6ee8227fef0e58dbc31fdb3f13487a Mon Sep 17 00:00:00 2001 From: Marius Weber Date: Fri, 2 Apr 2021 21:19:09 +0100 Subject: [PATCH 07/13] Phaser: zero oscillator amplitude after `init()` (close #1651) Currently, `init()` leaves a single oscillator at full scale. The phase accumulator of this oscillator is held continuously cleared. Provided no upconverting mechanism is active (DUC, CMIX, NCO), this produces a full-scale DC voltage. The DC voltage is blocked by hardware capacitors. This behaviour is not mentioned by the `init` documentation. If one attempts to use any other oscillator without reducing the amplitude of the oscillator enabled by `init`, there is by significant clipping. In the case that the NCO or CMIX are configured via the device_db (suggested in the docs), leaving the osillator at full scale results in full RF output power after calling `init()`. This may plausibly damage loads driven by phaser. Signed-off-by: Marius Weber --- artiq/coredevice/phaser.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index 9626a1b78..7d26f238b 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -306,6 +306,9 @@ class Phaser: self.duc_stb() delay(.1*ms) # settle link, pipeline and impulse response data = channel.get_dac_data() + delay(1*us) + channel.oscillator[0].set_amplitude_phase_mu(asf=0, pow=0xc000, + clr=1) delay(.1*ms) sqrt2 = 0x5a81 # 0x7fff/sqrt(2) data_i = data & 0xffff From 515cfa7dfb9d0f5fc9834c05ac86989ffa65c6da Mon Sep 17 00:00:00 2001 From: Marius Weber Date: Fri, 2 Apr 2021 21:05:23 +0100 Subject: [PATCH 08/13] Phaser: expose coarse mixer and document need to enable the DAC-mixer. in some use cases a larger tunable range than available via the DUC may be needed. Some use cases may wish to combine the coarse mixer with the DUC to extend the tunable range. Signed-off-by: Marius Weber --- artiq/coredevice/phaser.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index 7d26f238b..13ed4e37a 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -570,6 +570,27 @@ class Phaser: self.dac_write(0x1f, config1f & ~int32(1 << 1)) self.dac_write(0x1f, config1f | (1 << 1)) + @kernel + def set_dac_cmix(self, fs_8_step): + """Set the DAC coarse mixer frequency for both channels + + The selected coarse mixer frequency becomes active without explicit + synchronisation. + + Use of the coarse mixer requires the DAC mixer to be enabled. The mixer + can be configured via the `dac` device_db entries. + + :param fs_8_step: coarse mixer frequency shift in 125 MHz steps. This + should be an integer between -3 and 4 (inclusive). + """ + # values recommended in data-sheet + # 0 1 2 3 4 -3 -2 -1 + vals = [0b0000, 0b1000, 0b0100, 0b1100, 0b0010, 0b1010, 0b0001, 0b1110] + cmix = vals[fs_8_step%8] + config0d = self.dac_read(0x0d) + delay(.1*ms) + self.dac_write(0x0d, (config0d & ~(0b1111 << 12)) | (cmix << 12)) + @kernel def get_dac_alarms(self): """Read the DAC alarm flags. @@ -784,6 +805,9 @@ class PhaserChannel: """Set the NCO frequency. The frequency is only applied after DAC synchronisation. + Use of the NCO requires the DAC mixer to be enabled. The mixer can be + configured via the `dac` device_db entries. + :param ftw: NCO frequency tuning word (32 bit) """ self.phaser.dac_write(0x15 + (self.index << 1), ftw >> 16) @@ -794,6 +818,9 @@ class PhaserChannel: """Set the NCO frequency in SI units. The frequency is only applied after DAC synchronisation. + Use of the NCO requires the DAC mixer to be enabled. The mixer can be + configured via the `dac` device_db entries. + :param frequency: NCO frequency in Hz (passband from -400 MHz to 400 MHz, wrapping around at +- 500 MHz) """ From 4fa202867167445b2ad94a93c73334e9b6220b66 Mon Sep 17 00:00:00 2001 From: Marius Weber Date: Tue, 6 Apr 2021 17:34:28 +0100 Subject: [PATCH 09/13] phaser: fix coarse mixer register offset The CMIX bits are bits 12-15 in register 0x0d. This has been checked against the datasheet and verified on hardware. Until now, the bit for CMIX1 was written to CMIX0. The CMIX0 bit was written to a reserved bit. Signed-off-by: Marius Weber --- artiq/coredevice/dac34h84.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/coredevice/dac34h84.py b/artiq/coredevice/dac34h84.py index 51b93e6a0..4063551aa 100644 --- a/artiq/coredevice/dac34h84.py +++ b/artiq/coredevice/dac34h84.py @@ -201,7 +201,7 @@ class DAC34H84: mmap.append( (0x0d << 16) | (self.cmix_fs8 << 15) | (self.cmix_fs4 << 14) | - (self.cmix_fs2 << 12) | (self.cmix_nfs4 << 11) | + (self.cmix_fs2 << 13) | (self.cmix_nfs4 << 12) | (self.qmc_gainb << 0)) mmap.append((0x0e << 16) | (self.qmc_gainc << 0)) mmap.append( From f97baa8aec4956d479620a47d798c5ebba5f4778 Mon Sep 17 00:00:00 2001 From: Marius Weber Date: Wed, 14 Apr 2021 16:20:44 +0100 Subject: [PATCH 10/13] phaser: workaround malformed output with `mixer_ena=1` & `nco_ena=0` When Phaser is powered on and `init()` is first called, enabling the DAC-mixer while leaving the NCO disabled causes malformed output. This commit implements a workaround by making sure the NCO is enabled, before being set to the disired state. This commit also avoids the following procedure, resulting in malformed output: 1. Operate Phaser with the DAC Mixer and NCO enabled 2. Set the NCO to a non-zero frequency 3. Disable the NCO in the device_db 4. Re-initialise Phaser After this procedure, with CMIX disabled, incorrect output is produced. To clear the fault one must re-enable the NCO and write the NCO freqeuncy to zero before disabling the NCO. Signed-off-by: Marius Weber --- artiq/coredevice/phaser.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index 13ed4e37a..9b091b2b6 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -279,6 +279,16 @@ class Phaser: else: raise ValueError("DAC alarm") + # avoid malformed output for: mixer_ena=1, nco_ena=0 after power up + self.dac_write(self.dac_mmap[2] >> 16, self.dac_mmap[2] | (1 << 4)) + delay(40*us) + self.dac_sync() + delay(100*us) + self.dac_write(self.dac_mmap[2] >> 16, self.dac_mmap[2]) + delay(40*us) + self.dac_sync() + delay(100*us) + # power up trfs, release att reset self.set_cfg(clk_sel=self.clk_sel, dac_txena=0) From 043c9c20d72ac4e3992dbcdbb8937423cf001b3d Mon Sep 17 00:00:00 2001 From: Marius Weber Date: Sat, 8 May 2021 13:11:51 +0100 Subject: [PATCH 11/13] phaser: Improve documentation of DAC settings 1. Clarify which features require additional configuration via the `dac` constructor argument. 2. Document when DAC settings apply immediatly/are staged. 3. Document how staged DAC settings may be applied 4. Calrify operation of `dac_sync` Signed-off-by: Marius Weber --- artiq/coredevice/phaser.py | 59 +++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index 9b091b2b6..740b9f02b 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -86,7 +86,8 @@ class Phaser: LVDS bus operating at 1 Gb/s per pin pair and processed in the DAC (Texas Instruments DAC34H84). On the DAC 2x interpolation, sinx/x compensation, quadrature modulator compensation, fine and coarse mixing as well as group - delay capabilities are available. + delay capabilities are available. If desired, these features my be + configured via the `dac` dictionary. The latency/group delay from the RTIO events setting :class:`PhaserOscillator` or :class:`PhaserChannel` DUC parameters all the @@ -574,7 +575,18 @@ class Phaser: @kernel def dac_sync(self): """Trigger DAC synchronisation for both output channels. - If the DAC-NCO is enabled, this applies NCO frequency changes.""" + + The DAC sif_sync is de-asserts, then asserted. The synchronisation is + triggered on assertion. + + By default, the fine-mixer (NCO) and QMC are synchronised. This + includes applying the latest register settings. + + The synchronisation sources may be configured through the `syncsel_x` + fields in the `dac` configuration dictionary (see `__init__()`). + + .. note:: Synchronising the NCO clears the phase-accumulator + """ config1f = self.dac_read(0x1f) delay(.1*ms) self.dac_write(0x1f, config1f & ~int32(1 << 1)) @@ -584,12 +596,13 @@ class Phaser: def set_dac_cmix(self, fs_8_step): """Set the DAC coarse mixer frequency for both channels + Use of the coarse mixer requires the DAC mixer to be enabled. The mixer + can be configured via the `dac` configuration dictionary (see + `__init__()`). + The selected coarse mixer frequency becomes active without explicit synchronisation. - Use of the coarse mixer requires the DAC mixer to be enabled. The mixer - can be configured via the `dac` device_db entries. - :param fs_8_step: coarse mixer frequency shift in 125 MHz steps. This should be an integer between -3 and 4 (inclusive). """ @@ -813,10 +826,12 @@ class PhaserChannel: @kernel def set_nco_frequency_mu(self, ftw): """Set the NCO frequency. - The frequency is only applied after DAC synchronisation. - Use of the NCO requires the DAC mixer to be enabled. The mixer can be - configured via the `dac` device_db entries. + This method stages the new NCO frequency, but does not apply it. + + Use of the DAC-NCO requires the DAC mixer and NCO to be enabled. These + can be configured via the `dac` configuration dictionary (see + `__init__()`). :param ftw: NCO frequency tuning word (32 bit) """ @@ -826,10 +841,12 @@ class PhaserChannel: @kernel def set_nco_frequency(self, frequency): """Set the NCO frequency in SI units. - The frequency is only applied after DAC synchronisation. - Use of the NCO requires the DAC mixer to be enabled. The mixer can be - configured via the `dac` device_db entries. + This method stages the new NCO frequency, but does not apply it. + + Use of the DAC-NCO requires the DAC mixer and NCO to be enabled. These + can be configured via the `dac` configuration dictionary (see + `__init__()`). :param frequency: NCO frequency in Hz (passband from -400 MHz to 400 MHz, wrapping around at +- 500 MHz) @@ -841,6 +858,16 @@ class PhaserChannel: def set_nco_phase_mu(self, pow): """Set the NCO phase offset. + By default, the new NCO phase applies on completion of the SPI + transfer. This also causes a staged NCO frequency to be applied. + Different triggers for applying nco settings may be configured through + the `syncsel_mixerxx` fields in the `dac` configuration dictionary (see + `__init__()`). + + Use of the DAC-NCO requires the DAC mixer and NCO to be enabled. These + can be configured via the `dac` configuration dictionary (see + `__init__()`). + :param pow: NCO phase offset word (16 bit) """ self.phaser.dac_write(0x12 + self.index, pow) @@ -849,6 +876,16 @@ class PhaserChannel: def set_nco_phase(self, phase): """Set the NCO phase in SI units. + By default, the new NCO phase applies on completion of the SPI + transfer. This also causes a staged NCO frequency to be applied. + Different triggers for applying nco settings may be configured through + the `syncsel_mixerxx` fields in the `dac` configuration dictionary (see + `__init__()`). + + Use of the DAC-NCO requires the DAC mixer and NCO to be enabled. These + can be configured via the `dac` configuration dictionary (see + `__init__()`). + :param phase: NCO phase in turns """ pow = int32(round(phase*(1 << 16))) From fb6fad7c646068b7ba729e84f95917537b1a9f83 Mon Sep 17 00:00:00 2001 From: Marius Weber Date: Wed, 14 Apr 2021 17:29:09 +0100 Subject: [PATCH 12/13] update release notes Signed-off-by: Marius Weber --- RELEASE_NOTES.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 11a126813..1c668fd3f 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -9,8 +9,17 @@ ARTIQ-7 Highlights: * WRPLL * ``get()``, ``get_mu()``, ``get_att()``, and ``get_att_mu()`` functions added for AD9910 and AD9912 +* Phaser: + - Improved documentation + - Expose the DAC coarse mixer and sif_sync + - Exposes upconverter calibration and enabling/disabling of upconverter LO & RF outputs. Breaking changes: +* Updated Phaser-Upconverter default frequency 2.875 GHz. The new default uses the target PFD + frequency of the hardware design. +* `Phaser.init()` now disables all Kasli-oscillators. This avoids full power RF output being + generated for some configurations. +* Phaser: fixed coarse mixer frequency configuration ARTIQ-6 From 129cf8c1dd328efd333570aa873834b0b1e5f13c Mon Sep 17 00:00:00 2001 From: Marius Weber Date: Tue, 11 May 2021 23:16:14 +0100 Subject: [PATCH 13/13] Phaser: Make set_nco_phase set the phase of the NCO Previous to this commit `set_nco_phase()` set the phase of the DUC instead of the NCO. Setting the phase of the NCO may be desirable to utilise the auto-sync functionality of the double-buffered DAC-NCO settings. Signed-off-by: Marius Weber --- artiq/coredevice/phaser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/coredevice/phaser.py b/artiq/coredevice/phaser.py index 740b9f02b..c8c3c0938 100644 --- a/artiq/coredevice/phaser.py +++ b/artiq/coredevice/phaser.py @@ -889,7 +889,7 @@ class PhaserChannel: :param phase: NCO phase in turns """ pow = int32(round(phase*(1 << 16))) - self.set_duc_phase_mu(pow) + self.set_nco_phase_mu(pow) @kernel def set_att_mu(self, data):