1.1.0版本
This commit is contained in:
1
UniTAP/dev/ports/modules/link/hdmi/__init__.py
Normal file
1
UniTAP/dev/ports/modules/link/hdmi/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .types import FrlMode, FrlCaps, ClockRate, HdmiModeTx, HdmiModeRx, LinkMode
|
||||
134
UniTAP/dev/ports/modules/link/hdmi/arc_rx.py
Normal file
134
UniTAP/dev/ports/modules/link/hdmi/arc_rx.py
Normal 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"
|
||||
45
UniTAP/dev/ports/modules/link/hdmi/capabilities.py
Normal file
45
UniTAP/dev/ports/modules/link/hdmi/capabilities.py
Normal 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
|
||||
139
UniTAP/dev/ports/modules/link/hdmi/frl_caps_rx.py
Normal file
139
UniTAP/dev/ports/modules/link/hdmi/frl_caps_rx.py
Normal 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"
|
||||
366
UniTAP/dev/ports/modules/link/hdmi/frl_control_tx.py
Normal file
366
UniTAP/dev/ports/modules/link/hdmi/frl_control_tx.py
Normal 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"
|
||||
53
UniTAP/dev/ports/modules/link/hdmi/hdmi_utils.py
Normal file
53
UniTAP/dev/ports/modules/link/hdmi/hdmi_utils.py
Normal 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
|
||||
171
UniTAP/dev/ports/modules/link/hdmi/link.py
Normal file
171
UniTAP/dev/ports/modules/link/hdmi/link.py
Normal 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
|
||||
52
UniTAP/dev/ports/modules/link/hdmi/private_types.py
Normal file
52
UniTAP/dev/ports/modules/link/hdmi/private_types.py
Normal 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
|
||||
151
UniTAP/dev/ports/modules/link/hdmi/status_rx.py
Normal file
151
UniTAP/dev/ports/modules/link/hdmi/status_rx.py
Normal 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"
|
||||
140
UniTAP/dev/ports/modules/link/hdmi/status_tx.py
Normal file
140
UniTAP/dev/ports/modules/link/hdmi/status_tx.py
Normal 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"
|
||||
57
UniTAP/dev/ports/modules/link/hdmi/tmds_rx.py
Normal file
57
UniTAP/dev/ports/modules/link/hdmi/tmds_rx.py
Normal 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'}"
|
||||
99
UniTAP/dev/ports/modules/link/hdmi/tmds_tx.py
Normal file
99
UniTAP/dev/ports/modules/link/hdmi/tmds_tx.py
Normal 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"
|
||||
372
UniTAP/dev/ports/modules/link/hdmi/types.py
Normal file
372
UniTAP/dev/ports/modules/link/hdmi/types.py
Normal 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]
|
||||
Reference in New Issue
Block a user