1
0
forked from M-Labs/artiq

ad9834: port to nac3

This commit is contained in:
Sébastien Bourdeauducq 2024-12-17 17:29:11 +08:00
parent 62faca81e9
commit 7c93a69e6f

View File

@ -5,10 +5,12 @@ RTIO Driver for the Analog Devices AD9834 DDS via 3-wire SPI interface.
# https://www.analog.com/media/en/technical-documentation/data-sheets/AD9834.pdf
# https://www.analog.com/media/en/technical-documentation/app-notes/an-1070.pdf
from artiq.coredevice import spi2 as spi
from numpy import int32
from artiq.coredevice.core import Core
from artiq.coredevice.spi2 import *
from artiq.experiment import *
from artiq.language.core import *
from artiq.language.types import *
from artiq.language.units import *
AD9834_B28 = 1 << 13
@ -34,6 +36,7 @@ AD9834_PHASE_REG_1 = AD9834_PHASE_REG | (1 << 13)
PHASE_REGS = [AD9834_PHASE_REG_0, AD9834_PHASE_REG_1]
@nac3
class AD9834:
"""
AD9834 DDS driver.
@ -51,14 +54,18 @@ class AD9834:
:param core_device: Core device name (default: "core").
"""
kernel_invariants = {"core", "bus", "spi_freq", "clk_freq"}
core: KernelInvariant[Core]
bus: KernelInvariant[SPIMaster]
spi_freq: KernelInvariant[float]
clk_freq: KernelInvariant[float]
ctrl_reg: Kernel[int32]
def __init__(
self, dmgr, spi_device, spi_freq=10 * MHz, clk_freq=75 * MHz, core_device="core"
self, dmgr, spi_device, spi_freq=10. * MHz, clk_freq=75. * MHz, core_device="core"
):
self.core = dmgr.get(core_device)
self.bus = dmgr.get(spi_device)
assert spi_freq <= 40 * MHz, "SPI frequency exceeds maximum value of 40 MHz"
assert spi_freq <= 40. * MHz, "SPI frequency exceeds maximum value of 40 MHz"
self.spi_freq = spi_freq
self.clk_freq = clk_freq
self.ctrl_reg = 0x0000 # Reset control register
@ -81,11 +88,11 @@ class AD9834:
This method should be called before any other operations are performed
on the AD9834 to ensure that the device is in a known state.
"""
self.bus.set_config(spi.SPI_CLK_POLARITY | spi.SPI_END, 16, self.spi_freq, 1)
self.bus.set_config(SPI_CLK_POLARITY | SPI_END, 16, self.spi_freq, 1)
self.enable_reset()
@kernel
def set_frequency_reg(self, freq_reg, frequency: TFloat):
def set_frequency_reg(self, freq_reg: int32, frequency: float):
"""
Set the frequency for the specified frequency register.
@ -107,10 +114,11 @@ class AD9834:
then sends the fourteen least significant bits LSBs and fourteen most significant
bits MSBs in two consecutive writes to the specified frequency register.
"""
if freq_reg not in FREQ_REGS:
raise ValueError("Invalid frequency register")
# NAC3TODO
#if freq_reg not in FREQ_REGS:
# raise ValueError("Invalid frequency register")
assert frequency <= 37.5 * MHz, "Frequency exceeds maximum value of 37.5 MHz"
freq_word = int((frequency * (1 << 28)) / self.clk_freq) & 0x0FFFFFFF
freq_word = int32((frequency * float(1 << 28)) / self.clk_freq) & 0x0FFFFFFF
self.ctrl_reg |= AD9834_B28
self.write(self.ctrl_reg)
lsb = freq_word & 0x3FFF
@ -119,7 +127,7 @@ class AD9834:
self.write(freq_reg | msb)
@kernel
def set_frequency_reg_msb(self, freq_reg, word: TInt32):
def set_frequency_reg_msb(self, freq_reg: int32, word: int32):
"""
Set the fourteen most significant bits MSBs of the specified frequency register.
@ -134,15 +142,16 @@ class AD9834:
indicate that the MSB is being sent, and then writes the updated control register
followed by the MSB value to the specified frequency register.
"""
if freq_reg not in FREQ_REGS:
raise ValueError("Invalid frequency register")
# NAC3TODO
#if freq_reg not in FREQ_REGS:
# raise ValueError("Invalid frequency register")
self.ctrl_reg &= ~AD9834_B28
self.ctrl_reg |= AD9834_HLB
self.write(self.ctrl_reg)
self.write(freq_reg | (word & 0x3FFF))
@kernel
def set_frequency_reg_lsb(self, freq_reg, word: TInt32):
def set_frequency_reg_lsb(self, freq_reg: int32, word: int32):
"""
Set the fourteen least significant bits LSBs of the specified frequency register.
@ -156,15 +165,16 @@ class AD9834:
The method first clears the appropriate control bits and writes the updated control
register followed by the LSB value to the specified frequency register.
"""
if freq_reg not in FREQ_REGS:
raise ValueError("Invalid frequency register")
# NAC3TODO
#if freq_reg not in FREQ_REGS:
# raise ValueError("Invalid frequency register")
self.ctrl_reg &= ~AD9834_B28
self.ctrl_reg &= ~AD9834_HLB
self.write(self.ctrl_reg)
self.write(freq_reg | (word & 0x3FFF))
@kernel
def select_frequency_reg(self, freq_reg):
def select_frequency_reg(self, freq_reg: int32):
"""
Select the active frequency register for the phase accumulator.
@ -175,8 +185,9 @@ class AD9834:
:param freq_reg: The frequency register to select. Must be one of
:const:`AD9834_FREQ_REG_0` or :const:`AD9834_FREQ_REG_1`.
"""
if freq_reg not in FREQ_REGS:
raise ValueError("Invalid frequency register")
# NAC3TODO
#if freq_reg not in FREQ_REGS:
# raise ValueError("Invalid frequency register")
if freq_reg == FREQ_REGS[0]:
self.ctrl_reg &= ~AD9834_FSEL
else:
@ -186,7 +197,7 @@ class AD9834:
self.write(self.ctrl_reg)
@kernel
def set_phase_reg(self, phase_reg, phase: TInt32):
def set_phase_reg(self, phase_reg: int32, phase: int32):
"""
Set the phase for the specified phase register.
@ -199,13 +210,14 @@ class AD9834:
The method masks the phase value to ensure it fits within the 12-bit limit
and writes it to the specified phase register.
"""
if phase_reg not in PHASE_REGS:
raise ValueError("Invalid phase register")
# NAC3TODO
#if phase_reg not in PHASE_REGS:
# raise ValueError("Invalid phase register")
phase_word = phase & 0x0FFF
self.write(phase_reg | phase_word)
@kernel
def select_phase_reg(self, phase_reg):
def select_phase_reg(self, phase_reg: int32):
"""
Select the active phase register for the phase accumulator.
@ -216,8 +228,9 @@ class AD9834:
:param phase_reg: The phase register to select. Must be one of
:const:`AD9834_PHASE_REG_0` or :const:`AD9834_PHASE_REG_1`.
"""
if phase_reg not in PHASE_REGS:
raise ValueError("Invalid phase register")
# NAC3TODO
#if phase_reg not in PHASE_REGS:
# raise ValueError("Invalid phase register")
if phase_reg == PHASE_REGS[0]:
self.ctrl_reg &= ~AD9834_PSEL
else:
@ -380,7 +393,7 @@ class AD9834:
self.write(self.ctrl_reg)
@kernel
def write(self, data: TInt32):
def write(self, data: int32):
"""
Write a 16-bit word to the AD9834.