2
0
mirror of https://github.com/m-labs/artiq.git synced 2024-12-27 04:08:27 +08:00

coredevice/mirny: port to NAC3

This commit is contained in:
Sebastien Bourdeauducq 2021-11-23 17:13:43 +08:00
parent f5a5b7a22a
commit 29f42ccd8a

View File

@ -1,23 +1,24 @@
"""RTIO driver for Mirny (4 channel GHz PLLs)
"""
from artiq.language.core import kernel, delay
from artiq.language.core import nac3, KernelInvariant, kernel
from artiq.language.units import us
from numpy import int32
from artiq.coredevice import spi2 as spi
from artiq.coredevice.core import Core
from artiq.coredevice.spi2 import *
SPI_CONFIG = (
0 * spi.SPI_OFFLINE
| 0 * spi.SPI_END
| 0 * spi.SPI_INPUT
| 1 * spi.SPI_CS_POLARITY
| 0 * spi.SPI_CLK_POLARITY
| 0 * spi.SPI_CLK_PHASE
| 0 * spi.SPI_LSB_FIRST
| 0 * spi.SPI_HALF_DUPLEX
0 * SPI_OFFLINE
| 0 * SPI_END
| 0 * SPI_INPUT
| 1 * SPI_CS_POLARITY
| 0 * SPI_CLK_POLARITY
| 0 * SPI_CLK_PHASE
| 0 * SPI_LSB_FIRST
| 0 * SPI_HALF_DUPLEX
)
# SPI clock write and read dividers
@ -32,6 +33,7 @@ WE = 1 << 24
PROTO_REV_MATCH = 0x0
@nac3
class Mirny:
"""
Mirny PLL-based RF generator.
@ -46,8 +48,12 @@ class Mirny:
The effect depends on the hardware revision.
:param core_device: Core device name (default: "core")
"""
kernel_invariants = {"bus", "core", "refclk", "clk_sel_hw_rev"}
core: KernelInvariant[Core]
bus: KernelInvariant[SPIMaster]
refclk: KernelInvariant[float]
clk_sel_hw_rev: list[int32]
hw_rev: int32
clk_sel: int32
def __init__(self, dmgr, spi_device, refclk=100e6, clk_sel="XO", core_device="core"):
self.core = dmgr.get(core_device)
@ -81,22 +87,22 @@ class Mirny:
# TODO: support clk_div on v1.0 boards
@kernel
def read_reg(self, addr):
def read_reg(self, addr: int32) -> int32:
"""Read a register"""
self.bus.set_config_mu(
SPI_CONFIG | spi.SPI_INPUT | spi.SPI_END, 24, SPIT_RD, SPI_CS
SPI_CONFIG | SPI_INPUT | SPI_END, 24, SPIT_RD, SPI_CS
)
self.bus.write((addr << 25))
return self.bus.read() & int32(0xFFFF)
return self.bus.read() & 0xFFFF
@kernel
def write_reg(self, addr, data):
def write_reg(self, addr: int32, data: int32):
"""Write a register"""
self.bus.set_config_mu(SPI_CONFIG | spi.SPI_END, 24, SPIT_WR, SPI_CS)
self.bus.set_config_mu(SPI_CONFIG | SPI_END, 24, SPIT_WR, SPI_CS)
self.bus.write((addr << 25) | WE | ((data & 0xFFFF) << 8))
@kernel
def init(self, blind=False):
def init(self, blind: bool = False):
"""
Initialize and detect Mirny.
@ -110,33 +116,35 @@ class Mirny:
if not blind:
if (reg0 >> 2) & 0x3 != PROTO_REV_MATCH:
raise ValueError("Mirny PROTO_REV mismatch")
delay(100 * us) # slack
# NAC3TODO raise ValueError("Mirny PROTO_REV mismatch")
pass
self.core.delay(100. * us) # slack
# select clock source
self.clk_sel = self.clk_sel_hw_rev[self.hw_rev]
if self.clk_sel < 0:
raise ValueError("Hardware revision not supported")
# NAC3TODO raise ValueError("Hardware revision not supported")
pass
self.write_reg(1, (self.clk_sel << 4))
delay(1000 * us)
self.core.delay(1000. * us)
@kernel
def set_att_mu(self, channel, att):
def set_att_mu(self, channel: int32, att: int32):
"""Set digital step attenuator in machine units.
:param att: Attenuation setting, 8 bit digital.
"""
self.bus.set_config_mu(SPI_CONFIG | spi.SPI_END, 16, SPIT_WR, SPI_CS)
self.bus.set_config_mu(SPI_CONFIG | SPI_END, 16, SPIT_WR, SPI_CS)
self.bus.write(((channel | 8) << 25) | (att << 16))
@kernel
def write_ext(self, addr, length, data):
def write_ext(self, addr: int32, length: int32, data: int32):
"""Perform SPI write to a prefixed address"""
self.bus.set_config_mu(SPI_CONFIG, 8, SPIT_WR, SPI_CS)
self.bus.write(addr << 25)
self.bus.set_config_mu(SPI_CONFIG | spi.SPI_END, length, SPIT_WR, SPI_CS)
self.bus.set_config_mu(SPI_CONFIG | SPI_END, length, SPIT_WR, SPI_CS)
if length < 32:
data <<= 32 - length
self.bus.write(data)