1.1.0版本

This commit is contained in:
xinzhu.yin
2026-04-16 16:51:05 +08:00
commit c157e774e5
333 changed files with 70759 additions and 0 deletions

View File

@@ -0,0 +1 @@
from .types import FrlMode, FrlCaps, ClockRate, HdmiModeTx, HdmiModeRx, LinkMode

View File

@@ -0,0 +1,134 @@
from UniTAP.libs.lib_tsi.tsi_io import PortIO
from enum import IntEnum
from UniTAP.libs.lib_tsi.tsi_types import TSI_ARC_CONTROL_W, TSI_HDRX_ARC_STATUS_R
from ctypes import c_uint32
class ArcLoopbackAudioSource(IntEnum):
"""
Class `ArcLoopbackAudioSource` contains all possible variants of ARC loopback audio source type.
"""
Unknown = -1
TPG = 0
HDMI = 1
DVI = 2
DP = 3
SPDIF = 4
class ArcRx:
"""
Class `ArcRx` contains information about caps and states of Audio return channel.
- Support ARC `supported`.
- Loopback support TGP `loopback_supported_tpg`.
- Loopback support HDMI `loopback_supported_hdmi`.
- Loopback support DVI `loopback_supported_dvi`.
- Loopback support DP `loopback_supported_dp`.
- Loopback support SPDIF `loopback_supported_spdif`.
- Current state (enabled/disabled) - `enabled`.
- Control of ARC Source `arc_source`.
- Control of single mode `single_mode`.
"""
def __init__(self, port_io: PortIO):
self.__io = port_io
self.__supported = False
self.__loopback_supported_tpg = False
self.__loopback_supported_hdmi = False
self.__loopback_supported_dvi = False
self.__loopback_supported_dp = False
self.__loopback_supported_spdif = False
self.__enabled = False
self.__arc_source = ArcLoopbackAudioSource.HDMI
self.__arc_source_value = 2
self.__single_mode = True
def __read_arc_status(self) -> int:
return self.__io.get(TSI_HDRX_ARC_STATUS_R, c_uint32)[1]
def __write_arc(self, value: int):
self.__io.set(TSI_ARC_CONTROL_W, value, c_uint32)
@property
def supported(self) -> bool:
self.__supported = (self.__read_arc_status() & 0x1) != 0
return self.__supported
@property
def loopback_supported_tpg(self) -> bool:
self.__loopback_supported_tpg = ((self.__read_arc_status() >> 1) & 0x1) != 0
return self.__loopback_supported_tpg
@property
def loopback_supported_hdmi(self) -> bool:
self.__loopback_supported_hdmi = ((self.__read_arc_status() >> 2) & 0x1) != 0
return self.__loopback_supported_hdmi
@property
def loopback_supported_dvi(self) -> bool:
self.__loopback_supported_dvi = ((self.__read_arc_status() >> 8) & 0x1) != 0
return self.__loopback_supported_dvi
@property
def loopback_supported_dp(self) -> bool:
self.__loopback_supported_dp = ((self.__read_arc_status() >> 9) & 0x1) != 0
return self.__loopback_supported_dp
@property
def loopback_supported_spdif(self) -> bool:
self.__loopback_supported_spdif = ((self.__read_arc_status() >> 10) & 0x1) != 0
return self.__loopback_supported_spdif
@property
def enabled(self) -> bool:
self.__enabled = ((self.__read_arc_status() >> 31) & 0x1) != 0
return self.__enabled
@property
def arc_source(self) -> ArcLoopbackAudioSource:
return self.__arc_source
@property
def single_mode(self) -> bool:
return self.__single_mode
@single_mode.setter
def single_mode(self, single_mode: bool):
value = self.__arc_source_value | ((1 << 16) if single_mode else 0)
self.__write_arc(value)
self.__single_mode = single_mode
@arc_source.setter
def arc_source(self, arc_source: ArcLoopbackAudioSource):
self.__arc_source_value = 0
if arc_source == ArcLoopbackAudioSource.HDMI:
self.__arc_source_value |= 2
self.__arc_source_value |= (0 << 8)
elif arc_source == ArcLoopbackAudioSource.TPG:
self.__arc_source_value |= 1
elif arc_source == ArcLoopbackAudioSource.DVI:
self.__arc_source_value |= 2
self.__arc_source_value |= (1 << 8)
elif arc_source == ArcLoopbackAudioSource.DP:
self.__arc_source_value |= 2
self.__arc_source_value |= (2 << 8)
elif arc_source == ArcLoopbackAudioSource.SPDIF:
self.__arc_source_value |= 2
self.__arc_source_value |= (3 << 8)
value = self.__arc_source_value | ((1 << 16) if self.__single_mode else 0)
self.__write_arc(value)
self.__arc_source = arc_source
def __str__(self):
return f"Audio return channel supported: {self.supported}\n" \
f"Loopback supported TPG: {self.loopback_supported_tpg}\n" \
f"Loopback supported HDMI: {self.loopback_supported_hdmi}\n" \
f"Loopback supported DVI: {self.loopback_supported_dvi}\n" \
f"Loopback supported DP: {self.loopback_supported_dp}\n" \
f"Loopback supported SPDIF: {self.loopback_supported_spdif}\n" \
f"Enabled: {self.enabled}\n" \
f"ARC Source: {self.arc_source.name}\n" \
f"Single mode: {self.single_mode}\n"

View File

@@ -0,0 +1,45 @@
from UniTAP.libs.lib_tsi.tsi_io import PortIO
from ctypes import c_uint32
class HdmiCapabilities:
def __init__(self, ci_control: int, port_io: PortIO):
self.__io = port_io
caps = self.__io.get(ci_control, c_uint32)[1]
self.__cap_tmds = caps & 0x1
self.__cap_frl = (caps >> 1) & 0x1
self.__cap_arc = (caps >> 2) & 0x1
self.__cap_hdcp = (caps >> 3) & 0x1
self.__cap_behavior_14 = (caps >> 4) & 0x1
self.__cap_behavior_20 = (caps >> 5) & 0x1
self.__cap_behavior_21 = (caps >> 6) & 0x1
@property
def support_tmds(self) -> bool:
return self.__cap_tmds
@property
def support_frl(self) -> bool:
return self.__cap_tmds
@property
def support_arc(self) -> bool:
return self.__cap_tmds
@property
def support_hdcp(self) -> bool:
return self.__cap_tmds
@property
def support_hdmi_mode_14(self) -> bool:
return self.__cap_tmds
@property
def support_hdmi_mode_20(self) -> bool:
return self.__cap_tmds
@property
def support_hdmi_mode_21(self) -> bool:
return self.__cap_tmds

View File

