1.1.0版本

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

View File

@@ -0,0 +1,6 @@
from .pdo import Pdo
from .pdc_types import ExternalResistance, InternalResistance, ContractTypePriority, DifferentialPair, \
CableControlOrientation, DRPTryMode, USB3Mode, PDMode, PdcDeviceRole, FrSwapCurrent, PowerRole, CCPullUp
from .pdo_types import PdoSide, PeakCurrent, PdoTypeEnum, FixedPdoSink, FixedPdoSource, BatteryPdo, VariablePdo
from .pdc_dp_alt_mode import PinAssignment
from .pdc_dpam_types import PinAssignmentModes, DPAMVersion

View File

@@ -0,0 +1,111 @@
from .pdc_io import PDCPortIO
class BusElectricalStatus:
"""
Class `BusElectricalStatus` contains information about current BUU Electrical status.
- Get VBus voltage `vbus_voltage`, type `int`.
- Get VBus current `vbus_current`, type `int`.
- Get CC1 voltage `cc1_voltage`, type `int`.
- Get CC2 voltage `cc2_voltage`, type `int`.
- Get VCONN voltage `vconn_voltage`, type `int`.
- Get VCONN current `vconn_current`, type `int`.
- Get SBU-1 voltage `sbu_1_voltage`, type `int`.
- Get SBU-2 voltage `sbu_2_voltage`, type `int`.
"""
def __init__(self, pdc_io: PDCPortIO):
self.__io = pdc_io
@property
def vbus_voltage(self) -> int:
"""
Returns current VBus voltage.
Returns:
object of `int` type
"""
return self.__io.read_adc_vbus_status()[0]
@property
def vbus_current(self) -> int:
"""
Returns current VBus current.
Returns:
object of `int` type
"""
return self.__io.read_adc_vbus_status()[1]
@property
def cc1_voltage(self) -> int:
"""
Returns current CC1 voltage.
Returns:
object of `int` type
"""
return self.__io.read_adc_vbus_status()[2]
@property
def cc2_voltage(self) -> int:
"""
Returns current CC2 voltage.
Returns:
object of `int` type
"""
return self.__io.read_adc_vbus_status()[3]
@property
def vconn_voltage(self) -> int:
"""
Returns current VCONN voltage.
Returns:
object of `int` type
"""
return self.__io.read_adc_vbus_status()[4]
@property
def vconn_current(self) -> int:
"""
Returns current VCONN current.
Returns:
object of `int` type
"""
return self.__io.read_adc_vbus_status()[5]
@property
def sbu_1_voltage(self) -> int:
"""
Returns current SBU-1 voltage.
Returns:
object of `int` type
"""
return self.__io.read_adc_vbus_status()[6]
@property
def sbu_2_voltage(self) -> int:
"""
Returns current SBU-2 voltage.
Returns:
object of `int` type
"""
return self.__io.read_adc_vbus_status()[7]
def __str__(self) -> str:
electrical_status = self.__io.read_adc_vbus_status()
return f"Bus Electrical Status\n" \
f"VBus current: {electrical_status[0]}\n" \
f"VBus voltage: {electrical_status[1]}\n" \
f"CC1 voltage: {electrical_status[2]}\n" \
f"CC2 voltage: {electrical_status[3]}\n" \
f"VCONN voltage: {electrical_status[4]}\n" \
f"VCONN current: {electrical_status[5]}\n" \
f"SBU-1 voltage: {electrical_status[6]}\n" \
f"SBU-2 voltage: {electrical_status[7]}\n"

View File

@@ -0,0 +1,340 @@
from .pdc_io import PDCPortIO, PDCControlCommand, HWControlCommand
from .pdc_types import PdcDeviceRole, CCPullUp, DRPTryMode, USB3Mode, PowerRole
from .pdc_utils import support_or_not
class PcdCapsStatus:
"""
Class `PcdCapsStatus` contains information about PDC capabilities.
- Get initial device role `initial_role`, type `PdcDeviceRole`.
- Get data device role `data_role`, type `PdcDeviceRole`.
- Get power device role `power_role`, type `PowerRole`.
- Get Cable Control Pull Up `cc_pull_up`, type `CCPullUp`.
- Get current behavior, DRP try mode `behavior`, type `DRPTryMode`.
- Get state of PR Swap `pr_swap`, type `bool`.
- Get state of DR Swap `dr_swap`, type `bool`.
- Get state of FR Swap `fr_swap`, type `bool`.
- Get state of VCONN Swap `vconn_swap`, type `bool`.
- Get state of Debug accessory `debug_accessory`, type `bool`.
- Get state of Audio accessory `audio_accessory`, type `bool`.
"""
def __init__(self, pdc_io: PDCPortIO):
self.__io = pdc_io
def initial_role(self) -> PdcDeviceRole:
"""
Returns current initial role.
Returns:
object of `PdcDeviceRole` type
"""
return PdcDeviceRole(self.__io.read_pdc_state().dev_role)
def data_role(self) -> PdcDeviceRole:
"""
Returns current data role.
Returns:
object of `PdcDeviceRole` type
"""
return PdcDeviceRole(self.__io.read_pdc_status().data_role)
def power_role(self) -> PowerRole:
"""
Returns current power role.
Returns:
object of `PowerRole` type
"""
return PowerRole(self.__io.read_pdc_status().power_role)
def cc_pull_up(self) -> CCPullUp:
"""
Returns current cable control pull up.
Returns:
object of `CCPullUp` type
"""
return CCPullUp(self.__io.read_pdc_state().cc_pull_up)
def behavior(self) -> DRPTryMode:
"""
Returns current behavior of DPR mode.
Returns:
object of `DRPTryMode` type
"""
return DRPTryMode(self.__io.read_pdc_state().drp_try_mode)
def pr_swap(self) -> bool:
"""
Returns current state of PR Swap.
Returns:
object of `bool` type
"""
return bool(self.__io.read_pdc_state().pr_swap_en)
def dr_swap(self) -> bool:
"""
Returns current state of DR Swap.
Returns:
object of `bool` type
"""
return bool(self.__io.read_pdc_state().dr_swap_en)
def fr_swap(self) -> bool:
"""
Returns current state of FR Swap.
Returns:
object of `bool` type
"""
return bool(self.__io.read_pdc_state().fr_swap_en)
def vconn_swap(self) -> bool:
"""
Returns current state of VCONN Swap.
Returns:
object of `bool` type
"""
return bool(self.__io.read_pdc_state().vconn_swap_en)
def debug_accessory(self) -> bool:
"""
Returns current state of Debug accessory.
Returns:
object of `bool` type
"""
return bool(self.__io.read_pdc_state().dbg_accessory)
def audio_accessory(self) -> bool:
"""
Returns current state of Audio accessory.
Returns:
object of `bool` type
"""
return bool(self.__io.read_pdc_state().aud_accessory)
def __str__(self):
status = self.__io.read_pdc_state()
return f"PDC Capabilities:\n" \
f"Initial role: {PdcDeviceRole(status.dev_role).name}\n" \
f"Power role: {self.power_role().name}\n" \
f"Data role: {self.data_role().name}\n" \
f"CC Pull-Up: {CCPullUp(status.cc_pull_up).name}\n" \
f"Try behavior: {DRPTryMode(status.drp_try_mode).name}\n" \
f"PR Swap enabled: {support_or_not(status.pr_swap_en)}\n" \
f"DR Swap enabled: {support_or_not(status.dr_swap_en)}\n" \
f"FR Swap enabled: {support_or_not(status.fr_swap_en)}\n" \
f"VCONN Swap enabled: {support_or_not(status.vconn_swap_en)}\n" \
f"Debug accessory enabled: {support_or_not(status.dbg_accessory)}\n" \
f"Audio accessory enabled: {support_or_not(status.aud_accessory)}\n"
class PcdCapsStatus340(PcdCapsStatus):
"""
Class `PcdCapsStatus340` inherited of class`PcdCapsStatus` allows working with PDC.
Class `PcdCapsStatus340` has all the `PcdCapsStatus` functionality.
- Get state of USB 2.0 mode `usb20_mode`, type `bool`.
- Get state of UCd 3.0 mode `usb30_mode`, type `USB3Mode`.
"""
def __init__(self, pdc_io: PDCPortIO):
super().__init__(pdc_io)
def usb20_mode(self) -> bool:
"""
Returns current state of USB 2.0 mode.
Returns:
object of `bool` type
"""
return bool(self.__io.read_pdc_state().usb2_enabled)
def usb30_mode(self) -> USB3Mode:
"""
Returns current state of USB 3.0 mode.
Returns:
object of `USB3Mode` type
"""
return USB3Mode(self.__io.read_pdc_state().usb30_mode)
def __str__(self):
status = self.__io.read_pdc_state()
return f"PDC Capabilities:" \
f"Initial role: {PdcDeviceRole(status.dev_role).name}\n" \
f"CC Pull-Up: {CCPullUp(status.cc_pull_up).name}\n" \
f"Try behavior: {DRPTryMode(status.drp_try_mode).name}\n" \
f"USB 2 enabled: {support_or_not(status.usb2_enabled)}\n" \
f"USB 3: {USB3Mode(status.usb30_mode).name}\n" \
f"PR Swap enabled: {support_or_not(status.pr_swap_en)}\n" \
f"DR Swap enabled: {support_or_not(status.dr_swap_en)}\n" \
f"FR Swap enabled: {support_or_not(status.fr_swap_en)}\n" \
f"VCONN Swap enabled: {support_or_not(status.vconn_swap_en)}\n" \
f"Debug accessory enabled: {support_or_not(status.dbg_accessory)}\n" \
f"Audio accessory enabled: {support_or_not(status.aud_accessory)}\n"
class PdcCapabilities:
"""
Class `PdcCapabilities` allows controlling PDC capabilities.
- Set device initial role `set_initial_role`.
- Enable/Disable PR Swap `enable_pr_swap`.
- Enable/Disable DR Swap `enable_dr_swap`.
- Enable/Disable FR Swap `enable_fr_swap`.
- Enable/Disable VCONN Swap `enable_vconn_swap`.
- Set CC Pull Up `cc_pull_up`.
- Set DPR try mode behavior `try_behavior`.
- Enable/Disable Debug accessory `enable_debug_accessory`.
- Enable/Disable Audio accessory `enable_audio_accessory`.
"""
__device_role = {PdcDeviceRole.DFP: PDCControlCommand.SetDataRoleDFP,
PdcDeviceRole.UFP: PDCControlCommand.SetDataRoleUFP,
PdcDeviceRole.DRP: PDCControlCommand.SetDataRoleDRP}
__cc_pull_up = {CCPullUp.Current_05_09A: PDCControlCommand.PullCCLineToDefault,
CCPullUp.Current_1_5A: PDCControlCommand.PullCCLineTo1_5A,
CCPullUp.Current_3A: PDCControlCommand.PullCCLineTo3_0A}
__behavior = {DRPTryMode.PureDRP: PDCControlCommand.SetDataRoleDRP,
DRPTryMode.DRP_try_SNK: PDCControlCommand.SetDataRoleDRP_SNK_Support,
DRPTryMode.DRP_try_SRC: PDCControlCommand.SetDataRoleDRP_SRC_Support}
def __init__(self, pdc_io: PDCPortIO):
self.__io = pdc_io
self.__status = PcdCapsStatus(self.__io)
@property
def status(self) -> PcdCapsStatus:
"""
Returns current PDC Capabilities status.
Returns:
object of `PcdCapsStatus` type
"""
return self.__status
def set_initial_role(self, role: PdcDeviceRole):
"""
Set device initial role.
Args:
role (`PdcDeviceRole`)
"""
self.__io.write_pdc_command(self.__device_role.get(role))
def enable_pr_swap(self, enable: bool):
"""
Enable/Disable PR Swap.
Args:
enable (`bool`)
"""
self.__io.write_pdc_command(PDCControlCommand.EnablePRSwap if enable else PDCControlCommand.DisablePRSwap)
def enable_dr_swap(self, enable: bool):
"""
Enable/Disable DR Swap.
Args:
enable (`bool`)
"""
self.__io.write_pdc_command(PDCControlCommand.EnableDRSwap if enable else PDCControlCommand.DisableDRSwap)
def enable_fr_swap(self, enable: bool):
"""
Enable/Disable FR Swap.
Args:
enable (`bool`)
"""
self.__io.write_pdc_command(PDCControlCommand.EnableFRSwap if enable else PDCControlCommand.DisableFRSwap)
def enable_vconn_swap(self, enable: bool):
"""
Enable/Disable VCONN Swap.
Args:
enable (`bool`)
"""
self.__io.write_pdc_command(PDCControlCommand.EnableVconnSwap if enable else PDCControlCommand.DisableVconnSwap)
def cc_pull_up(self, cc_pull_up: CCPullUp):
"""
Set Cable Control Pull Up.
Args:
cc_pull_up (`CCPullUp`)
"""
self.__io.write_pdc_command(self.__cc_pull_up.get(cc_pull_up))
def try_behavior(self, behavior: DRPTryMode):
"""
Set DRP try mode behavior.
Args:
behavior (`DRPTryMode`)
"""
self.__io.write_pdc_command(self.__behavior.get(behavior))
def enable_debug_accessory(self, enable: bool):
"""
Enable/Disable Debug Accessory.
Args:
enable (`bool`)
"""
self.__io.write_pdc_command(PDCControlCommand.EnableDebugAccessorySupport if enable else
PDCControlCommand.EnableDebugAccessorySupport)
def enable_audio_accessory(self, enable: bool):
"""
Enable/Disable Audio Accessory.
Args:
enable (`bool`)
"""
self.__io.write_pdc_command(PDCControlCommand.EnableAudioAccessorySupport if enable else
PDCControlCommand.DisableAudioAccessorySupport)
class PdcCapabilities340(PdcCapabilities):
"""
Class `PdcCapabilities340` inherited of class`PdcCapabilities` allows working with PDC.
Class `PdcCapabilities340` has all the `PdcCapabilities` functionality.
- Enable/Disable USB 2.0 bypass `usb_2_bypass_function`.
- Enable/Disable USB 3.0 bypass `usb_3_bypass_function`.
"""
def __init__(self, pdc_io: PDCPortIO):
super().__init__(pdc_io)
def usb_2_bypass_function(self, enable: bool):
"""
Enable/Disable USB 2.0 bypass.
Args:
enable (`bool`)
"""
self.__io.write_hw_command(HWControlCommand.Enable20PHY if enable else HWControlCommand.Disable20PHY)
def usb_3_bypass_function(self, enable: bool):
"""
Enable/Disable USB 3.0 bypass.
Args:
enable (`bool`)
"""
self.__io.write_hw_command(HWControlCommand.Enable30PHY if enable else HWControlCommand.Disable30PHY)

