From 6f0dcff4c2afecff7c3d83cf1cdfeeaff75ae39a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20J=C3=B6rdens?= Date: Mon, 6 Mar 2023 10:33:33 +0000 Subject: [PATCH] coredevice: support Almazny v1.2 This does not affect the legacy Almazny v1.1/v1.0 support. --- artiq/coredevice/almazny.py | 68 +++++++++++++++++++ .../coredevice/coredevice_generic.schema.json | 4 ++ artiq/coredevice/mirny.py | 5 +- artiq/frontend/artiq_ddb_template.py | 14 ++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 artiq/coredevice/almazny.py diff --git a/artiq/coredevice/almazny.py b/artiq/coredevice/almazny.py new file mode 100644 index 000000000..8e5634b9d --- /dev/null +++ b/artiq/coredevice/almazny.py @@ -0,0 +1,68 @@ +from artiq.language.core import kernel, portable + +from numpy import int32 + + +class AlmaznyChannel: + """ + One Almazny channel + + Almazny is a mezzanine for the Quad PLL RF source Mirny that exposes and + controls the frequency-doubled outputs. + + This driver requires Almazny hardware revision v1.2 or later + and Mirny CPLD gateware v0.3 or later. + + Use :class:`artiq.coredevice.mirny.Almazny` for Almazny hardware v1.1 and earlier. + + :param cpld_device: Mirny CPLD device name + :param channel: channel index (0-3) + """ + + def __init__(self, dmgr, cpld_device, channel): + self.channel = channel + self.cpld = dmgr.get(cpld_device) + + @portable + def to_mu(self, att, enable, led): + """ + Convert an attenuation in dB, RF switch state and LED state to machine + units. + + :param att: attenuator setting in dB (0-31.5) + :param enable: RF switch state (bool) + :param led: LED state (bool) + :return: channel setting in machine units + """ + mu = int32(round(att * 2.)) + if mu >= 64 or mu < 0: + raise ValueError("Attenuation out of range") + # unfortunate hardware design: bit reverse + mu = ((mu & 0x15) << 1) | ((mu >> 1) & 0x15) + mu = ((mu & 0x03) << 4) | (mu & 0x0c) | ((mu >> 4) & 0x03) + if enable: + mu |= 1 << 6 + if led: + mu |= 1 << 7 + return mu + + @kernel + def set_mu(self, mu): + """ + Set channel state (machine units). + + :param mu: channel state in machine units. + """ + self.cpld.write_ext( + addr=0xc + self.channel, length=8, data=mu, ext_div=32) + + @kernel + def set(self, att, enable, led=False): + """ + Set attenuation, RF switch, and LET state (SI units). + + :param att: attenuator setting in dB (0-31.5) + :param enable: RF switch state (bool) + :param led: LED state (bool) + """ + self.set_mu(self.to_mu(att, enable, led)) diff --git a/artiq/coredevice/coredevice_generic.schema.json b/artiq/coredevice/coredevice_generic.schema.json index 951184881..bd2d1db7c 100644 --- a/artiq/coredevice/coredevice_generic.schema.json +++ b/artiq/coredevice/coredevice_generic.schema.json @@ -511,6 +511,10 @@ "almazny": { "type": "boolean", "default": false + }, + "almazny_channel": { + "type": "boolean", + "default": false } }, "required": ["ports"] diff --git a/artiq/coredevice/mirny.py b/artiq/coredevice/mirny.py index b3643bbf1..542bae106 100644 --- a/artiq/coredevice/mirny.py +++ b/artiq/coredevice/mirny.py @@ -183,6 +183,9 @@ class Almazny: """ Almazny (High frequency mezzanine board for Mirny) + This applies to Almazny hardware v1.1 and earlier. + Use :class:`artiq.coredevice.almazny.AlmaznyChannel` for Almazny v1.2 and later. + :param host_mirny - Mirny device Almazny is connected to """ @@ -279,4 +282,4 @@ class Almazny: @kernel def _update_all_registers(self): for i in range(4): - self._update_register(i) \ No newline at end of file + self._update_register(i) diff --git a/artiq/frontend/artiq_ddb_template.py b/artiq/frontend/artiq_ddb_template.py index fe9e78971..3c992ecd1 100755 --- a/artiq/frontend/artiq_ddb_template.py +++ b/artiq/frontend/artiq_ddb_template.py @@ -326,6 +326,20 @@ class PeripheralManager: name=mirny_name, mchn=i) + if peripheral.get("almazny_channel", False): + self.gen(""" + device_db["{name}_almazny{i}"] = {{ + "type": "local", + "module": "artiq.coredevice.almazny", + "class": "AlmaznyChannel", + "arguments": {{ + "cpld_device": "{name}_cpld", + "channel": {i}, + }}, + }}""", + name=mirny_name, + i=i) + clk_sel = peripheral["clk_sel"] if isinstance(peripheral["clk_sel"], str): clk_sel = '"' + peripheral["clk_sel"] + '"'