4.5. Commands for streaming acquisition
Prev | 4. Acquisition and configuration functions | Next

### 4.5. Commands for streaming acquisition

The most powerful Comedi acquisition primitive is the command. It's powerful because, with one single command, the programmer launches:

- a possibly infinite sequence of acquisitions,

- accompanied with various callback functionalities (DMA, interrupts, driver-specific callback functions),

- for any number of channels,

- with an arbitrary order of channels in each scan (possibly even with repeated channels per scan),

- and with various scan triggering sources, external (i.e., hardware pulses) as well as internal (i.e., pulses generated on the DAQ card itself, or generated by a software trigger instruction).

This command functionality exists in the Comedi API, because various data acquisition devices have the capability to perform this kind of complex acquisition, driven by either on-board or off-board timers and triggers.

A command specifies a particular data acquisition sequence, which consists of a number of scans, and each scan is comprised of a number of conversions, which usually corresponds to a single A/D or D/A conversion. So, for example, a scan could consist of sampling channels 1, 2 and 3 of a particular device, and this scan should be repeated 1000 times, at intervals of 1 millisecond apart.

The command function is complementary to the configuration instruction function: each channel in the command's `chanlist` should first be configured by an appropriate instruction.

#### 4.5.1. Executing a command

A command is executed by the function `comedi_command`:

`int comedi_command(` | comedi_t *device,
| comedi_cmd *command`)`;

The following sections explain the meaning of the comedi_cmd data structure. Filling in this structure can be quite complicated, and requires good knowledge about the exact functionalities of the DAQ card. So, before launching a command, the application programmer is adviced to check whether this complex command data structure can be successfully parsed. So, the typical sequence for executing a command is to first send the command through `comedi_command_test` once or twice. The test will check that the command is valid for the particular device, and often makes some adjustments to the command arguments, which can then be read back by the user to see the actual values used.

A Comedi program can find out on-line what the command capabilities of a specific device are, by means of the `comedi_get_cmd_src_mask` function.

#### 4.5.2. The command data structure

The command executes according to the information about the requested acquisition, which is stored in the comedi_cmd data structure:

    typedef struct comedi_cmd_struct comedi_cmd;

    struct comedi_cmd_struct {
      unsigned int subdev;         // which subdevice to sample
      unsigned int flags;          // encode some configuration possibilities
                                   // of the command execution; e.g.,
                                   // whether a callback routine is to be
                                   // called at the end of the command

      unsigned int start_src;      // event to make the acquisition start
      unsigned int start_arg;      // parameters that influence this start

      unsigned int scan_begin_src; // event to make a particular scan start
      unsigned int scan_begin_arg; // parameters that influence this start`

      unsigned int convert_src;    // event to make a particular conversion start
      unsigned int convert_arg;    // parameters that influence this start

      unsigned int scan_end_src;   // event to make a particular scan terminate
      unsigned int scan_end_arg;   // parameters that influence this termination

      unsigned int stop_src;       // what make the acquisition terminate
      unsigned int stop_arg;       // parameters that influence this termination

      unsigned int *chanlist;      // pointer to list of channels to be sampled
      unsigned int chanlist_len;   // number of channels to be sampled

      sampl_t *data;               // address of buffer
      unsigned int data_len;       // number of samples to acquire
    };

The start and end of the whole command acquisition sequence, and the start and end of each scan and of each conversion, is triggered by a so-called event. More on these in Section 4.5.3.

The `subdev` member of the comedi_cmd structure is the index of the subdevice the command is intended for. The `comedi_find_subdevice_by_type` function can be useful in discovering the index of your desired subdevice.

The `chanlist` member of the comedi_cmd data structure should point to an array whose number of elements is specified by `chanlist_len` (this will generally be the same as the `scan_end_arg`). The `chanlist` specifies the sequence of channels and gains (and analog references) that should be stepped through for each scan. The elements of the `chanlist` array should be initialized by “packing” the channel, range and reference information together with the `CR_PACK` macro.

The `data` and `data_len` members can be safely ignored when issueing commands from a user-space program. They only have meaning when a command is sent from a kernel module using the `kcomedilib` interface, in which case they specify the buffer where the driver should write/read its data to/from.

The final member of the comedi_cmd structure is the `flags` field, i.e., bits in a word that can be bitwise-or'd together. The meaning of these bits are explained in Section 4.5.4.

#### 4.5.3. The command trigger events

A command is a very versatile acquisition instruction, in the sense that it offers lots of possibilities to let different hardware and software sources determine when acquisitions are started, performed, and stopped. More specifically, the command data structure has five types of events: start the acquisition, start a scan, start a conversion, stop a scan, and stop the acquisition. Each event can be given its own source (the `…_src` members in the comedi_cmd data structure). And each event source can have a corresponding argument (the `…_arg` members of the comedi_cmd data structure) whose meaning depends on the type of source trigger. For example, to specify an external digital line “3” as a source (in general, any of the five event sources), you would use `src`=`TRIG_EXT` and `arg`=`3`.

The following paragraphs discuss in somewhat more detail the trigger event sources(`…_src`), and the corresponding arguments (`…_arg`).

The start of an acquisition is controlled by the `start_src` events. The available options are:

- `TRIG_NOW`: the “start” event occurs `start_arg` nanoseconds after the command is set up. Currently, only `start_arg`=`0` is supported.

- `TRIG_FOLLOW`: (For an output device.) The “start” event occurs when data is written to the buffer.

- `TRIG_EXT`: the “start” event occurs when an external trigger signal occurs; e.g., a rising edge of a digital line. `start_arg` chooses the particular digital line.

- `TRIG_INT`: the “start” event occurs on a Comedi internal signal, which is typically caused by an `INSN_INTTRIG` instruction.