View File

@@ -0,0 +1,253 @@
import math
import warnings
from .pdc_io import PDCPortIO, PDCControlCommand
from .pdc_utils import support_or_not
from .pdc_types import FrSwapCurrent, ContractTypePriority, InternalResistance, ExternalResistance
from typing import Union
class PowerContractControlBase:
"""
Class `PowerContractControlBase` allows setting and getting field related with power contract.
- Set and get Give Back flag `give_back_flag`, type `bool`.
- Set and get No USB suspend `no_usb_suspend`, type `bool`.
- Set and get PDO type priority `pdo_type_priority`, type `ContractTypePriority`.
- Set and get Maximum operation current `max_operation_current`, type `int`.
- Set FW Swap required current `fw_swap_required_current`, type `FrSwapCurrent`.
"""
__fr_swap_current = {FrSwapCurrent.Disable: PDCControlCommand.SetFRSwapNoSupported,
FrSwapCurrent.EnableDefaultUSBPower: PDCControlCommand.SetFRSwapUSBPower,
FrSwapCurrent.Enable_1_5A_5V: PDCControlCommand.SetFRSwap1_5A_5V,
FrSwapCurrent.Enable_3A_5V: PDCControlCommand.SetFRSwap3A_5V}
def __init__(self, pdc_io: PDCPortIO):
self._io = pdc_io
self.__caps = self._io.read_pdc_caps()
self.__pdo_count = self._io.read_hw_caps().pdo_count
@property
def give_back_flag(self) -> bool:
"""
Returns state of Give back flag.
Returns:
object of `bool` type
"""
return self._io.read_pdc_contract_control().give_back_flag != 0
@give_back_flag.setter
def give_back_flag(self, enable: bool):
data = self._io.read_pdc_contract_control()
data.give_back_flag = int(enable)
self._io.write_pdc_contract_control(data)
@property
def no_usb_suspend(self) -> bool:
"""
Returns state of No USB suspend flag.
Returns:
object of `bool` type
"""
return self._io.read_pdc_contract_control().no_usb_suspend != 0
@no_usb_suspend.setter
def no_usb_suspend(self, enable: bool):
data = self._io.read_pdc_contract_control()
data.no_usb_suspend = int(enable)
self._io.write_pdc_contract_control(data)
def fw_swap_required_current(self, fr_swap_current: FrSwapCurrent):
"""
Set FW Swap required current.
Args:
fr_swap_current (`FrSwapCurrent`)
"""
if self.__caps.fr_swap:
self._io.write_pdc_command(self.__fr_swap_current.get(fr_swap_current))
else:
warnings.warn("Do not support Fast Role Swap.")
@property
def pdo_type_priority(self) -> ContractTypePriority:
"""
Returns current PDO Type priority.
Returns:
object of `ContractTypePriority` type
"""
return ContractTypePriority(self._io.read_pdc_contract_control().type_priority)
@pdo_type_priority.setter
def pdo_type_priority(self, type_priority: ContractTypePriority):
data = self._io.read_pdc_contract_control()
data.type_priority = type_priority.value
self._io.write_pdc_contract_control(data)
@property
def max_operation_current(self) -> int:
"""
Returns current value of maximum operation current.
Returns:
object of `int` type
"""
data = self._io.read_contract_data()
return data[3] & 0x03FF
@max_operation_current.setter
def max_operation_current(self, current: int):
if current < 0:
raise ValueError(f"Incorrect current {current}. Must be more than 0.")
data = self._io.read_contract_data()
data[3] = (data[3] & 0xFFFFFC00) | (current & 0x03FF)
self._io.write_contract_data(data)
def established(self) -> bool:
"""
Returns state of power contract (established or not).
Returns:
object of `bool` type
"""
return self._io.read_pdc_status().pwr_contract == 1
def __str__(self) -> str:
return f"Power Contract Control\n" \
f"Give Back flag active: {support_or_not(self.give_back_flag)}\n" \
f"No USB suspend flag active: {support_or_not(self.no_usb_suspend)}\n" \
f"Contract type priority: {self.pdo_type_priority.name}\n" \
f"Max operation current: {self.max_operation_current} mA"
class PowerContractControl340(PowerContractControlBase):
"""
Class `PowerContractControl340` inherited from class `PowerContractControlBase`.
Class `PowerContractControl340` allows setting and getting internal and external resistance,
index of power contract.
Also has all the `PowerContractControlBase` functionality.
- Set and get flag Selecting power contract by index `selecting_by_index`, type `bool`.
- Set and get index of power contract `index_of_power_contract`, type `int`.
- Set and get internal resistance `internal_resistance`, type `int` or `InternalResistance`.
- Set and get external resistance `external_resistance`, type `int` or `ExternalResistance`.
"""
__internal_resistance = {10000: InternalResistance.Resistance_10_Ohm,
5500: InternalResistance.Resistance_5_5_Ohm,
3550: InternalResistance.Resistance_3_55_Ohm,
3500: InternalResistance.Resistance_3_5_Ohm,
2600: InternalResistance.Resistance_2_6_Ohm,
2140: InternalResistance.Resistance_2_14_Ohm,
1760: InternalResistance.Resistance_1_76_Ohm}
__external_resistance = {13900: ExternalResistance.Resistance_13_9_Ohm,
10600: ExternalResistance.Resistance_10_6_Ohm,
9100: ExternalResistance.Resistance_9_1_Ohm,
7600: ExternalResistance.Resistance_7_6_Ohm,
6600: ExternalResistance.Resistance_6_6_Ohm,
5600: ExternalResistance.Resistance_5_6_Ohm,
4600: ExternalResistance.Resistance_4_6_Ohm,
3600: ExternalResistance.Resistance_3_6_Ohm,
1800: ExternalResistance.Resistance_1_8_Ohm}
def __init__(self, pdc_io: PDCPortIO):
super().__init__(pdc_io)
@property
def selecting_by_index(self) -> bool:
"""
Returns state of Selecting by index flag.
Returns:
object of `bool` type
"""
return self._io.read_pdc_contract_control().manual != 0
@selecting_by_index.setter
def selecting_by_index(self, enable: bool):
data = self._io.read_pdc_contract_control()
data.manual = enable
self._io.write_pdc_contract_control(data)
@property
def index_of_power_contract(self) -> int:
"""
Returns index of current power contract.
Returns:
object of `int` type
"""
if not self._io.read_pdc_contract_control().manual:
return self._io.read_power_contract_select()
else:
warnings.warn("Negotiate power contract automatically disabled. "
"Please, enable (use function 'enable_selecting_by_index'.)")
return -1
@index_of_power_contract.setter
def index_of_power_contract(self, index: int):
if not self._io.read_pdc_contract_control().manual:
if index < 0:
raise ValueError(f"Incorrect index {index} of power contract. "
f"Must be between 0 and {self.__pdo_count}.")
self._io.write_power_contract_select(index)
else:
warnings.warn("Negotiate power contract automatically disabled. "
"Please, enable (use function 'enable_selecting_by_index'.)")
@property
def internal_resistance(self) -> Union[InternalResistance, int]:
"""
Returns internal resistance.
Returns:
object of `int` or `InternalResistance` type
"""
res = self._io.read_internal_resistance()
for key in self.__internal_resistance.keys():
if math.fabs(res - key) < 50:
return self.__internal_resistance.get(key)
return res
@internal_resistance.setter
def internal_resistance(self, resistance: InternalResistance):
self._io.write_resistance(resistance.value)
@property
def external_resistance(self) -> Union[ExternalResistance, int]:
"""
Returns external resistance.
Returns:
object of `int` or `ExternalResistance` type
"""
if self._io.read_hw_status().ext_power:
res = self._io.read_external_resistance()
for key in self.__external_resistance.keys():
if math.fabs(res - key) < 50:
return self.__external_resistance.get(key)
return res
else:
return ExternalResistance.Disable
@external_resistance.setter
def external_resistance(self, resistance: ExternalResistance):
if self._io.read_hw_status().ext_power:
self._io.write_resistance(resistance.value)
else:
warnings.warn("Does not enabled external power. Please, attach external power device.")
def __str__(self) -> str:
return f"Power Contract Control\n" \
f"Give Back flag active: {support_or_not(self.give_back_flag)}\n" \
f"No USB suspend flag active: {support_or_not(self.no_usb_suspend)}\n" \
f"Contract type priority: {self.pdo_type_priority.name}\n" \
f"Max operation current: {self.max_operation_current} mA\n" \
f"Internal resistance: {self.internal_resistance} Om\n" \
f"External resistance: {self.external_resistance} Om\n" \
f"Selecting power contract by index flag active: {support_or_not(self.selecting_by_index)}\n" \
f"Power contract index: {self.index_of_power_contract if self.selecting_by_index else '0'}"

View File

