188 lines
5.3 KiB
Python
188 lines
5.3 KiB
Python
import os
|
|
from typing import Union, Tuple
|
|
|
|
from UniTAP.libs.lib_tsi.tsi import *
|
|
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
|
|
|
|
|
class DPCDRegion:
|
|
|
|
"""
|
|
Class `DPCDRegion` describe a byte range of DPCD registers.
|
|
Allows saving DPCD data to dpd file format `save_to_dpd`, hex files format `save_to_hex`,
|
|
dsc file format `save_to_csv`.
|
|
|
|
Arguments:
|
|
base - start DPCD address of byte range.
|
|
data - DPCD data of byte range.
|
|
"""
|
|
|
|
def __init__(self, base: int, data: Union[bytearray, int]):
|
|
|
|
if not isinstance(data, bytearray):
|
|
self.data = bytearray()
|
|
self.data.append(data)
|
|
else:
|
|
self.data = data
|
|
self.base = base
|
|
|
|
@property
|
|
def size(self) -> int:
|
|
"""
|
|
|
|
Returns length fo data.
|
|
|
|
Returns:
|
|
result of int object
|
|
"""
|
|
return len(self.data)
|
|
|
|
def save_to_dpd(self, path: str):
|
|
"""
|
|
|
|
Save DPCD data to 'dpd' file format.
|
|
|
|
Args:
|
|
path (str) - full path to file
|
|
|
|
"""
|
|
if not path.lower().endswith('.dpd'):
|
|
path += '.DPD'
|
|
with open(path, 'bw') as file:
|
|
dpd_mark = 1
|
|
file.write(dpd_mark.to_bytes(4, 'little'))
|
|
file.write(self.base.to_bytes(4, 'little'))
|
|
file.write(len(self.data).to_bytes(4, 'little'))
|
|
file.write(self.data)
|
|
|
|
def save_to_hex(self, path: str):
|
|
"""
|
|
|
|
Save DPCD data to 'hex' file format.
|
|
|
|
Args:
|
|
path (str) - full path to file
|
|
|
|
"""
|
|
if not path.lower().endswith('.hex'):
|
|
path += '.HEX'
|
|
with open(path, 'w') as file:
|
|
file.write(f"\nRange 1. Start {self.base:#0{8}x}, Length {len(self.data):#0{8}x}\n")
|
|
file.write(
|
|
'\n'.join(
|
|
' '.join(
|
|
f'{value:#0{2}x}' for value in self.data[i:i + 16])
|
|
for i in range(0, len(self.data), 16)
|
|
)
|
|
)
|
|
|
|
def save_to_csv(self, path: str):
|
|
"""
|
|
|
|
Save DPCD data to 'csv' file format.
|
|
|
|
Args:
|
|
path (str) - full path to file
|
|
|
|
"""
|
|
if not path.lower().endswith('.csv'):
|
|
path += '.csv'
|
|
with open(path, 'w') as file:
|
|
file.write("Address (A), Data A+0, Data A+1, Data A+2, Data A+3, Data A+4, Data A+5,"
|
|
" Data A+6, Data A+7\n")
|
|
file.write(
|
|
'\n'.join(
|
|
f'{self.base + 8 * i:#0{8}x},' + ','.join(f'{value:#0{2}x}'
|
|
for value in self.data[i:i + 8])
|
|
for i in range(0, len(self.data), 8)
|
|
)
|
|
)
|
|
|
|
|
|
class DPCDRegisters:
|
|
|
|
"""
|
|
Class `DPCDRegisters` allows working with DPCD registers: writing `write` DPCD data to device,
|
|
reading `read` DPCD data from device, loading `load_from_file` DPCD data from file.
|
|
"""
|
|
|
|
def __init__(self, port_io: PortIO, base_ci: int, data_ci: int):
|
|
self.__io = port_io
|
|
self.__base_ci = base_ci
|
|
self.__data_ci = data_ci
|
|
|
|
def write(self, base: int, data: Union[bytearray, int, list]) -> int:
|
|
"""
|
|
|
|
Write transferred DPCD data to device from base address.
|
|
|
|
Args:
|
|
base (int) - start (base) address.
|
|
data (Union[bytearray, int]) - DPCD data.
|
|
|
|
Returns:
|
|
result of operation
|
|
"""
|
|
if isinstance(data, int):
|
|
data = bytearray(data.to_bytes(1, "big"))
|
|
elif isinstance(data, list):
|
|
data = bytearray(data)
|
|
|
|
result = self.__io.set(self.__base_ci, base)
|
|
if result < TSI_SUCCESS:
|
|
return result
|
|
result = self.__io.set(self.__data_ci, data, c_ubyte, len(data))
|
|
return result
|
|
|
|
def read(self, base: int, count: int) -> DPCDRegion:
|
|
"""
|
|
|
|
Read DPCD data from base address in a certain quantity.
|
|
|
|
Args:
|
|
base (int) - start (base) address.
|
|
count (int) - quantity of DPCD bytes.
|
|
|
|
Returns:
|
|
object of `DPCDRegion`
|
|
"""
|
|
self.__io.set(self.__base_ci, base)
|
|
|
|
result = self.__io.get(self.__data_ci, c_ubyte, count)
|
|
|
|
return DPCDRegion(base, result[1])
|
|
|
|
@staticmethod
|
|
def load_from_file(path: str) -> Tuple[DPCDRegion, DPCDRegion]:
|
|
"""
|
|
|
|
Read DPCD data from file.
|
|
Supported formats:
|
|
- DPD.
|
|
|
|
Args:
|
|
path (str) - full path to file.
|
|
|
|
Returns:
|
|
object of tuple with two `DPCDRegion` objects
|
|
"""
|
|
if not os.path.exists(path):
|
|
raise FileNotFoundError(f"DPCD load_from_file function can't find file: {path}")
|
|
|
|
if '.DPD' not in os.path.splitext(path):
|
|
raise TypeError("Wrong file extension. It should be .DPD")
|
|
|
|
with open(path, 'rb') as file:
|
|
file.read(4)
|
|
base1 = int.from_bytes(file.read(4)[::-1], 'little')
|
|
size1 = int.from_bytes(file.read(4)[::-1], 'little')
|
|
data1 = bytearray(file.read(size1))
|
|
region1 = DPCDRegion(base1, data1)
|
|
|
|
base2 = int.from_bytes(file.read(4)[::-1], 'little')
|
|
size2 = int.from_bytes(file.read(4)[::-1], 'little')
|
|
data2 = bytearray(file.read(size2))
|
|
region2 = DPCDRegion(base2, data2)
|
|
|
|
return region1, region2
|