.. _StartMeasRef: Starting a measurement ====================== The function :any:`sc_tdc_start_measure2` is used to start a measurement. After calling this function, the device switches into a measurement state. The library receives and processes data from the device in a separate thread, and transfers the results to the application through the data pipes that have been configured in advance. See :ref:`ReceivingDataRef` for more info on how to operate data pipes. Working with hardware-triggered measurements -------------------------------------------- By default, starting of a measurement comes with a certain variable delay, before the hardware actually enters the state of detecting and recording of data. This default behaviour corresponds to the ini file parameter ``ext_trigger`` being set to ``NO``. When the ini file parameter ``ext_trigger`` is set to ``YES``, the hardware waits for an external trigger at the *Sync In* input each time the application calls the :any:`sc_tdc_start_measure2` function --- so this function can be called in advance. As soon as the pulse on the *Sync In* input is received by the hardware, it starts the measurement with a duration as specified in the respective argument passed :any:`sc_tdc_start_measure2`. This is useful for precisely synchronizing the starts of measurements with external devices. Caution: If no pulse occurs on the *Sync In* input, the hardware remains in a waiting state and does not start the measurement. From the software side, the device is already regarded as being in a measurement state, but the end of the measurement is never reached. Working with external start pulses (for time-resolved measurements) ------------------------------------------------------------------- (This subsection applies to TDCs and DLDs but not to cameras). Hardware can be configured to work with external *Start pulses* by setting the ini file parameter ``Ext_Gpx_Start`` to ``YES``. The start of the measurement is not influenced by this setting --- by default, the hardware starts the measurement with a short delay after calling :any:`sc_tdc_start_measure2` and terminates the measurement after the specified exposure. However, for data to be recorded, at least one pulse has to be fed into the *Start In* hardware input. If no such pulse occurs, no data is recorded, such that histogram pipes return empty histograms and USER_CALLBACKS pipes do not deliver any DLD or TDC events. Waiting for the end of a measurement ------------------------------------ The :any:`sc_tdc_start_measure2` function starts a measurement in the background and control is immediately returned back to the user code, before the measurement finishes. There are two general options and two use-case specific options to wait for the end of a measurement. General options: 1. Polling the idle status The application developer can repeatedly call :any:`sc_tdc_get_status2` to ask whether the hardware is still in a measurement. This includes the internal PC-side processing of the scTDC library. The idle state is only reported when the library has finished processing the data stream of the hardware up to the end of the most recently started measurement. Between subsequent calls to :any:`sc_tdc_get_status2`, one typically uses sleep intervals so as to keep the CPU load low. The length of the sleep intervals is chosen as a compromise between fast reaction time and low CPU load. The more frequent you poll, the faster your reaction time for the end of the measurement is. In this sense, polling is always a somewhat inefficient pattern, but it is also easiest to implement. For better performance, read about the next option. 2. Registering an end-of-measurement callback Prior to starting a measurement, the application developer can register a function of his choice that the scTDC library calls when the end of measurement is reached. This registration is done by calling :any:`sc_tdc_set_complete_callback2` and providing a function with the signature ``void cb(void* privateptr, int reason_code);``. The proper end of measurement is indicated, when this function is called with a ``reason_code == 1``. However, as soon as the hardware stops its exposure, even before all of its data has been transferred to the PC and processed by the library, the ``cb`` function may be called with a ``reason_code == 4``. This code 4 comes in addition and prior to the code 1, so the application developer has to handle this case with a separate behaviour -- for example ignoring code 4 and reacting to code 1. Aborted measurements are indicated by ``cb`` invocations with ``reason_code == 2``, and ``reason_code == 3``. The reason codes have macro definitions in :ref:`file_scTDC_error_codes.h` (``SC_TDC_INFO_MEAS_COMPLETE``, ``SC_TDC_INFO_USER_INTERRUPT``, ``SC_TDC_INFO_BUFFER_FULL``, ``SC_TDC_INFO_HW_IDLE``) Use-case specific options: 3. Reading histogram data or reading statistics data If your application has configured a pipe that generates histograms or the statistics pipe, you will use :any:`sc_pipe_read2` to read the respective data. This function can be called with the timeout set to something much longer than the measurement time. As soon as the end of the measurement is reached, histogram data and statistics data become available and the function returns at this moment. This can be used to trigger any actions the application should perform with the data and also to trigger the start of the next measurement. 4. Reading event data from the `USER_CALLBACKS` pipe and reacting to its `end_of_measure` callback If your application reads event data via the `USER_CALLBACKS` pipe, one of the callback functions you can register for, notifies you when the end-of-measurement control sign is encountered by the internal hardware protocol decoder of the scTDC library. This control sign appears as the last thing of a measurement, so all measurement data and statistics data have already been processed by the library. However, some internal threads of the library may not have switched to the idle state. It is not possible to start a new measurement directly from the callback function. Instead, you can use thread synchronization mechanisms such as *semaphores* or *condition variables* to notify your main thread, that all data is available and possibly a new measurement can be started. Running sequences of measurements --------------------------------- After waiting for the end of a measurement, you may decide to start the next measurement, as soon as possible, thus establishing a sequence of measurements. Depending on how you waited for the end of the measurement you may run into a ``SC_TDC_ERR_NOTRDY`` (:ref:`file_scTDC_error_codes.h`) returned by calling :any:`sc_tdc_start_measure2`. This does not happen if you used the polling-for-idle-status mechanism, but it can happen with the other options discussed in the previous section. To make your sequence more robust, you can call :any:`sc_tdc_start_measure2` multiple times with a thread-yield (meaning your thread pauses for a minimal time until it is scheduled again by the operating system) in between until this function returns zero, indicating success, or some other error than ``SC_TDC_ERR_NOTRDY`` (in that case you should stop retrying).