@@ -0,0 +1,268 @@
import warnings
from typing import Optional
from UniTAP.utils import function_scheduler
from .pdc_io import PDCPortIO, PDCControlCommand, HWControlCommand
from .pdc_types import CableControlOrientation, DifferentialPair
class PdcControlsBase:
"""
Class `PdcControlsBase` allows controlling some PDC commands:
- Send PR Swap `send_pr_swap`.
- Send DR Swap `send_dr_swap`.
- Send FR Swap `send_fr_swap`.
- Send VCONN Swap `send_vconn_swap`.
- Change cable control orientation `orientation`.
- Attach/DeAttach `attach`.
- Enable/Disable auto negotiate power contract `enable_auto_negotiate_power_contract`.
- Enable/Disable communication capable as PD Sink `communication_capable_as_pd_sink`.
- Enable/Disable communication capable as PD Source `communication_capable_as_pd_source`.
"""
def __init__(self, pdc_io: PDCPortIO):
self.__io = pdc_io
self.__caps = self.__io.read_pdc_caps()
def send_pr_swap(self):
"""
Send Power Role swap. It will be necessary to manually check that the changes have been made.
"""
self.__io.write_pdc_command(PDCControlCommand.TogglePowerRole)
def send_dr_swap(self):
"""
Send Dual Role swap. It will be necessary to manually check that the changes have been made.
"""
self.__io.write_pdc_command(PDCControlCommand.ToggleDataRole)
def send_fr_swap(self):
"""
Send Fast Role swap. It will be necessary to manually check that the changes have been made.
"""
if self.__caps.fr_swap:
self.__io.write_pdc_command(PDCControlCommand.FastRoleSwap)
else:
warnings.warn("Do not support Fast Role Swap.")
def send_vconn_swap(self):
"""
Send VCONN Role swap. It will be necessary to manually check that the changes have been made.
"""
self.__io.write_pdc_command(PDCControlCommand.SwapVconn)
@property
def orientation(self) -> Optional[CableControlOrientation]:
if self.__io.read_hw_status().et_cable:
if self.__io.read_hw_status().cc1_closed:
return CableControlOrientation.CC1
elif self.__io.read_hw_status().cc2_closed:
return CableControlOrientation.CC2
else:
return None
else:
return None
@orientation.setter
def orientation(self, orientation: CableControlOrientation):
"""
Change cable control orientation.
Args:
orientation (`CableControlOrientation`)
"""
if self.__io.read_hw_status().et_cable:
self.__io.write_hw_command(HWControlCommand.SetCableFlipToOn
if orientation == CableControlOrientation.CC2 else
HWControlCommand.SetCableFlipToOff)
else:
warnings.warn("Unigraf ET cable is not connected. Cannot switch cable control orientation.")
def enable_auto_negotiate_power_contract(self, enable: bool):
"""
Enable/Disable auto negotiate power contract.
Args:
enable (`bool`)
"""
caps = self.__io.read_pdc_contract_control()
caps.auto_negotate = enable
self.__io.write_pdc_contract_control(caps)
def communication_capable_as_pd_sink(self, capable: bool):
"""
Enable/Disable communication capable as PD Sink.
Args:
capable (`bool`)
"""
self.enable_auto_negotiate_power_contract(capable)
pdo = self.__io.read_local_spr_source_pdo()
vdo = self.__io.read_tx_id_vdo()
if isinstance(vdo, list):
if capable:
vdo[0] |= 1 << 30
else:
vdo[0] &= ~(1 << 30)
self.__io.write_tx_id_vdo(vdo)
if isinstance(pdo, list):
if capable:
pdo[0].data |= 1 << 26
else:
pdo[0].data &= ~(1 << 26)
self.__io.write_local_spr_source_pdo([v.data for v in pdo])
def communication_capable_as_pd_source(self, capable: bool):
"""
Enable/Disable communication capable as PD Source.
Args:
capable (`bool`)
"""
pdo = self.__io.read_local_spr_source_pdo()
vdo = self.__io.read_tx_id_vdo()
if isinstance(vdo, list):
if capable:
vdo[0] |= 1 << 31
else:
vdo[0] &= ~(1 << 31)
self.__io.write_tx_id_vdo(vdo)
if isinstance(pdo, list):
if capable:
pdo[0].data |= 1 << 26
else:
pdo[0].data &= ~(1 << 26)
self.__io.write_local_spr_source_pdo([v.data for v in pdo])
class PdcControls340(PdcControlsBase):
"""
Class `PdcControls340` inherited from class `PdcControlsBase`.
Class `PdcControls340` allows controlling additional commands.
Also has all the `PdcControlsBase` functionality.
- Reconnect device `reconnect`.
- Reset device `reset`.
- Set ET cable different pairs `et_cable_diff_pairs`.
"""
def __init__(self, pdc_io: PDCPortIO):
super().__init__(pdc_io)
self.__io = pdc_io
def reset(self):
"""
Reset device.
"""
self.__io.write_hw_command(HWControlCommand.ResetPDController)
def attach(self, attach: bool):
"""
Attach/DeAttach device.
"""
self.__io.write_hw_command(HWControlCommand.ConnectCCLines if attach else HWControlCommand.DisconnectCCLines)
def reconnect(self):
"""
Reconnect device.
Returns:
result of reconnection, type `bool`.
"""
self.__io.write_hw_command(HWControlCommand.RePlugCable)
def is_reconnect_success(__io):
return self.__io.read_pdc_status().cable_plug != 0
return function_scheduler(is_reconnect_success, self.__io, interval=1, timeout=10)
def et_cable_diff_pairs(self, differential_pair: DifferentialPair):
"""
Set ET cable different pairs.
Args:
differential_pair (`DifferentialPair`)
"""
self.__io.write_hw_command(HWControlCommand.SetNewETCableMode if differential_pair.OnePair else
HWControlCommand.SetOldETCableMode)
class PdcControls424(PdcControlsBase):
"""
Class `PdcControls424` inherited from class `PdcControlsBase`.
Class `PdcControls424` allows controlling additional commands.
Also has all the `PdcControlsBase` functionality.
- Reconnect device `reconnect`.
- Reset device `reset`.
"""
def __init__(self, pdc_io: PDCPortIO):
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.
Returns:
result of reconnection, type `bool`.
"""
self.__io.write_pdc_command(PDCControlCommand.SimulateReConnect)
def is_reconnect_success(__io):
return self.__io.read_pdc_status().cable_plug != 0
return function_scheduler(is_reconnect_success, self.__io, interval=1, timeout=10)
class PdcControls500(PdcControlsBase):
"""
Class `PdcControls500` inherited from class `PdcControlsBase`.
Class `PdcControls500` allows controlling additional commands.
Also has all the `PdcControlsBase` functionality.
- Reconnect device `reconnect`.
- Enable/Disable internal resistance 10 Ohm `enable_internal_load_10_ohm`.
"""
def __init__(self, pdc_io: PDCPortIO):
super().__init__(pdc_io)
self.__io = pdc_io
def reconnect(self) -> bool:
"""
Reconnect device.
Returns:
result of reconnection, type `bool`.
"""
self.__io.write_hw_command(HWControlCommand.RePlugCable)
def is_reconnect_success(__io):
return self.__io.read_pdc_status().cable_plug != 0
return function_scheduler(is_reconnect_success, self.__io, interval=1, timeout=10)
def attach(self, attach: bool):
"""
Attach/DeAttach device.
"""
self.__io.write_hw_command(HWControlCommand.ConnectCCLines if attach else HWControlCommand.DisconnectCCLines)
def enable_internal_load_10_ohm(self, enable: bool):
"""
Enable/Disable internal resistance 10 Ohm.
Args:
enable (`bool`)
"""
self.__io.write_hw_command(HWControlCommand.EnableIntLoad_10_ohm if enable else
HWControlCommand.DisableIntLoad_10_ohm)

View File

@@ -0,0 +1,491 @@
import warnings
from UniTAP.dev.ports.modules.pdc.pdc_dpam_types import DPAMVersion
from .pdc_io import PDCPortIO, DPAMCommand
from .pdc_private_dpam_types import PinAssignmentModes, DISCDpSignaling, DISCCapability
from .pdc_utils import support_or_not
class PinAssignment:
"""
Class `PinAssignment` allows enabling and disabling assignment.
- Enable/Disable mode C 4 lanes `c_4_lanes`, type `bool`.
- Enable/Disable mode D 2 lanes `d_2_lanes`, type `bool`.
- Enable/Disable mode E 4 lanes `e_4_lanes`, type `bool`.
"""
def __init__(self):
self.__c_4_lanes = False
self.__d_2_lanes = False
self.__e_4_lanes = False
@property
def c_4_lanes(self) -> bool:
"""
Returns state of C 4 lanes mode.
Returns:
object of `bool` type.
"""
return self.__c_4_lanes
@c_4_lanes.setter
def c_4_lanes(self, enable: bool):
self.__c_4_lanes = enable
@property
def d_2_lanes(self) -> bool:
"""
Returns state of D 2 lanes mode.
Returns:
object of `bool` type.
"""
return self.__d_2_lanes
@d_2_lanes.setter
def d_2_lanes(self, enable: bool):
self.__d_2_lanes = enable
@property
def e_4_lanes(self) -> bool:
"""
Returns state of E 4 lanes mode.
Returns:
object of `bool` type.
"""
return self.__e_4_lanes
@e_4_lanes.setter
def e_4_lanes(self, enable: bool):
self.__e_4_lanes = enable
def __str__(self) -> str:
return f"C 4 lanes: {self.c_4_lanes}\n" \
f"D 2 lanes: {self.d_2_lanes}\n" \
f"E 4 lanes: {self.e_4_lanes}\n"
class DutDpAltModeStatus:
"""
Class `DutDpAltModeStatus` describes DUT DP Alt mode status.
- Get DUT connection state `dut_connection`, type `str`.
- Get DUT multi-function state `dut_multi_function`, type `bool`.
- Get DUT power low state `dut_power_low`, type `bool`.
"""
__dut_connection_status = {DISCCapability.Reserved: "No connection",
DISCCapability.DPF_D_capable: "DFP_D is connected",
DISCCapability.UFP_D_capable: "UFP_D is connected",
DISCCapability.UFP_D_and_DPF_D: "Both DFP_D and UFP_D are connected"}
def __init__(self, pdc_io: PDCPortIO):
self.__io = pdc_io
@property
def dut_connection(self) -> str:
"""
Returns DUT connection state.
Returns:
object of `str` type.
"""
return self.__dut_connection_status.get(DISCCapability(self.__io.read_dpam_recv().connection))
@property
def dut_multi_function(self) -> bool:
"""
Returns DUT multi-function state.
Returns:
object of `bool` type.
"""
return bool(self.__io.read_dpam_recv().multi_func)
@property
def dut_power_low(self) -> bool:
"""
Returns DUT power low state.
Returns:
object of `bool` type.
"""
return bool(self.__io.read_dpam_recv().power_low)
def __str__(self):
return f"DUT Alt mode: {self.dut_connection}\n" \
f"DUT Multi-function preferred: {support_or_not(self.dut_multi_function)}\n" \
f"DUT Power low: {'Low power or DP support disabled' if self.dut_power_low else 'Normal operation'}\n"
class TeDpAltModeStatus:
"""
Class `DutDpAltModeStatus` describes TE DP Alt mode status.
- Get active state `te_active`, type `bool`.
- Get DISC signaling DP v1.3 state, type `bool`.
- Get DISC signaling USB Gen 2 state, type `bool`.
- Get PIN assignment, type `PinAssignmentModes`.
"""
def __init__(self, pdc_io: PDCPortIO):
self.__io = pdc_io
@property
def te_active(self) -> bool:
"""
Returns active state.
Returns:
object of `bool` type.
"""
return bool(self.__io.read_pdc_status().cable_plug)
@property
def te_select_dp_1_3(self) -> bool:
"""
Returns DISC signaling DP v1.3 state.
Returns:
object of `bool` type.
"""
return self.__io.read_dpam_config().signaling == DISCDpSignaling.Dp_v13
@property
def te_select_usb_gen2(self) -> bool:
"""
Returns DISC signaling USB Gen 2 state.
Returns:
object of `bool` type.
"""
return self.__io.read_dpam_config().signaling == DISCDpSignaling.Gen2
@property
def te_pin_assignment(self) -> PinAssignmentModes:
"""
Returns PIN assignment.
Returns:
object of `PinAssignmentModes` type.
"""
return PinAssignmentModes(self.__io.read_dpam_config().pin_assign)
def __str__(self):
return f"TE Status Active: {support_or_not(self.te_active)}\n" \
f"TE Select DP v1.3: {self.te_select_dp_1_3}\n" \
f"TE Select USB gen2: {self.te_select_usb_gen2}\n" \
f"TE Pin Assignment: {self.te_pin_assignment.name}\n"
class DpAltModeStatus:
"""
Class `DpAltModeStatus` describes DP Alt mode status.
- Get DUT DP Alt mode status `dut_dp_alt_mode`, type `DutDpAltModeStatus`.
- Get TE DP Alt mode status, type `TeDpAltModeStatus`.
- Get support state of DISC Signaling DP v13 `support_dp_1_3`, type `bool`.
- Get support state of DISC Signaling USB Gen2 `support_usb_gen2`, type `bool`.
- Get support state of DFP D `support_dfp_d`, type `bool`.
- Get support state of UFP D `support_ufp_d`, type `bool`.
"""
def __init__(self, pdc_io: PDCPortIO):
self.__io = pdc_io
self.__dut_dp_alt_mode = DutDpAltModeStatus(self.__io)
self.__te_dp_alt_mode = TeDpAltModeStatus(self.__io)
@property
def support_dp_1_3(self) -> bool:
"""
Returns support state of DISC Signaling DP v13.
Returns:
object of `bool` type.
"""
return self.__io.read_dpam_disc_modes().signaling == DISCDpSignaling.Dp_v13
@property
def support_usb_gen2(self) -> bool:
"""
Returns support state of DISC Signaling USB Gen2.
Returns:
object of `bool` type.
"""
return self.__io.read_dpam_disc_modes().signaling == DISCDpSignaling.Gen2
@property
def support_dfp_d(self) -> bool:
"""
Returns support state of DFP D.
Returns:
object of `bool` type.
"""
return DISCCapability(self.__io.read_dpam_disc_modes().capability) in [DISCCapability.DPF_D_capable,
DISCCapability.UFP_D_and_DPF_D]
@property
def support_ufp_d(self) -> bool:
"""
Returns support state of UFP D.
Returns:
object of `bool` type.
"""
return DISCCapability(self.__io.read_dpam_disc_modes().capability) in [DISCCapability.UFP_D_capable,
DISCCapability.UFP_D_and_DPF_D]
def multifunction_preferred(self) -> bool:
"""
Returns state of multifunction preferred.
Returns:
object of `bool` type.
"""
return self.__io.read_dpam_caps2()
def auto_enter(self) -> bool:
"""
Returns state of auto enter.
Returns:
object of `bool` type.
"""
return self.__io.read_dpam_state().auto_dpam != 0
@property
def dut_dp_alt_mode(self) -> DutDpAltModeStatus:
"""
Returns DUT DP Alt mode status.
Returns:
object of `DutDpAltModeStatus` type.
"""
return self.__dut_dp_alt_mode
@property
def te_dp_alt_mode(self) -> TeDpAltModeStatus:
"""
Returns TE DP Alt mode status.
Returns:
object of `TeDpAltModeStatus` type.
"""
return self.__te_dp_alt_mode
def __str__(self):
return f"Supports DP v1.3: {support_or_not(self.support_dp_1_3)}\n" \
f"Supports USB gen2: {support_or_not(self.support_usb_gen2)}\n" \
f"Multifunction preferred: {support_or_not(self.multifunction_preferred())}\n" \
f"Auto enter: {support_or_not(self.auto_enter())}\n" \
f"Pin Assignment supported:\n" \
f" - Support DFP_D: {support_or_not(self.support_dfp_d)}\n" \
f" - Support UFP_D: {support_or_not(self.support_ufp_d)}\n" \
f"{self.__dut_dp_alt_mode.__str__()}" \
f"{self.__te_dp_alt_mode.__str__()}"
class DpAltModeBase:
"""
Class `DpAltModeBase` describes basic DP Alt mode functionality.
- Get DP Alt mode status `status`, type `DpAltModeStatus`.
- Enter to 2 lane mode `enter_2_lane`.
- Enter to 4 lane mode `enter_4_lane`.
- Exit from DP Alt mode `exit`.
- Disable DP Alt mode `disable`.
- Enable/Disable auto enter to DP Alt mode `auto_enter`.
- Enable/Disable multifunction preferred `multifunction_preferred`.
- Enable/Disable align Dp and USB Data role `align_dp_and_usb_data_role`.
- Set and get UFP caps `ufp_caps`, type `PinAssignment`.
- Set and get DFP caps `dfp_caps`, type `PinAssignment`.
"""
def __init__(self, pdc_io: PDCPortIO):
self._io = pdc_io
self.__caps = self._io.read_pdc_caps()
self.__status = DpAltModeStatus(pdc_io)
@property
def status(self) -> DpAltModeStatus:
"""
Returns DP Alt mode status.
Returns:
object of `DpAltModeStatus` type.
"""
return self.__status
def enter_2_lane(self):
"""
Enter to 2 lane mode.
"""
self._io.write_dpam_control(DPAMCommand.EnterDPAM2lanes)
def enter_4_lane(self):
"""
Enter to 4 lane mode.
"""
self._io.write_dpam_control(DPAMCommand.EnterDPAM4lanes)
def exit(self):
"""
Exit from DP Alt mode.
"""
self._io.write_dpam_control(DPAMCommand.ExitDPAM)
def disable(self):
"""
Disable DP Alt mode.
"""
self._io.write_dpam_control(DPAMCommand.DisableDPAM)
def auto_enter(self, enable: bool):
"""
Enable/Disable auto enter to DP Alt mode.
Args:
enable (`bool`)
"""
self._io.write_dpam_control(DPAMCommand.AutoEnterDPAM if enable else DPAMCommand.ManualDPAM)
def multifunction_preferred(self, enable: bool):
"""
Enable/Disable multifunction preferred.
Args:
enable (`bool`)
"""
self._io.write_dpam_control(DPAMCommand.SetMFPreferredFlag if enable else DPAMCommand.ClearMFPreferredFlag)
def align_dp_and_usb_data_role(self, enable: bool):
"""
Enable/Disable align Dp and USB Data role.
Args:
enable (`bool`)
"""
if self.__caps.align_dp_usb:
self._io.write_dpam_control(DPAMCommand.SetAlignDpCUsb if enable else DPAMCommand.ClearAlignDpCUsb)
self._io.write_dpam_control(DPAMCommand.SetAlignDpDUsb if enable else DPAMCommand.ClearAlignDpDUsb)
self._io.write_dpam_control(DPAMCommand.SetAlignDpEUsb if enable else DPAMCommand.ClearAlignDpEUsb)
else:
warnings.warn("Align DP and USB data role is not supported.")
@property
def ufp_caps(self) -> PinAssignment:
"""
Returns current UFP caps.
Returns:
object of `PinAssignment`
"""
caps = self._io.read_dpam_caps()
pin_assignment = PinAssignment()
pin_assignment.c_4_lanes = ((caps.ufp_assign >> 2 & 1) != 0)
pin_assignment.d_2_lanes = ((caps.ufp_assign >> 3 & 1) != 0)
pin_assignment.e_4_lanes = ((caps.ufp_assign >> 4 & 1) != 0)
return pin_assignment
@ufp_caps.setter
def ufp_caps(self, ufp_caps: PinAssignment):
caps = self._io.read_dpam_caps()
if ufp_caps.c_4_lanes:
caps.ufp_assign |= PinAssignmentModes.C_4lanes.value
else:
caps.ufp_assign &= ~PinAssignmentModes.C_4lanes.value
if ufp_caps.d_2_lanes:
caps.ufp_assign |= PinAssignmentModes.D_2lanes.value
else:
caps.ufp_assign &= ~PinAssignmentModes.D_2lanes.value
if ufp_caps.e_4_lanes:
caps.ufp_assign |= PinAssignmentModes.E_4lanes.value
else:
caps.ufp_assign &= ~PinAssignmentModes.E_4lanes.value
self._io.write_dpam_caps(caps)
@property
def dfp_caps(self) -> PinAssignment:
"""
Returns current DFP caps.
Returns:
object of `PinAssignment`
"""
caps = self._io.read_dpam_caps()
pin_assignment = PinAssignment()
pin_assignment.c_4_lanes = ((caps.ufp_assign >> 2 & 1) != 0)
pin_assignment.d_2_lanes = ((caps.ufp_assign >> 3 & 1) != 0)
pin_assignment.e_4_lanes = ((caps.ufp_assign >> 4 & 1) != 0)
return pin_assignment
@dfp_caps.setter
def dfp_caps(self, dfp_caps: PinAssignment):
caps = self._io.read_dpam_caps()
if dfp_caps.c_4_lanes:
caps.dfp_assign |= PinAssignmentModes.C_4lanes.value
else:
caps.dfp_assign &= ~PinAssignmentModes.C_4lanes.value
if dfp_caps.d_2_lanes:
caps.dfp_assign |= PinAssignmentModes.D_2lanes.value
else:
caps.dfp_assign &= ~PinAssignmentModes.D_2lanes.value
if dfp_caps.e_4_lanes:
caps.dfp_assign |= PinAssignmentModes.E_4lanes.value
else:
caps.dfp_assign &= ~PinAssignmentModes.E_4lanes.value
self._io.write_dpam_caps(caps)
@property
def version(self) -> DPAMVersion:
return DPAMVersion(self._io.read_dpam_caps().dpam_version)
class DpAltMode500(DpAltModeBase):
"""
Class `DpAltMode500` inherited from class `DpAltModeBase`.
Class `DpAltMode500` allows controlling additional commands.
Also has all the `DpAltModeBase` functionality.
- Enable/Disable DP 2.1 Alt mode `enable_dp21`.
"""
def __init__(self, pdc_io: PDCPortIO):
super().__init__(pdc_io)
def enable_dp21(self, enable: bool):
"""
Enable/Disable DP 2.1 Alt mode.
Args:
enable (`bool`)
"""
self._io.write_dpam_control(DPAMCommand.EnableDPAM2_1 if enable else DPAMCommand.DisableDPAM2_1)
class DpAltMode340(DpAltModeBase):
"""
Class `DpAltMode340` inherited from class `DpAltModeBase`.
Class `DpAltMode340` allows controlling additional commands.
Also has all the `DpAltModeBase` functionality.
- Enable/Disable DP to Type-C cable adapter mode `dp_to_type_c_cable_adapter_mode`.
"""
def __init__(self, pdc_io: PDCPortIO):
super().__init__(pdc_io)
def dp_to_type_c_cable_adapter_mode(self, enable: bool):
"""
Enable/Disable DP to Type-C cable adapter mode.
Args:
enable (`bool`)
"""
self._io.write_dpam_control(DPAMCommand.EnableDPtoTypeCAdapter if enable else
DPAMCommand.DisableDPtoTypeCAdapter)

View File

@@ -0,0 +1,43 @@
from enum import IntEnum
class DISCCapability(IntEnum):
"""
Class `DISCCapability` contains all possible variants of DISC capability.
"""
Reserved = 0
UFP_D_capable = 1
DPF_D_capable = 2
UFP_D_and_DPF_D = 3
class DISCDpSignaling(IntEnum):
"""
Class `DISCDpSignaling` contains all possible variants of signaling.
"""
Unspecified = 0
Dp_v13 = 1
Gen2 = 2
class PinAssignmentModes(IntEnum):
"""
Class `PinAssignmentModes` contains all possible variants of pin assignment.
"""
NotSupported = 0x00
A_4_2lanes = 0x01
B_2_1lanes = 0x02
C_4lanes = 0x04
D_2lanes = 0x08
E_4lanes = 0x10
F_2lanes_USB_GEN1 = 0x20
class DPAMVersion(IntEnum):
"""
Class `PinAssignmentModes` contains all possible variants of DP Alt mode version.
"""
V_20_or_Earlier = 0
V_21_or_Higher = 1
Reserved = 2
Reserved2 = 3

View File

@@ -0,0 +1,115 @@
from UniTAP.libs.lib_tsi.tsi_io import PortIO
from UniTAP.libs.lib_tsi.tsi_private_types import *
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
from .pdo_private_types import PdoUnion
class PDCPortIO:
def __init__(self, port_io: PortIO):
self.__io = port_io
self.write_adc_control()
def write_dpam_caps(self, caps: DPAMCaps):
self.__io.set(TSI_PDC_DPAM_CAPS, caps.value(), c_uint32)
def read_dpam_caps(self) -> DPAMCaps:
return self.__io.get(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
def read_dpam_state(self) -> DPAMState:
return self.__io.get(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)
def read_dpam_config(self) -> DPAMConfig:
return self.__io.get(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]
def read_dpam_recv(self) -> DPAMRecv:
return self.__io.get(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)
def read_hw_status(self) -> HWStatus:
return self.__io.get(TSI_PDC_HW_STATUS_R, HWStatus)[1]
def read_hw_caps(self) -> HWCaps:
return self.__io.get(TSI_PDC_HW_CAPS_R, HWCaps)[1]
def read_pdc_status(self) -> PDCStatus:
return self.__io.get(TSI_PDC_STATUS_R, PDCStatus)[1]
def write_pdc_command(self, command: PDCControlCommand):
self.__io.set(TSI_PDC_CONTROL, command.value, c_uint32)
def read_pdc_state(self) -> PDCState:
return self.__io.get(TSI_PDC_STATE, PDCState)[1]
def read_pdc_caps(self) -> PDCCaps:
return self.__io.get(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)
def read_pdc_contract_control(self) -> PDCContractInfo:
return self.__io.get(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]
def write_local_spr_source_pdo(self, data: list):
self.__io.set(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]
def write_local_spr_sink_pdo(self, data: list):
self.__io.set(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]
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]
def write_tx_id_vdo(self, data: list):
self.__io.set(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]
def write_contract_data(self, data: list):
self.__io.set(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]
def write_power_contract_select(self, index: int):
self.__io.set(TSI_USBC_PWR_CONTRACT_SELECT, index, c_uint32)
def read_resistance(self) -> int:
return self.__io.get(TSI_USBC_RESISTANCE_CONTROL, c_uint32)[1]
def write_resistance(self, resistance: int):
self.__io.set(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]
def read_internal_resistance(self) -> int:
return self.__io.get(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]
def write_adc_control(self):
self.__io.set(TSI_W_USBC_ADC_CTRL, 1, c_uint32)

View File

@@ -0,0 +1,144 @@
import copy
from .pdc_io import PDCPortIO
from .pdc_utils import load_pdo, save_pdo
from .pdo_types import FixedPdoSink, BatteryPdo, VariablePdo, PdoTypeEnum, PdoSide
from .pdo import Pdo
from .pdo_utils import get_pdo_value
from typing import List
class PowerSink:
"""
Class `PowerSink` contains information about PDO's on Sink side.
- Get PDO count `pdo_count`, type `int`.
- Set and get PDO list, `set_pdo_list`, `get_pdo_list`, type `list` with `Pdo`.
- Set and get PDO by index, `set_pdo_by_index`, `get_pdo_by_index`, type `Pdo`.
- Save information about PDO's to file, `save_pdo`.
- Load information about PDO's from file, `load_pdo`.
"""
def __init__(self, pdc_io: PDCPortIO):
self.__io = pdc_io
self.__pdo_count = self.__io.read_hw_caps().pdo_count
self.__pdo_list = self.__read_pdo()
def __read_pdo(self) -> List[Pdo]:
pdo_list = []
values = self.__io.read_local_spr_sink_pdo()
for i in range(self.__pdo_count):
if PdoTypeEnum(values[i].brief_info.pdo_type) == PdoTypeEnum.Fixed and values[i].data > 0:
pdo_list.append(Pdo(pdo=FixedPdoSink(values[i].fixed_pdo_sink, disable=False), side=PdoSide.Sink))
elif PdoTypeEnum(values[i].brief_info.pdo_type) == PdoTypeEnum.Fixed and values[i].data == 0:
pdo_list.append(Pdo(pdo=FixedPdoSink(values[i].fixed_pdo_sink, disable=True), side=PdoSide.Sink))
elif PdoTypeEnum(values[i].brief_info.pdo_type) == PdoTypeEnum.Battery:
pdo_list.append(Pdo(pdo=BatteryPdo(values[i].battery_pdo), side=PdoSide.Sink))
elif PdoTypeEnum(values[i].brief_info.pdo_type) == PdoTypeEnum.Variable:
pdo_list.append(Pdo(pdo=VariablePdo(values[i].variable_pdo), side=PdoSide.Sink))
return pdo_list
def __write_pdo(self) -> List[int]:
pdo_list = []
for index, item in enumerate(self.__pdo_list):
if index == 0:
pdo_list.append(get_pdo_value(item.get_pdo_as_selected_type(FixedPdoSink)))
elif item.pdo_type != PdoTypeEnum.Disabled:
pdo_list.append(get_pdo_value(item.pdo_object))
else:
pdo_list.append(0)
return pdo_list
@property
def pdo_count(self) -> int:
"""
Returns current pdo count.
Returns:
object of `int` type
"""
return self.__pdo_count
def set_pdo_list(self, pdo_list: List[Pdo]):
"""
Set new Pdo list.
Args:
pdo_list (`list` with 'Pdo')
"""
self.__pdo_list = copy.deepcopy(pdo_list)
self.__io.write_local_spr_sink_pdo(self.__write_pdo())
def set_pdo_by_index(self, pdo_object, index: int):
"""
Set new Pdo by index.
Args:
pdo_object ('Pdo')
index (`int`)
"""
if not 0 <= index < self.__pdo_count:
raise ValueError(f"Incorrect PDO index. Supported PDO amount: {self.__pdo_count}")
self.__pdo_list[index] = copy.deepcopy(pdo_object)
self.__io.write_local_spr_sink_pdo(self.__write_pdo())
def get_pdo_list(self, read_from_device: bool = False) -> List[Pdo]:
"""
Returns current pdo list.
Args:
read_from_device (`bool`)
Returns:
object of `list` type with `Pdo`.
"""
if read_from_device:
self.__pdo_list = self.__read_pdo()
return copy.deepcopy(self.__pdo_list)
def get_pdo_by_index(self, index: int, read_from_device: bool = False) -> Pdo:
"""
Returns current pdo by index.
Args:
index (`int`)
read_from_device (`bool`)
Returns:
object of `Pdo` type.
"""
if read_from_device:
self.__pdo_list = self.__read_pdo()
if not 0 <= index < self.__pdo_count:
raise ValueError(f"Incorrect PDO index. Supported PDO amount: {self.__pdo_count}")
return copy.deepcopy(self.__pdo_list[index])
def save_pdo(self, path: str):
"""
Save information about PDO's to file.
Supported formats:
- txt
- json
Args:
path (`str`)
"""
save_pdo(path, self.__pdo_list, False)
def load_pdo(self, path: str):
"""
Load information about PDO's from file.
Supported formats:
- txt
- json
Args:
path (`str`)
"""
self.__pdo_list = load_pdo(path, False)
def __str__(self) -> str:
pdo_status = ""
for index, item in enumerate(self.__pdo_list):
pdo_status += f"PDO {index}\n{item.pdo_object.__str__()}\n"
return f"Power Sink\n{pdo_status}\n"

View File

@@ -0,0 +1,152 @@
import copy
from .pdc_io import PDCPortIO
from .pdc_private_types import PDCControlCommand
from .pdc_utils import load_pdo, save_pdo
from .pdo_types import FixedPdoSource, BatteryPdo, VariablePdo, PdoTypeEnum, PdoSide
from .pdo import Pdo
from .pdo_utils import get_pdo_value
from typing import List
class PowerSource:
"""
Class `PowerSource` contains information about PDO's on Source side.
- Get PDO count `pdo_count`, type `int`.
- Set and get PDO list, `set_pdo_list`, `get_pdo_list`, type `list` with `Pdo`.
- Set and get PDO by index, `set_pdo_by_index`, `get_pdo_by_index`, type `Pdo`.
- Send Source PDO's, `send_pdo`.
- Save information about PDO's to file, `save_pdo`.
- Load information about PDO's from file, `load_pdo`.
"""
def __init__(self, pdc_io: PDCPortIO):
self.__io = pdc_io
self.__pdo_count = self.__io.read_hw_caps().pdo_count
self.__pdo_list = self.__read_pdo()
def __read_pdo(self) -> List[Pdo]:
pdo_list = []
values = self.__io.read_local_spr_source_pdo()
for i in range(self.__pdo_count):
if PdoTypeEnum(values[i].brief_info.pdo_type) == PdoTypeEnum.Fixed and values[i].data > 0:
pdo_list.append(Pdo(pdo=FixedPdoSource(values[i].fixed_pdo_source, disable=False), side=PdoSide.Source))
elif PdoTypeEnum(values[i].brief_info.pdo_type) == PdoTypeEnum.Fixed and values[i].data == 0:
pdo_list.append(Pdo(pdo=FixedPdoSource(values[i].fixed_pdo_source, disable=True), side=PdoSide.Source))
elif PdoTypeEnum(values[i].brief_info.pdo_type) == PdoTypeEnum.Battery:
pdo_list.append(Pdo(pdo=BatteryPdo(values[i].battery_pdo), side=PdoSide.Source))
elif PdoTypeEnum(values[i].brief_info.pdo_type) == PdoTypeEnum.Variable:
pdo_list.append(Pdo(pdo=VariablePdo(values[i].variable_pdo), side=PdoSide.Source))
return pdo_list
def __write_pdo(self) -> List[int]:
pdo_list = []
for index, item in enumerate(self.__pdo_list):
if index == 0:
pdo_list.append(get_pdo_value(item.get_pdo_as_selected_type(FixedPdoSource)))
elif item.pdo_type != PdoTypeEnum.Disabled:
pdo_list.append(get_pdo_value(item.pdo_object))
else:
pdo_list.append(0)
return pdo_list
@property
def pdo_count(self) -> int:
"""
Returns current pdo count.
Returns:
object of `int` type
"""
return self.__pdo_count
def send_pdo(self):
"""
Send Source PDO's.
"""
self.__io.write_pdc_command(PDCControlCommand.SendSourceCaps)
def get_pdo_list(self, read_from_device: bool = False) -> List[Pdo]:
"""
Returns current pdo list.
Args:
read_from_device (`bool`)
Returns:
object of `list` type with `Pdo`.
"""
if read_from_device:
self.__pdo_list = self.__read_pdo()
return copy.deepcopy(self.__pdo_list)
def get_pdo_by_index(self, index: int, read_from_device: bool = False):
"""
Returns current pdo by index.
Args:
index (`int`)
read_from_device (`bool`)
Returns:
object of `Pdo` type.
"""
if read_from_device:
self.__pdo_list = self.__read_pdo()
if not 0 <= index < self.__pdo_count:
raise ValueError(f"Incorrect PDO index. Supported PDO amount: {self.__pdo_count}")
return copy.deepcopy(self.__pdo_list[index])
def set_pdo_list(self, pdo_list: List[Pdo]):
"""
Set new Pdo list.
Args:
pdo_list (`list` with 'Pdo')
"""
self.__pdo_list = copy.deepcopy(pdo_list)
self.__io.write_local_spr_source_pdo(self.__write_pdo())
def set_pdo_by_index(self, pdo_object, index: int):
"""
Set new Pdo by index.
Args:
pdo_object ('Pdo')
index (`int`)
"""
if not 0 <= index < self.__pdo_count:
raise ValueError(f"Incorrect PDO index. Supported PDO amount: {self.__pdo_count}")
self.__pdo_list[index] = copy.deepcopy(pdo_object)
self.__io.write_local_spr_source_pdo(self.__write_pdo())
def save_pdo(self, path: str):
"""
Save information about PDO's to file.
Supported formats:
- txt
- json
Args:
path (`str`)
"""
save_pdo(path, self.__pdo_list, True)
def load_pdo(self, path: str):
"""
Load information about PDO's from file.
Supported formats:
- txt
- json
Args:
path (`str`)
"""
self.__pdo_list = load_pdo(path, True)
def __str__(self) -> str:
pdo_status = ""
for index, item in enumerate(self.__pdo_list):
pdo_status += f"PDO {index}\n{item.pdo_object.__str__()}\n"
return f"Power Source\n{pdo_status}\n"

View File

@@ -0,0 +1,104 @@
from ctypes import Structure, c_uint32
from enum import IntEnum
from .pdc_dpam_types import DISCCapability, DISCDpSignaling, PinAssignmentModes
class DPAMCommand(IntEnum):
DoesNothing = 0x00
AutoEnterDPAM = 0x01
EnterDPAM2lanes = 0x02
EnterDPAM4lanes = 0x03
ExitDPAM = 0x04
DisableDPAM = 0x05
ManualDPAM = 0x06
DisableDPtoTypeCAdapter = 0x08
EnableDPtoTypeCAdapter = 0x09
ClearMFPreferredFlag = 0x0E
SetMFPreferredFlag = 0x0F
ClearAlignDpCUsb = 0x30
SetAlignDpCUsb = 0x31
ClearAlignDpDUsb = 0x32
SetAlignDpDUsb = 0x33
ClearAlignDpEUsb = 0x34
SetAlignDpEUsb = 0x35
EnableDPAM2_1 = 0x38
DisableDPAM2_1 = 0x39
class DPAMCaps(Structure):
_fields_ = [
('', c_uint32, 8),
('dfp_assign', c_uint32, 8),
('ufp_assign', c_uint32, 8),
('', c_uint32, 6),
('dpam_version', c_uint32, 2)
]
def value(self) -> int:
return self.dfp_assign << 8 | self.dfp_assign << 16 | self.dpam_version << 30
class DPAMState(Structure):
_fields_ = [
('auto_dpam', c_uint32, 1),
('dpam_enable', c_uint32, 1),
('adapter_mode', c_uint32, 1),
('', c_uint32, 1),
('align_dp_c_usb', c_uint32, 1),
('align_dp_d_usb', c_uint32, 1),
('align_dp_e_usb', c_uint32, 1),
('', c_uint32, 25)
]
class DPAMConfig(Structure):
_fields_ = [
('config', c_uint32, 2),
('signaling', c_uint32, 4),
('', c_uint32, 2),
('pin_assign', c_uint32, 8),
('', c_uint32, 10),
('uhbr_13_5_support', c_uint32, 1),
('', c_uint32, 1),
('cable_active_component', c_uint32, 2),
('dpam_version', c_uint32, 2)
]
class DPAMDiscModes(Structure):
_fields_ = [
('capability', c_uint32, 2),
('signaling', c_uint32, 4),
('dp_placement', c_uint32, 1),
('usb_signaling', c_uint32, 1),
('dfp_assign', c_uint32, 8),
('ufp_assign', c_uint32, 8),
('', c_uint32, 6),
('dpam_version', c_uint32, 2)
]
@property
def capability(self) -> DISCCapability:
return DISCCapability(self.capability)
@property
def signaling(self) -> DISCDpSignaling:
return DISCDpSignaling(self.signaling)
class DPAMRecv(Structure):
_fields_ = [
('connection', c_uint32, 2),
('power_low', c_uint32, 1),
('enable', c_uint32, 1),
('multi_func', c_uint32, 1),
('usb_cfg_rq', c_uint32, 1),
('exit_rq', c_uint32, 1),
('hpd_state', c_uint32, 1),
('hpd_irq', c_uint32, 1),
('no_dpam_suspend', c_uint32, 1),
]
@property
def connection(self) -> DISCCapability:
return DISCCapability(self.capability)

View File

@@ -0,0 +1,227 @@
from ctypes import Structure, c_uint32, c_uint64
from enum import IntEnum
from .pdc_types import CCPullUp, ContractTypePriority, DRPTryMode, USB3Mode, PdcDeviceRole, PDMode
class HWControlCommand(IntEnum):
DoNothing = 0x00
ToggleCableFlip = 0x01
SetCableFlipToOff = 0x02
SetCableFlipToOn = 0x03
EnableUSBDeviceCharger = 0x04
DisableUSBDeviceCharger = 0x05
SwitchToHostMode = 0x06
SwitchToDeviceMode = 0x07
Enable20PHY = 0x08
Disable20PHY = 0x09
Enable20PHYDeviceModeEnableCharger = 0x0A
Enable20PHYHostModeDisableCharger = 0x0B
Disable20PHYDisableCharger = 0x0C
DisableIntLoad_5_5_ohm = 0x0E
EnableIntLoad_5_5_ohm = 0x0F
DisableIntLoad_3_5_ohm = 0x10
EnableIntLoad_3_5_ohm = 0x11
DisableIntLoad_10_ohm = 0x12
EnableIntLoad_10_ohm = 0x13
DisconnectCCLines = 0x14
ConnectCCLines = 0x15
RePlugCable = 0x16
SetNewETCableMode = 0x18
SetOldETCableMode = 0x19
Enable30PHY = 0x1A
Disable30PHY = 0x1B
ResetPDController = 0x1C
class PDCControlCommand(IntEnum):
DoNothing = 0x00
ToggleDataRole = 0x01
SetDataRoleUFP = 0x02
SetDataRoleDFP = 0x03
SwapVconn = 0x04
TogglePowerRole = 0x05
FastRoleSwap = 0x06
HardReset = 0x07
SimulateReConnect = 0x0A
PullCCLineToDefault = 0x0C
PullCCLineTo1_5A = 0x0D
PullCCLineTo3_0A = 0x0E
SetDataRoleDRP = 0x14
SetDataRoleDRP_SNK_Support = 0x15
SetDataRoleDRP_SRC_Support = 0x16
DisableUSB3 = 0x18
EnableUSB3_gen1 = 0x19
EnableUSB3_gen2 = 0x1A
DisableUSB2 = 0x1C
EnableUSB2 = 0x1D
DisableVconnSwap = 0x1E
EnableVconnSwap = 0x1F
DisablePRSwap = 0x20
EnablePRSwap = 0x21
DisableDRSwap = 0x22
EnableDRSwap = 0x23
DisableDebugAccessorySupport = 0x24
EnableDebugAccessorySupport = 0x25
DisableAudioAccessorySupport = 0x26
EnableAudioAccessorySupport = 0x27
DisableFRSwap = 0x28
EnableFRSwap = 0x29
SetFRSwapNoSupported = 0x2A
SetFRSwapUSBPower = 0x2B
SetFRSwap1_5A_5V = 0x2C
SetFRSwap3A_5V = 0x2C
EnableEPRasPowerSink = 0x2E
DisableEPRasPowerSink = 0x2F
EnableEPRAutoEnter = 0x30
DisableEPRAutoEnter = 0x31
InitiateEPRModeEnter = 0x32
InitiateEPRModeExit = 0x33
EnableRejectEPRModeEnter = 0x34
DisableRejectEPRModeEnter = 0x35
SendSourceCaps = 0x41
class HWCaps(Structure):
_fields_ = [
('', c_uint32, 1),
('et_board', c_uint32, 1),
('', c_uint32, 2),
('pdo_count', c_uint32, 4),
('', c_uint32, 24)
]
class HWStatus(Structure):
_fields_ = [
('cable_flip', c_uint32, 1),
('ext_power', c_uint32, 1),
('charger', c_uint32, 1),
('usb_mode', c_uint32, 1),
('usb_20_phy', c_uint32, 1),
('et_cable', c_uint32, 1),
('int_3_5_ohm', c_uint32, 1),
('int_10_ohm', c_uint32, 1),
('cc1_closed', c_uint32, 1),
('cc2_closed', c_uint32, 1),
('int_5_5_ohm', c_uint32, 1),
('et_cable_mode', c_uint32, 1),
('usb_30_phy', c_uint32, 1),
('int_3_5_ovp', c_uint32, 1),
('int_10_ovp', c_uint32, 1),
('int_5_5_ovp', c_uint32, 1),
('', c_uint32, 13),
('pdc_fault', c_uint32, 1),
('', c_uint32, 1),
('pdc_reset', c_uint32, 1)
]
class PDCStatus(Structure):
_fields_ = [
('cable_plug', c_uint64, 1),
('cable_orientation', c_uint64, 1),
('power_role', c_uint64, 1),
('data_role', c_uint64, 1),
('rmt_snk_pdo', c_uint64, 1),
('rmt_src_pdo', c_uint64, 1),
('pwr_contract', c_uint64, 1),
('rmt_svid', c_uint64, 1),
('vconn_enabled', c_uint64, 1),
('emarked_cable', c_uint64, 1),
('dp_alt_mode', c_uint64, 1),
('usb_device', c_uint64, 1),
('usb_host', c_uint64, 1),
('usb_2_conn', c_uint64, 1),
('usb_3_conn', c_uint64, 1),
('sop_identity', c_uint64, 1),
('current', c_uint64, 2),
('adc_data', c_uint64, 1),
('am_sw_inprog', c_uint64, 1),
('pullup_sence', c_uint64, 2),
('rx_identity', c_uint64, 1),
('', c_uint64, 6),
('pdc_fault', c_uint64, 1),
('', c_uint64, 2),
('rx_sink_pdp', c_uint64, 1),
('rx_source_pdp', c_uint64, 1),
('rx_snk_epr_pdo', c_uint64, 1),
('rx_src_epr_pdo', c_uint64, 1),
('', c_uint64, 28)
]
class PDCState(Structure):
_fields_ = [
('cc_pull_up', c_uint32, 2),
('dev_role', c_uint32, 2),
('pd_mode', c_uint32, 2),
('usb30_mode', c_uint32, 2),
('usb2_enabled', c_uint32, 1),
('vconn_swap_en', c_uint32, 1),
('pr_swap_en', c_uint32, 1),
('dr_swap_en', c_uint32, 1),
('dbg_accessory', c_uint32, 1),
('aud_accessory', c_uint32, 1),
('fr_swap_en', c_uint32, 1),
('', c_uint32, 1),
('drp_try_mode', c_uint32, 2),
('', c_uint32, 2),
('epr_snk_en', c_uint32, 1),
('epr_auto_enter_en', c_uint32, 1),
('epr_mode', c_uint32, 1),
('epr_enter_en', c_uint32, 1),
]
@property
def cc_pull_up(self) -> CCPullUp:
return CCPullUp(self.cc_pull_up)
@property
def dev_role(self) -> PdcDeviceRole:
return PdcDeviceRole(self.dev_role)
@property
def pd_mode(self) -> PDMode:
return PDMode(self.pd_mode)
@property
def usb30_mode(self) -> USB3Mode:
return USB3Mode(self.usb30_mode)
@property
def drp_try_mode(self) -> DRPTryMode:
return DRPTryMode(self.drp_try_mode)
class PDCCaps(Structure):
_fields_ = [
('try_snk', c_uint32, 1),
('try_src', c_uint32, 1),
('fr_swap', c_uint32, 1),
('cable_sim', c_uint32, 1),
('ext_sink_pc', c_uint32, 1),
('align_dp_usb', c_uint32, 1),
('', c_uint32, 16)
]
class PDCContractInfo(Structure):
_fields_ = [
('auto_negotate', c_uint32, 1),
('use_battery_pdo', c_uint32, 1),
('use_variable_pdo', c_uint32, 1),
('comm_capable', c_uint32, 1),
('type_priority', c_uint32, 2),
('no_usb_suspend', c_uint32, 1),
('give_back_flag', c_uint32, 1),
('auto_min_power', c_uint32, 1),
('', c_uint32, 6),
('min_power', c_uint32, 10),
('', c_uint32, 5),
('manual', c_uint32, 1),
]
def value(self) -> int:
return self.auto_negotate | self.use_battery_pdo << 1 | self.use_variable_pdo << 2 | self.comm_capable << 3 | \
self.type_priority << 4 | self.no_usb_suspend << 6 | self.give_back_flag << 7 | \
self.auto_min_power << 8 | self.min_power << 15 | self.manual << 31

View File

@@ -0,0 +1,125 @@
from enum import IntEnum
class CCPullUp(IntEnum):
"""
Class `CCPullUp` contains all possible variants of CC Pull Up.
"""
Current_05_09A = 0
Current_1_5A = 1
Current_3A = 2
Unknown = 3
class PowerRole(IntEnum):
"""
Class `PowerRole` contains all possible variants of device power role.
"""
Source = 0
Sink = 1
class FrSwapCurrent(IntEnum):
"""
Class `FrSwapCurrent` contains all possible variants of FR Swap current.
"""
Disable = 0
EnableDefaultUSBPower = 1
Enable_1_5A_5V = 2
Enable_3A_5V = 3
class PdcDeviceRole(IntEnum):
"""
Class `PdcDeviceRole` contains all possible variants of PDC device role.
"""
UFP = 0
DFP = 1
DRP = 2
Unknown = 3
class PDMode(IntEnum):
"""
Class `PDMode` contains all possible variants of PD modes.
"""
NormalPD = 0
LegacyUSBSource = 1
LegacyUSBSink = 2
Unknown = 3
class USB3Mode(IntEnum):
"""
Class `USB3Mode` contains all possible variants of USB-3 modes.
"""
Disabled = 0
EnabledGen1 = 1
EnabledGen2 = 2
Unknown = 3
class DRPTryMode(IntEnum):
"""
Class `DRPTryMode` contains all possible variants of DRP behavior modes.
"""
PureDRP = 0
DRP_try_SNK = 1
DRP_try_SRC = 2
Unknown = 3
class CableControlOrientation(IntEnum):
"""
Class `CableControlOrientation` contains all possible variants of orientation.
"""
CC1 = 0
CC2 = 1
class DifferentialPair(IntEnum):
"""
Class `DifferentialPair` contains all possible variants of differential pairs.
"""
OnePair = 0
TwoPair = 1
class ContractTypePriority(IntEnum):
"""
Class `ContractTypePriority` contains all possible variants of contract type priority.
"""
HigherCurrent = 0
HigherVoltage = 1
HigherPower = 2
Unknown = 3
class InternalResistance(IntEnum):
"""
Class `InternalResistance` contains all possible variants of internal resistance.
"""
Disable = 1
Resistance_10_Ohm = 40001
Resistance_5_5_Ohm = 22001
Resistance_3_55_Ohm = 14161
Resistance_3_5_Ohm = 14001
Resistance_2_6_Ohm = 10361
Resistance_2_14_Ohm = 8521
Resistance_1_76_Ohm = 7001
class ExternalResistance(IntEnum):
"""
Class `ExternalResistance` contains all possible variants of external resistance.
"""
Disable = 3
Resistance_13_9_Ohm = 55603
Resistance_10_6_Ohm = 42403
Resistance_9_1_Ohm = 36403
Resistance_7_6_Ohm = 30403
Resistance_6_6_Ohm = 26403
Resistance_5_6_Ohm = 22403
Resistance_4_6_Ohm = 18403
Resistance_3_6_Ohm = 14403
Resistance_1_8_Ohm = 7203

View File

@@ -0,0 +1,72 @@
import warnings
import os
import json
from UniTAP.dev.ports.modules.pdc.pdo import Pdo
from UniTAP.dev.ports.modules.pdc.pdo_utils import get_pdo_value
from UniTAP.dev.ports.modules.pdc.pdo_types import *
from UniTAP.dev.ports.modules.pdc.pdo_private_types import PdoUnion
def support_or_not(value) -> str:
return "Yes" if bool(value) else "No"
def save_pdo(path: str, pdo_list: list, source: bool):
filename, file_extension = os.path.splitext(path)
if file_extension.find('.txt') != -1:
file = open(path, 'w')
file.write("TSI_USBC_PWR_LOCAL_SOURCE_PDO\n" if source else "TSI_USBC_PWR_LOCAL_SINK_PDO\n")
file.write("1\n")
file.write(str(len(pdo_list) * 4))
for pdo in pdo_list:
file.write(str(get_pdo_value(pdo.get_pdo_object())))
file.close()
elif file_extension.find('.json') != -1:
values = {}
for index, pdo in enumerate(pdo_list):
values.update({f"EPR{index}": get_pdo_value(pdo.get_pdo_object())})
with open(path, "w") as outfile:
json.dump(values, outfile)
else:
warnings.warn(f"Unsupported file format: {file_extension}. "
f"Please, select file format from available variants: 'txt', 'json'")
def load_pdo(path: str, source: bool) -> list:
if os.path.exists(path):
raise ValueError(f"Incorrect path {path} to file. Path does not exist.")
filename, file_extension = os.path.splitext(path)
pdo_list = []
if file_extension.find('.txt') != -1:
file = open(path, 'r')
data = file.read().split("\n")
for index, line in enumerate(data):
if index >= 3:
fill_list(int(line), pdo_list, source)
file.close()
elif file_extension.find('.json') != -1:
with open(path, "r", encoding='utf-8') as read_file:
data = json.load(read_file)
keys = list(data.keys())
for index, key in enumerate(keys):
fill_list(int(data.get(key)), pdo_list, source)
else:
raise ValueError(f"Unsupported file format: {file_extension}. "
f"Please, select file format from available variants: 'txt', 'json'")
return pdo_list
def fill_list(data, pdo_list, source):
pdo_data = PdoUnion(data)
pdo_type = PdoTypeEnum(pdo_data.brief_info.pdo_type)
if pdo_type == PdoTypeEnum.Fixed:
pdo_list.append(Pdo(pdo=FixedPdoSource(pdo_data.fixed_pdo_source) if source else
FixedPdoSink(pdo_data.fixed_pdo_sink),
side=PdoSide.Source if source else PdoSide.Sink))
elif pdo_type == PdoTypeEnum.Battery:
pdo_list.append(Pdo(pdo=BatteryPdo(pdo_data.battery_pdo),
side=PdoSide.Source if source else PdoSide.Sink))
elif pdo_type == PdoTypeEnum.Variable:
pdo_list.append(Pdo(pdo=VariablePdo(pdo_data.variable_pdo),
side=PdoSide.Source if source else PdoSide.Sink))

View File

@@ -0,0 +1,99 @@
from typing import Type
from UniTAP.dev.ports.modules.pdc.pdo_utils import interpret_pdo_value
from UniTAP.dev.ports.modules.pdc.pdo_types import PdoSide, PdoType, FixedPdoSink, FixedPdoSource, BatteryPdo, \
VariablePdo, PdoTypeEnum
class Pdo:
"""
Class `Pdo` describes power delivery object in PDC module. Contains information about side of PDO `PdoSide` and
main PDO data. May have one of the available type `PdoType`: `FixedPdoSink`, `FixedPdoSource`, `BatteryPdo`,
`VariablePdo`.
- Get PDO type `pdo_type`, type of `PdoTypeEnum`.
- Get PDO side `pdo_side`, type of `PdoSide`.
- Set and get main PDO object `pdo_object`, type of `PdoType`.
- Get pdo object as selected PDO type `PdoType` `get_pdo_as_selected_type`, type of `PdoType`.
- Convert (interpret) from one PDO type to another `interpret_pdo_as_selected_type`.
"""
def __init__(self, pdo: PdoType, side: PdoSide):
self.__pdo = pdo
self.__side = side
@property
def pdo_type(self) -> PdoTypeEnum:
"""
Returns current PDO type.
Returns:
object of `PdoTypeEnum` type
"""
return self.__pdo.pdo_type
@property
def pdo_side(self) -> PdoSide:
"""
Returns current PDO side.
Returns:
object of `PdoSide` type
"""
return self.__side
@property
def pdo_object(self) -> PdoType:
"""
Returns current PDO object.
Returns:
object of `PdoType` type
"""
return self.__pdo
@pdo_object.setter
def pdo_object(self, pdo: PdoType):
self.__pdo = pdo
def disable_pdo(self):
"""
Disable PDO. Will be filled with zeros.
"""
self.__pdo = FixedPdoSink(disable=True) if self.__side == PdoSide.Sink else FixedPdoSource(disable=True)
def get_pdo_as_selected_type(self, pdo: Type[PdoType]) -> PdoType:
"""
Returns PDO object as selected new PDO type.
Args:
pdo (`PdoType`) - type of PDO
Returns:
object of `PdoType` type
"""
self.interpret_pdo_as_selected_type(pdo)
return self.__pdo
def interpret_pdo_as_selected_type(self, pdo: Type[PdoType]):
"""
Convert (interpret) from one PDO type to another.
Args:
pdo (`PdoType`) - type of PDO
"""
if pdo == FixedPdoSink and self.__side == PdoSide.Sink:
self.__pdo = FixedPdoSink(interpret_pdo_value(self.__pdo, pdo))
elif pdo == FixedPdoSource and self.__side == PdoSide.Source:
self.__pdo = FixedPdoSource(interpret_pdo_value(self.__pdo, pdo))
elif pdo == BatteryPdo:
self.__pdo = BatteryPdo(interpret_pdo_value(self.__pdo, pdo))
elif pdo == VariablePdo:
self.__pdo = VariablePdo(interpret_pdo_value(self.__pdo, pdo))
else:
raise ValueError(f"Incorrect PDO type: {pdo}. Available types: BatteryPdo, VariablePdo, "
f"{'FixedPdoSink' if self.__side == PdoSide.Sink else 'FixedPdoSource'}")
def __str__(self):
return f'PDO type: {self.pdo_type.name}\n' \
f'{self.__pdo.__str__()}'

View File

@@ -0,0 +1,74 @@
from typing import TypeVar
from ctypes import Structure, Union, c_uint32
class FixedPdoSourceStruct(Structure):
_fields_ = [
('max_current', c_uint32, 10),
('voltage', c_uint32, 10),
('peak_current', c_uint32, 2),
('', c_uint32, 3),
('dual_data_role', c_uint32, 1),
('usb_communication_capable', c_uint32, 1),
('externally_powered', c_uint32, 1),
('usb_suspend_supported', c_uint32, 1),
('dual_power_role_capable', c_uint32, 1),
('pdo_type', c_uint32, 2),
]
class FixedPdoSinkStruct(Structure):
_fields_ = [
('oper_current', c_uint32, 10),
('voltage', c_uint32, 10),
('', c_uint32, 5),
('dual_data_role', c_uint32, 1),
('usb_communication_capable', c_uint32, 1),
('externally_powered', c_uint32, 1),
('usb_suspend_supported', c_uint32, 1),
('dual_power_role_capable', c_uint32, 1),
('pdo_type', c_uint32, 2),
]
class VariablePdoStruct(Structure):
_fields_ = [
('max_current', c_uint32, 10),
('min_voltage', c_uint32, 10),
('max_voltage', c_uint32, 10),
('pdo_type', c_uint32, 2),
]
class BatteryPdoStruct(Structure):
_fields_ = [
('max_power', c_uint32, 10),
('min_voltage', c_uint32, 10),
('max_voltage', c_uint32, 10),
('pdo_type', c_uint32, 2),
]
class PdoBriefInfo(Structure):
_fields_ = [
('data', c_uint32, 30),
('pdo_type', c_uint32, 2)
]
class PdoUnion(Union):
_fields_ = [
('data', c_uint32),
('brief_info', PdoBriefInfo),
('fixed_pdo_source', FixedPdoSourceStruct),
('fixed_pdo_sink', FixedPdoSinkStruct),
('variable_pdo', VariablePdoStruct),
('battery_pdo', BatteryPdoStruct)
]
PdoTypeStruct = TypeVar("PdoTypeStruct",
FixedPdoSinkStruct,
FixedPdoSourceStruct,
BatteryPdoStruct,
VariablePdoStruct)

View File

@@ -0,0 +1,488 @@
from enum import IntEnum
from typing import TypeVar
from .pdo_private_types import FixedPdoSourceStruct, FixedPdoSinkStruct, BatteryPdoStruct, VariablePdoStruct
class PdoTypeEnum(IntEnum):
"""
Class `PdoTypeEnum` contains all possible variants of PDO types.
"""
Fixed = 0
Battery = 1
Variable = 2
Disabled = 3
Mandatory = 4
class PdoSide(IntEnum):
"""
Class `PdoTypeEnum` contains all possible variants of PDO side.
"""
Sink = 0
Source = 1
class PeakCurrent(IntEnum):
"""
Class `PdoTypeEnum` contains all possible variants of peak current for PDO.
"""
Percent_100 = 0
Percent_110 = 1
Percent_125 = 2
Percent_150 = 3
class FixedPdoSource:
"""
Class `FixedPdoSource` contains information about Fixed PDO on Source side.
- Set and get maximum current `max_current`, type `int`.
- Set and get voltage `voltage`, type `int`.
- Set and get peak_current `peak_current`, type `PeakCurrent`.
- Set and get dual data role flag `dual_data_role`, type `bool`.
- Set and get usb communication flag `usb_communication`, type `bool`.
- Set and get unconstrained power flag `unconstrained_power`, type `bool`.
- Set and get higher capability flag `higher_capability`, type `bool`.
- Set and get dual power role flag `dual_power_role`, type `bool`.
- Get PDO type `pdo_type`, type `PdoTypeEnum`.
"""
def __init__(self, pdo: FixedPdoSourceStruct = FixedPdoSourceStruct(0), disable=False):
self.__max_current = pdo.max_current * 10
self.__voltage = pdo.voltage * 50
self.__peak_current = PeakCurrent(pdo.peak_current)
self.__dual_data_role = pdo.dual_data_role
self.__usb_communication = pdo.usb_communication_capable
self.__unconstrained_power = pdo.externally_powered
self.__higher_capability = pdo.usb_suspend_supported
self.__dual_power_role = pdo.dual_power_role_capable
self.__type = PdoTypeEnum.Disabled if disable else PdoTypeEnum.Fixed
@property
def max_current(self) -> int:
"""
Returns maximum current.
Returns:
object of `int` type
"""
return self.__max_current
@max_current.setter
def max_current(self, max_current: int):
self.__max_current = max_current
@property
def voltage(self) -> int:
"""
Returns voltage.
Returns:
object of `int` type
"""
return self.__voltage
@voltage.setter
def voltage(self, voltage: int):
self.__voltage = voltage
@property
def peak_current(self) -> PeakCurrent:
"""
Returns peak current.
Returns:
object of `PeakCurrent` type
"""
return self.__peak_current
@peak_current.setter
def peak_current(self, peak_current: PeakCurrent):
self.__peak_current = peak_current
@property
def dual_data_role(self) -> bool:
"""
Returns flag of dual data role.
Returns:
object of `bool` type
"""
return bool(self.__dual_data_role)
@dual_data_role.setter
def dual_data_role(self, dual_data_role: bool):
self.__dual_data_role = dual_data_role
@property
def usb_communication(self) -> bool:
"""
Returns flag of usb communication.
Returns:
object of `bool` type
"""
return bool(self.__usb_communication)
@usb_communication.setter
def usb_communication(self, usb_communication: bool):
self.__usb_communication = usb_communication
@property
def unconstrained_power(self) -> bool:
"""
Returns flag of unconstrained power.
Returns:
object of `bool` type
"""
return bool(self.__unconstrained_power)
@unconstrained_power.setter
def unconstrained_power(self, unconstrained_power: bool):
self.__unconstrained_power = unconstrained_power
@property
def higher_capability(self) -> bool:
"""
Returns flag of higher capability.
Returns:
object of `bool` type
"""
return bool(self.__higher_capability)
@higher_capability.setter
def higher_capability(self, higher_capability: bool):
self.__higher_capability = higher_capability
@property
def dual_power_role(self) -> bool:
"""
Returns flag of dual power role.
Returns:
object of `bool` type
"""
return bool(self.__dual_power_role)
@dual_power_role.setter
def dual_power_role(self, dual_power_role: bool):
self.__dual_power_role = dual_power_role
@property
def pdo_type(self) -> PdoTypeEnum:
"""
Returns flag of PDO type.
Returns:
object of `PdoTypeEnum` type
"""
return self.__type
def __str__(self):
return f"Max Current: {self.__max_current}\n" \
f"Voltage: {self.__voltage}\n" \
f"Peak Current: {self.__peak_current.name}\n" \
f"Dual Role: {'Yes' if self.__dual_data_role else 'No'}\n" \
f"USB Communication: {'Yes' if self.__usb_communication else 'No'}\n" \
f"Unconstrained Power: {'Yes' if self.__unconstrained_power else 'No'}\n" \
f"Higher capability: {'Yes' if self.__higher_capability else 'No'}\n" \
f"Dual Power role: {'Yes' if self.__dual_power_role else 'No'}\n"
class VariablePdo:
"""
Class `VariablePdo` contains information about Fixed PDO on Sink and Source side.
- Set and get maximum current `max_current`, type `int`.
- Set and get minimum voltage `min_voltage`, type `int`.
- Set and get maximum voltage `max_voltage`, type `bool`.
- Get PDO type `pdo_type`, type `PdoTypeEnum`.
"""
def __init__(self, pdo: VariablePdoStruct = VariablePdoStruct(0)):
self.__max_current = pdo.max_current * 10
self.__min_voltage = pdo.min_voltage * 50
self.__max_voltage = pdo.max_voltage * 50
self.__type = PdoTypeEnum.Variable
@property
def max_current(self) -> int:
"""
Returns maximum current.
Returns:
object of `int` type
"""
return self.__max_current
@max_current.setter
def max_current(self, max_current: int):
self.__max_current = max_current
@property
def min_voltage(self) -> int:
"""
Returns minimum voltage.
Returns:
object of `int` type
"""
return self.__min_voltage
@min_voltage.setter
def min_voltage(self, min_voltage: int):
self.__min_voltage = min_voltage
@property
def max_voltage(self) -> int:
"""
Returns maximum voltage.
Returns:
object of `int` type
"""
return self.__max_voltage
@max_voltage.setter
def max_voltage(self, max_voltage: int):
self.__max_voltage = max_voltage
@property
def pdo_type(self) -> PdoTypeEnum:
"""
Returns flag of PDO type.
Returns:
object of `PdoTypeEnum` type
"""
return self.__type
def __str__(self):
return f"Max Current: {self.__max_current}\n" \
f"Min Voltage: {self.__min_voltage}\n" \
f"Max Voltage: {self.__max_voltage}"
class BatteryPdo:
"""
Class `BatteryPdo` contains information about Fixed PDO on Sink and Source side.
- Set and get maximum power `max_power`, type `int`.
- Set and get minimum voltage `min_voltage`, type `int`.
- Set and get maximum voltage `max_voltage`, type `bool`.
- Get PDO type `pdo_type`, type `PdoTypeEnum`.
"""
def __init__(self, pdo: BatteryPdoStruct = BatteryPdoStruct(0)):
self.__max_power = pdo.max_power * 250
self.__min_voltage = pdo.min_voltage * 50
self.__max_voltage = pdo.max_voltage * 50
self.__type = PdoTypeEnum.Battery
@property
def max_power(self) -> int:
"""
Returns maximum power.
Returns:
object of `int` type
"""
return self.__max_power
@max_power.setter
def max_power(self, max_power: int):
self.__max_power = max_power
@property
def min_voltage(self) -> int:
"""
Returns minimum voltage.
Returns:
object of `int` type
"""
return self.__min_voltage
@min_voltage.setter
def min_voltage(self, min_voltage: int):
self.__min_voltage = min_voltage
@property
def max_voltage(self) -> int:
"""
Returns maximum voltage.
Returns:
object of `int` type
"""
return self.__max_voltage
@max_voltage.setter
def max_voltage(self, max_voltage: int):
self.__max_voltage = max_voltage
@property
def pdo_type(self) -> PdoTypeEnum:
"""
Returns flag of PDO type.
Returns:
object of `PdoTypeEnum` type
"""
return self.__type
def __str__(self):
return f"Max power: {self.__max_power}\n" \
f"Min Voltage: {self.__min_voltage}\n" \
f"Max Voltage: {self.__max_voltage}"
class FixedPdoSink:
"""
Class `FixedPdoSink` contains information about Fixed PDO on Sink side.
- Set and get maximum current `max_current`, type `int`.
- Set and get voltage `voltage`, type `int`.
- Set and get dual data role flag `dual_data_role`, type `bool`.
- Set and get usb communication flag `usb_communication`, type `bool`.
- Set and get unconstrained power flag `unconstrained_power`, type `bool`.
- Set and get higher capability flag `higher_capability`, type `bool`.
- Set and get dual power role flag `dual_power_role`, type `bool`.
- Get PDO type `pdo_type`, type `PdoTypeEnum`.
"""
def __init__(self, pdo: FixedPdoSinkStruct = FixedPdoSinkStruct(0), disable=False):
self.__oper_current = pdo.oper_current * 10
self.__voltage = pdo.voltage * 50
self.__dual_data_role = bool(pdo.dual_data_role)
self.__usb_communication = bool(pdo.usb_communication_capable)
self.__unconstrained_power = bool(pdo.externally_powered)
self.__higher_capability = bool(pdo.usb_suspend_supported)
self.__dual_power_role = bool(pdo.dual_power_role_capable)
self.__type = PdoTypeEnum.Disabled if disable else PdoTypeEnum.Fixed
@property
def oper_current(self) -> int:
"""
Returns operation current.
Returns:
object of `int` type
"""
return self.__oper_current
@oper_current.setter
def oper_current(self, oper_current: int):
self.__oper_current = oper_current
@property
def voltage(self) -> int:
"""
Returns voltage.
Returns:
object of `int` type
"""
return self.__voltage
@voltage.setter
def voltage(self, voltage: int):
self.__voltage = voltage
@property
def dual_data_role(self) -> bool:
"""
Returns flag of dual data role.
Returns:
object of `bool` type
"""
return bool(self.__dual_data_role)
@dual_data_role.setter
def dual_data_role(self, dual_data_role: bool):
self.__dual_data_role = dual_data_role
@property
def usb_communication(self) -> bool:
"""
Returns flag of usb communication.
Returns:
object of `bool` type
"""
return bool(self.__usb_communication)
@usb_communication.setter
def usb_communication(self, usb_communication: bool):
self.__usb_communication = usb_communication
@property
def unconstrained_power(self) -> bool:
"""
Returns flag of unconstrained power.
Returns:
object of `bool` type
"""
return bool(self.__unconstrained_power)
@unconstrained_power.setter
def unconstrained_power(self, unconstrained_power: bool):
self.__unconstrained_power = unconstrained_power
@property
def higher_capability(self) -> bool:
"""
Returns flag of higher capability.
Returns:
object of `bool` type
"""
return bool(self.__higher_capability)
@higher_capability.setter
def higher_capability(self, higher_capability: bool):
self.__higher_capability = higher_capability
@property
def dual_power_role(self) -> bool:
"""
Returns flag of dual power role.
Returns:
object of `bool` type
"""
return bool(self.__dual_power_role)
@dual_power_role.setter
def dual_power_role(self, dual_power_role: bool):
self.__dual_power_role = dual_power_role
@property
def pdo_type(self) -> PdoTypeEnum:
"""
Returns flag of PDO type.
Returns:
object of `PdoTypeEnum` type
"""
return self.__type
def __str__(self):
return f"Oper Current: {self.__oper_current}\n" \
f"Voltage: {self.__voltage}\n" \
f"Dual Role: {'Yes' if self.__dual_data_role else 'No'}\n" \
f"USB Communication: {'Yes' if self.__usb_communication else 'No'}\n" \
f"Unconstrained Power: {'Yes' if self.__unconstrained_power else 'No'}\n" \
f"Higher capability: {'Yes' if self.__higher_capability else 'No'}\n" \
f"Dual Power role: {'Yes' if self.__dual_power_role else 'No'}\n"
PdoType = TypeVar("PdoType",
FixedPdoSink,
FixedPdoSource,
BatteryPdo,
VariablePdo)

View File

@@ -0,0 +1,31 @@
from UniTAP.dev.ports.modules.pdc.pdo_private_types import *
from UniTAP.dev.ports.modules.pdc.pdo_types import *
def get_pdo_value(pdo: PdoType) -> int:
if isinstance(pdo, FixedPdoSink):
value = int(pdo.oper_current / 10) | (int(pdo.voltage / 50) << 10) | (pdo.dual_data_role << 25) | (pdo.usb_communication << 26) | \
(pdo.unconstrained_power << 27) | (pdo.higher_capability << 28) | (pdo.dual_power_role << 29)
return value
elif isinstance(pdo, FixedPdoSource):
value = int(pdo.max_current / 10) | (int(pdo.voltage / 50) << 10) | (pdo.peak_current.value << 20) | (pdo.dual_data_role << 25) | \
(pdo.usb_communication << 26) | (pdo.unconstrained_power << 27) | (pdo.higher_capability << 28) | \
pdo.dual_power_role << 29
return value
elif isinstance(pdo, BatteryPdo):
value = int(pdo.max_power / 250) | (int(pdo.min_voltage / 50) << 10) | (int(pdo.max_voltage / 50) << 20) | (1 << 30)
return value
elif isinstance(pdo, VariablePdo):
value = int(pdo.max_current / 10) | (int(pdo.min_voltage / 50) << 10) | (int(pdo.max_voltage / 50) << 20) | (2 << 30)
return value
def interpret_pdo_value(old_type: PdoType, new_type: PdoType) -> PdoTypeStruct:
if new_type == FixedPdoSink:
return PdoUnion(get_pdo_value(old_type)).fixed_pdo_sink
elif new_type == FixedPdoSource:
return PdoUnion(get_pdo_value(old_type)).fixed_pdo_source
elif new_type == BatteryPdo:
return PdoUnion(get_pdo_value(old_type)).battery_pdo
elif new_type == VariablePdo:
return PdoUnion(get_pdo_value(old_type)).variable_pdo