@@ -0,0 +1,139 @@
from UniTAP.libs.lib_tsi.tsi_io import PortIO
from .types import FrlMode, LtpLanesPattern, FrlCaps, LtpPattern, _update_frl_values, _update_ltp_pattern_values
from UniTAP.libs.lib_tsi.tsi_types import TSI_HDRX_FRL_CAPABILITY, TSI_HDRX_FRL_PATTERN, TSI_HDRX_LINK_STATUS_R
from ctypes import c_uint32
class FrlControlRx:
"""
Class `FrlControlRx` contains information about FRL on Sink (RX - receiver) side.
allows working with:
- Set and get FRL mode `frl_mode`.
- Set and get FRL capabilities `frl_caps`.
- Set and get LTP requested `ltp_request` and additional `ltp_additional`.
"""
def __init__(self, port_io: PortIO):
self.__io = port_io
self.__frl_caps = FrlCaps()
self.__ltp_request = LtpLanesPattern()
self.__ltp_additional = LtpLanesPattern()
def __read_caps(self) -> int:
return self.__io.get(TSI_HDRX_FRL_CAPABILITY, c_uint32)[1]
def __write_caps(self, value: int):
self.__io.set(TSI_HDRX_FRL_CAPABILITY, value, c_uint32)
def __read_frl_pattern(self) -> int:
return self.__io.get(TSI_HDRX_FRL_PATTERN, c_uint32)[1]
def __write_frl_pattern(self, value: int):
self.__io.set(TSI_HDRX_FRL_PATTERN, value, c_uint32)
@property
def frl_mode(self) -> FrlMode:
"""
Returns current FRL mode.
Returns:
object of `FrlMode` type
"""
return FrlMode(self.__read_caps() & 0xF)
@frl_mode.setter
def frl_mode(self, frl_mode: FrlMode):
"""
Set new FRL mode.
Args:
frl_mode (`FrlMode`)
"""
new_value = frl_mode.value
new_value |= self.__read_caps() & ~0xF
self.__write_caps(new_value)
@property
def frl_caps(self) -> FrlCaps:
"""
Returns current FRL capabilities.
Returns:
object of `FrlCaps` type
"""
_update_frl_values(self.__frl_caps, self.__read_caps())
return self.__frl_caps
@frl_caps.setter
def frl_caps(self, frl_caps: FrlCaps):
"""
Set new FRL capabilities.
Args:
frl_caps (`FrlCaps`)
"""
new_value = frl_caps.value()
new_value |= self.__read_caps() & ~0xF
self.__write_caps(new_value)
self.__frl_caps = frl_caps
@property
def ltp_request(self) -> LtpLanesPattern:
"""
Returns current LTP lanes pattern. Current Pattern that is being checking during Link Training.
Each lane can request different pattern.
Returns:
object of `LtpLanesPattern` type
"""
_update_ltp_pattern_values(self.__ltp_request, self.__read_frl_pattern())
return self.__ltp_request
@ltp_request.setter
def ltp_request(self, ltp_request: LtpLanesPattern):
"""
Set new LTP lanes pattern.
Args:
ltp_request (`LtpLanesPattern`)
"""
new_value = ltp_request.value()
new_value |= self.__read_frl_pattern()
self.__write_frl_pattern(new_value)
self.__ltp_request = ltp_request
@property
def ltp_additional(self) -> LtpLanesPattern:
"""
Returns current additional LTP lanes pattern. Current Pattern that is being checking during Link Training.
Each lane can request different pattern.
Returns:
object of `LtpLanesPattern` type
"""
_update_ltp_pattern_values(self.__ltp_additional, self.__read_frl_pattern() >> 0xFF)
return self.__ltp_additional
@ltp_additional.setter
def ltp_additional(self, ltp_request: LtpLanesPattern):
"""
Set new additional LTP lanes pattern.
Args:
ltp_request (`LtpLanesPattern`)
"""
new_value = ltp_request.value() << 0xFF
new_value |= self.__read_frl_pattern()
self.__write_frl_pattern(new_value)
self.__ltp_additional = ltp_request
def re_train(self):
"""
DO re train.
"""
self.__io.set(TSI_HDRX_LINK_STATUS_R, 0x1c0000, c_uint32)
def __str__(self):
return f"FRL Mode: {self.frl_mode.name}\n" \
f"FRL Caps:\n{self.frl_caps.__str__()}" \
f"LTP Lanes Pattern:\n{self.ltp_request.__str__()}" \
f"LTP Lanes Pattern Additional:\n{self.ltp_additional.__str__()}\n"

View File