The start of the beginning of each scan is controlled by the `scan_begin_src` events. The available options are:

- `TRIG_TIMER`: “scan begin” events occur periodically. The time between “scan begin” events is `scan_begin_arg` nanoseconds.

- `TRIG_FOLLOW`: The “scan begin” event occurs immediately after a “scan end” event occurs.

- `TRIG_EXT`: the “scan begin” event occurs when an external trigger signal occurs; e.g., a rising edge of a digital line. `scan_begin_arg` chooses the particular digital line.

The `scan_begin_arg` used here may not be supported exactly by the device, but it will be adjusted to the nearest supported value by `comedi_command_test`.

The timing between each sample in a scan is controlled by the `convert_src` events. The available options are:

- `TRIG_TIMER`: the conversion events occur periodically. The time between “convert” events is `convert_arg` nanoseconds.

- `TRIG_EXT`: the conversion events occur when an external trigger signal occurs, e.g., a rising edge of a digital line. `convert_arg` chooses the particular digital line.

- `TRIG_NOW`: All conversion events in a scan occur simultaneously.

The end of each scan is almost always specified by setting the `scan_end_src` event to `TRIG_COUNT`, with the argument being the same as the number of channels in the `chanlist`. You could probably find a device that allows something else, but it would be strange.

The end of an acquisition is controlled by `stop_src` event. The available options are:

- `TRIG_COUNT`: stop the acquisition after `stop_arg` scans.

- `TRIG_NONE`: perform continuous acquisition, until stopped using `comedi_cancel`.

  `stop_arg` is used to denote how many samples should be used in the continuous acquisition. If `stop_arg` is set to `0`, the entire output buffer may contribute to the output. If `stop_arg` != `0`, only the memory for `stop_arg` samples will be used. Many drivers do not yet support `stop_arg`!=`0` and should enforce `stop_arg`=`0` via comedi_command_test.

There are a couple of less usual or not yet implemented events:

- `TRIG_TIME`: cause an event to occur at a particular time.

  (This event source is reserved for future use.)

- `TRIG_OTHER`: driver specific event trigger.

  This event can be useful as any of the trigger sources. Its exact meaning is driver specific, because it implements a feature that otherwise does not fit into the generic Comedi command interface. Configuration of `TRIG_OTHER` features are done by `INSN_CONFIG` instructions.

  The argument is reserved and should be set to `0`.

Not all event sources are applicable to all events. Supported trigger sources for specific events depend significantly on your particular device, and even more on the current state of its device driver. The `comedi_get_cmd_src_mask` function is useful for determining what trigger sources a subdevice supports.

#### 4.5.4. The command flags

The `flags` field in the command data structure is used to specify some “behaviour” of the acquisitions in a command. The meaning of the field is as follows:

- `TRIG_RT`: ask the driver to use a hard real-time interrupt handler. This will reduce latency in handling interrupts from your data aquisition hardware. It can be useful if you are sampling at high frequency, or if your hardware has a small onboard data buffer. You must have a real-time kernel (RTAI or RTLinux/GPL) and must compile Comedi with real-time support, or this flag will do nothing.

- `TRIG_WAKE_EOS`: where “EOS” stands for “End of Scan”. Some drivers will change their behaviour when this flag is set, trying to transfer data at the end of every scan (instead of, for example, passing data in chunks whenever the board's hardware data buffer is half full). This flag may degrade a driver's performance at high frequencies, because the end of a scan is, in general, a much more frequent event than the filling up of the data buffer.

- `TRIG_ROUND_NEAREST`: round to nearest supported timing period, the default. This flag (as well as the following three), indicates how timing arguments should be rounded if the hardware cannot achieve the exact timing requested.

- `TRIG_ROUND_DOWN`: round period down.

- `TRIG_ROUND_UP`: round period up.

- `TRIG_ROUND_UP_NEXT`: this one doesn't do anything, and I don't know what it was intended to do…?

- `TRIG_DITHER`: enable dithering? Dithering is a software technique to smooth the influence of discretization “noise”.

- `TRIG_DEGLITCH`: enable deglitching? Another “noise” smoothing technique.

- `TRIG_WRITE`: write to bidirectional devices. Could be useful, in principle, if someone wrote a driver that supported commands for a digital I/O device that could do either input or output.

- `TRIG_BOGUS`: do the motions?

- `TRIG_CONFIG`: perform configuration, not triggering. This is a legacy of the deprecated comedi_trig_struct data structure, and has no function at present.

#### 4.5.5. Anti-aliasing

If you wish to aquire accurate waveforms, it is vital that you use an anti-alias filter. An anti-alias filter is a low-pass filter used to remove all frequencies higher than the Nyquist frequency (half your sampling rate) from your analog input signal before you convert it to digital. If you fail to filter your input signal, any high frequency components in the original analog signal will create artifacts in your recorded digital waveform that cannot be corrected.

For example, suppose you are sampling an analog input channel at a rate of 1000 Hz. If you were to apply a 900 Hz sine wave to the input, you would find that your sampling rate is not high enough to faithfully record the 900 Hz input, since it is above your Nyquist frequency of 500 Hz. Instead, what you will see in your recorded digital waveform is a 100 Hz sine wave! If you don't use an anti-alias filter, it is impossible to tell whether the 100 Hz sine wave you see in your digital signal was really produced by a 100 Hz input signal, or a 900 Hz signal aliased to 100 Hz, or a 1100 Hz signal, etc.

In practice, the cutoff frequency for the anti-alias filter is usually set 10% to 20% below the Nyquist frequency due to fact that real filters do not have infinitely sharp cutoffs.

Prev | Up | Next
4.4. Instruction for internal triggering | Home | 4.6. Slowly-varying inputs