Source code for basil.HL.i2c
#
# ------------------------------------------------------------
# Copyright (c) All rights reserved
# SiLab, Institute of Physics, University of Bonn
# ------------------------------------------------------------
#
from basil.HL.RegisterHardwareLayer import RegisterHardwareLayer
[docs]
class i2c(RegisterHardwareLayer):
"""Implement master i2c programming interface driver."""
_registers = {
"RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}},
"VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}},
"START": {"descr": {"addr": 1, "size": 8, "properties": ["writeonly"]}},
"READY": {"descr": {"addr": 1, "size": 1, "properties": ["ro"]}},
"NO_ACK": {"descr": {"addr": 1, "size": 1, "offset": 1, "properties": ["ro"]}},
"SIZE": {"descr": {"addr": 3, "size": 16}},
"ADDR": {"descr": {"addr": 2, "size": 8}},
"MEM_BYTES": {"descr": {"addr": 6, "size": 16}},
}
_require_version = "==1"
def __init__(self, intf, conf):
super(i2c, self).__init__(intf, conf)
self._seq_mem_offset = 8 # in bytes
def init(self):
super(i2c, self).init()
self._mem_size = self.get_mem_size()
def get_mem_size(self):
return self.MEM_BYTES
def reset(self):
self.RESET = 0
def start(self):
self.START = 0
def set_addr(self, value):
self.ADDR = value
def set_address(self, value):
self.ADDR = value
def get_addr(self):
return self.ADDR
def get_address(self):
return self.ADDR
def set_size(self, value):
if self._mem_size < value:
raise ValueError("Size of data (%d bytes) is too big for memory (%d bytes)" % (value, self._mem_size))
self.SIZE = value
def get_size(self):
return self.SIZE
def is_done(self):
return self.is_ready
@property
def is_ready(self):
"""
:raises IOError: Transfer not acknowledged.
"""
if self.NO_ACK:
raise IOError("i2c:Transfer not acknowledged")
return self.READY
def get_done(self):
return self.is_ready
def set_data(self, data, addr=0):
if self._mem_size < len(data):
raise ValueError("Size of data (%d bytes) is too big for memory (%d bytes)" % (len(data), self._mem_size))
self._intf.write(self._conf["base_addr"] + self._seq_mem_offset + addr, data)
def get_data(self, size=None, addr=0):
if size and self._mem_size < size:
raise ValueError("Size is too big")
if not size:
return self._intf.read(self._conf["base_addr"] + self._seq_mem_offset + addr, self._mem_size)
else:
return self._intf.read(self._conf["base_addr"] + self._seq_mem_offset + addr, size)
[docs]
def write(self, addr, data):
"""Write access.
:param addr: i2c slave address
:type addr: char
:param data: array/list of bytes
:type data: iterable
:rtype: None
"""
self.set_addr(addr & 0xFE)
self.set_data(data)
self.set_size(len(data))
self.start()
while not self.is_ready:
pass
[docs]
def read(self, addr, size):
"""Read access.
:param addr: i2c slave address
:type addr: char
:param size: size of transfer
:type size: int
:returns: data byte array
:rtype: array.array('B')
"""
self.set_addr(addr | 0x01)
self.set_size(size)
self.start()
while not self.is_ready:
pass
return self.get_data(size)