@@ -0,0 +1,366 @@
from UniTAP.libs.lib_tsi.tsi_io import PortIO
from .types import FrlMode, LtpLanesPattern, FrlCaps, _update_frl_values, _update_ltp_pattern_values
from UniTAP.libs.lib_tsi.tsi_types import TSI_HDTX_FRL_CAPABILITY, TSI_HDTX_FRL_PATTERN_R, TSI_HDTX_FRL_TIMERS, \
TSI_HDTX_SINK_FEATURE_W, TSI_HDTX_FRL_STATUS_R
from ctypes import c_uint32
class FfeMax:
"""
Class `FfeMax` allows working with FFE on HDMI.
Possible to configure:
- Set and get Value for mode 3 lanes and 3 Gbps `mode_3lanes_3gbps`.
- Set and get Value for mode 3 lanes and 6 Gbps `mode_3lanes_6gbps`.
- Set and get Value for mode 4 lanes and 6 Gbps `mode_4lanes_6gbps`.
- Set and get Value for mode 4 lanes and 8 Gbps `mode_4lanes_8gbps`.
- Set and get Value for mode 4 lanes and 10 Gbps `mode_4lanes_10gbps`.
- Set and get Value for mode 4 lanes and 12 Gbps `mode_4lanes_12gbps`.
"""
def __init__(self, mode_3lanes_3gbps: int = 0, mode_3lanes_6gbps: int = 0, mode_4lanes_6gbps: int = 0,
mode_4lanes_8gbps: int = 0, mode_4lanes_10gbps: int = 0, mode_4lanes_12gbps: int = 0):
self.__mode_3lanes_3gbps = mode_3lanes_3gbps
self.__mode_3lanes_6gbps = mode_3lanes_6gbps
self.__mode_4lanes_6gbps = mode_4lanes_6gbps
self.__mode_4lanes_8gbps = mode_4lanes_8gbps
self.__mode_4lanes_10gbps = mode_4lanes_10gbps
self.__mode_4lanes_12gbps = mode_4lanes_12gbps
@property
def mode_3lanes_3gbps(self) -> int:
"""
Returns current value for mode 3 lanes and 3 Gbps.
Returns:
object of int type
"""
return self.__mode_3lanes_3gbps
@mode_3lanes_3gbps.setter
def mode_3lanes_3gbps(self, ffe_value: int):
"""
Set new FFE value for mode 3 lanes and 3 Gbps.
Args:
ffe_value (int)
"""
if not(0 <= ffe_value <= 3):
raise ValueError(f"FFE value must be in range 0-3. Current value = {ffe_value}")
self.__mode_3lanes_3gbps = ffe_value
@property
def mode_3lanes_6gbps(self) -> int:
"""
Returns current value for mode 3 lanes and 6 Gbps.
Returns:
object of int type
"""
return self.__mode_3lanes_6gbps
@mode_3lanes_6gbps.setter
def mode_3lanes_6gbps(self, ffe_value: int):
"""
Set new FFE value for mode 3 lanes and 6 Gbps.
Args:
ffe_value (int)
"""
if not(0 <= ffe_value <= 3):
raise ValueError(f"FFE value must be in range 0-3. Current value = {ffe_value}")
self.__mode_3lanes_6gbps = ffe_value
@property
def mode_4lanes_6gbps(self) -> int:
"""
Returns current value for mode 6 lanes and 6 Gbps.
Returns:
object of int type
"""
return self.__mode_4lanes_6gbps
@mode_4lanes_6gbps.setter
def mode_4lanes_6gbps(self, ffe_value: int):
"""
Set new FFE value for mode 4 lanes and 6 Gbps.
Args:
ffe_value (int)
"""
if not (0 <= ffe_value <= 3):
raise ValueError(f"FFE value must be in range 0-3. Current value = {ffe_value}")
self.__mode_4lanes_6gbps = ffe_value
@property
def mode_4lanes_8gbps(self) -> int:
"""
Returns current value for mode 6 lanes and 8 Gbps.
Returns:
object of int type
"""
return self.__mode_4lanes_8gbps
@mode_4lanes_8gbps.setter
def mode_4lanes_8gbps(self, ffe_value: int):
"""
Set new FFE value for mode 4 lanes and 8 Gbps.
Args:
ffe_value (int)
"""
if not (0 <= ffe_value <= 3):
raise ValueError(f"FFE value must be in range 0-3. Current value = {ffe_value}")
self.__mode_4lanes_8gbps = ffe_value
@property
def mode_4lanes_10gbps(self) -> int:
"""
Returns current value for mode 6 lanes and 10 Gbps.
Returns:
object of int type
"""
return self.__mode_4lanes_10gbps
@mode_4lanes_10gbps.setter
def mode_4lanes_10gbps(self, ffe_value: int):
"""
Set new FFE value for mode 4 lanes and 10 Gbps.
Args:
ffe_value (int)
"""
if not (0 <= ffe_value <= 3):
raise ValueError(f"FFE value must be in range 0-3. Current value = {ffe_value}")
self.__mode_4lanes_10gbps = ffe_value
@property
def mode_4lanes_12gbps(self) -> int:
"""
Returns current value for mode 6 lanes and 12 Gbps.
Returns:
object of int type
"""
return self.__mode_4lanes_12gbps
@mode_4lanes_12gbps.setter
def mode_4lanes_12gbps(self, ffe_value: int):
"""
Set new FFE value for mode 4 lanes and 12 Gbps.
Args:
ffe_value (int)
"""
if not (0 <= ffe_value <= 3):
raise ValueError(f"FFE value must be in range 0-3. Current value = {ffe_value}")
self.__mode_4lanes_12gbps = ffe_value
def value(self) -> int:
"""
Returns current combined value from all modes.
Returns:
object of int type
"""
return ((self.mode_3lanes_3gbps & 0x3) << 5) | ((self.mode_3lanes_6gbps & 0x3) << 7) |\
((self.mode_4lanes_6gbps & 0x3) << 9) | ((self.mode_4lanes_8gbps & 0x3) << 11) | \
((self.mode_4lanes_10gbps & 0x3) << 13) | ((self.mode_4lanes_12gbps & 0x3) << 15)
def __str__(self):
return f"3 lanes 3 Gbps - {self.mode_3lanes_3gbps}\n" \
f"3 lanes 6 Gbps - {self.mode_3lanes_6gbps}\n" \
f"4 lanes 6 Gbps - {self.mode_4lanes_6gbps}\n" \
f"4 lanes 8 Gbps - {self.mode_4lanes_8gbps}\n" \
f"4 lanes 10 Gbps - {self.mode_4lanes_10gbps}\n" \
f"4 lanes 12 Gbps - {self.mode_4lanes_12gbps}\n"
class FrlControlTx:
"""
Class `FrlControlTx` contains information about FRL on Source (TX - transmitter) side.
allows working with:
- Set and get FRL mode `frl_mode`.
- Set and get FRL capabilities `frl_caps`.
- Set and get FFE max `ffe_max`.
- Set and get LTP requested `ltp_pattern` and additional `ltp_additional_pattern`.
- Set link training timeout `lt_timeout` and link training poll timeout `lt_poll_timeout`.
"""
def __init__(self, port_io: PortIO):
self.__io = port_io
self.__ffe_max = FfeMax(0)
self.__frl_caps = FrlCaps()
self.__lt_timeout = 0
self.__lt_poll_timeout = 0
self.__ltp_request = LtpLanesPattern()
self.__ltp_additional = LtpLanesPattern()
def __read_caps(self) -> int:
return self.__io.get(TSI_HDTX_FRL_CAPABILITY, c_uint32)[1]
def __write_caps(self, value: int):
self.__io.set(TSI_HDTX_FRL_CAPABILITY, value, c_uint32)
def __read_frl_timers(self) -> int:
return self.__io.get(TSI_HDTX_FRL_TIMERS, c_uint32)[1]
def __write_frl_timers(self, value: int):
self.__io.set(TSI_HDTX_FRL_TIMERS, value, c_uint32)
def __read_frl_patterns(self) -> int:
return self.__io.get(TSI_HDTX_FRL_PATTERN_R, c_uint32)[1]
@property
def ltp_pattern(self) -> LtpLanesPattern:
"""
Returns current LTP lanes pattern. Current Pattern that is being checking during Link Training.
Each lane can request different pattern.
Returns:
object of `LtpLanesPattern` type
"""
_update_ltp_pattern_values(self.__ltp_request, self.__read_frl_patterns())
return self.__ltp_request
@property
def ltp_additional_pattern(self) -> LtpLanesPattern:
"""
Returns current additional LTP lanes pattern. Current Pattern that is being checking during Link Training.
Each lane can request different pattern.
Returns:
object of `LtpLanesPattern` type
"""
_update_ltp_pattern_values(self.__ltp_additional, self.__read_frl_patterns() >> 16)
return self.__ltp_additional
@property
def frl_caps(self) -> FrlCaps:
"""
Returns current FRL capabilities.
Returns:
object of `FrlCaps` type
"""
_update_frl_values(self.__frl_caps, self.__io.get(TSI_HDTX_FRL_STATUS_R, c_uint32)[1])
return self.__frl_caps
@property
def frl_mode(self) -> FrlMode:
"""
Returns current FRL mode.
Returns:
object of `FrlMode` type
"""
return FrlMode(self.__read_caps() & 0x7)
@frl_mode.setter
def frl_mode(self, frl_mode: FrlMode):
"""
Set new FRL mode.
Args:
frl_mode (FrlMode)
"""
new_value = frl_mode.value
new_value |= self.__read_caps() & ~0x7
self.__write_caps(new_value)
@property
def ffe_max(self) -> FfeMax:
"""
Returns current FFE MAX values.
Returns:
object of `FfeMax` type
"""
ffe_values = self.__read_caps()
self.__update_values(self.__ffe_max, ffe_values)
return self.__ffe_max
@ffe_max.setter
def ffe_max(self, ffe_max: FfeMax):
"""
Set new FFE max values.
Args:
ffe_max (FfeMax)
"""
new_value = ffe_max.value()
new_value |= (self.__read_caps() >> 5) & ~0xFFF
self.__write_caps(new_value)
self.__ffe_max = ffe_max
@property
def lt_timeout(self) -> int:
"""
Returns current value of link training timeout.
Returns:
object of int type
"""
self.__lt_timeout = self.__read_frl_timers() & 0xFFFF
return self.__lt_timeout
@lt_timeout.setter
def lt_timeout(self, lt_timeout: int):
"""
Set new link training timeout.
Args:
lt_timeout (int)
"""
new_value = lt_timeout
new_value |= self.__read_frl_timers() & ~0xFFFF
self.__write_frl_timers(new_value)
self.__lt_timeout = lt_timeout
@property
def lt_poll_timeout(self) -> int:
"""
Returns current value of link training poll timeout.
Returns:
object of int type
"""
self.__lt_timeout = self.__read_frl_timers() & 0xFFFF
return self.__lt_timeout
@lt_poll_timeout.setter
def lt_poll_timeout(self, lt_poll_timeout: int):
"""
Set new link training poll timeout.
Args:
lt_poll_timeout (int)
"""
new_value = lt_poll_timeout
new_value |= self.__read_frl_timers() & ~(0xFFFF << 16)
self.__write_frl_timers(new_value)
self.__lt_poll_timeout = lt_poll_timeout
def link_training(self):
"""
Do link training.
"""
self.__io.set(TSI_HDTX_SINK_FEATURE_W, 5, c_uint32)
@staticmethod
def __update_values(ffe_max: FfeMax, value: int):
ffe_max.mode_3lanes_3gbps = (value >> 5) & 0x3
ffe_max.mode_3lanes_6gbps = (value >> 7) & 0x3
ffe_max.mode_4lanes_6gbps = (value >> 9) & 0x3
ffe_max.mode_4lanes_8gbps = (value >> 11) & 0x3
ffe_max.mode_4lanes_10gbps = (value >> 13) & 0x3
ffe_max.mode_4lanes_12gbps = (value >> 15) & 0x3
def __str__(self):
return f"FRL Mode: {self.frl_mode.name}\n" \
f"FRL Caps:\n{self.frl_caps.__str__()}" \
f"LTP Lanes Pattern:\n{self.ltp_pattern.__str__()}" \
f"LTP Lanes Pattern Additional:\n{self.ltp_additional_pattern.__str__()}" \
f"LT timeout: {self.lt_timeout}\n" \
f"LT poll timeout: {self.lt_poll_timeout}\n" \
f"FFE Max:\n{self.ffe_max.__str__()}\n"

