Initial commit: merge nuescan, pymso, pybbd202, and pypewpewhops into scanengine-3

- Merged four separate hardware control projects into unified platform
- Created unified requirements.txt with all dependencies
- Added comprehensive .gitignore
- Added project overview README

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Thomas Ales [M S E]
2026-01-16 20:11:31 -06:00
commit fc43fbe4b0
65 changed files with 19127 additions and 0 deletions
+119
View File
@@ -0,0 +1,119 @@
#!/usr/bin/env python3
"""
Simple FastFrame test - minimal setup.
"""
import time
from tektronix_base import TektronixOscilloscopeBase
def main():
scope_ip = "192.168.10.105"
print(f"Connecting to {scope_ip}...")
scope = TektronixOscilloscopeBase(resource_name=scope_ip, timeout=20.0)
try:
scope.connect()
print(f"Connected: {scope.identify()}\n")
# Configure CH1 (same as failing test)
print("Configuring CH1...")
scope.set_channel_scale(1, 0.1)
scope.set_channel_offset(1, 0.0)
scope.set_channel_coupling(1, 'DC')
scope.set_channel_termination(1, 50)
# Configure horizontal (same as failing test)
print("Configuring horizontal...")
scope.set_record_length(5000)
scope.set_time_scale(80e-9)
actual_record_length = scope.get_record_length()
actual_time_scale = scope.get_time_scale()
actual_sample_rate = scope.get_sample_rate()
print(f" Record: {actual_record_length}, Time: {actual_time_scale*1e9:.0f}ns/div, Rate: {actual_sample_rate/1e6:.1f}MS/s")
# Configure trigger (same as failing test)
print("Configuring trigger...")
scope.set_trigger_source('CH1')
scope.set_trigger_level(1, 0.1)
scope.set_trigger_slope('RISE')
scope.set_trigger_mode('NORMAL')
scope.set_trigger_coupling('DC')
# Enable FastFrame with 1000 frames
print("Enabling FastFrame (1000 frames)...")
scope.set_fastframe_state(True)
scope.set_fastframe_count(1000)
ff_state = scope.get_fastframe_state()
ff_count = scope.get_fastframe_count()
print(f" State: {ff_state}, Count: {ff_count}")
# Configure data transfer (same as failing test)
print("Configuring data transfer...")
scope.set_data_encoding('RIBinary')
scope.set_wfmoutpre_encoding('BINary')
scope.set_wfmoutpre_byte_count(1)
scope.set_wfmoutpre_byte_order('MSB')
scope.set_data_source('CH1')
# Acquire
print("Acquiring...")
scope.write("ACQuire:STATE RUN")
time.sleep(2) # Wait for triggers
scope.write("ACQuire:STATE STOP")
time.sleep(0.5)
# Check record length
record_len = scope.get_record_length()
print(f"Record length: {record_len}")
# Test: Send single CURVe? and read ALL frames
print(f"\nTesting: Send one CURVe? and read all {ff_count} frames...")
scope.set_fastframe_selected(1) # Start from frame 1
scope.write("CURVe?")
all_waveforms = []
start_time = time.time()
for frame_num in range(1, ff_count + 1):
if frame_num == 1 or frame_num % 100 == 0:
elapsed = time.time() - start_time
if frame_num > 1:
rate = frame_num / elapsed
print(f" Frame {frame_num}/{ff_count} - {rate:.1f} fps")
else:
print(f" Frame {frame_num}/{ff_count}...")
# Read one frame using read_raw (no new CURVe? command)
curve_bytes = scope.read_raw()
waveform = scope.parse_curve_data(curve_bytes, byte_count=1, signed=True)
all_waveforms.append(waveform)
end_time = time.time()
total_time = end_time - start_time
print(f"\nTransferred {len(all_waveforms)} frames in {total_time:.2f}s")
print(f"Rate: {ff_count / total_time:.1f} frames/s")
print(f"Points per frame: {len(all_waveforms[0])}")
print(f"First frame: min={min(all_waveforms[0])}, max={max(all_waveforms[0])}")
print(f"Last frame: min={min(all_waveforms[-1])}, max={max(all_waveforms[-1])}")
except Exception as e:
print(f"\nError: {type(e).__name__}: {e}")
import traceback
traceback.print_exc()
finally:
if scope.is_connected:
try:
scope.set_fastframe_state(False)
print("FastFrame disabled")
except:
pass
scope.disconnect()
print("Disconnected")
if __name__ == "__main__":
main()