from spif import SpiFollower
class SpiRegAcc:
def __init__(self):
self.spi = SpiFollower(sig_check=False)
def write(self, addr, value_list):
self.spi.wr(addr, value_list)
def write32(self, addr, value):
data_bytes = list(value.to_bytes(4, 'little'))
self.spi.wr(addr, data_bytes)
def read(self, addr, read_len):
data_bytes = self.spi.rd(addr, read_len)
if read_len == 1:
return [data_bytes]
else:
return int.from_bytes(data_bytes, 'little')
def read32(self, addr):
data_bytes = self.spi.rd(addr, 4)
return int.from_bytes(data_bytes, 'little')
# Sample code for the entire I2CL sequence
class I2CLeader():
def __init__(self, read, write, read32, write32):
self.reg_read = read
self.reg_write = write
self.reg_read32 = read32
self.reg_write32 = write32
self.MAX_REGISTER_ADDRESS = 256
self.MAX_EXT_REGISTER_ADDRESS = 256
def init_cfg(self):
self.reg_write32(0x52050000, 0x0 & 0xff)
self.reg_write32(0x52050300, 128 & 0xff)
self.reg_write32(0x52050304, (128 & 0xffff) + ((109 << 16) & 0xffff0000))
self.reg_write32(0x52050308, (125 & 0xffff) + ((3 << 16) & 0xffff0000))
self.reg_write32(0x5205030C, 109 & 0xff)
def acquire_resource(self):
self.release_resource()
while True:
# self.reg_write32(0x52050100, (1 << 5))
self.reg_write(0x520503A2, [0xA])
while True:
busy = self.reg_read(0x520503AA, 1)
if busy[0] != 0:
break
if busy[0] != 3:
break
while self.reg_read(0x52050010, 1) == 1:
pass
def release_resource(self):
self.reg_write(0x520503A2, [0])
def wait_bus_idle(self):
while True:
stat_busy = self.reg_read32(0x52050010) & (1<<0)
if stat_busy == 0:
break
def write(self, dev_7bit, addr, addr_len, datas, verbose=True):
if dev_7bit > 0x7F:
raise ValueError(f"Error: dev_7bit exceeds 7-bit limit (0x7F). Provided value: 0x{dev_7bit:02X}")
if len(datas) > 16:
raise ValueError(f"Error: Data length exceeds maximum allowed size (16 bytes). Provided length: {len(datas)}")
if addr_len == 1 and addr + len(datas) - 1 > self.MAX_REGISTER_ADDRESS:
raise ValueError(f"Address range exceeds maximum allowed size (0xFF). Start address: {addr}, Data length: {len(datas)}")
if addr_len == 2 and addr + len(datas) - 1 > self.MAX_EXT_REGISTER_ADDRESS:
raise ValueError(f"Address range exceeds maximum allowed size (0xFFFF). Start address: {addr}, Data length: {len(datas)}")
if addr_len == 0 and addr != 0:
raise ValueError(f"Address must be 0 when addr_len is 0. Provided address: {addr}")
bit_done=0
bit_nack=1
bit_abort=2
bit_timeout=5
# Define error conditions with expected values
error_conditions = {
bit_nack: {"expected": 0, "message": "i2cl nack"},
bit_abort: {"expected": 0, "message": "i2cl abort"},
bit_timeout: {"expected": 0, "message": "i2cl timeout"},
}
data_len = len(datas)
if data_len % 4 != 0:
padding = 4 - (data_len % 4)
datas += [0] * padding
# Settings for I2CL_CONTROL
RW = 0 # 0:WRITE, 1:READ
ADDR_LEN = addr_len
WRITE_LEN = len(datas)-1
READ_LEN = 0
DEV = dev_7bit
REG = addr
# Settings for I2CL_XCTRL
SCALE = 14
NO_STOP = 0
OFFS_ONLY = 0
UNLOCK_SEL = 1 # 0:AUTO, 1:SELF
CONTROL0=(RW<<0)|(ADDR_LEN<<1)|(WRITE_LEN<<3)|(READ_LEN<<13)
CONTROL1=(DEV<<0)|(REG<<8)
XCTRL=(SCALE<<0)|(NO_STOP<<4)|(OFFS_ONLY<<15)|(UNLOCK_SEL<<22)
self.reg_write(0x5205000C, [1<<1]) # clear buffer
self.reg_write32(0x52050100, 0xFFFFFFFF)
self.reg_write32(0x52050004, CONTROL0)
self.reg_write32(0x52050008, CONTROL1)
self.reg_write32(0x5205031C, XCTRL)
self.reg_write(0x52050200, datas) # WDATA
self.reg_write(0x5205000C, [1<<0]) # REQ
while True:
int_stat = self.reg_read32(0x52050100)
if int_stat&(1<<bit_timeout):
if verbose:
print("i2cl timeout")
return bit_timeout
if int_stat&(1<<bit_done):
break
# Check each condition based on its expected value
for bit, condition in error_conditions.items():
expected = condition["expected"]
if (int_stat & (1 << bit)) != (expected << bit):
if verbose:
print(condition["message"])
return bit
if verbose:
print("i2cl write done")
def read(self, dev_7bit, addr, addr_len, data_len):
if dev_7bit > 0x7F:
raise ValueError(f"Error: dev_7bit exceeds 7-bit limit (0x7F). Provided value: 0x{dev_7bit:02X}")
if data_len > 16:
raise ValueError(f"Error: Data length exceeds maximum allowed size (16 bytes). Provided length: {data_len}")
if addr_len == 1 and addr + data_len - 1 > self.MAX_REGISTER_ADDRESS:
raise ValueError(f"Address range exceeds maximum allowed size (0xFF). Start address: {addr}, Data length: {data_len}")
if addr_len == 2 and addr + data_len - 1 > self.MAX_EXT_REGISTER_ADDRESS:
raise ValueError(f"Address range exceeds maximum allowed size (0xFFFF). Start address: {addr}, Data length: {data_len}")
if addr_len == 0 and addr != 0:
raise ValueError(f"Address must be 0 when addr_len is 0. Provided address: {addr}")
bit_done=0
bit_nack=1
bit_abort=2
bit_timeout=5
# Define error conditions with expected values
error_conditions = {
bit_nack: {"expected": 0, "message": "i2cl nack"},
bit_abort: {"expected": 0, "message": "i2cl abort"},
bit_done: {"expected": 1, "message": "i2cl not done"},
}
if data_len % 4 != 0:
padding = 4 - (data_len % 4)
# 1st transaction: START + DEV/W + OFFSET (NO_STOP)
# Settings for I2CL_CONTROL
RW = 0 # 0:WRITE, 1:READ
ADDR_LEN = addr_len
WRITE_LEN = 0
READ_LEN = 0
DEV = dev_7bit
REG = addr
# Settings for I2CL_XCTRL
SCALE = 14
NO_STOP = 1
OFFS_ONLY = 1
UNLOCK_SEL = 1 # 0:AUTO, 1:SELF
CONTROL0=(RW<<0)|(ADDR_LEN<<1)|(WRITE_LEN<<3)|(READ_LEN<<13)
CONTROL1=(DEV<<0)|(REG<<8)
XCTRL=(SCALE<<0)|(NO_STOP<<4)|(OFFS_ONLY<<15)|(UNLOCK_SEL<<22)
self.reg_write32(0x52050100, 0xFFFFFFFF)
self.reg_write(0x5205000C, [1<<1]) # clear buffer
self.reg_write32(0x52050004, CONTROL0)
self.reg_write32(0x52050008, CONTROL1)
self.reg_write32(0x5205031C, XCTRL)
self.reg_write(0x5205000C, [1<<0]) # REQ
while True:
int_stat = self.reg_read32(0x52050100)
if int_stat&(1<<bit_timeout):
print("i2cl timeout")
return [0]
if int_stat&(1<<bit_done):
break
# Check each condition based on its expected value
for bit, condition in error_conditions.items():
expected = condition["expected"]
if (int_stat & (1 << bit)) != (expected << bit):
print(condition["message"])
return [0]
# 2nd transaction: RSTART + DEV/R + DATA0 .. DATA.. + STOP
# Settings for I2CL_CONTROL
RW = 1 # 0:WRITE, 1:READ
ADDR_LEN = 0
WRITE_LEN = 0
READ_LEN = data_len-1
DEV = dev_7bit
REG = 0
# Settings for I2CL_XCTRL
SCALE = 14
NO_STOP = 0
OFFS_ONLY = 0
UNLOCK_SEL = 1 # 0:AUTO, 1:SELF
CONTROL0=(RW<<0)|(ADDR_LEN<<1)|(WRITE_LEN<<3)|(READ_LEN<<13)
CONTROL1=(DEV<<0)|(REG<<8)
XCTRL=(SCALE<<0)|(NO_STOP<<4)|(OFFS_ONLY<<15)|(UNLOCK_SEL<<22)
self.reg_write(0x5205000C, [1<<1]) # clear buffer
self.reg_write32(0x52050100, 0xFFFFFFFF)
self.reg_write32(0x52050004, CONTROL0)
self.reg_write32(0x52050008, CONTROL1)
self.reg_write32(0x5205031C, XCTRL)
self.reg_write(0x5205000C, [1<<0]) # REQ
while True:
int_stat = self.reg_read32(0x52050100)
if int_stat&(1<<bit_timeout):
print("i2cl timeout")
return [0]
if int_stat&(1<<bit_done):
break
# Check each condition on its expected value
for bit, condition in error_conditions.items():
expected = condition["expected"]
if (int_stat & (1 << bit)) != (expected << bit):
print(condition["message"])
return [0]
rdata = self.reg_read(0x52050210, int(data_len + padding) / 4)
int_stat = self.reg_read32(0x52050100)
if int_stat&(1<<bit_timeout):
print("i2cl timeout")
return [0]
print("i2cl read done")
return rdata
if __name__ == "__main__":
spi = SpiRegAcc()
i2cl = I2CLeader(spi.read, spi.write, spi.read32, spi.write32)
i2cl.init_cfg()
i2cl.acquire_resource()
# i2cl.wait_bus_idle()
# test write
i2cl.write(0x08, 0x74, 1, [0x12, 0x34, 0x56, 0x78, 0x9a])
# test read
rdata = i2cl.read(0x08, 0xCB, 1, 8)
print([format(x, '02x') for x in rdata])
i2cl.release_resource()
最新发布