View File

@@ -0,0 +1,53 @@
from UniTAP.common import VideoMode, ColorInfo, Timing
def get_vm_color_format(color_mode: int) -> ColorInfo.ColorFormat:
if color_mode == 0:
return ColorInfo.ColorFormat.CF_NONE
elif color_mode == 1:
return ColorInfo.ColorFormat.CF_UNKNOWN
elif color_mode == 2:
return ColorInfo.ColorFormat.CF_RGB
elif color_mode == 3:
return ColorInfo.ColorFormat.CF_YCbCr_422
elif color_mode == 4:
return ColorInfo.ColorFormat.CF_YCbCr_444
elif color_mode == 5:
return ColorInfo.ColorFormat.CF_YCbCr_420
else:
return ColorInfo.ColorFormat.CF_IDO_DEFINED
def get_vm_colorimetry(colorimetry: int) -> ColorInfo.Colorimetry:
if colorimetry == 0:
return ColorInfo.Colorimetry.CM_RESERVED
elif colorimetry == 1:
return ColorInfo.Colorimetry.CM_NONE
elif colorimetry == 2:
return ColorInfo.Colorimetry.CM_sRGB
elif colorimetry == 3:
return ColorInfo.Colorimetry.CM_SMPTE_170M
elif colorimetry == 4:
return ColorInfo.Colorimetry.CM_ITUR_BT601
elif colorimetry == 5:
return ColorInfo.Colorimetry.CM_ITUR_BT709
elif colorimetry == 6:
return ColorInfo.Colorimetry.CM_xvYCC601
elif colorimetry == 7:
return ColorInfo.Colorimetry.CM_xvYCC709
elif colorimetry == 8:
return ColorInfo.Colorimetry.CM_sYCC601
elif colorimetry == 9:
return ColorInfo.Colorimetry.CM_AdobeYCC601
elif colorimetry == 10:
return ColorInfo.Colorimetry.CM_AdobeRGB
elif colorimetry == 11:
return ColorInfo.Colorimetry.CM_ITUR_BT2020_YcCbcCrc
elif colorimetry == 12:
return ColorInfo.Colorimetry.CM_ITUR_BT2020_YCbCr
elif colorimetry == 13:
return ColorInfo.Colorimetry.CM_ITUR_BT2020_RGB
else:
return ColorInfo.Colorimetry.CM_RESERVED

View File

@@ -0,0 +1,171 @@
import warnings
from UniTAP.libs.lib_tsi.tsi_io import PortIO
from .arc_rx import ArcRx
from .tmds_rx import TmdsRx
from .tmds_tx import TmdsTx
from .status_rx import StatusRx, HdmiModeRx
from .status_tx import StatusTx, HdmiModeTx
from .capabilities import HdmiCapabilities
from .frl_control_tx import FrlControlTx
from .frl_caps_rx import FrlControlRx
from UniTAP.libs.lib_tsi.tsi_types import TSI_HDTX_CAPABILITY_R, TSI_HDRX_CAPABILITY_R
from typing import Optional
class HdmiLinkTx:
"""
Main class describes HDMI link on Source (TX - transmitter) side. Contains following objects for working with link:
- TMDS `tmds`.
- FRL `frl`.
- Status `status`.
"""
def __init__(self, port_io: PortIO):
self.__io = port_io
self.__tmds = TmdsTx(self.__io)
self.__status = StatusTx(self.__io)
self.__frl = FrlControlTx(self.__io)
self.__caps = HdmiCapabilities(TSI_HDTX_CAPABILITY_R, self.__io)
@property
def tmds(self) -> Optional[TmdsTx]:
"""
Returns object of class `TmdsTx` for working with TMDS.
None if TMDS does not support on the device.
Returns:
object of `TmdsTx`|None type
"""
if self.__status.hdmi_mode == HdmiModeTx.HDMI_2_1:
warnings.warn("Current device mode is HDMI 2.1, please, use FRL controls or change HDMI mode.")
return None
if not self.__caps.support_tmds:
warnings.warn("Current device does not support TMDS.")
return None
return self.__tmds
@property
def frl(self) -> Optional[FrlControlTx]:
"""
Returns object of class `FrlControlTx` for working with FRL.
None if FRL does not support on the device.
Returns:
object of `FrlControlTx`|None type
"""
if self.__status.hdmi_mode != HdmiModeTx.HDMI_2_1:
warnings.warn("Current device mode is not HDMI 2.1, please, use TMDS controls or change HDMI mode.")
return None
if not self.__caps.support_frl:
warnings.warn("Current device does not support FRl.")
return None
return self.__frl
@property
def status(self) -> StatusTx:
"""
Returns object of class `StatusTx` for working with link status.
Returns:
object of `StatusTx` type
"""
return self.__status
def __str__(self):
__str = f"Status:\n{self.status.__str__()}\n"
if self.__status.hdmi_mode == HdmiModeTx.HDMI_2_1 and self.__caps.support_frl:
__str += f"FRL:\n{self.frl.__str__()}\n"
if self.__status.hdmi_mode != HdmiModeTx.HDMI_2_1 and self.__caps.support_tmds:
__str += f"TMDS:\n{self.tmds.__str__()}\n"
return __str
class HdmiLinkRx:
"""
Main class describes HDMI link on Sink (RX - receiver) side. Contains following objects for working with link:
- TMDS `tmds`.
- FRL `frl`.
- ARC `arc`.
- Status `status`.
"""
def __init__(self, port_io: PortIO):
self.__io = port_io
self.__tmds = TmdsRx(self.__io)
self.__status = StatusRx(self.__io)
self.__frl = FrlControlRx(self.__io)
self.__arc = ArcRx(self.__io)
self.__caps = HdmiCapabilities(TSI_HDRX_CAPABILITY_R, self.__io)
@property
def tmds(self) -> Optional[TmdsRx]:
"""
Returns object of class `TmdsRx` for working with TMDS.
None if TMDS does not support on the device.
Returns:
object of `TmdsRx`|None type
"""
if self.__status.hdmi_mode == HdmiModeTx.HDMI_2_1:
warnings.warn("Current device mode is HDMI 2.1, please, use FRL controls or change HDMI mode.")
return None
if not self.__caps.support_tmds:
warnings.warn("Current device does not support TMDS.")
return None
return self.__tmds
@property
def frl(self) -> Optional[FrlControlRx]:
"""
Returns object of class `FrlControlRx` for working with FRL.
None if FRL does not support on the device.
Returns:
object of `FrlControlRx`|None type
"""
if self.__status.hdmi_mode != HdmiModeRx.HDMI_2_1:
warnings.warn("Current device mode is not HDMI 2.1, please, use TMDS controls or change HDMI mode.")
return None
if not self.__caps.support_frl:
warnings.warn("Current device does not support FRl.")
return None
return self.__frl
@property
def arc(self) -> Optional[ArcRx]:
"""
Returns object of class `ArcRx` for working with ARC.
None if ARC does not support on the device.
Returns:
object of `ArcRx`|None type
"""
if not self.__caps.support_arc:
warnings.warn("Current device does not support ARC.")
return None
return self.__arc
@property
def status(self) -> StatusRx:
"""
Returns object of class `StatusRx` for working with link status.
Returns:
object of `StatusRx` type
"""
return self.__status
def __str__(self):
__str = f"Status:\n{self.status.__str__()}\n"
if self.__status.hdmi_mode == HdmiModeTx.HDMI_2_1 and self.__caps.support_frl:
__str += f"FRL:\n{self.frl.__str__()}\n"
if self.__status.hdmi_mode != HdmiModeTx.HDMI_2_1 and self.__caps.support_tmds:
__str += f"TMDS:\n{self.tmds.__str__()}\n"
if self.__caps.support_arc:
__str += f"ARC:\n{self.arc.__str__()}\n"
__str += f"Stream info:\n{self.status.stream(0).__str__()}\n"
return __str

