import os import UniTAP import time import math import threading # # Config. # BULK_SIZE_MB = 100 # Mb FOLDER_TO_GENERATE = "./BulkData" tps3 = True tps4 = True fec = True lanes = [ 1, 2, 4 ] # If you want to use UCD-400, please, set 'dp_14_mode = True' and 'enable_dp_21_mode = False' # If you want to use UCD-500 in DP 1.4 mode, please, set 'dp_14_mode = True' and 'enable_dp_21_mode = False' # If you want to use UCD-500 in DP 2.1 mode, please, set 'dp_14_mode = False' and 'enable_dp_21_mode = True' dp_14_mode = False bit_rates_14 = [ 1.62, 2.7, 5.4, 6.75, 8.1 ] enable_dp_21_mode = True bit_rates_21 = [ 10, 13.5, 20 ] mst = True streams = [ 0, 1, 2, 3 ] # # Trigger config. # trigger_positions = [ UniTAP.bulk.TriggerPosition.TP_Start, UniTAP.bulk.TriggerPosition.TP_25, UniTAP.bulk.TriggerPosition.TP_50, UniTAP.bulk.TriggerPosition.TP_75, UniTAP.bulk.TriggerPosition.TP_End ] # If you do not want to use trigger config, please, set 'None' to variable # Use other types of trigger config. Full list located in 'TriggerType' trigger_config = UniTAP.bulk.TriggerType.U13() trigger_config.position = UniTAP.bulk.TriggerTypeEnum.SourceTypePosition.InitialLT lUniTAP = UniTAP.TsiLib() # # For opening device, please, put serial number of the device as 8 symbol str or put index of device. # # serial_number = "2150C474" # dev = lUniTAP.open(serial_number) # If you do not want to write device serial number, you can write index position of device index_position = 0 dev = lUniTAP.open(index_position) # Need to select type of device: UCD-400 or UCD-500 # role = dev.select_role(UniTAP.dev.UCD400.DPSourceDPSink) role = dev.select_role(UniTAP.dev.UCD500.DPSourceDPSink) timing_manager = role.dptx.pg.timing_manager timings = [ timing_manager.get_cta(16), timing_manager.get_cta(90), timing_manager.get_cta(97), timing_manager.get_cta(126), timing_manager.get_cta(196), ] color_formats = [ UniTAP.ColorInfo.ColorFormat.CF_RGB, UniTAP.ColorInfo.ColorFormat.CF_YCbCr_444, UniTAP.ColorInfo.ColorFormat.CF_YCbCr_422, UniTAP.ColorInfo.ColorFormat.CF_YCbCr_420, UniTAP.ColorInfo.ColorFormat.CF_Y_ONLY, UniTAP.ColorInfo.ColorFormat.CF_RAW ] colorimetry_list = [ UniTAP.ColorInfo.Colorimetry.CM_sRGB, UniTAP.ColorInfo.Colorimetry.CM_ITUR_BT601, UniTAP.ColorInfo.Colorimetry.CM_ITUR_BT709 ] # Note: BPC 7 and 14 will be work only with CF_Y_ONLY and CF_RAW bpc_list = [ 6, 7, 8, 10, 12, 14, 16 ] def link_training(dev_role): time.sleep(1) dev_role.dptx.link.start_link_training() def bool_str_format(value: bool) -> str: return "ON" if value else "OFF" def prepare_directory_name(_timing, _color_mode, _lane, _rate, _stream, tr_pos, tr_config=None) -> str: tr_conf_str = type(tr_config).__name__ if tr_config is not None else "-" auto_generated_folder = f"cap_[TG_Pos_{tr_pos.name}][TG_Conf-{tr_conf_str}][{'DP1.4' if dp_14_mode else 'DP2.1'}]" \ f"[MST-{bool_str_format(mst)}][FEC-{bool_str_format(fec)}][stream-{_stream}]" \ f"[TPS3-{bool_str_format(tps3)}][TPS4-{bool_str_format(tps4)}]" \ f"[{_timing.hactive}x{_timing.vactive}@" \ f"{math.ceil(_timing.frame_rate / 1000)}_{_color_mode.color_format.name}_{_color_mode.bpc}bpc" \ f"-{_color_mode.colorimetry.name}]" directory_name = os.path.join(FOLDER_TO_GENERATE, auto_generated_folder) return directory_name def do_bulk_capture(dev_role, _timing, _color_mode, _lane, _rate, _stream): # bulk_size - size of data in megabytes # trigger_position - available position of trigger. Variants: TP_Start, TP_25, TP_50, TP_75, TP_End # trigger_config - one of the variant of active trigger. # assume_scrambler - just flag of assume scrambler for tr_pos in trigger_positions: thread = None if trigger_config is not None: thread = threading.Thread(target=link_training, args=(role,)) thread.start() dev_role.dprx.bulk_capturer.start(bulk_size=BULK_SIZE_MB, trigger_position=tr_pos, trigger_config=trigger_config, assume_scrambler=False, gpio=False) dev_role.dprx.bulk_capturer.stop() if trigger_config is not None and thread is not None: thread.join() thread.stop_thread = False # If you want to get captured data, please, use 'capture_result'. It is the object of class 'ResultBulkObject'. # For saving data in file, please, use 'save_to_bin_file'. You need to set 'directory_name' - name of directory, # where you want to save files. If directory have already existed, is will be clean up. # If directory does not exist, it will be created. result = dev_role.dprx.bulk_capturer.capture_result directory_name = prepare_directory_name(_timing, _color_mode, _lane, _rate, _stream, tr_pos, trigger_config) result.save_to_bin_file(directory_name=directory_name) for lane in lanes: if dp_14_mode: rates = bit_rates_14 else: rates = bit_rates_21 for timing in timings: for rate in rates: for stream in streams: for color_format in color_formats: for bpc in bpc_list: for colorimetry in colorimetry_list: # Configure Sink Link caps caps = UniTAP.LinkCapabilities() caps.max_lane = lane if dp_14_mode: caps.bit_rate = rate else: caps.dp_128_132_bitrates = [rate] caps.fec = fec caps.tps3 = tps3 caps.tps4 = tps4 caps.mst = mst role.dprx.link.capabilities.set(caps) role.dprx.link.hpd_pulse() time.sleep(0.5) # Configure Source Link if dp_14_mode: config = UniTAP.LinkConfig.DP8b10b() config.mst = mst else: config = UniTAP.LinkConfig.DP128b132b() config.lane_count = lane config.bit_rate = rate if enable_dp_21_mode: config.force_dp_128_132 = True config.try_dp_128_132 = True else: config.force_dp_128_132 = False config.try_dp_128_132 = False role.dptx.link.config.set(config) role.dptx.link.start_link_training() time.sleep(0.5) color_mode = UniTAP.ColorInfo() color_mode.color_format = color_format color_mode.bpc = bpc color_mode.colorimetry = colorimetry if color_format in [UniTAP.ColorInfo.ColorFormat.CF_RGB, UniTAP.ColorInfo.ColorFormat.CF_RAW, UniTAP.ColorInfo.ColorFormat.CF_Y_ONLY]: color_mode.dynamic_range = UniTAP.ColorInfo.DynamicRange.DR_VESA else: color_mode.dynamic_range = UniTAP.ColorInfo.DynamicRange.DR_CTA video_mode = UniTAP.VideoMode(timing=timing, color_info=color_mode) if stream < role.dptx.pg.max_stream_count: role.dptx.pg[stream].set_vm(vm=video_mode) role.dptx.pg[stream].set_pattern(pattern=UniTAP.VideoPattern.ColorBars) role.dptx.pg[stream].apply() res_app = role.dptx.pg[stream].status().error print(f"Stream {stream} - Apply {res_app.__str__()}") if res_app == res_app.OK: print("Start do bulk capturing") try: do_bulk_capture(role, timing, color_mode, lane, rate, stream) print("Bulk capture completed successfully") except BaseException as e: print(f'Error during bulk capturing. Error: {e}') else: print('Cannot start to do bulk capturing, because PG does not apply settings.') # # Since the 3.5 version, TsiLib and TSIDevice objects have the option to be closed earlier. # TSIDevice can be closed with the TsiLib method close(). TsiLib can be closed with cleanup(). # Clean up will close all opened devices and block ability to open any devices # with same TsiLib object. # lUniTAP.close(dev) lUniTAP.cleanup()