141 lines
4.4 KiB
Python
141 lines
4.4 KiB
Python
|
|
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"
|