View File

@@ -0,0 +1,52 @@
from ctypes import Structure, c_uint16, c_uint32
class HdmiCrc(Structure):
_fields_ = [
('r', c_uint16),
('g', c_uint16),
('b', c_uint16)
]
class HdmiVideoMode(Structure):
_fields_ = [
('h_total', c_uint32),
('v_total', c_uint32),
('h_active', c_uint32),
('v_active', c_uint32),
('f_rate', c_uint32),
('color_mode', c_uint32),
('colorimetry', c_uint32),
('bpp', c_uint32),
('h_start', c_uint32),
('v_start', c_uint32),
('h_sync_width', c_uint32),
('v_sync_width', c_uint32),
('bpc', c_uint32)
]
class HdmiVideoModeInfo:
def __init__(self, hdmi_vm: HdmiVideoMode):
self.h_total = hdmi_vm.h_total
self.v_total = hdmi_vm.v_total
self.h_active = hdmi_vm.h_active
self.v_active = hdmi_vm.v_active
self.h_start = hdmi_vm.h_start
self.v_start = hdmi_vm.v_start
self.h_sync_width = hdmi_vm.h_sync_width
self.v_sync_width = hdmi_vm.v_sync_width
self.frame_rate = hdmi_vm.f_rate
self.bpp = hdmi_vm.bpp
self.color_mode = hdmi_vm.color_mode
self.colorimetry = hdmi_vm.colorimetry
self.bpc = hdmi_vm.bpc
def is_eq(self, other) -> bool:
return self.h_total == other.h_total and self.v_total == other.v_total and self.h_active == other.h_active and \
self.v_active == other.v_active and self.h_start == other.h_start and self.v_start == other.v_start and \
self.h_sync_width == other.h_sync_start and self.v_sync_width == other.v_sync_start and \
self.frame_rate == other.frame_rate and self.bpp == other.bpp and self.color_mode == other.color_mode \
and self.colorimetry == self.colorimetry and self.bpc == self.bpc

View File

@@ -0,0 +1,151 @@
import time
from UniTAP.libs.lib_tsi.tsi_io import PortIO
from .types import HdmiModeRx, FrlMode, _update_error_counters_rx
from UniTAP.libs.lib_tsi.tsi_types import TSI_HDRX_BEHAVIOR, TSI_HDRX_LANES_ERR_COUNTERS_R, TSI_HDRX_HPD_STATUS_R,\
TSI_HDRX_FRL_CAPABILITY, TSI_HDRX_LINK_STATUS_R, TSI_HDRX_HPD_CONTROL_W, TSI_HDRX_VIDEO_MODE_R, \
TSI_VIDCAP_SIGNAL_CRC_R, TSI_SUCCESS
from ctypes import c_uint8, c_uint32, c_uint64
from UniTAP.utils.function_wrapper import function_scheduler
from .types import _hdmi_vm_info_to_video_mode, HdmiVideoModeInfo
from .private_types import HdmiCrc, HdmiVideoMode
from ..dp.link_status_common import StreamStatus
class StatusRx:
"""
Class `StatusRx` describes information about HDMI link status on Sink (RX - receiver) side. Contains following info:
- HDMI mode `hdmi_mode`.
- Link Error counters `error_counters`.
- Channel lock `channel_lock`.
- HPD status `hpd_status` and HPD assert `set_assert_state`.
- Stream info `stream`.
"""
def __init__(self, port_io: PortIO):
self.__io = port_io
def __frl_status(self) -> FrlMode:
return FrlMode(self.__io.get(TSI_HDRX_FRL_CAPABILITY, c_uint32)[1] & 0xF)
@property
def hdmi_mode(self) -> HdmiModeRx:
"""
Returns current HDMI mode.
Returns:
object of `HdmiModeRx` type
"""
return HdmiModeRx(self.__io.get(TSI_HDRX_BEHAVIOR, c_uint32)[1])
@hdmi_mode.setter
def hdmi_mode(self, hdmi_mode: HdmiModeRx):
"""
Set new HDMI mode.
Args:
hdmi_mode (HdmiModeRx)
"""
self.__io.set(TSI_HDRX_BEHAVIOR, hdmi_mode.value, c_uint32)
@property
def error_counters(self) -> list:
"""
Returns values of current errors on link.
Returns:
object of list type
"""
return _update_error_counters_rx(self.__io.get(TSI_HDRX_LANES_ERR_COUNTERS_R, c_uint64)[1])
def set_assert_state(self, asserted: bool = True):
"""
Assert/Deassert HPD state.
Args:
asserted (bool)
"""
self.__io.set(TSI_HDRX_HPD_CONTROL_W, int(asserted), c_uint32)
@property
def channel_lock(self) -> list:
"""
Returns channel lock states of current link.
Returns:
object of list type
"""
return self.__update_channel_lock(self.__io.get(TSI_HDRX_LINK_STATUS_R, c_uint32)[1], self.hdmi_mode)
@staticmethod
def __update_channel_lock(value: int, mode: HdmiModeRx) -> list:
if mode != HdmiModeRx.HDMI_2_1:
lane_0 = (value & (1 << 4)) != 0
lane_1 = (value & (1 << 5)) != 0
lane_2 = (value & (1 << 6)) != 0
lane_3 = False
else:
lane_0 = (value & (1 << 13)) != 0
lane_1 = (value & (1 << 14)) != 0
lane_2 = (value & (1 << 15)) != 0
lane_3 = (value & (1 << 16)) != 0
return [lane_0, lane_1, lane_2, lane_3]
@property
def hpd_status(self) -> bool:
"""
Returns True if HDP is enabled, False - if not.
Returns:
object of bool type
"""
return (self.__io.get(TSI_HDRX_HPD_STATUS_R, c_uint32)[1] & 0x1) != 0
def __check_video(self) -> bool:
def is_msa_available(io):
result, msa_info, size = io.get(TSI_HDRX_VIDEO_MODE_R, HdmiVideoMode, 4)
return result > 0
return function_scheduler(is_msa_available, self.__io, interval=5, timeout=10)
def stream(self, stream_index: int = 0) -> StreamStatus:
"""
Returns status of selected stream `StreamStatus`.
Args:
stream_index (int) - number of selected number
Returns:
object of `StreamStatus` type
"""
stream_status = StreamStatus()
if not self.__check_video():
raise ValueError("Video is not available.")
time.sleep(1)
result, hdmi_video_mode_info, size = self.__io.get(TSI_HDRX_VIDEO_MODE_R, HdmiVideoMode, 4)
# TODO - Size temporary will be equal 1
size = 1
if 0 <= stream_index < size:
stream_status.video_mode = _hdmi_vm_info_to_video_mode(HdmiVideoModeInfo(hdmi_video_mode_info
[stream_index]))
result = self.__io.get(TSI_VIDCAP_SIGNAL_CRC_R, data_type=c_uint8, data_count=6)
if result[0] >= TSI_SUCCESS:
hdmi_crc = HdmiCrc.from_buffer(bytearray(result[1]))
stream_status.crc = [hdmi_crc.r, hdmi_crc.g, hdmi_crc.b]
stream_status.dsc_crc = [0, 0, 0]
else:
raise ValueError(f"Selected stream {stream_index} is not available. "
f"Available stream number: {size}")
return stream_status
def __str__(self):
return f"HDMI Mode: {self.hdmi_mode.name}\n" \
f"Channel Lock:\n{self.channel_lock}\n" \
f"Error Counters:\n{self.error_counters.__str__()}\n"

