Files

141 lines
4.4 KiB
Python
Raw Permalink Normal View History

2026-04-16 16:51:05 +08:00
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"