#!python3 """Script to convert an oscilloscope binary file to CSV format waveform files. """ # Import Modules import sys import re import struct # Variables. waveform_type_dict = { 0: "Unknown", 1: "Normal", 2: "Peak Detect", 3: "Average", 4: "Horizontal Histogram", 5: "Vertical Histogram", 6: "Logic", } buffer_type_dict = { 0: "Unknown data", 1: "Normal 32-bit float data", 2: "Maximum float data", 3: "Minimum float data", 4: "Time float data", 5: "Counts 32-bit float data", 6: "Digital unsigned 8-bit character data", } units_dict = { 0: "Unknown", 1: "Volts", 2: "Seconds", 3: "Constant", 4: "Amps", 5: "dB", 6: "Hz", } hex_to_binary_dict = { "0": "0000", "1": "0001", "2": "0010", "3": "0011", "4": "0100", "5": "0101", "6": "0110", "7": "0111", "8": "1000", "9": "1001", "a": "1010", "b": "1011", "c": "1100", "d": "1101", "e": "1110", "f": "1111", } def prtsv(string): """Function to print and save output information.""" global msg msg.write(f"{string}\n") print(string) def read_8bit_digital_data(buffer_size, x_origin, x_increment, label, segment_index): """Function to read 8-bit digital data from the binary data file. """ if segment_index == 0: csv_output_file = re.sub(r"\.bin", f"_{label}.csv", sys.argv[1]) else: csv_output_file = re.sub( r"\.bin", f"_segment-{segment_index}_{label}.csv", sys.argv[1] ) csv = open(csv_output_file, "w") # prtsv("---------- Digital Data ----------") for i in range(buffer_size): (digital_data,) = struct.unpack("B", bin_input.read(1)) # prtsv( # f"Point {i}, = '0x{digital_data:02x}', {x_origin + (i * x_increment):E} s" # ) hex_string = hex(digital_data) # Returns "0xn" or "0xnn". if len(hex_string) == 4: # "0xnn". un = hex_to_binary_dict[hex_string[2]] ln = hex_to_binary_dict[hex_string[3]] else: # "0xn". un = "0000" ln = hex_to_binary_dict[hex_string[2]] csv.write( f"{x_origin + i * x_increment}, {un[0]}, {un[1]}, {un[2]}, {un[3]}, {ln[0]}, {ln[1]}, {ln[2]}, {ln[3]}\n" ) csv.close() prtsv(f"CSV waveform data saved to: {csv_output_file}") def read_32bit_float_data( buffer_size, bytes_per_point, x_origin, x_increment, label, segment_index ): """Function to read 32-bit float data from the binary data file. """ if segment_index == 0: csv_output_file = re.sub(r"\.bin", f"_{label}.csv", sys.argv[1]) else: csv_output_file = re.sub( r"\.bin", f"_segment-{segment_index}_{label}.csv", sys.argv[1] ) csv = open(csv_output_file, "w") # prtsv("---------- Voltage Data ----------") for i in range(int(buffer_size / bytes_per_point)): (voltage,) = struct.unpack("f", bin_input.read(bytes_per_point)) # prtsv(f"Point {i}, = '{voltage:+.3f}' V, {x_origin + (i * x_increment):E} s") csv.write(f"{x_origin + i * x_increment:E}, {voltage:f}\n") csv.close() prtsv(f"CSV waveform data saved to: {csv_output_file}") def read_waveform_data(x_origin, x_increment, label, segment_index): """Function to print data from individual waveforms in binary data file. """ prtsv("---------- Waveform Data Header ----------") (waveform_data_header_size,) = struct.unpack("i", bin_input.read(4)) prtsv(f"Waveform Data Header Size = '{waveform_data_header_size}'") (buffer_type,) = struct.unpack("h", bin_input.read(2)) if buffer_type in buffer_type_dict: prtsv(f"Buffer Type = '{buffer_type_dict[buffer_type]}'") else: prtsv(f"Buffer Type (unknown) = '{buffer_type}'") bin_input.close() msg.close() sys.exit() (bytes_per_point,) = struct.unpack("h", bin_input.read(2)) prtsv(f"Bytes Per Point = '{bytes_per_point}'") (buffer_size,) = struct.unpack("i", bin_input.read(4)) prtsv(f"Buffer Size = '{buffer_size}'") if buffer_type == 1: # Normal 32-bit float data. read_32bit_float_data( buffer_size, bytes_per_point, x_origin, x_increment, label, segment_index ) elif buffer_type == 2: # Maximum float data. label = label + "_PkMax" read_32bit_float_data( buffer_size, bytes_per_point, x_origin, x_increment, label, segment_index ) elif buffer_type == 3: # Minimum float data. label = label + "_PkMin" read_32bit_float_data( buffer_size, bytes_per_point, x_origin, x_increment, label, segment_index ) elif buffer_type == 6: # Digital unsigned 8-bit char data. read_8bit_digital_data(buffer_size, x_origin, x_increment, label, segment_index) else: buffer_bytes = bin_input.read(buffer_size) def read_waveform(): """Function to print data from individual waveforms in binary data file. """ prtsv("---------- Waveform Header ----------") (waveform_header_size,) = struct.unpack("i", bin_input.read(4)) prtsv(f"Waveform Header Size = '{waveform_header_size}'") (waveform_type,) = struct.unpack("i", bin_input.read(4)) if waveform_type in waveform_type_dict: prtsv(f"Waveform Type = '{waveform_type_dict[waveform_type]}'") else: prtsv(f"Waveform Type (unknown) = '{waveform_type}'") bin_input.close() msg.close() sys.exit() (waveform_buffers,) = struct.unpack("i", bin_input.read(4)) prtsv(f"Number of Waveform buffers = '{waveform_buffers}'") (points,) = struct.unpack("i", bin_input.read(4)) prtsv(f"Points = '{points}'") (count,) = struct.unpack("i", bin_input.read(4)) prtsv(f"Count = '{count}'") (x_display_range,) = struct.unpack("f", bin_input.read(4)) prtsv(f"X Display Range = '{x_display_range:E}'") (x_display_origin,) = struct.unpack("d", bin_input.read(8)) prtsv(f"X Display Origin = '{x_display_origin:E}'") (x_increment,) = struct.unpack("d", bin_input.read(8)) prtsv(f"X Increment = '{x_increment:E}'") (x_origin,) = struct.unpack("d", bin_input.read(8)) prtsv(f"X Origin = '{x_origin:E}'") (x_units,) = struct.unpack("i", bin_input.read(4)) if x_units in units_dict: prtsv(f"X Units = '{units_dict[x_units]}'") else: prtsv(f"X Units = '{x_units}'") (y_units,) = struct.unpack("i", bin_input.read(4)) if x_units in units_dict: prtsv(f"Y Units = '{units_dict[y_units]}'") else: prtsv(f"Y Units = '{y_units}'") (date,) = struct.unpack("16s", bin_input.read(16)) prtsv(f"Date = '{date.decode("utf-8")}'") (time,) = struct.unpack("16s", bin_input.read(16)) prtsv(f"Time = '{time.decode("utf-8")}'") (frame,) = struct.unpack("24s", bin_input.read(24)) prtsv(f"Frame = '{frame.decode("utf-8")}'") (waveform_label,) = struct.unpack("16s", bin_input.read(16)) label = waveform_label.decode("utf-8").rstrip(chr(0)) prtsv(f"Waveform Label = '{label}'") (time_tags,) = struct.unpack("d", bin_input.read(8)) prtsv(f"Time Tags = '{time_tags:E}'") (segment_index,) = struct.unpack("I", bin_input.read(4)) prtsv(f"Segment Index = '{segment_index}'") for i in range(waveform_buffers): read_waveform_data( x_origin, x_increment, label.replace(" ", "_"), segment_index ) # ========================================================= # Main Program # ========================================================= if len(sys.argv) != 2: sys.stderr.write(f"Usage: python {sys.argv[0]} \n") sys.exit() # Open message output file. msg_output_file = re.sub(r"\.bin", "_info.txt", sys.argv[1]) msg = open(msg_output_file, "w") # Open binary file. bin_input = open(sys.argv[1], "rb") prtsv("---------- File Header ----------") (cookie,) = struct.unpack("2s", bin_input.read(2)) prtsv(f"Cookie = '{cookie.decode('utf-8')}'") (file_version,) = struct.unpack("2s", bin_input.read(2)) prtsv(f"File version = '{file_version.decode('utf-8')}'") (file_size,) = struct.unpack("i", bin_input.read(4)) prtsv(f"File size = '{file_size}' (always zero in Infiniium 2026)") (waveforms,) = struct.unpack("i", bin_input.read(4)) prtsv(f"Number of Waveforms = '{waveforms}'") for i in range(waveforms): read_waveform() # Close binary file. bin_input.close() # Close message output file. msg.close() # Exit program. sys.exit()