removed obsolete advanced.sgml. Got rid of references to hard-coded
comedi_config paths
This commit is contained in:
parent
c06d17d1dd
commit
598fa693a6
3 changed files with 7 additions and 677 deletions
|
@ -1,6 +1,6 @@
|
|||
|
||||
DOC=comedilib
|
||||
SGML= advanced.sgml drivers.sgml funcref.sgml glossary.sgml \
|
||||
SGML= drivers.sgml funcref.sgml glossary.sgml \
|
||||
install.sgml intro.sgml other.sgml reference.sgml tutorial.sgml
|
||||
|
||||
EXTRA_DIST=$(SGML) funcref mkref drivers.txt mkdr
|
||||
|
|
|
@ -1,672 +0,0 @@
|
|||
<p>
|
||||
<sect1>Configuring comedi for your hardware
|
||||
<p>
|
||||
|
||||
|
||||
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.
|
||||
|
||||
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>
|
||||
|
||||
This example requires a card that has analog or
|
||||
digital input. Right to the source:
|
||||
|
||||
<tscreen><verb>
|
||||
#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 */
|
||||
int range = 0; /* more on this later */
|
||||
int aref = AREF_GROUND; /* more on this later */
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
comedi_t *it;
|
||||
lsampl_t data;
|
||||
|
||||
it=comedi_open("/dev/comedi0");
|
||||
|
||||
comedi_data_read(it,subdev,chan,range,aref,&data);
|
||||
|
||||
printf("%d\n",data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
</verb></tscreen>
|
||||
|
||||
|
||||
Should be understandable: open the device, get the data,
|
||||
print it out. This is basically the guts of <tt>demo/inp.c</tt>,
|
||||
without error checking or fancy options.
|
||||
Compile it using
|
||||
|
||||
<tscreen><verb>
|
||||
cc tut1.c -lcomedi -o tut1
|
||||
</verb></tscreen>
|
||||
|
||||
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.
|
||||
|
||||
|
||||
<p>
|
||||
<sect1>Converting samples to voltages
|
||||
<p>
|
||||
|
||||
If you selected an analog input subdevice, you probably noticed
|
||||
that the output of <tt>tut1</tt> 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,
|
||||
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,
|
||||
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?"
|
||||
|
||||
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.
|
||||
|
||||
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.)
|
||||
|
||||
The largest sample value can be found using the function:
|
||||
|
||||
comedi_get_maxdata()
|
||||
|
||||
The number of available ranges can be found using the function:
|
||||
|
||||
comedi_get_n_ranges()
|
||||
|
||||
For each value of the range parameter for a particular
|
||||
subdevice/channel, you can get range information using the
|
||||
function:
|
||||
|
||||
ptr=comedi_get_range(comedi_file,subdevice,channel,
|
||||
range)
|
||||
|
||||
which returns a pointer to a comedi_range structure.
|
||||
The comedi_range structure looks like
|
||||
|
||||
<p>
|
||||
<tscreen><verb>
|
||||
typedef struct{
|
||||
double min;
|
||||
double max;
|
||||
unsigned int unit;
|
||||
}comedi_range;
|
||||
</verb></tscreen>
|
||||
|
||||
The structure element 'min' represents
|
||||
the voltage corresponding to comedi_data_read() returning 0,
|
||||
and 'max' represents comedi_data_read() returning 'maxdata',
|
||||
(i.e., 4095 for 12 bit A/C converters, 65535 for 16 bit,
|
||||
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.
|
||||
|
||||
"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
|
||||
|
||||
<tscreen><verb>
|
||||
volts=comedi_to_phys(it,data,range,maxdata);
|
||||
</verb></tscreen>
|
||||
|
||||
and the opposite
|
||||
|
||||
<tscreen><verb>
|
||||
data=comedi_from_phys(it,volts,range,maxdata);
|
||||
</verb></tscreen>
|
||||
|
||||
|
||||
<p>
|
||||
<sect1>Another section
|
||||
<p>
|
||||
|
||||
|
||||
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():
|
||||
|
||||
<p>
|
||||
<tscreen><verb>
|
||||
file=comedi_open("/dev/comedi0");
|
||||
</verb></tscreen>
|
||||
|
||||
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
|
||||
lots of goodies -- information that we will need to use
|
||||
soon.
|
||||
|
||||
Specifically, we needed to know maxdata for a specific
|
||||
subdevice/channel. How about:
|
||||
|
||||
<tscreen><verb>
|
||||
maxdata=comedi_get_maxdata(file,subdevice,channel);
|
||||
</verb></tscreen>
|
||||
|
||||
Wow. How easy. And the range type?
|
||||
|
||||
<tscreen><verb>
|
||||
range_type=comedi_get_rangetype(file,subdevice,channel);
|
||||
</verb></tscreen>
|
||||
|
||||
Cool. Other information you need to know about a channel
|
||||
can be gotten in a similar way.
|
||||
|
||||
|
||||
|
||||
<sect1>Your second comedi program
|
||||
<p>
|
||||
|
||||
|
||||
Actually, this is the first comedi program again, just
|
||||
that we've added what we've learned.
|
||||
|
||||
|
||||
<tscreen><verb>
|
||||
#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 */
|
||||
int range = 0; /* more on this later */
|
||||
int aref = 0; /* more on this later */
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
comedi_t *cf;
|
||||
int chan=0;
|
||||
lsampl_t data;
|
||||
int maxdata,rangetype;
|
||||
double volts;
|
||||
|
||||
cf=comedi_open("/dev/comedi0");
|
||||
|
||||
maxdata=comedi_get_maxdata(cf,subdev,chan);
|
||||
|
||||
rangetype=comedi_get_rangetype(cf,subdev,chan);
|
||||
|
||||
comedi_data_read(cf->fd,subdev,chan,range,aref,&data);
|
||||
|
||||
volts=comedi_to_phys(data,rangetype,range,maxdata);
|
||||
|
||||
printf("%d %g\n",data,volts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
</verb></tscreen>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<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.
|
||||
|
|
@ -58,11 +58,12 @@ information here to remind myself that the numbers aren't arbitrary.
|
|||
<para>
|
||||
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
|
||||
I boot, I put the lines
|
||||
</para>
|
||||
|
||||
<screen>
|
||||
/usr/sbin/comedi_config /dev/comedi0 ni_atmio 0x260,3
|
||||
export PATH=/sbin:/usr/sbin:/usr/local/sbin:$PATH
|
||||
comedi_config /dev/comedi0 ni_atmio 0x260,3
|
||||
</screen>
|
||||
|
||||
<para>
|
||||
|
@ -115,12 +116,13 @@ 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
|
||||
so I put good comments next to the following lines when I put
|
||||
it in rc.local.
|
||||
</para>
|
||||
|
||||
<screen>
|
||||
/usr/sbin/comedi_config /dev/comedi1 dt2821-f-8di 0x200,4,,1,1,1
|
||||
export PATH=/sbin:/usr/sbin:/usr/local/sbin:$PATH
|
||||
comedi_config /dev/comedi1 dt2821-f-8di 0x200,4,,1,1,1
|
||||
</screen>
|
||||
|
||||
<para>
|
||||
|
|
Loading…
Add table
Reference in a new issue