artiq/artiq/coredevice/i2c.py

113 lines
3.3 KiB
Python
Raw Normal View History

from artiq.language.core import syscall, kernel
2016-03-05 00:43:13 +08:00
from artiq.language.types import TBool, TInt32, TNone
from artiq.coredevice.exceptions import I2CError
@syscall
def i2c_init(busno: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")
@syscall
def i2c_start(busno: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")
@syscall
def i2c_stop(busno: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")
@syscall
def i2c_write(busno: TInt32, b: TInt32) -> TBool:
raise NotImplementedError("syscall not simulated")
@syscall
def i2c_read(busno: TInt32, ack: TBool) -> TInt32:
raise NotImplementedError("syscall not simulated")
class PCA9548:
2016-03-05 19:02:03 +08:00
"""Driver for the PCA9548 I2C bus switch.
On the KC705, this chip is used for selecting the I2C buses on the two FMC
connectors. HPC=1, LPC=2.
"""
2016-03-05 00:47:24 +08:00
def __init__(self, dmgr, busno=0, address=0xe8):
self.core = dmgr.get("core")
self.busno = busno
self.address = address
@kernel
def set(self, channel):
2016-03-05 19:02:03 +08:00
"""Select one channel.
2016-03-07 00:17:45 +08:00
Selecting multiple channels at the same time is not supported by this
driver.
2016-03-05 19:02:03 +08:00
:param channel: channel number (0-7)
"""
i2c_init(self.busno)
i2c_start(self.busno)
try:
if not i2c_write(self.busno, self.address):
raise I2CError("PCA9548 failed to ack address")
if not i2c_write(self.busno, 1 << channel):
raise I2CError("PCA9548 failed to ack control word")
finally:
i2c_stop(self.busno)
2016-03-05 19:01:35 +08:00
@kernel
def readback(self):
i2c_init(self.busno)
i2c_start(self.busno)
r = 0
try:
if not i2c_write(self.busno, self.address | 1):
raise I2CError("PCA9548 failed to ack address")
r = i2c_read(self.busno, False)
finally:
i2c_stop(self.busno)
return r
class TCA6424A:
2016-03-05 19:02:03 +08:00
"""Driver for the TCA6424A I2C I/O expander.
On the NIST QC2 hardware, this chip is used for switching the directions
of TTL buffers."""
def __init__(self, dmgr, busno=0, address=0x44):
self.core = dmgr.get("core")
self.busno = busno
self.address = address
@kernel
def _write24(self, command, value):
i2c_init(self.busno)
i2c_start(self.busno)
try:
if not i2c_write(self.busno, self.address):
raise I2CError("TCA6424A failed to ack address")
if not i2c_write(self.busno, command):
raise I2CError("TCA6424A failed to ack command")
for i in range(3):
if not i2c_write(self.busno, value >> 16):
2016-03-05 00:51:13 +08:00
raise I2CError("TCA6424A failed to ack data")
value <<= 8
finally:
i2c_stop(self.busno)
@kernel
def set(self, outputs):
2016-03-05 19:02:03 +08:00
"""Drive all pins of the chip to the levels given by the
specified 24-bit word.
On the QC2 hardware, the LSB of the word determines the direction of
TTL0 (on a given FMC card) and the MSB that of TTL23.
A bit set to 1 means the TTL is an output.
"""
self._write24(0x8c, 0) # set all directions to output
self._write24(0x84, output) # set levels