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.
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.
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.
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.