View File

@@ -0,0 +1,140 @@
from UniTAP.libs.lib_tsi.tsi_io import PortIO
from .types import HdmiModeTx, FrlMode, _update_error_counters_tx
from UniTAP.libs.lib_tsi.tsi_types import TSI_HDTX_FRL_STATUS_R, TSI_HDTX_CONTROL_W, TSI_HDTX_STATUS_R, \
TSI_HDTX_SINK_STATUS_R, TSI_HDTX_LANES_ERR_COUNTERS_R, TSI_HDTX_HPD_STATUS_R
from ctypes import c_uint32, c_uint64
class StatusTx:
"""
Class `StatusTx` describes information about HDMI link status on Source (TX - transmitter) side.
Contains following info:
- Set and get HDMI mode `hdmi_mode`.
- Link Error counters `error_counters`.
- Video status `video_status`.
- Channel lock `channel_lock`.
- HPD status `hpd_status`.
"""
def __init__(self, port_io: PortIO):
self.__io = port_io
def __read_status(self) -> int:
return self.__io.get(TSI_HDTX_STATUS_R, c_uint32)[1]
def __frl_status(self) -> FrlMode:
return FrlMode(self.__io.get(TSI_HDTX_FRL_STATUS_R, c_uint32)[1] & 0xF)
@property
def video_status(self) -> bool:
"""
Returns current video status (video enable or not).
Returns:
object of bool type
"""
return (self.__read_status() & 0x2) != 0
@property
def error_counters(self) -> list:
"""
Returns values of current errors on link.
Returns:
object of list type
"""
return _update_error_counters_tx(self.__io.get(TSI_HDTX_LANES_ERR_COUNTERS_R, c_uint64)[1])
@property
def channel_lock(self) -> list:
"""
Returns channel lock states of current link.
Returns:
object of list type
"""
if self.__frl_status().Mode_Disable or self.hdmi_mode in [HdmiModeTx.HDMI_1_4, HdmiModeTx.HDMI_2_0]:
return self.__update_channel_lock(self.__io.get(TSI_HDTX_SINK_STATUS_R, c_uint32)[1], self.hdmi_mode)
else:
return self.__update_channel_lock(self.__io.get(TSI_HDTX_FRL_STATUS_R, c_uint32)[1], self.hdmi_mode)
@property
def hpd_status(self) -> bool:
"""
Returns True if HDP is enabled, False - if not.
Returns:
object of bool type
"""
return (self.__io.get(TSI_HDTX_HPD_STATUS_R, c_uint32)[1] & 0x1) != 0
@property
def hdmi_mode(self) -> HdmiModeTx:
"""
Returns current HDMI mode.
Returns:
object of `HdmiModeTx` type
"""
return HdmiModeTx((self.__read_status() >> 2) & 0x3)
@hdmi_mode.setter
def hdmi_mode(self, hdmi_mode: HdmiModeTx):
"""
Set new HDMI mode.
Args:
hdmi_mode (HdmiModeTx)
"""
self.__io.set(TSI_HDTX_CONTROL_W, hdmi_mode.value << 2, c_uint32)
@property
def available_link_rate(self) -> float:
"""
Returns available link rate.
Returns:
object of float type
"""
gbps = 1000000000
frl_status = self.__frl_status()
if frl_status == FrlMode.Mode_Disable:
link_rate = 3 * 6 * gbps
elif frl_status == FrlMode.Mode_3lanes_3gbps:
link_rate = 3 * 3 * gbps
elif frl_status == FrlMode.Mode_3lanes_6gbps:
link_rate = 3 * 6 * gbps
elif frl_status == FrlMode.Mode_4lanes_6gbps:
link_rate = 4 * 6 * gbps
elif frl_status == FrlMode.Mode_4lanes_8gbps:
link_rate = 4 * 8 * gbps
elif frl_status == FrlMode.Mode_4lanes_10gbps:
link_rate = 4 * 10 * gbps
elif frl_status == FrlMode.Mode_4lanes_12gbps:
link_rate = 4 * 12 * gbps
else:
link_rate = 0
return link_rate
@staticmethod
def __update_channel_lock(value, mode: HdmiModeTx) -> list:
if mode != HdmiModeTx.HDMI_2_1:
lane_0 = (value & (1 << 6)) != 0
lane_1 = (value & (1 << 7)) != 0
lane_2 = (value & (1 << 8)) != 0
lane_3 = False
else:
lane_0 = (((value >> 25) & 0xF) >> 0) & 0x1 != 0
lane_1 = (((value >> 25) & 0xF) >> 1) & 0x1 != 0
lane_2 = (((value >> 25) & 0xF) >> 2) & 0x1 != 0
lane_3 = (((value >> 25) & 0xF) >> 3) & 0x1 != 0
return [lane_0, lane_1, lane_2, lane_3]
def __str__(self):
return f"HDMI Mode: {self.hdmi_mode.name}\n" \
f"Channel Lock:\n{self.channel_lock}\n" \
f"Error Counters:\n{self.error_counters.__str__()}\n"

