Last active
August 9, 2023 04:26
-
-
Save hansemro/4b8733cf5a217bcee7a5796f8eff2726 to your computer and use it in GitHub Desktop.
[WIP] Siglent BIN waveform viewer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# SPDX-License-Identifier: MIT | |
# Copyright (c) 2023 Hansem Ro | |
# Siglent BIN waveform viewer | |
# Tasks: | |
# - [ ] Support v0/v1 waveform | |
# - [ ] Process analog waveform | |
# - [ ] Process digital waveform | |
# - [x] Support v2 waveform | |
# - [x] Process analog waveform | |
# - [x] Process math waveform | |
# - [x] Process digital waveform | |
# - untested, assumes little endian bit order | |
# - [x] Parse code_per_div from bin file | |
# - Tested with SDS2000X+ 1.3.9R12 | |
# - 8-bit/10-bit ADC modes supported | |
# - [x] Support v4 waveform | |
# - [x] Process analog waveform | |
# - [x] Process math waveform | |
# - [x] Process digital waveform | |
# - [ ] Process memory waveform? | |
# - [ ] Process zoom waveform? | |
# - [ ] Refactor code | |
# Usage: | |
# 0. Install dependencies: | |
# `pip install matplotlib` | |
# 1. Run script with a bin file: | |
# `python3 siglent_bin_viewer.py <BIN_FILE>` | |
from argparse import ArgumentParser | |
import matplotlib.pyplot as plt | |
import struct | |
class SiglentChannel: | |
def __init__(self, name:str, enabled:bool): | |
self.name = name | |
self.enabled = enabled | |
class SiglentAnalogChannel(SiglentChannel): | |
def __init__(self, name:str, enabled:bool, volt_div_val:float, vert_offset:float, probe_factor:float, code_per_div:float): | |
super().__init__(name, enabled) | |
self.volt_div_val = volt_div_val | |
self.vert_offset = vert_offset | |
self.probe_factor = probe_factor | |
self.code_per_div = code_per_div | |
class SiglentDigitalChannel(SiglentChannel): | |
def __init__(self, name:str, enabled:bool): | |
super().__init__(name, enabled) | |
class SiglentMathChannel(SiglentChannel): | |
def __init__(self, name:str, enabled:bool, vdiv_val:float, vert_offset:float, wave_length:int, f_time:float): | |
super().__init__(name, enabled) | |
self.vdiv_val = vdiv_val | |
self.vert_offset = vert_offset | |
self.wave_length = wave_length | |
self.f_time = f_time | |
class SiglentBIN: | |
""" | |
Siglent BIN waveform | |
""" | |
def __init__(self, bin_file:str): | |
self.bin_file = bin_file | |
self.version = None | |
self.analog_channels = [] | |
self.digital_on = False | |
self.digital_channels = [] | |
self.math_channels = [] | |
self.time_div = None | |
self.time_delay = None | |
self.wave_length = None | |
self.s_rate = None | |
self.digital_wave_length = None | |
self.digital_s_rate = None | |
self.data_width = None | |
self.byte_order = None | |
self.num_hori_div = None | |
self.parse_bin() | |
def __parse_version_2__(self, data:bytearray): | |
""" | |
Spec details starting at page 23 of E02A document. | |
E02A: https://web.archive.org/web/20230730072643/https://www.siglenteu.com/wp-content/uploads/2021/08/How-to-Extract-Data-from-the-Binary-File.pdf | |
Model+FW that exports version 2 binary data: | |
- SDS5000X | |
- FW: 0.8.6 to 0.9.6 | |
- SDS2000X Plus | |
- FW: 1.2.6 to 1.3.9RX | |
- SDS6000A | |
- FW older than 1.4.1.0 | |
- SDS6000 H10 Pro | |
- FW older than 1.4.1.0 | |
- SDS6000 H12 Pro | |
- FW older than 1.4.1.0 | |
""" | |
version = struct.unpack('<l', data[0x0:0x4])[0] | |
assert version == 2 | |
for i in range(0,4): | |
# enable | |
# ch1: [0x4:0x4+4] | |
# ch2: [0x8:0x8+4] | |
# ch3: [0xc:0xc+4] | |
# ch4: [0x10:0x10+4] | |
ch_on = struct.unpack('<l', data[i*4+0x4:(i+1)*4+0x4])[0] == 1 | |
print(f"ch{i+1}_on: {ch_on}") | |
# volt_div_val | |
# ch1: [0x14:0x14+8] | |
# ch2: [0x3c:0x3c+8] | |
# ch3: [0x64:0x64+8] | |
# ch4: [0x8c:0x8c+8] | |
ch_volt_div_val = struct.unpack('<d', data[i*0x28+0x14:i*0x28+0x14+8])[0] | |
print(f"ch{i+1}_volt_div_val: {ch_volt_div_val}") | |
# vert_offset | |
# ch1: [0xb4:0xb4+8] | |
# ch2: [0xdc:0xdc+8] | |
# ch3: [0x104:0x104+8] | |
# ch4: [0x12c:0x12c+8] | |
ch_vert_offset = struct.unpack('<d', data[i*0x28+0xb4:i*0x28+0xb4+8])[0] | |
print(f"ch{i+1}_vert_offset: {ch_vert_offset}") | |
# probe_factor | |
# ch1: [0x240:0x240+8] | |
# ch2: [0x248:0x248+8] | |
# ch3: [0x250:0x250+8] | |
# ch4: [0x258:0x258+8] | |
ch_probe = struct.unpack('<d', data[i*8+0x240:(i+1)*8+0x240])[0] | |
print(f"ch{i+1}_probe: {ch_probe}") | |
# code_per_div | |
# ch1: [0x26c:0x26c+4] | |
# ch2: [0x270:0x270+4] | |
# ch3: [0x274:0x274+4] | |
# ch4: [0x278:0x278+4] | |
ch_code_per_div = struct.unpack('<l', data[i*4+0x26c:(i+1)*4+0x26c])[0] | |
print(f"ch{i+1}_code_per_div: {ch_code_per_div}") | |
ch = SiglentAnalogChannel(name=f"C{i+1}", enabled=ch_on, | |
volt_div_val=ch_volt_div_val, | |
vert_offset=ch_vert_offset, | |
probe_factor=ch_probe, | |
code_per_div=ch_code_per_div) | |
self.analog_channels += [ch] | |
self.digital_on = struct.unpack('<l', data[0x154:0x158])[0] == 1 | |
print(f"digital_on: {self.digital_on}") | |
for i in range(0, 16): | |
start = i * 4 + 0x158 | |
end = start + 4 | |
d_ch_on = struct.unpack('<l', data[start:end])[0] == 1 | |
d_ch = SiglentDigitalChannel(name=f"D{i}", enabled=d_ch_on) | |
self.digital_channels += [d_ch] | |
print(f"d{i}_on: {d_ch_on}") | |
self.time_div = struct.unpack('<d', data[0x198:0x1a0])[0] | |
self.time_delay = struct.unpack('<d', data[0x1c0:0x1c8])[0] | |
self.wave_length = struct.unpack('<l', data[0x1e8:0x1ec])[0] | |
self.s_rate = struct.unpack('<d', data[0x1ec:0x1f4])[0] | |
self.digital_wave_length = struct.unpack('<l', data[0x214:0x218])[0] | |
# typo in E02A: digital_s_rate is not between 0x208-0x20f | |
self.digital_s_rate = struct.unpack('<d', data[0x218:0x220])[0] | |
print(f"time_div: {self.time_div}") | |
print(f"time_delay: {self.time_delay}") | |
print(f"wave_length: {self.wave_length}") | |
print(f"s_rate: {self.s_rate}") | |
print(f"digital_wave_length: {self.digital_wave_length}") | |
print(f"digital_s_rate: {self.digital_s_rate}") | |
data_width = struct.unpack('<B', data[0x260:0x261])[0] | |
if data_width == 0: | |
print("data_width: byte") | |
self.data_width = 1 | |
elif data_width == 1: | |
print("data_width: word (2 bytes)") | |
self.data_width = 2 | |
else: | |
print(f"unknown data_width: {data_width}") | |
# byte order of waveform data | |
byte_order = struct.unpack('<B', data[0x261:0x262])[0] | |
if byte_order == 0: | |
self.byte_order = 'little' | |
else: | |
self.byte_order = 'big' | |
print(f"byte_order: {self.byte_order}") | |
self.num_hori_div = struct.unpack('<l', data[0x268:0x26c])[0] | |
print(f"num_hori_div: {self.num_hori_div}") | |
for i in range(0, 4): | |
# math_on: | |
# math1: [0x27c:0x27c+4] | |
# math2: [0x280:0x280+4] | |
# math3: [0x284:0x284+4] | |
# math4: [0x288:0x288+4] | |
math_on = struct.unpack('<l', data[i*4+0x27c:(i+1)*4+0x27c])[0] == 1 | |
print(f"math{i+1}_on: {math_on}") | |
# math_vdiv_val | |
# math1: [0x28c:0x28c+8] | |
# math2: [0x2b4:0x2b4+8] | |
# math3: [0x2dc:0x2dc+8] | |
# math4: [0x304:0x304+8] | |
math_vdiv_val = struct.unpack('<d', data[i*0x28+0x28c:i*0x28+0x28c+8])[0] | |
print(f"math{i+1}_vdiv_val: {math_vdiv_val}") | |
# math_vpos_val | |
# math1: [0x32c:0x32c+8] | |
# math2: [0x354:0x354+8] | |
# math3: [0x37c:0x37c+8] | |
# math4: [0x3a4:0x3a4+8] | |
math_vpos_val = struct.unpack('<d', data[i*0x28+0x32c:i*0x28+0x32c+8])[0] | |
print(f"math{i+1}_vpos_val: {math_vpos_val}") | |
# math_store_len (wave_length) | |
# math1: [0x3cc:0x3cc+4] | |
# math2: [0x3d0:0x3d0+4] | |
# math3: [0x3d4:0x3d4+4] | |
# math4: [0x3d8:0x3d8+4] | |
math_store_len = struct.unpack('<l', data[i*0x28+0x3cc:i*0x28+0x3cc+4])[0] | |
print(f"math{i+1}_store_len: {math_store_len}") | |
# math_f_time (time between samples) | |
# math1: [0x3dc:0x3dc+8] | |
# math2: [0x3e4:0x3e4+8] | |
# math3: [0x3ec:0x3ec+8] | |
# math4: [0x3f4:0x3f4+8] | |
math_f_time = struct.unpack('<d', data[i*8+0x3dc:(i+1)*8+0x3dc])[0] | |
print(f"math{i+1}_f_time: {math_f_time}") | |
math_ch = SiglentMathChannel(name=f"Math{i+1}", enabled=math_on, | |
vdiv_val=math_vdiv_val, | |
vert_offset=math_vpos_val, | |
wave_length=math_store_len, | |
f_time=math_f_time) | |
self.math_channels += [math_ch] | |
# math_code_per_div | |
self.math_code_per_div = struct.unpack('<l', data[0x3fc:0x400])[0] | |
print(f"math_code_per_div: {self.math_code_per_div}") | |
wave_data = data[0x800:] | |
print(f"len of wave_data: {len(wave_data)}") | |
center = 2**(8*self.data_width - 1) - 1 | |
wave_idx = 0 | |
for ch in self.analog_channels: | |
if ch.enabled: | |
start = wave_idx * self.data_width * self.wave_length | |
end = (wave_idx+1) * self.data_width * self.wave_length | |
ch_wave_data = wave_data[start:end] | |
print(f"{ch.name} Waveform:") | |
print(f"\tstart: {start}") | |
print(f"\tend: {end}") | |
time = [] | |
voltages = [] | |
v_gain = ch.volt_div_val * ch.probe_factor / ch.code_per_div | |
print(f"\tv_gain: {v_gain}") | |
# process data | |
for i in range(0, self.wave_length): | |
value = int.from_bytes(ch_wave_data[i*self.data_width:(i+1)*self.data_width], byteorder=self.byte_order, signed=False) | |
volt = float(value - center) * v_gain - ch.vert_offset | |
t = i / self.s_rate | |
time += [t] | |
voltages += [volt] | |
# plot waveform | |
plt.figure() | |
plt.xlabel('time') | |
plt.ylabel('V') | |
plt.plot(time, voltages) | |
plt.show() | |
wave_idx += 1 | |
analog_end = end | |
wave_idx = 0 | |
for ch in self.math_channels: | |
if ch.enabled: | |
start = wave_idx * self.data_width * ch.wave_length + analog_end | |
end = (wave_idx+1) * self.data_width * ch.wave_length + analog_end | |
ch_wave_data = wave_data[start:end] | |
print(f"{ch.name} Waveform:") | |
print(f"\tstart: {start}") | |
print(f"\tend: {end}") | |
time = [] | |
voltages = [] | |
v_gain = ch.vdiv_val / self.math_code_per_div | |
print(f"\tv_gain: {v_gain}") | |
# process data | |
for i in range(0, ch.wave_length): | |
value = int.from_bytes(ch_wave_data[i*self.data_width:(i+1)*self.data_width], byteorder=self.byte_order, signed=False) | |
volt = float(value - center) * v_gain - ch.vert_offset | |
t = i * ch.f_time | |
time += [t] | |
voltages += [volt] | |
# plot waveform | |
plt.figure() | |
plt.xlabel('time') | |
plt.ylabel('V') | |
plt.plot(time, voltages) | |
plt.show() | |
wave_idx += 1 | |
math_end = end | |
wave_idx = 0 | |
for ch in self.digital_channels: | |
if ch.enabled: | |
start = (wave_idx * self.digital_wave_length // 8) + math_end | |
end = ((wave_idx+1) * self.digital_wave_length // 8) + math_end | |
ch_wave_data = wave_data[start:end] | |
print(f"{ch.name} Waveform:") | |
print(f"\tstart: {start}") | |
print(f"\tend: {end}") | |
time = [] | |
values = [] | |
# process data | |
for i in range(0, self.wave_length, 8): | |
byte_value = int.from_bytes(ch_wave_data[i:i+1], byteorder=self.byte_order, signed=False) | |
for j in range(0, 8): | |
value = byte_value & 0x1 | |
byte_value = byte_value >> 1 | |
t = (i*8 + j) / self.digital_s_rate | |
time += [t] | |
values += [value] | |
# plot waveform | |
plt.figure() | |
plt.xlabel('time') | |
plt.ylabel('value') | |
plt.plot(time, values) | |
plt.show() | |
wave_idx += 1 | |
def __parse_version_4__(self, data:bytearray): | |
""" | |
Spec details starting at page 37 of E02A document. | |
E02A: https://web.archive.org/web/20230730072643/https://www.siglenteu.com/wp-content/uploads/2021/08/How-to-Extract-Data-from-the-Binary-File.pdf | |
Mostly the same as version 2, except a 4-byte data offset field was | |
inserted at 0x4, shifting everything down by 4 bytes. Waveform data | |
begins at 0x1000. | |
Model+FW that exports version 4 binary data: | |
- SDS5000X | |
- FW newer than 0.9.6 | |
- SDS2000X Plus | |
- FW newer than 1.4.0 | |
- SDS2000X HD | |
- FW: 1.2.1.1 (?) | |
- SDS6000A | |
- FW newer than 1.4.1.0 | |
- SDS6000 H10 Pro | |
- FW newer than 1.4.1.0 | |
- SDS6000 H12 Pro | |
- FW newer than 1.4.1.0 | |
""" | |
version = struct.unpack('<l', data[0x0:0x4])[0] | |
assert version == 4 | |
data_offset_byte = struct.unpack('<l', data[0x4:0x8])[0] | |
print(f"data_offset_byte: {data_offset_byte}") | |
for i in range(0,4): | |
# enable | |
# ch1: [0x8:0x8+4] | |
# ch2: [0xc:0xc+4] | |
# ch3: [0x10:0x10+4] | |
# ch4: [0x14:0x14+4] | |
ch_on = struct.unpack('<l', data[i*4+0x8:(i+1)*4+0x8])[0] == 1 | |
print(f"ch{i+1}_on: {ch_on}") | |
# volt_div_val | |
# ch1: [0x18:0x18+8] | |
# ch2: [0x40:0x40+8] | |
# ch3: [0x68:0x68+8] | |
# ch4: [0x90:0x90+8] | |
ch_volt_div_val = struct.unpack('<d', data[i*0x28+0x18:i*0x28+0x18+8])[0] | |
print(f"ch{i+1}_volt_div_val: {ch_volt_div_val}") | |
# vert_offset | |
# ch1: [0xb8:0xb8+8] | |
# ch2: [0xe0:0xe0+8] | |
# ch3: [0x108:0x108+8] | |
# ch4: [0x130:0x130+8] | |
ch_vert_offset = struct.unpack('<d', data[i*0x28+0xb8:i*0x28+0xb8+8])[0] | |
print(f"ch{i+1}_vert_offset: {ch_vert_offset}") | |
# probe_factor | |
# ch1: [0x244:0x244+8] | |
# ch2: [0x24c:0x24c+8] | |
# ch3: [0x254:0x254+8] | |
# ch4: [0x25c:0x25c+8] | |
ch_probe = struct.unpack('<d', data[i*8+0x244:(i+1)*8+0x244])[0] | |
print(f"ch{i+1}_probe: {ch_probe}") | |
# code_per_div | |
# ch1: [0x270:0x270+4] | |
# ch2: [0x274:0x274+4] | |
# ch3: [0x278:0x278+4] | |
# ch4: [0x27c:0x27c+4] | |
ch_code_per_div = struct.unpack('<l', data[i*4+0x26c:(i+1)*4+0x26c])[0] | |
print(f"ch{i+1}_code_per_div: {ch_code_per_div}") | |
ch = SiglentAnalogChannel(name=f"C{i+1}", enabled=ch_on, | |
volt_div_val=ch_volt_div_val, | |
vert_offset=ch_vert_offset, | |
probe_factor=ch_probe, | |
code_per_div=ch_code_per_div) | |
self.analog_channels += [ch] | |
self.digital_on = struct.unpack('<l', data[0x158:0x15c])[0] == 1 | |
print(f"digital_on: {self.digital_on}") | |
for i in range(0, 16): | |
d_ch_on = struct.unpack('<l', data[i*4 + 0x15c:(i+1)*4+0x15c])[0] == 1 | |
d_ch = SiglentDigitalChannel(name=f"D{i}", enabled=d_ch_on) | |
self.digital_channels += [d_ch] | |
print(f"d{i}_on: {d_ch_on}") | |
self.time_div = struct.unpack('<d', data[0x19c:0x19c+8])[0] | |
self.time_delay = struct.unpack('<d', data[0x1c4:0x1c4+8])[0] | |
self.wave_length = struct.unpack('<l', data[0x1ec:0x1ec+4])[0] | |
self.s_rate = struct.unpack('<d', data[0x1f0:0x1f0+8])[0] | |
self.digital_wave_length = struct.unpack('<l', data[0x218:0x218+4])[0] | |
self.digital_s_rate = struct.unpack('<d', data[0x21c:0x21c+8])[0] | |
print(f"time_div: {self.time_div}") | |
print(f"time_delay: {self.time_delay}") | |
print(f"wave_length: {self.wave_length}") | |
print(f"s_rate: {self.s_rate}") | |
print(f"digital_wave_length: {self.digital_wave_length}") | |
print(f"digital_s_rate: {self.digital_s_rate}") | |
data_width = struct.unpack('<B', data[0x264:0x265])[0] | |
if data_width == 0: | |
print("data_width: byte") | |
self.data_width = 1 | |
elif data_width == 1: | |
print("data_width: word (2 bytes)") | |
self.data_width = 2 | |
else: | |
print(f"unknown data_width: {data_width}") | |
# byte order of waveform data | |
byte_order = struct.unpack('<B', data[0x265:0x266])[0] | |
if byte_order == 0: | |
self.byte_order = 'little' | |
else: | |
self.byte_order = 'big' | |
print(f"byte_order: {self.byte_order}") | |
self.num_hori_div = struct.unpack('<l', data[0x26c:0x26c+4])[0] | |
print(f"num_hori_div: {self.num_hori_div}") | |
for i in range(0, 4): | |
# math_on: | |
# math1: [0x280:0x280+4] | |
# math2: [0x284:0x284+4] | |
# math3: [0x288:0x288+4] | |
# math4: [0x28c:0x28c+4] | |
math_on = struct.unpack('<l', data[i*4+0x280:(i+1)*4+0x280])[0] == 1 | |
print(f"math{i+1}_on: {math_on}") | |
# math_vdiv_val | |
# math1: [0x290:0x290+8] | |
# math2: [0x2b8:0x2b8+8] | |
# math3: [0x2e0:0x2e0+8] | |
# math4: [0x308:0x308+8] | |
math_vdiv_val = struct.unpack('<d', data[i*0x28+0x290:i*0x28+0x290+8])[0] | |
print(f"math{i+1}_vdiv_val: {math_vdiv_val}") | |
# math_vpos_val | |
# math1: [0x330:0x330+8] | |
# math2: [0x358:0x358+8] | |
# math3: [0x380:0x380+8] | |
# math4: [0x3a8:0x3a8+8] | |
math_vpos_val = struct.unpack('<d', data[i*0x28+0x330:i*0x28+0x330+8])[0] | |
print(f"math{i+1}_vpos_val: {math_vpos_val}") | |
# math_store_len (wave_length) | |
# math1: [0x3d0:0x3d0+4] | |
# math2: [0x3d4:0x3d4+4] | |
# math3: [0x3d8:0x3d8+4] | |
# math4: [0x3dc:0x3dc+4] | |
math_store_len = struct.unpack('<l', data[i*0x28+0x3d0:i*0x28+0x3d0+4])[0] | |
print(f"math{i+1}_store_len: {math_store_len}") | |
# math_f_time (time between samples) | |
# math1: [0x3e0:0x3e0+8] | |
# math2: [0x3e8:0x3e8+8] | |
# math3: [0x3f0:0x3f0+8] | |
# math4: [0x3f8:0x3f8+8] | |
math_f_time = struct.unpack('<d', data[i*8+0x3e0:(i+1)*8+0x3e0])[0] | |
print(f"math{i+1}_f_time: {math_f_time}") | |
math_ch = SiglentMathChannel(name=f"Math{i+1}", enabled=math_on, | |
vdiv_val=math_vdiv_val, | |
vert_offset=math_vpos_val, | |
wave_length=math_store_len, | |
f_time=math_f_time) | |
self.math_channels += [math_ch] | |
# math_code_per_div | |
self.math_code_per_div = struct.unpack('<l', data[0x400:0x400+4])[0] | |
print(f"math_code_per_div: {self.math_code_per_div}") | |
wave_data = data[0x1000:] | |
print(f"len of wave_data: {len(wave_data)}") | |
center = 2**(8*self.data_width - 1) - 1 | |
wave_idx = 0 | |
for ch in self.analog_channels: | |
if ch.enabled: | |
start = wave_idx * self.data_width * self.wave_length | |
end = (wave_idx+1) * self.data_width * self.wave_length | |
ch_wave_data = wave_data[start:end] | |
print(f"{ch.name} Waveform:") | |
print(f"\tstart: {start}") | |
print(f"\tend: {end}") | |
time = [] | |
voltages = [] | |
v_gain = ch.volt_div_val * ch.probe_factor / ch.code_per_div | |
print(f"\tv_gain: {v_gain}") | |
# process data | |
for i in range(0, self.wave_length): | |
value = int.from_bytes(ch_wave_data[i*self.data_width:(i+1)*self.data_width], byteorder=self.byte_order, signed=False) | |
volt = float(value - center) * v_gain - ch.vert_offset | |
t = i / self.s_rate | |
time += [t] | |
voltages += [volt] | |
# plot waveform | |
plt.figure() | |
plt.xlabel('time') | |
plt.ylabel('V') | |
plt.plot(time, voltages) | |
plt.show() | |
wave_idx += 1 | |
analog_end = end | |
wave_idx = 0 | |
for ch in self.math_channels: | |
if ch.enabled: | |
start = wave_idx * self.data_width * ch.wave_length + analog_end | |
end = (wave_idx+1) * self.data_width * ch.wave_length + analog_end | |
ch_wave_data = wave_data[start:end] | |
print(f"{ch.name} Waveform:") | |
print(f"\tstart: {start}") | |
print(f"\tend: {end}") | |
time = [] | |
voltages = [] | |
v_gain = ch.vdiv_val / self.math_code_per_div | |
print(f"\tv_gain: {v_gain}") | |
# process data | |
for i in range(0, ch.wave_length): | |
value = int.from_bytes(ch_wave_data[i*self.data_width:(i+1)*self.data_width], byteorder=self.byte_order, signed=False) | |
volt = float(value - center) * v_gain - ch.vert_offset | |
t = i * ch.f_time | |
time += [t] | |
voltages += [volt] | |
# plot waveform | |
plt.figure() | |
plt.xlabel('time') | |
plt.ylabel('V') | |
plt.plot(time, voltages) | |
plt.show() | |
wave_idx += 1 | |
math_end = end | |
wave_idx = 0 | |
for ch in self.digital_channels: | |
if ch.enabled: | |
start = (wave_idx * self.digital_wave_length // 8) + math_end | |
end = ((wave_idx+1) * self.digital_wave_length // 8) + math_end | |
ch_wave_data = wave_data[start:end] | |
print(f"{ch.name} Waveform:") | |
print(f"\tstart: {start}") | |
print(f"\tend: {end}") | |
time = [] | |
values = [] | |
# process data | |
for i in range(0, self.wave_length, 8): | |
byte_value = int.from_bytes(ch_wave_data[i:i+1], byteorder=self.byte_order, signed=False) | |
for j in range(0, 8): | |
value = byte_value & 0x1 | |
byte_value = byte_value >> 1 | |
t = (i*8 + j) / self.digital_s_rate | |
time += [t] | |
values += [value] | |
# plot waveform | |
plt.figure() | |
plt.xlabel('time') | |
plt.ylabel('value') | |
plt.plot(time, values) | |
plt.show() | |
wave_idx += 1 | |
def parse_bin(self): | |
with open(self.bin_file, "rb") as bf: | |
d = bf.read() | |
print(f"bin length: {len(d)}") | |
version = struct.unpack('<l', d[0x0:0x4])[0] | |
print(f"version: {version}") | |
if version == 2: | |
self.__parse_version_2__(d) | |
elif version == 4: | |
self.__parse_version_4__(d) | |
else: | |
print(f"unsupported version: {version}") | |
def create_parser(): | |
parser = ArgumentParser() | |
parser.add_argument('bin', | |
type=str, | |
help='Input Siglent BIN waveform file') | |
return parser | |
if __name__ == '__main__': | |
args = create_parser().parse_args() | |
sb = SiglentBIN(args.bin) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment