更新UCD-API库及文档

This commit is contained in:
xinzhu.yin
2026-07-02 17:16:18 +08:00
parent a500751d85
commit 9fa811a9eb
290 changed files with 9558 additions and 2306 deletions

View File

@@ -1,10 +1,12 @@
import copy
import os.path
from ctypes import c_uint8, c_uint, c_uint32
from typing import Union, List, Optional
from PIL import Image
from UniTAP.utils import function_scheduler
from UniTAP.libs.lib_tsi.tsi import *
import UniTAP.libs.lib_tsi.tsi_types as ci
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
from UniTAP.libs.lib_tsi.tsi_io import PortIO
from UniTAP.dev.modules import MemoryManager
from UniTAP.dev.ports.modules.internal_utils.math import aligned
@@ -26,29 +28,29 @@ Image.MAX_IMAGE_PIXELS = None
def _read_predefined_timings(io: PortIO) -> List[Timing]:
count = io.get(TSI_R_PG_PREDEF_TIMING_COUNT)[1]
count = io.get(ci.TSI_R_PG_PREDEF_TIMING_COUNT)[1]
predefined_list = []
for i in range(count):
io.set(TSI_W_PG_PREDEF_TIMING_SELECT, i)
io.set(ci.TSI_W_PG_PREDEF_TIMING_SELECT, i)
timing = Timing()
timing.htotal = io.get(TSI_PG_CUSTOM_TIMING_HTOTAL)[1]
timing.vtotal = io.get(TSI_PG_CUSTOM_TIMING_VTOTAL)[1]
timing.hactive = io.get(TSI_PG_CUSTOM_TIMING_HACTIVE)[1]
timing.vactive = io.get(TSI_PG_CUSTOM_TIMING_VACTIVE)[1]
timing.hstart = io.get(TSI_PG_CUSTOM_TIMING_HSTART)[1]
timing.vstart = io.get(TSI_PG_CUSTOM_TIMING_VSTART)[1]
timing.hswidth = io.get(TSI_PG_CUSTOM_TIMING_HSYNCW)[1]
timing.vswidth = io.get(TSI_PG_CUSTOM_TIMING_VSYNCW)[1]
timing.id = io.get(TSI_PG_CUSTOM_TIMING_ID)[1]
timing.htotal = io.get(ci.TSI_PG_CUSTOM_TIMING_HTOTAL)[1]
timing.vtotal = io.get(ci.TSI_PG_CUSTOM_TIMING_VTOTAL)[1]
timing.hactive = io.get(ci.TSI_PG_CUSTOM_TIMING_HACTIVE)[1]
timing.vactive = io.get(ci.TSI_PG_CUSTOM_TIMING_VACTIVE)[1]
timing.hstart = io.get(ci.TSI_PG_CUSTOM_TIMING_HSTART)[1]
timing.vstart = io.get(ci.TSI_PG_CUSTOM_TIMING_VSTART)[1]
timing.hswidth = io.get(ci.TSI_PG_CUSTOM_TIMING_HSYNCW)[1]
timing.vswidth = io.get(ci.TSI_PG_CUSTOM_TIMING_VSYNCW)[1]
timing.id = io.get(ci.TSI_PG_CUSTOM_TIMING_ID)[1]
# TODO: add conversion from pg AR to Timing AR
timing.aspect_ratio = io.get(TSI_PG_CUSTOM_TIMING_ASPECT_RATIO)[1]
timing.frame_rate = io.get(TSI_PG_CUSTOM_TIMING_FIELD_RATE)[1]
timing.standard = Timing.Standard(io.get(TSI_PG_CUSTOM_TIMING_STANDARD)[1])
timing.aspect_ratio = io.get(ci.TSI_PG_CUSTOM_TIMING_ASPECT_RATIO)[1]
timing.frame_rate = io.get(ci.TSI_PG_CUSTOM_TIMING_FIELD_RATE)[1]
timing.standard = Timing.Standard(io.get(ci.TSI_PG_CUSTOM_TIMING_STANDARD)[1])
timing_flags = io.get(TSI_PG_CUSTOM_TIMING_FLAGS)[1]
timing_flags = io.get(ci.TSI_PG_CUSTOM_TIMING_FLAGS)[1]
timing.hswidth *= (-1 if timing_flags >> 9 & 1 else 1)
timing.vswidth *= (-1 if timing_flags >> 10 & 1 else 1)
timing.reduce_blanking = Timing.ReduceBlanking((timing_flags >> 24) & 0x3)
@@ -191,7 +193,7 @@ class PatternGenerator:
def __read_caps(self):
self._become_active()
return self.__io.get(TSI_PG_CAPS_R, PgCaps)[1]
return self.__io.get(p_ci.TSI_PG_CAPS_R, PgCaps)[1]
def _caps(self) -> PgCaps:
return self.__caps
@@ -242,11 +244,11 @@ class PatternGenerator:
self.__memory_manager.set_memory_layout([block_sizes])
self.__memory_manager.set_memory_block_index(MemoryManager.MemoryOwner.MO_PatternGenerator)
self.__io.set(TSI_PG_CUSTOM_PATTERN_MEMORY_BLOCK_INDEX, 0)
self.__io.set(TSI_PG_CUSTOM_PATTERN_WIDTH, video_mode.timing.hactive)
self.__io.set(TSI_PG_CUSTOM_PATTERN_HEIGHT, video_mode.timing.vactive)
self.__io.set(TSI_PG_CUSTOM_PATTERN_PIXEL_FORMAT, pg_pixel_format_from_vm(video_mode))
self.__io.set(TSI_PG_CUSTOM_PATTERN_DATA, data, c_uint8, data_count=len(data))
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_MEMORY_BLOCK_INDEX, 0)
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_WIDTH, video_mode.timing.hactive)
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_HEIGHT, video_mode.timing.vactive)
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_PIXEL_FORMAT, pg_pixel_format_from_vm(video_mode))
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_DATA, data, c_uint8, data_count=len(data))
def __load_dsc_image(self, video_mode: VideoMode, content_data: Union[str, bytearray, VideoFrameDSC]):
if isinstance(content_data, str):
@@ -259,8 +261,8 @@ class PatternGenerator:
block_sizes = len(data)
self.__memory_manager.set_memory_layout([block_sizes])
self.__memory_manager.set_memory_block_index(MemoryManager.MemoryOwner.MO_PatternGenerator)
self.__io.set(TSI_PG_CUSTOM_PATTERN_MEMORY_BLOCK_INDEX, 0)
self.__io.set(TSI_PG_CUSTOM_PATTERN_DATA, data, c_uint8, data_count=len(data))
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_MEMORY_BLOCK_INDEX, 0)
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_DATA, data, c_uint8, data_count=len(data))
@staticmethod
def __calculate_frame_size(width: int, height: int) -> int:
@@ -331,7 +333,7 @@ class PatternGenerator:
raise TypeError(f"Incorrect input value: {self._pattern}.\n"
f"If you want to select pattern, see following list of available patterns:\n"
f"{self.__available_patterns}")
self.__io.set(TSI_PG_PREDEF_PATTERN_SELECT, self._pattern_id.value)
self.__io.set(ci.TSI_PG_PREDEF_PATTERN_SELECT, self._pattern_id.value)
return True
return False
@@ -362,17 +364,17 @@ class PatternGenerator:
self.__caps.max_h_total >= self._vm.timing.htotal and \
self.__caps.max_v_total >= self._vm.timing.vtotal and \
self.__caps.max_frame >= int(self._vm.timing.frame_rate / 1000):
self.__io.set(TSI_PG_CUSTOM_TIMING_FLAGS, pg_timingflags_from_vm(self._vm))
self.__io.set(TSI_PG_CUSTOM_TIMING_HTOTAL, self._vm.timing.htotal, c_uint)
self.__io.set(TSI_PG_CUSTOM_TIMING_VTOTAL, self._vm.timing.vtotal, c_uint)
self.__io.set(TSI_PG_CUSTOM_TIMING_HACTIVE, self._vm.timing.hactive, c_uint)
self.__io.set(TSI_PG_CUSTOM_TIMING_VACTIVE, self._vm.timing.vactive, c_uint)
self.__io.set(TSI_PG_CUSTOM_TIMING_HSTART, self._vm.timing.hstart, c_uint)
self.__io.set(TSI_PG_CUSTOM_TIMING_VSTART, self._vm.timing.vstart, c_uint)
self.__io.set(TSI_PG_CUSTOM_TIMING_HSYNCW, abs(self._vm.timing.hswidth), c_uint)
self.__io.set(TSI_PG_CUSTOM_TIMING_VSYNCW, abs(self._vm.timing.vswidth), c_uint)
self.__io.set(TSI_PG_CUSTOM_TIMING_FIELD_RATE, self._vm.timing.frame_rate, c_uint)
self.__io.set(TSI_PG_CUSTOM_TIMING_STANDARD, self._vm.timing.standard.value, c_uint)
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_FLAGS, pg_timingflags_from_vm(self._vm))
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_HTOTAL, self._vm.timing.htotal, c_uint)
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_VTOTAL, self._vm.timing.vtotal, c_uint)
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_HACTIVE, self._vm.timing.hactive, c_uint)
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_VACTIVE, self._vm.timing.vactive, c_uint)
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_HSTART, self._vm.timing.hstart, c_uint)
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_VSTART, self._vm.timing.vstart, c_uint)
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_HSYNCW, abs(self._vm.timing.hswidth), c_uint)
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_VSYNCW, abs(self._vm.timing.vswidth), c_uint)
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_FIELD_RATE, self._vm.timing.frame_rate, c_uint)
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_STANDARD, self._vm.timing.standard.value, c_uint)
return True
else:
raise ValueError(f"Incorrect Video Mode (incorrect resolution and(or) frame rate")
@@ -384,29 +386,40 @@ class PatternGenerator:
See available `PGPatternParams` types: `SolidColorParams`, `WhiteVStripsParams`, `GradientStripsParams`,
`MotionParams`,`SquareWindowParams` (see in pg pattern params).
These parameters can be applied without calling apply() method, if active pattern matches pattern params.
Args:
pattern_params (PGPatternParams)
"""
self._pattern_params = pattern_params
self._setup_pattern_params()
def _setup_pattern_params(self):
if self._pattern_params is not None and isinstance(self._pattern, VideoPattern):
if self._MAP_PATTERN_PARAMETER.get(PGPatternID(self._pattern_id.value)) is not None:
if isinstance(self._pattern_params,
self._MAP_PATTERN_PARAMETER.get(PGPatternID(self._pattern_id.value))):
self.__io.set(TSI_PG_PREDEF_PATTERN_PARAMS, get_pattern_params_value(self._pattern_params,
self._vm.color_info.bpc),
data_count=len(get_pattern_params_value(self._pattern_params)))
return True
else:
warnings.warn(f"Incorrect pattern name {self._pattern} and "
f"pattern params {type(self._pattern_params)}.\n"
f"For {self._pattern} you need to use "
f"{self._MAP_PATTERN_PARAMETER.get(self._pattern_id)}")
return False
if self._pattern_params is None or not isinstance(self._pattern, VideoPattern):
return False
if self._MAP_PATTERN_PARAMETER.get(self._pattern_id) is None:
return False
if not isinstance(self._pattern_params, self._MAP_PATTERN_PARAMETER.get(self._pattern_id)):
warnings.warn(f"Incorrect pattern name {self._pattern} and "
f"pattern params {type(self._pattern_params)}.\n"
f"For {self._pattern} you need to use "
f"{self._MAP_PATTERN_PARAMETER.get(self._pattern_id)}")
return False
solid_color_shifter = 16 - self._vm.color_info.bpc if self._vm is not None else 0
params = get_pattern_params_value(self._pattern_params, solid_color_shifter)
self._become_active()
self.__io.set(ci.TSI_PG_PREDEF_PATTERN_PARAM_1, params[0])
self.__io.set(ci.TSI_PG_PREDEF_PATTERN_PARAM_2, params[1])
return True
def __get_custom_timing_flags_to_video_mode(self) -> (ColorInfo, bool, bool):
timing_flags = self.__io.get(TSI_PG_CUSTOM_TIMING_FLAGS, CustomTimingFlags)[1]
timing_flags = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_FLAGS, CustomTimingFlags)[1]
vm_color_format = pg_colorformat_to_ci_colorformat(PGColorInfo(timing_flags.color_space))
@@ -440,28 +453,28 @@ class PatternGenerator:
video_mode = VideoMode()
video_mode.timing.hactive = self.__io.get(TSI_PG_CUSTOM_TIMING_HACTIVE, c_uint32)[1]
video_mode.timing.vactive = self.__io.get(TSI_PG_CUSTOM_TIMING_VACTIVE, c_uint32)[1]
video_mode.timing.htotal = self.__io.get(TSI_PG_CUSTOM_TIMING_HTOTAL, c_uint32)[1]
video_mode.timing.vtotal = self.__io.get(TSI_PG_CUSTOM_TIMING_VTOTAL, c_uint32)[1]
video_mode.timing.hstart = self.__io.get(TSI_PG_CUSTOM_TIMING_HSTART, c_uint32)[1]
video_mode.timing.vstart = self.__io.get(TSI_PG_CUSTOM_TIMING_VSTART, c_uint32)[1]
video_mode.timing.hactive = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_HACTIVE, c_uint32)[1]
video_mode.timing.vactive = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_VACTIVE, c_uint32)[1]
video_mode.timing.htotal = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_HTOTAL, c_uint32)[1]
video_mode.timing.vtotal = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_VTOTAL, c_uint32)[1]
video_mode.timing.hstart = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_HSTART, c_uint32)[1]
video_mode.timing.vstart = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_VSTART, c_uint32)[1]
video_mode.color_info, h_sync_polarity, v_sync_polarity = self.__get_custom_timing_flags_to_video_mode()
video_mode.timing.hswidth = self.__io.get(TSI_PG_CUSTOM_TIMING_HSYNCW, c_uint32)[1] * (
video_mode.timing.hswidth = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_HSYNCW, c_uint32)[1] * (
-1 if h_sync_polarity else 1)
video_mode.timing.vswidth = self.__io.get(TSI_PG_CUSTOM_TIMING_VSYNCW, c_uint32)[1] * (
video_mode.timing.vswidth = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_VSYNCW, c_uint32)[1] * (
-1 if v_sync_polarity else 1)
video_mode.timing.frame_rate = self.__io.get(TSI_PG_CUSTOM_TIMING_FIELD_RATE, c_uint32)[1]
video_mode.timing.frame_rate = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_FIELD_RATE, c_uint32)[1]
return video_mode
def _become_active(self):
self.__io.set(TSI_PG_STREAM_SELECT, self.__stream)
self.__io.set(ci.TSI_PG_STREAM_SELECT, self.__stream)
def __read_pg_settings(self):
self.__io.set(TSI_PG_COMMAND_W, 2)
self.__io.set(ci.TSI_PG_COMMAND_W, 2)
def apply(self) -> bool:
"""
@@ -471,7 +484,7 @@ class PatternGenerator:
Returns:
object of bool type - settings were set successfully or not
"""
self.__io.set(TSI_PG_COMMAND_W, 3)
self.__io.set(ci.TSI_PG_COMMAND_W, 3)
def is_apply_pg_success(pg: PatternGenerator):
return pg.status().error == PGStatus.PGError.OK
@@ -487,7 +500,7 @@ class PatternGenerator:
object of PGStatus type.
"""
self._become_active()
return PGStatus(self.__io.get(TSI_PG_STATUS_R, c_uint32)[1])
return PGStatus(self.__io.get(ci.TSI_PG_STATUS_R, c_uint32)[1])
def reset(self):
"""
@@ -631,7 +644,7 @@ class DpPatternGenerator(PatternGenerator):
self.__as_config = None
return False
self.__io.set(TSI_PG_ADAPTIVE_SYNC_CTRL,
self.__io.set(p_ci.TSI_PG_ADAPTIVE_SYNC_CTRL,
get_as_params_value(self.__as_config),
data_count=len(get_as_params_value(self.__as_config)))
return True
@@ -659,8 +672,8 @@ class DpPatternGenerator(PatternGenerator):
return False
value = 1
value |= (1 << 31)
self.__io.set(TSI_PG_CUSTOM_PATTERN_SCROLLING_CONTROL, value, c_uint32)
self.__io.set(TSI_PG_CUSTOM_PATTERN_SCROLLING_CONFIG, get_pattern_params_value(self.__scrolling_params),
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_SCROLLING_CONTROL, value, c_uint32)
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_SCROLLING_CONFIG, get_pattern_params_value(self.__scrolling_params),
data_count=len(get_pattern_params_value(self.__scrolling_params)))
return True
return False
@@ -675,9 +688,9 @@ class DpPatternGenerator(PatternGenerator):
"""
self._become_active()
res = self.__io.get(TSI_PG_ADAPTIVE_SYNC_STS, c_uint32)
res = self.__io.get(p_ci.TSI_PG_ADAPTIVE_SYNC_STS, c_uint32)
if res[0] < TSI_SUCCESS:
if res[0] < ci.TSI_SUCCESS:
return False
return res[1] & 1 != 0
@@ -894,5 +907,5 @@ class DpMstPatternGenerator:
return self.__pg_list[0].panel_replay()
def __read_max_stream_count(self) -> int:
result = self.__io.get(TSI_PG_MAX_STREAM_COUNT_R, c_uint32)
result = self.__io.get(ci.TSI_PG_MAX_STREAM_COUNT_R, c_uint32)
return result[1]