View File

@@ -0,0 +1,57 @@
from UniTAP.libs.lib_tsi.tsi_io import PortIO
from .types import LinkMode
from UniTAP.libs.lib_tsi.tsi_types import TSI_HDRX_LINK_STATUS_R
from ctypes import c_uint32
class TmdsRx:
"""
CLass `TmdsRx` allows working with TMDS on Sink (RX - receiver) side.
- Get link mode `link_mode`.
- Get clock rate `clock_rate`.
- Get input stream lock state `input_stream_lock`.
"""
def __init__(self, port_io: PortIO):
self.__io = port_io
self.__link_mode = LinkMode.Unknown
self.__input_stream_lock = False
def __read_link_status(self) -> int:
return self.__io.get(TSI_HDRX_LINK_STATUS_R, c_uint32)[1]
@property
def clock_rate(self) -> int:
"""
Returns current clock rate.
Returns:
object of int type
"""
return 6 if self.__read_link_status() & 0x2 else 3
@property
def link_mode(self) -> LinkMode:
"""
Returns current link mode.
Returns:
object of `LinkMode` type
"""
self.__link_mode = LinkMode(self.__read_link_status() & 0x8)
return self.__link_mode
@property
def input_stream_lock(self) -> bool:
"""
Returns current state of input stream lock.
Returns:
object of bool type
"""
self.__input_stream_lock = (self.__read_link_status() & 0x4) != 0
return self.__input_stream_lock
def __str__(self):
return f"Clock rate: {self.clock_rate}G\n" \
f"Link mode: {self.link_mode.name}\n" \
f"Input stream lock: {'Enable' if self.input_stream_lock else 'Disable'}"

View File

@@ -0,0 +1,99 @@
import warnings
from UniTAP.libs.lib_tsi.tsi_io import PortIO
from .types import ClockRate, LinkMode, ScramblerState
from UniTAP.libs.lib_tsi.tsi_types import TSI_HDTX_SINK_FEATURE_W, TSI_HDTX_STATUS_R, TSI_HDTX_SINK_STATUS_R, \
TSI_HDTX_CONTROL_W
from ctypes import c_uint32
class TmdsTx:
"""
CLass `TmdsRx` allows working with TMDS on Source (TX - transmitter) side.
- Get link mode `link_mode`.
- Set and get clock rate `clock_rate`.
- Set and get scrambler `scrambler`.
"""
def __init__(self, port_io: PortIO):
self.__io = port_io
self.__clock_rate = ClockRate.Unknown
self.__link_mode = LinkMode.Unknown
self.__scrambler = ScramblerState.Unknown
def __read_sink_status(self) -> int:
return self.__io.get(TSI_HDTX_SINK_STATUS_R, c_uint32)[1]
def __read_hdtx_status(self) -> int:
return self.__io.get(TSI_HDTX_STATUS_R, c_uint32)[1]
def __write_sink_feature(self, value: int):
self.__io.set(TSI_HDTX_SINK_FEATURE_W, value, c_uint32)
@property
def clock_rate(self) -> int:
"""
Returns current clock rate.
Returns:
object of int type
"""
return 6 if self.__read_sink_status() & 0x2 else 3
@clock_rate.setter
def clock_rate(self, clock_rate: int):
"""
Set new clock rate value. Available variants: 3, 6.
Args:
clock_rate (int)
"""
if clock_rate not in [3, 6]:
warnings.warn("Incorrect value. Must be from available values: 3, 6")
return
self.__write_sink_feature(3 if clock_rate == 3 else 4)
@property
def link_mode(self) -> LinkMode:
"""
Returns current link mode.
Returns:
object of `LinkMode` type
"""
self.__link_mode = LinkMode(self.__read_hdtx_status() & 0x1)
return self.__link_mode
@link_mode.setter
def link_mode(self, link_mode: LinkMode):
"""
Set new link mode.
Args:
link_mode (LinkMode)
"""
self.__io.set(TSI_HDTX_CONTROL_W, link_mode.value, c_uint32)
@property
def scrambler(self) -> bool:
"""
Returns current scrambler state.
Returns:
object of bool type
"""
return self.__read_sink_status() & 0x1 != 0
@scrambler.setter
def scrambler(self, scrambler: bool):
"""
Enable/disable scrambler.
Args:
scrambler (bool)
"""
self.__write_sink_feature(1 if scrambler else 2)
def __str__(self):
return f"Clock rate: {self.clock_rate}G\n" \
f"Link mode: {self.link_mode.name}\n" \
f"Scrambler: {'Enable' if self.scrambler else 'Disable'}\n"

View File

