Skip to content

Example: GPIO width trigger

The Protocol Exerciser can arm a GPIO width trigger on supported pins and deliver a global event when the measured pulse matches the configured rules. Use AqProtocolExerciser.set_gpio_trigger to arm the hardware and register a handler for the event name gpio_trigger. The payload is carried on PxEventMsg.global_event.gpio_trigger as PxGpioTriggerEvent (see aqpxlib.gpio or aqpxlib.event).

Constraints

  • Pins: Width trigger and pulse generation are only supported on GPIO indices 8 and 9 (the same restriction as send_gpio_pulse).
  • Durations: min_duration_ns and max_duration_ns must each be greater than 5 ns and less than 1 s.
  • Events: Subscribe by registering a handler for the logical name gpio_trigger on the exerciser session. This is a global event, not a per-device event.

Configure the trigger

Call set_gpio_trigger with:

Argument Meaning
gpio_idx Pin index (8 or 9).
min_duration_ns / max_duration_ns Pulse width window in nanoseconds.
low_pulse Consider low-going pulses when True.
high_pulse Consider high-going pulses when True.
mode PxGpioWidthTriggerMode.TRIGGER_PULSE_WIDTH_IN_RANGE (default) or TRIGGER_PULSE_WIDTH_OUT_OF_RANGE.

The mode selects whether a fire occurs when the width is inside or outside the [min, max] interval.

Handle gpio_trigger

Handlers receive a PxEventMsg. The payload is under global_event.gpio_trigger (PxGpioTriggerEvent):

Field Type Meaning
pin_idx int Pin index that caused the trigger.
pulse_duration int Measured width (nanoseconds).
pulse_polarity bool Polarity of the detected pulse.

Example

The script below arms a width-in-range trigger on pin 8, registers a handler, then emits a short pulse with send_gpio_pulse so the handler runs. Replace the pulse call with your own stimulus if you drive the pin from external equipment.

run_gpio_trigger_example.py
import logging
import threading

from aqpxlib import AqProtocolExerciser, PxGpioWidthTriggerMode, PxIoState
from aqpxlib.event import PxEventMsg

logger = logging.getLogger(__name__)


def run_gpio_trigger_example() -> None:
    with AqProtocolExerciser.connect(port=60600) as px:
        done = threading.Event()

        def on_gpio_trigger(event_msg: PxEventMsg) -> None:
            g = event_msg.global_event.gpio_trigger
            logger.info(
                "GPIO trigger: pin=%d duration_ns=%d polarity=%s",
                g.pin_idx,
                g.pulse_duration,
                g.pulse_polarity,
            )
            done.set()

        px.add_event_handler("gpio_trigger", on_gpio_trigger)

        pin = 8
        px.set_gpio_trigger(
            gpio_idx=pin,
            min_duration_ns=500,
            max_duration_ns=50_000,
            low_pulse=True,
            high_pulse=True,
            mode=PxGpioWidthTriggerMode.TRIGGER_PULSE_WIDTH_IN_RANGE,
        )

        px.send_gpio_pulse(
            gpio_idx=pin,
            active_state=PxIoState.HIGH,
            idle_state=PxIoState.LOW,
            active_time_ns=5000,
        )

        assert done.wait(timeout=3), "GPIO trigger event not received"


if __name__ == "__main__":
    logging.basicConfig(format="[%(levelname)s] %(message)s")
    logger.setLevel(logging.INFO)
    run_gpio_trigger_example()

Run:

python run_gpio_trigger_example.py

See also