4. Acquisition and configuration functions
Prev |  | Next

## 4. Acquisition and configuration functions

This Section gives an overview of all Comedi functions with which application programmers can implement their data acquisition. (With “acquisition” we mean all possible kinds of interfacing with the cards: input, output, configuration, streaming, etc.) Section 5 explains the function calls in full detail.

### 4.1. Functions for single acquisition

The simplest form of using Comedi is to get one single sample to or from an interface card. This sections explains how to do such simple digital and analog acquisitions.

#### 4.1.1. Single digital acquisition

Many boards supported by Comedi have digital input and output channels; i.e., channels that can only produce a `0` or a `1`. Some boards allow the direction (input or output) of each channel to be specified independently in software.

Comedi groups digital channels into a subdevice, which is a group of digital channels that have the same characteristics. For example, digital output lines will be grouped into a digital output subdevice, bidirectional digital lines will be grouped into a digital I/O subdevice. Thus, there can be multiple digital subdevices on a particular board.

Individual bits on a digital I/O device can be read and written using the functions `comedi_dio_read` and `comedi_dio_write`:

`int comedi_dio_read(` | comedi_t *device,
| unsigned int subdevice,
| unsigned int channel,
| unsigned int *bit`)`;

`int comedi_dio_write(` | comedi_t *device,
| unsigned int subdevice,
| unsigned int channel,
| unsigned int bit`)`;

The `device` parameter is a pointer to a successfully opened Comedi device. The `subdevice` and `channel` parameters are positive integers that indicate which subdevice and channel is used in the acquisition. The integer `bit` contains the value of the acquired bit.

The direction of bidirectional lines can be configured using the function `comedi_dio_config`:

`int comedi_dio_config(` | comedi_t *device,
| unsigned int subdevice,
| unsigned int channel,
| unsigned int dir`)`;

The parameter `dir` should be either `COMEDI_INPUT` or `COMEDI_OUTPUT`. Many digital I/O subdevices group channels into blocks for configuring direction. Changing one channel in a block changes the entire block.

Multiple channels can be read and written simultaneously using the function `comedi_dio_bitfield2`:

`int comedi_dio_bitfield2(` | comedi_t *device,
| unsigned int subdevice,
| unsigned int write_mask,
| unsigned int *bits,
| unsigned int base_channel`)`;

Each channel from `base_channel` to `base_channel` + `31` is assigned to a bit in the `write_mask` and `bits` bitfield with bit 0 assigned to channel `base_channel`, bit 1 assigned to channel `base_channel` + `1`, etc. If a bit in `write_mask` is set, the corresponding bit in `*bits` will be written to the digital output line corresponding to the channel given by `base_channel` plus the bit number. Each digital line is then read and placed into `*bits`. The value of bits in `*bits` corresponding to digital output lines is undefined and device-specific. Channel `base_channel` + `0` is the least significant bit in the bitfield. No more than 32 channels at once can be accessed using this method. Warning! Older versions of Comedi may ignore `base_channel` and treat it as `0` unless the subdevice has more than 32 channels.

The digital acquisition functions seem to be very simple, but, behind the implementation screens of the Comedi kernel module, they are executed as special cases of the general instruction command.

#### 4.1.2. Single analog acquisition

Analog Comedi channels can produce data values that are samples from continuous analog signals. These samples are integers with a significant content in the range of, typically, 8, 10, 12, or 16 bits.

Single samples can be read from an analog channel using the function `comedi_data_read`:

`int comedi_data_read(` | comedi_t *device,
| unsigned int subdevice,
| unsigned int channel,
| unsigned int range,
| unsigned int aref,
| lsampl_t *data`)`;

This reads one such data value from a Comedi channel, and puts it in the user-specified `data` buffer.

The `range` parameter is the zero-based index of one of the gain ranges supported by the channel. This is a number from 0 to N-1 where N is the number of ranges supported by the channel. Use the function `comedi_get_n_ranges` to get the number of ranges supported by the channel, the function `comedi_find_range` to search for a suitable range, or the function `comedi_get_range` to get the details of a supported range.

The `aref` parameter specifies an analog reference to use: `AREF_GROUND`, `AREF_COMMON`, `AREF_DIFF`, or `AREF_OTHER`. Use the function `comedi_get_subdevice_flags` to see which analog references are supported by the subdevice.

In the opposite direction, single samples can be written to an analog output channel using the function `comedi_data_write`:

`int comedi_data_write(` | comedi_t *device,
| unsigned int subdevice,
| unsigned int channel,
| unsigned int range,
| unsigned int aref,
| lsampl_t data`)`;

Raw data values read or written by the above functions are unsigned integers less than, or equal to, the maximum sample value of the channel, which can be determined using the function `comedi_get_maxdata`:

`lsampl_t comedi_get_maxdata(` | comedi_t *device,
| unsigned int subdevice,
| unsigned int channel`)`;

Conversion between raw data values and uncalibrated physical units can be performed by the functions `comedi_to_phys` and `comedi_from_phys`:

`double comedi_to_phys(` | lsampl_t data,
| comedi_range *range,
| lsampl_t maxdata`)`;

`lsampl_t comedi_from_phys(` | double data,
| comedi_range *range,
| lsampl_t maxdata`)`;

There are some data structures in these commands that are not fully self-explanatory:

- comedi_t: this data structure contains all information that a user program has to know about an open Comedi device. The programmer doesn't have to fill in this data structure manually: it gets filled in by opening the device.

- lsampl_t: this “data structure” represents one single sample. On most architectures, it's nothing more than a 32 bits value. Internally, Comedi does some conversion from raw sample data to “correct” integers. This is called “data munging”.

- comedi_range: this holds the minimum and maximum physical values for a gain range supported by a channel of a subdevice, and specifies the units. This can be used in combination with the channel's “maxdata” value to convert between unsigned integer sample values (of type lsampl_t or sampl_t) and physical units in a nominal (uncalibrated) way using the `comedi_to_phys` and `comedi_from_phys` functions. Use the `comedi_get_maxdata` function to get the “maxdata” value for the channel.

  Most functions specify the range to be used for a channel by a zero-based index into the list of ranges supported by the channel. Depending on the device and subdevice, different channels on the subdevice may or may not share the same list of ranges, that is, ranges may or may not be channel-specific. (The `SDF_RANGETYPE` subdevice flag indicates whether ranges are channel-specific.)

Each single acquisition by, for example, `comedi_data_read` requires quite some overhead, because all the arguments of the function call are checked. If multiple acquisitions must be done on the same channel, this overhead can be avoided by using a function that can read more than one sample, `comedi_data_read_n`:

`int comedi_data_read_n(` | comedi_t *device,
| unsigned int subdevice,
| unsigned int channel,
| unsigned int range,
| unsigned int aref,
| lsampl_t *data,
| unsigned int n`)`;

The number of samples, `n`, is limited by the Comedi implementation (to a maximum of 100 samples), because the call is blocking.

The start of the a single data acquisition can also be delayed by a specified number of nano-seconds using the function `comedi_data_read_delayed`:

`int comedi_data_read_delayed(` | comedi_t *device,
| unsigned int subdevice,
| unsigned int channel,
| unsigned int range,
| unsigned int aref,
| lsampl_t *data,
| unsigned int nano_sec`)`;

All these read and write acquisition functions are implemented on top of the generic instruction command.

Prev |  | Next
3.5. Further examples | Home | 4.2. Instructions for multiple acquisitions