2022-01-09 18:20:49 +01:00
|
|
|
from i2c_interfaces import I2CInterface
|
|
|
|
|
|
|
|
|
|
|
|
class TW88xx:
|
|
|
|
|
|
|
|
class Reg:
|
|
|
|
SPI_FLASH_MODE_CONTROL_0 = 0X4C0
|
|
|
|
SPI_FLASH_MODE_CONTROL_1 = 0X4C1
|
|
|
|
DMA_CONTROL = 0X4C3
|
|
|
|
FLASH_BUSY_CONTROL = 0X4C4
|
|
|
|
WAIT_CONTROL = 0X4C5
|
|
|
|
DMA_PAGE = 0X4C6
|
|
|
|
DMA_INDEX = 0X4C7
|
|
|
|
DMA_LENGTH_MID_BYTE = 0X4C8
|
|
|
|
DMA_LENGTH_LOW_BYTE = 0X4C9
|
|
|
|
DMA_COMMAND_BUFFER = 0X4CA # LEN 5
|
|
|
|
CLOCK_SWITCH_WAIT_COUNTER_VALUE = 0X4CF
|
|
|
|
DMA_READWRITE_BUFFER = 0X4D0 # LEN 8
|
|
|
|
SPI_FLASH_STATUS_COMMAND = 0X4D8
|
|
|
|
SPI_FLASH_BUSY_CONTROL = 0X4D9
|
|
|
|
DMA_LENGTH_HIGH_BYTE = 0X4DA
|
|
|
|
|
2022-01-09 22:14:53 +01:00
|
|
|
LUT_ACCESS_CTRL = 0x410
|
|
|
|
LUT_ADDR = 0x411
|
|
|
|
LUT_DATA = 0x412
|
|
|
|
|
2022-01-09 18:20:49 +01:00
|
|
|
def __init__(self, i2c: I2CInterface) -> None:
|
|
|
|
self.i2c = i2c
|
|
|
|
self.page = None
|
|
|
|
|
|
|
|
def _set_page(self, page: int) -> None:
|
|
|
|
self.i2c.write(self.ADDR, [0xFF, page])
|
|
|
|
|
|
|
|
def write_reg(self, reg: int, data: int) -> None:
|
|
|
|
page = reg >> 8
|
|
|
|
if not self.page or self.page != page:
|
|
|
|
self._set_page(page)
|
|
|
|
self.page = page
|
|
|
|
self.i2c.write(self.ADDR, [reg & 0xFF, data])
|
|
|
|
# print(f'{reg:03x} = {data:02x}')
|
|
|
|
|
|
|
|
def read_reg(self, reg: int):
|
|
|
|
page = reg >> 8
|
|
|
|
if not self.page or self.page != page:
|
|
|
|
self._set_page(page)
|
|
|
|
self.page = page
|
|
|
|
self.i2c.write(self.ADDR, [reg & 0xFF])
|
|
|
|
return self.i2c.read(self.ADDR, 1)[0]
|
|
|
|
|
2022-01-10 01:18:41 +01:00
|
|
|
def execute_flash_cmd(self, cmd: bytes, read_len=0, read_mode=None, data=None) -> bytes:
|
|
|
|
if read_mode is not None:
|
|
|
|
self.write_reg(TW88xx.Reg.SPI_FLASH_MODE_CONTROL_0, read_mode)
|
|
|
|
|
2022-01-09 18:20:49 +01:00
|
|
|
self.write_reg(TW88xx.Reg.DMA_CONTROL, 0x40 + len(cmd))
|
|
|
|
|
|
|
|
self.write_reg(TW88xx.Reg.DMA_PAGE, 0x04)
|
|
|
|
self.write_reg(TW88xx.Reg.DMA_INDEX, 0xD0)
|
|
|
|
|
|
|
|
self.write_reg(TW88xx.Reg.DMA_LENGTH_MID_BYTE, 0)
|
|
|
|
self.write_reg(TW88xx.Reg.DMA_LENGTH_LOW_BYTE, read_len)
|
|
|
|
self.write_reg(TW88xx.Reg.DMA_LENGTH_HIGH_BYTE, 0)
|
|
|
|
|
|
|
|
for i in range(len(cmd)):
|
|
|
|
self.write_reg(TW88xx.Reg.DMA_COMMAND_BUFFER + i, cmd[i])
|
|
|
|
|
|
|
|
if data:
|
|
|
|
for i in range(len(data)):
|
|
|
|
self.write_reg(TW88xx.Reg.DMA_READWRITE_BUFFER + i, data[i])
|
|
|
|
|
|
|
|
self.write_reg(TW88xx.Reg.FLASH_BUSY_CONTROL, 0x01)
|
|
|
|
while True:
|
|
|
|
busy = self.read_reg(TW88xx.Reg.FLASH_BUSY_CONTROL)
|
|
|
|
if (busy & 0x01) == 0:
|
|
|
|
break
|
|
|
|
|
|
|
|
data = []
|
|
|
|
for i in range(read_len):
|
|
|
|
data.append(self.read_reg(TW88xx.Reg.DMA_READWRITE_BUFFER + i))
|
|
|
|
return bytes(data)
|
|
|
|
|
2022-01-09 21:52:33 +01:00
|
|
|
def prepare_flash_read(self, cmd_len, read_len):
|
|
|
|
self.write_reg(TW88xx.Reg.DMA_CONTROL, 0x40 + cmd_len)
|
2022-01-09 18:20:49 +01:00
|
|
|
|
|
|
|
self.write_reg(TW88xx.Reg.DMA_PAGE, 0x04)
|
|
|
|
self.write_reg(TW88xx.Reg.DMA_INDEX, 0xD0)
|
|
|
|
|
|
|
|
self.write_reg(TW88xx.Reg.DMA_LENGTH_MID_BYTE, 0)
|
|
|
|
self.write_reg(TW88xx.Reg.DMA_LENGTH_LOW_BYTE, read_len)
|
|
|
|
self.write_reg(TW88xx.Reg.DMA_LENGTH_HIGH_BYTE, 0)
|
|
|
|
|
2022-01-09 22:14:53 +01:00
|
|
|
|
2022-01-09 21:52:33 +01:00
|
|
|
def do_flash_cmd(self, cmd, read_len):
|
2022-01-09 18:20:49 +01:00
|
|
|
for i in range(len(cmd)):
|
|
|
|
self.write_reg(TW88xx.Reg.DMA_COMMAND_BUFFER + i, cmd[i])
|
2022-01-09 21:52:33 +01:00
|
|
|
|
2022-01-09 18:20:49 +01:00
|
|
|
self.write_reg(TW88xx.Reg.FLASH_BUSY_CONTROL, 0x01)
|
|
|
|
while True:
|
|
|
|
busy = self.read_reg(TW88xx.Reg.FLASH_BUSY_CONTROL)
|
|
|
|
if (busy & 0x01) == 0:
|
|
|
|
break
|
|
|
|
|
|
|
|
data = []
|
|
|
|
for i in range(read_len):
|
|
|
|
data.append(self.read_reg(TW88xx.Reg.DMA_READWRITE_BUFFER + i))
|
2022-01-09 22:14:53 +01:00
|
|
|
return bytes(data)
|
|
|
|
|
2022-01-09 21:52:33 +01:00
|
|
|
def dump_regs(self):
|
|
|
|
for r in self.REGS:
|
|
|
|
val = self.read_reg(r)
|
2022-01-09 22:14:53 +01:00
|
|
|
print(f'{r:03x} = {val:02x} ({self.REGS[r]})')
|
|
|
|
|
|
|
|
def dump_lut(self):
|
|
|
|
lut_ctrl = self.read_reg(TW88xx.Reg.LUT_ACCESS_CTRL) & 0xF0
|
|
|
|
tbl = {}
|
|
|
|
for i in range(512):
|
|
|
|
data=[]
|
|
|
|
for b in range(4):
|
2022-01-10 01:18:41 +01:00
|
|
|
self.write_reg(TW88xx.Reg.LUT_ACCESS_CTRL, lut_ctrl | (8 if i>=256 else 0) | b)
|
2022-01-09 22:14:53 +01:00
|
|
|
self.write_reg(TW88xx.Reg.LUT_ADDR, i & 0xFF)
|
|
|
|
_ = self.read_reg(TW88xx.Reg.LUT_DATA)
|
|
|
|
data.append(self.read_reg(TW88xx.Reg.LUT_DATA))
|
|
|
|
print (f'{i:03x} = {bytes(data).hex()}')
|
|
|
|
tbl[i] = data
|
|
|
|
return tbl
|