@@ -0,0 +1,372 @@
from enum import IntEnum
from .hdmi_utils import *
from .private_types import HdmiVideoModeInfo
class FrlMode(IntEnum):
"""
Class `FrlMode` contains all possible variants of FRL modes.
"""
Mode_Unknown = -1
Mode_Disable = 0
Mode_3lanes_3gbps = 1
Mode_3lanes_6gbps = 2
Mode_4lanes_6gbps = 3
Mode_4lanes_8gbps = 4
Mode_4lanes_10gbps = 5
Mode_4lanes_12gbps = 6
class LtpPattern(IntEnum):
"""
Class `LtpPattern` contains all possible variants of LTP pattern types.
"""
Unknown = -1
NoLinkPattern = 0
All_1s = 1
All_0s = 2
NyquistClockPattern = 3
SourceTxFFECompliance = 4
LFSR0 = 5
LFSR1 = 6
LFSR2 = 7
LFSR3 = 8
class ScramblerState(IntEnum):
"""
Class `ScramblerState` contains all possible variants of scrambler states.
"""
Unknown = -1
Disable = 0
Enable = 1
class LinkMode(IntEnum):
"""
Class `LinkMode` contains all possible variants of Link modes.
"""
Unknown = -1
HDMI = 0
DVI = 1
class ClockRate(IntEnum):
"""
Class `ClockRate` contains all possible variants of clock rate.
"""
Unknown = -1
Rate3G = 0
Rate6G = 1
class HdmiModeTx(IntEnum):
"""
Class `HdmiModeTx` contains all possible variants of HDMI modes on TX side.
"""
Unknown = -1
HDMI_2_0 = 0
HDMI_1_4 = 1
HDMI_2_1 = 2
class HdmiModeRx(IntEnum):
"""
Class `HdmiModeRx` contains all possible variants of HDMI modes on RX side.
"""
Unknown = -1
HDMI_1_4 = 0
HDMI_2_0 = 1
HDMI_2_1 = 2
class LtpLanesPattern:
"""
Class `LtpLanesPattern` describes LTP pattern values on all lanes.
- Lane 0 `lane0`.
- Lane 1 `lane1`.
- Lane 2 `lane2`.
- Lane 3 `lane3`.
"""
def __init__(self):
self.__lane0 = LtpPattern.Unknown
self.__lane1 = LtpPattern.Unknown
self.__lane2 = LtpPattern.Unknown
self.__lane3 = LtpPattern.Unknown
@property
def lane0(self) -> LtpPattern:
"""
Returns `LtpPattern` value of line 0.
Returns:
object of `LtpPattern` type
"""
return self.__lane0
@lane0.setter
def lane0(self, lane0: LtpPattern):
"""
Set new value `LtpPattern` to lane 0.
Args:
lane0 (LtpPattern)
"""
self.__lane0 = lane0
@property
def lane1(self) -> LtpPattern:
"""
Returns `LtpPattern` value of line 1.
Returns:
object of `LtpPattern` type
"""
return self.__lane1
@lane1.setter
def lane1(self, lane1: LtpPattern):
"""
Set new value `LtpPattern` to lane 1.
Args:
lane1 (LtpPattern)
"""
self.__lane1 = lane1
@property
def lane2(self) -> LtpPattern:
"""
Returns `LtpPattern` value of line 2.
Returns:
object of `LtpPattern` type
"""
return self.__lane2
@lane2.setter
def lane2(self, lane2: LtpPattern):
"""
Set new value `LtpPattern` to lane 1.
Args:
lane2 (LtpPattern)
"""
self.__lane2 = lane2
@property
def lane3(self) -> LtpPattern:
"""
Returns `LtpPattern` value of line 3.
Returns:
object of `LtpPattern` type
"""
return self.__lane3
@lane3.setter
def lane3(self, lane3: LtpPattern):
"""
Set new value `LtpPattern` to lane 3.
Args:
lane3 (LtpPattern)
"""
self.__lane3 = lane3
def value(self) -> int:
"""
Returns combines value of all lines.
Returns:
object of int type
"""
return self.lane0.value | (self.lane1.value << 4) | (self.lane2.value << 8) | (self.lane3.value << 12)
def __str__(self):
return f"Lane 0: {self.lane0}\n" \
f"Lane 1: {self.lane1}\n" \
f"Lane 2: {self.lane2}\n" \
f"Lane 3: {self.lane3}\n"
class FrlCaps:
"""
Class `FrlCaps` describes FRL capabilities.
- FRL start `frl_start`.
- FLT no timeout `flt_no_timeout`.
- FLT ready `flt_ready`
- FRL max `frl_max`.
- Check patterns state `check_patterns`.
"""
def __init__(self):
self.__frl_start = False
self.__flt_no_timeout = False
self.__flt_ready = False
self.__frl_max = False
self.__check_patterns = False
@property
def frl_start(self) -> bool:
"""
Returns state of FRL start.
Returns:
object of bool type
"""
return self.__frl_start
@frl_start.setter
def frl_start(self, frl_start: bool):
"""
Set new state to FRL start.
Args:
frl_start (bool)
"""
self.__frl_start = frl_start
@property
def flt_no_timeout(self) -> bool:
"""
Returns state of FLT no timeout.
Returns:
object of bool type
"""
return self.__flt_no_timeout
@flt_no_timeout.setter
def flt_no_timeout(self, flt_no_timeout: bool):
"""
Set new state to FLT no timeout.
Args:
flt_no_timeout (bool)
"""
self.__flt_no_timeout = flt_no_timeout
@property
def flt_ready(self) -> bool:
"""
Returns state of FLT ready.
Returns:
object of bool type
"""
return self.__flt_ready
@flt_ready.setter
def flt_ready(self, flt_ready: bool):
"""
Set new state to FLT ready.
Args:
flt_ready (bool)
"""
self.__flt_ready = flt_ready
@property
def frl_max(self) -> bool:
"""
Returns state of FLT max.
Returns:
object of bool type
"""
return self.__frl_max
@frl_max.setter
def frl_max(self, frl_max: bool):
"""
Set new state to FLT max.
Args:
frl_max (bool)
"""
self.__frl_max = frl_max
@property
def check_patterns(self) -> bool:
"""
Returns state of check patterns.
Returns:
object of bool type
"""
return self.__check_patterns
@check_patterns.setter
def check_patterns(self, check_patterns: bool):
"""
Set new state to check patterns.
Args:
check_patterns (bool)
"""
self.__check_patterns = check_patterns
def value(self) -> int:
"""
Returns combined value of all flags.
Returns:
object of int type
"""
return (self.frl_start << 4) | (self.flt_ready << 5) | (self.flt_no_timeout << 6) | (self.frl_max << 7) | \
(self.check_patterns << 8)
def __str__(self):
return f"FRL Start: {self.__frl_start}\n" \
f"FRL No Timeout: {self.__flt_no_timeout}\n" \
f"FRL Max: {self.__frl_max}\n" \
f"Check patterns: {self.__check_patterns}\n"
def _hdmi_vm_info_to_video_mode(hdmi_vm_info: HdmiVideoModeInfo):
video_mode = VideoMode()
video_mode.timing.hactive = hdmi_vm_info.h_active
video_mode.timing.vactive = hdmi_vm_info.v_active
video_mode.timing.htotal = hdmi_vm_info.h_total
video_mode.timing.vtotal = hdmi_vm_info.v_total
video_mode.timing.hstart = hdmi_vm_info.h_start
video_mode.timing.vstart = hdmi_vm_info.v_start
video_mode.timing.hswidth = hdmi_vm_info.h_sync_width
video_mode.timing.vswidth = hdmi_vm_info.v_sync_width
video_mode.color_info.colorimetry = get_vm_colorimetry(hdmi_vm_info.colorimetry)
video_mode.color_info.color_format = get_vm_color_format(hdmi_vm_info.color_mode)
video_mode.color_info.bpc = hdmi_vm_info.bpc
video_mode.color_info.dynamic_range = ColorInfo.DynamicRange.DR_VESA
video_mode.timing.frame_rate = hdmi_vm_info.frame_rate
return video_mode
def _update_frl_values(frl_caps: FrlCaps, value: int):
frl_caps.frl_start = bool(value >> 4 & 0x1)
frl_caps.flt_ready = bool(value >> 5 & 0x1)
frl_caps.flt_no_timeout = bool(value >> 6 & 0x1)
frl_caps.frl_max = bool(value >> 7 & 0x1)
frl_caps.check_patterns = bool(value >> 8 & 0x1)
def _update_ltp_pattern_values(pattern: LtpLanesPattern, value: int):
pattern.lane0 = LtpPattern(value & 0xF)
pattern.lane1 = LtpPattern((value >> 4) & 0xF)
pattern.lane2 = LtpPattern((value >> 8) & 0xF)
pattern.lane3 = LtpPattern((value >> 12) & 0xF)
def _update_error_counters_rx(value: int) -> list:
lane0 = value & 0x7FFF if (value >> 15) & 0x1 else 0
lane1 = ((value >> 16) & 0xFFFF) if (value >> 31) & 0x1 else 0
lane2 = ((value >> 32) & 0xFFFF) if (value >> 47) & 0x1 else 0
lane3 = ((value >> 48) & 0xFFFF) if (value >> 63) & 0x1 else 0
return [lane0, lane1, lane2, lane3]
def _update_error_counters_tx(value: int) -> list:
return [value & 0xFFFF, (value >> 16) & 0xFFFF, (value >> 32) & 0xFFFF, (value >> 48) & 0xFFFF]