d6a56266b7
Groundwork for burst acquisition: the scope needs to report and transfer a whole multi-row FastFrame acquisition, and the BBD needs to gate its trigger output per row rather than staying armed for the scan. tektronix_base - get_fastframe_max_frames() exposes HORizontal:FASTframe:MAXFRames?, which is what sizes a burst once the horizontal settings are fixed. - transfer_fastframe_bulk() pulls a burst as one contiguous buffer. Unlike transfer_fastframe it does not assume how the scope frames the response: it accumulates until the expected byte count is reached, so one large IEEE block and one block per frame both work. - set_data_encoding() / set_data_width() make the transfer format settable instead of inherited from whatever the front panel was left on. - read_raw() had two real defects. The length-digit read used a bare recv() and only checked the length afterwards, so a short read raised "Failed to read data length" on a perfectly good transfer; it now goes through a _recv_exact() helper, as does the trailing separator. And a #0 indeterminate-length block was parsed as int("") -> ValueError. #0 is normally delimited by EOI, which a raw socket never sees, so read_raw now takes expected_bytes to size it. The bulk transfer relies on this. pybbd202 - arm_scan_gate(axis, armed) raises and drops the max-velocity trigger output the scope's AND-gate uses. A burst spans several rows with the scope running throughout, so the gate must be low for the flyback or the return move reaches max velocity and injects frames between rows. - set_trigger_verified() reads the mode back after setting it. set_trigger is fire-and-forget over the shared TX queue; burst mode toggles the gate between every row, where a dropped change silently corrupts the file rather than failing loudly. - set_trigger_gate_off() so the scan can leave the output idle on exit. - TRIGOUT_GATE_OFF is deliberately marked unverified. §7.6 of the BBD203 protocol doc describes `mode` as an enumeration capping at 0x11, which contradicts the bitmask this driver actually sends (TRIGOUT_MAXV = 0x90, known working), so the doc cannot settle which value idles the pin low. The engine's preflight check resolves it on the rig instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
65 lines
2.1 KiB
Python
Executable File
65 lines
2.1 KiB
Python
Executable File
'''
|
|
APT Constants and Registries
|
|
Thomas Ales | Feb 2026
|
|
'''
|
|
from enum import IntFlag
|
|
|
|
class StatusBits(IntFlag):
|
|
MOT_SB_CWHARDLIMIT = 0x01
|
|
MOT_SB_CCWHARDLIMIT = 0x02
|
|
MOT_SB_INMOTIONCW = 0x10
|
|
MOT_SB_INMOTIONCCW = 0x20
|
|
MOT_SB_HOMING = 0x200
|
|
MOT_SB_HOMED = 0x400
|
|
MOT_SB_TRACKING = 0x1000
|
|
MOT_SB_SETTLED = 0x2000
|
|
MOT_SB_POSITIONERROR = 0x4000
|
|
MOT_SB_INSTRERROR = 0x8000
|
|
MOT_SB_INTERLOCK = 0x10000
|
|
MOT_SB_OVERTEMP = 0x20000
|
|
MOT_SB_BUSVOLTFAULT = 0x40000
|
|
MOT_SB_COMMUTATIONERROR = 0x80000
|
|
MOT_SB_DIGIP1 = 0x100000
|
|
MOT_SB_OVERLOAD = 0x1000000
|
|
MOT_SB_POWEROK = 0x10000000
|
|
MOT_SB_ERROR = 0x40000000
|
|
MOT_SB_ENABLED = 0x80000000
|
|
|
|
# combined masks for checking various
|
|
# states
|
|
MOT_ANY_MOVE = MOT_SB_INMOTIONCW | MOT_SB_INMOTIONCCW
|
|
MOT_ANY_ERR = (MOT_SB_OVERTEMP | MOT_SB_BUSVOLTFAULT |
|
|
MOT_SB_COMMUTATIONERROR | MOT_SB_OVERLOAD |
|
|
MOT_SB_ERROR | MOT_SB_INSTRERROR)
|
|
|
|
class TriggerBitsServo(IntFlag):
|
|
TRIGIN_HIGH = 0x01
|
|
TRIGIN_RELMOVE = 0x02
|
|
TRIGIN_ABSMOVE = 0x04
|
|
TRIGIN_HOMEMOVE = 0x08
|
|
TRIGOUT_HIGH = 0x10
|
|
TRIGOUT_INMOTION = 0x20
|
|
TRIGOUT_MOTIONCOMPLETE = 0x40
|
|
TRIGOUT_MAXVELOCITY = 0x80
|
|
|
|
TRIGOUT_MAXV = TRIGOUT_HIGH | TRIGOUT_MAXVELOCITY
|
|
|
|
|
|
# Gate off: no trigger-out function selected, so the pin idles inactive.
|
|
#
|
|
# Treat this as unverified until it has been checked on the rig. §7.6 of
|
|
# docs/hardware/BBD203_Communications_Protocol.md documents `mode` as an
|
|
# enumeration capping at 0x11, which flatly contradicts the bitmask this
|
|
# driver actually sends (TRIGOUT_MAXV = 0x90, known working), so the doc
|
|
# cannot settle what makes the pin idle low. Under the bitmask reading 0x00
|
|
# clears everything and the pin sits low. If instead TRIGOUT_HIGH is an
|
|
# active-high *polarity* bit, clearing it means active-low and the pin idles
|
|
# HIGH — which in burst mode floods the acquisition with flyback frames.
|
|
# ScanEngine's gate-off preflight catches that; if it trips, change this to
|
|
# TriggerBitsServo.TRIGOUT_HIGH.
|
|
TRIGOUT_GATE_OFF = TriggerBitsServo(0)
|
|
|
|
|
|
|
|
|