Updates
This commit is contained in:
parent
f95a0c1eac
commit
9a417c7282
7 changed files with 927 additions and 1036 deletions
|
@ -1,7 +1,7 @@
|
|||
|
||||
all: drivers.sgml funcref.sgml
|
||||
-mkdir html
|
||||
-mkdir man
|
||||
-mkdir -p html
|
||||
-mkdir -p man
|
||||
-docbook2html -o html comedilib.sgml
|
||||
-docbook2man -o man comedilib.sgml
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
"docbook/dtd/3.1/docbook.dtd" [
|
||||
<!ENTITY intro SYSTEM "intro.sgml">
|
||||
<!ENTITY install SYSTEM "install.sgml">
|
||||
<!ENTITY tutorial SYSTEM "tutorial.sgml">
|
||||
<!ENTITY other SYSTEM "other.sgml">
|
||||
<!ENTITY drivers SYSTEM "drivers.sgml">
|
||||
<!ENTITY reference SYSTEM "reference.sgml">
|
||||
<!ENTITY funcref SYSTEM "funcref.sgml">
|
||||
|
@ -37,14 +39,9 @@
|
|||
|
||||
&install
|
||||
|
||||
<section>
|
||||
<title>
|
||||
Writing programs that use Comedi
|
||||
</title>
|
||||
<para>
|
||||
Empty.
|
||||
</para>
|
||||
</section>
|
||||
&tutorial
|
||||
|
||||
&other
|
||||
|
||||
&drivers
|
||||
|
||||
|
|
|
@ -3,63 +3,189 @@ Retval: int
|
|||
Param: comedi * device
|
||||
Description:
|
||||
Close a device previously opened by comedi_open().
|
||||
Returns:
|
||||
If sucessful, comedi_close returns 0. On failure, -1 is returned.
|
||||
|
||||
Function: comedi_open -- open a Comedi device
|
||||
Retval: comedi_t
|
||||
Param: const char * filename
|
||||
Description:
|
||||
Open a Comedi device represented by the file filename.
|
||||
Open a Comedi device specified by the file filename.
|
||||
Returns:
|
||||
If sucessful, comedi_open returns a pointer to a valid comedi_t
|
||||
structure. This structure is transparent; the pointer should not
|
||||
be dereferenced by the application. NULL is returned on failure.
|
||||
|
||||
Function: comedi_loglevel -- change Comedilib logging properties
|
||||
Retval: int
|
||||
Param: int loglevel
|
||||
Description:
|
||||
This function affects the output of debugging and error messages
|
||||
from Comedilib. By increasing the loglevel, additional debugging
|
||||
information will be printed. Error and debugging messages are
|
||||
printed to the stream stderr.
|
||||
|
||||
The default loglevel can be set by using the environment variable
|
||||
COMEDI_LOGLEVEL. The default loglevel is 1.
|
||||
|
||||
In order to conserve resources, some debugging information is
|
||||
disabled by default when Comedilib is compiled.
|
||||
|
||||
The meaning of the loglevels is as follows:
|
||||
|
||||
COMEDI_LOGLEVEL=0 Comedilib prints nothing.
|
||||
|
||||
COMEDI_LOGLEVEL=1 (default) Comedilib prints error messages when
|
||||
there is a self-consistency error (i.e., an internal bug.)
|
||||
|
||||
COMEDI_LOGLEVEL=2 Comedilib prints an error message when an invalid
|
||||
parameter is passed.
|
||||
|
||||
COMEDI_LOGLEVEL=3 Comedilib prints an error message whenever an
|
||||
error is generated in the Comedilib library or in the C library,
|
||||
when called by Comedilib.
|
||||
|
||||
COMEDI_LOGLEVEL=4 Comedilib prints a lot of junk.
|
||||
Returns:
|
||||
This function returns the previous loglevel.
|
||||
|
||||
Function: comedi_perror -- print a Comedilib error message
|
||||
Retval: void
|
||||
Param: const char * s
|
||||
Description:
|
||||
When a Comedilib function fails, it usually returns -1 or
|
||||
NULL, depending on the return type. An internal library
|
||||
variable stores an error number, which can be retrieved with
|
||||
comedi_errno(). This error number can be converted to a
|
||||
human-readable form by the functions comedi_perror()
|
||||
and comedi_strerror().
|
||||
|
||||
These functions are intended to mimic the behavior of the
|
||||
standard C library functions perror(), strerror(), and errno.
|
||||
In particular, Comedilib functions sometimes return an error
|
||||
that is generated inside the C library; the comedi error
|
||||
message in this case is the same as the C library.
|
||||
|
||||
The function comedi_perror() prints an error message to stderr.
|
||||
The error message consists of the argument string, a colon, a
|
||||
space, a description of the error condition, and a new line.
|
||||
|
||||
Function: comedi_strerror -- return string describing Comedilib error code
|
||||
Retval: char *
|
||||
Param: int errnum
|
||||
Description:
|
||||
When a Comedilib function fails, it usually returns -1 or
|
||||
NULL, depending on the return type. An internal library
|
||||
variable stores an error number, which can be retrieved with
|
||||
comedi_errno(). This error number can be converted to a
|
||||
human-readable form by the functions comedi_perror()
|
||||
and comedi_strerror().
|
||||
|
||||
These functions are intended to mimic the behavior of the
|
||||
standard C library functions perror(), strerror(), and errno.
|
||||
In particular, Comedilib functions sometimes return an error
|
||||
that is generated inside the C library; the comedi error
|
||||
message in this case is the same as the C library.
|
||||
|
||||
The function comedi_strerror() returns a pointer to a
|
||||
character string
|
||||
describing the Comedilib error errnum. The persistence
|
||||
of the returned pointer is undefined, and should not be trusted
|
||||
after the next Comedilib call. An unrecognized error number will
|
||||
return a pointer to the string "undefined error", or similar.
|
||||
|
||||
Function: comedi_errno -- number of last Comedilib error
|
||||
Retval: int
|
||||
Param: void
|
||||
Description:
|
||||
When a Comedilib function fails, it usually returns -1 or
|
||||
NULL, depending on the return type. An internal library
|
||||
variable stores an error number, which can be retrieved with
|
||||
comedi_errno(). This error number can be converted to a
|
||||
human-readable form by the functions comedi_perror()
|
||||
and comedi_strerror().
|
||||
|
||||
These functions are intended to mimic the behavior of the
|
||||
standard C library functions perror(), strerror(), and errno.
|
||||
In particular, Comedilib functions sometimes return an error
|
||||
that is generated inside the C library; the comedi error
|
||||
message in this case is the same as the C library.
|
||||
|
||||
The function comedi_errno() returns an integer describing
|
||||
the most recent comedilib error. This integer may be used
|
||||
as the errnum parameter for comedi_strerror().
|
||||
|
||||
Note that comedi_errno() is deliberately different than the
|
||||
variable errno. This is to overcome difficulties in making
|
||||
errno thread-safe.
|
||||
|
||||
Function: comedi_fileno -- integer descriptor of Comedilib device
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Description:
|
||||
The function comedi_fileno returns the integer descriptor for
|
||||
the device dev. This descriptor can then be used as the
|
||||
file descriptor parameter of read(), write(), etc.
|
||||
This function is intended to mimic the standard C library
|
||||
function fileno(). If dev is an invalid comedi_t
|
||||
pointer, the function returns -1 and sets the appropriate
|
||||
Comedilib error value.
|
||||
|
||||
Function: comedi_get_n_subdevices -- number of subdevices
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Description:
|
||||
Returns the number of subdevices belonging to the Comedi
|
||||
device referenced by the parameter device.
|
||||
|
||||
Function: comedi_get_version_code -- Comedi version code
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Description:
|
||||
Returns the Comedi kernel module version code. A valid Comedi
|
||||
device referenced by the parameter device is necessary to
|
||||
communicate with the kernel module. On error, -1 is returned.
|
||||
|
||||
The version code is encoded as a bitfield of three 8-bit
|
||||
numbers. For example, 0x00073d is the version code for
|
||||
version 0.7.61.
|
||||
|
||||
This function is of limited usefulness. A typical
|
||||
mis-application of this function is to use it to determine
|
||||
if a certain feature is supported. If the application needs
|
||||
to know of the existence of a particular feature, an existence
|
||||
test function should be written and put in the Comedilib source.
|
||||
|
||||
Function: comedi_get_driver_name -- Comedi driver name
|
||||
Retval: char *
|
||||
Param: comedi_t * device
|
||||
Description:
|
||||
The function comedi_get_driver_name returns a pointer
|
||||
to a string containing the name of the driver being used by comedi
|
||||
for the comedi device represented by device. This pointer is
|
||||
valid until the device is closed. This function returns NULL
|
||||
if there is an error.
|
||||
|
||||
Function: comedi_get_board_name -- Comedi device name
|
||||
Retval: char *
|
||||
Param: comedi_t * device
|
||||
Description:
|
||||
The function comedi_get_board_name returns a pointer
|
||||
to a string containing the name of the device. This pointer is
|
||||
valid until the comedi descriptor it is closed. This
|
||||
function returns NULL if there is an error.
|
||||
|
||||
Function: comedi_get_subdevice_type -- type of subdevice
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: unsigned int subdevice
|
||||
Description:
|
||||
The function comedi_get_subdevice_type() returns an
|
||||
integer describing the type of subdevice that belongs to the comedi
|
||||
device device and has the index subdevice. The
|
||||
function returns -1 if there is an error.
|
||||
|
||||
XXX Subdevice type table
|
||||
|
||||
Function: comedi_find_subdevice_by_type -- search for subdevice type
|
||||
Retval: int
|
||||
|
@ -67,30 +193,53 @@ Param: comedi_t * device
|
|||
Param: int type
|
||||
Param: unsigned int start_subdevice
|
||||
Description:
|
||||
The function comedi_find_subdevice_by_type() tries to
|
||||
locate a subdevice belonging to comedi device device,
|
||||
having type type, starting with the subdevice
|
||||
start_subdevice. If it finds a subdevice with the requested
|
||||
type, it returns its index. If it does not locate the requested
|
||||
subdevice, it returns -1 and sets the Comedilib error number to
|
||||
XXX "subdevice not found". If there is an error, the function
|
||||
returns -1 and sets the appropriate error.
|
||||
|
||||
Function: comedi_get_subdevice_flags -- properties of subdevice
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: unsigned int subdevice
|
||||
Description:
|
||||
This function returns a bitfield describing the capabilities of
|
||||
the specified subdevice. If there is an error, -1 is returned,
|
||||
and the Comedilib error value is set.
|
||||
|
||||
XXX table.
|
||||
|
||||
Function: comedi_get_n_channels -- number of subdevice channels
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: unsigned int subdevice
|
||||
Description:
|
||||
The function comedi_get_n_channels() returns the number
|
||||
of channels of the subdevice belonging to the comedi device device
|
||||
and having index subdevice. This function returns -1 on error and
|
||||
the Comedilib error value is set.
|
||||
|
||||
Function: comedi_range_is_chan_specific -- range information depends on channel
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: unsigned int subdevice
|
||||
Description:
|
||||
If each channel of the specified subdevice has different range
|
||||
information, this function returns 1. Otherwise, this function
|
||||
returns 0. On error, this function returns -1.
|
||||
|
||||
Function: comedi_maxdata_is_chan_specific -- maximum sample depends on channel
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: unsigned int subdevice
|
||||
Description:
|
||||
If each channel of the specified subdevice has different maximum
|
||||
sample values, this function returns 1. Otherwise, this function
|
||||
returns 0. On error, this function returns -1.
|
||||
|
||||
Function: comedi_get_maxdata -- maximum sample of channel
|
||||
Retval: lsampl_t
|
||||
|
@ -98,6 +247,10 @@ Param: comedi_t * device
|
|||
Param: unsigned int subdevice
|
||||
Param: unsigned int channel
|
||||
Description:
|
||||
The function comedi_get_maxdata() returns the maximum
|
||||
valid data value for channel chan of subdevice
|
||||
subdevice belonging to the comedi device device
|
||||
This function returns 0 on error.
|
||||
|
||||
Function: comedi_get_n_ranges -- number of ranges of channel
|
||||
Retval: int
|
||||
|
@ -105,6 +258,9 @@ Param: comedi_t * device
|
|||
Param: unsigned int subdevice
|
||||
Param: unsigned int channel
|
||||
Description:
|
||||
The function comedi_get_n_ranges() returns the number
|
||||
of ranges of the channel chan belonging to the subdevice
|
||||
of the comedi device device. This function returns -1 on error.
|
||||
|
||||
Function: comedi_get_range -- range information of channel
|
||||
Retval: comedi_range *
|
||||
|
@ -113,6 +269,11 @@ Param: unsigned int subdevice
|
|||
Param: unsigned int channel
|
||||
Param: unsigned int range
|
||||
Description:
|
||||
The function comedi_get_range() returns a pointer to a
|
||||
comedi_range structure that contains information that can be used to
|
||||
convert sample values to or from physical units. The pointer is valid
|
||||
until the Comedi device device is closed. If there is an
|
||||
error, NULL is returned.
|
||||
|
||||
Function: comedi_find_range -- search for range
|
||||
Retval: int
|
||||
|
@ -123,18 +284,32 @@ Param: unsigned int unit
|
|||
Param: double min
|
||||
Param: double max
|
||||
Description:
|
||||
The function comedi_find_range() tries to
|
||||
locate the optimal (smallest) range for the channel chan
|
||||
belonging to a subdevice of the comedi device device,
|
||||
that includes both min and max in units.
|
||||
If a matching range is found, the index of the matching range is
|
||||
returned. If no matching range is available, the function returns
|
||||
-1.
|
||||
|
||||
Function: comedi_get_buffer_size -- streaming buffer size of subdevice
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: unsigned int subdevice
|
||||
Description:
|
||||
The function comedi_get_buffer_size() returns the size (in bytes)
|
||||
of the streaming buffer for the subdevice specified by device and
|
||||
subdevice. On error, -1 is returned.
|
||||
|
||||
Function: comedi_get_max_buffer_size -- maximum streaming buffer size
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: unsigned int subdevice
|
||||
Description:
|
||||
The function comedi_get_max_buffer_size() returns the maximum
|
||||
allowable size (in bytes) of the streaming buffer for the subdevice
|
||||
specified by device and subdevice. Changing the maximum buffer
|
||||
size requires appropriate privileges. On error, -1 is returned.
|
||||
|
||||
Function: comedi_set_buffer_size -- streaming buffer size of subdevice
|
||||
Retval: int
|
||||
|
@ -142,37 +317,84 @@ Param: comedi_t * device
|
|||
Param: unsigned int subdevice
|
||||
Param: unsigned int size
|
||||
Description:
|
||||
The function comedi_set_buffer_size() changes the size of the
|
||||
streaming buffer for the subdevice specified by device and subdevice.
|
||||
The parameter size must be a multiple of the virtual memory page
|
||||
size.
|
||||
|
||||
The virtual memory page size can be determined using
|
||||
sysconf(_SC_PAGE_SIZE).
|
||||
|
||||
Function: comedi_trigger -- perform streaming input/output (deprecated)
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: comedi_trig * trig
|
||||
Description:
|
||||
Status: deprecated
|
||||
Description:
|
||||
The function comedi_trigger() instructs Comedi to
|
||||
perform the command specified by the trigger structure trig.
|
||||
The return value depends on
|
||||
the particular trig being issued. If there is an
|
||||
error, -1 is returned.
|
||||
|
||||
Function: comedi_do_insnlist -- perform multiple instructions
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: comedi_insnlist * list
|
||||
Description:
|
||||
The function comedi_do_insnlist() performs multiple Comedi
|
||||
instructions as part of one system call. In addition, Comedi
|
||||
attempts to perform the instructions atomically, that is, on
|
||||
standard Linux kernels, no process preemption should occur
|
||||
during the instructions. However, the process may be preempted
|
||||
before or after the group of instructions.
|
||||
|
||||
This function can be used to avoid the overhead of multiple
|
||||
system calls, or to ensure that multiple instructions occur
|
||||
without significant delay between them.
|
||||
|
||||
Preemption may occur if any of the instructions or the data
|
||||
arrays of any of the instructions exist in non-resident or
|
||||
copy-on-write pages.
|
||||
Returns:
|
||||
The function comedi_do_insnlist() returns the number of
|
||||
sucessfully completed instructions. Error information for
|
||||
the unsucessful instruction is not available. If there is
|
||||
an error before the first instruction can be executed, -1
|
||||
is returned.
|
||||
|
||||
Function: comedi_do_insn -- perform instruction
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: comedi_insn * instruction
|
||||
Description:
|
||||
The function comedi_do_insn() performs a single instruction.
|
||||
If sucessful, comedi_do_insn() returns the number of samples
|
||||
measured, which may be less than the number of requested
|
||||
samples. Comedi limits the number of requested samples in
|
||||
order to enforce fairness among processes. If there is an
|
||||
error, -1 is returned.
|
||||
|
||||
Function: comedi_lock -- subdevice reservation
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: unsigned int subdevice
|
||||
Description:
|
||||
The function comedi_lock() reserves a subdevice for use by the
|
||||
current process. While the lock is held, no other process is
|
||||
allowed to read, write, or configure that subdevice, although
|
||||
other processes can read information about the subdevice. The
|
||||
lock is released when comedi_unlock() is called, or the device
|
||||
is closed. If sucessful, 0 is returned. If there is an error,
|
||||
-1 is returned.
|
||||
|
||||
Function: comedi_unlock -- subdevice reservation
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: unsigned int subdevice
|
||||
Description:
|
||||
The function comedi_unlock() released a subdevice lock acquired
|
||||
by comedi_lock(). If sucessful, 0 is returned, otherwise -1.
|
||||
|
||||
Function: comedi_to_phys -- convert sample to physical units
|
||||
Retval: double
|
||||
|
@ -180,6 +402,20 @@ Param: lsampl_t data
|
|||
Param: comedi_range * range
|
||||
Param: lsampl_t maxdata
|
||||
Description:
|
||||
Converts data given in sample values (lsampl_t, between 0 and
|
||||
maxdata) into physical units (double). The parameter range
|
||||
represents the conversion information to use, and the parameter
|
||||
maxdata represents the maximum possible data value for the
|
||||
channel that the data was read.
|
||||
|
||||
Conversion of endpoint sample values, that is, sample values
|
||||
equal to 0 or maxdata, is affected by the Comedilib out-of-range
|
||||
behavior. If the out-of-range behavior is set to COMEDI_OOR_NAN,
|
||||
endpoint values are converted to NAN. If the out-of-range
|
||||
behavior is set to COMEDI_OOR_NUMBER, the endpoint values are
|
||||
converted similarly to other values.
|
||||
|
||||
If there is an error, NAN is returned.
|
||||
|
||||
Function: comedi_from_phys -- convert physical units to sample
|
||||
Retval: lsampl_t
|
||||
|
@ -187,6 +423,14 @@ Param: double data
|
|||
Param: comedi_range * range
|
||||
Param: lsampl_t maxdata
|
||||
Description:
|
||||
Converts data given in physical units (data) into sample values
|
||||
(lsampl_t, between 0 and maxdata). The parameter rng
|
||||
represents the conversion information to use, and the parameter
|
||||
maxdata represents the maximum possible data value for the
|
||||
channel that the data will be written to.
|
||||
|
||||
Conversion is not affected by out-of-range behavior. Out-of-range
|
||||
data parameters are silently truncated to the range 0 to maxdata.
|
||||
|
||||
Function: comedi_data_read -- read single sample from channel
|
||||
Retval: int
|
||||
|
@ -197,6 +441,26 @@ Param: unsigned int range
|
|||
Param: unsigned int aref
|
||||
Param: lsampl_t * data
|
||||
Description:
|
||||
Reads a single sample on the channel specified by the Comedi
|
||||
device device, the subdevice subdevice, and the channel channel.
|
||||
For the A/D conversion (if appropriate),
|
||||
the device is configured to use range specification
|
||||
range and (if appropriate) analog reference type
|
||||
aref. Analog reference types that are not supported
|
||||
by the device are silently ignored.
|
||||
|
||||
The function comedi_data_read() reads one data value from
|
||||
the specified channel and places the data value in the
|
||||
location pointed to by data.
|
||||
|
||||
On sucess, comedi_data_read() returns 0. If there is an
|
||||
error, -1 is returned.
|
||||
|
||||
Data values returned by this function 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().
|
||||
Conversion of data values to physical units can be performed
|
||||
by the function comedi_to_phys().
|
||||
|
||||
Function: comedi_data_write -- write single sample to channel
|
||||
Retval: int
|
||||
|
@ -207,6 +471,18 @@ Param: unsigned int range
|
|||
Param: unsigned int aref
|
||||
Param: lsampl_t data
|
||||
Description:
|
||||
Writes a single sample on the channel that is specified by the
|
||||
Comedi device device, the subdevice subdevice, and the channel
|
||||
channel. If appropriate, the device is configured to use range
|
||||
specification range and analog reference type aref. Analog
|
||||
reference types that are not supported by the device are
|
||||
silently ignored.
|
||||
|
||||
The function comedi_data_write() writes the data value specified
|
||||
by the parameter data to the specified channel.
|
||||
|
||||
On sucess, comedi_data_write() returns 0. If there is an error, -1 is
|
||||
returned.
|
||||
|
||||
Function: comedi_dio_config -- change input/output properties of channel
|
||||
Retval: int
|
||||
|
@ -215,6 +491,17 @@ Param: unsigned int subdevice
|
|||
Param: unsigned int channel
|
||||
Param: unsigned int direction
|
||||
Description:
|
||||
The function comedi_dio_config() configures individual channels
|
||||
in a digital I/O subdevice to be either input or output, depending
|
||||
on the value of parameter direction. Valid directions are
|
||||
COMEDI_INPUT or COMEDI_OUTPUT.
|
||||
|
||||
Depending on the capabilities of the hardware device, multiple
|
||||
channels may be grouped together to determine direction. In this
|
||||
case, a single call to comedi_dio_config() for any channel in the
|
||||
group will affect the entire group.
|
||||
|
||||
If sucessful, 0 is returned, otherwise -1.
|
||||
|
||||
Function: comedi_dio_read -- read single bit from digital channel
|
||||
Retval: int
|
||||
|
@ -223,6 +510,14 @@ Param: unsigned int subdevice
|
|||
Param: unsigned int channel
|
||||
Param: unsigned int * bit
|
||||
Description:
|
||||
The function reads the channel channel belonging to the
|
||||
subdevice subdevice of device device. The data value that is
|
||||
read is stored in the location pointed to by bit. This function
|
||||
is equivalent to comedi_data_read(device,subdevice,channel,0,0,bit).
|
||||
This function does not require a digital subdevice or a subdevice
|
||||
with a maximum data value of 1 to work properly.
|
||||
|
||||
Return values and errors are the same as comedi_data_read().
|
||||
|
||||
Function: comedi_dio_write -- write single bit to digital channel
|
||||
Retval: int
|
||||
|
@ -231,6 +526,13 @@ Param: unsigned int subdevice
|
|||
Param: unsigned int channel
|
||||
Param: unsigned int bit
|
||||
Description:
|
||||
The function writes the value bit to the channel channel belonging
|
||||
to the subdevice subdevice of device device. This function
|
||||
is equivalent to comedi_data_write(device,subdevice,channel,0,0,bit).
|
||||
This function does not require a digital subdevice or a subdevice
|
||||
with a maximum data value of 1 to work properly.
|
||||
|
||||
Return values and errors are the same as comedi_data_write().
|
||||
|
||||
Function: comedi_dio_bitfield -- read/write multiple digital channels
|
||||
Retval: int
|
||||
|
@ -239,6 +541,17 @@ Param: unsigned int subdevice
|
|||
Param: unsigned int write_mask
|
||||
Param: unsigned int * bits
|
||||
Description:
|
||||
The function comedi_dio_bitfield() allows multiple channels to
|
||||
be read simultaneously from a digital input or digital I/O device.
|
||||
The parameter write_mask and the value pointed to by bits
|
||||
are interpreted as bit fields, with the least significant bit
|
||||
representing channel 0. For each bit in write_mask that is
|
||||
set to 1, the cooresponding bit in *bits is written to the digital
|
||||
output channel. After writing all the output channels, each
|
||||
channel is read, and the result placed in the approprate bits in
|
||||
*bits. The result of reading an output channel is undefined.
|
||||
It is not possible to access channels greater than 31 using this
|
||||
function.
|
||||
|
||||
Function: comedi_sv_init -- slowly-varying inputs
|
||||
Retval: int
|
||||
|
@ -247,17 +560,31 @@ Param: comedi_t * device
|
|||
Param: unsigned int subdevice
|
||||
Param: unsigned int channel
|
||||
Description:
|
||||
The function comedi_sv_init() initializes the slow varying Comedi
|
||||
structure sv to use the device device, the analog input subdevice
|
||||
subdevice, and the channel channel. The slow varying Comedi
|
||||
structure is used by comedi_sv_measure() to accurately measure
|
||||
an analog input by averaging over many samples. The default
|
||||
number of samples is 100. This function returns 0 on success,
|
||||
-1 on error.
|
||||
|
||||
Function: comedi_sv_update -- slowly-varying inputs
|
||||
Retval: int
|
||||
Param: comedi_sv_t * sv
|
||||
Description:
|
||||
The function comedi_sv_update() updates internal parameters of
|
||||
the slowly varying Comedi structure sv.
|
||||
|
||||
Function: comedi_sv_measure -- slowly-varying inputs
|
||||
Retval: int
|
||||
Param: comedi_sv_t * sv
|
||||
Param: double * data
|
||||
Description:
|
||||
The function comedi_sv_measure() uses the slowly varying Comedi
|
||||
structure sv to measure a slowly varying signal. If sucessful,
|
||||
the result (in physical units) is stored in the location pointed
|
||||
to by data, and the number of samples is returned. On error, -1
|
||||
is returned.
|
||||
|
||||
Function: comedi_get_cmd_src_mask -- streaming input/output capabilities
|
||||
Retval: int
|
||||
|
@ -265,6 +592,12 @@ Param: comedi_t * device
|
|||
Param: unsigned int subdevice
|
||||
Param: comedi_cmd * command
|
||||
Description:
|
||||
The command capabilities of the subdevice indicated by the parameters
|
||||
device and subdevice are probed, and the results placed in the
|
||||
command structure pointed to by the parameter command. The trigger
|
||||
source elements of the command structure are set to the logical OR
|
||||
value of possible trigger sources. Other elements in the structure
|
||||
are undefined. If sucessful, 0 is returned, otherwise -1.
|
||||
|
||||
Function: comedi_get_cmd_generic_timed -- streaming input/output capabilities
|
||||
Retval: int
|
||||
|
@ -273,30 +606,66 @@ Param: unsigned int subdevice
|
|||
Param: comedi_cmd * command
|
||||
Param: unsigned int period_ns
|
||||
Description:
|
||||
The command capabilities of the subdevice indicated by the parameters
|
||||
device and subdevice are probed, and the results placed in the
|
||||
command structure pointed to by the parameter command. The command
|
||||
structure pointed to by the parameter command is modified to be a
|
||||
valid command that can be used as a parameter to comedi_command().
|
||||
The command measures samples at a rate that corresponds to the
|
||||
period period_ns. The rate is adjusted to a rate that the device
|
||||
can handle. If sucessful, 0 is returned, otherwise -1.
|
||||
|
||||
Function: comedi_cancel -- stop streaming input/outpu in progress
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: unsigned int subdevice
|
||||
Description:
|
||||
The function comedi_cancel() can be used to stop a Comedi command
|
||||
previously started by comedi_command() that is still in progress
|
||||
on the subdevice indicated by the parameters device and subdevice.
|
||||
This may not return the subdevice to a ready state, since there may
|
||||
be samples in the buffer that need to be read.
|
||||
|
||||
If sucessful, 0 is returned, otherwise -1.
|
||||
|
||||
Function: comedi_command -- start streaming input/output
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: comedi_cmd * command
|
||||
Description:
|
||||
The function comedi_command() starts streaming input or output. The
|
||||
command structure pointed to by the parameter command specifies the
|
||||
acquisition. For input subdevices, sample values are read using the
|
||||
function read(). For output subdevices, sample vlaues are written
|
||||
using the function write().
|
||||
|
||||
If sucessful, 0 is returned, otherwise -1.
|
||||
|
||||
Function: comedi_command_test -- test streaming input/output configuration
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: comedi_cmd * command
|
||||
Description:
|
||||
The function comedi_command_test() tests the command structure pointed
|
||||
to by the parameter command and returns an integer describing the
|
||||
testing stages that were sucessfully passed. In addition, if elements
|
||||
of the command structure are invalid, they may be modified. Source
|
||||
elements are modified to remove invalid source triggers. Argument
|
||||
elements are adjusted or rounded to the nearest valid value.
|
||||
|
||||
XXX return values.
|
||||
|
||||
Function: comedi_poll -- force updating of streaming buffer
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: unsigned int subdevice
|
||||
Description:
|
||||
The function comedi_poll() is used on a subdevice that has a
|
||||
Comedi command in progress in order to update the streaming buffer.
|
||||
If supported by the driver, all available samples are copied to
|
||||
the streaming buffer. These samples may be pending in DMA buffers
|
||||
or device FIFOs. If sucessful, the number of additional bytes
|
||||
available is returned. If there is an error, -1 is returned.
|
||||
|
||||
Function: comedi_set_max_buffer_size -- streaming buffer size of subdevice
|
||||
Retval: int
|
||||
|
@ -304,12 +673,21 @@ Param: comedi_t * device
|
|||
Param: unsigned int subdevice
|
||||
Param: unsigned int max_size
|
||||
Description:
|
||||
The function comedi_set_max_buffer_size() changes the maximum
|
||||
allowable size (in bytes) of the streaming buffer for the subdevice
|
||||
specified by device and subdevice. Changing the maximum buffer
|
||||
size requires appropriate privileges. If sucessful, the old buffer
|
||||
size is returned. On error, -1 is returned.
|
||||
|
||||
Function: comedi_get_buffer_contents -- streaming buffer status
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: unsigned int subdevice
|
||||
Description:
|
||||
The function comedi_get_buffer_contents() is used on a subdevice
|
||||
that has a Comedi command in progress. The number of bytes that
|
||||
are available in the streaming buffer is returned. If there is
|
||||
an error, -1 is returned.
|
||||
|
||||
Function: comedi_mark_buffer_read -- streaming buffer status
|
||||
Retval: int
|
||||
|
@ -317,12 +695,22 @@ Param: comedi_t * device
|
|||
Param: unsigned int subdevice
|
||||
Param: unsigned int num_bytes
|
||||
Description:
|
||||
The function comedi_mark_buffer_read() is used on a subdevice
|
||||
that has a Comedi command in progress. This function can be
|
||||
used to indicate that the next num_bytes bytes in the buffer
|
||||
are no longer needed and may be discarded.
|
||||
If there is an error, -1 is returned.
|
||||
|
||||
Function: comedi_get_buffer_offset -- streaming buffer status
|
||||
Retval: int
|
||||
Param: comedi_t * device
|
||||
Param: unsigned int subdevice
|
||||
Description:
|
||||
The function comedi_mark_buffer_read() is used on a subdevice
|
||||
that has a Comedi command in progress. This function returns
|
||||
the offset of the read pointer in the streaming buffer. This
|
||||
offset is only useful for memory mapped buffers.
|
||||
If there is an error, -1 is returned.
|
||||
|
||||
Function: comedi_get_timer -- timer information (deprecated)
|
||||
Retval: int
|
||||
|
@ -333,6 +721,13 @@ Param: unsigned int * trigvar
|
|||
Param: double * actual_frequency
|
||||
Description:
|
||||
Status: deprecated
|
||||
The function comedi_get_timer converts the frequency frequency
|
||||
to a number suitable to send to the driver in a comedi_trig
|
||||
structure. This function remains for compatibility with very
|
||||
old versions of Comedi, that converted sampling rates to timer
|
||||
values in the libary. This conversion is now done in the kernel,
|
||||
and every device has the timer type nanosec_timer, indicating
|
||||
that timer values are simply a time specified in nanoseconds.
|
||||
|
||||
Function: comedi_timed_1chan -- streaming input (deprecated)
|
||||
Retval: int
|
||||
|
@ -346,10 +741,20 @@ Param: unsigned int num_samples
|
|||
Param: double * data
|
||||
Description:
|
||||
Status: deprecated
|
||||
Not documented.
|
||||
|
||||
Function: comedi_set_global_oor_behavior -- out-of-range behavior
|
||||
Retval: int
|
||||
Param: enum comedi_oor_behavior behavior
|
||||
Description:
|
||||
Status: alpha
|
||||
This function changes the Comedilib out-of-range behavior.
|
||||
This currently affects the behavior of comedi_to_phys() when
|
||||
converting endpoint sample values, that is, sample values
|
||||
equal to 0 or maxdata. If the out-of-range behavior is set to
|
||||
COMEDI_OOR_NAN, endpoint values are converted to NAN. If the
|
||||
out-of-range behavior is set to COMEDI_OOR_NUMBER, the endpoint
|
||||
values are converted similarly to other values.
|
||||
|
||||
The previous out-of-range behavior is returned.
|
||||
|
||||
|
|
|
@ -16,13 +16,7 @@ print
|
|||
|
||||
while($s = <>){
|
||||
chomp $s;
|
||||
if($s eq ""){
|
||||
print $end;
|
||||
print
|
||||
"</refentry>
|
||||
";
|
||||
$end = "";
|
||||
}elsif($s =~ m/^Function: (.*)/){
|
||||
if($s =~ m/^Function: (.*)/){
|
||||
$funcname = $1;
|
||||
$refpurpose = "";
|
||||
if($s =~ m/^Function: (.*) -- (.*)/){
|
||||
|
@ -78,6 +72,19 @@ while($s = <>){
|
|||
$end =
|
||||
" </para>
|
||||
</refsect1>
|
||||
";
|
||||
}elsif($s =~ m/^Returns:/){
|
||||
print $end;
|
||||
print
|
||||
" <refsect1>
|
||||
<title>
|
||||
Return value
|
||||
</title>
|
||||
<para>
|
||||
";
|
||||
$end =
|
||||
" </para>
|
||||
</refsect1>
|
||||
";
|
||||
}elsif($s =~ m/^Status: (.*)/){
|
||||
print $end;
|
||||
|
@ -93,11 +100,17 @@ while($s = <>){
|
|||
" </para>
|
||||
</refsect1>
|
||||
";
|
||||
}elsif($s eq ""){
|
||||
print "</para><para>\n";
|
||||
}elsif($s =~ m/^ (.*)/){
|
||||
print "$1\n";
|
||||
}
|
||||
}
|
||||
|
||||
print $end;
|
||||
print
|
||||
"</refentry>
|
||||
";
|
||||
print
|
||||
"</section>
|
||||
";
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -112,6 +112,10 @@ Data Types and Structures
|
|||
comedi_t
|
||||
</title>
|
||||
|
||||
<programlisting>
|
||||
typedef struct comedi_t_struct comedi_t;
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
The data type comedi_t is used to represent an open Comedi
|
||||
device. A valid comedi_t pointer is returned by a successful
|
||||
|
@ -129,6 +133,9 @@ should not be dereferenced by the application.
|
|||
sampl_t
|
||||
</title>
|
||||
|
||||
<programlisting>
|
||||
typedef unsigned short sampl_t;
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
The data type sampl_t is one of the generic types used to represent
|
||||
|
@ -151,6 +158,10 @@ lsampl_t.
|
|||
lsampl_t
|
||||
</title>
|
||||
|
||||
<programlisting>
|
||||
typedef unsigned int lsampl_t;
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
The data type lsampl_t is the data type typically used to represent
|
||||
data values in libcomedi. On most architectures, lsampl_t is
|
||||
|
@ -165,6 +176,8 @@ comedi_trig (deprecated)
|
|||
</title>
|
||||
|
||||
<programlisting>
|
||||
typedef struct comedi_trig_struct comedi_trig;
|
||||
|
||||
struct comedi_trig_struct{
|
||||
unsigned int subdev; /* subdevice */
|
||||
unsigned int mode; /* mode */
|
||||
|
@ -178,7 +191,7 @@ struct comedi_trig_struct{
|
|||
unsigned int trigvar1;
|
||||
unsigned int data_len;
|
||||
unsigned int unused[3];
|
||||
}
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
|
@ -195,6 +208,8 @@ comedi_sv_t
|
|||
</title>
|
||||
|
||||
<programlisting>
|
||||
typedef struct comedi_sv_struct comedi_sv_t;
|
||||
|
||||
struct comedi_sv_struct{
|
||||
comedi_t *dev;
|
||||
unsigned int subdevice;
|
||||
|
@ -208,7 +223,7 @@ struct comedi_sv_struct{
|
|||
int n;
|
||||
|
||||
lsampl_t maxdata;
|
||||
}
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
|
@ -376,7 +391,9 @@ comedi_range
|
|||
</title>
|
||||
|
||||
<programlisting>
|
||||
typedef struct{
|
||||
typedef struct comedi_range_struct comedi_range;
|
||||
|
||||
struct comedi_range_struct{
|
||||
double min;
|
||||
double max;
|
||||
unsigned int unit;
|
||||
|
@ -400,6 +417,8 @@ comedi_krange
|
|||
</title>
|
||||
|
||||
<programlisting>
|
||||
typedef struct comedi_krange_struct comedi_krange;
|
||||
|
||||
struct comedi_krange_struct{
|
||||
int min;
|
||||
int max;
|
||||
|
@ -415,6 +434,33 @@ comedi_range structure, except the fields min and max
|
|||
are integers, multiplied by a factor of 1000000 compared to the
|
||||
counterparts in comedi_range.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In addition, kcomedilib uses the comedi_krange structure in place
|
||||
of the comedi_range structure.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="ref-type-comedi-insnlist">
|
||||
<title>
|
||||
comedi_insnlist
|
||||
</title>
|
||||
|
||||
<programlisting>
|
||||
typedef struct comedi_insnlist_struct comedi_insnlist;
|
||||
|
||||
struct comedi_insnlist_struct{
|
||||
unsigned int n_insns;
|
||||
comedi_insn *insns;
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
An instruction list (insnlist) structure is used to communicate
|
||||
a list of instructions.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
|
|
@ -1,210 +1,24 @@
|
|||
<p>
|
||||
<sect1>Configuring comedi for your hardware
|
||||
<p>
|
||||
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
|
||||
|
||||
|
||||
I assume that your hardware device is in your computer, and that
|
||||
you know the relevant details about it, i.e., what kind of card
|
||||
it is, the I/O base, the IRQ, jumper settings related to input
|
||||
ranges, etc.
|
||||
<section>
|
||||
<title>
|
||||
Writing programs that use comedi and comedilib
|
||||
</title>
|
||||
|
||||
To tell the comedi kernel module that you have a particular device, and
|
||||
some information about it, you will be running the <tt>comedi_config</tt>
|
||||
command. Perhaps you should read the man page now.
|
||||
|
||||
In this tutorial, I will go through the process of configuring comedi
|
||||
for two devices, a National Instruments AT-MIO-16E-10
|
||||
and a Data Translation DT2821-F-8DI.
|
||||
|
||||
The NI board is plug-and-play, and the man page tells me that I need
|
||||
to configure the PnP part of the board with isapnptools. The isapnptools
|
||||
package is a little cryptic, but the concepts are simple. Once I
|
||||
learned how to use it, I settled on a /etc/isapnp.conf file that
|
||||
contained the lines:
|
||||
|
||||
|
||||
<tscreen><verb>
|
||||
# ANSI string -->National Instruments, AT-MIO-16E-10<--
|
||||
(CONFIGURE NIC2400/10725401 (LD 0
|
||||
(IO 0 (BASE 0x0260))
|
||||
(INT 0 (IRQ 3 (MODE +E)))
|
||||
# (DMA 0 (CHANNEL 5))
|
||||
# (DMA 1 (CHANNEL 6))
|
||||
(ACT Y)
|
||||
))
|
||||
</verb></tscreen>
|
||||
|
||||
|
||||
It also contains a few lines about overall configuration and about my
|
||||
sound card. I found out after a bit of trial-and-error that the NI
|
||||
board does not always work with interrupts other than IRQ 3. YMMV.
|
||||
Currently, the driver doesn't use DMA, but it may in the future, so
|
||||
I commented out the DMA lines. It is a curious fact that the device
|
||||
ignores the IRQ and DMA information given here, however, I keep the
|
||||
information here to remind myself that the numbers aren't arbitrary.
|
||||
|
||||
When I run comedi_config (as root, of course), I provide the same
|
||||
information. Since I want to have the board configured every time
|
||||
I boot, I put the line
|
||||
|
||||
<tscreen><verb>
|
||||
/usr/sbin/comedi_config /dev/comedi0 atmio-E 0x260,3
|
||||
</verb></tscreen>
|
||||
|
||||
into <tt>/etc/rc.d/rc.local</tt>. You can, of course, run this command at
|
||||
a command prompt. The man page tells me that the option list
|
||||
is supposed to be "(I/O base),(IRQ)", so I used the same numbers
|
||||
as I put in /etc/isapnp.conf, i.e., 0x260,3.
|
||||
|
||||
For the Data Translation board, I need to have a list of the
|
||||
jumper settings. Fortunately, I wrote them all down in the
|
||||
manual -- I hope they are still correct. However, I had to
|
||||
open the case to figure out which board in the series I had.
|
||||
It is a DT2821-f-8di. The man page of comedi_config tells
|
||||
me that I need to know the I/O base, IRQ, DMA 1, DMA 2. However,
|
||||
since I wrote the driver, I know that it also recognizes the
|
||||
differential/single-ended and unipolar/bipolar jumpers. As always,
|
||||
the source is the final authority, and looking in module/dt282x.c
|
||||
tells me that the options list is interpreted as:
|
||||
|
||||
<itemize>
|
||||
<item>I/O base
|
||||
<item>IRQ
|
||||
<item>1=differential, 0=single ended
|
||||
<item>ai 0=unipolar, 1=bipolar
|
||||
<item>ao0 0=unipolar, 1=bipolar
|
||||
<item>ao1 0=unipolar, 1=bipolar
|
||||
<item>dma1
|
||||
<item>dma2
|
||||
</itemize>
|
||||
|
||||
(ai=analog input, ao=analog output.) From this, I decide that
|
||||
the appropriate options list is
|
||||
|
||||
<tscreen><verb>
|
||||
0x200,4,,1,1,1
|
||||
</verb></tscreen>
|
||||
|
||||
I left the differential/single-ended number blank, since the
|
||||
driver already knowns (from the board name), that it is
|
||||
differential. I also left the DMA numbers blank, since I
|
||||
don't want the driver to use DMA. (Don't want it to interfere
|
||||
with my sound card -- life is full of difficult choices.)
|
||||
Keep in mind that things commented in the source, but not in
|
||||
the documentation are about as likely to change as the weather,
|
||||
so I put good comments next to the following line when I put
|
||||
it in rc.local.
|
||||
|
||||
<tscreen><verb>
|
||||
/usr/sbin/comedi_config /dev/comedi1 dt2821-f-8di 0x200,4,,1,1,1
|
||||
</verb></tscreen>
|
||||
|
||||
So now I think that I have my boards configured correctly.
|
||||
Since data acquisition boards are not typically well-engineered,
|
||||
comedi sometimes can't figure out if the board is actually there.
|
||||
If it can't, it assumes you are right. Both of these boards
|
||||
are well-made, so comedi will give me an error message if it
|
||||
can't find them. The comedi kernel module, since it is a part
|
||||
of the kernel, prints messages to the kernel logs, which you
|
||||
can access through the command 'dmesg' or /var/log/messages.
|
||||
Here is a configuration failure (from dmesg):
|
||||
|
||||
<tscreen><verb>
|
||||
comedi0: ni_E: 0x0200 can't find board
|
||||
</verb></tscreen>
|
||||
|
||||
When it does work, I get:
|
||||
|
||||
<tscreen><verb>
|
||||
comedi0: ni_E: 0x0260 at-mio-16e-10 ( irq = 3 )
|
||||
</verb></tscreen>
|
||||
|
||||
Note that it also correctly identified my board.
|
||||
|
||||
|
||||
<p>
|
||||
<sect1>Getting information from comedi
|
||||
<p>
|
||||
|
||||
|
||||
So now that we have comedi talking to the hardware, we want to
|
||||
talk to comedi. Here's some pretty low-level information --
|
||||
it's sometimes useful for debugging:
|
||||
|
||||
<p>
|
||||
|
||||
<tscreen><verb>
|
||||
cat /proc/comedi
|
||||
</verb></tscreen>
|
||||
|
||||
Right now, on my computer, this command gives:
|
||||
|
||||
<tscreen><verb>
|
||||
comedi version 0.6.4
|
||||
format string
|
||||
0: atmio-E at-mio-16e-10 7
|
||||
1: dt282x dt2821-f-8di 4
|
||||
</verb></tscreen>
|
||||
|
||||
This is a feature that is not well-developed yet. Basically, it
|
||||
currently tells you driver name, device name, and number of
|
||||
subdevices.
|
||||
|
||||
In the <tt>demo/</tt> directory, there is a command called
|
||||
<tt>info</tt>, which provides information about each subdevice on the
|
||||
board. The output of it is rather long, since I have 7
|
||||
subdevices (4 or fewer is common for other boards.)
|
||||
Here's part of the output of the NI board (which
|
||||
is on <tt>/dev/comedi0</tt>.) ('demo/info /dev/comedi0')
|
||||
|
||||
<tscreen><verb>
|
||||
overall info:
|
||||
version code: 0x000604
|
||||
driver name: atmio-E
|
||||
board name: at-mio-16e-10
|
||||
number of subdevices: 7
|
||||
subdevice 0:
|
||||
type: 1 (unknown)
|
||||
number of channels: 16
|
||||
max data value: 4095
|
||||
</verb>
|
||||
...
|
||||
</tscreen>
|
||||
|
||||
The overall info gives information about the device -- basically
|
||||
the same information as /proc/comedi.
|
||||
|
||||
This board has 7 subdevices. Devices are separated into
|
||||
subdevices that each have a distinct purpose -- e.g., analog
|
||||
input, analog output, digital input/output. This board also
|
||||
has an EEPROM and calibration DACs that are also subdevices.
|
||||
|
||||
Subdevice 0 is the analog input subdevice. You would have
|
||||
known this from the 'type: 1 (unknown)' line, if I've updated
|
||||
demo/info recently, because it would say 'type: 1 (analog input)'
|
||||
instead. The other lines should be self-explanitory. Comedi
|
||||
has more information about the device, but demo/info doesn't
|
||||
currently display this.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<sect>Writing programs that use comedi and comedilib
|
||||
<p>
|
||||
|
||||
<sect1>Your first comedi program
|
||||
<p>
|
||||
<section>
|
||||
<title>
|
||||
Your first comedi program
|
||||
</title>
|
||||
|
||||
<para>
|
||||
This example requires a card that has analog or
|
||||
digital input. Right to the source:
|
||||
</para>
|
||||
|
||||
<tscreen><verb>
|
||||
#include <stdio.h> /* for printf() */
|
||||
#include <comedilib.h>
|
||||
<programlisting>
|
||||
#include <stdio.h> /* for printf() */
|
||||
#include <comedilib.h>
|
||||
|
||||
int subdev = 0; /* change this to your input subdevice */
|
||||
int chan = 0; /* change this to your channel */
|
||||
|
@ -224,33 +38,40 @@ int main(int argc,char *argv[])
|
|||
|
||||
return 0;
|
||||
}
|
||||
</verb></tscreen>
|
||||
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
Should be understandable: open the device, get the data,
|
||||
print it out. This is basically the guts of <tt>demo/inp.c</tt>,
|
||||
print it out. This is basically the guts of <filename>demo/inp.c</filename>,
|
||||
without error checking or fancy options.
|
||||
Compile it using
|
||||
</para>
|
||||
|
||||
<tscreen><verb>
|
||||
<screen>
|
||||
cc tut1.c -lcomedi -o tut1
|
||||
</verb></tscreen>
|
||||
</screen>
|
||||
|
||||
<para>
|
||||
A few notes: The range variable tells comedi which gain
|
||||
to use when measuring an analog voltage. Since we don't
|
||||
know (yet) which numbers are valid, or what each means,
|
||||
we'll use 0, because it won't cause errors. Likewise with
|
||||
aref, which determines the analog reference used.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
<p>
|
||||
<sect1>Converting samples to voltages
|
||||
<p>
|
||||
<section>
|
||||
<title>
|
||||
Converting samples to voltages
|
||||
</title>
|
||||
|
||||
<para>
|
||||
If you selected an analog input subdevice, you probably noticed
|
||||
that the output of <tt>tut1</tt> is a number between
|
||||
that the output of <command>tut1</command> is a number between
|
||||
0 and 4095, or 0 and 65535, depending on the number of bits
|
||||
in the A/D converter. Comedi samples are <bf>always</bf> unsigned,
|
||||
in the A/D converter. Comedi samples are <emphasis>always</emphasis>
|
||||
unsigned,
|
||||
with 0 representing the lowest voltage of the ADC, and 4095
|
||||
the highest. Comedi compensates for
|
||||
anything else the manual for your device says. However,
|
||||
|
@ -258,46 +79,65 @@ you probably prefer to have this number translated to
|
|||
a voltage. Naturally, as a good programmer, your first
|
||||
question is: "How do I do this in a device-independent
|
||||
manner?"
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Most devices give you a choice of gain and unipolar/bipolar
|
||||
input, and Comedi allows you to select which of these to
|
||||
use. This parameter is called the "range parameter", since
|
||||
it specifies the "input range" for analog input (or "output range"
|
||||
for analog output.) The range parameter represents both the gain
|
||||
and the unipolar/bipolar aspects.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Comedi keeps the number of available ranges and the largest
|
||||
sample value for each subdevice/channel combination. (Some
|
||||
devices allow different input/output ranges for different
|
||||
channels in a subdevice.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The largest sample value can be found using the function:
|
||||
</para>
|
||||
|
||||
comedi_get_maxdata()
|
||||
<programlisting>
|
||||
comedi_get_maxdata()
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
The number of available ranges can be found using the function:
|
||||
</para>
|
||||
|
||||
comedi_get_n_ranges()
|
||||
<programlisting>
|
||||
comedi_get_n_ranges()
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
For each value of the range parameter for a particular
|
||||
subdevice/channel, you can get range information using the
|
||||
function:
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
ptr=comedi_get_range(comedi_file,subdevice,channel,
|
||||
range)
|
||||
range);
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
which returns a pointer to a comedi_range structure.
|
||||
The comedi_range structure looks like
|
||||
</para>
|
||||
|
||||
<p>
|
||||
<tscreen><verb>
|
||||
<programlisting>
|
||||
typedef struct{
|
||||
double min;
|
||||
double max;
|
||||
unsigned int unit;
|
||||
}comedi_range;
|
||||
</verb></tscreen>
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
The structure element 'min' represents
|
||||
the voltage corresponding to comedi_data_read() returning 0,
|
||||
and 'max' represents comedi_data_read() returning 'maxdata',
|
||||
|
@ -305,75 +145,96 @@ and 'max' represents comedi_data_read() returning 'maxdata',
|
|||
or, 1 for digital input -- more on this in a bit.) The
|
||||
'unit' entry tells you if min and
|
||||
max refer to voltage, current, etc.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
"Could it get easier?", you say. Well, yes. Use
|
||||
the function comedi_to_phys(), which converts data
|
||||
values to physical units. Call it using something like
|
||||
</para>
|
||||
|
||||
<tscreen><verb>
|
||||
<programlisting>
|
||||
volts=comedi_to_phys(it,data,range,maxdata);
|
||||
</verb></tscreen>
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
and the opposite
|
||||
</para>
|
||||
|
||||
<tscreen><verb>
|
||||
<programlisting>
|
||||
data=comedi_from_phys(it,volts,range,maxdata);
|
||||
</verb></tscreen>
|
||||
|
||||
|
||||
<p>
|
||||
<sect1>Another section
|
||||
<p>
|
||||
</programlisting>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>
|
||||
Another section
|
||||
</title>
|
||||
|
||||
|
||||
<para>
|
||||
In addition to providing low level routines for data
|
||||
access, the comedi library provides higher-level access,
|
||||
much like the standard C library provides fopen(), etc.
|
||||
as a high-level (and portable) alternative to the direct
|
||||
UNIX system calls open(), etc. Similarily to fopen(),
|
||||
we have comedi_open():
|
||||
</para>
|
||||
|
||||
<p>
|
||||
<tscreen><verb>
|
||||
<programlisting>
|
||||
file=comedi_open("/dev/comedi0");
|
||||
</verb></tscreen>
|
||||
</programlisting>
|
||||
|
||||
where file is of type <tt>(comedi_t *)</tt>. This function
|
||||
calls <tt>open()</tt>, like we did explicitly in a previous
|
||||
section, but also fills the <tt>comedi_t</tt> structure with
|
||||
<para>
|
||||
where file is of type (comedi_t *). This function
|
||||
calls <function>open()</function>, like we did explicitly in a previous
|
||||
section, but also fills the comedi_t structure with
|
||||
lots of goodies -- information that we will need to use
|
||||
soon.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Specifically, we needed to know maxdata for a specific
|
||||
subdevice/channel. How about:
|
||||
</para>
|
||||
|
||||
<tscreen><verb>
|
||||
<programlisting>
|
||||
maxdata=comedi_get_maxdata(file,subdevice,channel);
|
||||
</verb></tscreen>
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
Wow. How easy. And the range type?
|
||||
</para>
|
||||
|
||||
<tscreen><verb>
|
||||
<programlisting>
|
||||
range_type=comedi_get_rangetype(file,subdevice,channel);
|
||||
</verb></tscreen>
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
Cool. Other information you need to know about a channel
|
||||
can be gotten in a similar way.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<sect1>Your second comedi program
|
||||
<p>
|
||||
<section>
|
||||
<title>
|
||||
Your second comedi program
|
||||
</title>
|
||||
|
||||
|
||||
<para>
|
||||
Actually, this is the first comedi program again, just
|
||||
that we've added what we've learned.
|
||||
</para>
|
||||
|
||||
|
||||
<tscreen><verb>
|
||||
#include <stdio.h> /* for printf() */
|
||||
#include <comedi.h> /* also included by comedilib.h */
|
||||
#include <comedilib.h> /* 'cuz we're using comedilib */
|
||||
<programlisting>
|
||||
#include <stdio.h> /* for printf() */
|
||||
#include <comedi.h> /* also included by comedilib.h */
|
||||
#include <comedilib.h> /* 'cuz we're using comedilib */
|
||||
|
||||
int subdev = 0; /* change this to your input subdevice */
|
||||
int chan = 0; /* change this to your channel */
|
||||
|
@ -402,271 +263,8 @@ int main(int argc,char *argv[])
|
|||
|
||||
return 0;
|
||||
}
|
||||
</verb></tscreen>
|
||||
</programlisting>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<p>
|
||||
<sect>Application-specific functions
|
||||
<p>
|
||||
|
||||
<sect1>Digital Input/Output
|
||||
<p>
|
||||
|
||||
Many boards supported by comedi have digital input and output
|
||||
channels. Some boards allow the direction of a channel to be
|
||||
specified in software.
|
||||
|
||||
Comedi groups digital channels into 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 digital lines can be read and written using the
|
||||
functions
|
||||
|
||||
<tt/comedi_dio_read(device,subdevice,channel,unsigned int *bit);/
|
||||
<tt/comedi_dio_write(device,subdevice,channel,unsigned int bit);/
|
||||
|
||||
The direction of bidirectional lines can be configured using
|
||||
the function
|
||||
|
||||
<tt/comedi_dio_config(device,subdevice,channel,unsigned int dir);/
|
||||
|
||||
The parameter <tt/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
|
||||
|
||||
<tt/comedi_dio_bitfield(device,subdevice,unsigned int write_mask,unsigned int *bits);/
|
||||
|
||||
Each channel is assigned to a bit in the <tt/write_mask/ and <tt/bits/
|
||||
bitfield. If a bit in <tt/write_mask/ is set, the corresponding bit
|
||||
in <tt/*bits/ will be written to the corresponding digital output line.
|
||||
Each digital line is then read and placed into <tt/*bits/. The value
|
||||
of bits in <tt/*bits/ corresponding to digital output lines is
|
||||
undefined and device-specific. Channel 0 is the least significant
|
||||
bit in the bitfield; channel 31 is the most significant bit. Channels
|
||||
higher than 31 cannot be accessed using this method.
|
||||
|
||||
|
||||
<p>
|
||||
<sect1>Slowly-varying inputs
|
||||
<p>
|
||||
|
||||
|
||||
Sometimes, your input channels change slowly enough that
|
||||
you are able to average many sucessive input values to get a
|
||||
more accurate measurement of the actual value. In general,
|
||||
the more samples you average, the better your estimate
|
||||
gets, roughly by a factor of sqrt(number_of_samples).
|
||||
Obviously, there are limitations to this:
|
||||
|
||||
<p>
|
||||
<itemize>
|
||||
<item>
|
||||
you are ultimately limited by "spurious free dynamic range"
|
||||
|
||||
<item>
|
||||
you need to have _some_ noise on the input channel,
|
||||
otherwise you will be averaging the same number N times.
|
||||
|
||||
<item>
|
||||
the more noise you have, the greater your SFDR, but it
|
||||
takes many more samples to compensate for the increased
|
||||
noise
|
||||
|
||||
<item>
|
||||
if you feel the need to average samples for 2 seconds,
|
||||
your signal will need to be _very_ slowly-varying, i.e.,
|
||||
not varying more than your target uncertainty for the
|
||||
entire 2 seconds.
|
||||
|
||||
</itemize>
|
||||
|
||||
As you might have guessed, the comedi library has functions
|
||||
to help you in your quest to accurately measure slowly varying
|
||||
inputs. I use these functions to measure thermocouple voltages
|
||||
-- actually, the library functions came from a section of code
|
||||
that was previously part of the thermocouple reading program.
|
||||
|
||||
The comedi self-calibration utility also uses these functions.
|
||||
On some hardware, it is possible to tell it to measure an
|
||||
internal stable voltage reference, which is typically going
|
||||
to be very slowly varying -- on the kilosecond time scale
|
||||
or more. So it is reasonable to measure millions of samples,
|
||||
to get a very accurate measurement of the A/D converter output
|
||||
value that corresponds to the voltage reference. Sometimes,
|
||||
however, this is overkill, since there is no need to
|
||||
perform a part-per-million calibration to a standard that
|
||||
is only accurate to part-per-thousand.
|
||||
|
||||
|
||||
<p>
|
||||
<sect1>Commands
|
||||
<label id="command_section">
|
||||
<p>
|
||||
|
||||
|
||||
Many data acquisition devices have the capability to directly
|
||||
control acquisition using either an on-board timer or an external
|
||||
triggering input. Comedi commands are used to control this kind
|
||||
of acquisition. The <ref id="comedi_cmd" name="comedi_cmd"> structure is
|
||||
used to control acquisition and query the capabilities of a device
|
||||
(see also <ref id="comedi_command" name="comedi_command()">,
|
||||
<ref id="comedi_command_test" name="comedi_command_test()">, and
|
||||
<ref id="comedi_get_cmd_src_mask" name="comedi_get_cmd_src_mask()">).
|
||||
|
||||
Commands specify a particular data acquisition sequence, which
|
||||
is comprised of a number of scans. Each scan is comprised of
|
||||
a number of conversions, which usually corresponds to a single
|
||||
A/D or D/A conversion. The start and end of the sequence, and
|
||||
the start and end of each scan, and each conversion is called an
|
||||
event.
|
||||
|
||||
Each of these 5 types of events are caused by a triggering
|
||||
source, specified through the <tt/*_src/ members of the
|
||||
<ref id="comedi_cmd" name="comedi_cmd"> structure. The source types are:
|
||||
|
||||
<itemize>
|
||||
<item>TRIG_NONE: don't ever cause an event
|
||||
<item>TRIG_NOW: cause event to occur immediately
|
||||
<item>TRIG_FOLLOW: see notes below
|
||||
<item>TRIG_TIME: cause event to occur at a particular time
|
||||
<item>TRIG_TIMER: cause event to occur repeatedly at a specific rate
|
||||
<item>TRIG_COUNT: cause event when count reaches specific value
|
||||
<item>TRIG_EXT: external signal causes event
|
||||
<item>TRIG_INT: internal signal causes event
|
||||
<item>TRIG_OTHER: driver-specific meaning
|
||||
</itemize>
|
||||
|
||||
Not all triggers are applicable to all events. Supported triggers
|
||||
for specific events depend significantly on your particular
|
||||
device. The <ref id="comedi_get_cmd_src_mask" name="comedi_get_cmd_src_mask()">
|
||||
function is useful for determining what triggers a subdevice supports.
|
||||
|
||||
For every trigger, there is a corresponding
|
||||
argument (the <tt/*_arg/ members of the <ref id="comedi_cmd" name="comedi_cmd">
|
||||
structure) whose meaning depends on the type of trigger. The meanings
|
||||
of the arguments are as follows:
|
||||
|
||||
TRIG_NONE is typically used only as a <tt/stop_src/. The argument for TRIG_NONE
|
||||
is reserved and should be set to 0.
|
||||
|
||||
TRIG_NOW is most often used as a <tt/start_src/. The argument for TRIG_NOW is
|
||||
the number of nanoseconds between when the command is issued and when
|
||||
the event should occur. In the case of using TRIG now as a <tt/start_src/,
|
||||
it indicates a delay between issuing the command and the start of
|
||||
acquisition. Most drivers only support a delay of 0.
|
||||
|
||||
TRIG_FOLLOW is a special type of trigger for events that trigger on
|
||||
the completion of some other, logically connected event. The argument
|
||||
is reserved and should be set to 0. When used
|
||||
as a <tt/scan_begin_src/, it indicates that a trigger should occur as a
|
||||
logical continuation of convert events. This is done in order to
|
||||
properly describe boards that do not have separate timers for
|
||||
convert and scan_begin events. When used as a <tt/start_src/ for analog
|
||||
output subdevices, it indicates that conversion of output samples
|
||||
should begin when samples are written to the buffer.
|
||||
|
||||
TRIG_TIME is reserved for future use.
|
||||
|
||||
TRIG_TIMER is most often used as a <tt/convert_src/, a <tt/scan_begin_src/, or
|
||||
both. It indicates that triggers should occur at a specific rate.
|
||||
The argument specifies the interval between triggers in nanoseconds.
|
||||
|
||||
TRIG_COUNT is used for <tt/scan_end_src/ and <tt/stop_src/. It indicates that
|
||||
a trigger should occur when the specified number of corresponding
|
||||
lower-level triggers (convert and scan_begin, respectively) occur.
|
||||
The argument is the count of lower-level triggers.
|
||||
|
||||
TRIG_EXT can be useful as any of the trigger sources. It indicates
|
||||
that an external digital line should be used to trigger the event.
|
||||
The exact meaning of digital line is device-dependent. Some devices
|
||||
have one dedicated line, others may allow generic digital input
|
||||
lines to be used. The argument indicates the particular external
|
||||
line to use as the trigger.
|
||||
|
||||
TRIG_INT is typically used as a <tt/start_src/. This trigger occurs when
|
||||
the application performs an INSN_INTTRIG instruction. Using TRIG_INT
|
||||
is a method by which the application can accurately record the time of
|
||||
the start of acquisition, since the parsing and setup time of a
|
||||
particular command may be significant. The argument associated with
|
||||
TRIG_INT is reserved and should be set to 0.
|
||||
|
||||
TRIG_OTHER can be useful as any of the trigger sources. The exact
|
||||
meaning of TRIG_OTHER is driver-specific, and implements a feature
|
||||
that otherwise does not fit into the command interface. Configuration
|
||||
of TRIG_OTHER features are done by INSN_CONFIG insns. The argument
|
||||
is reserved and should be set to 0.
|
||||
|
||||
Ths <tt/subdev/ member of the <ref id="comedi_cmd" name="comedi_cmd">
|
||||
structure is the index of the subdevice the command is intended for. The
|
||||
<ref id="comedi_find_subdevice_by_type" name="comedi_find_subdevice_by_type()">
|
||||
function can be useful in discovering the index of your desired subdevice.
|
||||
|
||||
The <tt/chanlist/ member of the <ref id="comedi_cmd" name="comedi_cmd">
|
||||
structure should point to an array whose number of elements is specificed by <tt/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 <ref id="CR_PACK" name="CR_PACK()"> macro.
|
||||
|
||||
The <tt/data/ and <tt/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 <ref id="comedi_cmd" name="comedi_cmd"> structure is <tt/flags/.
|
||||
The following flags are valid, and can be bitwise-or'd together.
|
||||
|
||||
<itemize>
|
||||
<item>TRIG_BOGUS: do the motions??
|
||||
<item>TRIG_DITHER: enable dithering??
|
||||
<item>TRIG_DEGLITCH: enable deglitching??
|
||||
<item>TRIG_RT: ask 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
|
||||
fifo. You must have a real-time kernel (RTAI or RTLinux) and must compile
|
||||
comedi with real-time support or this flag will do nothing.
|
||||
<item>TRIG_CONFIG: perform configuration, not triggering. This is a legacy of the
|
||||
deprecated comedi_trig_struct, and has no function at present.
|
||||
<item>TRIG_WAKE_EOS: 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 onboard fifo is half full). This flag
|
||||
may degrade a driver's performance at high frequencies.
|
||||
<item>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.
|
||||
</itemize>
|
||||
There are also a few flags that indicate how timing arguments should be rounded
|
||||
if the hardware cannot achieve the exact timing requested.
|
||||
<itemize>
|
||||
<item>TRIG_ROUND_NEAREST: round to nearest supported timing period, the default.
|
||||
<item>TRIG_ROUND_DOWN: round period down.
|
||||
<item>TRIG_ROUND_UP: round period up.
|
||||
<item>TRIG_ROUND_UP_NEXT: this one doesn't do anything, and I don't know what it was intended
|
||||
to do??
|
||||
</itemize>
|
||||
|
||||
<p>
|
||||
|
||||
The typical sequence for executing a command is to first send
|
||||
the command through
|
||||
<ref id="comedi_command_test" name="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. The
|
||||
command is executed with
|
||||
<ref id="comedi_command" name="comedi_command()">. For input/output commands, data
|
||||
is read from or written to the device file /dev/comedi[0..3] you are using.
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue