i2c: port to NAC3

This commit is contained in:
Sebastien Bourdeauducq 2022-03-01 17:21:54 +08:00
parent e6f26b5c74
commit 01e55f5731
1 changed files with 34 additions and 13 deletions

View File

@ -3,8 +3,10 @@ Non-realtime drivers for I2C chips on the core device.
""" """
from numpy import int32 from numpy import int32
from artiq.language.core import extern, kernel
from artiq.language.core import nac3, extern, kernel, KernelInvariant
from artiq.coredevice.exceptions import I2CError from artiq.coredevice.exceptions import I2CError
from artiq.coredevice.core import Core
@extern @extern
@ -32,13 +34,13 @@ def i2c_read(busno: int32, ack: bool) -> int32:
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")
@syscall(flags={"nounwind", "nowrite"}) @extern
def i2c_switch_select(busno: TInt32, address: TInt32, mask: TInt32) -> TNone: def i2c_switch_select(busno: int32, address: int32, mask: int32):
raise NotImplementedError("syscall not simulated") raise NotImplementedError("syscall not simulated")
@kernel @kernel
def i2c_poll(busno, busaddr): def i2c_poll(busno: int32, busaddr: int32) -> bool:
"""Poll I2C device at address. """Poll I2C device at address.
:param busno: I2C bus number :param busno: I2C bus number
@ -52,7 +54,7 @@ def i2c_poll(busno, busaddr):
@kernel @kernel
def i2c_write_byte(busno, busaddr, data, ack=True): def i2c_write_byte(busno: int32, busaddr: int32, data: int32, ack: bool = True):
"""Write one byte to a device. """Write one byte to a device.
:param busno: I2C bus number :param busno: I2C bus number
@ -71,7 +73,7 @@ def i2c_write_byte(busno, busaddr, data, ack=True):
@kernel @kernel
def i2c_read_byte(busno, busaddr): def i2c_read_byte(busno: int32, busaddr: int32) -> int32:
"""Read one byte from a device. """Read one byte from a device.
:param busno: I2C bus number :param busno: I2C bus number
@ -90,7 +92,7 @@ def i2c_read_byte(busno, busaddr):
@kernel @kernel
def i2c_write_many(busno, busaddr, addr, data, ack_last=True): def i2c_write_many(busno: int32, busaddr: int32, addr: int32, data: list[int32], ack_last: bool = True):
"""Transfer multiple bytes to a device. """Transfer multiple bytes to a device.
:param busno: I2c bus number :param busno: I2c bus number
@ -116,7 +118,7 @@ def i2c_write_many(busno, busaddr, addr, data, ack_last=True):
@kernel @kernel
def i2c_read_many(busno, busaddr, addr, data): def i2c_read_many(busno: int32, busaddr: int32, addr: int32, data: list[int32]):
"""Transfer multiple bytes from a device. """Transfer multiple bytes from a device.
:param busno: I2c bus number :param busno: I2c bus number
@ -141,6 +143,7 @@ def i2c_read_many(busno, busaddr, addr, data):
i2c_stop(busno) i2c_stop(busno)
@nac3
class I2CSwitch: class I2CSwitch:
"""Driver for the I2C bus switch. """Driver for the I2C bus switch.
@ -152,13 +155,18 @@ class I2CSwitch:
On the KC705, this chip is used for selecting the I2C buses on the two FMC On the KC705, this chip is used for selecting the I2C buses on the two FMC
connectors. HPC=1, LPC=2. connectors. HPC=1, LPC=2.
""" """
core: KernelInvariant[Core]
busno: KernelInvariant[int32]
address: KernelInvariant[int32]
def __init__(self, dmgr, busno=0, address=0xe8, core_device="core"): def __init__(self, dmgr, busno=0, address=0xe8, core_device="core"):
self.core = dmgr.get(core_device) self.core = dmgr.get(core_device)
self.busno = busno self.busno = busno
self.address = address self.address = address
@kernel @kernel
def set(self, channel): def set(self, channel: int32):
"""Enable one channel. """Enable one channel.
:param channel: channel number (0-7) :param channel: channel number (0-7)
""" """
@ -171,6 +179,7 @@ class I2CSwitch:
i2c_switch_select(self.busno, self.address >> 1, 0) i2c_switch_select(self.busno, self.address >> 1, 0)
@kernel
class TCA6424A: class TCA6424A:
"""Driver for the TCA6424A I2C I/O expander. """Driver for the TCA6424A I2C I/O expander.
@ -179,18 +188,23 @@ class TCA6424A:
On the NIST QC2 hardware, this chip is used for switching the directions On the NIST QC2 hardware, this chip is used for switching the directions
of TTL buffers.""" of TTL buffers."""
core: KernelInvariant[Core]
busno: KernelInvariant[int32]
address: KernelInvariant[int32]
def __init__(self, dmgr, busno=0, address=0x44, core_device="core"): def __init__(self, dmgr, busno=0, address=0x44, core_device="core"):
self.core = dmgr.get(core_device) self.core = dmgr.get(core_device)
self.busno = busno self.busno = busno
self.address = address self.address = address
@kernel @kernel
def _write24(self, addr, value): def _write24(self, addr: int32, value: int32):
i2c_write_many(self.busno, self.address, addr, i2c_write_many(self.busno, self.address, addr,
[value >> 16, value >> 8, value]) [value >> 16, value >> 8, value])
@kernel @kernel
def set(self, outputs): def set(self, outputs: int32):
"""Drive all pins of the chip to the levels given by the """Drive all pins of the chip to the levels given by the
specified 24-bit word. specified 24-bit word.
@ -207,19 +221,26 @@ class TCA6424A:
self._write24(0x8c, 0) # set all directions to output self._write24(0x8c, 0) # set all directions to output
self._write24(0x84, outputs_le) # set levels self._write24(0x84, outputs_le) # set levels
@nac3
class PCF8574A: class PCF8574A:
"""Driver for the PCF8574 I2C remote 8-bit I/O expander. """Driver for the PCF8574 I2C remote 8-bit I/O expander.
I2C transactions not real-time, and are performed by the CPU without I2C transactions not real-time, and are performed by the CPU without
involving RTIO. involving RTIO.
""" """
core: KernelInvariant[Core]
busno: KernelInvariant[int32]
address: KernelInvariant[int32]
def __init__(self, dmgr, busno=0, address=0x7c, core_device="core"): def __init__(self, dmgr, busno=0, address=0x7c, core_device="core"):
self.core = dmgr.get(core_device) self.core = dmgr.get(core_device)
self.busno = busno self.busno = busno
self.address = address self.address = address
@kernel @kernel
def set(self, data): def set(self, data: int32):
"""Drive data on the quasi-bidirectional pins. """Drive data on the quasi-bidirectional pins.
:param data: Pin data. High bits are weakly driven high :param data: Pin data. High bits are weakly driven high
@ -235,7 +256,7 @@ class PCF8574A:
i2c_stop(self.busno) i2c_stop(self.busno)
@kernel @kernel
def get(self): def get(self) -> int32:
"""Retrieve quasi-bidirectional pin input data. """Retrieve quasi-bidirectional pin input data.
:return: Pin data :return: Pin data