diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst index 40fec5f56..ed9ca7ca5 100644 --- a/RELEASE_NOTES.rst +++ b/RELEASE_NOTES.rst @@ -46,6 +46,7 @@ Highlights: * MSYS2 packaging for Windows, which replaces Conda. Conda packages are still available to support legacy installations, but may be removed in a future release. * Experiments can now be submitted with revisions set to a branch / tag name instead of only git hashes. +* Grabber image input now has an optional timeout Breaking changes: diff --git a/artiq/coredevice/grabber.py b/artiq/coredevice/grabber.py index 518a5b12a..c17486514 100644 --- a/artiq/coredevice/grabber.py +++ b/artiq/coredevice/grabber.py @@ -2,7 +2,7 @@ from numpy import int32, int64 from artiq.language.core import * from artiq.language.types import * -from artiq.coredevice.rtio import rtio_output, rtio_input_data +from artiq.coredevice.rtio import rtio_output, rtio_input_timestamped_data class OutOfSyncException(Exception): @@ -11,6 +11,11 @@ class OutOfSyncException(Exception): pass +class GrabberTimeoutException(Exception): + """Raised when a timeout occurs while attempting to read Grabber RTIO input events.""" + pass + + class Grabber: """Driver for the Grabber camera interface.""" kernel_invariants = {"core", "channel_base", "sentinel"} @@ -82,10 +87,10 @@ class Grabber: self.gate_roi(0) @kernel - def input_mu(self, data): + def input_mu(self, data, timeout_mu=-1): """ Retrieves the accumulated values for one frame from the ROI engines. - Blocks until values are available. + Blocks until values are available or timeout is reached. The input list must be a list of integers of the same length as there are enabled ROI engines. This method replaces the elements of the @@ -95,15 +100,25 @@ class Grabber: If the number of elements in the list does not match the number of ROI engines that produced output, an exception will be raised during this call or the next. + + If the timeout is reached before data is available, a RuntimeError is + raised. + + :param timeout_mu: Timestamp at which a timeout will occur. Set to -1 + (default) to disable timeout. """ channel = self.channel_base + 1 - sentinel = rtio_input_data(channel) + timestamp, sentinel = rtio_input_timestamped_data(timeout_mu, channel) + if timestamp == -1: + raise GrabberTimeoutException("Timeout before Grabber frame available") if sentinel != self.sentinel: raise OutOfSyncException for i in range(len(data)): - roi_output = rtio_input_data(channel) + timestamp, roi_output = rtio_input_timestamped_data(timeout_mu, channel) if roi_output == self.sentinel: raise OutOfSyncException + if timestamp == -1: + raise GrabberTimeoutException("Timeout retrieving ROIs") data[i] = roi_output