number stimulus outputs in device stage order
The output index now equals the device stage, so outputs follow the order the device measures them: master port 1 through its switch positions, then port 2. The previous position-major numbering permuted the middle two against the physical order, so data captured before this needs its calibration re-captured.
This commit is contained in:
@@ -399,20 +399,32 @@ class PerPointStimulusSwitchingTest(unittest.TestCase):
|
||||
|
||||
def test_two_positions_give_four_outputs(self) -> None:
|
||||
channels = build_output_channels((1, 2), 2)
|
||||
# Outputs are switch-position-major, so outputs 0/1 stay exactly what they are
|
||||
# without switching; stages are port-major, matching the bitstream taking the
|
||||
# port from the stage counter's UPPER bits.
|
||||
# Port-major in BOTH numbers: the output index is the device stage, so outputs
|
||||
# come in the order the device measures them — port 1 through its switch
|
||||
# positions, then port 2. Verified against a scope on the switch line.
|
||||
self.assertEqual(
|
||||
[(c.index, c.stimulus_port, c.stage_index) for c in channels],
|
||||
[(0, 1, 0), (1, 2, 2), (2, 1, 1), (3, 2, 3)],
|
||||
[(0, 1, 0), (1, 1, 1), (2, 2, 2), (3, 2, 3)],
|
||||
)
|
||||
|
||||
def test_output_index_is_the_device_stage(self) -> None:
|
||||
# The whole point of the 2026-09-17 renumbering: an operator hanging antennas
|
||||
# sees stage order on a scope, and the output numbering must not permute it.
|
||||
for substage_count in (1, 2, 4):
|
||||
channels = build_output_channels((1, 2), substage_count)
|
||||
self.assertEqual(
|
||||
[c.index for c in channels],
|
||||
[c.stage_index for c in channels],
|
||||
msg=f"substages={substage_count}",
|
||||
)
|
||||
self.assertEqual([c.index for c in channels], list(range(len(channels))))
|
||||
|
||||
def test_switch_position_is_the_low_stage_bit(self) -> None:
|
||||
# This is what lets the controller just invert its pin on every trigger cycle
|
||||
# instead of tracking an absolute stage number.
|
||||
channels = build_output_channels((1, 2), 2)
|
||||
for channel in channels:
|
||||
expected_position = channel.index // 2 # switch-position-major output order
|
||||
expected_position = channel.index & 1
|
||||
self.assertEqual(channel.stage_index & 1, expected_position)
|
||||
|
||||
def test_stage_budget_is_enforced(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user