Compare commits
3 Commits
a500751d85
...
4a2fa1daff
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a2fa1daff | ||
|
|
32aaef1c0f | ||
|
|
9fa811a9eb |
@@ -19,6 +19,7 @@ class AudioFormat(IntEnum):
|
||||
- PCMAudio.
|
||||
"""
|
||||
Unknown = -1
|
||||
Compressed = 0x0
|
||||
L_PCM = 0xFFFF
|
||||
|
||||
|
||||
@@ -218,7 +219,7 @@ class AudioFrameData:
|
||||
Args:
|
||||
sample_format (int) - must be more than 0
|
||||
"""
|
||||
if sample_format <= 0:
|
||||
if sample_format < 0:
|
||||
raise ValueError(f"Sample format must be more than 0.")
|
||||
self.__sample_format = AudioFormat(sample_format)
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from .ports import DPRX, DPTX, HDRX, HDTX, PDC340
|
||||
from .ports import DPRX, DPTX, HDRX, HDRX_eARC, HDTX, PDC340
|
||||
from .modules import MemoryManager, Capturer, DUTTests
|
||||
from UniTAP.libs.lib_tsi.tsi_io import DeviceIO, PortProtocol
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortProtocol
|
||||
from .dev_base_roles import DevBase, DeviceIO
|
||||
|
||||
|
||||
class UCD340:
|
||||
@@ -9,7 +10,8 @@ class UCD340:
|
||||
- 'USB-C, DP Alt Mode Reference Sink' `USBCSink`
|
||||
- 'USB-C, DP Alt Mode Reference Source' `USBCSource`.
|
||||
"""
|
||||
class USBCSink:
|
||||
|
||||
class USBCSink(DevBase):
|
||||
"""
|
||||
Class `USBCSink` contains information of available functionality modules for role USB-C Sink (RX - receiver)
|
||||
role:
|
||||
@@ -17,7 +19,9 @@ class UCD340:
|
||||
- `DUTTests`.
|
||||
- `PDC`.
|
||||
"""
|
||||
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__port_io = dev_io.create_port_io(0, PortProtocol.DisplayPortThrowUSBC)
|
||||
self.__dprx = DPRX(self.__port_io, memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
@@ -63,7 +67,7 @@ class UCD340:
|
||||
"""
|
||||
return list(UCD340.ROLE_DICT.keys())[list(UCD340.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
class USBCSource:
|
||||
class USBCSource(DevBase):
|
||||
"""
|
||||
Class `USBCSource` contains information of available functionality modules for role USB-C Source
|
||||
(TX - transmitter) role:
|
||||
@@ -71,7 +75,9 @@ class UCD340:
|
||||
- `DUTTests`.
|
||||
- `PDC`.
|
||||
"""
|
||||
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__port_io = dev_io.create_port_io(0, PortProtocol.DisplayPortThrowUSBC)
|
||||
self.__dptx = DPTX(self.__port_io, memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
@@ -140,13 +146,16 @@ class UCD323:
|
||||
- 'HDMI Reference Sink (HDCP 2.3)' `HDMISink`
|
||||
- 'HDMI Reference Source (HDCP 2.3)' `HDMISource`
|
||||
"""
|
||||
class DPSink:
|
||||
|
||||
class DPSink(DevBase):
|
||||
"""
|
||||
Class `DPSink` contains information of available functionality modules for role DP Sink (RX - receiver) role:
|
||||
- `DPRX`.
|
||||
- `DUTTests`.
|
||||
"""
|
||||
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__dprx = DPRX(dev_io.create_port_io(0, PortProtocol.DisplayPort), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
|
||||
@@ -180,14 +189,16 @@ class UCD323:
|
||||
"""
|
||||
return list(UCD323.ROLE_DICT.keys())[list(UCD323.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
class DPSource:
|
||||
class DPSource(DevBase):
|
||||
"""
|
||||
Class `DPSink` contains information of available functionality modules for role DP Source (TX - transmitter)
|
||||
role:
|
||||
- `DPTX`.
|
||||
- `DUTTests`.
|
||||
"""
|
||||
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__dptx = DPTX(dev_io.create_port_io(0, PortProtocol.DisplayPort), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
|
||||
@@ -221,19 +232,21 @@ class UCD323:
|
||||
"""
|
||||
return list(UCD323.ROLE_DICT.keys())[list(UCD323.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
class HDMISink:
|
||||
class HDMISink(DevBase):
|
||||
"""
|
||||
Class `HDMISink` contains information of available functionality modules for role HDMI Sink (RX - receiver)
|
||||
role:
|
||||
- `HDRX`.
|
||||
- `DUTTests`.
|
||||
"""
|
||||
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
self.__hdrx = HDRX(dev_io.create_port_io(0, PortProtocol.HDMI), memory_manager, capturer)
|
||||
super().__init__(dev_io)
|
||||
self.__hdrx = HDRX_eARC(dev_io.create_port_io(0, PortProtocol.HDMI), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
|
||||
@property
|
||||
def hdrx(self) -> HDRX:
|
||||
def hdrx(self) -> HDRX_eARC:
|
||||
"""
|
||||
Returns HDMI Sink (RX - receiver) role.
|
||||
|
||||
@@ -262,14 +275,16 @@ class UCD323:
|
||||
"""
|
||||
return list(UCD323.ROLE_DICT.keys())[list(UCD323.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
class HDMISource:
|
||||
class HDMISource(DevBase):
|
||||
"""
|
||||
Class `HDMISource` contains information of available functionality modules for role HDMI Source
|
||||
(TX - transmitter) role:
|
||||
- `HDTX`.
|
||||
- `DUTTests`.
|
||||
"""
|
||||
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__hdtx = HDTX(dev_io.create_port_io(0, PortProtocol.HDMI), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
|
||||
@@ -303,11 +318,55 @@ class UCD323:
|
||||
"""
|
||||
return list(UCD323.ROLE_DICT.keys())[list(UCD323.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
class HDMISinkEARC(DevBase):
|
||||
"""
|
||||
Class `HDMISink` contains information of available functionality modules for role HDMI Sink (RX - receiver)
|
||||
role:
|
||||
- `HDRX`.
|
||||
- `DUTTests`.
|
||||
"""
|
||||
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__hdrx = HDRX_eARC(dev_io.create_port_io(0, PortProtocol.HDMI), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
|
||||
@property
|
||||
def hdrx(self) -> HDRX_eARC:
|
||||
"""
|
||||
Returns HDMI Sink (RX - receiver) role.
|
||||
|
||||
Returns:
|
||||
object of HDRX type.
|
||||
"""
|
||||
return self.__hdrx
|
||||
|
||||
@property
|
||||
def dut_tests(self) -> DUTTests:
|
||||
"""
|
||||
Returns DUT Test module.
|
||||
|
||||
Returns:
|
||||
object of DUTTests type.
|
||||
"""
|
||||
return self.__dut_tests
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""
|
||||
Returns name of role.
|
||||
|
||||
Returns:
|
||||
object of str type.
|
||||
"""
|
||||
return list(UCD323.ROLE_DICT.keys())[list(UCD323.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
ROLE_DICT = {
|
||||
"DisplayPort Reference Sink (SST, HDCP 2.3)": DPSink,
|
||||
"DisplayPort Reference Source (SST, HDCP 2.3)": DPSource,
|
||||
"HDMI Reference Sink (HDCP 2.3)": HDMISink,
|
||||
"HDMI Reference Source (HDCP 2.3)": HDMISource,
|
||||
"HDMI Reference Sink (eARC)": HDMISinkEARC,
|
||||
}
|
||||
|
||||
|
||||
@@ -317,13 +376,16 @@ class UCD301:
|
||||
- 'DisplayPort Reference Sink (SST, HDCP 2.3)' `DPSink`
|
||||
- 'HDMI Reference Sink (HDCP 2.3)' `HDMISink`
|
||||
"""
|
||||
class DPSink:
|
||||
|
||||
class DPSink(DevBase):
|
||||
"""
|
||||
Class `DPSink` contains information of available functionality modules for role DP Sink (RX - receiver) role:
|
||||
- `DPRX`.
|
||||
- `DUTTests`.
|
||||
"""
|
||||
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__dprx = DPRX(dev_io.create_port_io(0, PortProtocol.DisplayPort), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
|
||||
@@ -357,14 +419,16 @@ class UCD301:
|
||||
"""
|
||||
return list(UCD301.ROLE_DICT.keys())[list(UCD301.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
class HDMISink:
|
||||
class HDMISink(DevBase):
|
||||
"""
|
||||
Class `HDMISink` contains information of available functionality modules for role HDMI Sink (RX - receiver)
|
||||
role:
|
||||
- `HDRX`.
|
||||
- `DUTTests`.
|
||||
"""
|
||||
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__hdrx = HDRX(dev_io.create_port_io(0, PortProtocol.HDMI), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
|
||||
@@ -398,7 +462,7 @@ class UCD301:
|
||||
"""
|
||||
return list(UCD301.ROLE_DICT.keys())[list(UCD301.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
class DPSinkHDMISink:
|
||||
class DPSinkHDMISink(DevBase):
|
||||
"""
|
||||
Class `DPSinkHDMISink` contains information of available functionality modules for role DP and HDMI Sink
|
||||
(RX - receiver) role:
|
||||
@@ -408,6 +472,7 @@ class UCD301:
|
||||
"""
|
||||
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__dprx = DPRX(dev_io.create_port_io(0, PortProtocol.DisplayPort), memory_manager, capturer)
|
||||
self.__hdrx = HDRX(dev_io.create_port_io(0, PortProtocol.HDMI), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from UniTAP.dev.ports import DPRX4xx, DPTX4xx, HDRX4xx, HDTX4xx, PDC424
|
||||
from .modules import MemoryManager, Capturer, DUTTests
|
||||
from UniTAP.libs.lib_tsi.tsi_io import DeviceIO, PortProtocol
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortProtocol
|
||||
from .dev_base_roles import DevBase, DeviceIO
|
||||
|
||||
|
||||
class UCD400:
|
||||
@@ -8,7 +9,7 @@ class UCD400:
|
||||
Class `UCD400` describes of device UCD-400. Device has one possible role:
|
||||
- 'DisplayPort Source and Sink' `DPSourceDPSink`
|
||||
"""
|
||||
class DPSourceDPSink:
|
||||
class DPSourceDPSink(DevBase):
|
||||
"""
|
||||
Class `DPSourceDPSink` contains information of available functionality modules for role DP Sink
|
||||
(RX - receiver) and DP Source (TX - transmitter) roles:
|
||||
@@ -17,7 +18,7 @@ class UCD400:
|
||||
- `DUTTests`.
|
||||
"""
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__()
|
||||
super().__init__(dev_io)
|
||||
self.__dprx = DPRX4xx(dev_io.create_port_io(0, PortProtocol.DisplayPort), memory_manager, capturer)
|
||||
self.__dptx = DPTX4xx(dev_io.create_port_io(1, PortProtocol.DisplayPort), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
@@ -72,7 +73,7 @@ class UCD422:
|
||||
Class `UCD422` describes of device UCD-422. Device has one possible role:
|
||||
- 'HDMI Source and Sink' `HDMISourceHDMISink`
|
||||
"""
|
||||
class HDMISourceHDMISink:
|
||||
class HDMISourceHDMISink(DevBase):
|
||||
"""
|
||||
Class `DPSourceDPSink` contains information of available functionality modules for role HDMI Sink
|
||||
(RX - receiver) and HDMI Source (TX - transmitter) roles:
|
||||
@@ -81,7 +82,7 @@ class UCD422:
|
||||
- `DUTTests`.
|
||||
"""
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__()
|
||||
super().__init__(dev_io)
|
||||
self.__hdrx = HDRX4xx(dev_io.create_port_io(0, PortProtocol.HDMI), memory_manager, capturer)
|
||||
self.__hdtx = HDTX4xx(dev_io.create_port_io(1, PortProtocol.HDMI), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
@@ -136,7 +137,7 @@ class UCD424:
|
||||
Class `UCD424` describes of device UCD-424. Device has one possible role:
|
||||
- 'USB-C Source and Sink' `USBCSourceUSBCSink`.
|
||||
"""
|
||||
class USBCSourceUSBCSink:
|
||||
class USBCSourceUSBCSink(DevBase):
|
||||
"""
|
||||
Class `DPSourceDPSink` contains information of available functionality modules for role HDMI Sink
|
||||
(RX - receiver) and HDMI Source (TX - transmitter) roles:
|
||||
@@ -146,7 +147,7 @@ class UCD424:
|
||||
- `PDC`.
|
||||
"""
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__()
|
||||
super().__init__(dev_io)
|
||||
self.__port_rx = dev_io.create_port_io(0, PortProtocol.DisplayPortThrowUSBC)
|
||||
self.__port_tx = dev_io.create_port_io(1, PortProtocol.DisplayPortThrowUSBC)
|
||||
self.__dprx = DPRX4xx(self.__port_rx, memory_manager, capturer)
|
||||
@@ -218,3 +219,237 @@ class UCD424:
|
||||
ROLE_DICT = {
|
||||
"USB-C Source and Sink": USBCSourceUSBCSink
|
||||
}
|
||||
|
||||
|
||||
class UCD451:
|
||||
"""
|
||||
Class `UCD451` describes of device UCD-451. Device has one possible role:
|
||||
- 'DP Source' `DPSource`
|
||||
"""
|
||||
|
||||
class DPSource(DevBase):
|
||||
"""
|
||||
Class `DPSourceDPSink` contains information of available functionality modules for role
|
||||
DP Source (TX - transmitter) roles:
|
||||
- `DPTX4xx`.
|
||||
- `DUTTests`.
|
||||
"""
|
||||
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__dptx = DPTX4xx(dev_io.create_port_io(0, PortProtocol.DisplayPort), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
|
||||
@property
|
||||
def dptx(self) -> DPTX4xx:
|
||||
"""
|
||||
Returns DP Source (TX - transmitter) role.
|
||||
|
||||
Returns:
|
||||
object of DPTX4xx type.
|
||||
"""
|
||||
return self.__dptx
|
||||
|
||||
@property
|
||||
def dut_tests(self) -> DUTTests:
|
||||
"""
|
||||
Returns DUT Test module.
|
||||
|
||||
Returns:
|
||||
object of DUTTests type.
|
||||
"""
|
||||
return self.__dut_tests
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""
|
||||
Returns name of role.
|
||||
|
||||
Returns:
|
||||
object of str type.
|
||||
"""
|
||||
return list(UCD451.ROLE_DICT.keys())[list(UCD451.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
ROLE_DICT = {
|
||||
"DisplayPort Source": DPSource
|
||||
}
|
||||
|
||||
|
||||
class UCD461:
|
||||
"""
|
||||
Class `UCD461` describes of device UCD-461. Device has one possible role:
|
||||
- 'DisplayPort Source and Sink' `DPSourceDPSink`
|
||||
"""
|
||||
class DPSourceDPSink(DevBase):
|
||||
"""
|
||||
Class `DPSourceDPSink` contains information of available functionality modules for role DP Sink
|
||||
(RX - receiver) and DP Source (TX - transmitter) roles:
|
||||
- `DPRX4xx`.
|
||||
- `DPTX4xx`.
|
||||
- `DUTTests`.
|
||||
"""
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__dprx = DPRX4xx(dev_io.create_port_io(0, PortProtocol.DisplayPort), memory_manager, capturer)
|
||||
self.__dptx = DPTX4xx(dev_io.create_port_io(1, PortProtocol.DisplayPort), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
|
||||
@property
|
||||
def dprx(self) -> DPRX4xx:
|
||||
"""
|
||||
Returns DP Sink (RX - receiver) role.
|
||||
|
||||
Returns:
|
||||
object of DPRX4xx type.
|
||||
"""
|
||||
return self.__dprx
|
||||
|
||||
@property
|
||||
def dptx(self) -> DPTX4xx:
|
||||
"""
|
||||
Returns DP Source (TX - transmitter) role.
|
||||
|
||||
Returns:
|
||||
object of DPTX4xx type.
|
||||
"""
|
||||
return self.__dptx
|
||||
|
||||
@property
|
||||
def dut_tests(self) -> DUTTests:
|
||||
"""
|
||||
Returns DUT Test module.
|
||||
|
||||
Returns:
|
||||
object of DUTTests type.
|
||||
"""
|
||||
return self.__dut_tests
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""
|
||||
Returns name of role.
|
||||
|
||||
Returns:
|
||||
object of str type.
|
||||
"""
|
||||
return list(UCD461.ROLE_DICT.keys())[list(UCD461.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
ROLE_DICT = {
|
||||
"DisplayPort Source and Sink": DPSourceDPSink
|
||||
}
|
||||
|
||||
|
||||
class UCD452:
|
||||
"""
|
||||
Class `UCD452` describes of device UCD-452. Device has one possible role:
|
||||
- 'HDMI Source' `HDMISource`
|
||||
"""
|
||||
class HDMISource(DevBase):
|
||||
"""
|
||||
Class `DPSourceDPSink` contains information of available functionality modules for role
|
||||
HDMI Source (TX - transmitter) roles:
|
||||
- `HDTX4xx`.
|
||||
- `DUTTests`.
|
||||
"""
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__hdtx = HDTX4xx(dev_io.create_port_io(0, PortProtocol.HDMI), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
|
||||
@property
|
||||
def hdtx(self) -> HDTX4xx:
|
||||
"""
|
||||
Returns HDMI Source (TX - transmitter) role.
|
||||
|
||||
Returns:
|
||||
object of HDTX4xx type.
|
||||
"""
|
||||
return self.__hdtx
|
||||
|
||||
@property
|
||||
def dut_tests(self) -> DUTTests:
|
||||
"""
|
||||
Returns DUT Test module.
|
||||
|
||||
Returns:
|
||||
object of DUTTests type.
|
||||
"""
|
||||
return self.__dut_tests
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""
|
||||
Returns name of role.
|
||||
|
||||
Returns:
|
||||
object of str type.
|
||||
"""
|
||||
return list(UCD452.ROLE_DICT.keys())[list(UCD452.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
ROLE_DICT = {
|
||||
"HDMI Source": HDMISource
|
||||
}
|
||||
|
||||
|
||||
class UCD462:
|
||||
"""
|
||||
Class `UCD462` describes of device UCD-462. Device has one possible role:
|
||||
- 'HDMI Source and Sink' `HDMISourceHDMISink`
|
||||
"""
|
||||
class HDMISourceHDMISink(DevBase):
|
||||
"""
|
||||
Class `DPSourceDPSink` contains information of available functionality modules for role HDMI Sink
|
||||
(RX - receiver) and HDMI Source (TX - transmitter) roles:
|
||||
- `HDRX4xx`.
|
||||
- `HDTX4xx`.
|
||||
- `DUTTests`.
|
||||
"""
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__hdrx = HDRX4xx(dev_io.create_port_io(0, PortProtocol.HDMI), memory_manager, capturer)
|
||||
self.__hdtx = HDTX4xx(dev_io.create_port_io(1, PortProtocol.HDMI), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
|
||||
@property
|
||||
def hdtx(self) -> HDTX4xx:
|
||||
"""
|
||||
Returns HDMI Source (TX - transmitter) role.
|
||||
|
||||
Returns:
|
||||
object of HDTX4xx type.
|
||||
"""
|
||||
return self.__hdtx
|
||||
|
||||
@property
|
||||
def hdrx(self) -> HDRX4xx:
|
||||
"""
|
||||
Returns HDMI Sink (RX - receiver) role.
|
||||
|
||||
Returns:
|
||||
object of HDRX4xx type.
|
||||
"""
|
||||
return self.__hdrx
|
||||
|
||||
@property
|
||||
def dut_tests(self) -> DUTTests:
|
||||
"""
|
||||
Returns DUT Test module.
|
||||
|
||||
Returns:
|
||||
object of DUTTests type.
|
||||
"""
|
||||
return self.__dut_tests
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""
|
||||
Returns name of role.
|
||||
|
||||
Returns:
|
||||
object of str type.
|
||||
"""
|
||||
return list(UCD462.ROLE_DICT.keys())[list(UCD462.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
ROLE_DICT = {
|
||||
"HDMI Source and Sink": HDMISourceHDMISink
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from UniTAP.dev.ports import DPRX5xx, DPTX5xx, PDC500
|
||||
from .modules import MemoryManager, Capturer, DUTTests
|
||||
from UniTAP.libs.lib_tsi.tsi_io import DeviceIO, PortProtocol
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortProtocol
|
||||
from .dev_base_roles import DevBase, DeviceIO
|
||||
|
||||
|
||||
class UCD500:
|
||||
@@ -11,7 +12,8 @@ class UCD500:
|
||||
- 'DisplayPort Sink and USB-C, DP Alt Mode Source' `USBCSourceDPSink`.
|
||||
- 'USB-C, DP Alt Mode Source and Sink' `USBCSourceUSBCSink`.
|
||||
"""
|
||||
class DPSourceDPSink:
|
||||
|
||||
class DPSourceDPSink(DevBase):
|
||||
"""
|
||||
Class `DPSourceDPSink` contains information of available functionality modules for role DP Sink
|
||||
(RX - receiver) and DP Source (TX - transmitter) roles:
|
||||
@@ -19,7 +21,9 @@ class UCD500:
|
||||
- `DPTX5xx`.
|
||||
- `DUTTests`.
|
||||
"""
|
||||
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__dprx = DPRX5xx(dev_io.create_port_io(0, PortProtocol.DisplayPort), memory_manager, capturer)
|
||||
self.__dptx = DPTX5xx(dev_io.create_port_io(1, PortProtocol.DisplayPort), memory_manager, capturer)
|
||||
self.__dut_tests = DUTTests(dev_io)
|
||||
@@ -64,8 +68,9 @@ class UCD500:
|
||||
"""
|
||||
return list(UCD500.ROLE_DICT.keys())[list(UCD500.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
class DPSourceUSBCSink:
|
||||
class DPSourceUSBCSink(DevBase):
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__port_rx = dev_io.create_port_io(0, PortProtocol.DisplayPortThrowUSBC)
|
||||
self.__dptx = DPTX5xx(dev_io.create_port_io(1, PortProtocol.DisplayPort), memory_manager, capturer)
|
||||
self.__dprx = DPRX5xx(self.__port_rx, memory_manager, capturer)
|
||||
@@ -122,8 +127,9 @@ class UCD500:
|
||||
"""
|
||||
return list(UCD500.ROLE_DICT.keys())[list(UCD500.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
class USBCSourceDPSink:
|
||||
class USBCSourceDPSink(DevBase):
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__port_tx = dev_io.create_port_io(1, PortProtocol.DisplayPortThrowUSBC)
|
||||
self.__dptx = DPTX5xx(self.__port_tx, memory_manager, capturer)
|
||||
self.__dprx = DPRX5xx(dev_io.create_port_io(0, PortProtocol.DisplayPort), memory_manager, capturer)
|
||||
@@ -180,8 +186,9 @@ class UCD500:
|
||||
"""
|
||||
return list(UCD500.ROLE_DICT.keys())[list(UCD500.ROLE_DICT.values()).index(type(self))]
|
||||
|
||||
class USBCSourceUSBCSink:
|
||||
class USBCSourceUSBCSink(DevBase):
|
||||
def __init__(self, dev_io: DeviceIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(dev_io)
|
||||
self.__port_rx = dev_io.create_port_io(0, PortProtocol.DisplayPortThrowUSBC)
|
||||
self.__port_tx = dev_io.create_port_io(1, PortProtocol.DisplayPortThrowUSBC)
|
||||
self.__dprx = DPRX5xx(self.__port_rx, memory_manager, capturer)
|
||||
|
||||
28
UniTAP/dev/dev_base_roles.py
Normal file
28
UniTAP/dev/dev_base_roles.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from UniTAP.libs.lib_tsi.tsi_io import DeviceIO
|
||||
|
||||
|
||||
class DevBase:
|
||||
"""
|
||||
Class `DevBase`.
|
||||
"""
|
||||
|
||||
def __init__(self, dev_io: DeviceIO):
|
||||
self.__dev_io = dev_io
|
||||
|
||||
def is_fw_update_available(self) -> bool:
|
||||
"""
|
||||
Checks if there is a firmware update available for the current device.
|
||||
|
||||
Returns:
|
||||
object of bool type.
|
||||
"""
|
||||
return self.__dev_io.is_fw_update_available()
|
||||
|
||||
def get_fw_update_info(self) -> str:
|
||||
"""
|
||||
Returns a list of modules to update on the current device and also displays the current version.
|
||||
|
||||
Returns:
|
||||
object of str type.
|
||||
"""
|
||||
return self.__dev_io.get_fw_update_info()
|
||||
@@ -3,7 +3,7 @@ import weakref
|
||||
from typing import TypeVar, Type, List
|
||||
|
||||
from .dev_5xx_roles import UCD500
|
||||
from .dev_4xx_roles import UCD400, UCD422, UCD424
|
||||
from .dev_4xx_roles import UCD400, UCD422, UCD424, UCD451, UCD452, UCD461, UCD462
|
||||
from .dev_3xx_roles import UCD240, UCD340, UCD323, UCD301
|
||||
from .modules import *
|
||||
|
||||
@@ -16,6 +16,11 @@ RoleType = TypeVar("RoleType",
|
||||
UCD500.USBCSourceUSBCSink,
|
||||
UCD500.USBCSourceDPSink,
|
||||
|
||||
UCD462.HDMISourceHDMISink,
|
||||
UCD461.DPSourceDPSink,
|
||||
UCD452.HDMISource,
|
||||
UCD451.DPSource,
|
||||
|
||||
UCD424.USBCSourceUSBCSink,
|
||||
UCD422.HDMISourceHDMISink,
|
||||
UCD400.DPSourceDPSink,
|
||||
@@ -26,6 +31,7 @@ RoleType = TypeVar("RoleType",
|
||||
UCD323.DPSink,
|
||||
UCD323.DPSource,
|
||||
UCD323.HDMISink,
|
||||
UCD323.HDMISinkEARC,
|
||||
UCD323.HDMISource,
|
||||
|
||||
UCD301.DPSink,
|
||||
@@ -36,6 +42,10 @@ RoleType = TypeVar("RoleType",
|
||||
|
||||
MODEL_TO_CLASS = {
|
||||
"UCD-500": UCD500,
|
||||
"UCD-462": UCD462,
|
||||
"UCD-461": UCD461,
|
||||
"UCD-452": UCD452,
|
||||
"UCD-451": UCD451,
|
||||
"UCD-424": UCD424,
|
||||
"UCD-422": UCD422,
|
||||
"UCD-400": UCD400,
|
||||
@@ -90,9 +100,10 @@ class TSIDevice:
|
||||
|
||||
def __define_internal_handler(self, role, role_type):
|
||||
if role_type in [UCD500.DPSourceUSBCSink, UCD500.DPSourceDPSink, UCD500.USBCSourceUSBCSink,
|
||||
UCD500.USBCSourceDPSink, UCD424.USBCSourceUSBCSink, UCD400.DPSourceDPSink]:
|
||||
UCD500.USBCSourceDPSink, UCD424.USBCSourceUSBCSink, UCD400.DPSourceDPSink,
|
||||
UCD461.DPSourceDPSink]:
|
||||
self.opf_handler._set_roles(role.dptx, role.dprx)
|
||||
elif role_type in [UCD422.HDMISourceHDMISink]:
|
||||
elif role_type in [UCD422.HDMISourceHDMISink, UCD462.HDMISourceHDMISink]:
|
||||
self.opf_handler._set_roles(role.hdtx, role.hdrx)
|
||||
|
||||
def select_role(self, role_type: Type[RoleType]) -> RoleType:
|
||||
@@ -152,3 +163,28 @@ class TSIDevice:
|
||||
@property
|
||||
def _terminal(self) -> Terminal:
|
||||
return self.__terminal
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
Reset Device NIOS FPGA.
|
||||
"""
|
||||
role = self.__io.get_role_type()
|
||||
|
||||
if role is None:
|
||||
logging.error("[UniTAP] Cannot reset device without selected role")
|
||||
return
|
||||
|
||||
if role not in (UCD500.DPSourceUSBCSink,
|
||||
UCD500.DPSourceDPSink,
|
||||
UCD500.USBCSourceUSBCSink,
|
||||
UCD500.USBCSourceDPSink):
|
||||
logging.error(f"[UniTAP] Reset functionality is not supported for selected role {role}.")
|
||||
return
|
||||
|
||||
self.__io.reset()
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Close Device (only with using TSI function `TSIX_DEV_CloseDevice`)
|
||||
"""
|
||||
self.__io.close()
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import time
|
||||
from typing import Union
|
||||
from ctypes import c_int, c_uint, c_int32
|
||||
from typing import Union, List
|
||||
|
||||
from UniTAP.libs.lib_tsi.tsi_io import DeviceIO
|
||||
from UniTAP.libs.lib_tsi.tsi import *
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
from UniTAP.dev.modules.capturer.statuses import CaptureStatus, AudioCaptureStatus, EventCaptureStatus, \
|
||||
VideoCaptureStatus, BulkCaptureStatus
|
||||
from UniTAP.common import AudioFrameData, VideoFrameDSC, create_from_pps
|
||||
@@ -12,6 +14,8 @@ from UniTAP.utils import function_scheduler
|
||||
from UniTAP.dev.ports.modules.capturer.bulk.private_bulk_types import *
|
||||
from UniTAP.dev.ports.modules.capturer.bulk.bulk_types import *
|
||||
from .types import *
|
||||
from UniTAP.utils import tsi_logging as logging
|
||||
|
||||
|
||||
|
||||
TIMEOUT = 10
|
||||
@@ -84,27 +88,27 @@ class Capturer:
|
||||
|
||||
@property
|
||||
def video_capturer_status(self) -> VideoCaptureStatus:
|
||||
return VideoCaptureStatus(self.__io.get(TSI_VIDCAP_CAPTURE_STATUS_R, c_int)[1])
|
||||
return VideoCaptureStatus(self.__io.get(p_ci.TSI_VIDCAP_CAPTURE_STATUS_R, c_int)[1])
|
||||
|
||||
@property
|
||||
def audio_capturer_status(self) -> AudioCaptureStatus:
|
||||
return AudioCaptureStatus(self.__io.get(TSI_R_AUDCAP_STATUS, c_int)[1])
|
||||
return AudioCaptureStatus(self.__io.get(ci.TSI_R_AUDCAP_STATUS, c_int)[1])
|
||||
|
||||
@property
|
||||
def event_capturer_status(self) -> EventCaptureStatus:
|
||||
return EventCaptureStatus(self.__io.get(TSI_EVCAP_CTRL, c_uint32)[1] & 0xFF)
|
||||
return EventCaptureStatus(self.__io.get(ci.TSI_EVCAP_CTRL, c_uint32)[1] & 0xFF)
|
||||
|
||||
@property
|
||||
def bulk_capturer_status(self) -> BulkCaptureStatus:
|
||||
return BulkCaptureStatus(self.__io.get(TSI_BULK_CAPTURE_STATUS_R, c_uint32)[1] & 0x3)
|
||||
return BulkCaptureStatus(self.__io.get(ci.TSI_BULK_CAPTURE_STATUS_R, c_uint32)[1] & 0x3)
|
||||
|
||||
def start_capture(self, config: CaptureConfig):
|
||||
self.__mutex.acquire()
|
||||
|
||||
self.__config.from_int(self.__current_config().to_int() | config.to_int())
|
||||
self.__io.set(TSI_CAP_CONFIG, self.__config.to_int())
|
||||
self.__io.set(ci.TSI_CAP_CONFIG, self.__config.to_int())
|
||||
|
||||
if self.__io.set(TSI_W_CAP_COMMAND, 1) == 0:
|
||||
if self.__io.set(ci.TSI_W_CAP_COMMAND, 1) == 0:
|
||||
self.__status = CaptureStatus.Running
|
||||
else:
|
||||
self.__status = CaptureStatus.Unknown
|
||||
@@ -115,9 +119,9 @@ class Capturer:
|
||||
self.__mutex.acquire()
|
||||
|
||||
self.__config.from_int(self.__current_config().to_int() & ~config.to_int())
|
||||
self.__io.set(TSI_CAP_CONFIG, self.__config.to_int())
|
||||
self.__io.set(ci.TSI_CAP_CONFIG, self.__config.to_int())
|
||||
|
||||
if self.__io.set(TSI_W_CAP_COMMAND, 2) == 0:
|
||||
if self.__io.set(ci.TSI_W_CAP_COMMAND, 2) == 0:
|
||||
self.__status = CaptureStatus.Stop
|
||||
else:
|
||||
self.__status = CaptureStatus.Unknown
|
||||
@@ -128,22 +132,22 @@ class Capturer:
|
||||
event = EventData()
|
||||
|
||||
if event_count > 0:
|
||||
event_size = self.__io.get(TSI_R_EVCAP_DATA, None, 0)[0]
|
||||
event_size = self.__io.get(ci.TSI_R_EVCAP_DATA, None, 0)[0]
|
||||
if event_size > 0:
|
||||
event.data = bytearray(self.__io.get(TSI_R_EVCAP_DATA, c_ubyte, event_size)[1])
|
||||
event.data = bytearray(self.__io.get(ci.TSI_R_EVCAP_DATA, c_ubyte, event_size)[1])
|
||||
|
||||
return event
|
||||
|
||||
def get_buffer_capacity(self, stream_number: int = None):
|
||||
if stream_number is not None:
|
||||
self.__io.set(TSI_DPRX_STREAM_SELECT, stream_number, c_uint32)
|
||||
self.__io.set(TSI_DPRX_MSA_COMMAND_W, 2, c_uint32)
|
||||
self.__io.set(ci.TSI_DPRX_STREAM_SELECT, stream_number, c_uint32)
|
||||
self.__io.set(ci.TSI_DPRX_MSA_COMMAND_W, 2, c_uint32)
|
||||
|
||||
width = self.__io.get(TSI_R_INPUT_WIDTH , c_uint32)[1]
|
||||
height = self.__io.get(TSI_R_INPUT_HEIGHT , c_uint32)[1]
|
||||
total_memory_bytes = self.__io.get(TSI_MEMORY_SIZE_R, c_uint64)[1]
|
||||
bpc = self.__io.get(TSI_INPUT_COLOR_DEPTH_R , c_uint32)[1]
|
||||
color_format = self.__io.get(TSI_INPUT_COLOR_MODE_R , c_uint32)[1]
|
||||
width = self.__io.get(ci.TSI_R_INPUT_WIDTH, c_uint32)[1]
|
||||
height = self.__io.get(ci.TSI_R_INPUT_HEIGHT, c_uint32)[1]
|
||||
total_memory_bytes = self.__io.get(ci.TSI_MEMORY_SIZE_R, c_uint64)[1]
|
||||
bpc = self.__io.get(ci.TSI_INPUT_COLOR_DEPTH_R, c_uint32)[1]
|
||||
color_format = self.__io.get(ci.TSI_INPUT_COLOR_MODE_R, c_uint32)[1]
|
||||
|
||||
bpp = self._get_bits_per_pixel(bpc, color_format)
|
||||
line_alignment = 1023
|
||||
@@ -186,7 +190,7 @@ class Capturer:
|
||||
return (value + alignment) & ~alignment
|
||||
|
||||
def get_available_events_count(self) -> int:
|
||||
return self.__io.get(TSI_R_EVCAP_COUNT, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_R_EVCAP_COUNT, c_uint32)[1]
|
||||
|
||||
def capture_n_events(self, events_count: int):
|
||||
if events_count <= 0:
|
||||
@@ -215,19 +219,21 @@ class Capturer:
|
||||
|
||||
audio_frame = AudioFrameData()
|
||||
|
||||
audio_frame.channel_count = self.__io.get(TSI_R_AUDCAP_CHANNEL_COUNT, c_int)[1]
|
||||
audio_frame.sample_size = self.__io.get(TSI_R_AUDCAP_SAMPLE_SIZE, c_int)[1] * 8
|
||||
audio_frame.sample_rate = self.__io.get(TSI_R_AUDCAP_SAMPLE_RATE, c_int)[1]
|
||||
audio_frame.timestamp = self.__io.get(TSI_R_AUDCAP_TIMESTAMP, c_uint64)[1]
|
||||
audio_frame.samples = self.__io.get(TSI_R_AUDCAP_SAMPLE_COUNT, c_int)[1]
|
||||
audio_frame.frame_counter = self.__io.get(TSI_R_AUDCAP_FRAME_COUNTER, c_int)[1]
|
||||
audio_frame.sample_format = self.__io.get(TSI_R_AUDCAP_SAMPLE_FORMAT, c_int)[1]
|
||||
audio_frame.channel_count = self.__io.get(ci.TSI_AUDCAP_CHANNEL_COUNT_R, c_int)[1]
|
||||
audio_frame.sample_size = self.__io.get(ci.TSI_AUDCAP_SAMPLE_BITS_SIZE_R, c_int)[1]
|
||||
audio_frame.sample_rate = self.__io.get(ci.TSI_R_AUDCAP_SAMPLE_RATE, c_int)[1]
|
||||
audio_frame.timestamp = self.__io.get(ci.TSI_R_AUDCAP_TIMESTAMP, c_uint64)[1]
|
||||
audio_frame.samples = self.__io.get(ci.TSI_R_AUDCAP_SAMPLE_COUNT, c_int)[1]
|
||||
audio_frame.frame_counter = self.__io.get(ci.TSI_R_AUDCAP_FRAME_COUNTER, c_int)[1]
|
||||
audio_frame.sample_format = self.__io.get(ci.TSI_R_AUDCAP_SAMPLE_FORMAT, c_int)[1]
|
||||
|
||||
min_buff_size = self.__io.get(TSI_R_AUDCAP_MIN_BUFFER_SIZE, c_uint32)[1]
|
||||
audio_frame.data = self.__io.get(TSI_R_AUDCAP_SAMPLE_DATA, c_uint8, min_buff_size)[1]
|
||||
min_buff_size = self.__io.get(ci.TSI_R_AUDCAP_MIN_BUFFER_SIZE, c_uint32)[1]
|
||||
audio_frame.data = self.__io.get(ci.TSI_R_AUDCAP_SAMPLE_DATA, c_uint8, min_buff_size)[1]
|
||||
|
||||
m_sec -= 1000 * len(audio_frame.data) / 2 / audio_frame.channel_count / audio_frame.sample_rate
|
||||
captured_sample_count = len(audio_frame.data) / (audio_frame.sample_size / 8) / audio_frame.channel_count
|
||||
captured_m_sec_count = int(captured_sample_count * 1000 / audio_frame.sample_rate)
|
||||
|
||||
m_sec -= captured_m_sec_count
|
||||
return audio_frame, m_sec
|
||||
|
||||
def capture_audio_by_n_frames(self, frames_count: int, timeout: int = None):
|
||||
@@ -263,29 +269,32 @@ class Capturer:
|
||||
raise ValueError(f"Seconds count must be more than 0.")
|
||||
|
||||
buffer = []
|
||||
time_break = False
|
||||
|
||||
while m_sec > 0 and not time_break:
|
||||
captured = 0
|
||||
last_data_time = time.time()
|
||||
while m_sec > 0:
|
||||
start_time = time.time()
|
||||
while captured < 10 and m_sec > 0:
|
||||
status = self.audio_capturer_status
|
||||
current_time = time.time()
|
||||
if current_time - start_time > TIMEOUT:
|
||||
time_break = True
|
||||
break
|
||||
if status == AudioCaptureStatus.Stop:
|
||||
continue
|
||||
while self.audio_capturer_status != AudioCaptureStatus.Running:
|
||||
if time.time() - start_time > TIMEOUT:
|
||||
logging.error(f"Audio capture device not running for {TIMEOUT} seconds. Aborting.")
|
||||
return buffer
|
||||
logging.debug(f"Audio capture device not running yet: {self.audio_capturer_status}")
|
||||
time.sleep(0.5)
|
||||
|
||||
audio_frame, m_sec = self.__capture_audio(m_sec=m_sec)
|
||||
if len(audio_frame.data) > 0:
|
||||
captured += 1
|
||||
buffer.append(audio_frame)
|
||||
last_data_time = time.time()
|
||||
else:
|
||||
if time.time() - last_data_time > TIMEOUT:
|
||||
logging.error(
|
||||
f"No audio data captured within {TIMEOUT} seconds. "
|
||||
f"Interrupting capture process."
|
||||
)
|
||||
break
|
||||
|
||||
return buffer
|
||||
|
||||
def get_available_video_frame_count(self):
|
||||
return self.__io.get(TSI_VIDCAP_AVAILABLE_FRAME_COUNT, c_int)[1]
|
||||
return self.__io.get(p_ci.TSI_VIDCAP_AVAILABLE_FRAME_COUNT, c_int)[1]
|
||||
|
||||
def __check_available_video(self, timeout) -> bool:
|
||||
def is_video_available(capturer):
|
||||
@@ -322,27 +331,27 @@ class Capturer:
|
||||
f"Cannot start to capture video. Current video capture status {self.video_capturer_status.name}")
|
||||
|
||||
try:
|
||||
result = self.__io.set(TSI_VIDCAP_CAPTURE_NEXT_W, 0)
|
||||
if result == TSI_ERROR_DATA_PROTECTION_ENABLED:
|
||||
result = self.__io.set(ci.TSI_VIDCAP_CAPTURE_NEXT_W, 0)
|
||||
if result == ci.TSI_ERROR_DATA_PROTECTION_ENABLED:
|
||||
raise CaptureError("Video data is HDCP protected. Capturing is not available.")
|
||||
except AssertionError as e:
|
||||
raise CaptureError(f"Error: {e}")
|
||||
|
||||
try:
|
||||
min_buffer_size = self.__io.get(TSI_R_VIDCAP_MIN_BUFFER_SIZE, c_int)[1]
|
||||
min_buffer_size = self.__io.get(ci.TSI_R_VIDCAP_MIN_BUFFER_SIZE, c_int)[1]
|
||||
if min_buffer_size <= 0:
|
||||
raise ValueError("Minimum buffer size must be more than 0")
|
||||
except AssertionError as e:
|
||||
raise CaptureError(f"Error: {e}")
|
||||
|
||||
try:
|
||||
frame_data = bytearray(self.__io.get(TSI_R_VIDCAP_FRAME_DATA, c_uint8, min_buffer_size)[1])
|
||||
frame_data = bytearray(self.__io.get(ci.TSI_R_VIDCAP_FRAME_DATA, c_uint8, min_buffer_size)[1])
|
||||
if len(frame_data) <= 0:
|
||||
raise ValueError("Minimum length of captured data must be more than 0")
|
||||
except AssertionError as e:
|
||||
raise CaptureError(f"Error: {e}")
|
||||
|
||||
frame_attributes = self.__io.get(TSI_VIDCAP_FRAME_HEADER_R, VideoFrameHeader)[1]
|
||||
frame_attributes = self.__io.get(ci.TSI_VIDCAP_FRAME_HEADER_R, VideoFrameHeader)[1]
|
||||
|
||||
if frame_attributes.is_dsc() and len(frame_data) > 128:
|
||||
vf = VideoFrameDSC()
|
||||
@@ -397,12 +406,12 @@ class Capturer:
|
||||
|
||||
def set_video_stream_number(self, number: int):
|
||||
self.__mutex.acquire()
|
||||
self.__io.set(TSI_DPRX_STREAM_SELECT, number, c_uint32)
|
||||
self.__io.set(ci.TSI_DPRX_STREAM_SELECT, number, c_uint32)
|
||||
self.__mutex.release()
|
||||
|
||||
def __current_config(self) -> CaptureConfig:
|
||||
config = CaptureConfig()
|
||||
config.from_int(self.__io.get(TSI_CAP_CONFIG, c_uint)[1])
|
||||
config.from_int(self.__io.get(ci.TSI_CAP_CONFIG, c_uint)[1])
|
||||
return config
|
||||
|
||||
# Capture CRC
|
||||
@@ -410,7 +419,7 @@ class Capturer:
|
||||
if crc_frame_count <= 0:
|
||||
raise ValueError(f"Incorrect crc frame count: {crc_frame_count}")
|
||||
|
||||
crc_values = self.__io.get(TSI_VIDCAP_SIGNAL_CRC_R, CrcStruct, crc_frame_count)[1]
|
||||
crc_values = self.__io.get(ci.TSI_VIDCAP_SIGNAL_CRC_R, CrcStruct, crc_frame_count)[1]
|
||||
crc_list = []
|
||||
if crc_frame_count == 1:
|
||||
crc_list = [(crc_values.r, crc_values.g, crc_values.b)]
|
||||
@@ -420,15 +429,15 @@ class Capturer:
|
||||
|
||||
# Bulk Capturer
|
||||
def read_bulk_capture_caps(self) -> CaptureCaps:
|
||||
return self.__io.get(TSI_BULK_CAPTURE_CAPS_R, CaptureCaps)[1]
|
||||
return self.__io.get(ci.TSI_BULK_CAPTURE_CAPS_R, CaptureCaps)[1]
|
||||
|
||||
def read_bulk_trigger_caps(self) -> int:
|
||||
return self.__io.get(TSI_BULK_TRIGGER_CAPS_R, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_BULK_TRIGGER_CAPS_R, c_uint32)[1]
|
||||
|
||||
def write_bulk_trigger_settings(self, trigger_mask: int, trigger_config: list, trigger_config_ext: list):
|
||||
self.__io.set(TSI_BULK_TRIGGER_MASK_W, trigger_mask, c_uint32)
|
||||
self.__io.set(TSI_BULK_TRIGGER_CONFIGURATION_W, trigger_config, c_uint32, data_count=len(trigger_config))
|
||||
self.__io.set(TSI_BULK_TRIGGER_CONFIGURATION_EXT_W, trigger_config_ext, c_uint32,
|
||||
self.__io.set(ci.TSI_BULK_TRIGGER_MASK_W, trigger_mask, c_uint32)
|
||||
self.__io.set(ci.TSI_BULK_TRIGGER_CONFIGURATION_W, trigger_config, c_uint32, data_count=len(trigger_config))
|
||||
self.__io.set(ci.TSI_BULK_TRIGGER_CONFIGURATION_EXT_W, trigger_config_ext, c_uint32,
|
||||
data_count=len(trigger_config_ext))
|
||||
|
||||
def write_bulk_size(self, size: int):
|
||||
@@ -436,56 +445,56 @@ class Capturer:
|
||||
data.BLOCK = 0
|
||||
data.OFFSET = 0
|
||||
data.SIZE = size
|
||||
self.__io.set(TSI_BULK_CAPTURE_BLOCK, data, SBlock)
|
||||
self.__io.set(ci.TSI_BULK_CAPTURE_BLOCK, data, SBlock)
|
||||
|
||||
def write_encoding_type(self, value: EncodingTypeEnum):
|
||||
self.__io.set(TSI_BULK_CAPTURE_TYPE, value.value, c_uint32)
|
||||
self.__io.set(ci.TSI_BULK_CAPTURE_TYPE, value.value, c_uint32)
|
||||
|
||||
def read_encoding_type(self) -> EncodingTypeEnum:
|
||||
return EncodingTypeEnum(self.__io.get(TSI_BULK_CAPTURE_TYPE, c_uint32)[1])
|
||||
return EncodingTypeEnum(self.__io.get(ci.TSI_BULK_CAPTURE_TYPE, c_uint32)[1])
|
||||
|
||||
def write_lane_count(self, value: LaneCountEnum):
|
||||
self.__io.set(TSI_BULK_CAPTURE_LANE_COUNT, value.value, c_uint32)
|
||||
self.__io.set(ci.TSI_BULK_CAPTURE_LANE_COUNT, value.value, c_uint32)
|
||||
|
||||
def read_lane_count(self) -> LaneCountEnum:
|
||||
return LaneCountEnum(self.__io.get(TSI_BULK_CAPTURE_LANE_COUNT, c_uint32)[1])
|
||||
return LaneCountEnum(self.__io.get(ci.TSI_BULK_CAPTURE_LANE_COUNT, c_uint32)[1])
|
||||
|
||||
def write_bulk_gpio(self, gpio: bool):
|
||||
self.__io.set(TSI_BULK_CAPTURE_GPIO_W, TSI_BULK_CAPTURE_GPIO_5BIT if gpio else TSI_BULK_CAPTURE_GPIO_OFF,
|
||||
self.__io.set(ci.TSI_BULK_CAPTURE_GPIO_W, ci.TSI_BULK_CAPTURE_GPIO_5BIT if gpio else ci.TSI_BULK_CAPTURE_GPIO_OFF,
|
||||
c_uint32)
|
||||
|
||||
def write_bulk_trigger_position(self, position: int):
|
||||
self.__io.set(TSI_BULK_TRIGGER_POS, position)
|
||||
self.__io.set(ci.TSI_BULK_TRIGGER_POS, position)
|
||||
|
||||
def start_bulk_capture(self):
|
||||
|
||||
self.__mutex.acquire()
|
||||
|
||||
self.__io.set(TSI_EVCAP_CTRL, 1)
|
||||
self.__io.set(TSI_BULK_CAPTURE_CONTROL_W, TSI_BULK_CAPTURE_START)
|
||||
self.__io.set(ci.TSI_EVCAP_CTRL, 1)
|
||||
self.__io.set(ci.TSI_BULK_CAPTURE_CONTROL_W, ci.TSI_BULK_CAPTURE_START)
|
||||
|
||||
self.__mutex.release()
|
||||
|
||||
def stop_bulk_capture(self):
|
||||
self.__mutex.acquire()
|
||||
|
||||
self.__io.set(TSI_EVCAP_CTRL, 0)
|
||||
self.__io.set(TSI_BULK_CAPTURE_CONTROL_W, TSI_BULK_CAPTURE_STOP)
|
||||
self.__io.set(ci.TSI_EVCAP_CTRL, 0)
|
||||
self.__io.set(ci.TSI_BULK_CAPTURE_CONTROL_W, ci.TSI_BULK_CAPTURE_STOP)
|
||||
|
||||
self.__mutex.release()
|
||||
|
||||
def start_event_capture(self):
|
||||
self.__mutex.acquire()
|
||||
|
||||
self.__io.set(TSI_EVCAP_CTRL, 1)
|
||||
self.__io.set(TSI_EVCAP_EVENT_SRC_EN, UCD_ALL_EVENTS)
|
||||
self.__io.set(ci.TSI_EVCAP_CTRL, 1)
|
||||
self.__io.set(ci.TSI_EVCAP_EVENT_SRC_EN, ci.UCD_ALL_EVENTS)
|
||||
|
||||
self.__mutex.release()
|
||||
|
||||
def stop_event_capture(self):
|
||||
self.__mutex.acquire()
|
||||
|
||||
self.__io.set(TSI_EVCAP_CTRL, 0)
|
||||
self.__io.set(ci.TSI_EVCAP_CTRL, 0)
|
||||
|
||||
self.__mutex.release()
|
||||
|
||||
@@ -494,9 +503,9 @@ class Capturer:
|
||||
value = -1
|
||||
time_waited = time.time()
|
||||
|
||||
while value != TSI_BULK_STATUS_IDLE and time.time() - time_waited < max_time_waiting:
|
||||
self.__io.set(TSI_BULK_CAPTURE_CLEAR_W, 0)
|
||||
value = self.__io.get(TSI_BULK_CAPTURE_STATUS_R)[1]
|
||||
while value != ci.TSI_BULK_STATUS_IDLE and time.time() - time_waited < max_time_waiting:
|
||||
self.__io.set(ci.TSI_BULK_CAPTURE_CLEAR_W, 0)
|
||||
value = self.__io.get(ci.TSI_BULK_CAPTURE_STATUS_R)[1]
|
||||
|
||||
def bulk_capture(self, all_size: int, trigger_enabled: Optional[TriggerVarType]) -> list:
|
||||
buffer = []
|
||||
@@ -504,16 +513,16 @@ class Capturer:
|
||||
prev_status = 0
|
||||
last_bulk_capture_time = time.time()
|
||||
for i in range(iterations):
|
||||
event_count = self.__io.get(TSI_EVCAP_COUNT_R, c_uint32)[1]
|
||||
event_count = self.__io.get(ci.TSI_EVCAP_COUNT_R, c_uint32)[1]
|
||||
if event_count > 0:
|
||||
event_number = 0
|
||||
prev_timestamp = 0
|
||||
events_captured = 0
|
||||
while event_count > 0 and events_captured < 500:
|
||||
event_size = self.__io.get(TSI_R_EVCAP_DATA, None, 0)[0]
|
||||
event_size = self.__io.get(ci.TSI_R_EVCAP_DATA, None, 0)[0]
|
||||
if event_size > 0:
|
||||
cap_data = CapturedData()
|
||||
cap_data.data = bytearray(self.__io.get(TSI_R_EVCAP_DATA, c_ubyte, event_size)[1])
|
||||
cap_data.data = bytearray(self.__io.get(ci.TSI_R_EVCAP_DATA, c_ubyte, event_size)[1])
|
||||
cap_data.data = cap_data.data[3:]
|
||||
cap_data.type = CapturedDataType.Event
|
||||
cap_data.timestamp = int.from_bytes(bytes=cap_data.data[:8], byteorder='big')
|
||||
@@ -526,8 +535,8 @@ class Capturer:
|
||||
events_captured += 1
|
||||
event_count -= 1
|
||||
|
||||
bulk_status = self.__io.get(TSI_BULK_CAPTURE_STATUS_R, c_int32)[1]
|
||||
if bulk_status == TSI_BULK_STATUS_IDLE and prev_status == TSI_BULK_STATUS_TRANSFERRING:
|
||||
bulk_status = self.__io.get(ci.TSI_BULK_CAPTURE_STATUS_R, c_int32)[1]
|
||||
if bulk_status == ci.TSI_BULK_STATUS_IDLE and prev_status == ci.TSI_BULK_STATUS_TRANSFERRING:
|
||||
return buffer
|
||||
prev_status = bulk_status
|
||||
|
||||
@@ -538,12 +547,12 @@ class Capturer:
|
||||
if not self.__check_available_bulk_data(TIMEOUT):
|
||||
return buffer
|
||||
|
||||
self.__io.set(TSI_EVCAP_CTRL, 0)
|
||||
self.__io.set(ci.TSI_EVCAP_CTRL, 0)
|
||||
cap_data = CapturedData()
|
||||
cap_data.type = CapturedDataType.Bulk
|
||||
result, data, _ = self.__io.get(TSI_BULK_CAPTURE_DATA_R, c_ubyte, 1024 * 1024)
|
||||
result, data, _ = self.__io.get(ci.TSI_BULK_CAPTURE_DATA_R, c_ubyte, 1024 * 1024)
|
||||
cap_data.data = bytearray(data)
|
||||
if result >= TSI_SUCCESS and len(cap_data.data) > 0:
|
||||
if result >= ci.TSI_SUCCESS and len(cap_data.data) > 0:
|
||||
buffer.append(cap_data)
|
||||
last_bulk_capture_time = time.time()
|
||||
|
||||
|
||||
@@ -1996,40 +1996,6 @@
|
||||
"minValue": 0,
|
||||
"name": "Maximum refresh rate for supported Adaptive-Sync video timings, in Hz.",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x10e000d",
|
||||
"defaultValue": "0",
|
||||
"description": "Reserved for extension.",
|
||||
"bitList":
|
||||
[
|
||||
{"description": "0x10e000d", "defaultValue": "0"},
|
||||
{"description": "0x10e000f", "defaultValue": "0"},
|
||||
{"description": "0x10e001c", "defaultValue": "0"},
|
||||
{"description": "0x10e001d", "defaultValue": "0"},
|
||||
{"description": "0x10e001e", "defaultValue": "0"},
|
||||
{"description": "0x10e001f", "defaultValue": "0"},
|
||||
{"description": "0x10e002f", "defaultValue": "0"},
|
||||
{"description": "0x10e0030", "defaultValue": "0"},
|
||||
{"description": "0x10e0031", "defaultValue": "0"},
|
||||
{"description": "0x10e0032", "defaultValue": "0"},
|
||||
{"description": "0x10e0033", "defaultValue": "0"},
|
||||
{"description": "0x10e0034", "defaultValue": "0"},
|
||||
{"description": "0x10e0035", "defaultValue": "0"},
|
||||
{"description": "0x10e0036", "defaultValue": "0"},
|
||||
{"description": "0x10e0037", "defaultValue": "0"},
|
||||
{"description": "0x10e00b7", "defaultValue": "0"},
|
||||
{"description": "0x10e00b8", "defaultValue": "0"},
|
||||
{"description": "0x10e00b9", "defaultValue": "0"},
|
||||
{"description": "0x10e00ba", "defaultValue": "0"},
|
||||
{"description": "0x10e00bb", "defaultValue": "0"},
|
||||
{"description": "0x10e00bc", "defaultValue": "0"},
|
||||
{"description": "0x10e00bd", "defaultValue": "0"},
|
||||
{"description": "0x10e00be", "defaultValue": "0"}
|
||||
],
|
||||
"flag": 3,
|
||||
"id": "RESERVED",
|
||||
"type": 4
|
||||
}
|
||||
],
|
||||
"id": "0x03",
|
||||
|
||||
@@ -67,20 +67,6 @@
|
||||
"minValue": 0,
|
||||
"name": "Delay between test cycles, in milliseconds",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x10703",
|
||||
"defaultValue": "0",
|
||||
"description": "Reserved for DUT Capabilities flags and DUT Test automation capabilities flags.",
|
||||
"bitList":
|
||||
[
|
||||
{"description": "0x10703", "defaultValue": "0"},
|
||||
{"description": "0x10704", "defaultValue": "0"}
|
||||
],
|
||||
"flag": 3,
|
||||
"id": "RESERVED",
|
||||
"name": "Reserved",
|
||||
"type": 4
|
||||
}
|
||||
],
|
||||
"id": "0x04",
|
||||
|
||||
@@ -65,7 +65,11 @@
|
||||
{"mask": "0x01000000", "description": "2x1 tiled display and DisplayID Tiled Display Topology data block supported"},
|
||||
{"mask": "0x02000000", "description": "Field sequential stereo and DisplayID Tiled Stereo Display Interface data block supported"},
|
||||
{"mask": "0x04000000", "description": "Stacked frame stereo and DisplayID Tiled Stereo Display Interface data block supported"},
|
||||
{"mask": "0x08000000", "description": "Dynamic Refresh Rate with VBlank stretch with MSA_TIMING_PAR_IGNORED supported"}
|
||||
{"mask": "0x08000000", "description": "Dynamic Refresh Rate with VBlank stretch with MSA_TIMING_PAR_IGNORED supported"},
|
||||
{"mask": "0x10000000", "description": "MST transmission supported"},
|
||||
{"mask": "0x20000000", "description": "MST UP_REQUEST supported"},
|
||||
{"mask": "0x40000000", "description": "MST RSN_REQUEST supported"},
|
||||
{"mask": "0x80000000", "description": "MST POWER_UP/DOWN_PHY supported"}
|
||||
],
|
||||
"flag": 3,
|
||||
"id": "TSI_DP20_SRCCTS_DUT_CAPS",
|
||||
@@ -211,6 +215,17 @@
|
||||
"name": "Debug mode configuration.",
|
||||
"type": 12
|
||||
},
|
||||
{
|
||||
"configId": "0x119000f",
|
||||
"defaultValue": "1028",
|
||||
"description": "Includes: Maximum stream count supported and Maximum daisy chain sink count supported.",
|
||||
"flag": 3,
|
||||
"id": "TSI_DP20_SRCCTS_DUT_MST_CAPS",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "MST source DUT capabilities.",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x1190010",
|
||||
"defaultValue": "32000",
|
||||
@@ -2598,39 +2613,6 @@
|
||||
"name": "Video mode supported by Source DUT (DP2.1 video & DSC tests)",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x119000f",
|
||||
"defaultValue": "0",
|
||||
"description": "Reserved for extension.",
|
||||
"bitList":
|
||||
[
|
||||
{"description": "0x119000f", "defaultValue": "0"},
|
||||
{"description": "0x119001c", "defaultValue": "0"},
|
||||
{"description": "0x119001d", "defaultValue": "0"},
|
||||
{"description": "0x119001e", "defaultValue": "0"},
|
||||
{"description": "0x119001f", "defaultValue": "0"},
|
||||
{"description": "0x119002f", "defaultValue": "0"},
|
||||
{"description": "0x1190030", "defaultValue": "0"},
|
||||
{"description": "0x1190031", "defaultValue": "0"},
|
||||
{"description": "0x1190032", "defaultValue": "0"},
|
||||
{"description": "0x1190033", "defaultValue": "0"},
|
||||
{"description": "0x1190034", "defaultValue": "0"},
|
||||
{"description": "0x1190035", "defaultValue": "0"},
|
||||
{"description": "0x1190036", "defaultValue": "0"},
|
||||
{"description": "0x1190037", "defaultValue": "0"},
|
||||
{"description": "0x11900b7", "defaultValue": "0"},
|
||||
{"description": "0x11900b8", "defaultValue": "0"},
|
||||
{"description": "0x11900b9", "defaultValue": "0"},
|
||||
{"description": "0x11900ba", "defaultValue": "0"},
|
||||
{"description": "0x11900bb", "defaultValue": "0"},
|
||||
{"description": "0x11900bc", "defaultValue": "0"},
|
||||
{"description": "0x11900bd", "defaultValue": "0"},
|
||||
{"description": "0x11900be", "defaultValue": "0"}
|
||||
],
|
||||
"flag": 3,
|
||||
"id": "RESERVED",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x11900f4",
|
||||
"defaultValue": "1920",
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
],
|
||||
"flag": 1,
|
||||
"id": "TSI_HDMI_SNKCTS_DSC_VIDEO_FORMAT",
|
||||
"name": "DSC Video formats 1.",
|
||||
"name": "DSC Video formats 1",
|
||||
"type": 12
|
||||
},
|
||||
{
|
||||
@@ -174,7 +174,7 @@
|
||||
],
|
||||
"flag": 1,
|
||||
"id": "TSI_HDMI_SNKCTS_DSC_VIDEO_FORMAT_2",
|
||||
"name": "DSC Video formats 2.",
|
||||
"name": "DSC Video formats 2",
|
||||
"type": 12
|
||||
},
|
||||
{
|
||||
@@ -197,7 +197,7 @@
|
||||
"id": "TSI_HDMI_SNKCTS_DSC_TOTAL_CHUNK_BYTES",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "DSC Max Slices",
|
||||
"name": "DSC TotalChunkKBytes",
|
||||
"type": 4
|
||||
}
|
||||
],
|
||||
|
||||
@@ -1,66 +1,8 @@
|
||||
{
|
||||
"descriptions": [
|
||||
{
|
||||
"configId": "0x2100",
|
||||
"defaultValue": "0",
|
||||
"description": "Does the Sink support Fast Vactive (FVA), also known as Quick Frame Transport (QFT)?",
|
||||
"flag": 3,
|
||||
"id": "TSI_HDMI_GAMING_FVA",
|
||||
"maxValue": 1,
|
||||
"minValue": 0,
|
||||
"name": "Sink_Supports_FVA",
|
||||
"type": 3,
|
||||
"enumerationVariants": "0 # NO\n1 # YES"
|
||||
},
|
||||
{
|
||||
"configId": "0x2101",
|
||||
"defaultValue": "1",
|
||||
"description": "Does the Sink support Variable Refresh Rate (VRR)",
|
||||
"flag": 3,
|
||||
"id": "TSI_HDMI_GAMING_VRR",
|
||||
"maxValue": 1,
|
||||
"minValue": 0,
|
||||
"name": "Sink_Supports_VRR",
|
||||
"type": 3,
|
||||
"enumerationVariants": "0 # NO\n1 # YES"
|
||||
},
|
||||
{
|
||||
"configId": "0x2102",
|
||||
"defaultValue": "0",
|
||||
"description": "Does the Sink support Negative Mvrr values?",
|
||||
"flag": 3,
|
||||
"id": "TSI_HDMI_GAMING_NMVRR",
|
||||
"maxValue": 1,
|
||||
"minValue": 0,
|
||||
"name": "Sink_Supports_Negative_MVRR",
|
||||
"type": 3,
|
||||
"enumerationVariants": "0 # NO\n1 # YES"
|
||||
},
|
||||
{
|
||||
"configId": "0x2103",
|
||||
"defaultValue": "40",
|
||||
"description": "What is the Sink’s supported VRR Range? Minimum value.\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_HDMI_GAMING_RANGE_MIN",
|
||||
"maxValue": 480,
|
||||
"minValue": 20,
|
||||
"name": "Sink_Supported_VRR_Range VRRMIN",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x2104",
|
||||
"defaultValue": "0",
|
||||
"description": "What is the Sink’s supported VRR Range? Maximum value or BRR\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_HDMI_GAMING_RANGE_MAX",
|
||||
"maxValue": 480,
|
||||
"minValue": 20,
|
||||
"name": "Sink_Supported_VRR_Range VRRMAX or 0 for BRR",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x2105",
|
||||
"defaultValue": "0",
|
||||
"defaultValue": "1",
|
||||
"description": "Does the Sink implement Auto Low-Latency Mode (ALLM)?",
|
||||
"flag": 3,
|
||||
"id": "TSI_HDMI_GAMING_ALLM",
|
||||
@@ -72,32 +14,28 @@
|
||||
},
|
||||
{
|
||||
"configId": "0x2106",
|
||||
"defaultValue": "0",
|
||||
"defaultValue": "Cinema",
|
||||
"description": "Which display processing mode is the preferred mode with normal latency?",
|
||||
"flag": 3,
|
||||
"id": "TSI_HDMI_GAMING_NLM",
|
||||
"maxValue": 2,
|
||||
"minValue": 0,
|
||||
"name": "Sink_Preferred_NLM",
|
||||
"type": 4,
|
||||
"enumerationVariants": "0 # Cinema\n1 # Vivid\n2 # Normal"
|
||||
"type": 2,
|
||||
"maxLength": 256
|
||||
},
|
||||
{
|
||||
"configId": "0x2107",
|
||||
"defaultValue": "0",
|
||||
"defaultValue": "Gaming",
|
||||
"description": "Which display processing mode is the preferred mode to minimize latency?",
|
||||
"flag": 3,
|
||||
"id": "TSI_HDMI_GAMING_LLM",
|
||||
"maxValue": 1,
|
||||
"minValue": 0,
|
||||
"name": "Sink_Preferred_LLM",
|
||||
"type": 4,
|
||||
"enumerationVariants": "0 # Game\n1 # PC"
|
||||
"type": 2,
|
||||
"maxLength": 256
|
||||
},
|
||||
{
|
||||
"configId": "0x2108",
|
||||
"defaultValue": "1",
|
||||
"description": "Does the Sink DUT support QMS-VRR?",
|
||||
"description": "Does the Sink supports QMS-VRR?",
|
||||
"flag": 3,
|
||||
"id": "TSI_HDMI_GAMING_QMS",
|
||||
"maxValue": 1,
|
||||
@@ -107,28 +45,58 @@
|
||||
"enumerationVariants": "0 # NO\n1 # YES"
|
||||
},
|
||||
{
|
||||
"configId": "0x2109",
|
||||
"defaultValue": "97",
|
||||
"description": "What is the highest resolution (i.e., width x height) and base refresh rate (BRR) for which all TFRs up to Sink_QMS_Max_TFR_TMDS are supported by the Sink using TMDS?",
|
||||
"configId": "0x2101",
|
||||
"defaultValue": "1",
|
||||
"description": "Does the Sink supports VRR?",
|
||||
"flag": 3,
|
||||
"id": "TSI_HDMI_GAMING_VIDEO_TMDS",
|
||||
"maxValue": 255,
|
||||
"minValue": 16,
|
||||
"name": "Sink_QMS_Video_Format_TMDS",
|
||||
"type": 4,
|
||||
"enumerationVariants": "78 # VIC=78; 1920x1080@120\n97 # VIC=97; 3840x2160@60"
|
||||
"id": "TSI_HDMI_GAMING_VRR",
|
||||
"maxValue": 1,
|
||||
"minValue": 0,
|
||||
"name": "Sink_Supports_VRR",
|
||||
"type": 3,
|
||||
"enumerationVariants": "0 # NO\n1 # YES"
|
||||
},
|
||||
{
|
||||
"configId": "0x2103",
|
||||
"defaultValue": "0",
|
||||
"description": "What is the Sink's supported VRR Range?",
|
||||
"bitList": [
|
||||
{
|
||||
"mask": "0xFFFF",
|
||||
"description": "VRR min"
|
||||
},
|
||||
{
|
||||
"mask": "0xFFFF0000",
|
||||
"description": "VRR max (0 for BRR)"
|
||||
}
|
||||
],
|
||||
"flag": 12,
|
||||
"id": "TSI_HDMI_GAMING_VRR_RANGE",
|
||||
"name": "Sink_Supported_VRR_Range",
|
||||
"type": 12
|
||||
},
|
||||
{
|
||||
"configId": "0x210A",
|
||||
"defaultValue": "118",
|
||||
"description": "What is the highest resolution (i.e., width x height) and base refresh rate (BRR) for which all TFRs up to Sink_QMS_Max_TFR_FRL are supported by the Sink using FRL?",
|
||||
"flag": 3,
|
||||
"defaultValue": "0x0003c0043800780",
|
||||
"description": "What is the highest resolution (i.e., width x height) and base refresh rate (BRR) for which all TFRs up to Sink_QMS_Max_TFR_FRL are supported by the Sink using TMDS?",
|
||||
"bitList": [
|
||||
{
|
||||
"mask": "0xFFFFF",
|
||||
"description": "Width"
|
||||
},
|
||||
{
|
||||
"mask": "0xFFFFF00000",
|
||||
"description": "Height"
|
||||
},
|
||||
{
|
||||
"mask": "0xFFFFF0000000000",
|
||||
"description": "BRR"
|
||||
}
|
||||
],
|
||||
"flag": 12,
|
||||
"id": "TSI_HDMI_GAMING_VIDEO_FRL",
|
||||
"maxValue": 255,
|
||||
"minValue": 16,
|
||||
"name": "Sink_QMS_Video_Format_FRL",
|
||||
"type": 4,
|
||||
"enumerationVariants": "0 # N/A\n78 # VIC=78; 1920x1080@120\n97 # VIC=97; 3840x2160@60\n118 # VIC=118; 3840x2160@120"
|
||||
"type": 13
|
||||
},
|
||||
{
|
||||
"configId": "0x210B",
|
||||
@@ -140,11 +108,11 @@
|
||||
"minValue": 0,
|
||||
"name": "Sink_QMS_Min_TFR",
|
||||
"type": 4,
|
||||
"enumerationVariants": "0 # N/A\n1 # TFR=1; 24/1.001\n2 # TFR=2; 24\n3 # TFR=3; 25\n4 # TFR=4; 30/1.001\n5 # TFR=5; 30\n6 # TFR=6; 48/1.001\n7 # TFR=7; 48\n8 # TFR=8; 50\n9 # TFR=9; 60/1.001\n10 # TFR=10; 60\n11 # TFR=11; 100\n12 # TFR=12; 120/1.001\n13 # TFR=13; 120"
|
||||
"enumerationVariants": "0 # N/A\n1 # 1 - 24/1.001\n2 # 2 - 24\n3 # 3 - 25\n4 # 4 - 30/1.001\n5 # 5 - 30\n6 # 6 - 48/1.001\n7 # 7 - 48\n8 # 8 - 50\n9 # 9 - 60/1.001\n10 # 10 - 60\n11 # 11 - 100\n12 # 12 - 120/1.001\n13 # 13 - 120"
|
||||
},
|
||||
{
|
||||
"configId": "0x210C",
|
||||
"defaultValue": "10",
|
||||
"defaultValue": "6",
|
||||
"description": "If the Sink DUT supports QMS-VRR, what is the maximum Next_TFR value supported using TMDS? (Refer to the Next_TFR field definition in HDMI 2.1a Table 10-37.)",
|
||||
"flag": 3,
|
||||
"id": "TSI_HDMI_GAMING_MAX_TFR_TMDS",
|
||||
@@ -152,11 +120,11 @@
|
||||
"minValue": 0,
|
||||
"name": "Sink_QMS_Max_TFR_TMDS",
|
||||
"type": 4,
|
||||
"enumerationVariants": "0 # N/A\n1 # TFR=1; 24/1.001\n2 # TFR=2; 24\n3 # TFR=3; 25\n4 # TFR=4; 30/1.001\n5 # TFR=5; 30\n6 # TFR=6; 48/1.001\n7 # TFR=7; 48\n8 # TFR=8; 50\n9 # TFR=9; 60/1.001\n10 # TFR=10; 60\n11 # TFR=11; 100\n12 # TFR=12; 120/1.001\n13 # TFR=13; 120"
|
||||
"enumerationVariants": "0 # N/A\n1 # 1 - 24/1.001\n2 # 2 - 24\n3 # 3 - 25\n4 # 4 - 30/1.001\n5 # 5 - 30\n6 # 6 - 48/1.001\n7 # 7 - 48\n8 # 8 - 50\n9 # 9 - 60/1.001\n10 # 10 - 60\n11 # 11 - 100\n12 # 12 - 120/1.001\n13 # 13 - 120"
|
||||
},
|
||||
{
|
||||
"configId": "0x210D",
|
||||
"defaultValue": "13",
|
||||
"defaultValue": "8",
|
||||
"description": "If the Sink DUT supports QMS-VRR, what is the maximum Next_TFR value supported using FRL? (Refer to the Next_TFR field definition in HDMI 2.1a Table 10-37.)",
|
||||
"flag": 3,
|
||||
"id": "TSI_HDMI_GAMING_MAX_TFR_FRL",
|
||||
@@ -164,9 +132,44 @@
|
||||
"minValue": 0,
|
||||
"name": "Sink_QMS_Max_TFR_FRL",
|
||||
"type": 4,
|
||||
"enumerationVariants": "0 # N/A\n1 # TFR=1; 24/1.001\n2 # TFR=2; 24\n3 # TFR=3; 25\n4 # TFR=4; 30/1.001\n5 # TFR=5; 30\n6 # TFR=6; 48/1.001\n7 # TFR=7; 48\n8 # TFR=8; 50\n9 # TFR=9; 60/1.001\n10 # TFR=10; 60\n11 # TFR=11; 100\n12 # TFR=12; 120/1.001\n13 # TFR=13; 120"
|
||||
"enumerationVariants": "0 # N/A\n1 # 1 - 24/1.001\n2 # 2 - 24\n3 # 3 - 25\n4 # 4 - 30/1.001\n5 # 5 - 30\n6 # 6 - 48/1.001\n7 # 7 - 48\n8 # 8 - 50\n9 # 9 - 60/1.001\n10 # 10 - 60\n11 # 11 - 100\n12 # 12 - 120/1.001\n13 # 13 - 120"
|
||||
},
|
||||
{
|
||||
"configId": "0x210E",
|
||||
"defaultValue": "1",
|
||||
"description": "What is the maximum FRL Rate that the product supports? (Set to 0 if the product does not support FRL reception.)",
|
||||
"flag": 3,
|
||||
"id": "TSI_HDMI_GAMING_MAX_FRL",
|
||||
"maxValue": 6,
|
||||
"minValue": 0,
|
||||
"name": "Sink_Max_FRL_Rate",
|
||||
"type": 4,
|
||||
"enumerationVariants": "0 # N/A\n1 # 1\n2 # 2\n3 # 3\n4 # 4\n5 # 5\n6 # 6"
|
||||
},
|
||||
{
|
||||
"configId": "0x210F",
|
||||
"defaultValue": "0x0003c0043800780",
|
||||
"description": "What is the highest resolution (i.e., width x height) and base refresh rate (BRR) for which all TFRs up to Sink_QMS_Max_TFR_TMDS are supported by the Sink using TMDS?",
|
||||
"bitList": [
|
||||
{
|
||||
"mask": "0xFFFFF",
|
||||
"description": "Width"
|
||||
},
|
||||
{
|
||||
"mask": "0xFFFFF00000",
|
||||
"description": "Height"
|
||||
},
|
||||
{
|
||||
"mask": "0xFFFFF0000000000",
|
||||
"description": "BRR"
|
||||
}
|
||||
],
|
||||
"flag": 12,
|
||||
"id": "TSI_HDMI_GAMING_VIDEO_TMDS",
|
||||
"name": "Sink_QMS_Video_Format_TMDS",
|
||||
"type": 13
|
||||
}
|
||||
],
|
||||
"id": "0x23",
|
||||
"name": "HDMI CTS MOI (VRR-QMS)"
|
||||
"name": "HDMI CTS MOI Gaming Features"
|
||||
}
|
||||
|
||||
197
UniTAP/dev/modules/dut_tests/cfg/[0x2D]src_dut_timings.json
Normal file
197
UniTAP/dev/modules/dut_tests/cfg/[0x2D]src_dut_timings.json
Normal file
@@ -0,0 +1,197 @@
|
||||
{
|
||||
"descriptions": [
|
||||
{
|
||||
"configId": "0x01260000",
|
||||
"defaultValue": "10000",
|
||||
"description": "Defines timeout for all Timings video tests, in milliseconds. Default setting is 10000ms.\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_TIMEOUT",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Test timeout, in milliseconds",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x01260001",
|
||||
"defaultValue": "200",
|
||||
"description": "Total number of frames to be tested. After timings check for total number of frames test will be completed. If total number is equal to 0, then test will be executing up to test timeout. Default setting is 200.\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_FRAMES_TO_TEST",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Test duration, in frames",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x01260002",
|
||||
"defaultValue": "2",
|
||||
"description": "Number of bad frames allowed in test. Default setting is 2\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_LIM_FRAME_MISMATCHES",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Allowed mismatches, in frames",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x01260003",
|
||||
"defaultValue": "24",
|
||||
"description": "Defines the color depth as bits per pixel. If the input video color depth does not match this setting, the test will fail. Default setting is 24.\n",
|
||||
"enumerationVariants": "12\n15\n16\n18\n20\n21\n24\n30\n32\n36\n48",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_REF_COLORDEPTH",
|
||||
"maxValue": 2147480000,
|
||||
"minValue": 0,
|
||||
"name": "Expected color depth, as bits per pixel",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x01260004",
|
||||
"defaultValue": "0",
|
||||
"description": "Defines the required frame rate for timings test, in millihertz. Setting of zero (0) disables the frame-rate requirement. Default setting is 0.\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_REQUIRED_FRAME_RATE",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Expected frame rate, in millihertz (mHz)",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x01260005",
|
||||
"defaultValue": "0",
|
||||
"description": "Defines the maximum allowed deviation of input frame-rate from the required frame rate (TSI_TIMINGS_REQUIRED_FRAME_RATE), in millihertz. When this setting is non-zero, it defines the range of allowed frame rate as requirements ± tolerance. If the frame-rate requirement is set to zero, this setting has no effect. Default setting is 0 mHz.\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_FRAME_RATE_TOLERANCE",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Frame rate tolerance, in millihertz (mHz)",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x01260006",
|
||||
"defaultValue": "2200",
|
||||
"description": "Defined the expected video width, in pixels. If the video being received does not match this setting, the test will fail. Default setting is 1920.\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_REF_HTOTAL",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Expected video width, in pixels",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x01260007",
|
||||
"defaultValue": "1125",
|
||||
"description": "Defined the expected total video height, in pixels. If the video being received does not match this setting, the test will fail. Default setting is 1080.\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_REF_VTOTAL",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Expected total video height, in pixels",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x01260008",
|
||||
"defaultValue": "1920",
|
||||
"description": "Defined the expected active video width, in pixels. If the video being received does not match this setting, the test will fail. Default setting is 1920.\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_REF_HACTIVE",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Expected active video width, in pixels",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x01260009",
|
||||
"defaultValue": "1080",
|
||||
"description": "Defined the expected active video height, in pixels. If the video being received does not match this setting, the test will fail. Default setting is 1080.\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_REF_VACTIVE",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Expected active video height, in pixels",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x0126000a",
|
||||
"defaultValue": "88",
|
||||
"description": "Defined the expected horizontal front porch, in pixels. If the video being received does not match this setting, the test will fail. Default setting is 1920.\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_REF_HFRONT",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Expected horizontal front porch, in pixels",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x0126000b",
|
||||
"defaultValue": "4",
|
||||
"description": "Defined the expected vertical front porch, in pixels. If the video being received does not match this setting, the test will fail. Default setting is 1080.\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_REF_VFRONT",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Expected vertical front porch, in pixels",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x0126000c",
|
||||
"defaultValue": "44",
|
||||
"description": "Defined the expected horizontal sync interval, in pixels. If the video being received does not match this setting, the test will fail. Default setting is 1920.\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_REF_HSYNC",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Expected horizontal sync interval, in pixels",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x0126000d",
|
||||
"defaultValue": "5",
|
||||
"description": "Defined the expected vertical sync interval, in pixels. If the video being received does not match this setting, the test will fail. Default setting is 1080.\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_REF_VSYNC",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Expected vertical sync interval, in pixels",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x0126000e",
|
||||
"defaultValue": "0",
|
||||
"description": "Data transfer timeout in milliseconds. Default setting is 0.\n",
|
||||
"flag": 3,
|
||||
"id": "TSI_TIMINGS_DATA_TRANSFER_TIMEOUT",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Data transfer timeout.",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x01260021",
|
||||
"defaultValue": "",
|
||||
"description": "Contains the full path to the folder where failed frames are to be saved without trailing backslash (‘\\’). No default. Failed frame file-name will be “Failed_<#>.ppm”, where <#> is replaced with an auto-incremented number.",
|
||||
"flag": 3,
|
||||
"id": "TSI_FAILED_FRAME_TARGET_FOLDER",
|
||||
"maxLength": 10000,
|
||||
"name": "Location where the failed frames are to be saved",
|
||||
"type": 11
|
||||
},
|
||||
{
|
||||
"configId": "0x01260022",
|
||||
"defaultValue": "0",
|
||||
"description": "Defines the number of failed frames to be exported from the video test. Default setting is 0. If the setting is 0, no frames are exported.",
|
||||
"flag": 3,
|
||||
"id": "TSI_MAX_EXPORT_FAILED",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Maximum number of exported frames",
|
||||
"type": 4
|
||||
}
|
||||
],
|
||||
"id": "0x2d",
|
||||
"name": "Timings Video Tests",
|
||||
"shortName": "Timings Video Tests",
|
||||
"old_names": [
|
||||
"Timings Video Test Set"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"descriptions": [
|
||||
{
|
||||
"configId": "0x1270000",
|
||||
"defaultValue": "5000",
|
||||
"description": "Defines test timeout in milliseconds, default value is 5000ms.",
|
||||
"flag": 3,
|
||||
"id": "TSI_DP20_MST_BRANCH_TIMEOUT",
|
||||
"maxValue": 2147483647,
|
||||
"minValue": 0,
|
||||
"name": "Test timeout in milliseconds.",
|
||||
"reportFormat": "Test timeout = %2ms<br>",
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"configId": "0x1270001",
|
||||
"defaultValue": "0x00000000",
|
||||
"description": "Defines the DUT capabilities as flags.",
|
||||
"bitList":
|
||||
[
|
||||
{"mask": "0x00000001", "description": "DUT supports CSN DFP broadcast", "reportFormat": "- DUT is Type-C device<br>"}
|
||||
],
|
||||
"flag": 3,
|
||||
"id": "TSI_DP20_MST_BRANCH_DUT_CAPS",
|
||||
"name": "DUT Capability flags.",
|
||||
"reportFormat": "Test DUT capabilities flags:<br>",
|
||||
"type": 12
|
||||
},
|
||||
{
|
||||
"configId": "0x1270002",
|
||||
"defaultValue": "0x00000010",
|
||||
"description": "Defines the numbers of DUT UFP and DFP ports connected to TE.",
|
||||
"bitList":
|
||||
[
|
||||
{"mask": "0x0000000f", "description": "DUT UFP port connected to TE"},
|
||||
{"mask": "0x000000f0", "description": "DUT DFP port connected to TE"}
|
||||
],
|
||||
"flag": 3,
|
||||
"id": "TSI_DP20_MST_BRANCH_DUT_UFP_DFP_PORTS",
|
||||
"name": "DUT UFP and DFP ports connected to TE",
|
||||
"reportFormat": "DUT UFP and DFP ports connected to TE:<br>",
|
||||
"type": 12
|
||||
},
|
||||
{
|
||||
"configId": "0x1270003",
|
||||
"defaultValue": "0x00005432",
|
||||
"description": "Defines the numbers of DUT DFP ports connected to external sinks.",
|
||||
"bitList":
|
||||
[
|
||||
{"mask": "0x0000000f", "description": "DUT DFP port connected to Sink 1"},
|
||||
{"mask": "0x000000f0", "description": "DUT DFP port connected to Sink 2"},
|
||||
{"mask": "0x00000f00", "description": "DUT DFP port connected to Sink 3"},
|
||||
{"mask": "0x0000f000", "description": "DUT DFP port connected to Sink 4"}
|
||||
],
|
||||
"flag": 3,
|
||||
"id": "TSI_DP20_MST_BRANCH_DUT_SINK_PORTS",
|
||||
"name": "DUT DFP ports connected to external sinks",
|
||||
"reportFormat": "DUT DFP ports connected to external sinks:<br>",
|
||||
"type": 12
|
||||
}
|
||||
],
|
||||
"id": "0x2E",
|
||||
"name": "DP 2.1 MST Branch CTS",
|
||||
"old_names": [
|
||||
"DP 2.1 MST Branch CTS"
|
||||
]
|
||||
}
|
||||
@@ -26,6 +26,13 @@ from .hdmi_sink_tests import HdmiSinkDUTTestParam, HdmiTestMode, HdmiFrlRate
|
||||
from .hdmi_source_tests import HdmiSourceDUTTestParam
|
||||
from .hdmi_sink_continuity_tests import HdmiSinkContinuityDUTTestParam
|
||||
from .hdmi_sink_cable_check_tests import HdmiSinkCableCheckTestParam
|
||||
from .hdmi_hdcp_1a_tests import HdmiHdcp1ATestParam
|
||||
from .hdmi_hdcp_1b_tests import HdmiHdcp1BTestParam
|
||||
from .hdmi_hdcp_2c_tests import HdmiHdcp2CTestParam
|
||||
from .hdmi_hdcp_3a_tests import HdmiHdcp3ATestParam
|
||||
from .hdmi_hdcp_3b_tests import HdmiHdcp3BTestParam
|
||||
from .hdmi_hdcp_3c_tests import HdmiHdcp3CTestParam
|
||||
from .dp_2_1_branch_mst import Dp21BranchMSTSourceDUTTestParam
|
||||
from ..test_group_params_types import Param, get_param_list
|
||||
|
||||
DUTTestParameters = TypeVar("DUTTestParameters",
|
||||
@@ -53,4 +60,12 @@ DUTTestParameters = TypeVar("DUTTestParameters",
|
||||
Hdr10TestParam,
|
||||
HdmiSinkDUTTestParam,
|
||||
HdmiSinkContinuityDUTTestParam,
|
||||
HdmiSinkCableCheckTestParam)
|
||||
HdmiSinkCableCheckTestParam,
|
||||
HdmiHdcp1ATestParam,
|
||||
HdmiHdcp1BTestParam,
|
||||
HdmiHdcp2CTestParam,
|
||||
HdmiHdcp3ATestParam,
|
||||
HdmiHdcp3BTestParam,
|
||||
HdmiHdcp3CTestParam,
|
||||
Dp21BranchMSTSourceDUTTestParam
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ from UniTAP.dev.modules.dut_tests.dut_default_params.dp_source_adaptive_sync_tab
|
||||
from UniTAP.dev.modules.dut_tests.dut_default_params.dp_2_1_video_modes import Dp21AvailableVideoModes
|
||||
from UniTAP.dev.modules.dut_tests.dut_default_params.dp_2_1_dsc_video_modes import Dp21AvailableDscVideoModes
|
||||
from UniTAP.dev.modules.dut_tests.dut_default_params.dp_source_audio_tab import AudioSourceDp21SettingTab
|
||||
from UniTAP.dev.modules.dut_tests.dut_default_params.dp_2_1_mst import Dp21MstSettingsTab
|
||||
|
||||
|
||||
class Dp21SourceDUTTestParam:
|
||||
@@ -13,6 +14,7 @@ class Dp21SourceDUTTestParam:
|
||||
- Set and get `DisplayIdDp21ConfigTab`. Allows working with parameters from Display ID part `display_id`.
|
||||
- Set and get `AdaptiveSyncDp21ConfigTab`. Allows working with parameters from Adaptive-Sync part `adaptive_sync`.
|
||||
- Set and get `Dp21AvailableVideoModes`. Allows working with parameters from Video modes part `video_modes`.
|
||||
- Set and get `Dp21MstSettingsTab`. Allows working with parameters from MST part `mst`.
|
||||
"""
|
||||
def __init__(self, json_obj):
|
||||
self.__general_tab = GeneralSourceDUTDp21SettingTab(json_obj)
|
||||
@@ -21,6 +23,7 @@ class Dp21SourceDUTTestParam:
|
||||
self.__adaptive_sync_tab = AdaptiveSyncDp21ConfigTab(json_obj)
|
||||
self.__video_modes = Dp21AvailableVideoModes(json_obj)
|
||||
self.__dsc_video_modes = Dp21AvailableDscVideoModes(json_obj)
|
||||
self.__mst_tab = Dp21MstSettingsTab(json_obj)
|
||||
|
||||
@property
|
||||
def general(self) -> GeneralSourceDUTDp21SettingTab:
|
||||
@@ -81,3 +84,13 @@ class Dp21SourceDUTTestParam:
|
||||
object of `Dp21AvailableVideoModes` type
|
||||
"""
|
||||
return self.__dsc_video_modes
|
||||
|
||||
@property
|
||||
def mst(self) -> Dp21MstSettingsTab:
|
||||
"""
|
||||
Get object of parameters from Video modes source part.
|
||||
|
||||
Returns:
|
||||
object of `Dp21MstSettingsTab` type
|
||||
"""
|
||||
return self.__mst_tab
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
from UniTAP.dev.modules.dut_tests.test_group_params_types import Param
|
||||
|
||||
|
||||
class DutCapsMSTBranchFlags:
|
||||
"""
|
||||
Class `DutCapsDp21Flags` defines the DUT capabilities as flags.
|
||||
|
||||
Setting:
|
||||
- DUT CSN DFP broadcast supported flag `support_csn_dfp_broadcast`.
|
||||
"""
|
||||
def __init__(self, json_obj):
|
||||
self.__value = Param(json_obj)
|
||||
|
||||
@property
|
||||
def support_csn_dfp_broadcast(self) -> bool:
|
||||
"""
|
||||
Set and get DUT CSN DFP broadcast flag support.
|
||||
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self.__value._get_by_bitmask(0, bool)
|
||||
|
||||
@support_csn_dfp_broadcast.setter
|
||||
def support_csn_dfp_broadcast(self, support_csn_dfp_broadcast: bool):
|
||||
self.__value._set_by_bitmask(support_csn_dfp_broadcast, 0)
|
||||
|
||||
|
||||
class PortsConnectedToTE:
|
||||
"""
|
||||
Class `PortsConnectedToTE` which defines the numbers of DUT UFP and DFP ports connected to TE.
|
||||
|
||||
Setting:
|
||||
- Number of DUT UFP ports connected to TE `ufp_ports`.
|
||||
- Number of DUT DFP ports connected to TE `dfp_ports`.
|
||||
"""
|
||||
def __init__(self, json_obj):
|
||||
self.__value = Param(json_obj)
|
||||
|
||||
@property
|
||||
def ufp_ports(self) -> int:
|
||||
"""
|
||||
Set and get number of DUT UFP ports connected to TE.
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__value._get_by_bitmask(0, int)
|
||||
|
||||
@ufp_ports.setter
|
||||
def ufp_ports(self, ufp_ports: int):
|
||||
self.__value._set_by_bitmask(ufp_ports, 0)
|
||||
|
||||
@property
|
||||
def dfp_ports(self) -> int:
|
||||
"""
|
||||
Set and get number of DUT DFP ports connected to TE.
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__value._get_by_bitmask(1, int)
|
||||
|
||||
@dfp_ports.setter
|
||||
def dfp_ports(self, dfp_ports: int):
|
||||
self.__value._set_by_bitmask(dfp_ports, 1)
|
||||
|
||||
|
||||
class PortsConnectedToExternalSink:
|
||||
"""
|
||||
Class `PortsConnectedToExternalSink` which defines the numbers of DUT DFP ports connected to external sinks.
|
||||
|
||||
Setting:
|
||||
- Number of DUT DFP ports connected to Sink 1 `sink_1`.
|
||||
- Number of DUT DFP ports connected to Sink 2 `sink_2`.
|
||||
- Number of DUT DFP ports connected to Sink 3 `sink_3`.
|
||||
- Number of DUT DFP ports connected to Sink 4 `sink_4`.
|
||||
"""
|
||||
def __init__(self, json_obj):
|
||||
self.__value = Param(json_obj)
|
||||
|
||||
@property
|
||||
def sink_1(self) -> int:
|
||||
"""
|
||||
Set and get number of DUT DFP ports connected to Sink 1.
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__value._get_by_bitmask(0, int)
|
||||
|
||||
@sink_1.setter
|
||||
def sink_1(self, ports_to_sink_1: int):
|
||||
self.__value._set_by_bitmask(ports_to_sink_1, 0)
|
||||
|
||||
@property
|
||||
def sink_2(self) -> int:
|
||||
"""
|
||||
Set and get number of DUT DFP ports connected to Sink 2.
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__value._get_by_bitmask(0, int)
|
||||
|
||||
@sink_2.setter
|
||||
def sink_2(self, ports_to_sink_2: int):
|
||||
self.__value._set_by_bitmask(ports_to_sink_2, 0)
|
||||
|
||||
@property
|
||||
def sink_3(self) -> int:
|
||||
"""
|
||||
Set and get number of DUT DFP ports connected to Sink 3.
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__value._get_by_bitmask(0, int)
|
||||
|
||||
@sink_3.setter
|
||||
def sink_3(self, ports_to_sink_3: int):
|
||||
self.__value._set_by_bitmask(ports_to_sink_3, 0)
|
||||
|
||||
@property
|
||||
def sink_4(self) -> int:
|
||||
"""
|
||||
Set and get number of DUT DFP ports connected to Sink 4.
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__value._get_by_bitmask(0, int)
|
||||
|
||||
@sink_4.setter
|
||||
def sink_4(self, ports_to_sink_1: int):
|
||||
self.__value._set_by_bitmask(ports_to_sink_1, 0)
|
||||
|
||||
|
||||
class Dp21BranchMSTSourceDUTTestParam:
|
||||
"""
|
||||
Class `Dp21BranchMSTSourceDUTTestParam` describes requirement parameters for DP 2.1 branch MST tests:
|
||||
- Set and get `timeout`. Describes test timeout, in milliseconds.
|
||||
- DUT MST Branch capabilities flags `dut_caps_flags` type `DutCapsMSTBranchFlags`.
|
||||
- DUT UFP and DFP ports connected to TE `ports_connect_to_te` type `PortsConnectedToTE`.
|
||||
- DUT DFP ports connected to external sinks `ports_connect_to_external_sink` type `PortsConnectedToExternalSink`
|
||||
"""
|
||||
def __init__(self, json_obj):
|
||||
self.__timeout = Param(json_obj["TSI_DP20_MST_BRANCH_TIMEOUT"])
|
||||
self.__dut_caps_flags = DutCapsMSTBranchFlags(json_obj["TSI_DP20_MST_BRANCH_DUT_CAPS"])
|
||||
self.__ports_connect_to_te = PortsConnectedToTE(json_obj["TSI_DP20_MST_BRANCH_DUT_UFP_DFP_PORTS"])
|
||||
self.__ports_connect_to_external_sink = PortsConnectedToExternalSink(json_obj["TSI_DP20_MST_BRANCH_DUT_SINK_PORTS"])
|
||||
|
||||
@property
|
||||
def timeout(self) -> int:
|
||||
"""
|
||||
Set and get test timeout, in milliseconds.
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__timeout.default_value
|
||||
|
||||
@timeout.setter
|
||||
def timeout(self, timeout: int):
|
||||
if not(self.__timeout.min_value < timeout < self.__timeout.max_value):
|
||||
raise ValueError(f"Timeout cannot be less than {self.__timeout.min_value} and more than "
|
||||
f"{self.__timeout.max_value}.")
|
||||
self.__timeout.default_value = timeout
|
||||
|
||||
@property
|
||||
def dut_caps_flags(self) -> DutCapsMSTBranchFlags:
|
||||
"""
|
||||
Set and get DUT capabilities flags.
|
||||
|
||||
Returns:
|
||||
object of `DutCapsMSTBranchFlags` type
|
||||
"""
|
||||
return self.__dut_caps_flags
|
||||
|
||||
@dut_caps_flags.setter
|
||||
def dut_caps_flags(self, dut_caps_flags: DutCapsMSTBranchFlags):
|
||||
self.__dut_caps_flags = dut_caps_flags
|
||||
|
||||
@property
|
||||
def ports_connect_to_te(self) -> PortsConnectedToTE:
|
||||
"""
|
||||
Set and get numbers DUT UFP and DFP ports connected to TE.
|
||||
|
||||
Returns:
|
||||
object of `PortsConnectedToTE` type
|
||||
"""
|
||||
return self.__ports_connect_to_te
|
||||
|
||||
@ports_connect_to_te.setter
|
||||
def ports_connect_to_te(self, ports_connect_to_te: PortsConnectedToTE):
|
||||
self.__ports_connect_to_te = ports_connect_to_te
|
||||
|
||||
@property
|
||||
def ports_connect_to_external_sink(self) -> PortsConnectedToExternalSink:
|
||||
"""
|
||||
Set and get numbers DUT UFP and DFP ports connected to External Sinks.
|
||||
|
||||
Returns:
|
||||
object of `PortsConnectedToExternalSink` type
|
||||
"""
|
||||
return self.__ports_connect_to_external_sink
|
||||
|
||||
@ports_connect_to_external_sink.setter
|
||||
def ports_connect_to_external_sink(self, ports_connect_to_external_sink: PortsConnectedToExternalSink):
|
||||
self.__ports_connect_to_external_sink = ports_connect_to_external_sink
|
||||
@@ -276,13 +276,11 @@ class VideoModeInfo:
|
||||
|
||||
def __init__(self, json_obj):
|
||||
self.__value = Param(json_obj)
|
||||
self.__standard = VideoModeStandard(self.__value)
|
||||
self.__colorimetry = ColorimetryModes(self.__value)
|
||||
|
||||
@property
|
||||
def standard(self) -> VideoModeStandard:
|
||||
return self.__standard
|
||||
return VideoModeStandard(self.__value)
|
||||
|
||||
@property
|
||||
def colorimetry(self) -> ColorimetryModes:
|
||||
return self.__colorimetry
|
||||
return ColorimetryModes(self.__value)
|
||||
|
||||
@@ -7,8 +7,6 @@ class Dp21AvailableDscVideoModes:
|
||||
- Set and get...
|
||||
"""
|
||||
def __init__(self, json_obj):
|
||||
self.__is_config_changed = False
|
||||
|
||||
self.__1920x1080_30hz = VideoModeInfo(json_obj["TSI_DP20_SRCCTS_DSC_VMT_1920_1080_30"])
|
||||
self.__1920x1080_60hz = VideoModeInfo(json_obj["TSI_DP20_SRCCTS_DSC_VMT_1920_1080_60"])
|
||||
self.__1920x1080_120hz = VideoModeInfo(json_obj["TSI_DP20_SRCCTS_DSC_VMT_1920_1080_120"])
|
||||
@@ -30,12 +28,6 @@ class Dp21AvailableDscVideoModes:
|
||||
self.__10240x4320_30hz = VideoModeInfo(json_obj["TSI_DP20_SRCCTS_DSC_VMT_10240_4320_30"])
|
||||
self.__10240x4320_60hz = VideoModeInfo(json_obj["TSI_DP20_SRCCTS_DSC_VMT_10240_4320_60"])
|
||||
|
||||
def __getattribute__(self, name):
|
||||
attr = super().__getattribute__(name)
|
||||
if "vm_" in name or "_all" in name:
|
||||
self.__is_config_changed = True
|
||||
return attr
|
||||
|
||||
@property
|
||||
def vm_1920x1080_30hz(self) -> VideoModeInfo:
|
||||
return self.__1920x1080_30hz
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
from UniTAP.dev.modules.dut_tests.test_group_params_types import Param
|
||||
|
||||
|
||||
class Dp21MstSettingsTab:
|
||||
"""
|
||||
Class `Dp21MstSettingsTab` allows working with MST source DUT capabilities.
|
||||
- Set and get Maximum stream count
|
||||
- Set and get Maximum daisy chain sink count
|
||||
"""
|
||||
def __init__(self, json_obj):
|
||||
self.__max_stream_count = Param(json_obj["TSI_DP20_SRCCTS_DUT_MST_CAPS"])
|
||||
self.__max_daisy_chain_sink_count = Param(json_obj["TSI_DP20_SRCCTS_DUT_MST_CAPS"])
|
||||
|
||||
@property
|
||||
def max_stream_count(self) -> int:
|
||||
"""
|
||||
Set and get max stream count (1-4).
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__max_stream_count.default_value & 0xFF
|
||||
|
||||
@max_stream_count.setter
|
||||
def max_stream_count(self, max_stream_count: int):
|
||||
if not (self.__max_stream_count.min_value <= max_stream_count <= self.__max_stream_count.max_value):
|
||||
raise ValueError(f"Timeout cannot be less than {self.__max_stream_count.min_value} and more than "
|
||||
f"{self.__max_stream_count.max_value}.")
|
||||
self.__max_stream_count.direct_set_bits_value(0xFF, max_stream_count, 0)
|
||||
|
||||
@property
|
||||
def max_daisy_chain_sink_count(self) -> int:
|
||||
"""
|
||||
Set and get max daisy chain sink count (1-4).
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return (self.__max_daisy_chain_sink_count.default_value >> 8) & 0xFF
|
||||
|
||||
@max_daisy_chain_sink_count.setter
|
||||
def max_daisy_chain_sink_count(self, max_daisy_chain_sink_count: int):
|
||||
if not (self.__max_stream_count.min_value <= max_daisy_chain_sink_count <= self.__max_stream_count.max_value):
|
||||
raise ValueError(f"Timeout cannot be less than {self.__max_daisy_chain_sink_count.min_value} and more than "
|
||||
f"{self.__max_daisy_chain_sink_count.max_value}.")
|
||||
self.__max_daisy_chain_sink_count.direct_set_bits_value(0xFF00, max_daisy_chain_sink_count, 8)
|
||||
@@ -114,7 +114,7 @@ class LinkRateDp21(Param):
|
||||
self._set_by_bitmask(support_13_5Gbps, 2)
|
||||
|
||||
|
||||
class DutCapsDp21Flags(Param):
|
||||
class DutCapsDp21Flags:
|
||||
"""
|
||||
Class `DutCapsDp21Flags` inherited of class`DutCapsFlags` which defines the DUT capabilities as flags and allows
|
||||
setting:
|
||||
@@ -123,7 +123,7 @@ class DutCapsDp21Flags(Param):
|
||||
Also has all the `DutCapsFlags` functionality.
|
||||
"""
|
||||
def __init__(self, json_obj):
|
||||
super().__init__(json_obj)
|
||||
self.__value = Param(json_obj)
|
||||
|
||||
@property
|
||||
def voltage_swing_supported(self) -> bool:
|
||||
@@ -133,11 +133,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(0, bool)
|
||||
return self.__value._get_by_bitmask(0, bool)
|
||||
|
||||
@voltage_swing_supported.setter
|
||||
def voltage_swing_supported(self, voltage_swing_supported: bool):
|
||||
self._set_by_bitmask(voltage_swing_supported, 0)
|
||||
self.__value._set_by_bitmask(voltage_swing_supported, 0)
|
||||
|
||||
@property
|
||||
def pre_emphasis_supported(self) -> bool:
|
||||
@@ -147,11 +147,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(1, bool)
|
||||
return self.__value._get_by_bitmask(1, bool)
|
||||
|
||||
@pre_emphasis_supported.setter
|
||||
def pre_emphasis_supported(self, pre_emphasis_supported: bool):
|
||||
self._set_by_bitmask(pre_emphasis_supported, 1)
|
||||
self.__value._set_by_bitmask(pre_emphasis_supported, 1)
|
||||
|
||||
@property
|
||||
def fixed_timing_dut_supported(self) -> bool:
|
||||
@@ -161,11 +161,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(2, bool)
|
||||
return self.__value._get_by_bitmask(2, bool)
|
||||
|
||||
@fixed_timing_dut_supported.setter
|
||||
def fixed_timing_dut_supported(self, fixed_timing_dut_supported: bool):
|
||||
self._set_by_bitmask(fixed_timing_dut_supported, 2)
|
||||
self.__value._set_by_bitmask(fixed_timing_dut_supported, 2)
|
||||
|
||||
@property
|
||||
def spread_spectrum_supported(self) -> bool:
|
||||
@@ -175,11 +175,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(3, bool)
|
||||
return self.__value._get_by_bitmask(3, bool)
|
||||
|
||||
@spread_spectrum_supported.setter
|
||||
def spread_spectrum_supported(self, spread_spectrum_supported: bool):
|
||||
self._set_by_bitmask(spread_spectrum_supported, 3)
|
||||
self.__value._set_by_bitmask(spread_spectrum_supported, 3)
|
||||
|
||||
@property
|
||||
def change_vf_without_lt_supported(self) -> bool:
|
||||
@@ -189,11 +189,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(4, bool)
|
||||
return self.__value._get_by_bitmask(4, bool)
|
||||
|
||||
@change_vf_without_lt_supported.setter
|
||||
def change_vf_without_lt_supported(self, change_vf_without_lt_supported: bool):
|
||||
self._set_by_bitmask(change_vf_without_lt_supported, 4)
|
||||
self.__value._set_by_bitmask(change_vf_without_lt_supported, 4)
|
||||
|
||||
@property
|
||||
def e_ddc_protocol_supported(self) -> bool:
|
||||
@@ -203,11 +203,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(5, bool)
|
||||
return self.__value._get_by_bitmask(5, bool)
|
||||
|
||||
@e_ddc_protocol_supported.setter
|
||||
def e_ddc_protocol_supported(self, e_ddc_protocol_supported: bool):
|
||||
self._set_by_bitmask(e_ddc_protocol_supported, 5)
|
||||
self.__value._set_by_bitmask(e_ddc_protocol_supported, 5)
|
||||
|
||||
@property
|
||||
def audio_transmission_supported(self) -> bool:
|
||||
@@ -217,11 +217,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(6, bool)
|
||||
return self.__value._get_by_bitmask(6, bool)
|
||||
|
||||
@audio_transmission_supported.setter
|
||||
def audio_transmission_supported(self, audio_transmission_supported: bool):
|
||||
self._set_by_bitmask(audio_transmission_supported, 6)
|
||||
self.__value._set_by_bitmask(audio_transmission_supported, 6)
|
||||
|
||||
@property
|
||||
def dut_is_type_c_device(self) -> bool:
|
||||
@@ -231,11 +231,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(7, bool)
|
||||
return self.__value._get_by_bitmask(7, bool)
|
||||
|
||||
@dut_is_type_c_device.setter
|
||||
def dut_is_type_c_device(self, dut_is_type_c_device: bool):
|
||||
self._set_by_bitmask(dut_is_type_c_device, 7)
|
||||
self.__value._set_by_bitmask(dut_is_type_c_device, 7)
|
||||
|
||||
@property
|
||||
def fec_supported(self) -> bool:
|
||||
@@ -245,11 +245,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(8, bool)
|
||||
return self.__value._get_by_bitmask(8, bool)
|
||||
|
||||
@fec_supported.setter
|
||||
def fec_supported(self, fec_supported: bool):
|
||||
self._set_by_bitmask(fec_supported, 8)
|
||||
self.__value._set_by_bitmask(fec_supported, 8)
|
||||
|
||||
@property
|
||||
def fec_disable_sequence_supported(self) -> bool:
|
||||
@@ -259,11 +259,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(9, bool)
|
||||
return self.__value._get_by_bitmask(9, bool)
|
||||
|
||||
@fec_disable_sequence_supported.setter
|
||||
def fec_disable_sequence_supported(self, fec_disable_sequence_supported: bool):
|
||||
self._set_by_bitmask(fec_disable_sequence_supported, 9)
|
||||
self.__value._set_by_bitmask(fec_disable_sequence_supported, 9)
|
||||
|
||||
@property
|
||||
def audio_without_video_supported(self) -> bool:
|
||||
@@ -273,11 +273,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(10, bool)
|
||||
return self.__value._get_by_bitmask(10, bool)
|
||||
|
||||
@audio_without_video_supported.setter
|
||||
def audio_without_video_supported(self, audio_without_video_supported: bool):
|
||||
self._set_by_bitmask(audio_without_video_supported, 10)
|
||||
self.__value._set_by_bitmask(audio_without_video_supported, 10)
|
||||
|
||||
@property
|
||||
def dsc_supported(self) -> bool:
|
||||
@@ -287,11 +287,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(11, bool)
|
||||
return self.__value._get_by_bitmask(11, bool)
|
||||
|
||||
@dsc_supported.setter
|
||||
def dsc_supported(self, dsc_supported: bool):
|
||||
self._set_by_bitmask(dsc_supported, 11)
|
||||
self.__value._set_by_bitmask(dsc_supported, 11)
|
||||
|
||||
@property
|
||||
def dsc_block_prediction_supported(self) -> bool:
|
||||
@@ -301,11 +301,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(12, bool)
|
||||
return self.__value._get_by_bitmask(12, bool)
|
||||
|
||||
@dsc_block_prediction_supported.setter
|
||||
def dsc_block_prediction_supported(self, dsc_block_prediction_supported: bool):
|
||||
self._set_by_bitmask(dsc_block_prediction_supported, 12)
|
||||
self.__value._set_by_bitmask(dsc_block_prediction_supported, 12)
|
||||
|
||||
@property
|
||||
def max_link_bandwidth_policy_supported(self):
|
||||
@@ -315,11 +315,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(13, bool)
|
||||
return self.__value._get_by_bitmask(13, bool)
|
||||
|
||||
@max_link_bandwidth_policy_supported.setter
|
||||
def max_link_bandwidth_policy_supported(self, max_link_bandwidth_policy_supported: bool):
|
||||
self._set_by_bitmask(max_link_bandwidth_policy_supported, 13)
|
||||
self.__value._set_by_bitmask(max_link_bandwidth_policy_supported, 13)
|
||||
|
||||
@property
|
||||
def use_3tap_conversion(self):
|
||||
@@ -329,11 +329,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(14, bool)
|
||||
return self.__value._get_by_bitmask(14, bool)
|
||||
|
||||
@use_3tap_conversion.setter
|
||||
def use_3tap_conversion(self, use_3tap_filter: bool):
|
||||
self._set_by_bitmask(use_3tap_filter, 14)
|
||||
self.__value._set_by_bitmask(use_3tap_filter, 14)
|
||||
|
||||
@property
|
||||
def usb4_tunnel_presented(self):
|
||||
@@ -343,11 +343,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(15, bool)
|
||||
return self.__value._get_by_bitmask(15, bool)
|
||||
|
||||
@usb4_tunnel_presented.setter
|
||||
def usb4_tunnel_presented(self, usb4_tunnel_presented: bool):
|
||||
self._set_by_bitmask(usb4_tunnel_presented, 15)
|
||||
self.__value._set_by_bitmask(usb4_tunnel_presented, 15)
|
||||
|
||||
@property
|
||||
def native_display_id_read(self) -> bool:
|
||||
@@ -357,11 +357,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(16, bool)
|
||||
return self.__value._get_by_bitmask(16, bool)
|
||||
|
||||
@native_display_id_read.setter
|
||||
def native_display_id_read(self, native_display_id_read: bool):
|
||||
self._set_by_bitmask(native_display_id_read, 16)
|
||||
self.__value._set_by_bitmask(native_display_id_read, 16)
|
||||
|
||||
@property
|
||||
def display_id_vii_supported(self) -> bool:
|
||||
@@ -371,11 +371,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(17, bool)
|
||||
return self.__value._get_by_bitmask(17, bool)
|
||||
|
||||
@display_id_vii_supported.setter
|
||||
def display_id_vii_supported(self, display_id_vii_supported: bool):
|
||||
self._set_by_bitmask(display_id_vii_supported, 17)
|
||||
self.__value._set_by_bitmask(display_id_vii_supported, 17)
|
||||
|
||||
@property
|
||||
def display_id_viii_supported(self) -> bool:
|
||||
@@ -385,12 +385,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(18, bool)
|
||||
return self.__value._get_by_bitmask(18, bool)
|
||||
|
||||
@display_id_viii_supported.setter
|
||||
def display_id_viii_supported(self, display_id_viii_supported: bool):
|
||||
self._set_by_bitmask(display_id_viii_supported, 18)
|
||||
|
||||
self.__value._set_by_bitmask(display_id_viii_supported, 18)
|
||||
|
||||
@property
|
||||
def display_id_ix_supported(self) -> bool:
|
||||
@@ -400,11 +399,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(19, bool)
|
||||
return self.__value._get_by_bitmask(19, bool)
|
||||
|
||||
@display_id_ix_supported.setter
|
||||
def display_id_ix_supported(self, display_id_ix_supported: bool):
|
||||
self._set_by_bitmask(display_id_ix_supported, 19)
|
||||
self.__value._set_by_bitmask(display_id_ix_supported, 19)
|
||||
|
||||
@property
|
||||
def display_id_x_supported(self) -> bool:
|
||||
@@ -414,11 +413,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(20, bool)
|
||||
return self.__value._get_by_bitmask(20, bool)
|
||||
|
||||
@display_id_x_supported.setter
|
||||
def display_id_x_supported(self, display_id_x_supported: bool):
|
||||
self._set_by_bitmask(display_id_x_supported, 20)
|
||||
self.__value._set_by_bitmask(display_id_x_supported, 20)
|
||||
|
||||
@property
|
||||
def display_id_tiled_display_topology(self) -> bool:
|
||||
@@ -428,11 +427,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(21, bool)
|
||||
return self.__value._get_by_bitmask(21, bool)
|
||||
|
||||
@display_id_tiled_display_topology.setter
|
||||
def display_id_tiled_display_topology(self, display_id_tiled_display_topology: bool):
|
||||
self._set_by_bitmask(display_id_tiled_display_topology, 21)
|
||||
self.__value._set_by_bitmask(display_id_tiled_display_topology, 21)
|
||||
|
||||
@property
|
||||
def display_id_tiled_stereo_display(self) -> bool:
|
||||
@@ -442,11 +441,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(22, bool)
|
||||
return self.__value._get_by_bitmask(22, bool)
|
||||
|
||||
@display_id_tiled_stereo_display.setter
|
||||
def display_id_tiled_stereo_display(self, display_id_tiled_stereo_display: bool):
|
||||
self._set_by_bitmask(display_id_tiled_stereo_display, 22)
|
||||
self.__value._set_by_bitmask(display_id_tiled_stereo_display, 22)
|
||||
|
||||
@property
|
||||
def stacked_frame_stereo_supported(self) -> bool:
|
||||
@@ -456,11 +455,11 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(23, bool)
|
||||
return self.__value._get_by_bitmask(23, bool)
|
||||
|
||||
@stacked_frame_stereo_supported.setter
|
||||
def stacked_frame_stereo_supported(self, stacked_frame_stereo_supported: bool):
|
||||
self._set_by_bitmask(stacked_frame_stereo_supported, 23)
|
||||
self.__value._set_by_bitmask(stacked_frame_stereo_supported, 23)
|
||||
|
||||
@property
|
||||
def dynamic_refresh_rate_support(self) -> bool:
|
||||
@@ -470,11 +469,67 @@ class DutCapsDp21Flags(Param):
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self._get_by_bitmask(24, bool)
|
||||
return self.__value._get_by_bitmask(24, bool)
|
||||
|
||||
@dynamic_refresh_rate_support.setter
|
||||
def dynamic_refresh_rate_support(self, dynamic_refresh_rate_support: bool):
|
||||
self._set_by_bitmask(dynamic_refresh_rate_support, 24)
|
||||
self.__value._set_by_bitmask(dynamic_refresh_rate_support, 24)
|
||||
|
||||
@property
|
||||
def mst_transmission_supported(self) -> bool:
|
||||
"""
|
||||
Set and get MST transmission supported flag supported.
|
||||
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self.__value._get_by_bitmask(25, bool)
|
||||
|
||||
@mst_transmission_supported.setter
|
||||
def mst_transmission_supported(self, mst_transmission_supported: bool):
|
||||
self.__value._set_by_bitmask(mst_transmission_supported, 25)
|
||||
|
||||
@property
|
||||
def mst_up_request_supported(self) -> bool:
|
||||
"""
|
||||
Set and get MST UP REQUEST supported flag supported.
|
||||
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self.__value._get_by_bitmask(26, bool)
|
||||
|
||||
@mst_up_request_supported.setter
|
||||
def mst_up_request_supported(self, mst_up_request_supported: bool):
|
||||
self.__value._set_by_bitmask(mst_up_request_supported, 26)
|
||||
|
||||
@property
|
||||
def mst_rsn_request_supported(self) -> bool:
|
||||
"""
|
||||
Set and get MST RSN REQUEST supported flag supported.
|
||||
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self.__value._get_by_bitmask(27, bool)
|
||||
|
||||
@mst_rsn_request_supported.setter
|
||||
def mst_rsn_request_supported(self, mst_rsn_request_supported: bool):
|
||||
self.__value._set_by_bitmask(mst_rsn_request_supported, 27)
|
||||
|
||||
@property
|
||||
def mst_power_up_request_supported(self) -> bool:
|
||||
"""
|
||||
Set and get MST POWER_UP DOWN_PHY supported flag supported.
|
||||
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return self.__value._get_by_bitmask(28, bool)
|
||||
|
||||
@mst_power_up_request_supported.setter
|
||||
def mst_power_up_request_supported(self, mst_power_up_request_supported: bool):
|
||||
self.__value._set_by_bitmask(mst_power_up_request_supported, 28)
|
||||
|
||||
|
||||
class DutCapsDp21:
|
||||
@@ -487,7 +542,7 @@ class DutCapsDp21:
|
||||
def __init__(self, json_obj):
|
||||
self.__max_lanes = Param(json_obj["TSI_DP20_SRCCTS_MAX_LANES"])
|
||||
self.__max_link_rate = Param(json_obj["TSI_DP20_SRCCTS_MAX_LINK_RATE"])
|
||||
self.__dut_caps_flags = DutCapsDp21Flags(json_obj["TSI_DP20_SRCCTS_DUT_CAPS"])
|
||||
self.__dut_caps_flags_mst = DutCapsDp21Flags(json_obj["TSI_DP20_SRCCTS_DUT_CAPS"])
|
||||
|
||||
@property
|
||||
def max_lanes(self) -> int:
|
||||
@@ -529,11 +584,11 @@ class DutCapsDp21:
|
||||
Returns:
|
||||
object of `DutCapsFlags` type
|
||||
"""
|
||||
return self.__dut_caps_flags
|
||||
return self.__dut_caps_flags_mst
|
||||
|
||||
@dut_caps_flags.setter
|
||||
def dut_caps_flags(self, dut_caps_flags: DutCapsDp21Flags):
|
||||
self.__dut_caps_flags = dut_caps_flags
|
||||
self.__dut_caps_flags_mst = dut_caps_flags
|
||||
|
||||
|
||||
class DebugOptions:
|
||||
@@ -755,4 +810,3 @@ class GeneralSourceDUTDp21SettingTab:
|
||||
@debug_options.setter
|
||||
def debug_options(self, debug_config: DebugOptions):
|
||||
self.__debug_options = debug_config
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
from UniTAP.dev.modules.dut_tests.test_group_params_types import Param
|
||||
|
||||
|
||||
class HdmiHdcp1ATestParam:
|
||||
"""
|
||||
Class `HdmiHdcp1ATestParam` describes requirement parameters for HDMI HDCP 1A tests:
|
||||
- Set and get `timeout`. Describes test timeout, in milliseconds.
|
||||
"""
|
||||
def __init__(self, json_obj):
|
||||
self.__timeout = Param(json_obj["TSI_HDMI_HDCP_1A_TIMEOUT"])
|
||||
|
||||
@property
|
||||
def timeout(self) -> int:
|
||||
"""
|
||||
Set and get test timeout, in milliseconds.
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__timeout.default_value
|
||||
|
||||
@timeout.setter
|
||||
def timeout(self, timeout: int):
|
||||
if not(self.__timeout.min_value < timeout < self.__timeout.max_value):
|
||||
raise ValueError(f"Timeout cannot be less than {self.__timeout.min_value} and more than "
|
||||
f"{self.__timeout.max_value}.")
|
||||
self.__timeout.default_value = timeout
|
||||
@@ -0,0 +1,27 @@
|
||||
from UniTAP.dev.modules.dut_tests.test_group_params_types import Param
|
||||
|
||||
|
||||
class HdmiHdcp1BTestParam:
|
||||
"""
|
||||
Class `HdmiHdcp1BTestParam` describes requirement parameters for HDMI HDCP 1B tests:
|
||||
- Set and get `timeout`. Describes test timeout, in milliseconds.
|
||||
"""
|
||||
def __init__(self, json_obj):
|
||||
self.__timeout = Param(json_obj["TSI_HDMI_HDCP_1B_TIMEOUT"])
|
||||
|
||||
@property
|
||||
def timeout(self) -> int:
|
||||
"""
|
||||
Set and get test timeout, in milliseconds.
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__timeout.default_value
|
||||
|
||||
@timeout.setter
|
||||
def timeout(self, timeout: int):
|
||||
if not(self.__timeout.min_value < timeout < self.__timeout.max_value):
|
||||
raise ValueError(f"Timeout cannot be less than {self.__timeout.min_value} and more than "
|
||||
f"{self.__timeout.max_value}.")
|
||||
self.__timeout.default_value = timeout
|
||||
@@ -0,0 +1,60 @@
|
||||
from UniTAP.dev.modules.dut_tests.test_group_params_types import Param
|
||||
from .hdmi_sink_tests import HdmiFrlRate
|
||||
|
||||
|
||||
class HdmiHdcp2CTestParam:
|
||||
"""
|
||||
Class `HdmiHdcp2CTestParam` describes requirement parameters for HDMI HDCP 2C tests:
|
||||
- Set and get `timeout`. Describes test timeout, in milliseconds.
|
||||
- Set and get `lt_before_test`.
|
||||
- Set and get `link_rate`.
|
||||
"""
|
||||
def __init__(self, json_obj):
|
||||
self.__timeout = Param(json_obj["TSI_HDMI_HDCP_2C_TIMEOUT"])
|
||||
self.__lt_before_test = Param(json_obj["TSI_HDMI_HDCP_2C_LT_BEFORE_TEST"])
|
||||
self.__link_rate = Param(json_obj["TSI_HDMI_HDCP_2C_LINK_RATE"])
|
||||
|
||||
@property
|
||||
def timeout(self) -> int:
|
||||
"""
|
||||
Set and get test timeout, in milliseconds.
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__timeout.default_value
|
||||
|
||||
@timeout.setter
|
||||
def timeout(self, timeout: int):
|
||||
if not(self.__timeout.min_value < timeout < self.__timeout.max_value):
|
||||
raise ValueError(f"Timeout cannot be less than {self.__timeout.min_value} and more than "
|
||||
f"{self.__timeout.max_value}.")
|
||||
self.__timeout.default_value = timeout
|
||||
|
||||
@property
|
||||
def lt_before_test(self) -> bool:
|
||||
"""
|
||||
Set and get flag to do or not link training before starting test
|
||||
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return bool(self.__lt_before_test.default_value)
|
||||
|
||||
@lt_before_test.setter
|
||||
def lt_before_test(self, enable: bool):
|
||||
self.__lt_before_test.default_value = int(enable)
|
||||
|
||||
@property
|
||||
def link_rate(self) -> HdmiFrlRate:
|
||||
"""
|
||||
Set and get the Link rate for link training.
|
||||
|
||||
Returns:
|
||||
object of `HdmiFrlRate` type
|
||||
"""
|
||||
return HdmiFrlRate(self.__link_rate.default_value)
|
||||
|
||||
@link_rate.setter
|
||||
def link_rate(self, link_rate: HdmiFrlRate):
|
||||
self.__link_rate.default_value = link_rate.value
|
||||
@@ -0,0 +1,27 @@
|
||||
from UniTAP.dev.modules.dut_tests.test_group_params_types import Param
|
||||
|
||||
|
||||
class HdmiHdcp3ATestParam:
|
||||
"""
|
||||
Class `HdmiHdcp3ATestParam` describes requirement parameters for HDMI HDCP 3A tests:
|
||||
- Set and get `timeout`. Describes test timeout, in milliseconds.
|
||||
"""
|
||||
def __init__(self, json_obj):
|
||||
self.__timeout = Param(json_obj["TSI_HDMI_HDCP_3A_TIMEOUT"])
|
||||
|
||||
@property
|
||||
def timeout(self) -> int:
|
||||
"""
|
||||
Set and get test timeout, in milliseconds.
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__timeout.default_value
|
||||
|
||||
@timeout.setter
|
||||
def timeout(self, timeout: int):
|
||||
if not(self.__timeout.min_value < timeout < self.__timeout.max_value):
|
||||
raise ValueError(f"Timeout cannot be less than {self.__timeout.min_value} and more than "
|
||||
f"{self.__timeout.max_value}.")
|
||||
self.__timeout.default_value = timeout
|
||||
@@ -0,0 +1,27 @@
|
||||
from UniTAP.dev.modules.dut_tests.test_group_params_types import Param
|
||||
|
||||
|
||||
class HdmiHdcp3BTestParam:
|
||||
"""
|
||||
Class `HdmiHdcp3BTestParam` describes requirement parameters for HDMI HDCP 3B tests:
|
||||
- Set and get `timeout`. Describes test timeout, in milliseconds.
|
||||
"""
|
||||
def __init__(self, json_obj):
|
||||
self.__timeout = Param(json_obj["TSI_HDMI_HDCP_3B_TIMEOUT"])
|
||||
|
||||
@property
|
||||
def timeout(self) -> int:
|
||||
"""
|
||||
Set and get test timeout, in milliseconds.
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__timeout.default_value
|
||||
|
||||
@timeout.setter
|
||||
def timeout(self, timeout: int):
|
||||
if not(self.__timeout.min_value < timeout < self.__timeout.max_value):
|
||||
raise ValueError(f"Timeout cannot be less than {self.__timeout.min_value} and more than "
|
||||
f"{self.__timeout.max_value}.")
|
||||
self.__timeout.default_value = timeout
|
||||
@@ -0,0 +1,27 @@
|
||||
from UniTAP.dev.modules.dut_tests.test_group_params_types import Param
|
||||
|
||||
|
||||
class HdmiHdcp3CTestParam:
|
||||
"""
|
||||
Class `HdmiHdcp3CTestParam` describes requirement parameters for HDMI HDCP 3C tests:
|
||||
- Set and get `timeout`. Describes test timeout, in milliseconds.
|
||||
"""
|
||||
def __init__(self, json_obj):
|
||||
self.__timeout = Param(json_obj["TSI_HDMI_HDCP_3C_TIMEOUT"])
|
||||
|
||||
@property
|
||||
def timeout(self) -> int:
|
||||
"""
|
||||
Set and get test timeout, in milliseconds.
|
||||
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__timeout.default_value
|
||||
|
||||
@timeout.setter
|
||||
def timeout(self, timeout: int):
|
||||
if not(self.__timeout.min_value < timeout < self.__timeout.max_value):
|
||||
raise ValueError(f"Timeout cannot be less than {self.__timeout.min_value} and more than "
|
||||
f"{self.__timeout.max_value}.")
|
||||
self.__timeout.default_value = timeout
|
||||
@@ -142,45 +142,25 @@ class DUTTests:
|
||||
- Make report after testing `make_report`.
|
||||
- Run test from file `run_from_file` - Not implemented. Will be added later.
|
||||
"""
|
||||
__DEFAULT_TEST_PARAMETERS = None
|
||||
|
||||
def __init__(self, dev_io: DeviceIO):
|
||||
self.__io = dev_io
|
||||
self.__opf_device = None
|
||||
self.__results = []
|
||||
self.__default_parameters = {}
|
||||
self.__test_groups = {}
|
||||
self.__parser = Parser()
|
||||
|
||||
self.__io.set_test_config(0)
|
||||
cfp_path = os.path.join(os.path.dirname(__file__), 'cfg')
|
||||
files = os.listdir(cfp_path)
|
||||
for file in files:
|
||||
try:
|
||||
if not os.path.isfile(os.path.join(cfp_path, file)):
|
||||
continue
|
||||
|
||||
with open(os.path.join(cfp_path, file), encoding='UTF-8') as cfg_json:
|
||||
json_obj = json.load(cfg_json)
|
||||
item_group = MergedTestGroups(int(json_obj.get('id'), 16))
|
||||
group_type = MERGED_GROUP_PARAMS_TYPE.get(item_group, None)
|
||||
|
||||
if group_type is None:
|
||||
continue
|
||||
|
||||
group_parameters_dict = {}
|
||||
for parameter in json_obj.get('descriptions'):
|
||||
group_parameters_dict[parameter["id"]] = parameter
|
||||
|
||||
self.__default_parameters[group_type] = group_type(group_parameters_dict)
|
||||
except ValueError:
|
||||
logging.info(
|
||||
f"[UniTAP] Failed to load {os.path.join(cfp_path, file)}.\n Value {int(json_obj.get('id'), 16)} is missing in MergedTestGroups.")
|
||||
|
||||
test_list = self.__io.get_test_list()
|
||||
|
||||
for test in test_list:
|
||||
test_id = test[0] & 0xFFFF
|
||||
try:
|
||||
group_id = TestGroupId(test[0] >> 16)
|
||||
except BaseException as e:
|
||||
logging.info(e)
|
||||
continue
|
||||
name = test[2]
|
||||
|
||||
if test[2].find(' / ') != -1:
|
||||
@@ -201,6 +181,49 @@ class DUTTests:
|
||||
|
||||
self.__test_groups[group_id]._add_new_test(Test(name=test_name, test_id=test_id))
|
||||
|
||||
@staticmethod
|
||||
def __enumerate_and_get_default_test_parameters():
|
||||
if DUTTests.__DEFAULT_TEST_PARAMETERS is None:
|
||||
DUTTests.__DEFAULT_TEST_PARAMETERS = {}
|
||||
|
||||
cfp_path = os.path.join(os.path.dirname(__file__), 'cfg')
|
||||
files = os.listdir(cfp_path)
|
||||
for file in files:
|
||||
try:
|
||||
if not os.path.isfile(os.path.join(cfp_path, file)):
|
||||
continue
|
||||
|
||||
with open(os.path.join(cfp_path, file), encoding='UTF-8') as cfg_json:
|
||||
json_obj = json.load(cfg_json)
|
||||
item_group = MergedTestGroups(int(json_obj.get('id'), 16))
|
||||
group_type = MERGED_GROUP_PARAMS_TYPE.get(item_group, None)
|
||||
|
||||
if group_type is None:
|
||||
continue
|
||||
|
||||
group_parameters_dict = {}
|
||||
for parameter in json_obj.get('descriptions'):
|
||||
group_parameters_dict[parameter["id"]] = parameter
|
||||
|
||||
DUTTests.__DEFAULT_TEST_PARAMETERS[group_type] = group_type(group_parameters_dict)
|
||||
except ValueError:
|
||||
logging.info(
|
||||
f"[UniTAP] Failed to load {os.path.join(cfp_path, file)}.\n Value {int(json_obj.get('id'), 16)} is missing in MergedTestGroups.")
|
||||
|
||||
return DUTTests.__DEFAULT_TEST_PARAMETERS
|
||||
|
||||
@staticmethod
|
||||
def __is_dsc_parameters_changed(param: Dp21SourceDUTTestParam):
|
||||
assert isinstance(param, Dp21SourceDUTTestParam)
|
||||
|
||||
result = []
|
||||
dsc_vm_params = vars(param.dsc_video_modes)
|
||||
for key in dsc_vm_params:
|
||||
vm_param_dict = vars(dsc_vm_params[key])
|
||||
result.append(any(vm_param_dict[param_key].is_modified for param_key in vm_param_dict))
|
||||
|
||||
return any(result)
|
||||
|
||||
def run(self, group_id: TestGroupId, test_id: int, params: Optional[DUTTestParameters] = None,
|
||||
print_fw_logs: bool = True, test_delay: int = 0) -> SubTestResultObject:
|
||||
"""
|
||||
@@ -234,8 +257,11 @@ class DUTTests:
|
||||
|
||||
if params is not None:
|
||||
params_list = get_param_list(params)
|
||||
if isinstance(params, Dp21SourceDUTTestParam) and not params.dsc_video_modes._Dp21AvailableDscVideoModes__is_config_changed:
|
||||
logging.warning("Detected that used didn't change new DSC config. Copy setting from video config.")
|
||||
|
||||
#
|
||||
# Backward compatibility with old config
|
||||
#
|
||||
if isinstance(params, Dp21SourceDUTTestParam):
|
||||
dsc_dp2_ci_remapper = {
|
||||
"TSI_DP20_SRCCTS_DSC_VMT_1920_1080_30": "TSI_DP20_SRCCTS_VMT_1920_1080_30",
|
||||
"TSI_DP20_SRCCTS_DSC_VMT_1920_1080_60": "TSI_DP20_SRCCTS_VMT_1920_1080_60",
|
||||
@@ -259,27 +285,33 @@ class DUTTests:
|
||||
"TSI_DP20_SRCCTS_DSC_VMT_10240_4320_60": "TSI_DP20_SRCCTS_VMT_10240_4320_60"
|
||||
}
|
||||
|
||||
if not DUTTests.__is_dsc_parameters_changed(params):
|
||||
logging.warn("Detected that user didn't change new DSC config. Copy setting from video config.")
|
||||
|
||||
for key in dsc_dp2_ci_remapper.keys():
|
||||
dst = next((obj for obj in params_list if obj.config_id_name == key), None)
|
||||
src = next((obj for obj in params_list if obj.config_id_name == dsc_dp2_ci_remapper[key]), None)
|
||||
|
||||
if dst.default_value != src.default_value:
|
||||
logging.warn(f"DSC Config missmatch detected. Apply workaround: {key}:{hex(dst.default_value)}; {dsc_dp2_ci_remapper[key]}:{hex(src.default_value)}")
|
||||
logging.warn(
|
||||
f"DSC Config missmatch detected. Apply workaround: {key}:{hex(dst.default_value)}; {dsc_dp2_ci_remapper[key]}:{hex(src.default_value)}")
|
||||
dst.default_value = src.default_value
|
||||
else:
|
||||
logging.warn(f"DSC Config modification detected. Skip workaround.")
|
||||
else:
|
||||
params_list = self.__default_parameters[merged_group_id]
|
||||
params_list = DUTTests.__enumerate_and_get_default_test_parameters()[merged_group_id]
|
||||
|
||||
for item in params_list:
|
||||
if group_id == TestGroupId.AUDIO_TEST and item.config_id_name == "TSI_REF1_FRAME_DATA":
|
||||
if isinstance(item.default_value, str) and os.path.exists(item.default_value):
|
||||
image_data = read_image_file(item.default_value)
|
||||
image_data, file_extension = read_image_file(item.default_value)
|
||||
if len(image_data) > 0:
|
||||
item.default_value = uicl_image_preparation(image_data, params)
|
||||
# It is assumed that the bin file already contains prepared data,
|
||||
# otherwise there is no way to determine whether additional conversion is required.
|
||||
item.default_value = uicl_image_preparation(image_data, params, file_extension == ".bin")
|
||||
elif isinstance(item, bytearray):
|
||||
# TODO: add 'bytearray' support
|
||||
item.default_value = uicl_image_preparation(item.default_value, params)
|
||||
item.default_value = uicl_image_preparation(item.default_value, params, False)
|
||||
|
||||
self.__io.set(item.config_id, item.default_value, dict_types.get(item.value_type),
|
||||
item.data_length)
|
||||
@@ -320,36 +352,46 @@ class DUTTests:
|
||||
|
||||
return copy.deepcopy(self.__results[-1])
|
||||
|
||||
def get_params_from_file(self, path: str) -> Tuple[TestGroupId, int, DUTTestParameters]:
|
||||
@staticmethod
|
||||
def get_params_from_file(path: str) -> Tuple[TestGroupId, int, DUTTestParameters]:
|
||||
"""
|
||||
Get test parameters from transferred file: td or json (not cdf).
|
||||
|
||||
Args:
|
||||
path ('str') - full path to config file
|
||||
"""
|
||||
self.__parser.set_file_name(path)
|
||||
group_id = self.__parser.detect_group()
|
||||
test_id = self.__parser.detect_test()
|
||||
parser = Parser()
|
||||
|
||||
parser.set_file_name(path)
|
||||
group_id = parser.detect_group()
|
||||
test_id = parser.detect_test()
|
||||
group_type = group_params_dict.get(group_id)
|
||||
params = self.__parser.parse(self.get_default_parameters(group_type))
|
||||
params = parser.parse(DUTTests.get_default_parameters(group_type))
|
||||
|
||||
return group_id, test_id, params
|
||||
|
||||
# TODO - add support parsing '.td' (other test groups) file extension
|
||||
|
||||
def get_params_from_cdf_file(self, path: str) -> DUTTestParameters:
|
||||
@staticmethod
|
||||
def get_params_from_cdf_file(path: str) -> DUTTestParameters:
|
||||
"""
|
||||
Get test parameters from transferred file: json (cdf).
|
||||
|
||||
Args:
|
||||
path ('str') - full path to config file
|
||||
"""
|
||||
self.__parser.set_file_name(path)
|
||||
group_id = self.__parser.detect_merged_group()
|
||||
|
||||
parser = Parser()
|
||||
|
||||
parser.set_file_name(path)
|
||||
group_id = parser.detect_merged_group()
|
||||
group_type = MERGED_GROUP_PARAMS_TYPE.get(group_id)
|
||||
params = self.__parser.parse(self.get_default_parameters(group_type))
|
||||
params = parser.parse(DUTTests.get_default_parameters(group_type))
|
||||
|
||||
return params
|
||||
|
||||
def get_default_parameters(self, group_type: Type[DUTTestParameters]) -> DUTTestParameters:
|
||||
@staticmethod
|
||||
def get_default_parameters(group_type: Type[DUTTestParameters]) -> DUTTestParameters:
|
||||
"""
|
||||
Get predefined (default) parameters of test group.
|
||||
|
||||
@@ -359,9 +401,9 @@ class DUTTests:
|
||||
Returns:
|
||||
object of `DUTTestParameters` type
|
||||
"""
|
||||
for group_id in self.__default_parameters.keys():
|
||||
if isinstance(self.__default_parameters.get(group_id), group_type):
|
||||
return copy.deepcopy(self.__default_parameters.get(group_id))
|
||||
for group_id in DUTTests.__enumerate_and_get_default_test_parameters().keys():
|
||||
if isinstance(DUTTests.__enumerate_and_get_default_test_parameters().get(group_id), group_type):
|
||||
return copy.deepcopy(DUTTests.__enumerate_and_get_default_test_parameters().get(group_id))
|
||||
raise ValueError(f"Group {group_type} is not available.")
|
||||
|
||||
def number_tests_in_group(self, group_id: TestGroupId) -> int:
|
||||
|
||||
@@ -31,7 +31,17 @@ class MergedTestGroups(IntEnum):
|
||||
HDRX_DSC_CTS = 0x20,
|
||||
HDTX_DSC_CTS = 0x21,
|
||||
HDTX_CONTINUITY = 0x22,
|
||||
HDTX_CABLE_CHECK = 0x24
|
||||
HDTX_CABLE_CHECK = 0x24,
|
||||
HDMI_HDCP_CTS_1A = 0x25,
|
||||
HDMI_HDCP_CTS_1B = 0x26,
|
||||
HDMI_HDCP_CTS_2C = 0x27,
|
||||
HDMI_HDCP_CTS_3A = 0x28,
|
||||
HDMI_HDCP_CTS_3B = 0x29,
|
||||
HDMI_HDCP_CTS_3C = 0x2A,
|
||||
DPRX_128b132b_LL_CTS_DEMO = 0x2B,
|
||||
DPTX_128b132b_LL_CTS_DEMO = 0x2C,
|
||||
TIMINGS_VIDEO_TEST = 0x2D,
|
||||
BRANCH_128b132b_MST_CTS = 0x2E
|
||||
|
||||
|
||||
MERGED_GROUP_PARAMS_TYPE = {
|
||||
@@ -60,7 +70,14 @@ MERGED_GROUP_PARAMS_TYPE = {
|
||||
MergedTestGroups.HDRX_DSC_CTS: HdmiSourceDUTTestParam,
|
||||
MergedTestGroups.HDTX_DSC_CTS: HdmiSinkDUTTestParam,
|
||||
MergedTestGroups.HDTX_CONTINUITY: HdmiSinkContinuityDUTTestParam,
|
||||
MergedTestGroups.HDTX_CABLE_CHECK: HdmiSinkCableCheckTestParam
|
||||
MergedTestGroups.HDTX_CABLE_CHECK: HdmiSinkCableCheckTestParam,
|
||||
MergedTestGroups.HDMI_HDCP_CTS_1A: HdmiHdcp1ATestParam,
|
||||
MergedTestGroups.HDMI_HDCP_CTS_1B: HdmiHdcp1BTestParam,
|
||||
MergedTestGroups.HDMI_HDCP_CTS_3A: HdmiHdcp3ATestParam,
|
||||
MergedTestGroups.HDMI_HDCP_CTS_3B: HdmiHdcp3BTestParam,
|
||||
MergedTestGroups.HDMI_HDCP_CTS_2C: HdmiHdcp2CTestParam,
|
||||
MergedTestGroups.HDMI_HDCP_CTS_3C: HdmiHdcp3CTestParam,
|
||||
MergedTestGroups.BRANCH_128b132b_MST_CTS: Dp21BranchMSTSourceDUTTestParam
|
||||
}
|
||||
|
||||
group_params_dict = {
|
||||
@@ -104,7 +121,25 @@ group_params_dict = {
|
||||
TestGroupId.HD_RX_DSC_CTS: HdmiSourceDUTTestParam,
|
||||
TestGroupId.HD_TX_DSC_CTS: HdmiSinkDUTTestParam,
|
||||
TestGroupId.HD_TX_CONTINUITY: HdmiSinkContinuityDUTTestParam,
|
||||
TestGroupId.HD_TX_CABLE_CHECK: HdmiSinkCableCheckTestParam
|
||||
TestGroupId.HD_TX_CABLE_CHECK: HdmiSinkCableCheckTestParam,
|
||||
TestGroupId.HDMI_HDCP_CTS_1A: HdmiHdcp1ATestParam,
|
||||
TestGroupId.HDMI_HDCP_CTS_1B: HdmiHdcp1BTestParam,
|
||||
TestGroupId.HDMI_HDCP_CTS_2C: HdmiHdcp2CTestParam,
|
||||
TestGroupId.HDMI_HDCP_CTS_3A: HdmiHdcp3ATestParam,
|
||||
TestGroupId.HDMI_HDCP_CTS_3B: HdmiHdcp3BTestParam,
|
||||
TestGroupId.HDMI_HDCP_CTS_3C: HdmiHdcp3CTestParam,
|
||||
TestGroupId.DEMO_DP_2_1_TX_DISPAYID: Dp21SinkTestParam,
|
||||
TestGroupId.DEMO_DP_2_1_RX_DISPAYID: Dp21SourceDUTTestParam,
|
||||
TestGroupId.DEMO_DP_2_1_TX_ADAPTIVESYNC: Dp21SinkTestParam,
|
||||
TestGroupId.DEMO_DP_2_1_RX_ADAPTIVESYNC: Dp21SourceDUTTestParam,
|
||||
TestGroupId.DEMO_DP_2_1_RX_LL_CTS: Dp21SourceDUTTestParam,
|
||||
TestGroupId.DEMO_DP_2_1_TX_LL_CTS: Dp21SinkTestParam,
|
||||
TestGroupId.DEMO_DP_2_1_RX_LTTPR_CTS: Dp21SourceDUTTestParam,
|
||||
TestGroupId.DEMO_DP_2_1_TX_LTTPR_CTS: Dp21SinkTestParam,
|
||||
TestGroupId.DEMO_DP_2_1_RX_DSC_CTS: Dp21SourceDUTTestParam,
|
||||
TestGroupId.DEMO_DP_2_1_TX_DSC_CTS: Dp21SinkTestParam,
|
||||
TestGroupId.DP_2_1_RX_MST_CTS: Dp21SourceDUTTestParam,
|
||||
TestGroupId.DP_2_1_BRANCH_MST_CTS: Dp21BranchMSTSourceDUTTestParam
|
||||
}
|
||||
|
||||
|
||||
@@ -127,11 +162,17 @@ def test_group_to_merged_group(fw_group: TestGroupId, test_id: int) -> MergedTes
|
||||
merged_group_id = MergedTestGroups.CRCVideoTest
|
||||
elif fw_group in [TestGroupId.DP_2_1_RX_LL_CTS, TestGroupId.DP_2_1_RX_DSC_CTS,
|
||||
TestGroupId.DP_2_1_RX_LTTPR_CTS, TestGroupId.DP_2_1_RX_DISPAYID,
|
||||
TestGroupId.DP_2_1_RX_ADAPTIVESYNC]:
|
||||
TestGroupId.DP_2_1_RX_ADAPTIVESYNC,
|
||||
TestGroupId.DEMO_DP_2_1_RX_LL_CTS, TestGroupId.DEMO_DP_2_1_RX_DSC_CTS,
|
||||
TestGroupId.DEMO_DP_2_1_RX_LTTPR_CTS, TestGroupId.DEMO_DP_2_1_RX_DISPAYID,
|
||||
TestGroupId.DEMO_DP_2_1_RX_ADAPTIVESYNC, TestGroupId.DP_2_1_RX_MST_CTS]:
|
||||
merged_group_id = MergedTestGroups.DPRX_128b132b_LL_CTS
|
||||
elif fw_group in [TestGroupId.DP_2_1_TX_LL_CTS, TestGroupId.DP_2_1_TX_DSC_CTS,
|
||||
TestGroupId.DP_2_1_TX_LTTPR_CTS, TestGroupId.DP_2_1_TX_DISPAYID,
|
||||
TestGroupId.DP_2_1_TX_ADAPTIVESYNC]:
|
||||
TestGroupId.DP_2_1_TX_ADAPTIVESYNC,
|
||||
TestGroupId.DEMO_DP_2_1_TX_LL_CTS, TestGroupId.DEMO_DP_2_1_TX_DSC_CTS,
|
||||
TestGroupId.DEMO_DP_2_1_TX_LTTPR_CTS, TestGroupId.DEMO_DP_2_1_TX_DISPAYID,
|
||||
TestGroupId.DEMO_DP_2_1_TX_ADAPTIVESYNC]:
|
||||
merged_group_id = MergedTestGroups.DPTX_128b132b_LL_CTS
|
||||
elif fw_group == TestGroupId.DP_2_1_LTTPR_CTS:
|
||||
merged_group_id = MergedTestGroups.LTTPR_128b132b_LL_CTS
|
||||
@@ -169,6 +210,20 @@ def test_group_to_merged_group(fw_group: TestGroupId, test_id: int) -> MergedTes
|
||||
merged_group_id = MergedTestGroups.HDTX_CONTINUITY
|
||||
elif fw_group == TestGroupId.HD_TX_CABLE_CHECK:
|
||||
merged_group_id = MergedTestGroups.HDTX_CABLE_CHECK
|
||||
elif fw_group == TestGroupId.HDMI_HDCP_CTS_1A:
|
||||
merged_group_id = MergedTestGroups.HDMI_HDCP_CTS_1A
|
||||
elif fw_group == TestGroupId.HDMI_HDCP_CTS_1B:
|
||||
merged_group_id = MergedTestGroups.HDMI_HDCP_CTS_1B
|
||||
elif fw_group == TestGroupId.HDMI_HDCP_CTS_2C:
|
||||
merged_group_id = MergedTestGroups.HDMI_HDCP_CTS_2C
|
||||
elif fw_group == TestGroupId.HDMI_HDCP_CTS_3A:
|
||||
merged_group_id = MergedTestGroups.HDMI_HDCP_CTS_3A
|
||||
elif fw_group == TestGroupId.HDMI_HDCP_CTS_3B:
|
||||
merged_group_id = MergedTestGroups.HDMI_HDCP_CTS_3B
|
||||
elif fw_group == TestGroupId.HDMI_HDCP_CTS_3C:
|
||||
merged_group_id = MergedTestGroups.HDMI_HDCP_CTS_3C
|
||||
elif fw_group == TestGroupId.DP_2_1_BRANCH_MST_CTS:
|
||||
merged_group_id = MergedTestGroups.BRANCH_128b132b_MST_CTS
|
||||
else:
|
||||
merged_group_id = MergedTestGroups.Unknown
|
||||
return merged_group_id
|
||||
|
||||
102
UniTAP/dev/modules/dut_tests/report/report_edid_extractor.py
Normal file
102
UniTAP/dev/modules/dut_tests/report/report_edid_extractor.py
Normal file
@@ -0,0 +1,102 @@
|
||||
import re
|
||||
|
||||
class ReportContentExtractor:
|
||||
"""
|
||||
Class `ReportContentExtractor` allows to extract content from test report.
|
||||
- Extracted EDIDs, DisplayIDs from test report.
|
||||
"""
|
||||
__EDID_LINE_PATTERN = re.compile(r"\d{4}.\d{3}.\d{3}:\s+[0-9a-f]{4}:\s+([0-9a-f]{2}\s+)+")
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.__extracting = False
|
||||
self.__edid_addr = 0
|
||||
self.__edid_size = 0
|
||||
self.__edid_ready = False
|
||||
self.__data = bytearray()
|
||||
|
||||
def __start_new_edid(self):
|
||||
self.__extracting = True
|
||||
self.__edid_addr = 0
|
||||
self.__edid_size = 0
|
||||
self.__edid_ready = False
|
||||
self.__data = bytearray()
|
||||
|
||||
def extract_content_from_report(self, report):
|
||||
edids = []
|
||||
for log_line in report.fw_logs.splitlines():
|
||||
self.__parse_line(log_line)
|
||||
if self.__edid_ready and self.__edid_size > 0:
|
||||
edids.append(self.__pop_edid())
|
||||
return edids
|
||||
|
||||
def __parse_line(self, line: str):
|
||||
if not self.__extracting:
|
||||
if ("Reference Source reads Sink DUT EDID" in line
|
||||
or "EDID contents:" in line):
|
||||
self.__start_new_edid()
|
||||
return
|
||||
|
||||
if len(line) < 18:
|
||||
return
|
||||
|
||||
view = line[18:]
|
||||
|
||||
if "I2C AUX WR" in line:
|
||||
sub_strs = view.split()
|
||||
|
||||
if len(sub_strs) <= 3:
|
||||
return
|
||||
|
||||
el = sub_strs[-3]
|
||||
|
||||
if "30h" in el:
|
||||
val = int(sub_strs[-1], 16)
|
||||
self.__edid_addr = val * 0x100
|
||||
elif "50h" in el:
|
||||
val = int(sub_strs[-1], 16)
|
||||
self.__edid_addr = val
|
||||
|
||||
return
|
||||
|
||||
if "I2C AUX RD" in line:
|
||||
sub_strs = view.split()
|
||||
|
||||
if len(sub_strs) <= 3:
|
||||
return
|
||||
|
||||
count = int(sub_strs[4])
|
||||
|
||||
for i in range(count):
|
||||
byte_hex = sub_strs[5 + i]
|
||||
self.__data.append(int(byte_hex, 16))
|
||||
self.__edid_addr += 1
|
||||
|
||||
self.__edid_size = max(self.__edid_size, self.__edid_addr)
|
||||
return
|
||||
|
||||
if self.__EDID_LINE_PATTERN.search(line):
|
||||
if len(line) < 20:
|
||||
return
|
||||
|
||||
view = line[line.rfind(':') + 1:]
|
||||
sub_strs = view.split()
|
||||
|
||||
for byte_hex in sub_strs:
|
||||
self.__data.append(int(byte_hex, 16))
|
||||
self.__edid_addr += 1
|
||||
|
||||
self.__edid_size = max(self.__edid_size, self.__edid_addr)
|
||||
return
|
||||
|
||||
self.__edid_ready = True
|
||||
self.__extracting = False
|
||||
|
||||
def __pop_edid(self):
|
||||
if self.__edid_ready and self.__edid_size > 0:
|
||||
edid = self.__data[:self.__edid_size].hex()
|
||||
self.__edid_ready = False
|
||||
self.__edid_size = 0
|
||||
self.__data = bytearray()
|
||||
self.__edid_addr = 0
|
||||
return edid
|
||||
return bytearray()
|
||||
@@ -1,8 +1,10 @@
|
||||
import os
|
||||
import platform
|
||||
from datetime import datetime
|
||||
from enum import IntEnum
|
||||
|
||||
from .report_template import *
|
||||
from .report_edid_extractor import ReportContentExtractor
|
||||
|
||||
|
||||
class TestResult(IntEnum):
|
||||
@@ -59,12 +61,48 @@ def replace_additional_info(test_additional_info: TestAdditionalInfo):
|
||||
return result
|
||||
|
||||
|
||||
def to_intel_hex(edid_hex: str) -> str:
|
||||
data = bytes.fromhex(edid_hex)
|
||||
lines = []
|
||||
for offset in range(0, len(data), 16):
|
||||
chunk = data[offset:offset + 16]
|
||||
byte_count = len(chunk)
|
||||
addr_hi = (offset >> 8) & 0xFF
|
||||
addr_lo = offset & 0xFF
|
||||
record = [byte_count, addr_hi, addr_lo, 0x00] + list(chunk)
|
||||
checksum = (~sum(record) + 1) & 0xFF
|
||||
hex_str = ''.join(f'{b:02X}' for b in record) + f'{checksum:02X}'
|
||||
lines.append(f':{hex_str}')
|
||||
lines.append(':00000001FF')
|
||||
return ('\r\n'.join(lines) + '\r\n').encode('utf-8').hex().upper()
|
||||
|
||||
|
||||
def generate_html_report(path: str, test_additional_info: TestAdditionalInfo, reports: list):
|
||||
result = str()
|
||||
|
||||
head = ReportHead
|
||||
head = head.replace("#count#", str((len(reports) + 2)))
|
||||
|
||||
for index, report in enumerate(reports):
|
||||
extractor = ReportContentExtractor()
|
||||
edid_displaid_content = extractor.extract_content_from_report(report)
|
||||
|
||||
if edid_displaid_content is None or len(edid_displaid_content) <= 0:
|
||||
continue
|
||||
|
||||
formatted_edids = '["' + '",\n "'.join(edid_displaid_content).upper() + '"]'
|
||||
formatted_edids_intel_hex = '["' + '",\n "'.join(to_intel_hex(edid) for edid in edid_displaid_content) + '"]'
|
||||
test_name_formatted = report.test_name.split(' ')[0].replace('.', '_')
|
||||
|
||||
if len(edid_displaid_content) > 0:
|
||||
head = head.replace("#edid_fill#", f"testsEdidData.set({index}, {{name: \"{test_name_formatted}\", data: {formatted_edids}, dataIntelHex: {formatted_edids_intel_hex}}}); \n#edid_fill#")
|
||||
break
|
||||
|
||||
head = head.replace("#edid_fill#", "")
|
||||
head = head.replace("#jsCode#", report_js)
|
||||
head = head.replace("#count#", str(len(reports) + 2))
|
||||
head = head.replace("#fileNamePrefix#", os.path.splitext(os.path.basename(path))[0])
|
||||
|
||||
body = ReportBody
|
||||
body = body.replace("#device_description#", replace_additional_info(test_additional_info))
|
||||
|
||||
@@ -105,7 +143,7 @@ def generate_html_report(path: str, test_additional_info: TestAdditionalInfo, re
|
||||
line = OptionListLine
|
||||
line = line.replace("#number#", str(i + 2))
|
||||
line = line.replace("#test_name#", f"{reports[i].group_name} / {reports[i].test_name}")
|
||||
line = line.replace("#test_result#", dict_result_2.get(reports[i].test_result))
|
||||
line = line.replace("#test_result#", dict_result_2.get(reports[i].test_result, "UNKNOWN"))
|
||||
options_list += line + "\n"
|
||||
|
||||
body = body.replace("#optionList#", options_list)
|
||||
@@ -117,7 +155,7 @@ def generate_html_report(path: str, test_additional_info: TestAdditionalInfo, re
|
||||
line = line.replace("#handler_number#", str(i + 2))
|
||||
line = line.replace("#test_name#", reports[i].test_name)
|
||||
line = line.replace("#test_group#", reports[i].group_name)
|
||||
line = line.replace("#test_result#", dict_result_2.get(reports[i].test_result))
|
||||
line = line.replace("#test_result#", dict_result_2.get(reports[i].test_result, "UNKNOWN"))
|
||||
line = line.replace("#error#", f"{reports[i].error_code}" if reports[i].error_code != 0 else "-")
|
||||
line = line.replace("#ending#", "2" if i % 2 else "")
|
||||
test_result = dict_result_2.get(reports[i].test_result)
|
||||
@@ -153,14 +191,17 @@ def generate_html_report(path: str, test_additional_info: TestAdditionalInfo, re
|
||||
line = line.replace("#test_number#", f"{i + 1}")
|
||||
line = line.replace("#test_group#", reports[i].group_name)
|
||||
line = line.replace("#test_name#", reports[i].test_name)
|
||||
line = line.replace("#result#", dict_result_2.get(reports[i].test_result))
|
||||
line = line.replace("#result#", dict_result_2.get(reports[i].test_result, "UNKNOWN"))
|
||||
line = line.replace("#test_delay#", f"{reports[i].test_delay * 1000}")
|
||||
line = line.replace("#test_parameters#", reports[i].config_info)
|
||||
line = line.replace("#warning#", "<b>Debug options enabled!</b><br><br>" if reports[i].debug else "")
|
||||
|
||||
if reports[i].debug:
|
||||
if "demo" in reports[i].group_name.lower():
|
||||
warnings = "<b>Demo Report Only - Not valid for DP Logo Certification.</b><br><br>"
|
||||
elif reports[i].debug:
|
||||
warnings = "<b>Debug options enabled!</b><br><br>"
|
||||
|
||||
line = line.replace("#warning#", warnings)
|
||||
|
||||
line = line.replace("#test_log#", escape_html(reports[i].fw_logs))
|
||||
tables_list += line + "\n"
|
||||
|
||||
|
||||
@@ -14,23 +14,29 @@ ReportHead = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\
|
||||
" PRE.TESTBODY{margin-top: 0;margin-bottom: 0;margin-left: 1.0cm;font-weight: medium;font-family: \"Courier New\";font-size: 11pt;color: #000000;}\n" \
|
||||
" P.BODYDETAILTEXT{margin-top: 0;margin-bottom: 0;margin-left: 1.4cm;font-weight: medium;font-family: \"Arial\";font-size: 9pt;color: #000000;}\n" \
|
||||
" P.CONTENTS SELECT{font-weight: normal;font-family: \"Arial\";font-size: 11pt;width: 98%;margin-top: 0;text-align: left;}\n" \
|
||||
"P.TABLE_HEADERS{background-color: #DCFABC;margin-top: 0;margin-bottom: 0;margin-left: 1.0cm;font-weight: " \
|
||||
"medium;font-family: \"Arial\";font-size: 12pt;color: #000000;}\n" \
|
||||
" P.TABLE_HEADERS{background-color: #DCFABC;margin-top: 0;margin-bottom: 0;margin-left: 1.0cm;font-weight: medium;font-family: \"Arial\";font-size: 12pt;color: #000000;}\n" \
|
||||
" P.TABLE_LINKS{margin-top: 0;margin-bottom: 0;margin-left: 1.0cm;font-weight: medium;font-family: \"Arial\";font-size: 11pt;}\n" \
|
||||
" P.TABLE_LINKS2{margin-top: 0;margin-bottom: 0;margin-left: 1.0cm;font-weight: medium;font-family: \"Arial\";font-size: 11pt; background-color: #DDDDDD;}\n" \
|
||||
" P.FAILED{margin-top: 0;margin-bottom: 0;background-color: #FFBCBC; font-weight: bold;font-family: \"Arial\";font-size: 11pt;color: #000000;}\n" \
|
||||
" P.PASSED{margin-top: 0;margin-bottom: 0;background-color: #BCFFBC; font-weight: bold;font-family: \"Arial\";font-size: 11pt;color: #000000;}\n" \
|
||||
" P.SKIPPED{margin-top: 0;margin-bottom: 0;background-color: #BCBCBC; font-weight: bold;font-family: \"Arial\";font-size: 11pt;color: #000000;}\n" \
|
||||
" P.ERROR_CODE{margin-top: 0;margin-bottom: 0;background-color: #FFFFFF; font-weight: bold;font-family: \"Arial\";font-size: 11pt;color: #000000;}\n" \
|
||||
" P.ABORTED{margin-top: 0;margin-bottom: 0;background-color: #FFFFFF; font-weight: bold;font-family: \"Arial\";font-size: 11pt;color: #000000;}\n" \
|
||||
" .TOPBUTTON{display: none; position: fixed; bottom: 20px; right: 30px; z-index: 99; font-size: 18px; border: solid black 1px; outline: none; background-color: #DCFABC; cursor: pointer; padding: 15px; border-radius: 5px;}\n" \
|
||||
" .DBG_HIGHLIGHT { color: #ff0000;}\n" \
|
||||
" .flex-container {\n" \
|
||||
" display: flex;\n" \
|
||||
" gap: 5px;\n" \
|
||||
" }\n" \
|
||||
"</style>\n" \
|
||||
"<script src=\"https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js\"></script>" \
|
||||
"<script type=\"text/javascript\">\n" \
|
||||
"var base64Content = #configInfo#;\n" \
|
||||
"window.current_index = 2;\n" \
|
||||
"window.min_value = 2;\n" \
|
||||
"window.max_value = #count# - 1;\n" \
|
||||
"window.onscroll = function() {scrollFunction()};\n" \
|
||||
"let testsEdidData = new Map();\n" \
|
||||
"#edid_fill#\n\n" \
|
||||
"function Hide(iElementIndex) { document.getElementById(\"ID\"+iElementIndex).style.display = 'none'; }\n" \
|
||||
"function Show(iElementIndex) { document.getElementById(\"ID\"+iElementIndex).style.display = 'inline'; }\n" \
|
||||
"function HideAll(iDivCount) { for(var i=0;i<iDivCount;i++) { Hide(i); }}\n" \
|
||||
@@ -39,7 +45,17 @@ ReportHead = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\
|
||||
"function GetIndex() { return parseInt(window.current_index, 10); }\n" \
|
||||
"function HideButtons() { document.getElementById(\"top_buttons\").style.display = 'none'; document.getElementById(\"bottom_buttons\").style.display = 'none'; }\n" \
|
||||
"function ShowButtons() { document.getElementById(\"top_buttons\").style.display = 'inline'; document.getElementById(\"bottom_buttons\").style.display = 'inline';} \n" \
|
||||
"function UpdateButtonsState() { GetIndex() >= window.min_value && window.max_value ? ShowButtons() : HideButtons(); }\n" \
|
||||
"function ShowHideEdidBtn() {\n" \
|
||||
" let index = GetIndex();\n" \
|
||||
" let edidBtnVisibility = 'none';\n" \
|
||||
" if (index < window.min_value || index > window.max_value) {\n" \
|
||||
" if (testsEdidData.size > 0) edidBtnVisibility = 'inline';\n }" \
|
||||
" else if (testsEdidData.has(index)) edidBtnVisibility = 'inline';\n" \
|
||||
" document.getElementById(\"save_edid_btn\").style.display = edidBtnVisibility;\n" \
|
||||
" document.getElementById(\"save_edid_intel_hex_btn\").style.display = edidBtnVisibility;\n" \
|
||||
"}\n" \
|
||||
"function UpdateButtonsState() { GetIndex() >= window.min_value && window.max_value ? ShowButtons() : HideButtons();\n" \
|
||||
" ShowHideEdidBtn(); }\n" \
|
||||
"function ListHandler (iOptionValue) { if(iOptionValue==-1) { ShowAll(#count#); Hide(1); SetIndex(1); UpdateButtonsState(); return; } HideAll(#count#); Show(iOptionValue); SetIndex(iOptionValue > 1 ? iOptionValue : 1); UpdateButtonsState();}\n" \
|
||||
"function NextTest() { var index = GetIndex(); ListHandler ((index + 1 > window.max_value) ? (window.min_value) : (index + 1)); }\n" \
|
||||
"function PreviousTest() { var index = GetIndex(); ListHandler ((index - 1 < window.min_value) ? (window.max_value) : (index - 1)); }\n" \
|
||||
@@ -47,6 +63,7 @@ ReportHead = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\
|
||||
"function TopFunction() { document.body.scrollTop = 0; document.documentElement.scrollTop = 0;}\n" \
|
||||
"function SaveConfig() { var jsonData = atob(base64Content[GetIndex()-2]); var blob = new Blob([jsonData], { type: 'application/json' }); var link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); var currentPageURL = window.location.href; var decodedURL = decodeURIComponent(currentPageURL); link.download = getText() + \".json\"; document.body.appendChild(link); link.click(); document.body.removeChild(link); }\n" \
|
||||
"function getText() { var index = GetIndex(); let a = document.getElementById(\"testlist\"); let option = a.options[index]; return option.text.replace('/', '').replace('>', '').replace(':', '') }\n" \
|
||||
"#jsCode#" \
|
||||
"</script>\n" \
|
||||
"</head>\n"
|
||||
|
||||
@@ -115,17 +132,23 @@ ReportBody = "<body onload='ListHandler(0);'>\n" \
|
||||
" <option value=\"0\">Report Summary</option>\n" \
|
||||
" <option value=\"1\">Test Summary</option>\n" \
|
||||
"#optionList#\n" \
|
||||
" <option value=\"-1\">Show everything</option>\n" \
|
||||
" <option value=\"-1\">Show All</option>\n" \
|
||||
" </select>\n" \
|
||||
" </td>\n" \
|
||||
" </table>\n" \
|
||||
"<div id=\"top_buttons\" style='margin-left: 12'>\n" \
|
||||
"<div class='flex-container'>" \
|
||||
" <div id=\"top_buttons\">\n" \
|
||||
" <button type=\"button\" onclick=\"PreviousTest()\">Previous</button>\n" \
|
||||
" <button type=\"button\" onclick=\"ListHandler(1)\">Summary</button>\n" \
|
||||
" <button type=\"button\" onclick=\"SaveConfig()\">Save Test Config</button>\n" \
|
||||
" <button type=\"button\" onclick=\"NextTest()\">Next</button>\n" \
|
||||
" </div>\n" \
|
||||
" <div>\n" \
|
||||
" <button type=\"button\" id=\"save_edid_btn\" onclick=\"SaveEdid()\">Save EDID as bin</button>\n" \
|
||||
" <button type=\"button\" id=\"save_edid_intel_hex_btn\" onclick=\"SaveEdidIntelHex()\">Save EDID as intel hex</button>\n" \
|
||||
" <br>\n" \
|
||||
" </div>\n" \
|
||||
"</div>\n" \
|
||||
"<br>\n" \
|
||||
"<div id=\"ID0\">\n" \
|
||||
"<p class=\"SUBHEADING\" style=\"margin-left: 0; margin-top: 0;\"> Report summary</p>\n" \
|
||||
@@ -151,3 +174,134 @@ ReportFooter = "<br><br></pre></div>\n" \
|
||||
" </p>\n" \
|
||||
"</body>\n" \
|
||||
"</html>\n"
|
||||
|
||||
report_js = """
|
||||
function hexToUint8Array(hex) {
|
||||
const clean = hex.replace(/\s+/g, '');
|
||||
const bytes = new Uint8Array(clean.length / 2);
|
||||
|
||||
for (let i = 0; i < clean.length; i += 2) {
|
||||
bytes[i / 2] = parseInt(clean.substr(i, 2), 16);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function saveBlob(blob, fileName) {
|
||||
const a = document.createElement('a');
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
a.href = url;
|
||||
a.download = fileName;
|
||||
a.style.display = 'none';
|
||||
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
|
||||
setTimeout(() => {
|
||||
URL.revokeObjectURL(url);
|
||||
a.remove();
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
async function saveZip(files, zipName) {
|
||||
const zip = new JSZip();
|
||||
|
||||
for (const file of files) {
|
||||
zip.file(file.name, file.data, {
|
||||
binary: true
|
||||
});
|
||||
}
|
||||
|
||||
const uint8 = await zip.generateAsync({
|
||||
type: 'uint8array',
|
||||
compression: 'STORE'
|
||||
});
|
||||
|
||||
const blob = new Blob([uint8], { type: 'application/zip' });
|
||||
saveBlob(blob, zipName);
|
||||
}
|
||||
|
||||
async function saveFiles(getFileList, zipName, mimeType) {
|
||||
const files = getFileList();
|
||||
|
||||
if (files.length === 1) {
|
||||
saveBlob(
|
||||
new Blob([files[0].data], { type: mimeType }),
|
||||
files[0].name
|
||||
);
|
||||
} else if (files.length > 1) {
|
||||
await saveZip(files, zipName);
|
||||
}
|
||||
}
|
||||
|
||||
function getEdidBinFiles() {
|
||||
let index = GetIndex();
|
||||
const files = [];
|
||||
|
||||
if (index < window.min_value || index > window.max_value) {
|
||||
for (const [key, value] of testsEdidData) {
|
||||
for (let i = 0; i < value.data.length; ++i) {
|
||||
files.push({
|
||||
name: `#fileNamePrefix#_Test${key}_${value.name}_EDID_${i}.bin`,
|
||||
data: hexToUint8Array(value.data[i])
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (testsEdidData.has(index)) {
|
||||
const testData = testsEdidData.get(index);
|
||||
|
||||
for (let i = 0; i < testData.data.length; ++i) {
|
||||
files.push({
|
||||
name: `#fileNamePrefix#_Test_${testData.name}_EDID_${i}.bin`,
|
||||
data: hexToUint8Array(testData.data[i])
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
function getEdidIntelHexFiles() {
|
||||
let index = GetIndex();
|
||||
const files = [];
|
||||
|
||||
if (index < window.min_value || index > window.max_value) {
|
||||
for (const [key, value] of testsEdidData) {
|
||||
for (let i = 0; i < value.dataIntelHex.length; ++i) {
|
||||
files.push({
|
||||
name: `#fileNamePrefix#_Test${key}_${value.name}_EDID_${i}.hex`,
|
||||
data: hexToUint8Array(value.dataIntelHex[i])
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (testsEdidData.has(index)) {
|
||||
const testData = testsEdidData.get(index);
|
||||
|
||||
for (let i = 0; i < testData.dataIntelHex.length; ++i) {
|
||||
files.push({
|
||||
name: `#fileNamePrefix#_Test_${testData.name}_EDID_${i}.hex`,
|
||||
data: hexToUint8Array(testData.dataIntelHex[i])
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
async function SaveEdid() {
|
||||
await saveFiles(
|
||||
getEdidBinFiles,
|
||||
'#fileNamePrefix#_EDID_BIN.zip',
|
||||
'application/octet-stream'
|
||||
);
|
||||
}
|
||||
|
||||
async function SaveEdidIntelHex() {
|
||||
await saveFiles(
|
||||
getEdidIntelHexFiles,
|
||||
'#fileNamePrefix#_EDID_HEX.zip',
|
||||
'application/octet-stream'
|
||||
);
|
||||
}
|
||||
"""
|
||||
|
||||
@@ -121,6 +121,8 @@ class Param:
|
||||
|
||||
self.__process_value(json_obj)
|
||||
|
||||
self.__modified = False
|
||||
|
||||
def _set_by_bitmask(self, value, bitmask_index):
|
||||
if len(self.__bit_field_list) > bitmask_index:
|
||||
mask = self.__bit_field_list[bitmask_index].mask
|
||||
@@ -149,12 +151,17 @@ class Param:
|
||||
def direct_set_def_value(self, default_value):
|
||||
self.__default_value = default_value
|
||||
|
||||
def direct_set_bits_value(self, mask: int, value: int, shift: int = 0):
|
||||
cleared = self.__default_value & ~mask
|
||||
self.__default_value = cleared | (value << shift)
|
||||
|
||||
@property
|
||||
def default_value(self):
|
||||
return self.__default_value
|
||||
|
||||
@default_value.setter
|
||||
def default_value(self, default_value):
|
||||
self.__modified = True
|
||||
if self.__enumeration_variants is not None:
|
||||
if str(default_value) in self.__enumeration_variants.available_values:
|
||||
self.__default_value = default_value
|
||||
@@ -203,6 +210,10 @@ class Param:
|
||||
else:
|
||||
return 1
|
||||
|
||||
@property
|
||||
def is_modified(self):
|
||||
return self.__modified
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.default_value if self.data_length <= 50 else self.default_value[:50]}"
|
||||
|
||||
@@ -274,25 +285,28 @@ def param_by_ci_name(json_obj, name: str) -> Param:
|
||||
return Param({})
|
||||
|
||||
|
||||
def read_image_file(full_filename: str) -> bytearray:
|
||||
def read_image_file(full_filename: str) -> [bytearray, str]:
|
||||
file_name, file_extension = os.path.splitext(full_filename)
|
||||
if file_extension.lower() == '.bin':
|
||||
with open(full_filename, 'rb') as file:
|
||||
image_data = bytearray(file.read())
|
||||
return image_data
|
||||
return image_data, file_extension
|
||||
elif file_extension.lower() in [".png", '.jpg', ".ppm", '.bmp', '.tif', '.tiff']:
|
||||
image = Image.open(full_filename)
|
||||
image = image.convert('RGB')
|
||||
image_data = bytearray(image.tobytes())
|
||||
return image_data
|
||||
return image_data, file_extension
|
||||
else:
|
||||
return bytearray()
|
||||
return bytearray(), file_extension
|
||||
|
||||
|
||||
def uicl_image_preparation(data: bytearray, params):
|
||||
def uicl_image_preparation(data: bytearray, params, is_prepared):
|
||||
ref_image = UICL_Image()
|
||||
ref_param = UICL_ImageParameters()
|
||||
|
||||
if is_prepared:
|
||||
return list(data)
|
||||
|
||||
ref_param.Width = params.image_width
|
||||
ref_param.Height = params.image_height
|
||||
# VideoPixelTestElementFormat: RGB_16BPC = 20
|
||||
|
||||
@@ -58,6 +58,26 @@ class TestGroupId(IntEnum):
|
||||
HD_TX_DSC_CTS = 0x41
|
||||
HD_TX_CONTINUITY = 0x42
|
||||
HD_TX_CABLE_CHECK = 0x43
|
||||
HDMI_HDCP_CTS_1A = 0x44
|
||||
HDMI_HDCP_CTS_1B = 0x45
|
||||
HDMI_HDCP_CTS_2C = 0x46
|
||||
HDMI_HDCP_CTS_3A = 0x47
|
||||
HDMI_HDCP_CTS_3B = 0x48
|
||||
HDMI_HDCP_CTS_3C = 0x49
|
||||
DP_2_1_RX_MST_CTS = 0x4A,
|
||||
DEMO_DP_2_1_TX_DISPAYID = 0x4B,
|
||||
DEMO_DP_2_1_RX_DISPAYID = 0x4C,
|
||||
DEMO_DP_2_1_TX_ADAPTIVESYNC = 0x4D,
|
||||
DEMO_DP_2_1_RX_ADAPTIVESYNC = 0x4E,
|
||||
DEMO_DP_2_1_RX_LL_CTS = 0x4F,
|
||||
DEMO_DP_2_1_TX_LL_CTS = 0x50,
|
||||
DEMO_DP_2_1_RX_LTTPR_CTS = 0x51,
|
||||
DEMO_DP_2_1_TX_LTTPR_CTS = 0x52,
|
||||
DEMO_DP_2_1_RX_DSC_CTS = 0x53,
|
||||
DEMO_DP_2_1_TX_DSC_CTS = 0x54,
|
||||
DP_2_1_BRANCH_MST_CTS = 0x55,
|
||||
HDMI_TIMINGS_TEST_SUIT = 0x59,
|
||||
DP_TIMINGS_TEST_SUIT = 0x5A,
|
||||
PIXEL_VIDEO_TEST = 0x3E8
|
||||
HDR10_TEST = -2
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@ from typing import List
|
||||
from ctypes import c_uint64, c_uint32, c_uint8
|
||||
from enum import IntEnum
|
||||
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_R_MEMORY_SIZE, TSI_MEMORY_LAYOUT,\
|
||||
TSI_MEMORY_BLOCK_INDEX, TSI_MEMORY_RESET_W, TSI_MEMORY_WRITE_W
|
||||
from UniTAP.libs.lib_tsi.tsi import TSIX_TS_GetConfigItem, TSIX_TS_SetConfigItem
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from UniTAP.libs.lib_tsi.tsi_io import DeviceIO
|
||||
|
||||
|
||||
@@ -16,31 +14,31 @@ class MemoryManager:
|
||||
|
||||
MAX_BLOCK_COUNT = 4
|
||||
|
||||
DEFAULT_MEMOTY_ALLOCATION = [534600704, 534600704, 534600704]
|
||||
DEFAULT_MEMOTY_ALLOCATION = [534600704, 534600704, 2048]
|
||||
RESERVED_MEMORY_BYTES = 8192 * (5120 + 1) * 4 + 0x80000
|
||||
|
||||
def __init__(self, io: DeviceIO):
|
||||
self.__io = io
|
||||
|
||||
def get_total_memory(self) -> int:
|
||||
result = self.__io.get(TSI_R_MEMORY_SIZE, c_uint64)[1]
|
||||
result = self.__io.get(ci.TSI_R_MEMORY_SIZE, c_uint64)[1]
|
||||
return result
|
||||
|
||||
def set_memory_layout(self, layout: List[int]):
|
||||
self.__io.set(TSI_MEMORY_LAYOUT, layout, c_uint64, data_count=len(layout))
|
||||
self.__io.set(ci.TSI_MEMORY_LAYOUT, layout, c_uint64, data_count=len(layout))
|
||||
|
||||
def get_memory_layout(self) -> List[int]:
|
||||
return self.__io.get(TSI_MEMORY_LAYOUT, c_uint64, self.MAX_BLOCK_COUNT)
|
||||
return list(self.__io.get(ci.TSI_MEMORY_LAYOUT, c_uint64, self.MAX_BLOCK_COUNT)[1])
|
||||
|
||||
def set_memory_block_index(self, index: MemoryOwner):
|
||||
self.__io.set(TSI_MEMORY_BLOCK_INDEX, index.value)
|
||||
self.__io.set(ci.TSI_MEMORY_BLOCK_INDEX, index.value)
|
||||
|
||||
def make_default(self):
|
||||
self.__io.set(TSI_MEMORY_LAYOUT, self.DEFAULT_MEMOTY_ALLOCATION, c_uint64,
|
||||
self.__io.set(ci.TSI_MEMORY_LAYOUT, self.DEFAULT_MEMOTY_ALLOCATION, c_uint64,
|
||||
data_count=len(self.DEFAULT_MEMOTY_ALLOCATION))
|
||||
|
||||
def reset(self):
|
||||
self.__io.set(TSI_MEMORY_RESET_W, 0)
|
||||
self.__io.set(ci.TSI_MEMORY_RESET_W, 0)
|
||||
|
||||
def memory_write(self, data, size):
|
||||
self.__io.set(TSI_MEMORY_WRITE_W, bytearray(data), data_type=c_uint8, data_count=size)
|
||||
self.__io.set(ci.TSI_MEMORY_WRITE_W, bytearray(data), data_type=c_uint8, data_count=size)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import platform
|
||||
import warnings
|
||||
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_OPF_CALLBACK_STRUCT, TSI_OPF_RETURN_CODE_ABORT
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from UniTAP.libs.lib_tsi.tsi_io import DeviceIO
|
||||
from UniTAP.utils import tsi_logging as logging
|
||||
from .handlers import OpfHandlerBase, OpfHandlerDefault
|
||||
@@ -9,11 +9,11 @@ from .handlers import OpfHandlerBase, OpfHandlerDefault
|
||||
if platform.system() == 'Windows':
|
||||
from ctypes import c_int, POINTER, c_void_p, WINFUNCTYPE
|
||||
|
||||
OPF_CALLBACK_TYPE = WINFUNCTYPE(c_int, POINTER(TSI_OPF_CALLBACK_STRUCT), c_void_p)
|
||||
OPF_CALLBACK_TYPE = WINFUNCTYPE(c_int, POINTER(ci.TSI_OPF_CALLBACK_STRUCT), c_void_p)
|
||||
else:
|
||||
from ctypes import c_int, POINTER, c_void_p, CFUNCTYPE
|
||||
|
||||
OPF_CALLBACK_TYPE = CFUNCTYPE(c_int, POINTER(TSI_OPF_CALLBACK_STRUCT), c_void_p)
|
||||
OPF_CALLBACK_TYPE = CFUNCTYPE(c_int, POINTER(ci.TSI_OPF_CALLBACK_STRUCT), c_void_p)
|
||||
|
||||
|
||||
class OperatorFeedbackHandler:
|
||||
@@ -33,8 +33,8 @@ class OperatorFeedbackHandler:
|
||||
self.__handler = OpfHandlerDefault()
|
||||
|
||||
def __get_callback(self):
|
||||
def ofp_impl(_struct: POINTER(TSI_OPF_CALLBACK_STRUCT), context_ptr: c_void_p):
|
||||
opf_struct: TSI_OPF_CALLBACK_STRUCT = _struct.contents
|
||||
def ofp_impl(_struct: POINTER(ci.TSI_OPF_CALLBACK_STRUCT), context_ptr: c_void_p):
|
||||
opf_struct: ci.TSI_OPF_CALLBACK_STRUCT = _struct.contents
|
||||
logging.debug(f"Received OPF dialog with ID: {opf_struct.id()}, Session: {opf_struct.session_id()}.")
|
||||
|
||||
try:
|
||||
@@ -46,7 +46,7 @@ class OperatorFeedbackHandler:
|
||||
opf_struct.parameters())
|
||||
except BaseException as e:
|
||||
warnings.warn(f"OPF Dialog {opf_struct.id()} was aborted due an exception. Exception: {e}")
|
||||
return opf_struct.write_opf_result(TSI_OPF_RETURN_CODE_ABORT)
|
||||
return opf_struct.write_opf_result(ci.TSI_OPF_RETURN_CODE_ABORT)
|
||||
|
||||
return ofp_impl
|
||||
|
||||
|
||||
@@ -30,6 +30,9 @@ class OpfHandlerInternal(OpfHandlerBase):
|
||||
19: OPFFunctions.opf_19_handler,
|
||||
20: OPFFunctions.opf_20_handler,
|
||||
21: OPFFunctions.opf_21_handler,
|
||||
22: OPFFunctions.opf_22_handler,
|
||||
23: OPFFunctions.opf_23_handler,
|
||||
24: OPFFunctions.opf_24_handler,
|
||||
101: OPFFunctions.opf_101_handler,
|
||||
102: OPFFunctions.opf_102_handler,
|
||||
103: OPFFunctions.opf_103_handler,
|
||||
@@ -37,6 +40,7 @@ class OpfHandlerInternal(OpfHandlerBase):
|
||||
105: OPFFunctions.opf_105_handler,
|
||||
106: OPFFunctions.opf_106_handler,
|
||||
107: OPFFunctions.opf_107_handler,
|
||||
108: OPFFunctions.opf_108_handler,
|
||||
120: OPFFunctions.opf_120_handler,
|
||||
121: OPFFunctions.opf_121_handler,
|
||||
122: OPFFunctions.opf_122_handler,
|
||||
@@ -47,6 +51,8 @@ class OpfHandlerInternal(OpfHandlerBase):
|
||||
143: OPFFunctions.opf_143_handler,
|
||||
144: OPFFunctions.opf_144_handler,
|
||||
145: OPFFunctions.opf_145_handler,
|
||||
146: OPFFunctions.opf_146_handler,
|
||||
147: OPFFunctions.opf_147_handler,
|
||||
150: OPFFunctions.opf_150_handler,
|
||||
161: OPFFunctions.opf_161_handler
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import copy
|
||||
import math
|
||||
import re
|
||||
import threading
|
||||
import time
|
||||
@@ -17,22 +18,19 @@ from UniTAP.utils.function_wrapper import function_scheduler
|
||||
from UniTAP.libs.lib_dscl.dscl import DSC_TOOLS_FOLDER, DSCL_ExtractPPSFromData, DSCL_Encode, DSCL_Decode
|
||||
from UniTAP.libs.lib_dscl.dscl_utils import calculate_slice_size, dscl_image_to_dsc_vf
|
||||
from UniTAP.libs.lib_pdl.pdl import generate_pattern_as_vf, PatternType
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_MEMORY_WRITE_W, TSI_MEMORY_BLOCK_INDEX, TSI_MEMORY_LAYOUT, \
|
||||
TSI_DP20_SINKCTS_SUPPORT_444CRC, TSI_DP14_SINKCTS_SUPPORT_444CRC
|
||||
from UniTAP.libs.lib_tsi.tsi_private_types import TSI_DSC_MEMORY_BLOCK, TSI_DSC_DATA_SIZE, \
|
||||
TSI_DSC_TX_CRC, TSI_DPRX_DSC_TEST_CRC, TSI_SELECT_SUITE
|
||||
from UniTAP.libs.lib_tsi.tsi import TSIX_TS_SetConfigItem, TSIX_TS_GetConfigItem
|
||||
import UniTAP.libs.lib_tsi.tsi as tsi
|
||||
from ctypes import c_uint64, c_uint32
|
||||
from UniTAP.libs.lib_tsi import TSI_OPF_RETURN_CODE_ABORT, TSI_OPF_RETURN_CODE_PASS, \
|
||||
TSI_OPF_RETURN_CODE_PROCEED, TSI_OPF_RETURN_CODE_FAIL, TSI_OPF_RETURN_CODE_AUTO_CLOSED
|
||||
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
|
||||
|
||||
class OPFDialogAnswer(IntEnum):
|
||||
ABORT = TSI_OPF_RETURN_CODE_ABORT
|
||||
PASS = TSI_OPF_RETURN_CODE_PASS
|
||||
PROCEED = TSI_OPF_RETURN_CODE_PROCEED
|
||||
FAIL = TSI_OPF_RETURN_CODE_FAIL
|
||||
NOTHING = TSI_OPF_RETURN_CODE_AUTO_CLOSED
|
||||
ABORT = ci.TSI_OPF_RETURN_CODE_ABORT
|
||||
PASS = ci.TSI_OPF_RETURN_CODE_PASS
|
||||
PROCEED = ci.TSI_OPF_RETURN_CODE_PROCEED
|
||||
FAIL = ci.TSI_OPF_RETURN_CODE_FAIL
|
||||
NOTHING = ci.TSI_OPF_RETURN_CODE_AUTO_CLOSED
|
||||
|
||||
|
||||
class OPFFunctions:
|
||||
@@ -380,7 +378,16 @@ class OPFFunctions:
|
||||
for i in range(iterations):
|
||||
|
||||
vf = capture_frame(dprx)
|
||||
vf = video_frame_to_ci(vf, vf.color_info, OPFFunctions.g_vf.data_info)
|
||||
|
||||
if OPFFunctions.g_vf is None:
|
||||
data_info = DataInfo()
|
||||
data_info.packing = DataInfo.Packing.P_PACKED
|
||||
data_info.component_order = DataInfo.ComponentOrder.CO_RGB
|
||||
data_info.alignment = DataInfo.Alignment.A_LSB
|
||||
else:
|
||||
data_info = OPFFunctions.g_vf.data_info
|
||||
|
||||
vf = video_frame_to_ci(vf, vf.color_info, data_info)
|
||||
|
||||
if vf is not None and len(vf.data) > 0:
|
||||
if OPFFunctions.g_vf is not None:
|
||||
@@ -390,11 +397,88 @@ class OPFFunctions:
|
||||
else:
|
||||
if OPFFunctions.g_vf.data in vf.data:
|
||||
return OPFDialogAnswer.PASS
|
||||
else:
|
||||
return OPFDialogAnswer.PASS
|
||||
|
||||
return OPFDialogAnswer.FAIL
|
||||
|
||||
@staticmethod
|
||||
def opf_13_handler(dptx, dprx, message: str) -> OPFDialogAnswer:
|
||||
return OPFFunctions.opf_pass_handler(dptx, dprx, message)
|
||||
audio_mode = dptx.ag.audio_mode
|
||||
|
||||
dptx.ag.setup(audio_mode, UniTAP.AudioPattern.SignalPing, 2000, 100)
|
||||
|
||||
if not dptx.ag.apply():
|
||||
return OPFDialogAnswer.FAIL
|
||||
|
||||
dprx.audio_capturer.start(m_sec=10000)
|
||||
dprx.audio_capturer.stop()
|
||||
|
||||
result = dprx.audio_capturer.capture_result
|
||||
|
||||
sample_size_bytes = int(math.ceil(result.audio_mode.bits / 8))
|
||||
|
||||
samples = {}
|
||||
for channel in range(result.audio_mode.channel_count):
|
||||
samples[channel] = []
|
||||
|
||||
for frame in result.buffer:
|
||||
frame: UniTAP.AudioFrameData
|
||||
sample_per_channel = int(len(frame.data) / sample_size_bytes / result.audio_mode.channel_count)
|
||||
|
||||
for sample_index in range(sample_per_channel):
|
||||
for channel in range(result.audio_mode.channel_count):
|
||||
sample_offset = (sample_index * sample_size_bytes * result.audio_mode.channel_count) + (
|
||||
channel * sample_size_bytes)
|
||||
sample_value = int.from_bytes(frame.data[sample_offset:sample_offset + sample_size_bytes], "little",
|
||||
signed=True)
|
||||
samples[channel].append(sample_value)
|
||||
|
||||
logging.info(f"Total samples per channel 0: {len(samples[0])}")
|
||||
|
||||
def find_next_transition(start_pos: int, sample_list: list):
|
||||
for pos in range(start_pos + 1, len(sample_list) - 1):
|
||||
previous_value = sample_list[pos - 1]
|
||||
current_value = sample_list[pos]
|
||||
next_value = sample_list[pos + 1]
|
||||
|
||||
if previous_value == 0 and current_value == 0 and next_value != 0:
|
||||
return "burst", pos + 1
|
||||
elif previous_value != 0 and current_value == 0 and next_value == 0:
|
||||
return "silence", pos + 1
|
||||
|
||||
return None, -1
|
||||
|
||||
transition_type, transition_pos = find_next_transition(0, samples[0])
|
||||
if transition_type is None:
|
||||
logging.warn("OPF 13: No transitions were found. Audio may be invalid.")
|
||||
return OPFDialogAnswer.FAIL
|
||||
|
||||
#
|
||||
# Cut beginning of captured data to start exactly with transition.
|
||||
#
|
||||
samples[0] = samples[0][transition_pos:]
|
||||
chunk_info_list = []
|
||||
transition_pos = 0
|
||||
while (t_info := find_next_transition(transition_pos, samples[0])) != (None, -1):
|
||||
chuck_size = t_info[1] - transition_pos + 1
|
||||
chunk_length_ms = int(chuck_size / result.audio_mode.sample_rate * 1000)
|
||||
logging.info(f"Chuck size: {chuck_size}")
|
||||
logging.info(f"Chuck length: {chunk_length_ms}ms")
|
||||
|
||||
chunk_info_list.append((t_info[0], chuck_size, chunk_length_ms))
|
||||
|
||||
transition_pos = t_info[1]
|
||||
|
||||
valid = True
|
||||
for chunk in chunk_info_list:
|
||||
if chunk[2] not in range(245, 255):
|
||||
valid = False
|
||||
break
|
||||
logging.info(f"Chunk validation: {'PASS' if valid else 'FAIL'}")
|
||||
logging.info(f"Chunks: {chunk_info_list}")
|
||||
|
||||
return OPFDialogAnswer.PASS if valid else OPFDialogAnswer.FAIL
|
||||
|
||||
@staticmethod
|
||||
def opf_14_handler(dptx, dprx, message: str) -> OPFDialogAnswer:
|
||||
@@ -553,10 +637,10 @@ class OPFFunctions:
|
||||
|
||||
try:
|
||||
if not OPFFunctions.check_video(dprx):
|
||||
print('Video is not available.')
|
||||
logging.error('Video is not available.')
|
||||
return OPFDialogAnswer.ABORT
|
||||
except BaseException as e:
|
||||
print(e)
|
||||
logging.error(e)
|
||||
return OPFDialogAnswer.ABORT
|
||||
|
||||
return OPFDialogAnswer.PROCEED
|
||||
@@ -582,16 +666,10 @@ class OPFFunctions:
|
||||
def opf_19_handler(dptx, dprx, use_3tap) -> OPFDialogAnswer:
|
||||
|
||||
if not OPFFunctions.check_dprx(dprx):
|
||||
return OPFDialogAnswer.ABORT
|
||||
return OPFDialogAnswer.FAIL
|
||||
|
||||
# check DSC state
|
||||
if not dprx.link.capabilities.link_caps_status().dsc:
|
||||
return OPFDialogAnswer.ABORT
|
||||
|
||||
incorrect_crc = [0xFFFF, 0xFFFF, 0xFFFF, 0x1111, 0x1111, 0x1111]
|
||||
|
||||
def load_dsc(handle: int, values: list) -> OPFDialogAnswer:
|
||||
TSIX_TS_SetConfigItem(handle, TSI_DPRX_DSC_TEST_CRC, values, data_count=6)
|
||||
return OPFDialogAnswer.FAIL
|
||||
|
||||
# TODO: Need to change on public interface. Temporary solution.
|
||||
@@ -599,19 +677,13 @@ class OPFFunctions:
|
||||
__getattribute__('_MemoryManager__io'). \
|
||||
__getattribute__('device_handle')
|
||||
|
||||
iterations = 5
|
||||
def upload_dut_and_te_crc(handle: int, values: list) -> OPFDialogAnswer:
|
||||
if tsi.TSIX_TS_SetConfigItem(handle, p_ci.TSI_DPRX_DSC_TEST_CRC, values, data_count=6) > ci.TSI_SUCCESS:
|
||||
return OPFDialogAnswer.PROCEED
|
||||
else:
|
||||
return OPFDialogAnswer.FAIL
|
||||
|
||||
for i in range(iterations):
|
||||
# capture frame
|
||||
try:
|
||||
dprx.video_capturer.start(frames_count=1)
|
||||
vf = dprx.video_capturer.capture_result.buffer[-1]
|
||||
dprx.video_capturer.stop()
|
||||
except BaseException:
|
||||
dprx.video_capturer.stop()
|
||||
return load_dsc(device_handle, incorrect_crc)
|
||||
|
||||
def create_reference_image(video_frame, crc_values: list):
|
||||
def create_reference_image(video_frame, crc_value: list):
|
||||
try:
|
||||
pps_info = DSCL_ExtractPPSFromData(video_frame.data)
|
||||
except BaseException:
|
||||
@@ -684,34 +756,46 @@ class OPFFunctions:
|
||||
reference_image_crc = UICL_CRC16()
|
||||
try:
|
||||
res = UICL_CalculateCRC16(dsc_decoded_uicl_image, reference_image_crc)
|
||||
if res < UICL_SUCCESS:
|
||||
crc_values.extend([0xFFFF, 0xFFFF, 0xFFFF])
|
||||
if res >= UICL_SUCCESS:
|
||||
crc = [reference_image_crc.R, reference_image_crc.G, reference_image_crc.B]
|
||||
logging.info(f"TE successfully generated image from DUT's PPS and calculated CRC: {crc}")
|
||||
crc_value[:] = crc
|
||||
else:
|
||||
crc_values.extend([reference_image_crc.R, reference_image_crc.G, reference_image_crc.B])
|
||||
except BaseException:
|
||||
return
|
||||
logging.error(f"TE failed to generate image from DUT's PPS without exception with error: {res}")
|
||||
except BaseException as exc:
|
||||
logging.error(f"TE failed to generated image fro DUT's PPS due an exception: {exc}")
|
||||
|
||||
def decompress_dsc(video_frame, crc_values: list):
|
||||
def decompress_dsc(video_frame, crc_value: list):
|
||||
decoded_captured_vf = decode_video_frame(video_frame)
|
||||
uicl_decoded_image_2 = image_from_vf(decoded_captured_vf)
|
||||
decompressed_image_crc = UICL_CRC16()
|
||||
try:
|
||||
res = UICL_CalculateCRC16(uicl_decoded_image_2, decompressed_image_crc)
|
||||
if res < UICL_SUCCESS:
|
||||
crc_values.extend([0x1111, 0x1111, 0x1111])
|
||||
if res >= UICL_SUCCESS:
|
||||
crc = [decompressed_image_crc.R, decompressed_image_crc.G, decompressed_image_crc.B]
|
||||
logging.info(f"DUT's DSC CRC successfully calculated: {crc}")
|
||||
crc_value[:] = crc
|
||||
else:
|
||||
crc_values.extend([decompressed_image_crc.R, decompressed_image_crc.G,
|
||||
decompressed_image_crc.B])
|
||||
except BaseException:
|
||||
return
|
||||
logging.error(f"DUT's DSC CRC calculation failed, without exception: {res}")
|
||||
except BaseException as exc:
|
||||
logging.error(f"Failed to decompress DUT's DSC image due an exception: {exc}")
|
||||
|
||||
reference_image_crc_values = []
|
||||
decompressed_image_crc_values = []
|
||||
reference_image_crc_values = [0x0BAD, 0x0BAD, 0x0BAD]
|
||||
decompressed_image_crc_values = [0xBAD0, 0xBAD0, 0xBAD0]
|
||||
max_frames_to_validate = 5
|
||||
|
||||
try:
|
||||
dprx.video_capturer.start()
|
||||
|
||||
for frame_idx in range(1, max_frames_to_validate + 1):
|
||||
try:
|
||||
logging.info(f"Iteration {frame_idx}. Start frame capturing.")
|
||||
frame = dprx.video_capturer.pop_element()
|
||||
|
||||
thread_create_reference_image = threading.Thread(target=create_reference_image,
|
||||
args=(vf, reference_image_crc_values))
|
||||
args=(frame, reference_image_crc_values))
|
||||
thread_decompressed_image = threading.Thread(target=decompress_dsc,
|
||||
args=(vf, decompressed_image_crc_values))
|
||||
args=(frame, decompressed_image_crc_values))
|
||||
|
||||
thread_create_reference_image.start()
|
||||
thread_decompressed_image.start()
|
||||
@@ -719,20 +803,27 @@ class OPFFunctions:
|
||||
thread_create_reference_image.join()
|
||||
thread_decompressed_image.join()
|
||||
|
||||
if len(reference_image_crc_values) > 0 and len(decompressed_image_crc_values) > 0 and \
|
||||
((reference_image_crc_values == decompressed_image_crc_values) or
|
||||
(reference_image_crc_values != decompressed_image_crc_values and (i == iterations - 1))):
|
||||
# Write crc to register
|
||||
load_dsc(device_handle, [decompressed_image_crc_values[0],
|
||||
decompressed_image_crc_values[1],
|
||||
decompressed_image_crc_values[2],
|
||||
reference_image_crc_values[0],
|
||||
reference_image_crc_values[1],
|
||||
reference_image_crc_values[2]])
|
||||
if reference_image_crc_values == decompressed_image_crc_values:
|
||||
logging.info(f"Frame {frame_idx} is OK.")
|
||||
break
|
||||
else:
|
||||
te_crc_str = [f"0x{value:04X}" for value in reference_image_crc_values]
|
||||
dut_crc_str = [f"0x{value:04X}" for value in decompressed_image_crc_values]
|
||||
logging.info(f"Frame {frame_idx} is NOT OK. "
|
||||
f"TE CRC: {te_crc_str}. "
|
||||
f"DUT CRC: {dut_crc_str}.")
|
||||
|
||||
return OPFDialogAnswer.PROCEED
|
||||
except BaseException as exception:
|
||||
logging.error(f"Frame {frame_idx} is NOT OK. Exception: {exception}")
|
||||
|
||||
return load_dsc(device_handle, incorrect_crc)
|
||||
except BaseException as exc:
|
||||
logging.error(f"Failed to process OPF 19 due an exception: {exc}")
|
||||
finally:
|
||||
dprx.video_capturer.stop()
|
||||
logging.info(f"Capturing has been stopped.")
|
||||
combined_crc_list = decompressed_image_crc_values + reference_image_crc_values
|
||||
logging.info("OPF 19 finished.")
|
||||
return upload_dut_and_te_crc(device_handle, combined_crc_list)
|
||||
|
||||
@staticmethod
|
||||
def opf_20_handler(dptx, dprx, res_x, res_y, res_frate, res_bpc, col_format, col_range, col_yc, tim_std,
|
||||
@@ -742,6 +833,14 @@ class OPFFunctions:
|
||||
|
||||
logging.info((res_x, res_y, res_frate, res_bpc, col_format, col_range, col_yc, tim_std, pattern_name))
|
||||
|
||||
if res_x == 0 and res_y == 0:
|
||||
logging.info("Received request to disable PG.")
|
||||
dptx.pg.set_pattern(pattern=UniTAP.VideoPattern.Disabled)
|
||||
res = dptx.pg.apply()
|
||||
logging.info(f"PG perform apply. Success: {res}.")
|
||||
|
||||
return UniTAP.OPFDialogAnswer.PASS if res else UniTAP.OPFDialogAnswer.FAIL
|
||||
|
||||
if pattern_name is not None:
|
||||
if pattern_name == 'No Video':
|
||||
pattern_name = VideoPattern.Disabled
|
||||
@@ -823,6 +922,18 @@ class OPFFunctions:
|
||||
return OPFDialogAnswer.ABORT
|
||||
return OPFDialogAnswer.PROCEED
|
||||
|
||||
@staticmethod
|
||||
def opf_22_handler(dptx, dprx, message: str) -> OPFDialogAnswer:
|
||||
return OPFDialogAnswer.PROCEED
|
||||
|
||||
@staticmethod
|
||||
def opf_23_handler(dptx, dprx, message: str) -> OPFDialogAnswer:
|
||||
return OPFDialogAnswer.PROCEED
|
||||
|
||||
@staticmethod
|
||||
def opf_24_handler(dptx, dprx, message: str) -> OPFDialogAnswer:
|
||||
return OPFDialogAnswer.PROCEED
|
||||
|
||||
@staticmethod
|
||||
def opf_101_handler(dptx, dprx, message: str) -> OPFDialogAnswer:
|
||||
if not OPFFunctions.check_dprx(dprx):
|
||||
@@ -834,7 +945,7 @@ class OPFFunctions:
|
||||
return UniTAP.OPFDialogAnswer.PASS if len(
|
||||
dprx.audio_capturer.capture_result.buffer) > 0 else UniTAP.OPFDialogAnswer.FAIL
|
||||
except BaseException as e:
|
||||
print(f"Cannot capture audio. Error: {e}")
|
||||
logging.error(f"Cannot capture audio. Error: {e}")
|
||||
return UniTAP.OPFDialogAnswer.FAIL
|
||||
|
||||
@staticmethod
|
||||
@@ -926,7 +1037,7 @@ class OPFFunctions:
|
||||
OPFFunctions.g_h_slice_size = h_slice_size
|
||||
OPFFunctions.g_v_slice_size = v_slice_size
|
||||
|
||||
res, suite_id = TSIX_TS_GetConfigItem(device_handle, TSI_SELECT_SUITE, c_uint32)
|
||||
res, suite_id = tsi.TSIX_TS_GetConfigItem(device_handle, p_ci.TSI_SELECT_SUITE, c_uint32)
|
||||
if res > 0:
|
||||
suite_id = TestGroupId(suite_id)
|
||||
else:
|
||||
@@ -936,10 +1047,12 @@ class OPFFunctions:
|
||||
try:
|
||||
if suite_id in [TestGroupId.DP_TX_LL_CTS, TestGroupId.DP_TX_LL_CTS_DSC,
|
||||
TestGroupId.DP_TX_DISPLAYID, TestGroupId.DP_TX_ADAPTIVESYNC]:
|
||||
res, is_simple_as_444 = TSIX_TS_GetConfigItem(device_handle, TSI_DP14_SINKCTS_SUPPORT_444CRC, c_uint32)
|
||||
res, is_simple_as_444 = tsi.TSIX_TS_GetConfigItem(device_handle, ci.TSI_DP14_SINKCTS_SUPPORT_444CRC,
|
||||
c_uint32)
|
||||
elif suite_id in [TestGroupId.DP_2_1_TX_LL_CTS, TestGroupId.DP_2_1_TX_DSC_CTS,
|
||||
TestGroupId.DP_2_1_TX_DISPAYID, TestGroupId.DP_2_1_TX_ADAPTIVESYNC]:
|
||||
res, is_simple_as_444 = TSIX_TS_GetConfigItem(device_handle, TSI_DP20_SINKCTS_SUPPORT_444CRC, c_uint32)
|
||||
res, is_simple_as_444 = tsi.TSIX_TS_GetConfigItem(device_handle, ci.TSI_DP20_SINKCTS_SUPPORT_444CRC,
|
||||
c_uint32)
|
||||
except BaseException as e:
|
||||
pass
|
||||
|
||||
@@ -964,18 +1077,18 @@ class OPFFunctions:
|
||||
|
||||
OPFFunctions.g_vm = copy.deepcopy(encoded_video_frame)
|
||||
|
||||
TSIX_TS_SetConfigItem(device_handle, TSI_MEMORY_LAYOUT, len(encoded_video_frame.data), c_uint64)
|
||||
TSIX_TS_SetConfigItem(device_handle, TSI_MEMORY_BLOCK_INDEX, 0, data_size=4)
|
||||
TSIX_TS_SetConfigItem(device_handle, TSI_MEMORY_WRITE_W, bytearray(encoded_video_frame.data),
|
||||
tsi.TSIX_TS_SetConfigItem(device_handle, ci.TSI_MEMORY_LAYOUT, len(encoded_video_frame.data), c_uint64)
|
||||
tsi.TSIX_TS_SetConfigItem(device_handle, ci.TSI_MEMORY_BLOCK_INDEX, 0, data_size=4)
|
||||
tsi.TSIX_TS_SetConfigItem(device_handle, ci.TSI_MEMORY_WRITE_W, bytearray(encoded_video_frame.data),
|
||||
data_type=c_uint8,
|
||||
data_count=len(encoded_video_frame.data))
|
||||
TSIX_TS_SetConfigItem(device_handle, TSI_DSC_MEMORY_BLOCK, 0)
|
||||
TSIX_TS_SetConfigItem(device_handle, TSI_DSC_DATA_SIZE, len(encoded_video_frame.data))
|
||||
tsi.TSIX_TS_SetConfigItem(device_handle, p_ci.TSI_DSC_MEMORY_BLOCK, 0)
|
||||
tsi.TSIX_TS_SetConfigItem(device_handle, p_ci.TSI_DSC_DATA_SIZE, len(encoded_video_frame.data))
|
||||
|
||||
decoded_vf = decode_video_frame(encoded_video_frame)
|
||||
|
||||
crc0, crc1, crc2 = calculate_crc(decoded_vf)
|
||||
TSIX_TS_SetConfigItem(device_handle, TSI_DSC_TX_CRC, [crc0, crc1, crc2], data_count=3)
|
||||
tsi.TSIX_TS_SetConfigItem(device_handle, p_ci.TSI_DSC_TX_CRC, [crc0, crc1, crc2], data_count=3)
|
||||
|
||||
return OPFDialogAnswer.PROCEED
|
||||
|
||||
@@ -1020,14 +1133,17 @@ class OPFFunctions:
|
||||
vf.data[pps_size + slice_size:slice_size * 2]:
|
||||
return OPFDialogAnswer.PASS
|
||||
else:
|
||||
print(f"Frame {i + 1}: Image looks good and distortion free for slice #2. It is wrong.")
|
||||
logging.info(
|
||||
f"Frame {i + 1}: Image looks good and distortion free for slice #2. It is wrong.")
|
||||
else:
|
||||
print(
|
||||
logging.info(
|
||||
f"Frame {i + 1}: Image does not look good and distortion free for slice #4. It is wrong.")
|
||||
else:
|
||||
print(f"Frame {i + 1}: Image does not look good and distortion free for slice #3. It is wrong.")
|
||||
logging.info(
|
||||
f"Frame {i + 1}: Image does not look good and distortion free for slice #3. It is wrong.")
|
||||
else:
|
||||
print(f"Frame {i + 1}: Image does not look good and distortion free for slice #1. It is wrong.")
|
||||
logging.info(
|
||||
f"Frame {i + 1}: Image does not look good and distortion free for slice #1. It is wrong.")
|
||||
|
||||
return OPFDialogAnswer.FAIL
|
||||
|
||||
@@ -1043,6 +1159,66 @@ class OPFFunctions:
|
||||
def opf_107_handler(dptx, dprx, message: str) -> OPFDialogAnswer:
|
||||
return OPFFunctions.opf_pass_handler(dptx, dprx, message)
|
||||
|
||||
@staticmethod
|
||||
def opf_108_handler(dptx, dprx, *args) -> OPFDialogAnswer:
|
||||
if not OPFFunctions.check_dprx(dprx):
|
||||
return OPFDialogAnswer.ABORT
|
||||
|
||||
if len(args) == 4:
|
||||
audio_pattern, sample_rate, sample_size, ch_count = args
|
||||
else:
|
||||
audio_pattern, sample_rate, sample_size, ch_count = None, None, None, None
|
||||
|
||||
logging.info(audio_pattern, sample_rate, sample_size, ch_count)
|
||||
|
||||
try:
|
||||
dprx.audio_capturer.start(10)
|
||||
dprx.audio_capturer.stop()
|
||||
|
||||
if len(dprx.audio_capturer.capture_result.buffer) <= 0:
|
||||
logging.info("Audio buffer is empty")
|
||||
return UniTAP.OPFDialogAnswer.FAIL
|
||||
|
||||
if audio_pattern is None:
|
||||
logging.info("Default 108 OPF, check audio availability")
|
||||
return UniTAP.OPFDialogAnswer.PASS if len(dprx.audio_capturer.capture_result.buffer) > 0 else \
|
||||
UniTAP.OPFDialogAnswer.FAIL
|
||||
|
||||
def check_audio_frame(index, ch_count, sample_freq, sample_size) -> bool:
|
||||
|
||||
frame = dprx.audio_capturer.capture_result.buffer[index]
|
||||
_data = list(frame.data)
|
||||
length = len(_data)
|
||||
zero_count = _data.count(0)
|
||||
|
||||
is_only_zero = zero_count == length
|
||||
active_channel_count = OPFFunctions.get_active_channel_count(raw_data=frame.data,
|
||||
bit_depths=[frame.sample_size],
|
||||
channel_range=[frame.channel_count],
|
||||
expected_channels=ch_count
|
||||
)
|
||||
|
||||
logging.info(f"Frame index[{index}]: Len - {length}, Zero count - {zero_count}, "
|
||||
f"Reference channel count - {ch_count}, Captured active channel count - {active_channel_count}, "
|
||||
f"Reference sample rate - {sample_freq}, Captured sample rate - {frame.sample_rate}\n")
|
||||
return not is_only_zero and \
|
||||
active_channel_count == ch_count and \
|
||||
frame.sample_rate == sample_freq and \
|
||||
frame.sample_size == sample_size
|
||||
|
||||
buffer_len = len(dprx.audio_capturer.capture_result.buffer)
|
||||
|
||||
state = buffer_len > 0 and \
|
||||
(check_audio_frame(0, ch_count, sample_rate, sample_size) or
|
||||
check_audio_frame(int(buffer_len / 2), ch_count, sample_rate, sample_size) or
|
||||
check_audio_frame(buffer_len - 1, ch_count, sample_rate, sample_size))
|
||||
|
||||
return UniTAP.OPFDialogAnswer.PASS if state else UniTAP.OPFDialogAnswer.FAIL
|
||||
|
||||
except BaseException as e:
|
||||
logging.error(f"Cannot capture audio. Error: {e}")
|
||||
return UniTAP.OPFDialogAnswer.FAIL
|
||||
|
||||
@staticmethod
|
||||
def opf_120_handler(dptx, dprx, res_x, res_y, res_frate, res_bpc, color_format) -> OPFDialogAnswer:
|
||||
if not OPFFunctions.check_dprx(dprx):
|
||||
@@ -1256,6 +1432,38 @@ class OPFFunctions:
|
||||
else:
|
||||
return OPFDialogAnswer.ABORT
|
||||
|
||||
@staticmethod
|
||||
def opf_146_handler(dptx, dprx, res_x, res_y, rate):
|
||||
if not OPFFunctions.check_dptx(dptx):
|
||||
logging.error("DPTX is not initialized")
|
||||
return OPFDialogAnswer.ABORT
|
||||
|
||||
logging.info(res_x, res_y, rate)
|
||||
|
||||
return OPFDialogAnswer.PROCEED
|
||||
|
||||
@staticmethod
|
||||
def opf_147_handler(dptx, dprx, rate):
|
||||
if not OPFFunctions.check_dptx(dptx):
|
||||
logging.error("DPTX is not initialized")
|
||||
return OPFDialogAnswer.ABORT
|
||||
|
||||
logging.info(f"Refresh rate passed from OPF: {rate}")
|
||||
|
||||
dptx.pg.set_as_config(as_config=FixedASParams(refresh_rate=rate,
|
||||
divide_by_1_001=False,
|
||||
increase_lines=100,
|
||||
decrease_lines=100))
|
||||
res_pg = dptx.pg.apply()
|
||||
|
||||
if not res_pg:
|
||||
logging.info("DPTX pattern is not applied")
|
||||
return OPFDialogAnswer.ABORT
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
return OPFDialogAnswer.PROCEED
|
||||
|
||||
@staticmethod
|
||||
def opf_150_handler(dptx, dprx, message: str) -> OPFDialogAnswer:
|
||||
return OPFFunctions.opf_pass_handler(dptx, dprx, message)
|
||||
@@ -1388,3 +1596,94 @@ class OPFFunctions:
|
||||
compression_info.is_simple_as_444 = is_simple_as_444
|
||||
|
||||
return compression_info
|
||||
|
||||
@staticmethod
|
||||
def read_pcm(raw_data, sample_size):
|
||||
"""
|
||||
Read raw PCM data from file into a list of int32 values.
|
||||
Handles 16, 20, and 24-bit samples (little-endian).
|
||||
"""
|
||||
if sample_size == 16:
|
||||
if len(raw_data) % 2 != 0:
|
||||
raise ValueError("File length not divisible by 2 for 16-bit audio")
|
||||
result = []
|
||||
for i in range(0, len(raw_data), 2):
|
||||
sample = int.from_bytes(raw_data[i:i + 2], byteorder='little', signed=True)
|
||||
result.append(sample)
|
||||
return result, 32767
|
||||
elif sample_size == 20 or sample_size == 24:
|
||||
if len(raw_data) % 3 != 0:
|
||||
raise ValueError("File length not divisible by 3 for 24/20-bit audio")
|
||||
result = []
|
||||
for i in range(0, len(raw_data), 3):
|
||||
val = (raw_data[i] |
|
||||
(raw_data[i + 1] << 8) |
|
||||
(raw_data[i + 2] << 16))
|
||||
sign_mask = 1 << 23
|
||||
val = (val & (sign_mask - 1)) - (val & sign_mask)
|
||||
result.append(val)
|
||||
return result, (1 << 23) - 1
|
||||
else:
|
||||
raise ValueError(f"Unsupported bit depth: {sample_size}")
|
||||
|
||||
@staticmethod
|
||||
def get_active_channel_count(raw_data, bit_depths: list, channel_range: list, expected_channels: int,
|
||||
rms_threshold=1e-3, nonzero_frac_threshold=1e-4):
|
||||
"""
|
||||
Try multiple bit depths and channel counts, report active channels.
|
||||
"""
|
||||
active_count = 0
|
||||
for bd in bit_depths:
|
||||
try:
|
||||
data, dtype_max = OPFFunctions.read_pcm(raw_data, bd)
|
||||
except Exception as e:
|
||||
logging.info(f"[{bd}-bit] Error: {e}")
|
||||
continue
|
||||
|
||||
logging.info(f"\n=== Testing bit depth {bd} ===")
|
||||
|
||||
for nch in [expected_channels] + [ch for ch in channel_range if ch != expected_channels]:
|
||||
if len(data) % nch != 0:
|
||||
logging.info(f"Skipping {nch} channels: data length {len(data)} not divisible by {nch}")
|
||||
continue
|
||||
frames = len(data) // nch
|
||||
|
||||
arr = []
|
||||
for f in range(frames):
|
||||
frame = data[f * nch:(f + 1) * nch]
|
||||
arr.append(frame)
|
||||
|
||||
rms = []
|
||||
peak = []
|
||||
nonzero_frac = []
|
||||
for ch in range(nch):
|
||||
channel_data = [arr[f][ch] for f in range(frames)]
|
||||
|
||||
mean_square = sum(x * x for x in channel_data) / frames
|
||||
rms.append(mean_square ** 0.5)
|
||||
|
||||
peak.append(max(abs(x) for x in channel_data))
|
||||
|
||||
nonzero_count = sum(1 for x in channel_data if x != 0)
|
||||
nonzero_frac.append(nonzero_count / frames)
|
||||
|
||||
norm_rms = [r / dtype_max for r in rms]
|
||||
norm_peak = [p / dtype_max for p in peak]
|
||||
|
||||
logging.info(f"\nAssuming {nch} channel(s):")
|
||||
channel_active_count = 0
|
||||
for ch in range(nch):
|
||||
active = (norm_rms[ch] > rms_threshold or
|
||||
nonzero_frac[ch] > nonzero_frac_threshold)
|
||||
if active:
|
||||
channel_active_count += 1
|
||||
logging.info(f" Ch{ch}: normRMS={norm_rms[ch]:.6f}, "
|
||||
f"normPeak={norm_peak[ch]:.6f}, "
|
||||
f"nonzero={nonzero_frac[ch]:.6f}, ACTIVE={active}")
|
||||
logging.info(f" => Detected {channel_active_count}/{nch} active channels")
|
||||
|
||||
if channel_active_count == expected_channels:
|
||||
active_count = channel_active_count
|
||||
break
|
||||
|
||||
return active_count
|
||||
|
||||
@@ -8,7 +8,7 @@ class OPFParametersParser:
|
||||
return parse_link_training(args[3])
|
||||
if opf_id in [2]:
|
||||
return parse_video_mode_2(args[3])
|
||||
if opf_id in [3, 4, 5, 7, 8, 11, 12, 13, 14, 15, 16, 17, 101, 102, 104, 105, 106, 121, 122, 123, 145, 150, 152, 161]:
|
||||
if opf_id in [3, 4, 5, 7, 8, 11, 12, 13, 14, 15, 16, 17, 22, 23, 24, 101, 102, 104, 105, 106, 121, 122, 123, 145, 150, 152, 161]:
|
||||
return parse_message(args[1])
|
||||
if opf_id in [6]:
|
||||
return parse_video_mode_6(args[1], args[3])
|
||||
@@ -26,6 +26,11 @@ class OPFParametersParser:
|
||||
return parse_opf_21(args[3])
|
||||
if opf_id in [103]:
|
||||
return parse_video_mode_103(args[3])
|
||||
if opf_id in [108]:
|
||||
if len(args) > 3:
|
||||
return parse_audio_mode_108(args[3])
|
||||
else:
|
||||
return parse_message(args[1])
|
||||
if opf_id in [120]:
|
||||
return parse_video_mode_120(args[3])
|
||||
if opf_id in [140]:
|
||||
@@ -38,6 +43,10 @@ class OPFParametersParser:
|
||||
return parse_video_mode_143(args[3])
|
||||
if opf_id in [144]:
|
||||
return parse_video_mode_144(args[3])
|
||||
if opf_id in [146]:
|
||||
return parse_video_mode_146(args[3])
|
||||
if opf_id in [147]:
|
||||
return parse_video_mode_147(args[3])
|
||||
if opf_id in [151]:
|
||||
return parse_video_mode_103(args[3])
|
||||
else:
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import re
|
||||
from typing import List, Optional
|
||||
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_OPF_PARAMETER
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
|
||||
|
||||
def parse_link_training(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
def parse_link_training(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
dp_lanes = 0
|
||||
dp_link_rate = 0
|
||||
encoding = None
|
||||
@@ -29,7 +29,7 @@ def parse_link_training(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
return int(dp_lanes), float(dp_link_rate), encoding
|
||||
|
||||
|
||||
def parse_video_mode_2(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
def parse_video_mode_2(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
res_x = 0
|
||||
res_y = 0
|
||||
res_frate = 0
|
||||
@@ -48,7 +48,7 @@ def parse_video_mode_2(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
return int(res_x), int(res_y), int(float(res_frate) * 1000), int(res_bpc), tim_std, tim_rb
|
||||
|
||||
|
||||
def parse_video_mode_6(pattern_request: str, parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
def parse_video_mode_6(pattern_request: str, parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
res_x = 0
|
||||
res_y = 0
|
||||
res_frate = 0
|
||||
@@ -79,7 +79,7 @@ def parse_video_mode_6(pattern_request: str, parameters_list: List[TSI_OPF_PARAM
|
||||
res_bpc), timing_standard, col_format, col_range, col_yc, pattern_name
|
||||
|
||||
|
||||
def parse_video_mode_9(parameters_list: List[TSI_OPF_PARAMETER], pattern_request: Optional[str] = None):
|
||||
def parse_video_mode_9(parameters_list: List[ci.TSI_OPF_PARAMETER], pattern_request: Optional[str] = None):
|
||||
res_x = 0
|
||||
res_y = 0
|
||||
res_frate = 0
|
||||
@@ -101,7 +101,7 @@ def parse_video_mode_9(parameters_list: List[TSI_OPF_PARAMETER], pattern_request
|
||||
return int(res_x), int(res_y), int(float(res_frate) * 1000), int(res_bpc), tim_std, pattern_name
|
||||
|
||||
|
||||
def parse_opf_10(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
def parse_opf_10(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
res_x, res_y, res_frate, res_bpc, timing_standard = [0] * 5
|
||||
|
||||
audio_pattern = ''
|
||||
@@ -136,7 +136,7 @@ def parse_message(message: str):
|
||||
return [str(message)]
|
||||
|
||||
|
||||
def parse_video_mode_19(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
def parse_video_mode_19(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
use_3tap = False
|
||||
for param in parameters_list:
|
||||
if param.name == 'Conversion type filter':
|
||||
@@ -144,7 +144,7 @@ def parse_video_mode_19(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
return [use_3tap]
|
||||
|
||||
|
||||
def parse_video_mode_18(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
def parse_video_mode_18(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
res_x = 0
|
||||
res_y = 0
|
||||
res_frate = 0
|
||||
@@ -166,7 +166,7 @@ def parse_video_mode_18(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
return int(res_x), int(res_y), int(float(res_frate) * 1000), int(res_bpc), col_format, col_range, col_yc, tim_std
|
||||
|
||||
|
||||
def parse_video_mode_20(parameters_list: List[TSI_OPF_PARAMETER], pattern_request: Optional[str] = None):
|
||||
def parse_video_mode_20(parameters_list: List[ci.TSI_OPF_PARAMETER], pattern_request: Optional[str] = None):
|
||||
pattern_name = None
|
||||
res_x = 0
|
||||
res_y = 0
|
||||
@@ -186,7 +186,7 @@ def parse_video_mode_20(parameters_list: List[TSI_OPF_PARAMETER], pattern_reques
|
||||
enable_dsc = False
|
||||
|
||||
for param in parameters_list:
|
||||
if param.name == 'Video Mode':
|
||||
if param.name == 'Video Mode' and param.description != "Disable Video":
|
||||
line = param.description.split("Hz")
|
||||
res_x, res_y, res_frate = re.findall(r'\d+', line[0])
|
||||
tim_std = re.findall(r'VIC \d+|DMT \w+|UFG \d+|CVT RB\d+|CVT|OVT', line[1])
|
||||
@@ -203,7 +203,7 @@ def parse_video_mode_20(parameters_list: List[TSI_OPF_PARAMETER], pattern_reques
|
||||
pattern_name, enable_dsc
|
||||
|
||||
|
||||
def parse_opf_21(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
def parse_opf_21(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
audio_pattern = ''
|
||||
ch_count = 0
|
||||
sample_freq = 0
|
||||
@@ -230,7 +230,7 @@ def parse_opf_21(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
ch_info if len(ch_info) > 0 else None)
|
||||
|
||||
|
||||
def parse_video_mode_103(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
def parse_video_mode_103(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
width = 0
|
||||
height = 0
|
||||
res_frate = 60000
|
||||
@@ -268,7 +268,26 @@ def parse_video_mode_103(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
int(h_slice_number), int(buffer_bit_depth), int(v_slice_number), int(dsc_v_major), int(dsc_v_minor)
|
||||
|
||||
|
||||
def parse_video_mode_120(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
def parse_audio_mode_108(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
audio_pattern = ''
|
||||
ch_count = 0
|
||||
sample_rate = 0
|
||||
sample_size = 0
|
||||
|
||||
for ind, param in enumerate(parameters_list):
|
||||
if param.name == 'Audio test pattern':
|
||||
audio_pattern = param.description
|
||||
elif param.name == 'Sample rate':
|
||||
sample_rate, = re.findall(r'\d+', param.description)
|
||||
elif param.name == 'Sample size':
|
||||
sample_size, = re.findall(r'\d+', param.description)
|
||||
elif param.name == 'Channels count':
|
||||
ch_count, = re.findall(r'\d+', param.description)
|
||||
|
||||
return audio_pattern, int(sample_rate), int(sample_size), int(ch_count)
|
||||
|
||||
|
||||
def parse_video_mode_120(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
res_x = 0
|
||||
res_y = 0
|
||||
res_frate = 0
|
||||
@@ -282,7 +301,7 @@ def parse_video_mode_120(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
return int(res_x), int(res_y), int(float(res_frate) * 1000), int(res_bpc), color_format
|
||||
|
||||
|
||||
def parse_video_mode_140(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
def parse_video_mode_140(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
res_x = 0
|
||||
res_y = 0
|
||||
res_frate = 0
|
||||
@@ -300,7 +319,7 @@ def parse_video_mode_140(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
return int(res_x), int(res_y), int(float(res_frate) * 1000), tim_std, tim_std_num
|
||||
|
||||
|
||||
def parse_video_mode_141(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
def parse_video_mode_141(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
audio_format = ''
|
||||
channels = 0
|
||||
size = 0
|
||||
@@ -313,7 +332,7 @@ def parse_video_mode_141(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
return audio_format, int(channels), int(size), int(float(rate) * 1000)
|
||||
|
||||
|
||||
def parse_video_mode_143(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
def parse_video_mode_143(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
res_frate = 0
|
||||
|
||||
for param in parameters_list:
|
||||
@@ -323,5 +342,23 @@ def parse_video_mode_143(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
return [int(float(res_frate))]
|
||||
|
||||
|
||||
def parse_video_mode_144(parameters_list: List[TSI_OPF_PARAMETER]):
|
||||
def parse_video_mode_144(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
return [parameters_list[0].description]
|
||||
|
||||
def parse_video_mode_146(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
res_x = 0
|
||||
res_y = 0
|
||||
rate = 0
|
||||
for param in parameters_list:
|
||||
if param.name == "Resolution":
|
||||
res_x, res_y = re.findall(r'\d+', param.description)
|
||||
if param.name == 'Refresh rate':
|
||||
rate = re.findall(r'\d+', param.description)[0]
|
||||
return int(res_x), int(res_y), int(float(rate) * 1000)
|
||||
|
||||
def parse_video_mode_147(parameters_list: List[ci.TSI_OPF_PARAMETER]):
|
||||
refresh_rate = 0
|
||||
for param in parameters_list:
|
||||
if param.name == 'Refresh rate':
|
||||
refresh_rate = re.findall(r'\d+', param.description)[0]
|
||||
return int(refresh_rate)
|
||||
@@ -1,7 +1,7 @@
|
||||
import time
|
||||
from UniTAP.libs.lib_tsi.tsi_io import DeviceIO
|
||||
from UniTAP.libs.lib_tsi.tsi import TSI_TERMINAL_RW
|
||||
from ctypes import c_char
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
|
||||
|
||||
class Terminal:
|
||||
@@ -30,7 +30,7 @@ class Terminal:
|
||||
def __execute(self, command):
|
||||
command += '\r'
|
||||
str_len = (len(command) / 4 + (1 if len(command) % 4 else 0)) * 4
|
||||
self.__io.set(config_id=TSI_TERMINAL_RW,
|
||||
self.__io.set(config_id=p_ci.TSI_TERMINAL_RW,
|
||||
data=command,
|
||||
data_type=c_char,
|
||||
data_count=len(command),
|
||||
@@ -41,7 +41,7 @@ class Terminal:
|
||||
start = time.time()
|
||||
result = []
|
||||
while time.time() - start < timeout:
|
||||
result = self.__io.get(TSI_TERMINAL_RW, c_char, 1024)[1]
|
||||
result = self.__io.get(p_ci.TSI_TERMINAL_RW, c_char, 1024)[1]
|
||||
if result[0] != b'\x00':
|
||||
break
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ from .dptx5xx import DPTX, DPTX4xx, DPTX5xx
|
||||
from .dprx5xx import DPRX, DPRX4xx, DPRX5xx
|
||||
from .hdrx4xx import HDRX, HDRX4xx
|
||||
from .hdtx4xx import HDTX, HDTX4xx
|
||||
from .hdrx_earc import HDRX_eARC
|
||||
from .pdc_port import PDC340, PDC424, PDC500
|
||||
from .modules import *
|
||||
import UniTAP.dev.ports.modules.capturer.bulk as bulk
|
||||
|
||||
@@ -5,9 +5,7 @@ from .modules.edid.edid import EdidSink
|
||||
from .modules.hdcp import HdcpSink
|
||||
from .modules.capturer.event.event_capturer import EventCapturer, EventFilterDpRx, EventFilterUsbc
|
||||
from .modules.link.dp.private_link_rx_types import DPRXHWCaps
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_DPRX_HDCP_CAPS_R, TSI_DPRX_HDCP_STATUS_R
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_DPRX_DPCD_BASE_W, TSI_DPRX_DPCD_DATA
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_PDC_LOG_CONTROL, TSI_DPRX_HW_CAPS_R
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortProtocol
|
||||
|
||||
|
||||
@@ -34,11 +32,11 @@ class DPRX(RX):
|
||||
def __init__(self, port_io: PortIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(port_io, memory_manager, capturer)
|
||||
|
||||
hw_caps = port_io.get(TSI_DPRX_HW_CAPS_R, DPRXHWCaps)[1]
|
||||
self.__dpcd = DPCDRegisters(port_io, TSI_DPRX_DPCD_BASE_W, TSI_DPRX_DPCD_DATA)
|
||||
hw_caps = port_io.get(ci.TSI_DPRX_HW_CAPS_R, DPRXHWCaps)[1]
|
||||
self.__dpcd = DPCDRegisters(port_io, ci.TSI_DPRX_DPCD_BASE_W, ci.TSI_DPRX_DPCD_DATA)
|
||||
self.__link = LinkDisplayPortRx(port_io, hw_caps, self.__dpcd)
|
||||
self.__edid = EdidSink(port_io, self.__link.status.mst_stream_count)
|
||||
self.__hdcp = HdcpSink(port_io, TSI_DPRX_HDCP_CAPS_R, TSI_DPRX_HDCP_STATUS_R)
|
||||
self.__hdcp = HdcpSink(port_io, ci.TSI_DPRX_HDCP_CAPS_R, ci.TSI_DPRX_HDCP_STATUS_R)
|
||||
self.__video_capturer = VideoCapturerDP(capturer, hw_caps.mst_stream_count)
|
||||
|
||||
event_filters = []
|
||||
|
||||
@@ -4,6 +4,7 @@ from .modules.capturer.bulk.bulk_capturer import BulkCapturer
|
||||
from .modules.edid.edid import DisplayIdSink
|
||||
from .modules.panel_replay import SinkPanelReplay, SinkPanelSelfRefresh
|
||||
from typing import Optional
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
|
||||
|
||||
class DPRX4xx(DPRX):
|
||||
@@ -26,7 +27,7 @@ class DPRX4xx(DPRX):
|
||||
def __init__(self, port_io: PortIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(port_io, memory_manager, capturer)
|
||||
|
||||
hw_caps = port_io.get(TSI_DPRX_HW_CAPS_R, DPRXHWCaps)[1]
|
||||
hw_caps = port_io.get(ci.TSI_DPRX_HW_CAPS_R, DPRXHWCaps)[1]
|
||||
self.__fec = FecRx(port_io, self.dpcd)
|
||||
self.__bulk_capturer = BulkCapturer(capturer, memory_manager)
|
||||
self.__display_id = DisplayIdSink(port_io, hw_caps.mst_stream_count)
|
||||
|
||||
@@ -5,9 +5,7 @@ from .modules.vtg.pg import DpPatternGenerator
|
||||
from .modules.hdcp import HdcpSource
|
||||
from .modules.capturer.event.event_capturer import EventCapturer, EventFilterDpTx, EventFilterUsbc
|
||||
from .modules.link.dp.private_link_tx_types import DPTXHWCaps
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_DPTX_DPCD_BASE_W, TSI_DPTX_DPCD_DATA
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_DPTX_HDCP_CAPS_R, TSI_DPTX_HDCP_STATUS_R
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_DPTX_HW_CAPS_R
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortProtocol
|
||||
|
||||
|
||||
@@ -34,12 +32,12 @@ class DPTX(TX):
|
||||
def __init__(self, port_io: PortIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(port_io, memory_manager, capturer)
|
||||
|
||||
hw_caps = port_io.get(TSI_DPTX_HW_CAPS_R, DPTXHWCaps)[1]
|
||||
self.__dpcd = DPCDRegisters(port_io, TSI_DPTX_DPCD_BASE_W, TSI_DPTX_DPCD_DATA)
|
||||
hw_caps = port_io.get(ci.TSI_DPTX_HW_CAPS_R, DPTXHWCaps)[1]
|
||||
self.__dpcd = DPCDRegisters(port_io, ci.TSI_DPTX_DPCD_BASE_W, ci.TSI_DPTX_DPCD_DATA)
|
||||
self.__link = LinkDisplayPortTx(port_io, self.__dpcd, hw_caps)
|
||||
self.__pg = DpPatternGenerator(port_io, memory_manager, 0)
|
||||
self.__edid = EdidSource(port_io, self.__link.max_stream_count)
|
||||
self.__hdcp = HdcpSource(port_io, TSI_DPTX_HDCP_CAPS_R, TSI_DPTX_HDCP_STATUS_R)
|
||||
self.__hdcp = HdcpSource(port_io, ci.TSI_DPTX_HDCP_CAPS_R, ci.TSI_DPTX_HDCP_STATUS_R)
|
||||
# event_filters = [e(hw_caps) for e in self.__CHECK_EVENT_FILTER.get(port_io.protocol())]
|
||||
|
||||
event_filters = []
|
||||
|
||||
@@ -2,6 +2,8 @@ from .dptx import *
|
||||
from .modules.fec import FecTx, FECCounters, FECErrorType8b10b
|
||||
from .modules.vtg.pg import DpMstPatternGenerator
|
||||
from .modules.edid.edid import DisplayIdSource
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
|
||||
|
||||
|
||||
class DPTX4xx(DPTX):
|
||||
@@ -21,7 +23,7 @@ class DPTX4xx(DPTX):
|
||||
def __init__(self, port_io: PortIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(port_io, memory_manager, capturer)
|
||||
|
||||
hw_caps = port_io.get(TSI_DPTX_HW_CAPS_R, DPTXHWCaps)[1]
|
||||
hw_caps = port_io.get(ci.TSI_DPTX_HW_CAPS_R, DPTXHWCaps)[1]
|
||||
self.__fec = FecTx(port_io, self.dpcd)
|
||||
self.__pg = DpMstPatternGenerator(port_io, memory_manager, hw_caps.mst_stream_count)
|
||||
self.__display_id = DisplayIdSource(port_io, hw_caps.mst_stream_count)
|
||||
|
||||
@@ -4,8 +4,7 @@ from .modules.link.hdmi.link import HdmiLinkRx
|
||||
from .modules.hdcp import HdcpSink
|
||||
from .modules.cec.cec_rx import CecRx
|
||||
from .modules.capturer.event.event_capturer import EventCapturer, EventFilterHdRx
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_HDRX_HDCP_CAPS_R, TSI_HDRX_HDCP_STATUS_R
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_HDRX_LOG_CONTROL
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
|
||||
|
||||
class HDRX(RX):
|
||||
@@ -30,7 +29,7 @@ class HDRX(RX):
|
||||
|
||||
self.__link = HdmiLinkRx(port_io)
|
||||
self.__edid = EdidSink(port_io, 1)
|
||||
self.__hdcp = HdcpSink(port_io, TSI_HDRX_HDCP_CAPS_R, TSI_HDRX_HDCP_STATUS_R)
|
||||
self.__hdcp = HdcpSink(port_io, ci.TSI_HDRX_HDCP_CAPS_R, ci.TSI_HDRX_HDCP_STATUS_R)
|
||||
self.__event_capturer = EventCapturer(capturer, port_io.index(), [EventFilterHdRx(0)])
|
||||
self.__video_capturer = VideoCapturerHDMI(capturer, 1)
|
||||
self.__cec = CecRx(port_io)
|
||||
|
||||
30
UniTAP/dev/ports/hdrx_earc.py
Normal file
30
UniTAP/dev/ports/hdrx_earc.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from UniTAP.dev.ports.modules.earc.earc_tx import EarcTx
|
||||
from .hdrx import HDRX, PortIO, MemoryManager, Capturer
|
||||
|
||||
|
||||
class HDRX_eARC(HDRX):
|
||||
|
||||
"""
|
||||
|
||||
Main class of `HDRX` object.
|
||||
Inherited from class `RX`.
|
||||
Class describes capabilities of 300th (3XX) series of HDMI devices in Sink (RX - receiver) role with eARC support.
|
||||
|
||||
Attributes:
|
||||
__earc (EarcTx): object of `EarcTx`.
|
||||
"""
|
||||
|
||||
def __init__(self, port_io: PortIO, memory_manager: MemoryManager, capturer: Capturer):
|
||||
super().__init__(port_io, memory_manager, capturer)
|
||||
self.__earc = EarcTx(port_io, memory_manager)
|
||||
|
||||
@property
|
||||
def earc(self) -> EarcTx:
|
||||
"""
|
||||
|
||||
Should be used to control link capabilities on Sink (RX - receiver) role.
|
||||
|
||||
Returns:
|
||||
object of `EarcTx` type.
|
||||
"""
|
||||
return self.__earc
|
||||
@@ -5,8 +5,8 @@ from .modules.vtg.pg import HdmiPatternGenerator
|
||||
from .modules.hdcp import HdcpSource
|
||||
from .modules.capturer.event.event_capturer import EventCapturer, EventFilterHdTx
|
||||
from .modules.cec.cec_tx import CecTx
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_HDTX_HDCP_CAPS_R, TSI_HDTX_HDCP_STATUS_R
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_HDTX_LOG_CONTROL
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
|
||||
|
||||
|
||||
class HDTX(TX):
|
||||
@@ -32,7 +32,7 @@ class HDTX(TX):
|
||||
self.__link = HdmiLinkTx(port_io)
|
||||
self.__edid = EdidSource(port_io, 1)
|
||||
self.__pg = HdmiPatternGenerator(port_io, memory_manager)
|
||||
self.__hdcp = HdcpSource(port_io, TSI_HDTX_HDCP_CAPS_R, TSI_HDTX_HDCP_STATUS_R)
|
||||
self.__hdcp = HdcpSource(port_io, ci.TSI_HDTX_HDCP_CAPS_R, ci.TSI_HDTX_HDCP_STATUS_R)
|
||||
self.__event_capturer = EventCapturer(capturer, port_io.index(), [EventFilterHdTx(0)])
|
||||
self.__cec = CecTx(port_io)
|
||||
|
||||
|
||||
@@ -7,5 +7,7 @@ from .hdcp import *
|
||||
from .capturer import *
|
||||
from .edid import *
|
||||
from .panel_replay import *
|
||||
from .earc import *
|
||||
from .packet_generator import *
|
||||
import UniTAP.dev.ports.modules.cec as cec
|
||||
import UniTAP.dev.ports.modules.pdc as pdc
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
from UniTAP.libs.lib_tsi.tsi_types import *
|
||||
from ctypes import c_uint8, c_int, c_int32
|
||||
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from UniTAP.utils import function_scheduler
|
||||
from .ag_utils import *
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO, PortProtocol
|
||||
@@ -43,16 +45,16 @@ class AudioGenerator:
|
||||
|
||||
self.__memory_manager.make_default()
|
||||
self.__memory_manager.set_memory_block_index(MemoryManager.MemoryOwner.MO_AudioGenerator)
|
||||
self.__io.set(TSI_AUDGEN_SIGNAL_BLOCK, MemoryManager.MemoryOwner.MO_AudioGenerator.value)
|
||||
self.__io.set(ci.TSI_AUDGEN_SIGNAL_BLOCK, MemoryManager.MemoryOwner.MO_AudioGenerator.value)
|
||||
self.__memory_manager.memory_write(data, size)
|
||||
self.__io.set(TSI_AUDGEN_AUDIO_SIZE, size)
|
||||
self.__io.set(ci.TSI_AUDGEN_AUDIO_SIZE, size)
|
||||
|
||||
ag_struct = self.__io.get(TSI_AUDGEN_CONFIG, AudioConfigStructure)[1]
|
||||
ag_struct = self.__io.get(ci.TSI_AUDGEN_CONFIG, AudioConfigStructure)[1]
|
||||
ag_struct.non_lpcm = 0
|
||||
ag_struct.loop = 1
|
||||
|
||||
audio_sts = create_audio_sts(audio_mode=audio_mode)
|
||||
self.__io.set(TSI_AUDGEN_CHANNELS_STS, audio_sts, data_type=c_uint8, data_count=len(audio_sts))
|
||||
self.__io.set(ci.TSI_AUDGEN_CHANNELS_STS, audio_sts, data_type=c_uint8, data_count=len(audio_sts))
|
||||
|
||||
if self.__io.protocol() == PortProtocol.HDMI:
|
||||
tp = 0
|
||||
@@ -63,16 +65,16 @@ class AudioGenerator:
|
||||
ag_struct.n_selector = 1
|
||||
ag_struct.cts_selector = 1
|
||||
|
||||
self.__io.set(TSI_AUDGEN_CONFIG, ag_struct.value())
|
||||
self.__io.set(ci.TSI_AUDGEN_CONFIG, ag_struct.value())
|
||||
|
||||
self.__io.set(TSI_AUDGEN_PACKET_TYPE, tp)
|
||||
self.__io.set(ci.TSI_AUDGEN_PACKET_TYPE, tp)
|
||||
else:
|
||||
self.__io.set(TSI_AUDGEN_CONFIG, ag_struct.value())
|
||||
self.__io.set(ci.TSI_AUDGEN_CONFIG, ag_struct.value())
|
||||
|
||||
self.__io.set(TSI_AUDGEN_SIGNAL_TYPE, AudioPattern.CustomAudio.value)
|
||||
self.__io.set(TSI_AUDGEN_CHANNEL_COUNT, audio_mode.channel_count)
|
||||
self.__io.set(TSI_AUDGEN_SAMPLE_RATE, audio_mode.sample_rate)
|
||||
self.__io.set(TSI_AUDGEN_SAMPLE_SIZE, audio_mode.bits)
|
||||
self.__io.set(ci.TSI_AUDGEN_SIGNAL_TYPE, AudioPattern.CustomAudio.value)
|
||||
self.__io.set(ci.TSI_AUDGEN_CHANNEL_COUNT, audio_mode.channel_count)
|
||||
self.__io.set(ci.TSI_AUDGEN_SAMPLE_RATE, audio_mode.sample_rate)
|
||||
self.__io.set(ci.TSI_AUDGEN_SAMPLE_SIZE, audio_mode.bits)
|
||||
elif isinstance(audio_pattern, AudioPattern):
|
||||
list_sample_rate = [22050, 44100, 88200, 176400, 24000, 48000, 96000, 192000, 32000, 768000]
|
||||
list_bits = [16, 20, 24]
|
||||
@@ -93,16 +95,16 @@ class AudioGenerator:
|
||||
if amplitude not in [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]:
|
||||
raise ValueError(f"'Amplitude' must be more than 0")
|
||||
|
||||
memory_block_no = 2
|
||||
memory_block_no = 1
|
||||
|
||||
self.__memory_manager.make_default()
|
||||
self.__io.set(TSI_AUDGEN_SIGNAL_BLOCK, memory_block_no)
|
||||
self.__io.set(TSI_AUDGEN_SIGNAL_TYPE, audio_pattern.value)
|
||||
self.__io.set(TSI_AUDGEN_CHANNEL_COUNT, audio_mode.channel_count)
|
||||
self.__io.set(TSI_AUDGEN_SAMPLE_RATE, audio_mode.sample_rate)
|
||||
self.__io.set(TSI_AUDGEN_SAMPLE_SIZE, audio_mode.bits)
|
||||
self.__io.set(TSI_AUDGEN_SIGNAL_FREQ, signal_frequency)
|
||||
self.__io.set(TSI_AUDGEN_SIGNAL_VOLUME, amplitude)
|
||||
self.__io.set(ci.TSI_AUDGEN_SIGNAL_BLOCK, memory_block_no)
|
||||
self.__io.set(ci.TSI_AUDGEN_SIGNAL_TYPE, audio_pattern.value)
|
||||
self.__io.set(ci.TSI_AUDGEN_CHANNEL_COUNT, audio_mode.channel_count)
|
||||
self.__io.set(ci.TSI_AUDGEN_SAMPLE_RATE, audio_mode.sample_rate)
|
||||
self.__io.set(ci.TSI_AUDGEN_SAMPLE_SIZE, audio_mode.bits)
|
||||
self.__io.set(ci.TSI_AUDGEN_SIGNAL_FREQ, signal_frequency)
|
||||
self.__io.set(ci.TSI_AUDGEN_SIGNAL_VOLUME, amplitude)
|
||||
else:
|
||||
available_variants = '\n'.join([e.name for e in AudioPattern])
|
||||
raise ValueError(f"Incorrect value of audio pattern - {audio_pattern}\n"
|
||||
@@ -115,7 +117,7 @@ class AudioGenerator:
|
||||
Returns:
|
||||
object of `bool` type - generation was enabled successfully or not.
|
||||
"""
|
||||
self.__io.set(TSI_W_AUDGEN_CONTROL, 1)
|
||||
self.__io.set(ci.TSI_W_AUDGEN_CONTROL, 1)
|
||||
|
||||
def is_apply_ag_success(ag: AudioGenerator):
|
||||
return ag.status == AGStatus.Running
|
||||
@@ -129,7 +131,7 @@ class AudioGenerator:
|
||||
Returns:
|
||||
object of `bool` type - generation was disabled successfully or not.
|
||||
"""
|
||||
return True if self.__io.set(TSI_W_AUDGEN_CONTROL, 0) >= TSI_SUCCESS else False
|
||||
return True if self.__io.set(ci.TSI_W_AUDGEN_CONTROL, 0) >= ci.TSI_SUCCESS else False
|
||||
|
||||
@property
|
||||
def status(self) -> AGStatus:
|
||||
@@ -139,7 +141,7 @@ class AudioGenerator:
|
||||
Returns:
|
||||
object of `AGStatus` type
|
||||
"""
|
||||
self.__status = AGStatus(self.__io.get(TSI_AUDGEN_STATUS_R, c_int)[1] & 0x1)
|
||||
self.__status = AGStatus(self.__io.get(ci.TSI_AUDGEN_STATUS_R, c_int)[1] & 0x1)
|
||||
return self.__status
|
||||
|
||||
@property
|
||||
@@ -150,7 +152,7 @@ class AudioGenerator:
|
||||
Returns:
|
||||
object of `AudioMode` type
|
||||
"""
|
||||
self.__audio_mode.sample_rate = self.__io.get(TSI_AUDGEN_SAMPLE_RATE, c_int32)[1]
|
||||
self.__audio_mode.bits = self.__io.get(TSI_AUDGEN_SAMPLE_SIZE, c_int32)[1]
|
||||
self.__audio_mode.channel_count = self.__io.get(TSI_AUDGEN_CHANNEL_COUNT, c_int32)[1]
|
||||
self.__audio_mode.sample_rate = self.__io.get(ci.TSI_AUDGEN_SAMPLE_RATE, c_int32)[1]
|
||||
self.__audio_mode.bits = self.__io.get(ci.TSI_AUDGEN_SAMPLE_SIZE, c_int32)[1]
|
||||
self.__audio_mode.channel_count = self.__io.get(ci.TSI_AUDGEN_CHANNEL_COUNT, c_int32)[1]
|
||||
return self.__audio_mode
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import os.path
|
||||
import warnings
|
||||
import wave
|
||||
import pickle
|
||||
from collections import deque
|
||||
from ctypes import c_uint32
|
||||
|
||||
from _ctypes import sizeof
|
||||
|
||||
from UniTAP.common.audio_mode import AudioMode, AudioFileFormat
|
||||
from UniTAP.libs.lib_tsi.tsi import sizeof, c_uint32
|
||||
|
||||
|
||||
def save_to_wave_file(path: str, audio_mode: AudioMode, data: bytearray):
|
||||
|
||||
158
UniTAP/dev/ports/modules/ag/earc.py
Normal file
158
UniTAP/dev/ports/modules/ag/earc.py
Normal file
@@ -0,0 +1,158 @@
|
||||
from ctypes import c_uint8, c_int, c_int32
|
||||
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from UniTAP.utils import function_scheduler
|
||||
from .ag_utils import *
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO, PortProtocol
|
||||
from UniTAP.dev.modules import MemoryManager
|
||||
from .types import *
|
||||
from .private_types import *
|
||||
from typing import Union
|
||||
|
||||
|
||||
class AudioGeneratorEARC:
|
||||
"""
|
||||
Class `AudioGenerator` allows working with generating audio from Source (TX - transmitter). You can configure
|
||||
audio generator `setup`, apply settings and start generate audio `apply`, stop generate audio `stop_generate`,
|
||||
read audio generator `status` and get current `audio_mode`.
|
||||
"""
|
||||
def __init__(self, port_io: PortIO, memory_manager: MemoryManager):
|
||||
self.__io = port_io
|
||||
self.__memory_manager = memory_manager
|
||||
self.__status = AGStatus.Unknown
|
||||
self.__audio_mode = AudioMode()
|
||||
|
||||
def setup(self, audio_mode: AudioMode = AudioMode(),
|
||||
audio_pattern: Union[AudioPattern, str] = AudioPattern.SignalSine,
|
||||
signal_frequency: int = 1000, amplitude: int = 60):
|
||||
"""
|
||||
Configure audio generator. Possible two variants of configuration:
|
||||
- From 'wav' or 'bin' file.
|
||||
- From `AudioPattern` parameters.
|
||||
|
||||
Args:
|
||||
audio_mode (AudioMode) - object of `AudioMode`
|
||||
audio_pattern (Union[AudioPattern, str]) - object of `AudioPattern` or path to audio file ('bin' or 'wave')
|
||||
signal_frequency (int)
|
||||
amplitude (int)
|
||||
"""
|
||||
self.stop_generate()
|
||||
if isinstance(audio_pattern, str) and check_file_format(audio_pattern) != AudioFileFormat.UNKNOWN:
|
||||
if check_file_format(audio_pattern) == AudioFileFormat.BIN:
|
||||
data, _, size = load_from_bin_file(path=audio_pattern)
|
||||
else:
|
||||
data, audio_mode, size = load_from_wave_file(path=audio_pattern)
|
||||
|
||||
self.__memory_manager.make_default()
|
||||
self.__memory_manager.set_memory_block_index(MemoryManager.MemoryOwner.MO_AudioGenerator)
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_SIGNAL_BLOCK, MemoryManager.MemoryOwner.MO_AudioGenerator.value)
|
||||
self.__memory_manager.memory_write(data, size)
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_AUDIO_SIZE, size)
|
||||
|
||||
ag_struct = self.__io.get(ci.TSI_EARC_AUDGEN_CONFIG, AudioConfigStructure)[1]
|
||||
ag_struct.non_lpcm = 0
|
||||
ag_struct.loop = 1
|
||||
|
||||
audio_sts = create_audio_sts(audio_mode=audio_mode)
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_CHANNELS_STS, audio_sts, data_type=c_uint8, data_count=len(audio_sts))
|
||||
|
||||
if self.__io.protocol() == PortProtocol.HDMI:
|
||||
tp = 0
|
||||
|
||||
if audio_mode.channel_count == 8 and audio_mode.sample_rate >= 64000:
|
||||
tp = 3
|
||||
|
||||
ag_struct.n_selector = 1
|
||||
ag_struct.cts_selector = 1
|
||||
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_CONFIG, ag_struct.value())
|
||||
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_PACKET_TYPE, tp)
|
||||
else:
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_CONFIG, ag_struct.value())
|
||||
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_SIGNAL_TYPE, AudioPattern.CustomAudio.value)
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_CHANNEL_COUNT, audio_mode.channel_count)
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_SAMPLE_RATE, audio_mode.sample_rate)
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_SAMPLE_SIZE, audio_mode.bits)
|
||||
elif isinstance(audio_pattern, AudioPattern):
|
||||
list_sample_rate = [22050, 44100, 88200, 176400, 24000, 48000, 96000, 192000, 32000, 768000]
|
||||
list_bits = [16, 20, 24]
|
||||
audio_pattern = AudioPattern(audio_pattern.value)
|
||||
|
||||
if not (1 <= audio_mode.channel_count <= 8):
|
||||
raise ValueError(f"'Channel count' must be in range: 1 - 8")
|
||||
|
||||
if audio_mode.sample_rate not in list_sample_rate:
|
||||
raise ValueError(f"'Sample rate' must be in list {list_sample_rate}")
|
||||
|
||||
if audio_mode.bits not in list_bits:
|
||||
raise ValueError(f"'Bits' must be in list {list_bits}")
|
||||
|
||||
if signal_frequency <= 0:
|
||||
raise ValueError(f"'Signal frequency' must be more than 0")
|
||||
|
||||
if amplitude not in [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]:
|
||||
raise ValueError(f"'Amplitude' must be more than 0")
|
||||
|
||||
memory_block_no = 1
|
||||
|
||||
self.__memory_manager.make_default()
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_SIGNAL_BLOCK, memory_block_no)
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_SIGNAL_TYPE, audio_pattern.value)
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_CHANNEL_COUNT, audio_mode.channel_count)
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_SAMPLE_RATE, audio_mode.sample_rate)
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_SAMPLE_SIZE, audio_mode.bits)
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_SIGNAL_FREQ, signal_frequency)
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_SIGNAL_VOLUME, amplitude)
|
||||
else:
|
||||
available_variants = '\n'.join([e.name for e in AudioPattern])
|
||||
raise ValueError(f"Incorrect value of audio pattern - {audio_pattern}\n"
|
||||
f"Available audio patterns: {available_variants}")
|
||||
|
||||
def apply(self) -> bool:
|
||||
"""
|
||||
Apply settings and start generate audio.
|
||||
|
||||
Returns:
|
||||
object of `bool` type - generation was enabled successfully or not.
|
||||
"""
|
||||
self.__io.set(ci.TSI_EARC_AUDGEN_CONTROL_W, 1)
|
||||
|
||||
def is_apply_ag_success(ag: AudioGeneratorEARC) -> bool:
|
||||
return ag.status == AGStatus.Running
|
||||
|
||||
return function_scheduler(is_apply_ag_success, self, interval=1, timeout=10)
|
||||
|
||||
def stop_generate(self) -> bool:
|
||||
"""
|
||||
Stop generate audio.
|
||||
|
||||
Returns:
|
||||
object of `bool` type - generation was disabled successfully or not.
|
||||
"""
|
||||
return True if self.__io.set(ci.TSI_EARC_AUDGEN_CONTROL_W, 0) >= ci.TSI_SUCCESS else False
|
||||
|
||||
@property
|
||||
def status(self) -> AGStatus:
|
||||
"""
|
||||
Return audio generator status.
|
||||
|
||||
Returns:
|
||||
object of `AGStatus` type
|
||||
"""
|
||||
self.__status = AGStatus(self.__io.get(ci.TSI_EARC_AUDGEN_STATUS_R, c_int)[1] & 0x1)
|
||||
return self.__status
|
||||
|
||||
@property
|
||||
def audio_mode(self) -> AudioMode:
|
||||
"""
|
||||
Return current audio mode.
|
||||
|
||||
Returns:
|
||||
object of `AudioMode` type
|
||||
"""
|
||||
self.__audio_mode.sample_rate = self.__io.get(ci.TSI_EARC_AUDGEN_SAMPLE_RATE, c_int32)[1]
|
||||
self.__audio_mode.bits = self.__io.get(ci.TSI_EARC_AUDGEN_SAMPLE_SIZE, c_int32)[1]
|
||||
self.__audio_mode.channel_count = self.__io.get(ci.TSI_EARC_AUDGEN_CHANNEL_COUNT, c_int32)[1]
|
||||
return self.__audio_mode
|
||||
@@ -17,3 +17,12 @@ class AudioConfigStructure(Structure):
|
||||
def value(self) -> int:
|
||||
return self.auto_ch_sts | self.use_raw_data << 1 | self.non_lpcm << 2 | self.loop << 3 | \
|
||||
self.auto_info_frame << 4 | self.n_selector << 8 | self.cts_selector << 12
|
||||
|
||||
|
||||
class AudioSignalStruct(Structure):
|
||||
_fields_ = [
|
||||
('freq', c_uint32, 32),
|
||||
('volume', c_uint32, 32),
|
||||
('shift', c_uint32, 32),
|
||||
('type', c_uint32, 32),
|
||||
]
|
||||
|
||||
@@ -10,7 +10,8 @@ class AudioPattern(IntEnum):
|
||||
SignalSquare = 2
|
||||
CustomAudio = 3
|
||||
SignalIncremental = 4
|
||||
Unknown = 5
|
||||
SignalPing = 5
|
||||
Unknown = 6
|
||||
|
||||
|
||||
class AGStatus(IntEnum):
|
||||
|
||||
@@ -4,7 +4,7 @@ import copy
|
||||
|
||||
from typing import Union, TypeVar, Type, List
|
||||
|
||||
from UniTAP.libs.lib_tsi.tsi import TSIX_TS_SetPortConfigItem
|
||||
import UniTAP.libs.lib_tsi.tsi as tsi
|
||||
from UniTAP.dev.modules.capturer.capture import Capturer, CaptureConfig
|
||||
from UniTAP.dev.modules.capturer.statuses import EventCaptureStatus
|
||||
from .result_event import ResultEventObject
|
||||
@@ -98,10 +98,10 @@ class EventCapturer:
|
||||
self.__event_filter[i] = event_filter
|
||||
|
||||
for item in event_filter.additional_filter:
|
||||
TSIX_TS_SetPortConfigItem(self.__device.device_handle, self.__port_id, item.ci_control, item.value,
|
||||
tsi.TSIX_TS_SetPortConfigItem(self.__device.device_handle, self.__port_id, item.ci_control, item.value,
|
||||
data_count=len(item.value) if isinstance(item.value, list) else 1)
|
||||
|
||||
TSIX_TS_SetPortConfigItem(self.__device.device_handle, self.__port_id, event_filter._control_ci,
|
||||
tsi.TSIX_TS_SetPortConfigItem(self.__device.device_handle, self.__port_id, event_filter._control_ci,
|
||||
event_filter.config)
|
||||
|
||||
def clear_capturer_config(self):
|
||||
@@ -110,7 +110,7 @@ class EventCapturer:
|
||||
"""
|
||||
for item in self.__event_filter:
|
||||
item.clear()
|
||||
TSIX_TS_SetPortConfigItem(self.__device.device_handle, self.__port_id, item._control_ci, 0)
|
||||
tsi.TSIX_TS_SetPortConfigItem(self.__device.device_handle, self.__port_id, item._control_ci, 0)
|
||||
|
||||
def start(self, sec=0, n_elements=0):
|
||||
"""
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
from enum import IntEnum
|
||||
|
||||
from .event_utils import set_bit_in_vector, search_in_list
|
||||
from .private_event_types import AdditionalSDPEventFilter, AdditionalLinkPatternEventFilter, \
|
||||
AdditionalInfoFrameEventFilter, AdditionalVBIDEventFilter, AdditionalMSAEventFilter, AdditionalLSEEventFilter
|
||||
from UniTAP.libs.lib_tsi.tsi_types import *
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
import warnings
|
||||
|
||||
|
||||
@@ -405,7 +407,7 @@ class EventFilterDpRx(EventFilter):
|
||||
|
||||
def __init__(self, hw_caps):
|
||||
super().__init__(hw_caps)
|
||||
self._control_ci = TSI_DPRX_LOG_CONTROL
|
||||
self._control_ci = ci.TSI_DPRX_LOG_CONTROL
|
||||
self.additional_filter = [AdditionalSDPEventFilter()]
|
||||
if hw_caps.link_pat_log:
|
||||
self.additional_filter.append(AdditionalLinkPatternEventFilter())
|
||||
@@ -422,9 +424,9 @@ class EventFilterDpRx(EventFilter):
|
||||
enable (bool) - enable/disable HDP events
|
||||
"""
|
||||
if enable:
|
||||
self.config |= TSI_DPRX_LOG_CTRL_VALUE_HPD
|
||||
self.config |= ci.TSI_DPRX_LOG_CTRL_VALUE_HPD
|
||||
else:
|
||||
self.config &= ~TSI_DPRX_LOG_CTRL_VALUE_HPD
|
||||
self.config &= ~ci.TSI_DPRX_LOG_CTRL_VALUE_HPD
|
||||
|
||||
def config_aux_events(self, enable: bool):
|
||||
"""
|
||||
@@ -434,9 +436,9 @@ class EventFilterDpRx(EventFilter):
|
||||
enable (bool) - enable/disable AUX events
|
||||
"""
|
||||
if enable:
|
||||
self.config |= TSI_DPRX_LOG_CTRL_VALUE_AUX
|
||||
self.config |= ci.TSI_DPRX_LOG_CTRL_VALUE_AUX
|
||||
else:
|
||||
self.config &= ~TSI_DPRX_LOG_CTRL_VALUE_AUX
|
||||
self.config &= ~ci.TSI_DPRX_LOG_CTRL_VALUE_AUX
|
||||
|
||||
def config_sdp_events(self, enable: bool, *args: EventSDP):
|
||||
"""
|
||||
@@ -447,9 +449,9 @@ class EventFilterDpRx(EventFilter):
|
||||
*args (`EventSDP`) - SDP packet types
|
||||
"""
|
||||
if enable:
|
||||
self.config |= TSI_DPRX_LOG_CTRL_VALUE_SDP
|
||||
self.config |= ci.TSI_DPRX_LOG_CTRL_VALUE_SDP
|
||||
else:
|
||||
self.config &= ~TSI_DPRX_LOG_CTRL_VALUE_SDP
|
||||
self.config &= ~ci.TSI_DPRX_LOG_CTRL_VALUE_SDP
|
||||
|
||||
if len(args) > 0:
|
||||
for item in args:
|
||||
@@ -466,9 +468,9 @@ class EventFilterDpRx(EventFilter):
|
||||
"""
|
||||
if self._hw_caps is not None and self._hw_caps.link_pat_log:
|
||||
if enable:
|
||||
self.config |= TSI_DPRX_LOG_CTRL_VALUE_LINK_PAT
|
||||
self.config |= ci.TSI_DPRX_LOG_CTRL_VALUE_LINK_PAT
|
||||
else:
|
||||
self.config &= ~TSI_DPRX_LOG_CTRL_VALUE_LINK_PAT
|
||||
self.config &= ~ci.TSI_DPRX_LOG_CTRL_VALUE_LINK_PAT
|
||||
|
||||
if len(args) > 0:
|
||||
for item in args:
|
||||
@@ -490,9 +492,9 @@ class EventFilterDpRx(EventFilter):
|
||||
"""
|
||||
if self._hw_caps is not None and self._hw_caps.vbid_hw_log:
|
||||
if enable:
|
||||
self.config |= TSI_DPRX_LOG_CTRL_VALUE_VBID_HW
|
||||
self.config |= ci.TSI_DPRX_LOG_CTRL_VALUE_VBID_HW
|
||||
else:
|
||||
self.config &= ~TSI_DPRX_LOG_CTRL_VALUE_VBID_HW
|
||||
self.config &= ~ci.TSI_DPRX_LOG_CTRL_VALUE_VBID_HW
|
||||
|
||||
if len(args) > 0:
|
||||
for item in args:
|
||||
@@ -516,9 +518,9 @@ class EventFilterDpRx(EventFilter):
|
||||
"""
|
||||
if self._hw_caps is not None and self._hw_caps.msa_hw_log:
|
||||
if enable:
|
||||
self.config |= TSI_DPRX_LOG_CTRL_VALUE_MSA_HW
|
||||
self.config |= ci.TSI_DPRX_LOG_CTRL_VALUE_MSA_HW
|
||||
else:
|
||||
self.config &= ~TSI_DPRX_LOG_CTRL_VALUE_MSA_HW
|
||||
self.config &= ~ci.TSI_DPRX_LOG_CTRL_VALUE_MSA_HW
|
||||
|
||||
if len(args) > 0:
|
||||
for item in args:
|
||||
@@ -541,9 +543,9 @@ class EventFilterDpRx(EventFilter):
|
||||
"""
|
||||
if self._hw_caps is not None and self._hw_caps.aux_bw_log:
|
||||
if enable:
|
||||
self.config |= TSI_DPRX_LOG_CTRL_VALUE_AUX_BW
|
||||
self.config |= ci.TSI_DPRX_LOG_CTRL_VALUE_AUX_BW
|
||||
else:
|
||||
self.config &= ~TSI_DPRX_LOG_CTRL_VALUE_AUX_BW
|
||||
self.config &= ~ci.TSI_DPRX_LOG_CTRL_VALUE_AUX_BW
|
||||
else:
|
||||
warnings.warn("HW does not support Aux Bw Logger")
|
||||
|
||||
@@ -556,7 +558,7 @@ class EventFilterDpTx(EventFilter):
|
||||
|
||||
def __init__(self, hw_caps):
|
||||
super().__init__(hw_caps)
|
||||
self._control_ci = TSI_DPTX_LOG_CONTROL
|
||||
self._control_ci = ci.TSI_DPTX_LOG_CONTROL
|
||||
|
||||
def config_hpd_events(self, enable: bool):
|
||||
"""
|
||||
@@ -566,9 +568,9 @@ class EventFilterDpTx(EventFilter):
|
||||
enable (bool) - enable/disable HDP events
|
||||
"""
|
||||
if enable:
|
||||
self.config |= TSI_DPTX_LOG_CONTROL_VALUE_HPD
|
||||
self.config |= ci.TSI_DPTX_LOG_CONTROL_VALUE_HPD
|
||||
else:
|
||||
self.config &= ~TSI_DPTX_LOG_CONTROL_VALUE_HPD
|
||||
self.config &= ~ci.TSI_DPTX_LOG_CONTROL_VALUE_HPD
|
||||
|
||||
def config_aux_events(self, enable: bool):
|
||||
"""
|
||||
@@ -578,9 +580,9 @@ class EventFilterDpTx(EventFilter):
|
||||
enable (bool) - enable/disable AUX events
|
||||
"""
|
||||
if enable:
|
||||
self.config |= TSI_DPTX_LOG_CONTROL_VALUE_AUX
|
||||
self.config |= ci.TSI_DPTX_LOG_CONTROL_VALUE_AUX
|
||||
else:
|
||||
self.config &= ~TSI_DPTX_LOG_CONTROL_VALUE_AUX
|
||||
self.config &= ~ci.TSI_DPTX_LOG_CONTROL_VALUE_AUX
|
||||
|
||||
|
||||
class EventFilterHdRx(EventFilter):
|
||||
@@ -593,7 +595,7 @@ class EventFilterHdRx(EventFilter):
|
||||
def __init__(self, hw_caps):
|
||||
super().__init__(hw_caps)
|
||||
self.additional_filter = [AdditionalInfoFrameEventFilter()]
|
||||
self._control_ci = TSI_HDRX_LOG_CONTROL
|
||||
self._control_ci = ci.TSI_HDRX_LOG_CONTROL
|
||||
|
||||
def config_hpd_events(self, enable: bool):
|
||||
"""
|
||||
@@ -603,9 +605,9 @@ class EventFilterHdRx(EventFilter):
|
||||
enable (bool) - enable/disable HPD events
|
||||
"""
|
||||
if enable:
|
||||
self.config |= TSI_HDRX_LOG_CTRL_VALUE_HPD
|
||||
self.config |= ci.TSI_HDRX_LOG_CTRL_VALUE_HPD
|
||||
else:
|
||||
self.config &= ~TSI_HDRX_LOG_CTRL_VALUE_HPD
|
||||
self.config &= ~ci.TSI_HDRX_LOG_CTRL_VALUE_HPD
|
||||
|
||||
def config_packets_events(self, enable: bool, *args: EventInfoFrame):
|
||||
"""
|
||||
@@ -616,9 +618,9 @@ class EventFilterHdRx(EventFilter):
|
||||
*args (`EventInfoFrame`) - InfoFrame packet types
|
||||
"""
|
||||
if enable:
|
||||
self.config |= TSI_HDRX_LOG_CTRL_VALUE_INFO
|
||||
self.config |= ci.TSI_HDRX_LOG_CTRL_VALUE_INFO
|
||||
else:
|
||||
self.config &= ~TSI_HDRX_LOG_CTRL_VALUE_INFO
|
||||
self.config &= ~ci.TSI_HDRX_LOG_CTRL_VALUE_INFO
|
||||
|
||||
if len(args) > 0:
|
||||
for item in args:
|
||||
@@ -633,9 +635,9 @@ class EventFilterHdRx(EventFilter):
|
||||
enable (bool) - enable/disable I2C events
|
||||
"""
|
||||
if enable:
|
||||
self.config |= TSI_HDRX_LOG_CTRL_VALUE_I2C
|
||||
self.config |= ci.TSI_HDRX_LOG_CTRL_VALUE_I2C
|
||||
else:
|
||||
self.config &= ~TSI_HDRX_LOG_CTRL_VALUE_I2C
|
||||
self.config &= ~ci.TSI_HDRX_LOG_CTRL_VALUE_I2C
|
||||
|
||||
def config_cec_events(self, enable: bool):
|
||||
"""
|
||||
@@ -645,9 +647,9 @@ class EventFilterHdRx(EventFilter):
|
||||
enable (bool) - enable/disable CEC events
|
||||
"""
|
||||
if enable:
|
||||
self.config |= TSI_HDRX_LOG_CTRL_VALUE_CEC
|
||||
self.config |= ci.TSI_HDRX_LOG_CTRL_VALUE_CEC
|
||||
else:
|
||||
self.config &= ~TSI_HDRX_LOG_CTRL_VALUE_CEC
|
||||
self.config &= ~ci.TSI_HDRX_LOG_CTRL_VALUE_CEC
|
||||
|
||||
|
||||
class EventFilterHdTx(EventFilter):
|
||||
@@ -659,7 +661,7 @@ class EventFilterHdTx(EventFilter):
|
||||
|
||||
def __init__(self, hw_caps):
|
||||
super().__init__(hw_caps)
|
||||
self._control_ci = TSI_HDTX_LOG_CONTROL
|
||||
self._control_ci = ci.TSI_HDTX_LOG_CONTROL
|
||||
|
||||
def config_hpd_events(self, enable: bool):
|
||||
"""
|
||||
@@ -669,9 +671,9 @@ class EventFilterHdTx(EventFilter):
|
||||
enable (bool) - enable/disable HPD events
|
||||
"""
|
||||
if enable:
|
||||
self.config |= TSI_HDTX_LOG_CTRL_VALUE_HPD
|
||||
self.config |= ci.TSI_HDTX_LOG_CTRL_VALUE_HPD
|
||||
else:
|
||||
self.config &= ~TSI_HDTX_LOG_CTRL_VALUE_HPD
|
||||
self.config &= ~ci.TSI_HDTX_LOG_CTRL_VALUE_HPD
|
||||
|
||||
def config_i2c_events(self, enable: bool):
|
||||
"""
|
||||
@@ -681,9 +683,9 @@ class EventFilterHdTx(EventFilter):
|
||||
enable (bool) - enable/disable I2C events
|
||||
"""
|
||||
if enable:
|
||||
self.config |= TSI_HDTX_LOG_CTRL_VALUE_I2C
|
||||
self.config |= ci.TSI_HDTX_LOG_CTRL_VALUE_I2C
|
||||
else:
|
||||
self.config &= ~TSI_HDTX_LOG_CTRL_VALUE_I2C
|
||||
self.config &= ~ci.TSI_HDTX_LOG_CTRL_VALUE_I2C
|
||||
|
||||
def config_cec_events(self, enable: bool):
|
||||
"""
|
||||
@@ -693,9 +695,9 @@ class EventFilterHdTx(EventFilter):
|
||||
enable (bool) - enable/disable CEC events
|
||||
"""
|
||||
if enable:
|
||||
self.config |= TSI_HDTX_LOG_CTRL_VALUE_CEC
|
||||
self.config |= ci.TSI_HDTX_LOG_CTRL_VALUE_CEC
|
||||
else:
|
||||
self.config &= ~TSI_HDTX_LOG_CTRL_VALUE_CEC
|
||||
self.config &= ~ci.TSI_HDTX_LOG_CTRL_VALUE_CEC
|
||||
|
||||
|
||||
class EventFilterUsbc(EventFilter):
|
||||
@@ -707,7 +709,7 @@ class EventFilterUsbc(EventFilter):
|
||||
|
||||
def __init__(self, hw_caps):
|
||||
super().__init__(hw_caps)
|
||||
self._control_ci = TSI_PDC_LOG_CONTROL
|
||||
self._control_ci = ci.TSI_PDC_LOG_CONTROL
|
||||
if hw_caps is not None and hw_caps.voltage:
|
||||
self.additional_filter.append(AdditionalLSEEventFilter())
|
||||
|
||||
@@ -719,9 +721,9 @@ class EventFilterUsbc(EventFilter):
|
||||
enable (bool) - enable/disable PD events
|
||||
"""
|
||||
if enable:
|
||||
self.config |= TSI_PDC_LOG_CTRL_VALUE_PD
|
||||
self.config |= ci.TSI_PDC_LOG_CTRL_VALUE_PD
|
||||
else:
|
||||
self.config &= ~TSI_PDC_LOG_CTRL_VALUE_PD
|
||||
self.config &= ~ci.TSI_PDC_LOG_CTRL_VALUE_PD
|
||||
|
||||
def config_voltage_events(self, enable: bool, value: EventLCE):
|
||||
"""
|
||||
@@ -733,9 +735,9 @@ class EventFilterUsbc(EventFilter):
|
||||
"""
|
||||
if self._hw_caps is not None and self._hw_caps.voltage:
|
||||
if enable:
|
||||
self.config |= TSI_PDC_LOG_CTRL_VALUE_USBC_VOLTAGE
|
||||
self.config |= ci.TSI_PDC_LOG_CTRL_VALUE_USBC_VOLTAGE
|
||||
else:
|
||||
self.config &= ~TSI_PDC_LOG_CTRL_VALUE_USBC_VOLTAGE
|
||||
self.config &= ~ci.TSI_PDC_LOG_CTRL_VALUE_USBC_VOLTAGE
|
||||
|
||||
for i in enumerate(value.values()):
|
||||
self.additional_filter[search_in_list(AdditionalLSEEventFilter,
|
||||
@@ -752,9 +754,9 @@ class EventFilterUsbc(EventFilter):
|
||||
"""
|
||||
if self._hw_caps is not None and self._hw_caps.events:
|
||||
if enable:
|
||||
self.config |= TSI_PDC_LOG_CTRL_VALUE_USBC_EVENT
|
||||
self.config |= ci.TSI_PDC_LOG_CTRL_VALUE_USBC_EVENT
|
||||
else:
|
||||
self.config &= ~TSI_PDC_LOG_CTRL_VALUE_USBC_EVENT
|
||||
self.config &= ~ci.TSI_PDC_LOG_CTRL_VALUE_USBC_EVENT
|
||||
else:
|
||||
warnings.warn("HW does not support 'USB-C' events")
|
||||
|
||||
@@ -767,8 +769,8 @@ class EventFilterUsbc(EventFilter):
|
||||
"""
|
||||
if self._hw_caps is not None and self._hw_caps.states:
|
||||
if enable:
|
||||
self.config |= TSI_PDC_LOG_CTRL_VALUE_USBC_STATE
|
||||
self.config |= ci.TSI_PDC_LOG_CTRL_VALUE_USBC_STATE
|
||||
else:
|
||||
self.config &= ~TSI_PDC_LOG_CTRL_VALUE_USBC_STATE
|
||||
self.config &= ~ci.TSI_PDC_LOG_CTRL_VALUE_USBC_STATE
|
||||
else:
|
||||
warnings.warn("HW does not support 'USB-C Port State' events")
|
||||
|
||||
@@ -113,7 +113,7 @@ def save_to_bin_file(path: str, events: list, index=None):
|
||||
|
||||
|
||||
def save_to_csv_file(path: str, events: list):
|
||||
with (open(path, 'w', newline='') as file):
|
||||
with open(path, 'w', newline='') as file:
|
||||
writer = csv.writer(file, delimiter=';')
|
||||
writer.writerow(["Source", "Type", "Start", "Brief info", "Full info"])
|
||||
for data in events:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_DPRX_LOG_IF_SEL, TSI_HDRX_LOG_IF_SEL, TSI_DPRX_LOG_CTRL_VALUE_LINK_PAT, \
|
||||
TSI_DPRX_VBID_LOG_SEL, TSI_DPRX_MSA_LOG_SEL, TSI_PDC_USBC_LOG_THRESH
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
|
||||
|
||||
class AdditionalEventFilter:
|
||||
@@ -31,7 +30,7 @@ class AdditionalSDPEventFilter(AdditionalEventFilter):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.ci_control = TSI_DPRX_LOG_IF_SEL
|
||||
self.ci_control = ci.TSI_DPRX_LOG_IF_SEL
|
||||
self.value = [0] * 8
|
||||
|
||||
|
||||
@@ -39,7 +38,7 @@ class AdditionalInfoFrameEventFilter(AdditionalEventFilter):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.ci_control = TSI_HDRX_LOG_IF_SEL
|
||||
self.ci_control = ci.TSI_HDRX_LOG_IF_SEL
|
||||
self.value = [0] * 8
|
||||
|
||||
|
||||
@@ -47,7 +46,7 @@ class AdditionalLinkPatternEventFilter(AdditionalEventFilter):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.ci_control = TSI_DPRX_LOG_CTRL_VALUE_LINK_PAT
|
||||
self.ci_control = ci.TSI_DPRX_LOG_CTRL_VALUE_LINK_PAT
|
||||
self.value = [0] * 3
|
||||
|
||||
|
||||
@@ -55,7 +54,7 @@ class AdditionalVBIDEventFilter(AdditionalEventFilter):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.ci_control = TSI_DPRX_VBID_LOG_SEL
|
||||
self.ci_control = ci.TSI_DPRX_VBID_LOG_SEL
|
||||
self.value = 0
|
||||
|
||||
|
||||
@@ -63,7 +62,7 @@ class AdditionalMSAEventFilter(AdditionalEventFilter):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.ci_control = TSI_DPRX_MSA_LOG_SEL
|
||||
self.ci_control = ci.TSI_DPRX_MSA_LOG_SEL
|
||||
self.value = 0
|
||||
|
||||
|
||||
@@ -71,5 +70,5 @@ class AdditionalLSEEventFilter(AdditionalEventFilter):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.ci_control = TSI_PDC_USBC_LOG_THRESH
|
||||
self.ci_control = ci.TSI_PDC_USBC_LOG_THRESH
|
||||
self.value = [0] * 5
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import warnings
|
||||
|
||||
from UniTAP.dev.modules.capturer.result_object import ResultObject
|
||||
from UniTAP.libs.lib_tsi.tsi import TSIEventParser
|
||||
import UniTAP.libs.lib_tsi.tsi as tsi
|
||||
from .event_utils import save_to_bin_file, save_to_csv_file, save_to_txt_file, save_to_html_file
|
||||
from .event_types import EventFileFormat
|
||||
|
||||
@@ -96,7 +96,7 @@ class ResultEventObject(ResultObject):
|
||||
warnings.warn("Buffer size is equal 0.")
|
||||
|
||||
def __parse_buffer(self):
|
||||
with TSIEventParser() as parser:
|
||||
with tsi.TSIEventParser() as parser:
|
||||
for index, item in enumerate(self.buffer):
|
||||
if len(item.data) > 12:
|
||||
res = parser.parse(item.data, to_dict=True)
|
||||
|
||||
@@ -52,6 +52,36 @@ class VideoCapturer:
|
||||
"""
|
||||
return self.__max_stream_number
|
||||
|
||||
def start(self, frames_count: int = 0, sec: int = 0, capture_type: CaptureConfig.Type = CaptureConfig.Type.LIVE):
|
||||
"""
|
||||
Start capturing. Possible some variants of capturing:
|
||||
- Capture with fixed frames count (will be captured fixed frames count and capturing will be stopped).
|
||||
- Capture with fixed time (capturing will be continued fixed seconds and capturing will be stopped).
|
||||
- Capture without parameters - Live capturing (for getting frames you need to use functions `pop_element` and
|
||||
`pop_all_elements`)
|
||||
|
||||
All results can be obtained using the function `capture_result`.
|
||||
|
||||
Args:
|
||||
frames_count (int)
|
||||
sec (int)
|
||||
type (CaptureConfig.Type)
|
||||
"""
|
||||
|
||||
config = CaptureConfig()
|
||||
config.video = True
|
||||
config.type = capture_type
|
||||
|
||||
self.__capturer.start_capture(config)
|
||||
|
||||
self.capture_result.clear()
|
||||
self.capture_result.start_capture_time = time.time()
|
||||
|
||||
if frames_count > 0:
|
||||
self.capture_result.buffer.extend(self.__capturer.capture_video_by_n_frames(frames_count, capture_type))
|
||||
elif sec > 0:
|
||||
self.capture_result.buffer.extend(self.__capturer.capture_video_by_n_sec(sec))
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
Stop capture video.
|
||||
@@ -127,8 +157,8 @@ class VideoCapturerDP(VideoCapturer):
|
||||
super().__init__(capturer, max_stream_number)
|
||||
self.__capturer = capturer
|
||||
|
||||
def start(self, frames_count: int = 0, sec: int = 0, stream_number: int = 0,
|
||||
capture_type: CaptureConfig.Type = CaptureConfig.Type.LIVE):
|
||||
def start(self, frames_count: int = 0, sec: int = 0, capture_type: CaptureConfig.Type = CaptureConfig.Type.LIVE,
|
||||
stream_number: int = 0):
|
||||
"""
|
||||
Start capturing. Possible some variants of capturing:
|
||||
- Capture with fixed frames count (will be captured fixed frames count and capturing will be stopped).
|
||||
@@ -150,21 +180,7 @@ class VideoCapturerDP(VideoCapturer):
|
||||
f"{', '.join([str(i) for i in range(self.max_stream_number)])}")
|
||||
|
||||
self.__capturer.set_video_stream_number(stream_number)
|
||||
|
||||
config = CaptureConfig()
|
||||
config.video = True
|
||||
config.type = capture_type
|
||||
|
||||
self.__capturer.start_capture(config)
|
||||
|
||||
self.capture_result.clear()
|
||||
self.capture_result.start_capture_time = time.time()
|
||||
|
||||
if frames_count > 0:
|
||||
self.capture_result.buffer.extend(self.__capturer.capture_video_by_n_frames(frames_count, capture_type))
|
||||
elif sec > 0:
|
||||
self.capture_result.buffer.extend(self.__capturer.capture_video_by_n_sec(sec))
|
||||
|
||||
super().start(frames_count, sec, capture_type)
|
||||
|
||||
def get_buffer_capacity(self, stream_number: int = 0):
|
||||
return self.__capturer.get_buffer_capacity(stream_number)
|
||||
@@ -182,43 +198,5 @@ class VideoCapturerHDMI(VideoCapturer):
|
||||
super().__init__(capturer, max_stream_number)
|
||||
self.__capturer = capturer
|
||||
|
||||
def start(self, frames_count: int = 0, sec: int = 0, stream_number: int = 0):
|
||||
"""
|
||||
Start capturing. Possible some variants of capturing:
|
||||
- Capture with fixed frames count (will be captured fixed frames count and capturing will be stopped).
|
||||
- Capture with fixed time (capturing will be continued fixed seconds and capturing will be stopped).
|
||||
- Capture without parameters - Live capturing (for getting frames you need to use functions `pop_element` and
|
||||
`pop_all_elements`)
|
||||
|
||||
All results can be obtained using the function `capture_result`.
|
||||
|
||||
Args:
|
||||
frames_count (int)
|
||||
sec (int)
|
||||
stream_number (int)
|
||||
"""
|
||||
|
||||
if stream_number >= self.max_stream_number:
|
||||
assert ValueError(f"Incorrect index of stream. Value must be from available options: "
|
||||
f"{', '.join([str(i) for i in range(self.max_stream_number)])}")
|
||||
|
||||
config = CaptureConfig()
|
||||
config.video = True
|
||||
config.type = CaptureConfig.Type.LIVE
|
||||
|
||||
self.__capturer.start_capture(config)
|
||||
|
||||
self.capture_result.clear()
|
||||
self.capture_result.start_capture_time = time.time()
|
||||
|
||||
if frames_count > 0:
|
||||
if frames_count > 1:
|
||||
self.capture_result.buffer.extend(self.__capturer.capture_video_by_n_frames(frames_count))
|
||||
else:
|
||||
self.capture_result.buffer.extend(self.__capturer.capture_video_by_n_frames(frames_count))
|
||||
elif sec > 0:
|
||||
self.capture_result.buffer.extend(self.__capturer.capture_video_by_n_sec(sec))
|
||||
|
||||
|
||||
def get_buffer_capacity(self):
|
||||
return self.__capturer.get_buffer_capacity()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
from UniTAP.libs.lib_tsi.tsi import *
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from .cec_types import *
|
||||
from .cec_private_types import *
|
||||
from typing import Union
|
||||
@@ -29,7 +29,7 @@ class CecRx:
|
||||
Args:
|
||||
state (`bool`)
|
||||
"""
|
||||
self.__io.set(TSI_HDRX_CEC_CONTROL, state, c_uint32)
|
||||
self.__io.set(ci.TSI_HDRX_CEC_CONTROL, state, c_uint32)
|
||||
|
||||
def is_enabled(self) -> bool:
|
||||
"""
|
||||
@@ -38,7 +38,7 @@ class CecRx:
|
||||
Returns:
|
||||
object of `bool` type
|
||||
"""
|
||||
return self.__io.get(TSI_HDRX_CEC_CONTROL, c_uint32)[1] & 0x1 == 1
|
||||
return self.__io.get(ci.TSI_HDRX_CEC_CONTROL, c_uint32)[1] & 0x1 == 1
|
||||
|
||||
@property
|
||||
def logical_address(self) -> LogicalAddressEnum:
|
||||
@@ -48,11 +48,11 @@ class CecRx:
|
||||
Returns:
|
||||
object of `LogicalAddressEnum` type
|
||||
"""
|
||||
return LogicalAddressEnum(self.__io.get(TSI_HDRX_CEC_LOGICAL_ADDRESS, c_uint32)[1])
|
||||
return LogicalAddressEnum(self.__io.get(ci.TSI_HDRX_CEC_LOGICAL_ADDRESS, c_uint32)[1])
|
||||
|
||||
@logical_address.setter
|
||||
def logical_address(self, address: LogicalAddressEnum):
|
||||
self.__io.set(TSI_HDRX_CEC_LOGICAL_ADDRESS, address.value, c_uint32)
|
||||
self.__io.set(ci.TSI_HDRX_CEC_LOGICAL_ADDRESS, address.value, c_uint32)
|
||||
|
||||
@property
|
||||
def destination(self) -> LogicalAddressEnum:
|
||||
@@ -62,11 +62,11 @@ class CecRx:
|
||||
Returns:
|
||||
object of `LogicalAddressEnum` type
|
||||
"""
|
||||
return LogicalAddressEnum(self.__io.get(TSI_HDRX_CEC_DESTINATION, c_uint32)[1])
|
||||
return LogicalAddressEnum(self.__io.get(ci.TSI_HDRX_CEC_DESTINATION, c_uint32)[1])
|
||||
|
||||
@destination.setter
|
||||
def destination(self, address: LogicalAddressEnum):
|
||||
self.__io.set(TSI_HDRX_CEC_DESTINATION, address.value, c_uint32)
|
||||
self.__io.set(ci.TSI_HDRX_CEC_DESTINATION, address.value, c_uint32)
|
||||
|
||||
@property
|
||||
def phy_address(self) -> int:
|
||||
@@ -76,11 +76,11 @@ class CecRx:
|
||||
Returns:
|
||||
object of `int` type
|
||||
"""
|
||||
return self.__io.get(TSI_HDRX_CEC_PHYSICAL_ADDRESS, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDRX_CEC_PHYSICAL_ADDRESS, c_uint32)[1]
|
||||
|
||||
@phy_address.setter
|
||||
def phy_address(self, address: int):
|
||||
self.__io.set(TSI_HDRX_CEC_PHYSICAL_ADDRESS, address, c_uint32)
|
||||
self.__io.set(ci.TSI_HDRX_CEC_PHYSICAL_ADDRESS, address, c_uint32)
|
||||
|
||||
@property
|
||||
def op_code(self) -> int:
|
||||
@@ -90,11 +90,11 @@ class CecRx:
|
||||
Returns:
|
||||
object of `int` type
|
||||
"""
|
||||
return self.__io.get(TSI_HDRX_CEC_OP_CODE, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDRX_CEC_OP_CODE, c_uint32)[1]
|
||||
|
||||
@op_code.setter
|
||||
def op_code(self, code: int):
|
||||
self.__io.set(TSI_HDRX_CEC_OP_CODE, code, c_uint32)
|
||||
self.__io.set(ci.TSI_HDRX_CEC_OP_CODE, code, c_uint32)
|
||||
|
||||
@property
|
||||
def op_code_param(self) -> Union[int, list]:
|
||||
@@ -104,12 +104,12 @@ class CecRx:
|
||||
Returns:
|
||||
object of `int` type
|
||||
"""
|
||||
return self.__io.get(TSI_HDRX_CEC_OP_CODE_PARAM, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDRX_CEC_OP_CODE_PARAM, c_uint32)[1]
|
||||
|
||||
@op_code_param.setter
|
||||
def op_code_param(self, code_param: Union[int, list]):
|
||||
data_count = len(code_param) if isinstance(code_param, list) else 1
|
||||
self.__io.set(TSI_HDRX_CEC_OP_CODE_PARAM, code_param, c_uint32, data_count=data_count)
|
||||
self.__io.set(ci.TSI_HDRX_CEC_OP_CODE_PARAM, code_param, c_uint32, data_count=data_count)
|
||||
|
||||
@property
|
||||
def device_type(self) -> DeviceType:
|
||||
@@ -119,7 +119,7 @@ class CecRx:
|
||||
Returns:
|
||||
object of `DeviceType` type
|
||||
"""
|
||||
data = self.__io.get(TSI_HDRX_CEC_DEVICE_TYPE, DeviceTypePrivate)[1]
|
||||
data = self.__io.get(ci.TSI_HDRX_CEC_DEVICE_TYPE, DeviceTypePrivate)[1]
|
||||
return DeviceType(data.cecSwitch, data.audioSystem, data.pbDevice, data.tuner, data.recDev, data.tv)
|
||||
|
||||
@device_type.setter
|
||||
@@ -134,7 +134,7 @@ class CecRx:
|
||||
value = dev_type & 0xFF
|
||||
else:
|
||||
raise TypeError(f"Unsupported type: {type(dev_type)}")
|
||||
self.__io.set(TSI_HDRX_CEC_DEVICE_TYPE, value, c_uint32)
|
||||
self.__io.set(ci.TSI_HDRX_CEC_DEVICE_TYPE, value, c_uint32)
|
||||
|
||||
@property
|
||||
def status(self) -> CECStatus:
|
||||
@@ -144,7 +144,7 @@ class CecRx:
|
||||
Returns:
|
||||
object of `CECStatus` type
|
||||
"""
|
||||
data = self.__io.get(TSI_HDRX_CEC_STATUS_R, CECStatusPrivate)[1]
|
||||
data = self.__io.get(ci.TSI_HDRX_CEC_STATUS_R, CECStatusPrivate)[1]
|
||||
return CECStatus(data.bufferOverflowed)
|
||||
|
||||
@property
|
||||
@@ -155,7 +155,7 @@ class CecRx:
|
||||
Returns:
|
||||
object of `int` type
|
||||
"""
|
||||
return self.__io.get(TSI_HDRX_CEC_RECEIVED_CNT_R, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDRX_CEC_RECEIVED_CNT_R, c_uint32)[1]
|
||||
|
||||
@property
|
||||
def data(self) -> list:
|
||||
@@ -165,8 +165,8 @@ class CecRx:
|
||||
Returns:
|
||||
object of `list` type
|
||||
"""
|
||||
data_size = self.__io.get(TSI_HDRX_CEC_DATA_SIZE_R, c_uint32)[1]
|
||||
return self.__io.get(TSI_HDRX_CEC_DATA_RECIEVED, c_uint32, data_size)[1]
|
||||
data_size = self.__io.get(ci.TSI_HDRX_CEC_DATA_SIZE_R, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDRX_CEC_DATA_RECIEVED, c_uint32, data_size)[1]
|
||||
|
||||
def reset_data(self, command: CecResetDataCommand):
|
||||
"""
|
||||
@@ -175,10 +175,10 @@ class CecRx:
|
||||
Returns:
|
||||
object of `CecResetDataCommand` type
|
||||
"""
|
||||
self.__io.set(TSI_HDRX_CEC_DATA_RESET_W, command.value, c_uint32)
|
||||
self.__io.set(ci.TSI_HDRX_CEC_DATA_RESET_W, command.value, c_uint32)
|
||||
|
||||
def __read_version(self) -> (int, int):
|
||||
version = self.__io.get(TSI_HDRX_CEC_VERSION_R, CECVersion)[1]
|
||||
version = self.__io.get(ci.TSI_HDRX_CEC_VERSION_R, CECVersion)[1]
|
||||
return version.minor, version.major
|
||||
|
||||
def add_command(self, command: CECCommand = CECCommand()):
|
||||
@@ -250,7 +250,7 @@ class CecRx:
|
||||
self.__send_cec_command()
|
||||
|
||||
def __send_cec_command(self):
|
||||
self.__io.set(TSI_HDRX_CEC_COMMAND, 1, c_uint32)
|
||||
self.__io.set(ci.TSI_HDRX_CEC_COMMAND, 1, c_uint32)
|
||||
|
||||
@property
|
||||
def commands(self) -> list:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
from UniTAP.libs.lib_tsi.tsi import *
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from .cec_types import *
|
||||
from .cec_private_types import *
|
||||
from typing import Union
|
||||
@@ -29,7 +29,7 @@ class CecTx:
|
||||
Args:
|
||||
state (`bool`)
|
||||
"""
|
||||
self.__io.set(TSI_HDTX_CEC_CONTROL, state, c_uint32)
|
||||
self.__io.set(ci.TSI_HDTX_CEC_CONTROL, state, c_uint32)
|
||||
|
||||
def is_enabled(self) -> bool:
|
||||
"""
|
||||
@@ -38,7 +38,7 @@ class CecTx:
|
||||
Returns:
|
||||
object of `bool` type
|
||||
"""
|
||||
return self.__io.get(TSI_HDTX_CEC_CONTROL, c_uint32)[1] & 0x1 == 1
|
||||
return self.__io.get(ci.TSI_HDTX_CEC_CONTROL, c_uint32)[1] & 0x1 == 1
|
||||
|
||||
@property
|
||||
def logical_address(self) -> LogicalAddressEnum:
|
||||
@@ -48,11 +48,11 @@ class CecTx:
|
||||
Returns:
|
||||
object of `LogicalAddressEnum` type
|
||||
"""
|
||||
return LogicalAddressEnum(self.__io.get(TSI_HDTX_CEC_LOGICAL_ADDRESS, c_uint32)[1])
|
||||
return LogicalAddressEnum(self.__io.get(ci.TSI_HDTX_CEC_LOGICAL_ADDRESS, c_uint32)[1])
|
||||
|
||||
@logical_address.setter
|
||||
def logical_address(self, address: LogicalAddressEnum):
|
||||
self.__io.set(TSI_HDTX_CEC_LOGICAL_ADDRESS, address.value, c_uint32)
|
||||
self.__io.set(ci.TSI_HDTX_CEC_LOGICAL_ADDRESS, address.value, c_uint32)
|
||||
|
||||
@property
|
||||
def destination(self) -> LogicalAddressEnum:
|
||||
@@ -62,11 +62,11 @@ class CecTx:
|
||||
Returns:
|
||||
object of `LogicalAddressEnum` type
|
||||
"""
|
||||
return LogicalAddressEnum(self.__io.get(TSI_HDTX_CEC_DESTINATION, c_uint32)[1])
|
||||
return LogicalAddressEnum(self.__io.get(ci.TSI_HDTX_CEC_DESTINATION, c_uint32)[1])
|
||||
|
||||
@destination.setter
|
||||
def destination(self, address: LogicalAddressEnum):
|
||||
self.__io.set(TSI_HDTX_CEC_DESTINATION, address.value, c_uint32)
|
||||
self.__io.set(ci.TSI_HDTX_CEC_DESTINATION, address.value, c_uint32)
|
||||
|
||||
@property
|
||||
def phy_address(self) -> int:
|
||||
@@ -76,11 +76,11 @@ class CecTx:
|
||||
Returns:
|
||||
object of `int` type
|
||||
"""
|
||||
return self.__io.get(TSI_HDTX_CEC_PHYSICAL_ADDRESS, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDTX_CEC_PHYSICAL_ADDRESS, c_uint32)[1]
|
||||
|
||||
@phy_address.setter
|
||||
def phy_address(self, address: int):
|
||||
self.__io.set(TSI_HDTX_CEC_PHYSICAL_ADDRESS, address, c_uint32)
|
||||
self.__io.set(ci.TSI_HDTX_CEC_PHYSICAL_ADDRESS, address, c_uint32)
|
||||
|
||||
@property
|
||||
def op_code(self) -> int:
|
||||
@@ -90,11 +90,11 @@ class CecTx:
|
||||
Returns:
|
||||
object of `int` type
|
||||
"""
|
||||
return self.__io.get(TSI_HDTX_CEC_OP_CODE, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDTX_CEC_OP_CODE, c_uint32)[1]
|
||||
|
||||
@op_code.setter
|
||||
def op_code(self, code: int):
|
||||
self.__io.set(TSI_HDTX_CEC_OP_CODE, code, c_uint32)
|
||||
self.__io.set(ci.TSI_HDTX_CEC_OP_CODE, code, c_uint32)
|
||||
|
||||
@property
|
||||
def op_code_param(self) -> Union[int, list]:
|
||||
@@ -104,12 +104,12 @@ class CecTx:
|
||||
Returns:
|
||||
object of `int` type
|
||||
"""
|
||||
return self.__io.get(TSI_HDTX_CEC_OP_CODE_PARAM, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDTX_CEC_OP_CODE_PARAM, c_uint32)[1]
|
||||
|
||||
@op_code_param.setter
|
||||
def op_code_param(self, code_param: Union[int, list]):
|
||||
data_count = len(code_param) if isinstance(code_param, list) else 1
|
||||
self.__io.set(TSI_HDTX_CEC_OP_CODE_PARAM, code_param, c_uint32, data_count=data_count)
|
||||
self.__io.set(ci.TSI_HDTX_CEC_OP_CODE_PARAM, code_param, c_uint32, data_count=data_count)
|
||||
|
||||
@property
|
||||
def device_type(self) -> DeviceType:
|
||||
@@ -119,7 +119,7 @@ class CecTx:
|
||||
Returns:
|
||||
object of `DeviceType` type
|
||||
"""
|
||||
data = self.__io.get(TSI_HDTX_CEC_DEVICE_TYPE, DeviceTypePrivate)[1]
|
||||
data = self.__io.get(ci.TSI_HDTX_CEC_DEVICE_TYPE, DeviceTypePrivate)[1]
|
||||
return DeviceType(data.cecSwitch, data.audioSystem, data.pbDevice, data.tuner, data.recDev, data.tv)
|
||||
|
||||
@device_type.setter
|
||||
@@ -134,7 +134,7 @@ class CecTx:
|
||||
value = dev_type & 0xFF
|
||||
else:
|
||||
raise TypeError(f"Unsupported type: {type(dev_type)}")
|
||||
self.__io.set(TSI_HDTX_CEC_DEVICE_TYPE, value, c_uint32)
|
||||
self.__io.set(ci.TSI_HDTX_CEC_DEVICE_TYPE, value, c_uint32)
|
||||
|
||||
@property
|
||||
def status(self) -> CECStatus:
|
||||
@@ -144,7 +144,7 @@ class CecTx:
|
||||
Returns:
|
||||
object of `CECStatus` type
|
||||
"""
|
||||
data = self.__io.get(TSI_HDTX_CEC_STATUS_R, CECStatusPrivate)[1]
|
||||
data = self.__io.get(ci.TSI_HDTX_CEC_STATUS_R, CECStatusPrivate)[1]
|
||||
return CECStatus(data.bufferOverflowed)
|
||||
|
||||
@property
|
||||
@@ -155,7 +155,7 @@ class CecTx:
|
||||
Returns:
|
||||
object of `int` type
|
||||
"""
|
||||
return self.__io.get(TSI_HDTX_CEC_RECEIVED_CNT_R, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDTX_CEC_RECEIVED_CNT_R, c_uint32)[1]
|
||||
|
||||
@property
|
||||
def data(self) -> list:
|
||||
@@ -165,8 +165,8 @@ class CecTx:
|
||||
Returns:
|
||||
object of `list` type
|
||||
"""
|
||||
data_size = self.__io.get(TSI_HDTX_CEC_DATA_SIZE_R, c_uint32)[1]
|
||||
return self.__io.get(TSI_HDTX_CEC_DATA_RECEIVED_R, c_uint32, data_size)[1]
|
||||
data_size = self.__io.get(ci.TSI_HDTX_CEC_DATA_SIZE_R, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDTX_CEC_DATA_RECEIVED_R, c_uint32, data_size)[1]
|
||||
|
||||
def reset_data(self, command: CecResetDataCommand):
|
||||
"""
|
||||
@@ -175,10 +175,10 @@ class CecTx:
|
||||
Returns:
|
||||
object of `CecResetDataCommand` type
|
||||
"""
|
||||
self.__io.set(TSI_HDTX_CEC_DATA_RESET_W, command.value, c_uint32)
|
||||
self.__io.set(ci.TSI_HDTX_CEC_DATA_RESET_W, command.value, c_uint32)
|
||||
|
||||
def __read_version(self) -> (int, int):
|
||||
version = self.__io.get(TSI_HDTX_CEC_VERSION_R, CECVersion)[1]
|
||||
version = self.__io.get(ci.TSI_HDTX_CEC_VERSION_R, CECVersion)[1]
|
||||
return version.minor, version.major
|
||||
|
||||
def add_command(self, command: CECCommand = CECCommand()):
|
||||
@@ -250,7 +250,7 @@ class CecTx:
|
||||
self.__send_cec_command()
|
||||
|
||||
def __send_cec_command(self):
|
||||
self.__io.set(TSI_HDTX_CEC_COMMAND, 1, c_uint32)
|
||||
self.__io.set(ci.TSI_HDTX_CEC_COMMAND, 1, c_uint32)
|
||||
|
||||
@property
|
||||
def commands(self) -> list:
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import os
|
||||
from ctypes import c_ubyte
|
||||
from typing import Union, Tuple
|
||||
|
||||
from UniTAP.libs.lib_tsi.tsi import *
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
|
||||
|
||||
class DPCDRegion:
|
||||
@@ -129,7 +130,7 @@ class DPCDRegisters:
|
||||
data = bytearray(data)
|
||||
|
||||
result = self.__io.set(self.__base_ci, base)
|
||||
if result < TSI_SUCCESS:
|
||||
if result < ci.TSI_SUCCESS:
|
||||
return result
|
||||
result = self.__io.set(self.__data_ci, data, c_ubyte, len(data))
|
||||
return result
|
||||
|
||||
2
UniTAP/dev/ports/modules/earc/__init__.py
Normal file
2
UniTAP/dev/ports/modules/earc/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from .earc_types import EarcMode
|
||||
from .earc_tx import EarcTx
|
||||
83
UniTAP/dev/ports/modules/earc/earc_tx.py
Normal file
83
UniTAP/dev/ports/modules/earc/earc_tx.py
Normal file
@@ -0,0 +1,83 @@
|
||||
from ctypes import c_ubyte
|
||||
|
||||
from UniTAP.dev.ports.modules.ag.earc import AudioGeneratorEARC
|
||||
from UniTAP.dev.modules.memory_manager import MemoryManager
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
|
||||
from .earc_types import EarcControl, EarcMode, EarcStatus, EarcState, EarcHearthbeatState, EarcRxStatus
|
||||
|
||||
class EarcTx:
|
||||
__MAX_EARC_EDID_SIZE = 128
|
||||
|
||||
def __init__(self, port_io: PortIO, memory_manager: MemoryManager) -> None:
|
||||
self.__io = port_io
|
||||
self.__earc_ag = AudioGeneratorEARC(port_io, memory_manager)
|
||||
self.__control = self.__io.get(ci.TSI_HDRX_EARC_CTRL, EarcControl)[1]
|
||||
|
||||
def configure(self, mode: EarcMode, latency: int, bypass: bool = False) -> None:
|
||||
self.__control.mode = mode
|
||||
self.__control.bypass = bypass
|
||||
self.__apply_control()
|
||||
self.__set_audio_latency(latency)
|
||||
|
||||
def get_status(self) -> EarcStatus:
|
||||
"""
|
||||
Get eARC transmitter status.
|
||||
|
||||
Returns:
|
||||
object of `EarcStatus` type.
|
||||
"""
|
||||
return self.__io.get(ci.TSI_HDRX_EARC_STS_R, EarcStatus)[1]
|
||||
|
||||
def get_latency(self) -> int:
|
||||
"""
|
||||
Get current audio latency for eARC transmitter.
|
||||
|
||||
Returns:
|
||||
object of `int` type.
|
||||
"""
|
||||
return self.__io.get(ci.TSI_HDRX_EARC_LATENCY, int)[1]
|
||||
|
||||
def get_edid(self) -> bytearray:
|
||||
"""
|
||||
Get EDID data from eARC receiver.
|
||||
|
||||
Returns:
|
||||
object of `bytearray` type.
|
||||
"""
|
||||
result, edid_data, size = self.__io.get(ci.TSI_HDRX_EARC_EDID_DATA, c_ubyte, self.__MAX_EARC_EDID_SIZE)
|
||||
if result > 0:
|
||||
return bytearray(edid_data[:result])
|
||||
else:
|
||||
return bytearray()
|
||||
|
||||
@property
|
||||
def ag(self) -> AudioGeneratorEARC:
|
||||
"""
|
||||
Get audio generator for eARC transmitter.
|
||||
|
||||
Returns:
|
||||
object of `AudioGeneratorEARC` type.
|
||||
"""
|
||||
return self.__earc_ag
|
||||
|
||||
def __apply_control(self):
|
||||
"""
|
||||
Apply eARC control settings.
|
||||
"""
|
||||
self.__io.set(ci.TSI_HDRX_EARC_CTRL, self.__control)
|
||||
|
||||
def __set_audio_latency(self, latency: int):
|
||||
"""
|
||||
Set audio latency request for eARC transmitter.
|
||||
|
||||
Args:
|
||||
latency (int) - latency value to set
|
||||
"""
|
||||
self.__io.set(ci.TSI_HDRX_EARC_LATENCY_REQ, latency)
|
||||
|
||||
|
||||
|
||||
112
UniTAP/dev/ports/modules/earc/earc_types.py
Normal file
112
UniTAP/dev/ports/modules/earc/earc_types.py
Normal file
@@ -0,0 +1,112 @@
|
||||
from enum import IntEnum
|
||||
from ctypes import c_uint32, Structure
|
||||
|
||||
from UniTAP.utils.bit_ops import get_bitfield, set_bitfield
|
||||
|
||||
class EarcMode(IntEnum):
|
||||
"""
|
||||
Describes possible eArc modes.
|
||||
"""
|
||||
Disabled = 0
|
||||
eArc = 1
|
||||
Legacy = 2
|
||||
eArcNone = 3
|
||||
|
||||
class EarcState(IntEnum):
|
||||
"""
|
||||
Describes possible eArc states.
|
||||
"""
|
||||
H14bARC = 0
|
||||
IDLE1 = 1
|
||||
IDLE2 = 2
|
||||
DISC1 = 3
|
||||
DISC2 = 4
|
||||
EARC = 5
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
class EarcHearthbeatState(IntEnum):
|
||||
"""
|
||||
Describes possible eArc states.
|
||||
"""
|
||||
LOST = 0
|
||||
SUCCESS = 1
|
||||
FAIL = 2
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
class EarcRxStatus(IntEnum):
|
||||
"""
|
||||
Describes possible eArc RX statuses.
|
||||
"""
|
||||
INVALID = 0
|
||||
STAT_CHNG = 1
|
||||
CAP_CHNG = 2
|
||||
EARC_HPD = 4
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
class EarcStatus(Structure):
|
||||
__EARC_STATE_OFFSET = 0
|
||||
__EARC_STATE_MASK = 0xF << __EARC_STATE_OFFSET
|
||||
|
||||
__EARC_HEARTHBEAT_OFFSET = 4
|
||||
__EARC_HEARTHBEAT_MASK = 0xF << __EARC_HEARTHBEAT_OFFSET
|
||||
|
||||
__EARC_RX_STATUS_OFFSET = 8
|
||||
__EARC_RX_STATUS_MASK = 0xF << __EARC_RX_STATUS_OFFSET
|
||||
|
||||
_fields_ = [
|
||||
('data', c_uint32, 32)
|
||||
]
|
||||
|
||||
def __init__(self, value: int) -> None:
|
||||
self.data = value
|
||||
|
||||
@property
|
||||
def earc_state(self) -> EarcState:
|
||||
return EarcState(get_bitfield(self.data, self.__EARC_STATE_MASK, self.__EARC_STATE_OFFSET))
|
||||
|
||||
@property
|
||||
def earc_hearthbeat(self) -> EarcHearthbeatState:
|
||||
return EarcHearthbeatState(get_bitfield(self.data, self.__EARC_HEARTHBEAT_MASK, self.__EARC_HEARTHBEAT_OFFSET))
|
||||
|
||||
@property
|
||||
def earc_rx_status(self) -> EarcRxStatus:
|
||||
return EarcRxStatus(get_bitfield(self.data, self.__EARC_RX_STATUS_MASK, self.__EARC_RX_STATUS_OFFSET))
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"EarcStatus(state={self.earc_state}, heartbeat={self.earc_hearthbeat}, rx_status={self.earc_rx_status})"
|
||||
|
||||
class EarcControl(Structure):
|
||||
__EARC_MODE_OFFSET = 0
|
||||
__EARC_MODE_MASK = 0x7 << __EARC_MODE_OFFSET
|
||||
|
||||
__EARC_BYPASS_OFFSET = 3
|
||||
__EARC_BYPASS_MASK = 0x1 << __EARC_BYPASS_OFFSET
|
||||
|
||||
_fields_ = [
|
||||
('data', c_uint32, 32)
|
||||
]
|
||||
|
||||
def __init__(self, value: int) -> None:
|
||||
self.data = value
|
||||
|
||||
@property
|
||||
def mode(self) -> EarcMode:
|
||||
return EarcMode(get_bitfield(self.data, self.__EARC_MODE_MASK, self.__EARC_MODE_OFFSET))
|
||||
|
||||
@mode.setter
|
||||
def mode(self, value: EarcMode):
|
||||
self.data = set_bitfield(self.data, self.__EARC_MODE_MASK, self.__EARC_MODE_OFFSET, value.value)
|
||||
|
||||
@property
|
||||
def bypass(self) -> bool:
|
||||
return bool(get_bitfield(self.data, self.__EARC_BYPASS_MASK, self.__EARC_BYPASS_OFFSET))
|
||||
|
||||
@bypass.setter
|
||||
def bypass(self, value: bool):
|
||||
self.data = set_bitfield(self.data, self.__EARC_BYPASS_MASK, self.__EARC_BYPASS_OFFSET, int(value))
|
||||
@@ -3,10 +3,7 @@ from typing import List
|
||||
|
||||
from UniTAP.common import Timing
|
||||
|
||||
from UniTAP.libs.lib_tsi.tsi_types import TSI_EDID_SELECT_STREAM, TSI_EDID_TE_INPUT, TSI_EDID_TE_OUTPUT, \
|
||||
TSI_EDID_TE_OUTPUT_REMOTE_R, TSI_DID_TE_OUTPUT, TSI_DID_TE_INPUT, TSI_DID_SELECT_STREAM, \
|
||||
TSI_DID_TE_OUTPUT_REMOTE_R, TSI_DPRX_DISPLAYID_CTRL, TSI_DPTX_DISPLAYID_CTRL, TSI_EDID_DUT_TIMINGS_COUNT, \
|
||||
TSI_EDID_DUT_TIMINGS_DATA
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
from UniTAP.dev.ports.modules.device_constants import MAX_EDID_SIZE
|
||||
from ctypes import c_ubyte, c_uint32
|
||||
@@ -67,12 +64,12 @@ class Edid:
|
||||
"""
|
||||
|
||||
"""
|
||||
timings_count = self._io.get(TSI_EDID_DUT_TIMINGS_COUNT, c_uint32)[1]
|
||||
timings_count = self._io.get(ci.TSI_EDID_DUT_TIMINGS_COUNT, c_uint32)[1]
|
||||
|
||||
if timings_count == 0:
|
||||
return []
|
||||
|
||||
timings = self._io.get(TSI_EDID_DUT_TIMINGS_DATA, ParsedTimingStruct, timings_count)[1]
|
||||
timings = self._io.get(ci.TSI_EDID_DUT_TIMINGS_DATA, ParsedTimingStruct, timings_count)[1]
|
||||
parsed_timings = []
|
||||
|
||||
for i in range(timings_count):
|
||||
@@ -123,7 +120,7 @@ class EdidSource(Edid):
|
||||
"""
|
||||
|
||||
def __init__(self, port_io: PortIO, max_stream_count: int):
|
||||
super().__init__(port_io, TSI_EDID_TE_OUTPUT, max_stream_count, TSI_EDID_SELECT_STREAM)
|
||||
super().__init__(port_io, ci.TSI_EDID_TE_OUTPUT, max_stream_count, ci.TSI_EDID_SELECT_STREAM)
|
||||
|
||||
def read_sbm(self, stream: int):
|
||||
"""
|
||||
@@ -137,7 +134,7 @@ class EdidSource(Edid):
|
||||
|
||||
"""
|
||||
self._select_stream(stream)
|
||||
result, edid_data, size = self._io.get(TSI_EDID_TE_OUTPUT_REMOTE_R, c_ubyte, MAX_EDID_SIZE)
|
||||
result, edid_data, size = self._io.get(ci.TSI_EDID_TE_OUTPUT_REMOTE_R, c_ubyte, MAX_EDID_SIZE)
|
||||
if result > 0:
|
||||
return bytearray(edid_data[:result])
|
||||
else:
|
||||
@@ -153,7 +150,7 @@ class EdidSink(Edid):
|
||||
"""
|
||||
|
||||
def __init__(self, port_io: PortIO, max_stream_count: int):
|
||||
super().__init__(port_io, TSI_EDID_TE_INPUT, max_stream_count, TSI_EDID_SELECT_STREAM)
|
||||
super().__init__(port_io, ci.TSI_EDID_TE_INPUT, max_stream_count, ci.TSI_EDID_SELECT_STREAM)
|
||||
|
||||
def write_edid(self, data: bytearray, stream: int = 0):
|
||||
"""
|
||||
@@ -216,7 +213,7 @@ class DisplayIdSource(Edid):
|
||||
"""
|
||||
|
||||
def __init__(self, port_io: PortIO, max_stream_count: int):
|
||||
super().__init__(port_io, TSI_DID_TE_OUTPUT, max_stream_count, TSI_DID_SELECT_STREAM)
|
||||
super().__init__(port_io, ci.TSI_DID_TE_OUTPUT, max_stream_count, ci.TSI_DID_SELECT_STREAM)
|
||||
|
||||
def read_sbm(self, stream: int):
|
||||
"""
|
||||
@@ -230,7 +227,7 @@ class DisplayIdSource(Edid):
|
||||
|
||||
"""
|
||||
self._select_stream(stream)
|
||||
result, data, size = self._io.get(TSI_DID_TE_OUTPUT_REMOTE_R, c_ubyte, MAX_EDID_SIZE)
|
||||
result, data, size = self._io.get(ci.TSI_DID_TE_OUTPUT_REMOTE_R, c_ubyte, MAX_EDID_SIZE)
|
||||
if result > 0:
|
||||
return bytearray(data[:result])
|
||||
else:
|
||||
@@ -243,7 +240,7 @@ class DisplayIdSource(Edid):
|
||||
Args:
|
||||
mode (`DisplayIDReadMode`)
|
||||
"""
|
||||
self._io.set(TSI_DPTX_DISPLAYID_CTRL, mode.value, c_uint32)
|
||||
self._io.set(ci.TSI_DPTX_DISPLAYID_CTRL, mode.value, c_uint32)
|
||||
|
||||
def get_display_id_mode(self) -> DisplayIDReadMode:
|
||||
"""
|
||||
@@ -252,7 +249,7 @@ class DisplayIdSource(Edid):
|
||||
Returns:
|
||||
object of `DisplayIDReadMode` type.
|
||||
"""
|
||||
result = self._io.get(TSI_DPTX_DISPLAYID_CTRL, c_uint32)[1]
|
||||
result = self._io.get(ci.TSI_DPTX_DISPLAYID_CTRL, c_uint32)[1]
|
||||
return DisplayIDReadMode(result)
|
||||
|
||||
|
||||
@@ -265,7 +262,7 @@ class DisplayIdSink(Edid):
|
||||
"""
|
||||
|
||||
def __init__(self, port_io: PortIO, max_stream_count: int):
|
||||
super().__init__(port_io, TSI_DID_TE_INPUT, max_stream_count, TSI_DID_SELECT_STREAM)
|
||||
super().__init__(port_io, ci.TSI_DID_TE_INPUT, max_stream_count, ci.TSI_DID_SELECT_STREAM)
|
||||
|
||||
def is_enabled(self) -> bool:
|
||||
"""
|
||||
@@ -274,7 +271,7 @@ class DisplayIdSink(Edid):
|
||||
Returns:
|
||||
object of `bool` type.
|
||||
"""
|
||||
result = self._io.get(TSI_DPRX_DISPLAYID_CTRL, c_uint32)
|
||||
result = self._io.get(ci.TSI_DPRX_DISPLAYID_CTRL, c_uint32)
|
||||
status_display_id = ((result[1] & 0x1) != 0)
|
||||
return bool(status_display_id)
|
||||
|
||||
@@ -286,7 +283,7 @@ class DisplayIdSink(Edid):
|
||||
enable (bool) - enable (True) or disable (False)
|
||||
"""
|
||||
val = 0x1 if enable else 0x0
|
||||
self._io.set(TSI_DPRX_DISPLAYID_CTRL, val)
|
||||
self._io.set(ci.TSI_DPRX_DISPLAYID_CTRL, val)
|
||||
|
||||
def write_display_id(self, data: bytearray):
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
from UniTAP.libs.lib_tsi.tsi import *
|
||||
from ctypes import c_int
|
||||
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
|
||||
from .fec_shared import FECCounters
|
||||
@@ -27,7 +29,7 @@ class FecRx:
|
||||
Returns:
|
||||
object of `bool` type.
|
||||
"""
|
||||
result = self.__io.get(TSI_DPRX_FEC_STATUS_R, c_int)
|
||||
result = self.__io.get(ci.TSI_DPRX_FEC_STATUS_R, c_int)
|
||||
status_fec = ((result[1] & 0x1) != 0)
|
||||
return bool(status_fec)
|
||||
|
||||
@@ -38,7 +40,7 @@ class FecRx:
|
||||
Returns:
|
||||
object of `bool` type.
|
||||
"""
|
||||
result = self.__io.get(TSI_DPRX_FEC_CTRL, c_int)
|
||||
result = self.__io.get(ci.TSI_DPRX_FEC_CTRL, c_int)
|
||||
enabled_fec = (result[1] & 0x1) != 0
|
||||
return enabled_fec
|
||||
|
||||
@@ -50,7 +52,7 @@ class FecRx:
|
||||
enable (bool) - enable (True) or disable (False)
|
||||
"""
|
||||
val = 0x1 if enable else 0x0
|
||||
self.__io.set(TSI_DPRX_FEC_CTRL, val)
|
||||
self.__io.set(ci.TSI_DPRX_FEC_CTRL, val)
|
||||
|
||||
def aggregate_errors(self, enable: bool):
|
||||
"""
|
||||
@@ -59,7 +61,7 @@ class FecRx:
|
||||
Args:
|
||||
enable (bool) - enable (True) or disable (False)
|
||||
"""
|
||||
result = self.__io.get(TSI_DPRX_FEC_CONTROL, c_int)
|
||||
result = self.__io.get(ci.TSI_DPRX_FEC_CONTROL, c_int)
|
||||
val = result[1]
|
||||
if enable:
|
||||
val |= 0x2
|
||||
@@ -67,7 +69,7 @@ class FecRx:
|
||||
else:
|
||||
val &= ~0x2
|
||||
self.__aggregate_error = 0
|
||||
self.__io.set(TSI_DPRX_FEC_CONTROL, val)
|
||||
self.__io.set(ci.TSI_DPRX_FEC_CONTROL, val)
|
||||
|
||||
def get_error_counters(self) -> FECCounters:
|
||||
"""
|
||||
@@ -78,7 +80,7 @@ class FecRx:
|
||||
object of `FECCounters` type
|
||||
"""
|
||||
result = FECCounters()
|
||||
lane_count = self.__io.get(TSI_R_DPRX_LINK_LANE_COUNT, c_int)[1]
|
||||
lane_count = self.__io.get(ci.TSI_R_DPRX_LINK_LANE_COUNT, c_int)[1]
|
||||
if lane_count == 4:
|
||||
lane_count += 1 if self.__aggregate_error else 0
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
from UniTAP.libs.lib_tsi.tsi import *
|
||||
from ctypes import c_int, c_uint32
|
||||
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
|
||||
from .fec_shared import FECCounters, FECErrorType8b10b, FECErrorType128b132b
|
||||
from UniTAP.dev.ports.modules.dpcd.dpcd import DPCDRegisters
|
||||
@@ -29,7 +32,7 @@ class FecTx:
|
||||
Returns:
|
||||
object of `bool` type.
|
||||
"""
|
||||
result = self.__io.get(TSI_DPTX_FEC_STATUS_R, c_int)
|
||||
result = self.__io.get(ci.TSI_DPTX_FEC_STATUS_R, c_int)
|
||||
status_fec = ((result[1] & 0x1) != 0)
|
||||
return bool(status_fec)
|
||||
|
||||
@@ -40,7 +43,7 @@ class FecTx:
|
||||
Returns:
|
||||
object of `bool` type.
|
||||
"""
|
||||
result = self.__io.get(TSI_DPTX_FEC_CTRL, c_int)
|
||||
result = self.__io.get(ci.TSI_DPTX_FEC_CTRL, c_int)
|
||||
enabled_fec = (result[1] & 0x2) != 0
|
||||
return enabled_fec
|
||||
|
||||
@@ -51,10 +54,10 @@ class FecTx:
|
||||
Args:
|
||||
enable (bool) - enable (True) or disable (False)
|
||||
"""
|
||||
result = self.__io.get(TSI_DPTX_FEC_CTRL, c_int)
|
||||
result = self.__io.get(ci.TSI_DPTX_FEC_CTRL, c_int)
|
||||
val = result[1]
|
||||
val |= 0x8 if enable else 0x10
|
||||
self.__io.set(TSI_DPTX_FEC_CTRL, val)
|
||||
self.__io.set(ci.TSI_DPTX_FEC_CTRL, val)
|
||||
|
||||
def enable_intent(self, enable: bool):
|
||||
"""
|
||||
@@ -63,10 +66,10 @@ class FecTx:
|
||||
Args:
|
||||
enable (bool) - enable (True) or disable (False)
|
||||
"""
|
||||
result = self.__io.get(TSI_DPTX_FEC_CTRL, c_int)
|
||||
result = self.__io.get(ci.TSI_DPTX_FEC_CTRL, c_int)
|
||||
val = result[1]
|
||||
val |= 1 if enable else 4
|
||||
self.__io.set(TSI_DPTX_FEC_CTRL, val)
|
||||
self.__io.set(ci.TSI_DPTX_FEC_CTRL, val)
|
||||
|
||||
def aggregate_errors(self, enable: bool):
|
||||
"""
|
||||
@@ -75,7 +78,7 @@ class FecTx:
|
||||
Args:
|
||||
enable (bool) - enable (True) or disable (False)
|
||||
"""
|
||||
result = self.__io.get(TSI_DPTX_FEC_CONTROL, c_int)
|
||||
result = self.__io.get(ci.TSI_DPTX_FEC_CONTROL, c_int)
|
||||
val = result[1]
|
||||
if enable:
|
||||
val |= 0x40
|
||||
@@ -83,7 +86,7 @@ class FecTx:
|
||||
else:
|
||||
val &= ~0x40
|
||||
self.__aggregate_error = 0
|
||||
self.__io.set(TSI_DPTX_FEC_CONTROL, val)
|
||||
self.__io.set(ci.TSI_DPTX_FEC_CONTROL, val)
|
||||
|
||||
def generate_errors(self, error_type: Union[FECErrorType8b10b, FECErrorType128b132b], lane: list, ms: int = 100):
|
||||
"""
|
||||
@@ -94,8 +97,8 @@ class FecTx:
|
||||
lane (list)
|
||||
ms (int) - time in m seconds
|
||||
"""
|
||||
result, status = self.__io.get(TSI_DPTX_LINK_MODE_R, c_int)
|
||||
resut, hw_caps, size = self.__io.get(TSI_DPTX_HW_CAPS_R, c_uint32, 4)
|
||||
result, status = self.__io.get(ci.TSI_DPTX_LINK_MODE_R, c_int)
|
||||
resut, hw_caps, size = self.__io.get(ci.TSI_DPTX_HW_CAPS_R, c_uint32, 4)
|
||||
if status == 0:
|
||||
if isinstance(error_type, FECErrorType128b132b):
|
||||
assert False, "This device doesn't support 128b/132b" if (hw_caps[1] & 0x7) == 0 else "Change link mode!"
|
||||
@@ -109,24 +112,24 @@ class FecTx:
|
||||
|
||||
delay = ms * 100
|
||||
|
||||
self.__io.set(TSI_MLEG_CONTROL, 0)
|
||||
nl = self.__io.get(TSI_R_DPTX_LINK_STATUS_LANE_COUNT, c_uint32)[1]
|
||||
self.__io.set(p_ci.TSI_MLEG_CONTROL, 0)
|
||||
nl = self.__io.get(ci.TSI_R_DPTX_LINK_STATUS_LANE_COUNT, c_uint32)[1]
|
||||
|
||||
self.__io.set(TSI_MLEG_SYMBOL_REPLACE_A, 0x00010000)
|
||||
self.__io.set(TSI_MLEG_SYMBOL_REPLACE_MASK_A, 0x00010001)
|
||||
self.__io.set(TSI_MLEG_SYMBOL_REPLACE_B, 0x00000001)
|
||||
self.__io.set(TSI_MLEG_SYMBOL_REPLACE_MASK_B, 0x00010001)
|
||||
self.__io.set(p_ci.TSI_MLEG_SYMBOL_REPLACE_A, 0x00010000)
|
||||
self.__io.set(p_ci.TSI_MLEG_SYMBOL_REPLACE_MASK_A, 0x00010001)
|
||||
self.__io.set(p_ci.TSI_MLEG_SYMBOL_REPLACE_B, 0x00000001)
|
||||
self.__io.set(p_ci.TSI_MLEG_SYMBOL_REPLACE_MASK_B, 0x00010001)
|
||||
|
||||
self.__io.set(TSI_MLEG_DELAY_COUNTER, delay)
|
||||
self.__io.set(p_ci.TSI_MLEG_DELAY_COUNTER, delay)
|
||||
|
||||
n = lane[0] << 16
|
||||
self.__io.set(TSI_MLEG_LANE0_REPLACE_COUNTERS, n)
|
||||
self.__io.set(p_ci.TSI_MLEG_LANE0_REPLACE_COUNTERS, n)
|
||||
n = lane[1] << 16
|
||||
self.__io.set(TSI_MLEG_LANE1_REPLACE_COUNTERS, n)
|
||||
self.__io.set(p_ci.TSI_MLEG_LANE1_REPLACE_COUNTERS, n)
|
||||
n = lane[2] << 16
|
||||
self.__io.set(TSI_MLEG_LANE2_REPLACE_COUNTERS, n)
|
||||
self.__io.set(p_ci.TSI_MLEG_LANE2_REPLACE_COUNTERS, n)
|
||||
n = lane[3] << 16
|
||||
self.__io.set(TSI_MLEG_LANE3_REPLACE_COUNTERS, n)
|
||||
self.__io.set(p_ci.TSI_MLEG_LANE3_REPLACE_COUNTERS, n)
|
||||
|
||||
ctrl = 0
|
||||
ctrl |= (error_type.value << 16)
|
||||
@@ -144,7 +147,7 @@ class FecTx:
|
||||
if lane[3]:
|
||||
ctrl |= (1 << 3)
|
||||
|
||||
self.__io.set(TSI_MLEG_CONTROL, ctrl)
|
||||
self.__io.set(p_ci.TSI_MLEG_CONTROL, ctrl)
|
||||
|
||||
def get_error_counters(self) -> FECCounters:
|
||||
"""
|
||||
@@ -154,7 +157,7 @@ class FecTx:
|
||||
object of `FECCounters` type
|
||||
"""
|
||||
result = FECCounters()
|
||||
lane_count = self.__io.get(TSI_R_DPTX_LINK_STATUS_LANE_COUNT, c_uint32)[1]
|
||||
lane_count = self.__io.get(ci.TSI_R_DPTX_LINK_STATUS_LANE_COUNT, c_uint32)[1]
|
||||
if lane_count == 4:
|
||||
lane_count += 1 if self.__aggregate_error else 0
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import warnings
|
||||
from typing import Optional, Union
|
||||
from ctypes import c_int
|
||||
from typing import Optional, Union, Type
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO, PortProtocol
|
||||
from .types import *
|
||||
from UniTAP.libs.lib_tsi.tsi import c_int
|
||||
|
||||
|
||||
class HdcpSinkStatus:
|
||||
@@ -77,7 +78,7 @@ class HdcpSinkStatus:
|
||||
|
||||
def __read_status(self, mode: HdcpMode) -> int:
|
||||
if mode == HdcpMode.Mode1_4:
|
||||
return self.__io.get(TSI_HDCP_1X_STATUS_R, c_int)[1]
|
||||
return self.__io.get(ci.TSI_HDCP_1X_STATUS_R, c_int)[1]
|
||||
else:
|
||||
return self.__io.get(self.__ci_status_control, c_int)[1]
|
||||
|
||||
@@ -164,7 +165,7 @@ class HdcpSinkConfig:
|
||||
if keys == HdcpSink2XKeys.Production and not self.__caps_2x.production_keys_available:
|
||||
warnings.warn("Production keys is not hw supported. Please, select another keys.")
|
||||
|
||||
self.__io.set(TSI_HDCP_1X_COMMAND_W if hdcp_mode == HdcpMode.Mode1_4 else TSI_HDCP_2X_COMMAND_W, keys.value)
|
||||
self.__io.set(ci.TSI_HDCP_1X_COMMAND_W if hdcp_mode == HdcpMode.Mode1_4 else ci.TSI_HDCP_2X_COMMAND_W, keys.value)
|
||||
|
||||
def __set_capable(self, value: Optional[bool], hdcp_mode: HdcpMode):
|
||||
if value is None:
|
||||
@@ -172,9 +173,10 @@ class HdcpSinkConfig:
|
||||
if not self.__full_check(hdcp_mode):
|
||||
return
|
||||
|
||||
self.__io.set(TSI_HDCP_1X_COMMAND_W if hdcp_mode == HdcpMode.Mode1_4 else TSI_HDCP_2X_COMMAND_W,
|
||||
(H1_SINK_SET_CAPABLE if value else H1_SINK_CLEAR_CAPABLE)
|
||||
if hdcp_mode == HdcpMode.Mode1_4 else (H2_SINK_SET_CAPABLE if value else H2_SINK_CLEAR_CAPABLE))
|
||||
self.__io.set(ci.TSI_HDCP_1X_COMMAND_W if hdcp_mode == HdcpMode.Mode1_4 else ci.TSI_HDCP_2X_COMMAND_W,
|
||||
(ci.H1_SINK_SET_CAPABLE if value else ci.H1_SINK_CLEAR_CAPABLE)
|
||||
if hdcp_mode == HdcpMode.Mode1_4 else (
|
||||
ci.H2_SINK_SET_CAPABLE if value else ci.H2_SINK_CLEAR_CAPABLE))
|
||||
|
||||
def __full_check(self, hdcp_mode: HdcpMode) -> bool:
|
||||
if hdcp_mode == HdcpMode.Unknown:
|
||||
@@ -239,7 +241,7 @@ class HdcpSink:
|
||||
|
||||
def __read_hw_caps(self, mode: HdcpMode, ci_caps_control: int = 0) -> int:
|
||||
if mode == HdcpMode.Mode1_4:
|
||||
return self.__io.get(TSI_HDCP_1X_STATUS_R, c_int)[1]
|
||||
return self.__io.get(ci.TSI_HDCP_1X_STATUS_R, c_int)[1]
|
||||
elif mode == HdcpMode.Mode2_3:
|
||||
return self.__io.get(ci_caps_control, c_int)[1]
|
||||
else:
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import warnings
|
||||
from typing import Optional, Union
|
||||
from typing import Optional, Union, Type
|
||||
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO, PortProtocol
|
||||
from .types import *
|
||||
from UniTAP.libs.lib_tsi.tsi_private_types import *
|
||||
from ctypes import c_int
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
from ctypes import c_int, c_uint32
|
||||
|
||||
|
||||
class HdcpSourceStatus:
|
||||
@@ -52,10 +53,18 @@ class HdcpSourceStatus:
|
||||
if self.__caps_1x.hw_supported:
|
||||
status_value = self.__read_status(HdcpMode.Mode1_4)
|
||||
status = HdcpStatus.Status1x()
|
||||
|
||||
if (status_value >> 9) & 1:
|
||||
status.keys = HdcpSource1XKeys.Test
|
||||
elif (status_value >> 10) & 1:
|
||||
status.keys = HdcpSource1XKeys.Production
|
||||
else:
|
||||
status.keys = HdcpSource1XKeys.Unload
|
||||
|
||||
status.active = (status_value >> 8) & 1
|
||||
status.keys = HdcpSource1XKeys(((status_value >> 9) & 3) + 0x100)
|
||||
status.capable = ((status_value >> 11) & 1)
|
||||
status.authenticated = ((status_value >> 12) & 1)
|
||||
|
||||
return status
|
||||
else:
|
||||
warnings.warn(f"Not supported 'HDCP 1.4'")
|
||||
@@ -63,9 +72,7 @@ class HdcpSourceStatus:
|
||||
if self.__caps_2x.hw_supported:
|
||||
status_value = self.__read_status(HdcpMode.Mode2_3)
|
||||
status = HdcpStatus.StatusTx2x()
|
||||
if self.__io.protocol() == PortProtocol.HDMI:
|
||||
status.keys = HdcpSource2XKeys.Production if (status_value >> 9) & 1 else HdcpSource2XKeys.Unload
|
||||
else:
|
||||
|
||||
if (status_value >> 14) & 1:
|
||||
status.keys = HdcpSource2XKeys.TestR1
|
||||
elif (status_value >> 15) & 1:
|
||||
@@ -78,7 +85,7 @@ class HdcpSourceStatus:
|
||||
status.km_is_stored = (status_value >> 13) & 1
|
||||
status.try_authenticate = (status_value >> 18) & 1
|
||||
status.try_encrypt = (status_value >> 19) & 1
|
||||
status.content_level = self.__io.get(TSI_HDCP_2X_CFG, c_uint32)[1]
|
||||
status.content_level = self.__io.get(p_ci.TSI_HDCP_2X_CFG, c_uint32)[1]
|
||||
|
||||
status.active = (status_value >> 8) & 1
|
||||
status.capable = (status_value >> 10) & 1
|
||||
@@ -90,7 +97,7 @@ class HdcpSourceStatus:
|
||||
|
||||
def __read_status(self, mode: HdcpMode):
|
||||
if mode == HdcpMode.Mode1_4:
|
||||
return self.__io.get(TSI_HDCP_1X_STATUS_R, c_int)[1]
|
||||
return self.__io.get(ci.TSI_HDCP_1X_STATUS_R, c_int)[1]
|
||||
elif mode == HdcpMode.Mode2_3:
|
||||
return self.__io.get(self.__ci_status_control, c_int)[1]
|
||||
else:
|
||||
@@ -172,17 +179,17 @@ class HdcpSourceConfig:
|
||||
if value is None:
|
||||
return
|
||||
if hdcp_mode == HdcpMode.Mode1_4:
|
||||
self.__io.set(TSI_HDCP_1X_COMMAND_W, H1_SOURCE_ENABLE_ENCRYPT if value else H1_SOURCE_DISABLE_ENCRYPT)
|
||||
self.__io.set(ci.TSI_HDCP_1X_COMMAND_W, ci.H1_SOURCE_ENABLE_ENCRYPT if value else ci.H1_SOURCE_DISABLE_ENCRYPT)
|
||||
elif hdcp_mode == HdcpMode.Mode2_3:
|
||||
self.__io.set(TSI_HDCP_2X_COMMAND_W, H2_SOURCE_ENABLE_ENCRYPT if value else H2_SOURCE_DISABLE_ENCRYPT)
|
||||
self.__io.set(ci.TSI_HDCP_2X_COMMAND_W, ci.H2_SOURCE_ENABLE_ENCRYPT if value else ci.H2_SOURCE_DISABLE_ENCRYPT)
|
||||
|
||||
def __set_authenticate(self, value: Optional[bool], hdcp_mode: HdcpMode):
|
||||
if value is None:
|
||||
return
|
||||
if hdcp_mode == HdcpMode.Mode1_4:
|
||||
self.__io.set(TSI_HDCP_1X_COMMAND_W, H1_SOURCE_AUTHENTICATE if value else H1_SOURCE_DE_AUTHENTICATE)
|
||||
self.__io.set(ci.TSI_HDCP_1X_COMMAND_W, ci.H1_SOURCE_AUTHENTICATE if value else ci.H1_SOURCE_DE_AUTHENTICATE)
|
||||
elif hdcp_mode == HdcpMode.Mode2_3:
|
||||
self.__io.set(TSI_HDCP_2X_COMMAND_W, H2_SOURCE_AUTHENTICATE if value else H2_SOURCE_DE_AUTHENTICATE)
|
||||
self.__io.set(ci.TSI_HDCP_2X_COMMAND_W, ci.H2_SOURCE_AUTHENTICATE if value else ci.H2_SOURCE_DE_AUTHENTICATE)
|
||||
|
||||
def __load_keys(self, keys: Optional[Union[HdcpSource1XKeys, HdcpSource2XKeys]], hdcp_mode: HdcpMode):
|
||||
if keys is None:
|
||||
@@ -203,7 +210,7 @@ class HdcpSourceConfig:
|
||||
if keys == HdcpSource2XKeys.Production and not self.__caps_2x.production_keys_available:
|
||||
warnings.warn("Production keys is not hw supported. Please, select another keys.")
|
||||
|
||||
self.__io.set(TSI_HDCP_1X_COMMAND_W if hdcp_mode == HdcpMode.Mode1_4 else TSI_HDCP_2X_COMMAND_W, keys.value)
|
||||
self.__io.set(ci.TSI_HDCP_1X_COMMAND_W if hdcp_mode == HdcpMode.Mode1_4 else ci.TSI_HDCP_2X_COMMAND_W, keys.value)
|
||||
|
||||
def __full_check(self, hdcp_mode: HdcpMode) -> bool:
|
||||
if hdcp_mode == HdcpMode.Unknown:
|
||||
@@ -231,14 +238,14 @@ class HdcpSourceConfig:
|
||||
def __set_store_km(self, value: Optional[bool]):
|
||||
if value is None:
|
||||
return
|
||||
self.__io.set(TSI_HDCP_2X_COMMAND_W, H2_SOURCE_AUTHENTICATE_STORE_KM if value else H2_SOURCE_CLEAR_STORE_KM)
|
||||
self.__io.set(ci.TSI_HDCP_2X_COMMAND_W, ci.H2_SOURCE_AUTHENTICATE_STORE_KM if value else ci.H2_SOURCE_CLEAR_STORE_KM)
|
||||
|
||||
def __set_content_level(self, value: Optional[int]):
|
||||
if value is None:
|
||||
return
|
||||
if value not in [0, 1]:
|
||||
raise ValueError(f"Incorrect input value of 'Content level' - {value}. Must be from range: 0-1")
|
||||
self.__io.set(TSI_HDCP_2X_CFG, value)
|
||||
self.__io.set(p_ci.TSI_HDCP_2X_CFG, value)
|
||||
|
||||
|
||||
class HdcpSource:
|
||||
@@ -280,7 +287,7 @@ class HdcpSource:
|
||||
|
||||
def __read_hw_caps(self, mode: HdcpMode, ci_caps_control: int = 0) -> int:
|
||||
if mode == HdcpMode.Mode1_4:
|
||||
return self.__io.get(TSI_HDCP_1X_STATUS_R, c_int)[1]
|
||||
return self.__io.get(ci.TSI_HDCP_1X_STATUS_R, c_int)[1]
|
||||
elif mode == HdcpMode.Mode2_3:
|
||||
return self.__io.get(ci_caps_control, c_int)[1]
|
||||
else:
|
||||
|
||||
@@ -1,38 +1,37 @@
|
||||
from typing import TypeVar
|
||||
|
||||
from UniTAP.libs.lib_tsi.tsi_types import *
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from enum import IntEnum
|
||||
from typing import Type
|
||||
|
||||
|
||||
class HdcpSink1XKeys(IntEnum):
|
||||
Unknown = -1
|
||||
Unload = H1_SINK_UNLOAD_KEYS
|
||||
Test = H1_SINK_LOAD_TEST_KEYS
|
||||
Production = H1_SINK_LOAD_PROD_KEYS
|
||||
Unload = ci.H1_SINK_UNLOAD_KEYS
|
||||
Test = ci.H1_SINK_LOAD_TEST_KEYS
|
||||
Production = ci.H1_SINK_LOAD_PROD_KEYS
|
||||
|
||||
|
||||
class HdcpSink2XKeys(IntEnum):
|
||||
Unknown = -1
|
||||
Unload = H2_SINK_UNLOAD_KEYS
|
||||
Production = H2_SINK_LOAD_PROD_KEYS
|
||||
TestR1 = H2_SINK_LOAD_TEST_KEYS_R1
|
||||
TestR2 = H2_SINK_LOAD_TEST_KEYS_R2
|
||||
Unload = ci.H2_SINK_UNLOAD_KEYS
|
||||
Production = ci.H2_SINK_LOAD_PROD_KEYS
|
||||
TestR1 = ci.H2_SINK_LOAD_TEST_KEYS_R1
|
||||
TestR2 = ci.H2_SINK_LOAD_TEST_KEYS_R2
|
||||
|
||||
|
||||
class HdcpSource1XKeys(IntEnum):
|
||||
Unknown = -1
|
||||
Unload = H1_SOURCE_UNLOAD_KEYS
|
||||
Test = H1_SOURCE_LOAD_TEST_KEYS
|
||||
Production = H1_SOURCE_LOAD_PROD_KEYS
|
||||
Unload = ci.H1_SOURCE_UNLOAD_KEYS
|
||||
Test = ci.H1_SOURCE_LOAD_TEST_KEYS
|
||||
Production = ci.H1_SOURCE_LOAD_PROD_KEYS
|
||||
|
||||
|
||||
class HdcpSource2XKeys(IntEnum):
|
||||
Unknown = -1
|
||||
Unload = H2_SOURCE_UNLOAD_KEYS
|
||||
Production = H2_SOURCE_LOAD_PROD_KEYS
|
||||
TestR1 = H2_SOURCE_LOAD_TEST_KEYS_R1
|
||||
TestR2 = H2_SOURCE_LOAD_TEST_KEYS_R2
|
||||
Unload = ci.H2_SOURCE_UNLOAD_KEYS
|
||||
Production = ci.H2_SOURCE_LOAD_PROD_KEYS
|
||||
TestR1 = ci.H2_SOURCE_LOAD_TEST_KEYS_R1
|
||||
TestR2 = ci.H2_SOURCE_LOAD_TEST_KEYS_R2
|
||||
|
||||
|
||||
class HdcpMode(IntEnum):
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from .link_rx_caps import LinkDisplayPortCaps
|
||||
from .link_rx_status import *
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from .dp_cable_info import DpCableInfo, CableCapabilitiesEnum
|
||||
from .link_rx_aux_controller import DisplayPortAUXController
|
||||
from UniTAP.dev.ports.modules.dpcd import DPCDRegisters
|
||||
@@ -20,7 +22,7 @@ class LinkDisplayPortRx:
|
||||
self.__HW_CAPS = hw_caps
|
||||
self.__status = LinkDisplayPortStatusSink(port_io, self.__HW_CAPS)
|
||||
self.__capabilities = LinkDisplayPortCaps(port_io, self.__HW_CAPS)
|
||||
self.__cable_info = DpCableInfo(port_io, TSI_DPRX_CABLE_ATTRIBUTES_R)
|
||||
self.__cable_info = DpCableInfo(port_io, p_ci.TSI_DPRX_CABLE_ATTRIBUTES_R)
|
||||
self.__aux_controller = DisplayPortAUXController(port_io, dpcd)
|
||||
|
||||
@property
|
||||
@@ -60,7 +62,7 @@ class LinkDisplayPortRx:
|
||||
Args:
|
||||
duration_us (int)
|
||||
"""
|
||||
self.__io.set(TSI_DPRX_HPD_PULSE_W, duration_us, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_HPD_PULSE_W, duration_us, c_int)
|
||||
|
||||
def set_assert_state(self, state: bool):
|
||||
"""
|
||||
@@ -70,7 +72,7 @@ class LinkDisplayPortRx:
|
||||
state (bool)
|
||||
"""
|
||||
val = 0x1 if state else 0x0
|
||||
self.__io.set(TSI_FORCE_HOT_PLUG_STATE_W, val)
|
||||
self.__io.set(ci.TSI_FORCE_HOT_PLUG_STATE_W, val)
|
||||
|
||||
@property
|
||||
def scrambler_seed(self) -> int:
|
||||
@@ -84,7 +86,7 @@ class LinkDisplayPortRx:
|
||||
warnings.warn("Scrambler Seed is not supported.")
|
||||
return 0
|
||||
|
||||
return self.__io.get(TSI_DPRX_SCR_SEED, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_DPRX_SCR_SEED, c_uint32)[1]
|
||||
|
||||
@scrambler_seed.setter
|
||||
def scrambler_seed(self, value: int = 0):
|
||||
@@ -98,7 +100,7 @@ class LinkDisplayPortRx:
|
||||
raise ValueError(f"Scrambler seed {value} is not available.")
|
||||
|
||||
if self.__HW_CAPS.scrambler_seed:
|
||||
self.__io.set(TSI_DPRX_SCR_SEED, value)
|
||||
self.__io.set(ci.TSI_DPRX_SCR_SEED, value)
|
||||
else:
|
||||
warnings.warn("Scrambler Seed is not supported.")
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
from ctypes import c_uint32, c_int
|
||||
from typing import Optional
|
||||
from UniTAP.libs.lib_tsi import PortIO
|
||||
from UniTAP.libs.lib_tsi.tsi_private_types import *
|
||||
from UniTAP.libs.lib_tsi.tsi_types import *
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from .private_link_rx_types import RoutedLTStatusPrivate
|
||||
from .link_rx_types import RoutedLTStatus, RoutedLTConfig
|
||||
from UniTAP.dev.ports.modules.dpcd import DPCDRegisters
|
||||
@@ -34,7 +35,7 @@ class DisplayPortAUXController:
|
||||
else:
|
||||
ctrl &= ~0x01
|
||||
|
||||
res = self.__io.set(TSI_DPRX_LT_ROUTE_CONTROL_W, ctrl, c_uint32)
|
||||
res = self.__io.set(ci.TSI_DPRX_LT_ROUTE_CONTROL_W, ctrl, c_uint32)
|
||||
if not res:
|
||||
raise Exception("The feature requires a license key and the required license key is not installed.")
|
||||
|
||||
@@ -50,6 +51,7 @@ class DisplayPortAUXController:
|
||||
max_rate_dp14 = 0
|
||||
max_rate_dp20 = 0
|
||||
|
||||
if not config.is_edp_lt:
|
||||
if config.is128b132b:
|
||||
if config.link_bw == 1:
|
||||
max_rate_dp20 = 1
|
||||
@@ -91,12 +93,21 @@ class DisplayPortAUXController:
|
||||
if config.is128b132b:
|
||||
self.__dpcd.write(0x21, 0x01)
|
||||
self.__dpcd.write(0x90, 0xff)
|
||||
edp_data = [0x00] * 16
|
||||
self.__dpcd.write(0x10, edp_data)
|
||||
self.__dpcd.write(0x700, 0x00)
|
||||
dsc_data = [0x0f, 0x21, 0x03, 0x03, 0xeb, 0x07, 0x01, 0x00, 0x00, 0x1f, 0x0e, 0x11, 0x08, 0x07, 0x00, 0x00]
|
||||
self.__dpcd.write(0x60, dsc_data)
|
||||
self.__dpcd.write(0x2217, 0x06)
|
||||
else:
|
||||
self.__dpcd.write(0x21, 0x00)
|
||||
self.__dpcd.write(0x90, 0x00)
|
||||
edp_data = [0x00] * 16
|
||||
if config.is_edp_lt:
|
||||
edp_data[0] = config.link_bw & 0xff
|
||||
edp_data[1] = (config.link_bw >> 8) & 0xff
|
||||
self.__dpcd.write(0x10, edp_data)
|
||||
self.__dpcd.write(0x700, config.is_edp_lt and 0x06 or 0x00)
|
||||
dsc_data = [0x00] * 16
|
||||
self.__dpcd.write(0x60, dsc_data)
|
||||
self.__dpcd.write(0x2217, 0x00)
|
||||
@@ -200,19 +211,19 @@ class DisplayPortAUXController:
|
||||
step=routed_lt_status.step)
|
||||
|
||||
def __set_routed_lt_config(self, value: int) -> bool:
|
||||
res = self.__io.set(TSI_DPRX_LT_ROUTE_CREATE, value, c_uint32)
|
||||
res = self.__io.set(ci.TSI_DPRX_LT_ROUTE_CREATE, value, c_uint32)
|
||||
return res >= 0
|
||||
|
||||
def __set_force_cable_status_to_plugged(self, enable: bool):
|
||||
val = 0x3C if enable else 0
|
||||
self.__io.set(TSI_DPRX_HPD_FORCE, val, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_HPD_FORCE, val, c_int)
|
||||
|
||||
def __read_status(self) -> Optional[RoutedLTStatusPrivate]:
|
||||
res, status = self.__io.get(TSI_DPRX_LT_ROUTE_STATUS_R, RoutedLTStatusPrivate)
|
||||
res, status = self.__io.get(ci.TSI_DPRX_LT_ROUTE_STATUS_R, RoutedLTStatusPrivate)
|
||||
|
||||
if res >= 0:
|
||||
return status
|
||||
return None
|
||||
|
||||
def __generate_short_hpd_pulse(self, value: int):
|
||||
self.__io.set(TSI_DPRX_HPD_PULSE_W, value, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_HPD_PULSE_W, value, c_int)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import warnings
|
||||
from ctypes import c_int, c_uint, c_uint32
|
||||
from typing import List, Optional, Union, Type
|
||||
|
||||
from .link_rx_types import LinkCapabilities, LinkEDPCapabilities, DisplayPortLinkCaps
|
||||
from .private_link_rx_types import DPRXHWCaps, DPRXLinkControl
|
||||
from UniTAP.libs.lib_tsi import PortIO
|
||||
from UniTAP.libs.lib_tsi.tsi_types import *
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
|
||||
|
||||
class LinkDisplayPortCaps:
|
||||
@@ -27,7 +28,8 @@ class LinkDisplayPortCaps:
|
||||
if isinstance(capabilities, LinkCapabilities):
|
||||
self.__set_max_lanes(capabilities.max_lane)
|
||||
self.__set_max_bitrate(capabilities.bit_rate)
|
||||
self.__set_force_cable_status_to_plugged(capabilities.force_cable_status_to_plugged)
|
||||
# TODO: Temporarily disabled for writing value
|
||||
# self.__set_force_cable_status_to_plugged(capabilities.force_cable_status_to_plugged)
|
||||
self.__set_dp_link_control(old_dp2_lt=capabilities.old_dp_2_0_lt)
|
||||
self.__set_dp_128_132_bitrates(capabilities.dp_128_132_bitrates)
|
||||
self.__set_bitrate_override(10.0, capabilities.override_10g)
|
||||
@@ -86,10 +88,10 @@ class LinkDisplayPortCaps:
|
||||
return
|
||||
if lane_count not in [1, 2, 4]:
|
||||
raise ValueError(f"Incorrect lane count number {lane_count}. Must be from list: 1, 2, 4")
|
||||
self.__io.set(TSI_DPRX_MAX_LANES, lane_count, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_MAX_LANES, lane_count, c_int)
|
||||
|
||||
def __get_max_lanes(self) -> int:
|
||||
return self.__io.get(TSI_DPRX_MAX_LANES)[1]
|
||||
return self.__io.get(ci.TSI_DPRX_MAX_LANES)[1]
|
||||
|
||||
def __set_max_bitrate(self, bitrate: Optional[float]):
|
||||
if bitrate is None:
|
||||
@@ -97,10 +99,10 @@ class LinkDisplayPortCaps:
|
||||
bitrate = round(bitrate / 0.27)
|
||||
if bitrate not in [6, 10, 20, 25, 30]:
|
||||
raise ValueError(f"Incorrect bit rate number {bitrate}. Must be from list: 1.62, 2.7, 5.4, 6.75, 8.1")
|
||||
self.__io.set(TSI_DPRX_MAX_LINK_RATE, bitrate, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_MAX_LINK_RATE, bitrate, c_int)
|
||||
|
||||
def __get_max_bitrate(self) -> int:
|
||||
return round(self.__io.get(TSI_DPRX_MAX_LINK_RATE)[1] * 0.27, 2)
|
||||
return round(self.__io.get(ci.TSI_DPRX_MAX_LINK_RATE)[1] * 0.27, 2)
|
||||
|
||||
def __set_bitrate_override(self, to_override: float, with_override: Optional[float]):
|
||||
if with_override is None:
|
||||
@@ -109,19 +111,19 @@ class LinkDisplayPortCaps:
|
||||
if not isinstance(to_override, float) or not isinstance(with_override, float):
|
||||
raise TypeError("DP 128b/132b bitrate override settings must float type!")
|
||||
|
||||
list_value = self.__io.get(TSI_DP2RX_CUSTOM_RATE_MAP, c_uint, 3)[1]
|
||||
list_value = self.__io.get(ci.TSI_DP2RX_CUSTOM_RATE_MAP, c_uint, 3)[1]
|
||||
|
||||
if with_override not in [2.5, 2.7, 5.0, 5.4]:
|
||||
raise ValueError(f"Incorrect bit rate number {with_override}. "
|
||||
f"Must be from list: 2.5, 2.7, 5.0, 5.4")
|
||||
list_value[0] = int(with_override * 1000000000 / 200000)
|
||||
self.__io.set(TSI_DP2RX_CUSTOM_RATE_MAP, list_value, c_uint, 3)
|
||||
self.__io.set(ci.TSI_DP2RX_CUSTOM_RATE_MAP, list_value, c_uint, 3)
|
||||
|
||||
def __get_bitrate_override(self, to_override: float) -> Optional[float]:
|
||||
if not isinstance(to_override, float):
|
||||
raise TypeError("DP 128b/132b bitrate override settings must float type!")
|
||||
|
||||
override_list = self.__io.get(TSI_DP2RX_CUSTOM_RATE_MAP, c_uint, 3)[1]
|
||||
override_list = self.__io.get(ci.TSI_DP2RX_CUSTOM_RATE_MAP, c_uint, 3)[1]
|
||||
if override_list.count(0) == len(override_list):
|
||||
return None
|
||||
|
||||
@@ -138,21 +140,21 @@ class LinkDisplayPortCaps:
|
||||
if edp_aux_preamble is not None:
|
||||
ctrl.edp_aux_preamble = edp_aux_preamble
|
||||
|
||||
self.__io.set(TSI_DPRX_LINK_CONTROL, ctrl.value(), c_uint32)
|
||||
self.__io.set(ci.TSI_DPRX_LINK_CONTROL, ctrl.value(), c_uint32)
|
||||
|
||||
def __get_dp_link_control(self) -> DPRXLinkControl:
|
||||
return self.__io.get(TSI_DPRX_LINK_CONTROL, DPRXLinkControl)[1]
|
||||
return self.__io.get(ci.TSI_DPRX_LINK_CONTROL, DPRXLinkControl)[1]
|
||||
|
||||
def __set_dp_128_132_bitrates(self, rates: Optional[List[float]]):
|
||||
flags = self.__io.get(TSI_DPRX_LINK_FLAGS)[1] & ~0xc0
|
||||
flags = self.__io.get(ci.TSI_DPRX_LINK_FLAGS)[1] & ~0xc0
|
||||
if rates is None:
|
||||
return
|
||||
elif isinstance(rates, list) and len(rates) == 0:
|
||||
flags &= ~(1 << 4)
|
||||
self.__io.set(TSI_DPRX_LINK_FLAGS, flags, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_LINK_FLAGS, flags, c_int)
|
||||
else:
|
||||
flags |= (1 << 4)
|
||||
self.__io.set(TSI_DPRX_LINK_FLAGS, flags, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_LINK_FLAGS, flags, c_int)
|
||||
val = 0
|
||||
if 10.0 in rates:
|
||||
val |= 0x01
|
||||
@@ -160,12 +162,12 @@ class LinkDisplayPortCaps:
|
||||
val |= 0x04
|
||||
if 20.0 in rates:
|
||||
val |= 0x02
|
||||
self.__io.set(TSI_DP2RX_LINK_RATE_CAPS, val, c_int)
|
||||
self.__io.set(ci.TSI_DP2RX_LINK_RATE_CAPS, val, c_int)
|
||||
|
||||
def __get_dp_128_132_bitrates(self) -> Optional[List[float]]:
|
||||
val = (self.__io.get(TSI_DPRX_LINK_FLAGS)[1] >> 4) & 0x1
|
||||
val = (self.__io.get(ci.TSI_DPRX_LINK_FLAGS)[1] >> 4) & 0x1
|
||||
if val:
|
||||
rates = self.__io.get(TSI_DP2RX_LINK_RATE_CAPS)[1]
|
||||
rates = self.__io.get(ci.TSI_DP2RX_LINK_RATE_CAPS)[1]
|
||||
list_rates = []
|
||||
if rates & 0x01:
|
||||
list_rates.append(10.0)
|
||||
@@ -181,47 +183,47 @@ class LinkDisplayPortCaps:
|
||||
if enable is None:
|
||||
return
|
||||
val = 0x3C if enable else 0
|
||||
self.__io.set(TSI_DPRX_HPD_FORCE, val, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_HPD_FORCE, val, c_int)
|
||||
|
||||
def __get_force_cable_status_to_plugged(self) -> bool:
|
||||
return bool(self.__io.get(TSI_DPRX_HPD_FORCE)[1])
|
||||
return bool(self.__io.get(ci.TSI_DPRX_HPD_FORCE)[1])
|
||||
|
||||
def __set_dsc(self, enable: Optional[bool]):
|
||||
if enable is None:
|
||||
return
|
||||
val = 0x1 if enable else 0x0
|
||||
if self.__caps.dsc:
|
||||
self.__io.set(TSI_DPRX_DSC_CONTROL, val, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_DSC_CONTROL, val, c_int)
|
||||
|
||||
def __get_dsc(self) -> Optional[bool]:
|
||||
if self.__io.get(TSI_DPRX_DSC_STATUS_R)[1] & 0x1:
|
||||
return bool(self.__io.get(TSI_DPRX_DSC_CONTROL)[1] & 0x1)
|
||||
if self.__io.get(ci.TSI_DPRX_DSC_STATUS_R)[1] & 0x1:
|
||||
return bool(self.__io.get(ci.TSI_DPRX_DSC_CONTROL)[1] & 0x1)
|
||||
|
||||
def __set_fec(self, enable: Optional[bool]):
|
||||
if enable is None:
|
||||
return
|
||||
val = 0x1 if enable else 0x0
|
||||
if self.__caps.fec:
|
||||
self.__io.set(TSI_DPRX_FEC_CONTROL, val, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_FEC_CONTROL, val, c_int)
|
||||
|
||||
def __get_fec(self) -> Optional[bool]:
|
||||
if self.__caps.fec:
|
||||
return bool(self.__io.get(TSI_DPRX_FEC_CONTROL)[1] & 0x1)
|
||||
return bool(self.__io.get(ci.TSI_DPRX_FEC_CONTROL)[1] & 0x1)
|
||||
|
||||
def __set_mst(self, enable: Optional[bool]):
|
||||
if enable is None:
|
||||
return
|
||||
flags = self.__io.get(TSI_DPRX_LINK_FLAGS)[1] & ~0xc0
|
||||
flags = self.__io.get(ci.TSI_DPRX_LINK_FLAGS)[1] & ~0xc0
|
||||
if enable:
|
||||
flags |= 1
|
||||
else:
|
||||
flags &= ~1
|
||||
if self.__caps.mst:
|
||||
self.__io.set(TSI_DPRX_LINK_FLAGS, flags, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_LINK_FLAGS, flags, c_int)
|
||||
|
||||
def __get_mst(self) -> Optional[bool]:
|
||||
if self.__caps.mst:
|
||||
return bool(self.__io.get(TSI_DPRX_LINK_FLAGS)[1] & 0x1)
|
||||
return bool(self.__io.get(ci.TSI_DPRX_LINK_FLAGS)[1] & 0x1)
|
||||
|
||||
def __set_mst_sink_count(self, count: int):
|
||||
if count is None:
|
||||
@@ -230,73 +232,73 @@ class LinkDisplayPortCaps:
|
||||
if count > self.__caps.mst_stream_count:
|
||||
warnings.warn(f"Maximum sink count: {self.__caps.mst_stream_count}")
|
||||
else:
|
||||
self.__io.set(TSI_DPRX_MST_SINK_COUNT, count, c_uint32)
|
||||
self.__io.set(ci.TSI_DPRX_MST_SINK_COUNT, count, c_uint32)
|
||||
else:
|
||||
warnings.warn("MST or Custom Sink Count are not supported")
|
||||
|
||||
def __get_mst_sink_count(self) -> int:
|
||||
if self.__caps.sink_cnt_config and self.__caps.mst:
|
||||
return int(self.__io.get(TSI_DPRX_MST_SINK_COUNT)[1])
|
||||
return int(self.__io.get(ci.TSI_DPRX_MST_SINK_COUNT)[1])
|
||||
else:
|
||||
return 0
|
||||
|
||||
def __set_tps3(self, enable: Optional[bool]):
|
||||
if enable is None:
|
||||
return
|
||||
flags = self.__io.get(TSI_DPRX_LINK_FLAGS)[1] & ~0xc0
|
||||
flags = self.__io.get(ci.TSI_DPRX_LINK_FLAGS)[1] & ~0xc0
|
||||
if enable:
|
||||
flags |= (1 << 1)
|
||||
else:
|
||||
flags &= ~(1 << 1)
|
||||
if self.__caps.fec:
|
||||
self.__io.set(TSI_DPRX_LINK_FLAGS, flags, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_LINK_FLAGS, flags, c_int)
|
||||
|
||||
def __get_tps3(self) -> Optional[bool]:
|
||||
if self.__caps.fec:
|
||||
return bool((self.__io.get(TSI_DPRX_LINK_FLAGS)[1] >> 1) & 0x1)
|
||||
return bool((self.__io.get(ci.TSI_DPRX_LINK_FLAGS)[1] >> 1) & 0x1)
|
||||
|
||||
def __set_tps4(self, enable: Optional[bool]):
|
||||
if enable is None:
|
||||
return
|
||||
flags = self.__io.get(TSI_DPRX_LINK_FLAGS)[1] & ~0xc0
|
||||
flags = self.__io.get(ci.TSI_DPRX_LINK_FLAGS)[1] & ~0xc0
|
||||
if enable:
|
||||
flags |= (1 << 2)
|
||||
else:
|
||||
flags &= ~(1 << 2)
|
||||
if self.__caps.fec:
|
||||
self.__io.set(TSI_DPRX_LINK_FLAGS, flags, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_LINK_FLAGS, flags, c_int)
|
||||
|
||||
def __get_tps4(self) -> Optional[bool]:
|
||||
if self.__caps.fec:
|
||||
return bool((self.__io.get(TSI_DPRX_LINK_FLAGS)[1] >> 2) & 0x1)
|
||||
return bool((self.__io.get(ci.TSI_DPRX_LINK_FLAGS)[1] >> 2) & 0x1)
|
||||
|
||||
def __set_ss_sbm(self, enable: bool):
|
||||
if enable is None:
|
||||
return
|
||||
if self.__caps.dp2_support_rates:
|
||||
flags = self.__io.get(TSI_DPRX_LINK_FLAGS)[1] & ~0xc0
|
||||
flags = self.__io.get(ci.TSI_DPRX_LINK_FLAGS)[1] & ~0xc0
|
||||
if enable:
|
||||
flags |= (1 << 5)
|
||||
else:
|
||||
flags &= ~(1 << 5)
|
||||
self.__io.set(TSI_DPRX_LINK_FLAGS, flags, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_LINK_FLAGS, flags, c_int)
|
||||
|
||||
def __get_ss_sbm(self) -> Optional[bool]:
|
||||
if self.__caps.dp2_support_rates:
|
||||
return bool((self.__io.get(TSI_DPRX_LINK_FLAGS)[1] >> 5) & 0x1)
|
||||
return bool((self.__io.get(ci.TSI_DPRX_LINK_FLAGS)[1] >> 5) & 0x1)
|
||||
|
||||
def __set_edp_support(self, enable: bool):
|
||||
if self.__caps.edp:
|
||||
flags = self.__io.get(TSI_DPRX_LINK_FLAGS)[1] & ~0xc0
|
||||
flags = self.__io.get(ci.TSI_DPRX_LINK_FLAGS)[1] & ~0xc0
|
||||
if enable:
|
||||
flags |= (1 << 3)
|
||||
else:
|
||||
flags &= ~(1 << 3)
|
||||
self.__io.set(TSI_DPRX_LINK_FLAGS, flags, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_LINK_FLAGS, flags, c_int)
|
||||
|
||||
def __get_edp_support(self) -> Optional[bool]:
|
||||
if self.__caps.edp:
|
||||
return bool((self.__io.get(TSI_DPRX_LINK_FLAGS)[1] >> 3) & 0x1)
|
||||
return bool((self.__io.get(ci.TSI_DPRX_LINK_FLAGS)[1] >> 3) & 0x1)
|
||||
|
||||
def __set_edp_sel_rates(self, rates: List[float]):
|
||||
if self.__caps.edp:
|
||||
@@ -310,11 +312,11 @@ class LinkDisplayPortCaps:
|
||||
j += 1
|
||||
|
||||
rates.sort()
|
||||
self.__io.set(TSI_DPRX_EDP_SEL_RATES, to_write_list, data_type=c_uint32, data_count=8)
|
||||
self.__io.set(ci.TSI_DPRX_EDP_SEL_RATES, to_write_list, data_type=c_uint32, data_count=8)
|
||||
|
||||
def __get_edp_sel_rates(self) -> List[float]:
|
||||
if self.__caps.edp:
|
||||
rates = self.__io.get(TSI_DPRX_EDP_SEL_RATES, data_type=c_uint32, data_count=8)[1]
|
||||
rates = self.__io.get(ci.TSI_DPRX_EDP_SEL_RATES, data_type=c_uint32, data_count=8)[1]
|
||||
res_rates = []
|
||||
for rate in rates:
|
||||
if rate == 0:
|
||||
@@ -324,7 +326,7 @@ class LinkDisplayPortCaps:
|
||||
|
||||
def __get_edp_caps_rates(self) -> List[float]:
|
||||
if self.__caps.edp:
|
||||
rates = self.__io.get(TSI_DPRX_EDP_CAPS_RATES_R, data_type=c_uint32, data_count=32)[1]
|
||||
rates = self.__io.get(ci.TSI_DPRX_EDP_CAPS_RATES_R, data_type=c_uint32, data_count=32)[1]
|
||||
new_rates = []
|
||||
for rate in rates:
|
||||
if rate > 0:
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import time
|
||||
import warnings
|
||||
from ctypes import c_int, c_uint32, c_uint8, c_uint
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from UniTAP.libs.lib_tsi import PortIO
|
||||
from UniTAP.libs.lib_tsi.tsi_private_types import *
|
||||
from UniTAP.libs.lib_tsi.tsi_types import *
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from UniTAP.utils.function_wrapper import function_scheduler
|
||||
from .private_link_rx_types import DPRXHWCaps
|
||||
from .link_status_common import *
|
||||
@@ -48,7 +49,7 @@ class LinkDisplayPortStatusSink:
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
res, value = self.__io.get(TSI_DPRX_MST_STATUS_R, c_uint)
|
||||
res, value = self.__io.get(p_ci.TSI_DPRX_MST_STATUS_R, c_uint)
|
||||
return value >> 8
|
||||
|
||||
@property
|
||||
@@ -59,7 +60,7 @@ class LinkDisplayPortStatusSink:
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__io.get(TSI_DPRX_LINK_LANE_COUNT_R, c_int)[1]
|
||||
return self.__io.get(ci.TSI_DPRX_LINK_LANE_COUNT_R, c_int)[1]
|
||||
|
||||
@property
|
||||
def link_encoding(self) -> DpLinkEncoding:
|
||||
@@ -69,7 +70,7 @@ class LinkDisplayPortStatusSink:
|
||||
Returns:
|
||||
object of `DpLinkEncoding` type
|
||||
"""
|
||||
result, value = self.__io.get(TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint)
|
||||
result, value = self.__io.get(ci.TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint)
|
||||
|
||||
if value >> 20 & 1:
|
||||
return DpLinkEncoding.LE_128b132b
|
||||
@@ -84,7 +85,7 @@ class LinkDisplayPortStatusSink:
|
||||
Returns:
|
||||
object of float type
|
||||
"""
|
||||
current_link_rate = self.__io.get(TSI_DPRX_LINK_BR_R, c_int)[1]
|
||||
current_link_rate = self.__io.get(ci.TSI_DPRX_LINK_BR_R, c_int)[1]
|
||||
if self.link_encoding == DpLinkEncoding.LE_8b10b:
|
||||
return round(current_link_rate * 0.27, 2)
|
||||
else:
|
||||
@@ -105,7 +106,7 @@ class LinkDisplayPortStatusSink:
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return bool(self.__io.get(TSI_DPRX_HPD_STATUS_R, c_int)[1] & 1)
|
||||
return bool(self.__io.get(ci.TSI_DPRX_HPD_STATUS_R, c_int)[1] & 1)
|
||||
|
||||
@property
|
||||
def cable_state(self) -> bool:
|
||||
@@ -115,7 +116,7 @@ class LinkDisplayPortStatusSink:
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return bool(self.__io.get(TSI_DPRX_HPD_STATUS_R, c_int)[1] & 4)
|
||||
return bool(self.__io.get(ci.TSI_DPRX_HPD_STATUS_R, c_int)[1] & 4)
|
||||
|
||||
@property
|
||||
def enhanced_framing(self) -> bool:
|
||||
@@ -125,7 +126,7 @@ class LinkDisplayPortStatusSink:
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return bool((self.__io.get(TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1] >> 17) & 1)
|
||||
return bool((self.__io.get(ci.TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1] >> 17) & 1)
|
||||
|
||||
@property
|
||||
def scrambling_enabled(self) -> bool:
|
||||
@@ -135,7 +136,7 @@ class LinkDisplayPortStatusSink:
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return bool((self.__io.get(TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1] >> 18) & 1)
|
||||
return bool((self.__io.get(ci.TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1] >> 18) & 1)
|
||||
|
||||
@property
|
||||
def dsc_enabled(self) -> Union[bool, None]:
|
||||
@@ -146,7 +147,7 @@ class LinkDisplayPortStatusSink:
|
||||
object of bool|None type
|
||||
"""
|
||||
if self.__caps.dsc or self.__caps.dsc2:
|
||||
return bool((self.__io.get(TSI_DPRX_DSC_STATUS_R)[1] >> 1) & 1)
|
||||
return bool((self.__io.get(ci.TSI_DPRX_DSC_STATUS_R)[1] >> 1) & 1)
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -159,7 +160,7 @@ class LinkDisplayPortStatusSink:
|
||||
object of bool|None type
|
||||
"""
|
||||
if self.__caps.fec or self.__caps.fec2:
|
||||
return bool(self.__io.get(TSI_DPRX_FEC_STATUS_R)[1] & 1)
|
||||
return bool(self.__io.get(ci.TSI_DPRX_FEC_STATUS_R)[1] & 1)
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -172,7 +173,7 @@ class LinkDisplayPortStatusSink:
|
||||
object of bool|None type
|
||||
"""
|
||||
if self.__caps.mst:
|
||||
return bool((self.__io.get(TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1] >> 19) & 1)
|
||||
return bool((self.__io.get(ci.TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1] >> 19) & 1)
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -184,8 +185,8 @@ class LinkDisplayPortStatusSink:
|
||||
Returns:
|
||||
object of bool|None type
|
||||
"""
|
||||
if (self.__io.get(TSI_DPRX_SSC_STATUS_R, c_int)[1] >> 1) & 1:
|
||||
return bool(self.__io.get(TSI_DPRX_SSC_STATUS_R, c_int)[1] & 1)
|
||||
if (self.__io.get(ci.TSI_DPRX_SSC_STATUS_R, c_int)[1] >> 1) & 1:
|
||||
return bool(self.__io.get(ci.TSI_DPRX_SSC_STATUS_R, c_int)[1] & 1)
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -197,7 +198,7 @@ class LinkDisplayPortStatusSink:
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return bool((self.__io.get(TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1] >> 16) & 1)
|
||||
return bool((self.__io.get(ci.TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1] >> 16) & 1)
|
||||
|
||||
@property
|
||||
def eq_ila(self) -> bool:
|
||||
@@ -207,7 +208,7 @@ class LinkDisplayPortStatusSink:
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return bool((self.__io.get(TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1] >> 30) & 1)
|
||||
return bool((self.__io.get(ci.TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1] >> 30) & 1)
|
||||
|
||||
@property
|
||||
def cds_ila(self) -> bool:
|
||||
@@ -217,7 +218,7 @@ class LinkDisplayPortStatusSink:
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return bool((self.__io.get(TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1] >> 29) & 1)
|
||||
return bool((self.__io.get(ci.TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1] >> 29) & 1)
|
||||
|
||||
@property
|
||||
def lt_fail(self) -> bool:
|
||||
@@ -227,7 +228,7 @@ class LinkDisplayPortStatusSink:
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return bool((self.__io.get(TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1] >> 28) & 1)
|
||||
return bool((self.__io.get(ci.TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1] >> 28) & 1)
|
||||
|
||||
def lane(self, lane_number: int) -> LaneStatus:
|
||||
"""
|
||||
@@ -242,10 +243,10 @@ class LinkDisplayPortStatusSink:
|
||||
if not (0 <= lane_number <= 3):
|
||||
raise ValueError(f"Incorrect lane number {lane_number}. Available range: 0-{self.lane_count}")
|
||||
|
||||
status = self.__io.get(TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1]
|
||||
voltage_swing = self.__io.get(TSI_DPRX_LINK_VS_R, c_uint32)[1]
|
||||
pre_emphasis = self.__io.get(TSI_DPRX_LINK_PE_R, c_uint32)[1]
|
||||
_, error_counters = self.__io.get(TSI_DPRX_GET_ERROR_COUNTS_R, c_uint32 * 4)
|
||||
status = self.__io.get(ci.TSI_DPRX_LINK_STATUS_FLAGS_R, c_uint32)[1]
|
||||
voltage_swing = self.__io.get(ci.TSI_DPRX_LINK_VS_R, c_uint32)[1]
|
||||
pre_emphasis = self.__io.get(ci.TSI_DPRX_LINK_PE_R, c_uint32)[1]
|
||||
_, error_counters = self.__io.get(ci.TSI_DPRX_GET_ERROR_COUNTS_R, c_uint32 * 4)
|
||||
|
||||
lane_status = LaneStatus()
|
||||
|
||||
@@ -273,7 +274,7 @@ class LinkDisplayPortStatusSink:
|
||||
if self.__caps.dp2_support_rates and self.link_encoding == DpLinkEncoding.LE_128b132b:
|
||||
lane_status.voltage_swing = 0
|
||||
lane_status.pre_emphasis = 0
|
||||
_, ffe_preset = self.__io.get(TSI_DP2RX_LINK_FFE_PRESET_R, c_uint32)
|
||||
_, ffe_preset = self.__io.get(ci.TSI_DP2RX_LINK_FFE_PRESET_R, c_uint32)
|
||||
lane_status.ffe_preset = (ffe_preset >> (8 * lane_number)) & 0xF
|
||||
else:
|
||||
lane_status.voltage_swing = (voltage_swing >> (8 * lane_number)) & 0x3
|
||||
@@ -297,7 +298,7 @@ class LinkDisplayPortStatusSink:
|
||||
raise ValueError(f"Selected stream {stream_index} is not available. "
|
||||
f"Available stream number: {self.mst_stream_count}")
|
||||
|
||||
res = self.__io.get(TSI_DPRX_VC_TABLE_R, VCPTable, 4)[1]
|
||||
res = self.__io.get(ci.TSI_DPRX_VC_TABLE_R, VCPTable, 4)[1]
|
||||
|
||||
if self.mst_enabled:
|
||||
status = VCPStatus()
|
||||
@@ -316,7 +317,7 @@ class LinkDisplayPortStatusSink:
|
||||
|
||||
def __check_video(self) -> bool:
|
||||
def is_msa_available(io):
|
||||
result, msa_info, size = io.get(TSI_DPRX_MSA_INFO_R, DpMsa, 4)
|
||||
result, msa_info, size = io.get(p_ci.TSI_DPRX_MSA_INFO_R, DpMsa, 4)
|
||||
return size > 0
|
||||
|
||||
return function_scheduler(is_msa_available, self.__io, interval=5, timeout=10)
|
||||
@@ -339,7 +340,7 @@ class LinkDisplayPortStatusSink:
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
result, msa_info, size = self.__io.get(TSI_DPRX_MSA_INFO_R, DpMsa, 4)
|
||||
result, msa_info, size = self.__io.get(p_ci.TSI_DPRX_MSA_INFO_R, DpMsa, 4)
|
||||
|
||||
if stream_index < size:
|
||||
msa_info_private = MSAInfo(msa_info[stream_index])
|
||||
@@ -348,22 +349,22 @@ class LinkDisplayPortStatusSink:
|
||||
stream_status.mvid = msa_info_private.m_video
|
||||
stream_status.nvid = msa_info_private.n_video
|
||||
|
||||
result = self.__io.get(TSI_DPRX_CRC_LOG_R, DpCrc, self.mst_stream_count)
|
||||
if result[0] >= TSI_SUCCESS and self.mst_stream_count > 1:
|
||||
result = self.__io.get(ci.TSI_DPRX_CRC_LOG_R, DpCrc, self.mst_stream_count)
|
||||
if result[0] >= ci.TSI_SUCCESS and self.mst_stream_count > 1:
|
||||
stream_status.crc = [result[1][stream_index].r, result[1][stream_index].g, result[1][stream_index].b]
|
||||
elif result[0] >= TSI_SUCCESS and size == 1:
|
||||
elif result[0] >= ci.TSI_SUCCESS and size == 1:
|
||||
stream_status.crc = [result[1].r, result[1].g, result[1].b]
|
||||
|
||||
result = self.__io.get(TSI_DPRX_DSC_CRC_R, DpCrc, self.mst_stream_count)
|
||||
if result[0] >= TSI_SUCCESS and self.mst_stream_count > 1:
|
||||
result = self.__io.get(ci.TSI_DPRX_DSC_CRC_R, DpCrc, self.mst_stream_count)
|
||||
if result[0] >= ci.TSI_SUCCESS and self.mst_stream_count > 1:
|
||||
stream_status.dsc_crc = [result[1][stream_index].r, result[1][stream_index].g, result[1][stream_index].b]
|
||||
elif result[0] >= TSI_SUCCESS and size == 1:
|
||||
elif result[0] >= ci.TSI_SUCCESS and size == 1:
|
||||
stream_status.dsc_crc = [result[1].r, result[1].g, result[1].b]
|
||||
|
||||
if self.__caps.dp2_support_rates:
|
||||
res = self.__io.get(TSI_DPRX_SDP_CRC16_CTRL, c_uint32)
|
||||
stream_status.sdp_crc16.state = False if res[0] < TSI_SUCCESS else (res[1] & 0x1 == 1)
|
||||
stream_status.sdp_crc16.errors = self.__io.get(TSI_DPRX_SDP_CRC16_COUNTERS, c_uint8,
|
||||
res = self.__io.get(p_ci.TSI_DPRX_SDP_CRC16_CTRL, c_uint32)
|
||||
stream_status.sdp_crc16.state = False if res[0] < ci.TSI_SUCCESS else (res[1] & 0x1 == 1)
|
||||
stream_status.sdp_crc16.errors = self.__io.get(p_ci.TSI_DPRX_SDP_CRC16_COUNTERS, c_uint8,
|
||||
self.__caps.mst_stream_count)[1][stream_index]
|
||||
else:
|
||||
raise ValueError(f"Selected stream {stream_index} is not available. "
|
||||
@@ -378,7 +379,7 @@ class LinkDisplayPortStatusSink:
|
||||
if not self.__caps.dp2_support_rates:
|
||||
warnings.warn("SDP CRC16 is not supported. Cannot reset errors.")
|
||||
return
|
||||
self.__io.set(TSI_DPRX_SDP_CRC16_COUNTERS, 0)
|
||||
self.__io.set(p_ci.TSI_DPRX_SDP_CRC16_COUNTERS, 0)
|
||||
|
||||
def __str__(self) -> str:
|
||||
lane_status_str = ""
|
||||
|
||||
@@ -78,6 +78,7 @@ class RoutedLTConfig:
|
||||
def __init__(self):
|
||||
self.__is128b132b = False
|
||||
self.__is_old_dp20_lt = False
|
||||
self.__is_edp_lt = False
|
||||
self.__vs = 0
|
||||
self.__pe = 0
|
||||
self.__ffe = 0
|
||||
@@ -100,13 +101,21 @@ class RoutedLTConfig:
|
||||
def is_old_dp20_lt(self, value: bool = False):
|
||||
self.__is_old_dp20_lt = value
|
||||
|
||||
@property
|
||||
def is_edp_lt(self) -> bool:
|
||||
return self.__is_edp_lt
|
||||
|
||||
@is_edp_lt.setter
|
||||
def is_edp_lt(self, value: bool = False):
|
||||
self.__is_edp_lt = value
|
||||
|
||||
@property
|
||||
def vs(self) -> int:
|
||||
return self.__vs
|
||||
|
||||
@vs.setter
|
||||
def vs(self, value: int):
|
||||
if not (0 <= value < 3):
|
||||
if not (0 <= value <= 0x3):
|
||||
raise ValueError(f"VS cannot be less than 0 and more than 3")
|
||||
self.__vs = value
|
||||
|
||||
@@ -136,8 +145,8 @@ class RoutedLTConfig:
|
||||
|
||||
@link_bw.setter
|
||||
def link_bw(self, value: int):
|
||||
if not (0 <= value <= 0xFF):
|
||||
raise ValueError(f"link_bw cannot be less than 0 and more than 0xFF")
|
||||
if not (0 <= value <= 0xFFFF):
|
||||
raise ValueError(f"link_bw cannot be less than 0 and more than 0xFFFF")
|
||||
self.__link_bw = value
|
||||
|
||||
@property
|
||||
@@ -151,8 +160,9 @@ class RoutedLTConfig:
|
||||
self.__lane_count = value
|
||||
|
||||
def int_value(self) -> int:
|
||||
val = (self.ffe << 8) if self.is128b132b else ((self.vs << 8) | (self.pe << 10))
|
||||
return self.is128b132b | (self.__is_old_dp20_lt << 1) | val | (self.link_bw << 16) | (self.lane_count << 24)
|
||||
val = (self.ffe << 4) if self.is128b132b else ((self.vs << 4) | (self.pe << 6))
|
||||
return self.is128b132b | (self.__is_old_dp20_lt << 1) | (self.__is_edp_lt << 2) | val | \
|
||||
(self.lane_count << 8) | (self.link_bw << 16)
|
||||
|
||||
|
||||
class RoutedLTStatus:
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import warnings
|
||||
from ctypes import c_uint, c_uint8
|
||||
from typing import List
|
||||
from warnings import warn
|
||||
|
||||
from UniTAP.libs.lib_tsi import *
|
||||
from UniTAP.dev.ports.modules.link.dp.link_status_common import DpLinkTrainingResult
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
from UniTAP.utils.function_wrapper import *
|
||||
from .link_tx_status import LinkDisplayPortStatusSource
|
||||
from .link_tx_config import LinkDisplayPortConfig
|
||||
@@ -34,7 +38,7 @@ class LinkDisplayPortTx:
|
||||
self.__status = LinkDisplayPortStatusSource(self.__io, self.__HW_CAPS, dpcd)
|
||||
self.__config = LinkDisplayPortConfig(self.__io, self.__HW_CAPS)
|
||||
self.__force_config = LinkDisplayPortForceConfig(self.__io, self.__HW_CAPS)
|
||||
self.__cable_info = DpCableInfo(port_io, TSI_DPTX_CABLE_ATTRIBUTES_R)
|
||||
self.__cable_info = DpCableInfo(port_io, p_ci.TSI_DPTX_CABLE_ATTRIBUTES_R)
|
||||
|
||||
@property
|
||||
def status(self) -> LinkDisplayPortStatusSource:
|
||||
@@ -86,7 +90,7 @@ class LinkDisplayPortTx:
|
||||
def is_link_training_success(link: LinkDisplayPortTx):
|
||||
return link.last_lt_result() == DpLinkTrainingResult.LTR_SUCCESS
|
||||
|
||||
self.__io.set(TSI_W_DPTX_COMMAND, 1, c_uint32)
|
||||
self.__io.set(ci.TSI_W_DPTX_COMMAND, 1, c_uint32)
|
||||
|
||||
return function_scheduler(is_link_training_success, self, interval=0.1, timeout=5)
|
||||
|
||||
@@ -97,7 +101,7 @@ class LinkDisplayPortTx:
|
||||
Returns:
|
||||
object of `DpLinkTrainingResult` type
|
||||
"""
|
||||
_, value = self.__io.get(TSI_DPTX_LT_RESULT_R, c_uint)
|
||||
_, value = self.__io.get(ci.TSI_DPTX_LT_RESULT_R, c_uint)
|
||||
return DpLinkTrainingResult(value)
|
||||
|
||||
@property
|
||||
@@ -112,7 +116,7 @@ class LinkDisplayPortTx:
|
||||
warnings.warn("Scrambler Seed is not supported.")
|
||||
return 0
|
||||
|
||||
return self.__io.get(TSI_DPTX_SCR_SEED, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_DPTX_SCR_SEED, c_uint32)[1]
|
||||
|
||||
@scrambler_seed.setter
|
||||
def scrambler_seed(self, value: int = 0):
|
||||
@@ -126,7 +130,7 @@ class LinkDisplayPortTx:
|
||||
warnings.warn("Scrambler Seed is not supported.")
|
||||
return
|
||||
if self.config._read_lt_features().auto_seed is not None and not self.config._read_lt_features().auto_seed:
|
||||
self.__io.set(TSI_DPTX_SCR_SEED, value, c_uint32)
|
||||
self.__io.set(ci.TSI_DPTX_SCR_SEED, value, c_uint32)
|
||||
else:
|
||||
warnings.warn("AutoSeed has already enabled. Transferred value will not be written")
|
||||
|
||||
@@ -160,7 +164,7 @@ class LinkDisplayPortTx:
|
||||
old_value = self.__get_override_voltage()
|
||||
old_value &= ~(3 << (stream_index * 8))
|
||||
old_value |= (value << (stream_index * 8))
|
||||
self.__io.set(TSI_DPTX_OVERRIDE_VOLTAGE_SWING, old_value, c_uint32)
|
||||
self.__io.set(ci.TSI_DPTX_OVERRIDE_VOLTAGE_SWING, old_value, c_uint32)
|
||||
|
||||
def get_override_pre_emp(self, stream_index: int) -> int:
|
||||
"""
|
||||
@@ -192,7 +196,7 @@ class LinkDisplayPortTx:
|
||||
old_value = self.__get_override_pre_emp()
|
||||
old_value &= ~(3 << (stream_index * 8))
|
||||
old_value |= (value << (stream_index * 8))
|
||||
self.__io.set(TSI_DPTX_OVERRIDE_PRE_EMPHASIS, old_value, c_uint32)
|
||||
self.__io.set(ci.TSI_DPTX_OVERRIDE_PRE_EMPHASIS, old_value, c_uint32)
|
||||
|
||||
@property
|
||||
def override_ffe_presets(self) -> list:
|
||||
@@ -205,7 +209,7 @@ class LinkDisplayPortTx:
|
||||
if not self.__HW_CAPS.dp2_custom_rates:
|
||||
warnings.warn("FFE presets does not support.")
|
||||
return []
|
||||
return self.__io.get(TSI_DP2TX_OUT_FFE, c_uint8, 4)[1]
|
||||
return self.__io.get(ci.TSI_DP2TX_OUT_FFE, c_uint8, 4)[1]
|
||||
|
||||
@override_ffe_presets.setter
|
||||
def override_ffe_presets(self, value: List[int]):
|
||||
@@ -219,13 +223,13 @@ class LinkDisplayPortTx:
|
||||
warnings.warn("FFE presets does not support.")
|
||||
return
|
||||
new_value = value[0] | (value[0] << 8) | (value[0] << 16) | (value[0] << 32)
|
||||
self.__io.set(TSI_DP2TX_OUT_FFE, new_value)
|
||||
self.__io.set(ci.TSI_DP2TX_OUT_FFE, new_value)
|
||||
|
||||
def __get_override_voltage(self) -> int:
|
||||
return self.__io.get(TSI_DPTX_OVERRIDE_VOLTAGE_SWING, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_DPTX_OVERRIDE_VOLTAGE_SWING, c_uint32)[1]
|
||||
|
||||
def __get_override_pre_emp(self) -> int:
|
||||
return self.__io.get(TSI_DPTX_OVERRIDE_PRE_EMPHASIS, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_DPTX_OVERRIDE_PRE_EMPHASIS, c_uint32)[1]
|
||||
|
||||
@property
|
||||
def link_pattern(self) -> DPLinkPattern:
|
||||
@@ -235,7 +239,7 @@ class LinkDisplayPortTx:
|
||||
Returns:
|
||||
object of `DPLinkPattern` type
|
||||
"""
|
||||
return DPLinkPattern(self.__io.get(TSI_DPTX_OUTPUT_PATTERN, c_uint32)[1])
|
||||
return DPLinkPattern(self.__io.get(ci.TSI_DPTX_OUTPUT_PATTERN, c_uint32)[1])
|
||||
|
||||
def set_link_pattern(self, pattern: DPLinkPattern, additional_param: int = 1):
|
||||
"""
|
||||
@@ -247,16 +251,16 @@ class LinkDisplayPortTx:
|
||||
"""
|
||||
if not self.__HW_CAPS.dp2_custom_rates and pattern not in [e.value for e in DPLinkPattern]:
|
||||
raise ValueError(f"Current pattern {pattern.name} is not supported")
|
||||
self.__io.set(TSI_DPTX_OUTPUT_PATTERN, pattern.value, c_uint32)
|
||||
self.__io.set(ci.TSI_DPTX_OUTPUT_PATTERN, pattern.value, c_uint32)
|
||||
|
||||
if pattern == DPLinkPattern.LinkSquarePattern:
|
||||
self.__io.set(TSI_DPTX_SQUARE_PATTERN_NUMBER, additional_param, c_uint32)
|
||||
self.__io.set(ci.TSI_DPTX_SQUARE_PATTERN_NUMBER, additional_param, c_uint32)
|
||||
|
||||
def set_force_link_mode(self, link_mode: DPOutLinkMode):
|
||||
self.__io.set(TSI_DPTX_OUT_LINK_MODE, link_mode.value, c_uint32)
|
||||
self.__io.set(p_ci.TSI_DPTX_OUT_LINK_MODE, link_mode.value, c_uint32)
|
||||
|
||||
def get_force_link_mode(self) -> DPOutLinkMode:
|
||||
return DPOutLinkMode(self.__io.get(TSI_DPTX_OUT_LINK_MODE, c_uint32)[1])
|
||||
return DPOutLinkMode(self.__io.get(p_ci.TSI_DPTX_OUT_LINK_MODE, c_uint32)[1])
|
||||
|
||||
def cable_rx_type(self) -> CableCapabilitiesEnum:
|
||||
"""
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from typing import Optional, Union, Type
|
||||
from ctypes import c_uint, c_int
|
||||
from typing import Optional, Union, Type, List
|
||||
|
||||
from UniTAP.libs.lib_tsi import PortIO
|
||||
from UniTAP.libs.lib_tsi.tsi_private_types import *
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
from .link_tx_types import *
|
||||
from .private_link_tx_types import *
|
||||
from .link_status_common import *
|
||||
@@ -123,10 +126,10 @@ class LinkDisplayPortConfig:
|
||||
return link_status
|
||||
|
||||
def _read_lt_features(self) -> LTFeatures:
|
||||
return self.__io.get(TSI_DPTX_LT_FEATURES, LTFeatures)[1]
|
||||
return self.__io.get(ci.TSI_DPTX_LT_FEATURES, LTFeatures)[1]
|
||||
|
||||
def __get_post_lt_features(self) -> PostLtFeatures:
|
||||
return self.__io.get(TSI_DPTX_POST_LT_FEATURES, PostLtFeatures)[1]
|
||||
return self.__io.get(p_ci.TSI_DPTX_POST_LT_FEATURES, PostLtFeatures)[1]
|
||||
|
||||
def __set_post_lt_features(self, config: DisplayPortLinkConfig):
|
||||
post_lt_features = self.__get_post_lt_features()
|
||||
@@ -134,10 +137,10 @@ class LinkDisplayPortConfig:
|
||||
post_lt_features.force_edid_timings = config.force_edid_timings_after_lt
|
||||
if config.adaptive_sync_auto_enable is not None and self.__caps.adaptive_sync:
|
||||
post_lt_features.as_auto_enable = config.adaptive_sync_auto_enable
|
||||
self.__io.set(TSI_DPTX_POST_LT_FEATURES, post_lt_features.value(), c_uint32)
|
||||
self.__io.set(p_ci.TSI_DPTX_POST_LT_FEATURES, post_lt_features.value(), c_uint32)
|
||||
|
||||
def __get_dp2_custom_rates(self) -> list:
|
||||
rates = self.__io.get(TSI_DP2TX_CUSTOM_RATE_CAPS_R, c_uint32, 32)[1]
|
||||
rates = self.__io.get(ci.TSI_DP2TX_CUSTOM_RATE_CAPS_R, c_uint32, 32)[1]
|
||||
custom_rates = []
|
||||
for i in range(len(rates)):
|
||||
custom_rates.append(float(rates[i]) * 200000 / 1000000000)
|
||||
@@ -149,20 +152,20 @@ class LinkDisplayPortConfig:
|
||||
return
|
||||
if lane_count not in [1, 2, 4]:
|
||||
raise ValueError(f"Incorrect lane count number {lane_count}. Must be from list: 1, 2, 4")
|
||||
self.__io.set(TSI_DPTX_LINK_CFG_LANES, lane_count, c_uint32)
|
||||
self.__io.set(ci.TSI_DPTX_LINK_CFG_LANES, lane_count, c_uint32)
|
||||
|
||||
def __get_lane_count_dp14(self) -> int:
|
||||
return self.__io.get(TSI_DPTX_LINK_CFG_LANES)[1]
|
||||
return self.__io.get(ci.TSI_DPTX_LINK_CFG_LANES)[1]
|
||||
|
||||
def __set_lane_count_dp21(self, lane_count: Optional[int]):
|
||||
if lane_count is None:
|
||||
return
|
||||
if lane_count not in [1, 2, 4]:
|
||||
raise ValueError(f"Incorrect lane count number {lane_count}. Must be from list: 1, 2, 4")
|
||||
self.__io.set(TSI_DP2TX_LT_SLC, lane_count, c_uint32)
|
||||
self.__io.set(ci.TSI_DP2TX_LT_SLC, lane_count, c_uint32)
|
||||
|
||||
def __get_lane_count_dp21(self) -> int:
|
||||
return self.__io.get(TSI_DP2TX_LT_SLC)[1]
|
||||
return self.__io.get(ci.TSI_DP2TX_LT_SLC)[1]
|
||||
|
||||
def __set_bit_rate_14(self, bit_rate: Optional[float]):
|
||||
if bit_rate is None:
|
||||
@@ -170,10 +173,10 @@ class LinkDisplayPortConfig:
|
||||
if int(round(bit_rate / 0.27)) > self.__caps.max_link_rate:
|
||||
raise ValueError(f"Following 8b/10b bit rate {bit_rate} is not supported on device. "
|
||||
f"Max supported link rate {round(self.__caps.max_link_rate * 0.27, 2)}")
|
||||
self.__io.set(TSI_DPTX_LINK_CFG_BIT_RATE, int(round(bit_rate / 0.27)), c_uint32)
|
||||
self.__io.set(ci.TSI_DPTX_LINK_CFG_BIT_RATE, int(round(bit_rate / 0.27)), c_uint32)
|
||||
|
||||
def __get_bit_rate_14(self) -> float:
|
||||
return round(self.__io.get(TSI_DPTX_LINK_CFG_BIT_RATE)[1] * 0.27, 2)
|
||||
return round(self.__io.get(ci.TSI_DPTX_LINK_CFG_BIT_RATE)[1] * 0.27, 2)
|
||||
|
||||
def __set_bit_rate_21(self, bit_rate: Optional[Union[float, int]]):
|
||||
if bit_rate is None:
|
||||
@@ -182,42 +185,42 @@ class LinkDisplayPortConfig:
|
||||
if not self.__caps.support_10gbps:
|
||||
raise ValueError(f"Following bit rate {bit_rate} is not supported on device.")
|
||||
else:
|
||||
res = self.__io.get(TSI_DP2TX_CUSTOM_RATE_MAP, c_uint32, 3)[1]
|
||||
self.__io.set(TSI_DP2TX_CUSTOM_RATE_MAP, (int(bit_rate * 1000000000 / 200000), res[1], res[2]),
|
||||
res = self.__io.get(ci.TSI_DP2TX_CUSTOM_RATE_MAP, c_uint32, 3)[1]
|
||||
self.__io.set(ci.TSI_DP2TX_CUSTOM_RATE_MAP, (int(bit_rate * 1000000000 / 200000), res[1], res[2]),
|
||||
c_uint32, 3)
|
||||
elif (bit_rate == 10.0 and not self.__caps.support_10gbps) or \
|
||||
(bit_rate == 13.5 and not self.__caps.support_13_5gbps) or \
|
||||
(bit_rate == 20.0 and not self.__caps.support_20gbps):
|
||||
raise ValueError(f"Following bit rate {bit_rate} is not supported on device.")
|
||||
self.__io.set(TSI_DP2TX_LT_SBR, DP21_LinkRateRev.get(bit_rate), c_uint32)
|
||||
self.__io.set(ci.TSI_DP2TX_LT_SBR, DP21_LinkRateRev.get(bit_rate), c_uint32)
|
||||
|
||||
def __get_bit_rate_21(self) -> float:
|
||||
return DP21_LinkRate.get(self.__io.get(TSI_DP2TX_LT_SBR)[1])
|
||||
return DP21_LinkRate.get(self.__io.get(ci.TSI_DP2TX_LT_SBR)[1])
|
||||
|
||||
def __support_ssc(self) -> bool:
|
||||
return (self.__io.get(TSI_DPTX_DOWNSPREAD_STATUS_R, c_uint32)[1] >> 1) & 1 != 0
|
||||
return (self.__io.get(ci.TSI_DPTX_DOWNSPREAD_STATUS_R, c_uint32)[1] >> 1) & 1 != 0
|
||||
|
||||
def __set_config_ssc(self, ssc_conf: Optional[SSCConfig]):
|
||||
if ssc_conf is None:
|
||||
return
|
||||
if not self.__support_ssc():
|
||||
raise ValueError(f"SSC is not supported on the device.")
|
||||
self.__io.set(TSI_DPTX_DOWNSPREAD_CONTROL, int(ssc_conf.enabled), c_uint32)
|
||||
self.__io.set(ci.TSI_DPTX_DOWNSPREAD_CONTROL, int(ssc_conf.enabled), c_uint32)
|
||||
if ssc_conf.enabled:
|
||||
if not (1 <= ssc_conf.amplitude <= 50):
|
||||
raise ValueError(f"Incorrect amplitude value {ssc_conf.amplitude}. Must be from range: 0.1 - 0.5")
|
||||
self.__io.set(TSI_DPTX_DOWNSPREAD_AMP, ssc_conf.amplitude, c_uint32)
|
||||
self.__io.set(ci.TSI_DPTX_DOWNSPREAD_AMP, ssc_conf.amplitude, c_uint32)
|
||||
if not (30000 <= ssc_conf.frequency <= 63000):
|
||||
raise ValueError(f"Incorrect frequency value {ssc_conf.frequency}. Must be from range: 30000 - 63000")
|
||||
self.__io.set(TSI_DPTX_DOWNSPREAD_FREQ, ssc_conf.frequency, c_uint32)
|
||||
self.__io.set(ci.TSI_DPTX_DOWNSPREAD_FREQ, ssc_conf.frequency, c_uint32)
|
||||
|
||||
def __get_config_ssc(self) -> SSCConfig:
|
||||
if not self.__support_ssc():
|
||||
return None
|
||||
ssc_conf = SSCConfig()
|
||||
ssc_conf.enabled = (self.__io.get(TSI_DPTX_DOWNSPREAD_STATUS_R)[1] & 1) != 0
|
||||
ssc_conf.frequency = self.__io.get(TSI_DPTX_DOWNSPREAD_FREQ)[1]
|
||||
ssc_conf.amplitude = self.__io.get(TSI_DPTX_DOWNSPREAD_AMP)[1]
|
||||
ssc_conf.enabled = (self.__io.get(ci.TSI_DPTX_DOWNSPREAD_STATUS_R)[1] & 1) != 0
|
||||
ssc_conf.frequency = self.__io.get(ci.TSI_DPTX_DOWNSPREAD_FREQ)[1]
|
||||
ssc_conf.amplitude = self.__io.get(ci.TSI_DPTX_DOWNSPREAD_AMP)[1]
|
||||
return ssc_conf
|
||||
|
||||
def __dp2_support_rates(self) -> bool:
|
||||
@@ -228,7 +231,7 @@ class LinkDisplayPortConfig:
|
||||
return
|
||||
if not self.__dp2_support_rates():
|
||||
raise ValueError(f"LTTPR is not supported on the device.")
|
||||
self.__io.set(TSI_DPTX_LTTPR_CONTROL, int(enable))
|
||||
self.__io.set(ci.TSI_DPTX_LTTPR_CONTROL, int(enable))
|
||||
|
||||
def __set_lt_features(self, config: Optional[DisplayPortLinkConfig]):
|
||||
if config is None:
|
||||
@@ -270,22 +273,22 @@ class LinkDisplayPortConfig:
|
||||
else:
|
||||
raise TypeError("Incorrect DisplayPortLinkConfig format!")
|
||||
|
||||
self.__io.set(TSI_DPTX_LT_FEATURES, res.value(), c_uint32)
|
||||
self.__io.set(ci.TSI_DPTX_LT_FEATURES, res.value(), c_uint32)
|
||||
|
||||
def __enable_mst(self, enable: Optional[bool]):
|
||||
if enable is None:
|
||||
return
|
||||
self.__io.set(TSI_DPTX_COMMAND_W, 3 if enable else 4, c_uint32)
|
||||
self.__io.set(ci.TSI_DPTX_COMMAND_W, 3 if enable else 4, c_uint32)
|
||||
|
||||
def __set_mst_channel_count(self, count: Optional[int]):
|
||||
if count is None:
|
||||
return
|
||||
if not (0 <= count <= self.__caps.mst_stream_count):
|
||||
raise ValueError(f"Incorrect stream count {count}. Available stream count {self.__caps.mst_stream_count}")
|
||||
self.__io.set(TSI_PG_ENABLED_STREAM_COUNT, count, c_uint32)
|
||||
self.__io.set(ci.TSI_PG_ENABLED_STREAM_COUNT, count, c_uint32)
|
||||
|
||||
def __link_encoding(self) -> DpLinkEncoding:
|
||||
result, value = self.__io.get(TSI_DPTX_LINK_MODE_R, c_uint)
|
||||
result, value = self.__io.get(ci.TSI_DPTX_LINK_MODE_R, c_uint)
|
||||
|
||||
if value == 0:
|
||||
return DpLinkEncoding.LE_8b10b
|
||||
@@ -293,36 +296,36 @@ class LinkDisplayPortConfig:
|
||||
return DpLinkEncoding.LE_128b132b
|
||||
|
||||
def __mst_enabled(self) -> bool:
|
||||
return (self.__io.get(TSI_DPTX_LINK_STATUS_BITS_R)[1] & (1 << 30)) != 0
|
||||
return (self.__io.get(ci.TSI_DPTX_LINK_STATUS_BITS_R)[1] & (1 << 30)) != 0
|
||||
|
||||
def __mst_stream_count(self) -> int:
|
||||
result, mst_status = self.__io.get(TSI_DPTX_MST_STATUS_R, c_uint)
|
||||
result, mst_status = self.__io.get(ci.TSI_DPTX_MST_STATUS_R, c_uint)
|
||||
return (mst_status >> 8) & 0xFF
|
||||
|
||||
def __lttpr_active(self) -> Optional[bool]:
|
||||
if self.__link_encoding == DpLinkEncoding.LE_128b132b:
|
||||
return (self.__io.get(TSI_DPTX_LTTPR_CONTROL, c_uint32)[1] & 1) != 0
|
||||
return (self.__io.get(ci.TSI_DPTX_LTTPR_CONTROL, c_uint32)[1] & 1) != 0
|
||||
else:
|
||||
return None
|
||||
|
||||
def __check_custom_bit_rate(self) -> float:
|
||||
res = self.__io.get(TSI_DP2TX_CUSTOM_RATE_MAP, c_uint32, 3)[1]
|
||||
res = self.__io.get(ci.TSI_DP2TX_CUSTOM_RATE_MAP, c_uint32, 3)[1]
|
||||
for i in range(3):
|
||||
if res[i] != 0:
|
||||
return res[i] * 200000 / 1000000000
|
||||
return 0
|
||||
|
||||
def __try_fec_after_lt(self, enable: bool):
|
||||
result = self.__io.get(TSI_DPTX_FEC_CTRL, c_int)
|
||||
result = self.__io.get(ci.TSI_DPTX_FEC_CTRL, c_int)
|
||||
val = result[1]
|
||||
if enable:
|
||||
val |= 0x2
|
||||
else:
|
||||
val &= ~0x2
|
||||
self.__io.set(TSI_DPTX_FEC_CTRL, val)
|
||||
self.__io.set(ci.TSI_DPTX_FEC_CTRL, val)
|
||||
|
||||
def __fec_after_lt_state(self) -> bool:
|
||||
return (self.__io.get(TSI_DPTX_FEC_CTRL, c_int)[1] & 0x2) != 0
|
||||
return (self.__io.get(ci.TSI_DPTX_FEC_CTRL, c_int)[1] & 0x2) != 0
|
||||
|
||||
def __sdp_control(self, config: Optional[DisplayPortLinkConfig]):
|
||||
if config is None:
|
||||
@@ -335,24 +338,24 @@ class LinkDisplayPortConfig:
|
||||
self.__write_sdp_control(sdp_control)
|
||||
|
||||
def __write_sdp_control(self, sdp_control: SdpControl):
|
||||
self.__io.set(TSI_DPTX_SDP_CTRL, sdp_control.value())
|
||||
self.__io.set(p_ci.TSI_DPTX_SDP_CTRL, sdp_control.value())
|
||||
|
||||
def __read_sdp_control(self) -> SdpControl:
|
||||
return self.__io.get(TSI_DPTX_SDP_CTRL, SdpControl)[1]
|
||||
return self.__io.get(p_ci.TSI_DPTX_SDP_CTRL, SdpControl)[1]
|
||||
|
||||
def __set_edp_sel_rate(self, rate: float):
|
||||
if self.__caps.edp and rate in self.__get_edp_caps_rates():
|
||||
self.__io.set(TSI_DPTX_EDP_LT_SBR, int(rate / 0.0002), c_uint32)
|
||||
self.__io.set(ci.TSI_DPTX_EDP_LT_SBR, int(rate / 0.0002), c_uint32)
|
||||
elif not self.__caps.edp:
|
||||
raise ValueError("EDP is not supported.")
|
||||
|
||||
def __get_edp_sel_rate(self) -> int:
|
||||
if self.__caps.edp:
|
||||
return self.__io.get(TSI_DPTX_EDP_LT_SBR)[1] * 0.0002
|
||||
return self.__io.get(ci.TSI_DPTX_EDP_LT_SBR)[1] * 0.0002
|
||||
|
||||
def __get_edp_caps_rates(self) -> List[float]:
|
||||
if self.__caps.edp:
|
||||
rates = self.__io.get(TSI_DPTX_EXTRA_DP14_RATES, data_type=c_uint32, data_count=8)[1]
|
||||
rates = self.__io.get(ci.TSI_DPTX_EXTRA_DP14_RATES, data_type=c_uint32, data_count=8)[1]
|
||||
new_rates = []
|
||||
for rate in rates:
|
||||
if rate > 0:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from typing import Optional, Union, Type
|
||||
from UniTAP.libs.lib_tsi import PortIO
|
||||
from UniTAP.libs.lib_tsi.tsi_private_types import *
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
from .link_tx_types import *
|
||||
from .private_link_tx_types import *
|
||||
from .link_status_common import *
|
||||
@@ -62,25 +62,25 @@ class LinkDisplayPortForceConfig:
|
||||
(bit_rate == 13.5 and not self.__caps.support_13_5gbps) or \
|
||||
(bit_rate == 20.0 and not self.__caps.support_20gbps):
|
||||
raise ValueError(f"Following bit rate {bit_rate} is not supported on device.")
|
||||
self.__io.set(TSI_DP2TX_OUT_BR, DP21_LinkRateRev.get(bit_rate), c_uint32)
|
||||
self.__io.set(p_ci.TSI_DP2TX_OUT_BR, DP21_LinkRateRev.get(bit_rate), c_uint32)
|
||||
|
||||
def __force_get_bit_rate(self) -> float:
|
||||
return DP21_LinkRate.get(self.__io.get(TSI_DP2TX_OUT_BR)[1])
|
||||
return DP21_LinkRate.get(self.__io.get(p_ci.TSI_DP2TX_OUT_BR)[1])
|
||||
|
||||
def __force_set_lane_count(self, lane_count: Optional[int]):
|
||||
if lane_count is None:
|
||||
return
|
||||
if lane_count not in [1, 2, 4]:
|
||||
raise ValueError(f"Incorrect lane count number {lane_count}. Must be from list: 1, 2, 4")
|
||||
self.__io.set(TSI_DP2TX_OUT_LC, lane_count, c_uint32)
|
||||
self.__io.set(p_ci.TSI_DP2TX_OUT_LC, lane_count, c_uint32)
|
||||
|
||||
def __force_get_lane_count(self) -> int:
|
||||
return self.__io.get(TSI_DP2TX_OUT_LC)[1]
|
||||
return self.__io.get(p_ci.TSI_DP2TX_OUT_LC)[1]
|
||||
|
||||
def __force_set_pattern(self, pattern: Optional[DP128b132bLinkPattern]):
|
||||
if pattern is None:
|
||||
return
|
||||
self.__io.set(TSI_DP2TX_OUT_TEST_PATTERN, pattern.value, c_uint32)
|
||||
self.__io.set(p_ci.TSI_DP2TX_OUT_TEST_PATTERN, pattern.value, c_uint32)
|
||||
|
||||
def __force_get_pattern(self) -> DP128b132bLinkPattern:
|
||||
return DP128b132bLinkPattern(self.__io.get(TSI_DP2TX_OUT_TEST_PATTERN, c_uint32)[1])
|
||||
return DP128b132bLinkPattern(self.__io.get(p_ci.TSI_DP2TX_OUT_TEST_PATTERN, c_uint32)[1])
|
||||
|
||||
@@ -2,8 +2,7 @@ import warnings
|
||||
from typing import Optional
|
||||
|
||||
from UniTAP.libs.lib_tsi import PortIO
|
||||
from UniTAP.libs.lib_tsi.tsi_types import *
|
||||
from .link_tx_types import *
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from .private_link_tx_types import *
|
||||
from .link_status_common import *
|
||||
from .private_link_status_common import *
|
||||
@@ -47,7 +46,7 @@ class LinkDisplayPortStatusSource:
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
result, mst_status = self.__io.get(TSI_DPTX_MST_STATUS_R, c_uint)
|
||||
result, mst_status = self.__io.get(ci.TSI_DPTX_MST_STATUS_R, c_uint)
|
||||
return (mst_status >> 8) & 0xFF
|
||||
|
||||
@property
|
||||
@@ -58,7 +57,7 @@ class LinkDisplayPortStatusSource:
|
||||
Returns:
|
||||
object of DpLinkEncoding type
|
||||
"""
|
||||
result, value = self.__io.get(TSI_DPTX_LINK_MODE_R, c_uint)
|
||||
result, value = self.__io.get(ci.TSI_DPTX_LINK_MODE_R, c_uint)
|
||||
|
||||
if value == 0:
|
||||
return DpLinkEncoding.LE_8b10b
|
||||
@@ -77,9 +76,9 @@ class LinkDisplayPortStatusSource:
|
||||
if self.__check_custom_bit_rate() != 0:
|
||||
return self.__check_custom_bit_rate()
|
||||
else:
|
||||
return DP21_LinkRate.get(self.__io.get(TSI_DP2TX_LT_RATE_R, c_uint)[1])
|
||||
return DP21_LinkRate.get(self.__io.get(ci.TSI_DP2TX_LT_RATE_R, c_uint)[1])
|
||||
else:
|
||||
return round(self.__io.get(TSI_DPTX_LINK_RATE_R, c_uint)[1] * 0.27, 2)
|
||||
return round(self.__io.get(ci.TSI_DPTX_LINK_RATE_R, c_uint)[1] * 0.27, 2)
|
||||
|
||||
@property
|
||||
def lane_count(self) -> int:
|
||||
@@ -89,7 +88,7 @@ class LinkDisplayPortStatusSource:
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return self.__io.get(TSI_DPTX_LINK_LANE_COUNT_R, c_int)[1]
|
||||
return self.__io.get(ci.TSI_DPTX_LINK_LANE_COUNT_R, c_int)[1]
|
||||
|
||||
@property
|
||||
def hpd_asserted(self) -> bool:
|
||||
@@ -99,7 +98,7 @@ class LinkDisplayPortStatusSource:
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return (self.__io.get(TSI_DPTX_HPD_STATUS_R, c_int)[1] & 1) != 0
|
||||
return (self.__io.get(ci.TSI_DPTX_HPD_STATUS_R, c_int)[1] & 1) != 0
|
||||
|
||||
@property
|
||||
def available_link_rate(self) -> float:
|
||||
@@ -142,8 +141,8 @@ class LinkDisplayPortStatusSource:
|
||||
raise ValueError(f"Incorrect lane number {lane_number}. Available range: 0-{self.lane_count}")
|
||||
|
||||
status = self.__read_link_status()
|
||||
voltage_swing = self.__io.get(TSI_DPTX_LINK_VOLTAGE_SWING_R, LinkVoltageSwing)[1]
|
||||
pre_emphasis = self.__io.get(TSI_DPTX_LINK_PRE_EMPHASIS_R, LinkPreEmphasis)[1]
|
||||
voltage_swing = self.__io.get(ci.TSI_DPTX_LINK_VOLTAGE_SWING_R, LinkVoltageSwing)[1]
|
||||
pre_emphasis = self.__io.get(ci.TSI_DPTX_LINK_PRE_EMPHASIS_R, LinkPreEmphasis)[1]
|
||||
error_counters = self.__dpcd.read(0x210, 8).data
|
||||
|
||||
lane_status = LaneStatus()
|
||||
@@ -178,7 +177,7 @@ class LinkDisplayPortStatusSource:
|
||||
lane_status.error_count = error_counters[6] | ((error_counters[7] & 0x7F) << 8)
|
||||
|
||||
if self.link_encoding == DpLinkEncoding.LE_128b132b:
|
||||
ffe_preset = self.__io.get(TSI_DP2TX_LT_FFE_PRESET_R, c_uint32)[1]
|
||||
ffe_preset = self.__io.get(ci.TSI_DP2TX_LT_FFE_PRESET_R, c_uint32)[1]
|
||||
lane_status.ffe_preset = (ffe_preset >> (8 * lane_number)) & 0xFF
|
||||
else:
|
||||
lane_status.ffe_preset = 0
|
||||
@@ -195,7 +194,7 @@ class LinkDisplayPortStatusSource:
|
||||
object of bool or None type
|
||||
"""
|
||||
if self.__caps.dsc or self.__caps.dsc2:
|
||||
return (self.__io.get(TSI_DPTX_DSC_STATUS_R)[1] & 1) != 0
|
||||
return (self.__io.get(ci.TSI_DPTX_DSC_STATUS_R)[1] & 1) != 0
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -209,7 +208,7 @@ class LinkDisplayPortStatusSource:
|
||||
object of bool or None type
|
||||
"""
|
||||
if self.__caps.mst:
|
||||
return (self.__io.get(TSI_DPTX_MST_STATUS_R, c_uint32)[1] & 1) != 0
|
||||
return (self.__io.get(ci.TSI_DPTX_MST_STATUS_R, c_uint32)[1] & 1) != 0
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -222,7 +221,7 @@ class LinkDisplayPortStatusSource:
|
||||
Returns:
|
||||
object of bool or None type
|
||||
"""
|
||||
res = self.__io.get(TSI_DPTX_DOWNSPREAD_STATUS_R)[1]
|
||||
res = self.__io.get(ci.TSI_DPTX_DOWNSPREAD_STATUS_R)[1]
|
||||
if ((res >> 1) & 1) != 0:
|
||||
return (res & 1) != 0
|
||||
else:
|
||||
@@ -238,7 +237,7 @@ class LinkDisplayPortStatusSource:
|
||||
object of bool or None type
|
||||
"""
|
||||
if self.__caps.fec or self.__caps.fec2:
|
||||
return (self.__io.get(TSI_DPTX_FEC_STATUS_R)[1] & 1) != 0
|
||||
return (self.__io.get(ci.TSI_DPTX_FEC_STATUS_R)[1] & 1) != 0
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -272,7 +271,7 @@ class LinkDisplayPortStatusSource:
|
||||
object of bool or None type
|
||||
"""
|
||||
if self.link_encoding == DpLinkEncoding.LE_128b132b:
|
||||
return (self.__io.get(TSI_DPTX_LTTPR_STATUS_R, c_uint32)[1] & 1) != 0
|
||||
return (self.__io.get(ci.TSI_DPTX_LTTPR_STATUS_R, c_uint32)[1] & 1) != 0
|
||||
else:
|
||||
return None
|
||||
|
||||
@@ -327,7 +326,7 @@ class LinkDisplayPortStatusSource:
|
||||
object of `StreamStatusDP` type
|
||||
"""
|
||||
stream_status = StreamStatusDP()
|
||||
result, msa_info, size = self.__io.get(TSI_DPTX_MSA_INFO_R, DpMsa, 4)
|
||||
result, msa_info, size = self.__io.get(ci.TSI_DPTX_MSA_INFO_R, DpMsa, 4)
|
||||
|
||||
if stream_index < size:
|
||||
msa_info_private = MSAInfo(msa_info[stream_index])
|
||||
@@ -336,16 +335,16 @@ class LinkDisplayPortStatusSource:
|
||||
stream_status.mvid = msa_info_private.m_video
|
||||
stream_status.nvid = msa_info_private.n_video
|
||||
|
||||
result = self.__io.get(TSI_DPTX_CRC_R, DpCrc, self.mst_stream_count)
|
||||
if result[0] >= TSI_SUCCESS and self.mst_stream_count > 1:
|
||||
result = self.__io.get(ci.TSI_DPTX_CRC_R, DpCrc, self.mst_stream_count)
|
||||
if result[0] >= ci.TSI_SUCCESS and self.mst_stream_count > 1:
|
||||
stream_status.crc = [result[1][stream_index].r, result[1][stream_index].g, result[1][stream_index].b]
|
||||
elif result[0] >= TSI_SUCCESS and self.mst_stream_count == 1:
|
||||
elif result[0] >= ci.TSI_SUCCESS and self.mst_stream_count == 1:
|
||||
stream_status.crc = [result[1].r, result[1].g, result[1].b]
|
||||
|
||||
result = self.__io.get(TSI_DPTX_DSC_CRC_R, DpCrc, self.mst_stream_count)
|
||||
if result[0] >= TSI_SUCCESS and self.mst_stream_count > 1:
|
||||
result = self.__io.get(ci.TSI_DPTX_DSC_CRC_R, DpCrc, self.mst_stream_count)
|
||||
if result[0] >= ci.TSI_SUCCESS and self.mst_stream_count > 1:
|
||||
stream_status.dsc_crc = [result[1][stream_index].r, result[1][stream_index].g, result[1][stream_index].b]
|
||||
elif result[0] >= TSI_SUCCESS and self.mst_stream_count == 1:
|
||||
elif result[0] >= ci.TSI_SUCCESS and self.mst_stream_count == 1:
|
||||
stream_status.dsc_crc = [result[1].r, result[1].g, result[1].b]
|
||||
else:
|
||||
raise ValueError(f"Selected stream {stream_index} is not available. "
|
||||
@@ -368,7 +367,7 @@ class LinkDisplayPortStatusSource:
|
||||
raise ValueError(f"Selected stream {stream_index} is not available. "
|
||||
f"Available stream number: {self.mst_stream_count}")
|
||||
|
||||
res = self.__io.get(TSI_DPTX_VCP_TABLE_R, VCPTable, 4)[1]
|
||||
res = self.__io.get(ci.TSI_DPTX_VCP_TABLE_R, VCPTable, 4)[1]
|
||||
|
||||
if self.mst_enabled:
|
||||
status = VCPStatus()
|
||||
@@ -389,16 +388,16 @@ class LinkDisplayPortStatusSource:
|
||||
"""
|
||||
Send ACT command.
|
||||
"""
|
||||
self.__io.set(TSI_DPTX_MST_COMMAND_W, 1, c_uint32)
|
||||
self.__io.set(ci.TSI_DPTX_MST_COMMAND_W, 1, c_uint32)
|
||||
|
||||
def __read_lt_features(self) -> LTFeatures:
|
||||
return self.__io.get(TSI_DPTX_LT_FEATURES, LTFeatures)[1]
|
||||
return self.__io.get(ci.TSI_DPTX_LT_FEATURES, LTFeatures)[1]
|
||||
|
||||
def __read_link_status(self) -> LinkTxStatus:
|
||||
return self.__io.get(TSI_DPTX_LINK_STATUS_R, LinkTxStatus)[1]
|
||||
return self.__io.get(ci.TSI_DPTX_LINK_STATUS_R, LinkTxStatus)[1]
|
||||
|
||||
def __check_custom_bit_rate(self) -> float:
|
||||
res = self.__io.get(TSI_DP2TX_CUSTOM_RATE_MAP, c_uint32, 3)[1]
|
||||
res = self.__io.get(ci.TSI_DP2TX_CUSTOM_RATE_MAP, c_uint32, 3)[1]
|
||||
for i in range(3):
|
||||
if res[i] != 0:
|
||||
return res[i] * 200000 / 1000000000
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from ctypes import c_uint32
|
||||
|
||||
|
||||
@@ -44,10 +44,10 @@ class ArcRx:
|
||||
self.__single_mode = True
|
||||
|
||||
def __read_arc_status(self) -> int:
|
||||
return self.__io.get(TSI_HDRX_ARC_STATUS_R, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDRX_ARC_STATUS_R, c_uint32)[1]
|
||||
|
||||
def __write_arc(self, value: int):
|
||||
self.__io.set(TSI_ARC_CONTROL_W, value, c_uint32)
|
||||
self.__io.set(ci.TSI_ARC_CONTROL_W, value, c_uint32)
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from ctypes import c_uint32
|
||||
|
||||
|
||||
@@ -19,16 +19,16 @@ class FrlControlRx:
|
||||
self.__ltp_additional = LtpLanesPattern()
|
||||
|
||||
def __read_caps(self) -> int:
|
||||
return self.__io.get(TSI_HDRX_FRL_CAPABILITY, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDRX_FRL_CAPABILITY, c_uint32)[1]
|
||||
|
||||
def __write_caps(self, value: int):
|
||||
self.__io.set(TSI_HDRX_FRL_CAPABILITY, value, c_uint32)
|
||||
self.__io.set(ci.TSI_HDRX_FRL_CAPABILITY, value, c_uint32)
|
||||
|
||||
def __read_frl_pattern(self) -> int:
|
||||
return self.__io.get(TSI_HDRX_FRL_PATTERN, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDRX_FRL_PATTERN, c_uint32)[1]
|
||||
|
||||
def __write_frl_pattern(self, value: int):
|
||||
self.__io.set(TSI_HDRX_FRL_PATTERN, value, c_uint32)
|
||||
self.__io.set(ci.TSI_HDRX_FRL_PATTERN, value, c_uint32)
|
||||
|
||||
@property
|
||||
def frl_mode(self) -> FrlMode:
|
||||
@@ -130,7 +130,7 @@ class FrlControlRx:
|
||||
"""
|
||||
DO re train.
|
||||
"""
|
||||
self.__io.set(TSI_HDRX_LINK_STATUS_R, 0x1c0000, c_uint32)
|
||||
self.__io.set(ci.TSI_HDRX_LINK_STATUS_R, 0x1c0000, c_uint32)
|
||||
|
||||
def __str__(self):
|
||||
return f"FRL Mode: {self.frl_mode.name}\n" \
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
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
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from ctypes import c_uint32
|
||||
|
||||
|
||||
@@ -197,19 +196,19 @@ class FrlControlTx:
|
||||
self.__ltp_additional = LtpLanesPattern()
|
||||
|
||||
def __read_caps(self) -> int:
|
||||
return self.__io.get(TSI_HDTX_FRL_CAPABILITY, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDTX_FRL_CAPABILITY, c_uint32)[1]
|
||||
|
||||
def __write_caps(self, value: int):
|
||||
self.__io.set(TSI_HDTX_FRL_CAPABILITY, value, c_uint32)
|
||||
self.__io.set(ci.TSI_HDTX_FRL_CAPABILITY, value, c_uint32)
|
||||
|
||||
def __read_frl_timers(self) -> int:
|
||||
return self.__io.get(TSI_HDTX_FRL_TIMERS, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDTX_FRL_TIMERS, c_uint32)[1]
|
||||
|
||||
def __write_frl_timers(self, value: int):
|
||||
self.__io.set(TSI_HDTX_FRL_TIMERS, value, c_uint32)
|
||||
self.__io.set(ci.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]
|
||||
return self.__io.get(ci.TSI_HDTX_FRL_PATTERN_R, c_uint32)[1]
|
||||
|
||||
@property
|
||||
def ltp_pattern(self) -> LtpLanesPattern:
|
||||
@@ -243,7 +242,7 @@ class FrlControlTx:
|
||||
Returns:
|
||||
object of `FrlCaps` type
|
||||
"""
|
||||
_update_frl_values(self.__frl_caps, self.__io.get(TSI_HDTX_FRL_STATUS_R, c_uint32)[1])
|
||||
_update_frl_values(self.__frl_caps, self.__io.get(ci.TSI_HDTX_FRL_STATUS_R, c_uint32)[1])
|
||||
return self.__frl_caps
|
||||
|
||||
@property
|
||||
@@ -345,7 +344,7 @@ class FrlControlTx:
|
||||
"""
|
||||
Do link training.
|
||||
"""
|
||||
self.__io.set(TSI_HDTX_SINK_FEATURE_W, 5, c_uint32)
|
||||
self.__io.set(ci.TSI_HDTX_SINK_FEATURE_W, 5, c_uint32)
|
||||
|
||||
@staticmethod
|
||||
def __update_values(ffe_max: FfeMax, value: int):
|
||||
|
||||
@@ -9,7 +9,7 @@ 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
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class HdmiLinkTx:
|
||||
self.__tmds = TmdsTx(self.__io)
|
||||
self.__status = StatusTx(self.__io)
|
||||
self.__frl = FrlControlTx(self.__io)
|
||||
self.__caps = HdmiCapabilities(TSI_HDTX_CAPABILITY_R, self.__io)
|
||||
self.__caps = HdmiCapabilities(ci.TSI_HDTX_CAPABILITY_R, self.__io)
|
||||
|
||||
@property
|
||||
def tmds(self) -> Optional[TmdsTx]:
|
||||
@@ -96,7 +96,7 @@ class HdmiLinkRx:
|
||||
self.__status = StatusRx(self.__io)
|
||||
self.__frl = FrlControlRx(self.__io)
|
||||
self.__arc = ArcRx(self.__io)
|
||||
self.__caps = HdmiCapabilities(TSI_HDRX_CAPABILITY_R, self.__io)
|
||||
self.__caps = HdmiCapabilities(ci.TSI_HDRX_CAPABILITY_R, self.__io)
|
||||
|
||||
@property
|
||||
def tmds(self) -> Optional[TmdsRx]:
|
||||
|
||||
@@ -2,9 +2,7 @@ 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
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
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
|
||||
@@ -25,7 +23,7 @@ class StatusRx:
|
||||
self.__io = port_io
|
||||
|
||||
def __frl_status(self) -> FrlMode:
|
||||
return FrlMode(self.__io.get(TSI_HDRX_FRL_CAPABILITY, c_uint32)[1] & 0xF)
|
||||
return FrlMode(self.__io.get(ci.TSI_HDRX_FRL_CAPABILITY, c_uint32)[1] & 0xF)
|
||||
|
||||
@property
|
||||
def hdmi_mode(self) -> HdmiModeRx:
|
||||
@@ -35,7 +33,7 @@ class StatusRx:
|
||||
Returns:
|
||||
object of `HdmiModeRx` type
|
||||
"""
|
||||
return HdmiModeRx(self.__io.get(TSI_HDRX_BEHAVIOR, c_uint32)[1])
|
||||
return HdmiModeRx(self.__io.get(ci.TSI_HDRX_BEHAVIOR, c_uint32)[1])
|
||||
|
||||
@hdmi_mode.setter
|
||||
def hdmi_mode(self, hdmi_mode: HdmiModeRx):
|
||||
@@ -45,7 +43,7 @@ class StatusRx:
|
||||
Args:
|
||||
hdmi_mode (HdmiModeRx)
|
||||
"""
|
||||
self.__io.set(TSI_HDRX_BEHAVIOR, hdmi_mode.value, c_uint32)
|
||||
self.__io.set(ci.TSI_HDRX_BEHAVIOR, hdmi_mode.value, c_uint32)
|
||||
|
||||
@property
|
||||
def error_counters(self) -> list:
|
||||
@@ -55,7 +53,7 @@ class StatusRx:
|
||||
Returns:
|
||||
object of list type
|
||||
"""
|
||||
return _update_error_counters_rx(self.__io.get(TSI_HDRX_LANES_ERR_COUNTERS_R, c_uint64)[1])
|
||||
return _update_error_counters_rx(self.__io.get(ci.TSI_HDRX_LANES_ERR_COUNTERS_R, c_uint64)[1])
|
||||
|
||||
def set_assert_state(self, asserted: bool = True):
|
||||
"""
|
||||
@@ -64,7 +62,7 @@ class StatusRx:
|
||||
Args:
|
||||
asserted (bool)
|
||||
"""
|
||||
self.__io.set(TSI_HDRX_HPD_CONTROL_W, int(asserted), c_uint32)
|
||||
self.__io.set(ci.TSI_HDRX_HPD_CONTROL_W, int(asserted), c_uint32)
|
||||
|
||||
@property
|
||||
def channel_lock(self) -> list:
|
||||
@@ -74,7 +72,7 @@ class StatusRx:
|
||||
Returns:
|
||||
object of list type
|
||||
"""
|
||||
return self.__update_channel_lock(self.__io.get(TSI_HDRX_LINK_STATUS_R, c_uint32)[1], self.hdmi_mode)
|
||||
return self.__update_channel_lock(self.__io.get(ci.TSI_HDRX_LINK_STATUS_R, c_uint32)[1], self.hdmi_mode)
|
||||
|
||||
@staticmethod
|
||||
def __update_channel_lock(value: int, mode: HdmiModeRx) -> list:
|
||||
@@ -99,11 +97,11 @@ class StatusRx:
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return (self.__io.get(TSI_HDRX_HPD_STATUS_R, c_uint32)[1] & 0x1) != 0
|
||||
return (self.__io.get(ci.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)
|
||||
result, msa_info, size = io.get(ci.TSI_HDRX_VIDEO_MODE_R, HdmiVideoMode, 4)
|
||||
return result > 0
|
||||
|
||||
return function_scheduler(is_msa_available, self.__io, interval=5, timeout=10)
|
||||
@@ -125,7 +123,7 @@ class StatusRx:
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
result, hdmi_video_mode_info, size = self.__io.get(TSI_HDRX_VIDEO_MODE_R, HdmiVideoMode, 4)
|
||||
result, hdmi_video_mode_info, size = self.__io.get(ci.TSI_HDRX_VIDEO_MODE_R, HdmiVideoMode, 4)
|
||||
|
||||
# TODO - Size temporary will be equal 1
|
||||
size = 1
|
||||
@@ -133,8 +131,8 @@ class StatusRx:
|
||||
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:
|
||||
result = self.__io.get(ci.TSI_VIDCAP_SIGNAL_CRC_R, data_type=c_uint8, data_count=6)
|
||||
if result[0] >= ci.TSI_SUCCESS:
|
||||
hdmi_crc = HdmiCrc.from_buffer(bytearray(result[1]))
|
||||
stream_status.crc = [hdmi_crc.r, hdmi_crc.g, hdmi_crc.b]
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
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
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from ctypes import c_uint32, c_uint64
|
||||
|
||||
|
||||
@@ -19,10 +18,10 @@ class StatusTx:
|
||||
self.__io = port_io
|
||||
|
||||
def __read_status(self) -> int:
|
||||
return self.__io.get(TSI_HDTX_STATUS_R, c_uint32)[1]
|
||||
return self.__io.get(ci.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)
|
||||
return FrlMode(self.__io.get(ci.TSI_HDTX_FRL_STATUS_R, c_uint32)[1] & 0xF)
|
||||
|
||||
@property
|
||||
def video_status(self) -> bool:
|
||||
@@ -42,7 +41,7 @@ class StatusTx:
|
||||
Returns:
|
||||
object of list type
|
||||
"""
|
||||
return _update_error_counters_tx(self.__io.get(TSI_HDTX_LANES_ERR_COUNTERS_R, c_uint64)[1])
|
||||
return _update_error_counters_tx(self.__io.get(ci.TSI_HDTX_LANES_ERR_COUNTERS_R, c_uint64)[1])
|
||||
|
||||
@property
|
||||
def channel_lock(self) -> list:
|
||||
@@ -53,9 +52,9 @@ class StatusTx:
|
||||
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)
|
||||
return self.__update_channel_lock(self.__io.get(ci.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)
|
||||
return self.__update_channel_lock(self.__io.get(ci.TSI_HDTX_FRL_STATUS_R, c_uint32)[1], self.hdmi_mode)
|
||||
|
||||
@property
|
||||
def hpd_status(self) -> bool:
|
||||
@@ -65,7 +64,7 @@ class StatusTx:
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
return (self.__io.get(TSI_HDTX_HPD_STATUS_R, c_uint32)[1] & 0x1) != 0
|
||||
return (self.__io.get(ci.TSI_HDTX_HPD_STATUS_R, c_uint32)[1] & 0x1) != 0
|
||||
|
||||
@property
|
||||
def hdmi_mode(self) -> HdmiModeTx:
|
||||
@@ -85,7 +84,7 @@ class StatusTx:
|
||||
Args:
|
||||
hdmi_mode (HdmiModeTx)
|
||||
"""
|
||||
self.__io.set(TSI_HDTX_CONTROL_W, hdmi_mode.value << 2, c_uint32)
|
||||
self.__io.set(ci.TSI_HDTX_CONTROL_W, hdmi_mode.value << 2, c_uint32)
|
||||
|
||||
@property
|
||||
def available_link_rate(self) -> float:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from ctypes import c_uint32
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class TmdsRx:
|
||||
self.__input_stream_lock = False
|
||||
|
||||
def __read_link_status(self) -> int:
|
||||
return self.__io.get(TSI_HDRX_LINK_STATUS_R, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_HDRX_LINK_STATUS_R, c_uint32)[1]
|
||||
|
||||
@property
|
||||
def clock_rate(self) -> int:
|
||||
@@ -27,7 +27,7 @@ class TmdsRx:
|
||||
Returns:
|
||||
object of int type
|
||||
"""
|
||||
return 6 if self.__read_link_status() & 0x2 else 3
|
||||
return 6 if self.__read_link_status() >> 1 & 0x1 else 3
|
||||
|
||||
@property
|
||||
def link_mode(self) -> LinkMode:
|
||||
@@ -37,7 +37,7 @@ class TmdsRx:
|
||||
Returns:
|
||||
object of `LinkMode` type
|
||||
"""
|
||||
self.__link_mode = LinkMode(self.__read_link_status() & 0x8)
|
||||
self.__link_mode = LinkMode(self.__read_link_status() >> 3 & 0x1)
|
||||
return self.__link_mode
|
||||
|
||||
@property
|
||||
@@ -48,7 +48,7 @@ class TmdsRx:
|
||||
Returns:
|
||||
object of bool type
|
||||
"""
|
||||
self.__input_stream_lock = (self.__read_link_status() & 0x4) != 0
|
||||
self.__input_stream_lock = (self.__read_link_status() >> 2 & 0x1) != 0
|
||||
return self.__input_stream_lock
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@@ -2,8 +2,7 @@ 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
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from ctypes import c_uint32
|
||||
|
||||
|
||||
@@ -21,13 +20,13 @@ class TmdsTx:
|
||||
self.__scrambler = ScramblerState.Unknown
|
||||
|
||||
def __read_sink_status(self) -> int:
|
||||
return self.__io.get(TSI_HDTX_SINK_STATUS_R, c_uint32)[1]
|
||||
return self.__io.get(ci.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]
|
||||
return self.__io.get(ci.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)
|
||||
self.__io.set(ci.TSI_HDTX_SINK_FEATURE_W, value, c_uint32)
|
||||
|
||||
@property
|
||||
def clock_rate(self) -> int:
|
||||
@@ -71,7 +70,7 @@ class TmdsTx:
|
||||
Args:
|
||||
link_mode (LinkMode)
|
||||
"""
|
||||
self.__io.set(TSI_HDTX_CONTROL_W, link_mode.value, c_uint32)
|
||||
self.__io.set(ci.TSI_HDTX_CONTROL_W, link_mode.value, c_uint32)
|
||||
|
||||
@property
|
||||
def scrambler(self) -> bool:
|
||||
|
||||
1
UniTAP/dev/ports/modules/packet_generator/__init__.py
Normal file
1
UniTAP/dev/ports/modules/packet_generator/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .packet_generator import PacketGenerator
|
||||
@@ -0,0 +1,92 @@
|
||||
from ctypes import c_byte
|
||||
from typing import Union, List, Optional
|
||||
|
||||
from UniTAP.libs.lib_tsi import ci, p_ci
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
from UniTAP.dev.modules import MemoryManager
|
||||
|
||||
|
||||
class PacketGenerator:
|
||||
class Status:
|
||||
def __init__(self, value: int):
|
||||
self.enabled = bool(value & 0x1)
|
||||
self.active = bool(value & 0x2)
|
||||
self.error = bool(value & 0x4)
|
||||
self.overflow = bool(value & 0x8)
|
||||
|
||||
def __str__(self):
|
||||
return f"Packet Generator Status: Enabled: {self.enabled}; Active: {self.active}; Error: {self.error}; Overflow: {self.overflow};"
|
||||
"""
|
||||
|
||||
Main class `PacketGenerator` allows working with PG functionality on the device: set different types of pattern
|
||||
`set_pattern`, set different video modes `set_vm`, set additional parameters for some patterns `set_pattern_params`,
|
||||
get information about current video mode on stream `get_stream_video_mode`, `apply` all transferred setting,
|
||||
`reset` settings and read pattern generator `status`.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, port_io: PortIO, memory_manager: MemoryManager):
|
||||
self.__io = port_io
|
||||
self.__memory_manager = memory_manager
|
||||
self.__packets = []
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
|
||||
Reset static packet generator settings to default values.
|
||||
|
||||
"""
|
||||
self.stop()
|
||||
self.__packets = []
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
|
||||
Start packet generator with current settings.
|
||||
|
||||
"""
|
||||
self.stop()
|
||||
self.__upload_data()
|
||||
if self.__io.set(ci.TSI_PACKETGEN_CONTROL_W, 1) < ci.TSI_SUCCESS:
|
||||
raise Exception("Failed to start packet generator")
|
||||
|
||||
def stop(self):
|
||||
"""
|
||||
|
||||
Stop packet generator.
|
||||
|
||||
"""
|
||||
self.__io.set(ci.TSI_PACKETGEN_CONTROL_W, 2)
|
||||
|
||||
def status(self) -> Status:
|
||||
"""
|
||||
|
||||
Get current status of packet generator.
|
||||
|
||||
Returns:
|
||||
Status - current status of packet generator
|
||||
"""
|
||||
return PacketGenerator.Status(self.__io.get(ci.TSI_PACKETGEN_STATUS_R)[1])
|
||||
|
||||
def add_packet(self, raw_packet_data: bytearray):
|
||||
self.__packets.append(raw_packet_data)
|
||||
|
||||
def load_packet(self, file_path: str):
|
||||
with open(file_path, "rb") as f:
|
||||
packet_data = f.read()
|
||||
self.__packets.append(bytearray(packet_data))
|
||||
|
||||
def __upload_data(self):
|
||||
mem_layout = self.__memory_manager.get_memory_layout()
|
||||
if len(mem_layout) <= MemoryManager.MemoryOwner.MO_Events.value or mem_layout[MemoryManager.MemoryOwner.MO_Events.value] == 0:
|
||||
self.__memory_manager.make_default()
|
||||
|
||||
if self.__io.set(ci.TSI_PACKETGEN_PACKETS_NUMBER, len(self.__packets)) < ci.TSI_SUCCESS:
|
||||
raise Exception("Failed to set packets number for packet generator")
|
||||
for index, packet in enumerate(self.__packets):
|
||||
if self.__io.set(ci.TSI_PACKETGEN_PACKET_DATA, packet, data_type=c_byte, data_count=len(packet)) < ci.TSI_SUCCESS:
|
||||
raise Exception(f"Failed to set packet data for packet {index} in packet generator")
|
||||
|
||||
if self.__io.set(ci.TSI_PACKETGEN_MEM_BLOCK, int(MemoryManager.MemoryOwner.MO_Events)) < ci.TSI_SUCCESS:
|
||||
raise Exception("Failed to set memory block for packet generator")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
from UniTAP.libs.lib_tsi.tsi import *
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
from .pr_private_types import *
|
||||
from .pr_status import PanelReplayStatus
|
||||
from .pr_config import PanelReplayConfig
|
||||
@@ -68,6 +69,6 @@ class PanelReplay:
|
||||
self.__write_pr_control(PrControl.EnableSelectiveUpdate)
|
||||
|
||||
def __write_pr_control(self, command: PrControl):
|
||||
self.__io.set(TSI_PG_STREAM_SELECT, 0)
|
||||
self.__io.set(TSI_PG_PR_CTRL_W, command.value)
|
||||
self.__io.set(ci.TSI_PG_STREAM_SELECT, 0)
|
||||
self.__io.set(p_ci.TSI_PG_PR_CTRL_W, command.value)
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
from UniTAP.libs.lib_tsi.tsi import *
|
||||
import UniTAP.libs.lib_tsi.tsi as tsi
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
from .pr_types import *
|
||||
from .pr_private_types import *
|
||||
|
||||
@@ -35,7 +37,7 @@ class PanelReplayConfig:
|
||||
"""
|
||||
caps = self.pr_caps
|
||||
|
||||
self.__io.set(TSI_PG_STREAM_SELECT, 0)
|
||||
self.__io.set(ci.TSI_PG_STREAM_SELECT, 0)
|
||||
pr_config, _ = self.__read_config()
|
||||
|
||||
pr_config.early_transport = config.flags.early_transport if caps.pr_flags().early_transport else 0
|
||||
@@ -60,7 +62,7 @@ class PanelReplayConfig:
|
||||
region = RegionConfig(0)
|
||||
region.value = item
|
||||
data.extend(region.value)
|
||||
self.__io.set(TSI_PG_PR_CFG, data, data_count=len(data))
|
||||
self.__io.set(p_ci.TSI_PG_PR_CFG, data, data_count=len(data))
|
||||
|
||||
def get(self) -> PrSettings:
|
||||
"""
|
||||
@@ -114,8 +116,8 @@ class PanelReplayConfig:
|
||||
def __read_config(self):
|
||||
caps = self.pr_caps
|
||||
|
||||
self.__io.set(TSI_PG_STREAM_SELECT, 0)
|
||||
result = self.__io.get(TSI_PG_PR_CFG, c_uint32, caps.calculate_size())[1]
|
||||
self.__io.set(ci.TSI_PG_STREAM_SELECT, 0)
|
||||
result = self.__io.get(p_ci.TSI_PG_PR_CFG, c_uint32, caps.calculate_size())[1]
|
||||
if not isinstance(result, list):
|
||||
result = [0]
|
||||
pr_config = PrConfig(result[0])
|
||||
@@ -128,5 +130,5 @@ class PanelReplayConfig:
|
||||
return pr_config, pr_regions
|
||||
|
||||
def __read_caps(self) -> PRCaps:
|
||||
self.__io.set(TSI_PG_STREAM_SELECT, 0)
|
||||
return self.__io.get(TSI_PG_PR_CAPS_R, PRCaps)[1]
|
||||
self.__io.set(ci.TSI_PG_STREAM_SELECT, 0)
|
||||
return self.__io.get(p_ci.TSI_PG_PR_CAPS_R, PRCaps)[1]
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
from ctypes import c_int, c_uint32
|
||||
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
from .pr_sink_private_types import SinkPanelReplayCapsStruct, SinkPanelSelfRefreshCapsStruct
|
||||
from .pr_sink_types import PRCapsFlags, PrGranularityCaps, SuYGranularity, PSRCapsFlags, PSRCaps, PSRSetupTime
|
||||
from UniTAP.libs.lib_tsi.tsi import *
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from typing import Tuple
|
||||
|
||||
|
||||
@@ -27,7 +29,7 @@ class SinkPanelReplayCaps:
|
||||
(flags.y_gran_extended_supported << 14) | (flags.link_off_supported << 15))
|
||||
|
||||
self.__write([flags_value, x_granularity.value, y_granularity.value, granularity.combined_value()])
|
||||
self.__io.set(TSI_DPRX_HPD_PULSE_W, 500000, c_int)
|
||||
self.__io.set(ci.TSI_DPRX_HPD_PULSE_W, 500000, c_int)
|
||||
|
||||
def get(self) -> Tuple[PRCapsFlags, PrGranularityCaps, PrGranularityCaps, SuYGranularity]:
|
||||
caps = self.__read()
|
||||
@@ -65,10 +67,10 @@ class SinkPanelReplayCaps:
|
||||
return flags, x_granularity, y_granularity, granularity
|
||||
|
||||
def __read(self) -> SinkPanelReplayCapsStruct:
|
||||
return self.__io.get(TSI_DPRX_PR_CAPS, SinkPanelReplayCapsStruct)[1]
|
||||
return self.__io.get(ci.TSI_DPRX_PR_CAPS, SinkPanelReplayCapsStruct)[1]
|
||||
|
||||
def __write(self, data: list):
|
||||
self.__io.set(TSI_DPRX_PR_CAPS, data, data_type=c_uint32, data_count=len(data))
|
||||
self.__io.set(ci.TSI_DPRX_PR_CAPS, data, data_type=c_uint32, data_count=len(data))
|
||||
|
||||
|
||||
class SinkPanelSelfRefreshCaps:
|
||||
@@ -105,7 +107,7 @@ class SinkPanelSelfRefreshCaps:
|
||||
return flags, x_granularity, y_granularity
|
||||
|
||||
def __read(self) -> SinkPanelSelfRefreshCapsStruct:
|
||||
return self.__io.get(TSI_DPRX_PSR_CAPS, SinkPanelSelfRefreshCapsStruct)[1]
|
||||
return self.__io.get(ci.TSI_DPRX_PSR_CAPS, SinkPanelSelfRefreshCapsStruct)[1]
|
||||
|
||||
def __write(self, data: list):
|
||||
self.__io.set(TSI_DPRX_PSR_CAPS, data, data_type=c_uint32, data_count=len(data))
|
||||
self.__io.set(ci.TSI_DPRX_PSR_CAPS, data, data_type=c_uint32, data_count=len(data))
|
||||
@@ -1,7 +1,8 @@
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from .pr_sink_private_types import SinkPanelSelfRefreshStatusStruct, SinkPanelReplayStatusStruct
|
||||
from .pr_sink_types import (SinkPRStatusFlags, SelfStatus, FrameStatus, SinkPSRStatusFlags, PRSSelfRefreshStatus)
|
||||
from UniTAP.libs.lib_tsi.tsi import *
|
||||
import UniTAP.libs.lib_tsi.tsi as tsi
|
||||
|
||||
|
||||
class SinkPanelReplayStatus:
|
||||
@@ -31,7 +32,7 @@ class SinkPanelReplayStatus:
|
||||
|
||||
def __read(self) -> SinkPanelReplayStatusStruct:
|
||||
|
||||
return self.__io.get(TSI_DPRX_PR_STATUS, SinkPanelReplayStatusStruct)[1]
|
||||
return self.__io.get(ci.TSI_DPRX_PR_STATUS, SinkPanelReplayStatusStruct)[1]
|
||||
|
||||
|
||||
class SinkPanelSelfRefreshStatus:
|
||||
@@ -59,4 +60,4 @@ class SinkPanelSelfRefreshStatus:
|
||||
self_refresh=PRSSelfRefreshStatus(pr_flags.self_refresh))
|
||||
|
||||
def __read(self) -> SinkPanelSelfRefreshStatusStruct:
|
||||
return self.__io.get(TSI_DPRX_PSR_STATUS, SinkPanelSelfRefreshStatusStruct)[1]
|
||||
return self.__io.get(ci.TSI_DPRX_PSR_STATUS, SinkPanelSelfRefreshStatusStruct)[1]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from .pr_private_types import *
|
||||
from UniTAP.libs.lib_tsi.tsi import *
|
||||
from .pr_types import *
|
||||
|
||||
|
||||
@@ -43,6 +44,6 @@ class PanelReplayStatus:
|
||||
return PRError(self.__read().error)
|
||||
|
||||
def __read(self) -> PrStatus:
|
||||
self.__io.set(TSI_PG_STREAM_SELECT, 0)
|
||||
return self.__io.get(TSI_PG_PR_STATUS_R, PrStatus)[1]
|
||||
self.__io.set(ci.TSI_PG_STREAM_SELECT, 0)
|
||||
return self.__io.get(p_ci.TSI_PG_PR_STATUS_R, PrStatus)[1]
|
||||
|
||||
|
||||
@@ -237,6 +237,12 @@ class PdcControls500(PdcControlsBase):
|
||||
super().__init__(pdc_io)
|
||||
self.__io = pdc_io
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
Reset device.
|
||||
"""
|
||||
self.__io.write_hw_command(HWControlCommand.ResetPDController)
|
||||
|
||||
def reconnect(self) -> bool:
|
||||
"""
|
||||
Reconnect device.
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
from ctypes import c_uint32
|
||||
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
from UniTAP.libs.lib_tsi.tsi_private_types import *
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
from .pdc_private_dpam_types import DPAMCaps, DPAMState, DPAMCommand, DPAMConfig, DPAMDiscModes, DPAMRecv
|
||||
from .pdc_private_types import HWControlCommand, HWStatus, HWCaps, PDCStatus, PDCControlCommand, PDCState, PDCCaps, \
|
||||
PDCContractInfo
|
||||
@@ -13,103 +16,103 @@ class PDCPortIO:
|
||||
self.write_adc_control()
|
||||
|
||||
def write_dpam_caps(self, caps: DPAMCaps):
|
||||
self.__io.set(TSI_PDC_DPAM_CAPS, caps.value(), c_uint32)
|
||||
self.__io.set(ci.TSI_PDC_DPAM_CAPS, caps.value(), c_uint32)
|
||||
|
||||
def read_dpam_caps(self) -> DPAMCaps:
|
||||
return self.__io.get(TSI_PDC_DPAM_CAPS, DPAMCaps)[1]
|
||||
return self.__io.get(ci.TSI_PDC_DPAM_CAPS, DPAMCaps)[1]
|
||||
|
||||
def read_dpam_caps2(self) -> bool:
|
||||
return (self.__io.get(TSI_PDC_DPAM_CAPS2, c_uint32)[1] & 0x1) != 0
|
||||
return (self.__io.get(ci.TSI_PDC_DPAM_CAPS2, c_uint32)[1] & 0x1) != 0
|
||||
|
||||
def read_dpam_state(self) -> DPAMState:
|
||||
return self.__io.get(TSI_PDC_DPAM_STATE_R, DPAMState)[1]
|
||||
return self.__io.get(ci.TSI_PDC_DPAM_STATE_R, DPAMState)[1]
|
||||
|
||||
def write_dpam_control(self, command: DPAMCommand):
|
||||
self.__io.set(TSI_PDC_DPAM_CONTROL_W, command.value, c_uint32)
|
||||
self.__io.set(ci.TSI_PDC_DPAM_CONTROL_W, command.value, c_uint32)
|
||||
|
||||
def read_dpam_config(self) -> DPAMConfig:
|
||||
return self.__io.get(TSI_PDC_DPAM_CONFIG_R, DPAMConfig)[1]
|
||||
return self.__io.get(p_ci.TSI_PDC_DPAM_CONFIG_R, DPAMConfig)[1]
|
||||
|
||||
def read_dpam_disc_modes(self) -> DPAMDiscModes:
|
||||
return self.__io.get(TSI_PDC_DPAM_DISC_MODES_R, DPAMDiscModes)[1]
|
||||
return self.__io.get(ci.TSI_PDC_DPAM_DISC_MODES_R, DPAMDiscModes)[1]
|
||||
|
||||
def read_dpam_recv(self) -> DPAMRecv:
|
||||
return self.__io.get(TSI_PDC_DPAM_RECV_STS_R, DPAMRecv)[1]
|
||||
return self.__io.get(ci.TSI_PDC_DPAM_RECV_STS_R, DPAMRecv)[1]
|
||||
|
||||
def write_hw_command(self, command: HWControlCommand):
|
||||
self.__io.set(TSI_PDC_HW_CONTROL_W, command.value, c_uint32)
|
||||
self.__io.set(ci.TSI_PDC_HW_CONTROL_W, command.value, c_uint32)
|
||||
|
||||
def read_hw_status(self) -> HWStatus:
|
||||
return self.__io.get(TSI_PDC_HW_STATUS_R, HWStatus)[1]
|
||||
return self.__io.get(ci.TSI_PDC_HW_STATUS_R, HWStatus)[1]
|
||||
|
||||
def read_hw_caps(self) -> HWCaps:
|
||||
return self.__io.get(TSI_PDC_HW_CAPS_R, HWCaps)[1]
|
||||
return self.__io.get(p_ci.TSI_PDC_HW_CAPS_R, HWCaps)[1]
|
||||
|
||||
def read_pdc_status(self) -> PDCStatus:
|
||||
return self.__io.get(TSI_PDC_STATUS_R, PDCStatus)[1]
|
||||
return self.__io.get(ci.TSI_PDC_STATUS_R, PDCStatus)[1]
|
||||
|
||||
def write_pdc_command(self, command: PDCControlCommand):
|
||||
self.__io.set(TSI_PDC_CONTROL, command.value, c_uint32)
|
||||
self.__io.set(ci.TSI_PDC_CONTROL, command.value, c_uint32)
|
||||
|
||||
def read_pdc_state(self) -> PDCState:
|
||||
return self.__io.get(TSI_PDC_STATE, PDCState)[1]
|
||||
return self.__io.get(ci.TSI_PDC_STATE, PDCState)[1]
|
||||
|
||||
def read_pdc_caps(self) -> PDCCaps:
|
||||
return self.__io.get(TSI_PDC_CAPS, PDCCaps)[1]
|
||||
return self.__io.get(ci.TSI_PDC_CAPS, PDCCaps)[1]
|
||||
|
||||
def write_pdc_contract_control(self, caps: PDCContractInfo):
|
||||
self.__io.set(TSI_USBC_PWR_CONTRACT_CONTROL, caps.value(), c_uint32)
|
||||
self.__io.set(ci.TSI_USBC_PWR_CONTRACT_CONTROL, caps.value(), c_uint32)
|
||||
|
||||
def read_pdc_contract_control(self) -> PDCContractInfo:
|
||||
return self.__io.get(TSI_USBC_PWR_CONTRACT_CONTROL, PDCContractInfo)[1]
|
||||
return self.__io.get(ci.TSI_USBC_PWR_CONTRACT_CONTROL, PDCContractInfo)[1]
|
||||
|
||||
def read_local_spr_source_pdo(self) -> list:
|
||||
return self.__io.get(TSI_USBC_PWR_LOCAL_SOURCE_PDO, PdoUnion, self.read_hw_caps().pdo_count)[1]
|
||||
return self.__io.get(ci.TSI_USBC_PWR_LOCAL_SOURCE_PDO, PdoUnion, self.read_hw_caps().pdo_count)[1]
|
||||
|
||||
def write_local_spr_source_pdo(self, data: list):
|
||||
self.__io.set(TSI_USBC_PWR_LOCAL_SOURCE_PDO, data, c_uint32, len(data))
|
||||
self.__io.set(ci.TSI_USBC_PWR_LOCAL_SOURCE_PDO, data, c_uint32, len(data))
|
||||
|
||||
def read_local_spr_sink_pdo(self) -> list:
|
||||
return self.__io.get(TSI_USBC_PWR_LOCAL_SINK_PDO, PdoUnion, self.read_hw_caps().pdo_count)[1]
|
||||
return self.__io.get(ci.TSI_USBC_PWR_LOCAL_SINK_PDO, PdoUnion, self.read_hw_caps().pdo_count)[1]
|
||||
|
||||
def write_local_spr_sink_pdo(self, data: list):
|
||||
self.__io.set(TSI_USBC_PWR_LOCAL_SINK_PDO, data, c_uint32, len(data))
|
||||
self.__io.set(ci.TSI_USBC_PWR_LOCAL_SINK_PDO, data, c_uint32, len(data))
|
||||
|
||||
def read_tx_id_vdo_count(self) -> int:
|
||||
return self.__io.get(TSI_PDC_TX_ID_VDO_CNT, c_uint32)[1]
|
||||
return self.__io.get(p_ci.TSI_PDC_TX_ID_VDO_CNT, c_uint32)[1]
|
||||
|
||||
def read_tx_id_vdo(self) -> list:
|
||||
return self.__io.get(TSI_PDC_TX_ID_VDO, c_uint32, self.read_tx_id_vdo_count())[1]
|
||||
return self.__io.get(p_ci.TSI_PDC_TX_ID_VDO, c_uint32, self.read_tx_id_vdo_count())[1]
|
||||
|
||||
def write_tx_id_vdo(self, data: list):
|
||||
self.__io.set(TSI_PDC_TX_ID_VDO, data, c_uint32, len(data))
|
||||
self.__io.set(p_ci.TSI_PDC_TX_ID_VDO, data, c_uint32, len(data))
|
||||
|
||||
def read_contract_data(self) -> list:
|
||||
return self.__io.get(TSI_PDC_CONTRACT_DATA, c_uint32, 4)[1]
|
||||
return self.__io.get(p_ci.TSI_PDC_CONTRACT_DATA, c_uint32, 4)[1]
|
||||
|
||||
def write_contract_data(self, data: list):
|
||||
self.__io.set(TSI_PDC_CONTRACT_DATA, data, c_uint32, len(data))
|
||||
self.__io.set(p_ci.TSI_PDC_CONTRACT_DATA, data, c_uint32, len(data))
|
||||
|
||||
def read_power_contract_select(self) -> int:
|
||||
return self.__io.get(TSI_USBC_PWR_CONTRACT_SELECT, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_USBC_PWR_CONTRACT_SELECT, c_uint32)[1]
|
||||
|
||||
def write_power_contract_select(self, index: int):
|
||||
self.__io.set(TSI_USBC_PWR_CONTRACT_SELECT, index, c_uint32)
|
||||
self.__io.set(ci.TSI_USBC_PWR_CONTRACT_SELECT, index, c_uint32)
|
||||
|
||||
def read_resistance(self) -> int:
|
||||
return self.__io.get(TSI_USBC_RESISTANCE_CONTROL, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_USBC_RESISTANCE_CONTROL, c_uint32)[1]
|
||||
|
||||
def write_resistance(self, resistance: int):
|
||||
self.__io.set(TSI_USBC_RESISTANCE_CONTROL, resistance, c_uint32)
|
||||
self.__io.set(ci.TSI_USBC_RESISTANCE_CONTROL, resistance, c_uint32)
|
||||
|
||||
def read_adc_vbus_status(self) -> list:
|
||||
return self.__io.get(TSI_ADC_VBUS_VOLTAGE_R, c_uint32, TSI_ADC_BLOCK_SIZE_WORDS)[1]
|
||||
return self.__io.get(ci.TSI_ADC_VBUS_VOLTAGE_R, c_uint32, ci.TSI_ADC_BLOCK_SIZE_WORDS)[1]
|
||||
|
||||
def read_internal_resistance(self) -> int:
|
||||
return self.__io.get(TSI_USBC_INT_RESISTANCE_STATUS_R, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_USBC_INT_RESISTANCE_STATUS_R, c_uint32)[1]
|
||||
|
||||
def read_external_resistance(self) -> int:
|
||||
return self.__io.get(TSI_USBC_EXT_RESISTANCE_STATUS_R, c_uint32)[1]
|
||||
return self.__io.get(ci.TSI_USBC_EXT_RESISTANCE_STATUS_R, c_uint32)[1]
|
||||
|
||||
def write_adc_control(self):
|
||||
self.__io.set(TSI_W_USBC_ADC_CTRL, 1, c_uint32)
|
||||
self.__io.set(ci.TSI_W_USBC_ADC_CTRL, 1, c_uint32)
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import copy
|
||||
import os.path
|
||||
from ctypes import c_uint8, c_uint, c_uint32
|
||||
from typing import Union, List, Optional
|
||||
|
||||
from PIL import Image
|
||||
from UniTAP.utils import function_scheduler
|
||||
from UniTAP.libs.lib_tsi.tsi import *
|
||||
import UniTAP.libs.lib_tsi.tsi_types as ci
|
||||
import UniTAP.libs.lib_tsi.tsi_private_types as p_ci
|
||||
from UniTAP.libs.lib_tsi.tsi_io import PortIO
|
||||
from UniTAP.dev.modules import MemoryManager
|
||||
from UniTAP.dev.ports.modules.internal_utils.math import aligned
|
||||
@@ -26,29 +28,29 @@ Image.MAX_IMAGE_PIXELS = None
|
||||
|
||||
|
||||
def _read_predefined_timings(io: PortIO) -> List[Timing]:
|
||||
count = io.get(TSI_R_PG_PREDEF_TIMING_COUNT)[1]
|
||||
count = io.get(ci.TSI_R_PG_PREDEF_TIMING_COUNT)[1]
|
||||
|
||||
predefined_list = []
|
||||
|
||||
for i in range(count):
|
||||
io.set(TSI_W_PG_PREDEF_TIMING_SELECT, i)
|
||||
io.set(ci.TSI_W_PG_PREDEF_TIMING_SELECT, i)
|
||||
|
||||
timing = Timing()
|
||||
timing.htotal = io.get(TSI_PG_CUSTOM_TIMING_HTOTAL)[1]
|
||||
timing.vtotal = io.get(TSI_PG_CUSTOM_TIMING_VTOTAL)[1]
|
||||
timing.hactive = io.get(TSI_PG_CUSTOM_TIMING_HACTIVE)[1]
|
||||
timing.vactive = io.get(TSI_PG_CUSTOM_TIMING_VACTIVE)[1]
|
||||
timing.hstart = io.get(TSI_PG_CUSTOM_TIMING_HSTART)[1]
|
||||
timing.vstart = io.get(TSI_PG_CUSTOM_TIMING_VSTART)[1]
|
||||
timing.hswidth = io.get(TSI_PG_CUSTOM_TIMING_HSYNCW)[1]
|
||||
timing.vswidth = io.get(TSI_PG_CUSTOM_TIMING_VSYNCW)[1]
|
||||
timing.id = io.get(TSI_PG_CUSTOM_TIMING_ID)[1]
|
||||
timing.htotal = io.get(ci.TSI_PG_CUSTOM_TIMING_HTOTAL)[1]
|
||||
timing.vtotal = io.get(ci.TSI_PG_CUSTOM_TIMING_VTOTAL)[1]
|
||||
timing.hactive = io.get(ci.TSI_PG_CUSTOM_TIMING_HACTIVE)[1]
|
||||
timing.vactive = io.get(ci.TSI_PG_CUSTOM_TIMING_VACTIVE)[1]
|
||||
timing.hstart = io.get(ci.TSI_PG_CUSTOM_TIMING_HSTART)[1]
|
||||
timing.vstart = io.get(ci.TSI_PG_CUSTOM_TIMING_VSTART)[1]
|
||||
timing.hswidth = io.get(ci.TSI_PG_CUSTOM_TIMING_HSYNCW)[1]
|
||||
timing.vswidth = io.get(ci.TSI_PG_CUSTOM_TIMING_VSYNCW)[1]
|
||||
timing.id = io.get(ci.TSI_PG_CUSTOM_TIMING_ID)[1]
|
||||
# TODO: add conversion from pg AR to Timing AR
|
||||
timing.aspect_ratio = io.get(TSI_PG_CUSTOM_TIMING_ASPECT_RATIO)[1]
|
||||
timing.frame_rate = io.get(TSI_PG_CUSTOM_TIMING_FIELD_RATE)[1]
|
||||
timing.standard = Timing.Standard(io.get(TSI_PG_CUSTOM_TIMING_STANDARD)[1])
|
||||
timing.aspect_ratio = io.get(ci.TSI_PG_CUSTOM_TIMING_ASPECT_RATIO)[1]
|
||||
timing.frame_rate = io.get(ci.TSI_PG_CUSTOM_TIMING_FIELD_RATE)[1]
|
||||
timing.standard = Timing.Standard(io.get(ci.TSI_PG_CUSTOM_TIMING_STANDARD)[1])
|
||||
|
||||
timing_flags = io.get(TSI_PG_CUSTOM_TIMING_FLAGS)[1]
|
||||
timing_flags = io.get(ci.TSI_PG_CUSTOM_TIMING_FLAGS)[1]
|
||||
timing.hswidth *= (-1 if timing_flags >> 9 & 1 else 1)
|
||||
timing.vswidth *= (-1 if timing_flags >> 10 & 1 else 1)
|
||||
timing.reduce_blanking = Timing.ReduceBlanking((timing_flags >> 24) & 0x3)
|
||||
@@ -191,7 +193,7 @@ class PatternGenerator:
|
||||
|
||||
def __read_caps(self):
|
||||
self._become_active()
|
||||
return self.__io.get(TSI_PG_CAPS_R, PgCaps)[1]
|
||||
return self.__io.get(p_ci.TSI_PG_CAPS_R, PgCaps)[1]
|
||||
|
||||
def _caps(self) -> PgCaps:
|
||||
return self.__caps
|
||||
@@ -242,11 +244,11 @@ class PatternGenerator:
|
||||
self.__memory_manager.set_memory_layout([block_sizes])
|
||||
self.__memory_manager.set_memory_block_index(MemoryManager.MemoryOwner.MO_PatternGenerator)
|
||||
|
||||
self.__io.set(TSI_PG_CUSTOM_PATTERN_MEMORY_BLOCK_INDEX, 0)
|
||||
self.__io.set(TSI_PG_CUSTOM_PATTERN_WIDTH, video_mode.timing.hactive)
|
||||
self.__io.set(TSI_PG_CUSTOM_PATTERN_HEIGHT, video_mode.timing.vactive)
|
||||
self.__io.set(TSI_PG_CUSTOM_PATTERN_PIXEL_FORMAT, pg_pixel_format_from_vm(video_mode))
|
||||
self.__io.set(TSI_PG_CUSTOM_PATTERN_DATA, data, c_uint8, data_count=len(data))
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_MEMORY_BLOCK_INDEX, 0)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_WIDTH, video_mode.timing.hactive)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_HEIGHT, video_mode.timing.vactive)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_PIXEL_FORMAT, pg_pixel_format_from_vm(video_mode))
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_DATA, data, c_uint8, data_count=len(data))
|
||||
|
||||
def __load_dsc_image(self, video_mode: VideoMode, content_data: Union[str, bytearray, VideoFrameDSC]):
|
||||
if isinstance(content_data, str):
|
||||
@@ -259,8 +261,8 @@ class PatternGenerator:
|
||||
block_sizes = len(data)
|
||||
self.__memory_manager.set_memory_layout([block_sizes])
|
||||
self.__memory_manager.set_memory_block_index(MemoryManager.MemoryOwner.MO_PatternGenerator)
|
||||
self.__io.set(TSI_PG_CUSTOM_PATTERN_MEMORY_BLOCK_INDEX, 0)
|
||||
self.__io.set(TSI_PG_CUSTOM_PATTERN_DATA, data, c_uint8, data_count=len(data))
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_MEMORY_BLOCK_INDEX, 0)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_DATA, data, c_uint8, data_count=len(data))
|
||||
|
||||
@staticmethod
|
||||
def __calculate_frame_size(width: int, height: int) -> int:
|
||||
@@ -331,7 +333,7 @@ class PatternGenerator:
|
||||
raise TypeError(f"Incorrect input value: {self._pattern}.\n"
|
||||
f"If you want to select pattern, see following list of available patterns:\n"
|
||||
f"{self.__available_patterns}")
|
||||
self.__io.set(TSI_PG_PREDEF_PATTERN_SELECT, self._pattern_id.value)
|
||||
self.__io.set(ci.TSI_PG_PREDEF_PATTERN_SELECT, self._pattern_id.value)
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -362,17 +364,17 @@ class PatternGenerator:
|
||||
self.__caps.max_h_total >= self._vm.timing.htotal and \
|
||||
self.__caps.max_v_total >= self._vm.timing.vtotal and \
|
||||
self.__caps.max_frame >= int(self._vm.timing.frame_rate / 1000):
|
||||
self.__io.set(TSI_PG_CUSTOM_TIMING_FLAGS, pg_timingflags_from_vm(self._vm))
|
||||
self.__io.set(TSI_PG_CUSTOM_TIMING_HTOTAL, self._vm.timing.htotal, c_uint)
|
||||
self.__io.set(TSI_PG_CUSTOM_TIMING_VTOTAL, self._vm.timing.vtotal, c_uint)
|
||||
self.__io.set(TSI_PG_CUSTOM_TIMING_HACTIVE, self._vm.timing.hactive, c_uint)
|
||||
self.__io.set(TSI_PG_CUSTOM_TIMING_VACTIVE, self._vm.timing.vactive, c_uint)
|
||||
self.__io.set(TSI_PG_CUSTOM_TIMING_HSTART, self._vm.timing.hstart, c_uint)
|
||||
self.__io.set(TSI_PG_CUSTOM_TIMING_VSTART, self._vm.timing.vstart, c_uint)
|
||||
self.__io.set(TSI_PG_CUSTOM_TIMING_HSYNCW, abs(self._vm.timing.hswidth), c_uint)
|
||||
self.__io.set(TSI_PG_CUSTOM_TIMING_VSYNCW, abs(self._vm.timing.vswidth), c_uint)
|
||||
self.__io.set(TSI_PG_CUSTOM_TIMING_FIELD_RATE, self._vm.timing.frame_rate, c_uint)
|
||||
self.__io.set(TSI_PG_CUSTOM_TIMING_STANDARD, self._vm.timing.standard.value, c_uint)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_FLAGS, pg_timingflags_from_vm(self._vm))
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_HTOTAL, self._vm.timing.htotal, c_uint)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_VTOTAL, self._vm.timing.vtotal, c_uint)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_HACTIVE, self._vm.timing.hactive, c_uint)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_VACTIVE, self._vm.timing.vactive, c_uint)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_HSTART, self._vm.timing.hstart, c_uint)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_VSTART, self._vm.timing.vstart, c_uint)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_HSYNCW, abs(self._vm.timing.hswidth), c_uint)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_VSYNCW, abs(self._vm.timing.vswidth), c_uint)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_FIELD_RATE, self._vm.timing.frame_rate, c_uint)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_TIMING_STANDARD, self._vm.timing.standard.value, c_uint)
|
||||
return True
|
||||
else:
|
||||
raise ValueError(f"Incorrect Video Mode (incorrect resolution and(or) frame rate")
|
||||
@@ -384,29 +386,40 @@ class PatternGenerator:
|
||||
See available `PGPatternParams` types: `SolidColorParams`, `WhiteVStripsParams`, `GradientStripsParams`,
|
||||
`MotionParams`,`SquareWindowParams` (see in pg pattern params).
|
||||
|
||||
These parameters can be applied without calling apply() method, if active pattern matches pattern params.
|
||||
|
||||
Args:
|
||||
pattern_params (PGPatternParams)
|
||||
"""
|
||||
self._pattern_params = pattern_params
|
||||
self._setup_pattern_params()
|
||||
|
||||
def _setup_pattern_params(self):
|
||||
if self._pattern_params is not None and isinstance(self._pattern, VideoPattern):
|
||||
if self._MAP_PATTERN_PARAMETER.get(PGPatternID(self._pattern_id.value)) is not None:
|
||||
if isinstance(self._pattern_params,
|
||||
self._MAP_PATTERN_PARAMETER.get(PGPatternID(self._pattern_id.value))):
|
||||
self.__io.set(TSI_PG_PREDEF_PATTERN_PARAMS, get_pattern_params_value(self._pattern_params,
|
||||
self._vm.color_info.bpc),
|
||||
data_count=len(get_pattern_params_value(self._pattern_params)))
|
||||
return True
|
||||
else:
|
||||
if self._pattern_params is None or not isinstance(self._pattern, VideoPattern):
|
||||
return False
|
||||
|
||||
if self._MAP_PATTERN_PARAMETER.get(self._pattern_id) is None:
|
||||
return False
|
||||
|
||||
if not isinstance(self._pattern_params, self._MAP_PATTERN_PARAMETER.get(self._pattern_id)):
|
||||
warnings.warn(f"Incorrect pattern name {self._pattern} and "
|
||||
f"pattern params {type(self._pattern_params)}.\n"
|
||||
f"For {self._pattern} you need to use "
|
||||
f"{self._MAP_PATTERN_PARAMETER.get(self._pattern_id)}")
|
||||
return False
|
||||
|
||||
solid_color_shifter = 16 - self._vm.color_info.bpc if self._vm is not None else 0
|
||||
params = get_pattern_params_value(self._pattern_params, solid_color_shifter)
|
||||
|
||||
self._become_active()
|
||||
|
||||
self.__io.set(ci.TSI_PG_PREDEF_PATTERN_PARAM_1, params[0])
|
||||
self.__io.set(ci.TSI_PG_PREDEF_PATTERN_PARAM_2, params[1])
|
||||
|
||||
return True
|
||||
|
||||
def __get_custom_timing_flags_to_video_mode(self) -> (ColorInfo, bool, bool):
|
||||
timing_flags = self.__io.get(TSI_PG_CUSTOM_TIMING_FLAGS, CustomTimingFlags)[1]
|
||||
timing_flags = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_FLAGS, CustomTimingFlags)[1]
|
||||
|
||||
vm_color_format = pg_colorformat_to_ci_colorformat(PGColorInfo(timing_flags.color_space))
|
||||
|
||||
@@ -440,28 +453,28 @@ class PatternGenerator:
|
||||
|
||||
video_mode = VideoMode()
|
||||
|
||||
video_mode.timing.hactive = self.__io.get(TSI_PG_CUSTOM_TIMING_HACTIVE, c_uint32)[1]
|
||||
video_mode.timing.vactive = self.__io.get(TSI_PG_CUSTOM_TIMING_VACTIVE, c_uint32)[1]
|
||||
video_mode.timing.htotal = self.__io.get(TSI_PG_CUSTOM_TIMING_HTOTAL, c_uint32)[1]
|
||||
video_mode.timing.vtotal = self.__io.get(TSI_PG_CUSTOM_TIMING_VTOTAL, c_uint32)[1]
|
||||
video_mode.timing.hstart = self.__io.get(TSI_PG_CUSTOM_TIMING_HSTART, c_uint32)[1]
|
||||
video_mode.timing.vstart = self.__io.get(TSI_PG_CUSTOM_TIMING_VSTART, c_uint32)[1]
|
||||
video_mode.timing.hactive = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_HACTIVE, c_uint32)[1]
|
||||
video_mode.timing.vactive = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_VACTIVE, c_uint32)[1]
|
||||
video_mode.timing.htotal = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_HTOTAL, c_uint32)[1]
|
||||
video_mode.timing.vtotal = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_VTOTAL, c_uint32)[1]
|
||||
video_mode.timing.hstart = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_HSTART, c_uint32)[1]
|
||||
video_mode.timing.vstart = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_VSTART, c_uint32)[1]
|
||||
|
||||
video_mode.color_info, h_sync_polarity, v_sync_polarity = self.__get_custom_timing_flags_to_video_mode()
|
||||
|
||||
video_mode.timing.hswidth = self.__io.get(TSI_PG_CUSTOM_TIMING_HSYNCW, c_uint32)[1] * (
|
||||
video_mode.timing.hswidth = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_HSYNCW, c_uint32)[1] * (
|
||||
-1 if h_sync_polarity else 1)
|
||||
video_mode.timing.vswidth = self.__io.get(TSI_PG_CUSTOM_TIMING_VSYNCW, c_uint32)[1] * (
|
||||
video_mode.timing.vswidth = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_VSYNCW, c_uint32)[1] * (
|
||||
-1 if v_sync_polarity else 1)
|
||||
video_mode.timing.frame_rate = self.__io.get(TSI_PG_CUSTOM_TIMING_FIELD_RATE, c_uint32)[1]
|
||||
video_mode.timing.frame_rate = self.__io.get(ci.TSI_PG_CUSTOM_TIMING_FIELD_RATE, c_uint32)[1]
|
||||
|
||||
return video_mode
|
||||
|
||||
def _become_active(self):
|
||||
self.__io.set(TSI_PG_STREAM_SELECT, self.__stream)
|
||||
self.__io.set(ci.TSI_PG_STREAM_SELECT, self.__stream)
|
||||
|
||||
def __read_pg_settings(self):
|
||||
self.__io.set(TSI_PG_COMMAND_W, 2)
|
||||
self.__io.set(ci.TSI_PG_COMMAND_W, 2)
|
||||
|
||||
def apply(self) -> bool:
|
||||
"""
|
||||
@@ -471,7 +484,7 @@ class PatternGenerator:
|
||||
Returns:
|
||||
object of bool type - settings were set successfully or not
|
||||
"""
|
||||
self.__io.set(TSI_PG_COMMAND_W, 3)
|
||||
self.__io.set(ci.TSI_PG_COMMAND_W, 3)
|
||||
|
||||
def is_apply_pg_success(pg: PatternGenerator):
|
||||
return pg.status().error == PGStatus.PGError.OK
|
||||
@@ -487,7 +500,7 @@ class PatternGenerator:
|
||||
object of PGStatus type.
|
||||
"""
|
||||
self._become_active()
|
||||
return PGStatus(self.__io.get(TSI_PG_STATUS_R, c_uint32)[1])
|
||||
return PGStatus(self.__io.get(ci.TSI_PG_STATUS_R, c_uint32)[1])
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
@@ -631,7 +644,7 @@ class DpPatternGenerator(PatternGenerator):
|
||||
self.__as_config = None
|
||||
return False
|
||||
|
||||
self.__io.set(TSI_PG_ADAPTIVE_SYNC_CTRL,
|
||||
self.__io.set(p_ci.TSI_PG_ADAPTIVE_SYNC_CTRL,
|
||||
get_as_params_value(self.__as_config),
|
||||
data_count=len(get_as_params_value(self.__as_config)))
|
||||
return True
|
||||
@@ -659,8 +672,8 @@ class DpPatternGenerator(PatternGenerator):
|
||||
return False
|
||||
value = 1
|
||||
value |= (1 << 31)
|
||||
self.__io.set(TSI_PG_CUSTOM_PATTERN_SCROLLING_CONTROL, value, c_uint32)
|
||||
self.__io.set(TSI_PG_CUSTOM_PATTERN_SCROLLING_CONFIG, get_pattern_params_value(self.__scrolling_params),
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_SCROLLING_CONTROL, value, c_uint32)
|
||||
self.__io.set(ci.TSI_PG_CUSTOM_PATTERN_SCROLLING_CONFIG, get_pattern_params_value(self.__scrolling_params),
|
||||
data_count=len(get_pattern_params_value(self.__scrolling_params)))
|
||||
return True
|
||||
return False
|
||||
@@ -675,9 +688,9 @@ class DpPatternGenerator(PatternGenerator):
|
||||
"""
|
||||
self._become_active()
|
||||
|
||||
res = self.__io.get(TSI_PG_ADAPTIVE_SYNC_STS, c_uint32)
|
||||
res = self.__io.get(p_ci.TSI_PG_ADAPTIVE_SYNC_STS, c_uint32)
|
||||
|
||||
if res[0] < TSI_SUCCESS:
|
||||
if res[0] < ci.TSI_SUCCESS:
|
||||
return False
|
||||
|
||||
return res[1] & 1 != 0
|
||||
@@ -894,5 +907,5 @@ class DpMstPatternGenerator:
|
||||
return self.__pg_list[0].panel_replay()
|
||||
|
||||
def __read_max_stream_count(self) -> int:
|
||||
result = self.__io.get(TSI_PG_MAX_STREAM_COUNT_R, c_uint32)
|
||||
result = self.__io.get(ci.TSI_PG_MAX_STREAM_COUNT_R, c_uint32)
|
||||
return result[1]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user