diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 28e06bdd6..6c891909a 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -12,6 +12,9 @@ Highlights: * Implemented Phaser-MIQRO support. This requires the Phaser MIQRO gateware variant. * MSYS2 packaging for Windows. +* Sampler: adjusted ADC MU to Volt conversion base for Sampler since v2.2. + For earlier version please explicitly define it as an argument in the device database file + (e.g. ``"hw_rev": "v2.1"``). ARTIQ-7 ------- diff --git a/artiq/coredevice/coredevice_generic.schema.json b/artiq/coredevice/coredevice_generic.schema.json index 79527cf31..e29f76511 100644 --- a/artiq/coredevice/coredevice_generic.schema.json +++ b/artiq/coredevice/coredevice_generic.schema.json @@ -376,6 +376,9 @@ "minItems": 2, "maxItems": 2 }, + "sampler_hw_rev": { + "type": "string" + }, "urukul0_ports": { "type": "array", "items": { diff --git a/artiq/coredevice/sampler.py b/artiq/coredevice/sampler.py index 8679ad93c..caba223fe 100644 --- a/artiq/coredevice/sampler.py +++ b/artiq/coredevice/sampler.py @@ -15,24 +15,26 @@ SPI_CS_PGIA = 1 # separate SPI bus, CS used as RCLK @portable -def adc_mu_to_volt(data, gain=0): +def adc_mu_to_volt(data, gain=0, corrected_fs=True): """Convert ADC data in machine units to Volts. :param data: 16 bit signed ADC word :param gain: PGIA gain setting (0: 1, ..., 3: 1000) + :param corrected_fs: use corrected ADC FS reference. + Should be True for Samplers' revisions after v2.1. False for v2.1 and earlier. :return: Voltage in Volts """ if gain == 0: - volt_per_lsb = 20./(1 << 16) + volt_per_lsb = 20.48 / (1 << 16) if corrected_fs else 20. / (1 << 16) elif gain == 1: - volt_per_lsb = 2./(1 << 16) + volt_per_lsb = 2.048 / (1 << 16) if corrected_fs else 2. / (1 << 16) elif gain == 2: - volt_per_lsb = .2/(1 << 16) + volt_per_lsb = .2048 / (1 << 16) if corrected_fs else .2 / (1 << 16) elif gain == 3: - volt_per_lsb = .02/(1 << 16) + volt_per_lsb = 0.02048 / (1 << 16) if corrected_fs else .02 / (1 << 16) else: raise ValueError("invalid gain") - return data*volt_per_lsb + return data * volt_per_lsb class Sampler: @@ -48,12 +50,13 @@ class Sampler: :param gains: Initial value for PGIA gains shift register (default: 0x0000). Knowledge of this state is not transferred between experiments. + :param hw_rev: Sampler's hardware revision string (default 'v2.2') :param core_device: Core device name """ - kernel_invariants = {"bus_adc", "bus_pgia", "core", "cnv", "div"} + kernel_invariants = {"bus_adc", "bus_pgia", "core", "cnv", "div", "corrected_fs"} def __init__(self, dmgr, spi_adc_device, spi_pgia_device, cnv_device, - div=8, gains=0x0000, core_device="core"): + div=8, gains=0x0000, hw_rev="v2.2", core_device="core"): self.bus_adc = dmgr.get(spi_adc_device) self.bus_adc.update_xfer_duration_mu(div, 32) self.bus_pgia = dmgr.get(spi_pgia_device) @@ -62,6 +65,11 @@ class Sampler: self.cnv = dmgr.get(cnv_device) self.div = div self.gains = gains + self.corrected_fs = self.use_corrected_fs(hw_rev) + + @staticmethod + def use_corrected_fs(hw_rev): + return hw_rev != "v2.1" @kernel def init(self): @@ -144,4 +152,4 @@ class Sampler: for i in range(n): channel = i + 8 - len(data) gain = (self.gains >> (channel*2)) & 0b11 - data[i] = adc_mu_to_volt(adc_data[i], gain) + data[i] = adc_mu_to_volt(adc_data[i], gain, self.revision) diff --git a/artiq/coredevice/suservo.py b/artiq/coredevice/suservo.py index 1d0a72dad..26df13532 100644 --- a/artiq/coredevice/suservo.py +++ b/artiq/coredevice/suservo.py @@ -23,12 +23,12 @@ def y_mu_to_full_scale(y): @portable -def adc_mu_to_volts(x, gain): +def adc_mu_to_volts(x, gain, corrected_fs=True): """Convert servo ADC data from machine units to Volt.""" val = (x >> 1) & 0xffff mask = 1 << 15 val = -(val & mask) + (val & ~mask) - return sampler.adc_mu_to_volt(val, gain) + return sampler.adc_mu_to_volt(val, gain, corrected_fs) class SUServo: @@ -62,14 +62,15 @@ class SUServo: :param gains: Initial value for PGIA gains shift register (default: 0x0000). Knowledge of this state is not transferred between experiments. + :param sampler_hw_rev: Sampler's revision string :param core_device: Core device name """ kernel_invariants = {"channel", "core", "pgia", "cplds", "ddses", - "ref_period_mu"} + "ref_period_mu", "corrected_fs"} def __init__(self, dmgr, channel, pgia_device, cpld_devices, dds_devices, - gains=0x0000, core_device="core"): + gains=0x0000, sampler_hw_rev="v2.2", core_device="core"): self.core = dmgr.get(core_device) self.pgia = dmgr.get(pgia_device) @@ -81,6 +82,7 @@ class SUServo: self.gains = gains self.ref_period_mu = self.core.seconds_to_mu( self.core.coarse_ref_period) + self.corrected_fs = sampler.Sampler.use_corrected_fs(sampler_hw_rev) assert self.ref_period_mu == self.core.ref_multiplier @kernel @@ -234,7 +236,7 @@ class SUServo: """ val = self.get_adc_mu(channel) gain = (self.gains >> (channel*2)) & 0b11 - return adc_mu_to_volts(val, gain) + return adc_mu_to_volts(val, gain, self.corrected_fs) class Channel: diff --git a/artiq/frontend/artiq_ddb_template.py b/artiq/frontend/artiq_ddb_template.py index 275c6e42e..f359b65f0 100755 --- a/artiq/frontend/artiq_ddb_template.py +++ b/artiq/frontend/artiq_ddb_template.py @@ -410,10 +410,12 @@ class PeripheralManager: "arguments": {{ "spi_adc_device": "spi_{name}_adc", "spi_pgia_device": "spi_{name}_pgia", - "cnv_device": "ttl_{name}_cnv" + "cnv_device": "ttl_{name}_cnv", + "hw_rev": "{hw_rev}" }} }}""", name=self.get_name("sampler"), + hw_rev=peripheral.get("hw_rev", "v2.2"), adc_channel=rtio_offset, pgia_channel=rtio_offset + 1, cnv_channel=rtio_offset + 2) @@ -444,11 +446,13 @@ class PeripheralManager: "channel": 0x{suservo_channel:06x}, "pgia_device": "spi_{sampler_name}_pgia", "cpld_devices": {cpld_names_list}, - "dds_devices": {dds_names_list} + "dds_devices": {dds_names_list}, + "sampler_hw_rev": "{sampler_hw_rev}" }} }}""", suservo_name=suservo_name, sampler_name=sampler_name, + sampler_hw_rev=peripheral.get("sampler_hw_rev", "v2.2"), cpld_names_list=[urukul_name + "_cpld" for urukul_name in urukul_names], dds_names_list=[urukul_name + "_dds" for urukul_name in urukul_names], suservo_channel=rtio_offset+next(channel))