View File

@@ -10,18 +10,18 @@ class SolidColorParams:
"""
def __init__(self, first: int = 0, second: int = 0, third: int = 0):
if not (0 <= first <= 255):
warnings.warn("Incorrect value. Must use value from range: 0 - 255. Will be used default value = 0")
if not (0 <= first < (1 << 16)):
warnings.warn("Incorrect value. Must use value from range: 0 - 65535. Will be used default value = 0")
first = 0
self.first = first
if not (0 <= second <= 255):
warnings.warn("Incorrect value. Must use value from range: 0 - 255. Will be used default value = 0")
if not (0 <= second < (1 << 16)):
warnings.warn("Incorrect value. Must use value from range: 0 - 65535. Will be used default value = 0")
second = 0
self.second = second
if not (0 <= third <= 255):
warnings.warn("Incorrect value. Must use value from range: 0 - 255. Will be used default value = 0")
if not (0 <= third < (1 << 16)):
warnings.warn("Incorrect value. Must use value from range: 0 - 65535. Will be used default value = 0")
third = 0
self.third = third

View File

@@ -1,8 +1,5 @@
from UniTAP.common import ColorInfo, VideoMode
from UniTAP.libs.lib_tsi.tsi_types import TSI_IMF_PK444_RGB_W8_C8, TSI_IMF_PK444_RGB_W16_C12, \
TSI_IMF_PK444_RGB_W16_C16, TSI_IMF_PK444_YCbCr_W8_C8, TSI_IMF_PK444_YCbCr_W16_C16, \
TSI_IMF_PK422_CbYCrY_W16_C8, TSI_IMF_PK422_CbYCrY_W16_C16, TSI_IMF_PK420_CxYY0_W8_C8, \
TSI_IMF_PK420_CxYY0_W8_C10, TSI_IMF_PK420_CxYY_W16_C12, TSI_IMF_PK420_CxYY_W16_C16
import UniTAP.libs.lib_tsi.tsi_types as ci
from .types import PGColorInfo, PGColorDepth, PGColorimetry, PGDynamicRange
@@ -106,30 +103,30 @@ def pg_pixel_format_from_vm(vm: VideoMode) -> int:
if color_format == ColorInfo.ColorFormat.CF_RGB:
if bpc == 8:
return TSI_IMF_PK444_RGB_W8_C8
return ci.TSI_IMF_PK444_RGB_W8_C8
elif bpc in [10, 12]:
return TSI_IMF_PK444_RGB_W16_C12
return ci.TSI_IMF_PK444_RGB_W16_C12
elif bpc == 16:
return TSI_IMF_PK444_RGB_W16_C16
return ci.TSI_IMF_PK444_RGB_W16_C16
elif color_format == ColorInfo.ColorFormat.CF_YCbCr_444:
if bpc == 8:
return TSI_IMF_PK444_YCbCr_W8_C8
return ci.TSI_IMF_PK444_YCbCr_W8_C8
elif bpc in [10, 12, 16]:
return TSI_IMF_PK444_YCbCr_W16_C16
return ci.TSI_IMF_PK444_YCbCr_W16_C16
elif color_format == ColorInfo.ColorFormat.CF_YCbCr_422:
if bpc == 8:
return TSI_IMF_PK422_CbYCrY_W16_C8
return ci.TSI_IMF_PK422_CbYCrY_W16_C8
elif bpc in [10, 12, 16]:
return TSI_IMF_PK422_CbYCrY_W16_C16
return ci.TSI_IMF_PK422_CbYCrY_W16_C16
elif color_format == ColorInfo.ColorFormat.CF_YCbCr_420:
if bpc == 8:
return TSI_IMF_PK420_CxYY0_W8_C8
return ci.TSI_IMF_PK420_CxYY0_W8_C8
elif bpc == 10:
return TSI_IMF_PK420_CxYY0_W8_C10
return ci.TSI_IMF_PK420_CxYY0_W8_C10
elif bpc == 12:
return TSI_IMF_PK420_CxYY_W16_C12
return ci.TSI_IMF_PK420_CxYY_W16_C12
elif bpc == 16:
return TSI_IMF_PK420_CxYY_W16_C16
return ci.TSI_IMF_PK420_CxYY_W16_C16
return 0xffffffff

View File

@@ -93,10 +93,9 @@ def get_as_params_value(params: ASParams) -> list:
params.increase_lines, params.decrease_lines]
def get_pattern_params_value(params: Union[PGPatternParams, PGScrollingParams], bpc: int = 8) -> list:
def get_pattern_params_value(params: Union[PGPatternParams, PGScrollingParams], solid_color_shifter = 8) -> list:
if isinstance(params, SolidColorParams):
up_shift = 16 - bpc
return [(((params.first << up_shift) << 16) | (params.second << up_shift)), (params.third << up_shift)]
return [(params.first << solid_color_shifter << 16) | (params.second << solid_color_shifter), params.third << solid_color_shifter]
elif isinstance(params, WhiteVStripsParams):
return [params.white_stripes_width, params.black_stripes_width]
elif isinstance(params, GradientStripsParams):
@@ -107,3 +106,5 @@ def get_pattern_params_value(params: Union[PGPatternParams, PGScrollingParams],
return [params.white_square]
elif isinstance(params, StepsScrollingParams):
return [params.frames, params.horizontally, params.frames, params.vertically]
else:
raise ValueError("Unsupported pattern params type")