Converting docs to DocBook 3.1
authorDavid Schleef <ds@schleef.org>
Mon, 21 Jan 2002 11:15:31 +0000 (11:15 +0000)
committerDavid Schleef <ds@schleef.org>
Mon, 21 Jan 2002 11:15:31 +0000 (11:15 +0000)
12 files changed:
doc/docbook/Makefile [new file with mode: 0644]
doc/docbook/advanced.sgml [new file with mode: 0644]
doc/docbook/comedilib.sgml [new file with mode: 0644]
doc/docbook/drivers.txt [new file with mode: 0644]
doc/docbook/funcref [new file with mode: 0644]
doc/docbook/install.sgml [new file with mode: 0644]
doc/docbook/intro.sgml [new file with mode: 0644]
doc/docbook/mkdr [new file with mode: 0755]
doc/docbook/mkref [new file with mode: 0755]
doc/docbook/other.sgml [new file with mode: 0644]
doc/docbook/reference.sgml [new file with mode: 0644]
doc/docbook/tutorial.sgml [new file with mode: 0644]

diff --git a/doc/docbook/Makefile b/doc/docbook/Makefile
new file mode 100644 (file)
index 0000000..aa575a4
--- /dev/null
@@ -0,0 +1,18 @@
+
+all: drivers.sgml funcref.sgml
+       -mkdir html
+       -mkdir man
+       -docbook2html -o html comedilib.sgml
+       -docbook2man -o man comedilib.sgml
+
+funcref.sgml: funcref mkref
+       ./mkref funcref >funcref.sgml
+
+drivers.sgml: drivers.txt mkdr
+       ./mkdr drivers.txt >drivers.sgml
+
+clean:
+       -rm -rf html
+       -rm -rf man
+       -rm -f drivers.sgml funcref.sgml
+
diff --git a/doc/docbook/advanced.sgml b/doc/docbook/advanced.sgml
new file mode 100644 (file)
index 0000000..d5f6303
--- /dev/null
@@ -0,0 +1,672 @@
+<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,&amp;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,&amp;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.
+
diff --git a/doc/docbook/comedilib.sgml b/doc/docbook/comedilib.sgml
new file mode 100644 (file)
index 0000000..a331196
--- /dev/null
@@ -0,0 +1,69 @@
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V3.1//EN"
+       "docbook/dtd/3.1/docbook.dtd" [
+<!ENTITY intro SYSTEM "intro.sgml">
+<!ENTITY install SYSTEM "install.sgml">
+<!ENTITY drivers SYSTEM "drivers.sgml">
+<!ENTITY reference SYSTEM "reference.sgml">
+<!ENTITY funcref SYSTEM "funcref.sgml">
+]>
+
+<article>
+
+<artheader>
+  <title>
+    Comedi Documentation
+  </title>
+  <author>
+    <firstname>David</firstname>
+    <surname>Schleef</surname>
+    <affiliation>
+      <address>
+        ds@schleef.org
+      </address>
+    </affiliation>
+  </author>
+  <author>
+    <firstname>Frank</firstname>
+    <surname>Hess</surname>
+    <affiliation>
+      <address>
+        fmhess@uiuc.edu
+      </address>
+    </affiliation>
+  </author>
+</artheader>
+
+&intro
+
+&install
+
+<section>
+<title>
+Writing programs that use Comedi
+</title>
+<para>
+Empty.
+</para>
+</section>
+
+&drivers
+
+<section>
+  <title>
+    Comedi Reference
+  </title>
+  <para>
+    Reference for functions, macros, and constants.
+  </para>
+
+  &reference
+
+  &funcref
+
+</section>
+
+
+
+
+</article>
+
diff --git a/doc/docbook/drivers.txt b/doc/docbook/drivers.txt
new file mode 100644 (file)
index 0000000..d362f40
--- /dev/null
@@ -0,0 +1,1075 @@
+Driver: 8255.o
+Description: generic 8255 support
+Devices: [standard] 8255 (8255)
+Author: ds
+
+The classic in digital I/O.  Three channels of 8 bit digital I/O,
+each channel is I/O configurable, channels 0 and 1 in 8 bit units,
+channel 2 in 4 bit units.  The driver does not support modes 1 or 2
+yet, since I don't really understand how they would potentially be used.
+(Send me email if you want to use these modes.)  If and when
+modes 1 and 2 are supported, there is a strong possibility that the
+3rd channel will be split into two 4-bit channels.  (Refer to the
+8255 spec for clues as to why.)
+
+You should configure this driver if you plan to use a board that
+has an 8255 chip.  For multifunction boards, the main driver will
+configure the 8255 subdevice automatically.
+
+This driver also works independently with ISA cards that directly
+map the 8255 registers to I/O ports, including cards with multiple
+8255 chips.  To configure the driver for such a card, the option
+list should be a list of the I/O port bases for each of the 8255
+chips.
+
+
+
+Driver: adl_pci9118.o
+Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR
+Author: Michal Dobes <majkl@tesnet.cz>
+Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg),
+  PCI-9118HR (pci9118hr)
+Status: works
+
+This driver supports AI, AO, DI and DO subdevices.
+AI subdevice supports cmd and insn interface,
+other subdevices support only insn interface.
+For AI:
+- If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46).
+- If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44).
+- If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46).
+- It is not neccessary to have cmd.scan_end_arg=cmd.chanlist_len but
+  cmd.scan_end_arg modulo cmd.chanlist_len must by 0.
+- If return value of cmdtest is 5 then you've bad channel list
+  (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar
+  ranges).
+There is know problem with this driver:
+- If you use scan_begin_src=TRIG_EXT & convert_src=TRIG_TIMER
+  then this mode sometimes discards some samples. :-((
+
+Configuration options:
+  [0] - PCI bus of device (optional)
+  [1] - PCI slot of device (optional)
+          If bus/slot is not specified, the first available PCI
+          device will be used.
+
+If you have an external multiplexer, the third option in the option
+list should be used to indicate the number of channels in the
+multiplexer.
+
+
+
+Driver: adv_pci1710.o
+Description: Advantech PCI-1710, PCI-1710HG, PCI-1711, PCI-1713,
+             Advantech PCI-1720, PCI-1731
+Author: Michal Dobes <majkl@tesnet.cz>
+Devices: [Advantech] PCI-1710 (pci1710), PCI-1710HG (pci1710hg),
+  PCI-1711 (pci1711), PCI-1713 (pci1713), PCI-1720 (pci1720),
+  PCI-1731 (pci1731)
+Status: works
+
+This driver supports AI, AO, DI and DO subdevices.
+AI subdevice supports cmd and insn interface,
+other subdevices support only insn interface.
+
+The PCI-1710 and PCI-1710HG have the same PCI device ID, so the
+driver cannot distinguish between them, as would be normal for a
+PCI driver.
+
+Configuration options:
+  [0] - PCI bus of device (optional)
+  [1] - PCI slot of device (optional)
+          If bus/slot is not specified, the first available PCI
+          device will be used.
+
+
+
+Driver: amplc_pci230.o
+Description: Driver for Amplicom PCI230 and PCI260 Multifunction I/O boards
+Author: Allan Willcox <allanwillcox@ozemail.com.au>
+Updated: Mon,  3 Sep 2001 17:37:12 -0700
+Devices: [Amplicon] PCI230 (amplc_pci230), PCI260
+
+
+
+Driver: cb_pcidas.o
+Description: Driver for the ComputerBoards/MeasurementComputing cards
+  of the PCI-DAS series with the AMCC S5933 PCI controller.
+Author: Ivan Martinez <ivanmr@altavista.com>,
+  Frank Mori Hess <fmhess@uiuc.edu>
+Status:
+  - PCI-DAS1602/16: Analog input is tested, works.  Analog output untested.
+  - PCI-DAS1602/16jr: Driver should work, but untested.  Please
+      report usage.
+  - PCI-DAS1602/12: Same as above.
+  - PCI-DAS1200, 1200jr: Tested, works.
+  - PCI-DAS1000, 1001, 1002: Should work, but untested.  Please report
+    usage.
+
+  The boards' autocalibration features are not yet supported.
+
+Updated: 2002-1-09
+Devices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas),
+  PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr,
+  PCI-DAS1000, PCI-DAS1001, PCI_DAS1002
+
+Configuration options:
+  [0] - PCI bus of device (optional)
+  [1] - PCI slot of device (optional)
+  If bus/slot is not specified, the first available PCI
+  device will be used.
+
+For commands, the scanned channels must be consecutive
+(i.e. 4-5-6-7, 2-3-4,...), and must all have the same
+range and aref.
+
+
+
+Driver: cb_pcidas64.o
+Description: Driver for the ComputerBoards/MeasurementComputing
+   PCI-DAS64xxx series with the PLX 9080 PCI controller.
+Author: Frank Mori Hess <fmhess@uiuc.edu>
+Status: Experimental
+Updated: 2001-9-19
+Devices: [Measurement Computing] PCI-DAS6402/16 (cb_pcidas64),
+  PCI-DAS6402/12, PCI-DAS64/M1/16, PCI-DAS64/M2/16,
+  PCI-DAS64/M3/16, PCI-DAS6402/16/JR, PCI-DAS64/M1/16/JR,
+  PCI-DAS64/M2/16/JR, PCI-DAS64/M3/16/JR, PCI-DAS64/M1/14,
+  PCI-DAS64/M2/14, PCI-DAS64/M3/14
+Configuration options:
+   [0] - PCI bus of device (optional)
+   [1] - PCI slot of device (optional)
+
+Basic insn support should work, but untested as far as I know.
+Has command support for analog input, which may also work.  Support
+for pci dma transfers can be enabled by editing the source to #define
+PCIDMA instead of #undef'ing it. This driver is in need of stout-hearted
+testers who aren't afraid to crash their computers in the name of progress.
+Feel free to send and success/failure reports to author.
+
+Some devices are not identified because the PCI device IDs are not known.
+
+
+
+Driver: cb_pcidda.o
+Description: ComputerBoards/MeasurementComputing PCI-DDA series
+Author: Ivan Martinez <ivanmr@altavista.com>, Frank Mori Hess <fmhess@users.sourceforge.net>
+Status: Supports 08/16, 04/16, 02/16, 08/12, 04/12, and 02/12
+Devices: [Measurement Computing] PCI-DDA08/12 (cb_pcidda), PCI-DDA04/12,
+  PCI-DDA02/12, PCI-DDA08/16, PCI-DDA04/16, PCI-DDA02/16
+
+Configuration options:
+  [0] - PCI bus of device (optional)
+  [1] - PCI slot of device (optional)
+  If bus/slot is not specified, the first available PCI
+  device will be used.
+
+Only simple analog output writing is supported.
+
+SO FAR IT HAS ONLY BEEN TESTED WITH:
+  - PCI-DDA08/12
+PLEASE REPORT IF YOU ARE USING IT WITH A DIFFERENT CARD
+<ivanmr@altavista.com>.
+
+
+
+Driver: comedi_parport.o
+Description: Standard PC parallel port
+Author: ds
+Status: works in immediate mode
+Devices: [standard] parallel port (comedi_parport)
+
+A cheap and easy way to get a few more digital I/O lines.  Steal
+additional parallel ports from old computers or your neighbors'
+computers.
+
+Option list:
+ 0: I/O port base for the parallel port.
+ 1: IRQ
+
+Parallel Port Lines:
+
+pin     subdev  chan    aka
+---     ------  ----    ---
+1       2       0       strobe
+2       0       0       data 0
+3       0       1       data 1
+4       0       2       data 2
+5       0       3       data 3
+6       0       4       data 4
+7       0       5       data 5
+8       0       6       data 6
+9       0       7       data 7
+10      1       3       acknowledge
+11      1       4       busy
+12      1       2       output
+13      1       1       printer selected
+14      2       1       auto LF
+15      1       0       error
+16      2       2       init
+17      2       3       select printer
+18-25   ground
+
+Notes:
+
+Channel 0 and 2 are output, channel 1 is input.  I know that it
+is possible to change this with ECP/EPP parallel ports, but this
+driver is a cheap hack.
+
+Pins 13 and 14 are inverted once by comedi and once by the
+hardware, thus cancelling the effect.
+
+Pin 1 is a strobe, thus acts like one.  There's no way in software
+to change this, at least on a standard parallel port.
+
+Subdevice 3 pretends to be a digital input subdevice, but it always
+returns 0 when read.  However, if you run a command with
+scan_begin_src=TRIG_EXT, it uses pin 13 as a external triggering
+pin, which can be used to wake up tasks.  (or is that pin 10. --ds)
+
+
+
+Driver: comedi_rt_timer.o
+Description: Command emulator using real-time tasks
+Authors: ds, fmhess
+Devices:
+Status: works
+
+This driver requires RTAI or RTLinux to work correctly.  It doesn't
+actually drive hardware directly, but calls other drivers and uses
+a real-time task to emulate commands for drivers and devices that
+are incapable of native commands.  Thus, you can get accurately
+timed I/O on any device.
+
+Since the timing is all done in software, sampling jitter is much
+higher than with a device that has an on-board timer, and maximum
+sample rate is much lower.
+
+Configuration options:
+  [0] - device index
+  [1] - subdevice index
+
+
+
+Driver: daqboard2000.o
+Description: IOTech DAQBoard/2000
+Author: Anders Blomdell <anders.blomdell@control.lth.se>
+Status: works
+Devices: [IOTech] DAQBoard/2000 (daqboard2000)
+
+Much of the functionality of this driver was determined from reading
+the source code for the Windows driver.
+
+The FPGA on the board requires initialization code, which can either
+be compiled into the driver or loaded by comedi_config using the -i
+option.  The latter is recommended, in order to save a bit of kernel
+memory.
+
+Configuration options:
+  [0] - pointer to FPGA initialization data
+          The pointer and size options are handled automatically
+          by comedi_config when you use the -i option.
+  [1] - size of FPGA data
+
+
+
+Driver: das08.o
+Description: DAS-08 compatible boards
+Authors: Warren Jasper, ds, Frank Hess
+Devices: [ComputerBoards] DAS08 (das08), DAS08-PGM (das08-pgm),
+  DAS08-PGH (das08-pgh), DAS08-PGL (das08-pgl), DAS08-AOH (das08-aoh),
+  DAS08-AOL (das08-aol), DAS08-AOM (das08-aom), DAS08/JR-AO (das08/jr-ao),
+  DAS08/JR-16-AO (das08jr-16-ao), PCI-DAS08 (pci-das08), PCM-DAS08 (pcm-das08),
+  PC104-DAS08 (pc104-das08), DAS08/JR/16 (das08jr/16)
+Status: works
+
+This is a rewrite of the das08 and das08jr drivers.
+
+Options (for ISA cards):
+        [0] - base io address
+
+Options (for pci-das08):
+        [0] - bus  (optional)
+        [1] = slot (optional)
+Use the name 'pci-das08' for the pci-das08, NOT 'das08'.
+
+Options (for pcm-das08):
+        NONE
+
+The das08 driver doesn't support asynchronous commands, since
+the cheap das08 hardware doesn't really support them (except for
+pcm-das08).  The
+comedi_rt_timer driver can be used to emulate commands for this
+driver.
+
+
+
+Driver: das16.o
+Description: DAS16 compatible boards
+Authors: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess
+Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g),
+  DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202),
+  DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601),
+  DAS-1602 (das-1602),
+  [ComputerBoards] PC104-DAS16/JR (pc104-das16jr),
+  PC104-DAS16JR/16 (pc104-das16jr/16),
+  CIO-DAS16/JR (cio-das16/jr), CIO-DAS1401/12 (cio-das1401/12),
+  CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16),
+  CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12),
+  CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330)
+Status: works in das16 mode, das-1600 enhanced mode features untested.
+Updated: 2001-8-27
+
+A rewrite of the das16 and das1600 drivers.
+Options:
+        [0] - base io address
+        [1] - irq (optional)
+        [2] - dma (optional)
+        [3] - master clock speed in MHz (optional, 1 or 10, ignored if
+               board can probe clock, defaults to 1)
+        [4] - analog input range lowest voltage in microvolts (optional,
+               only useful if your board does not have software
+               programmable gain)
+        [5] - analog input range highest voltage in microvolts (optional,
+               only useful if board does not have software programmable
+               gain)
+        [6] - analog output range lowest voltage in microvolts (optional)
+        [7] - analog output range highest voltage in microvolts (optional)
+
+Passing a zero for an option is the same as leaving it unspecified.
+
+Both an irq line and dma channel are required for timed or externally
+triggered conversions.
+
+
+
+Driver: das16m1.o
+Description: CIO-DAS16/M1
+Authors: Frank Mori Hess <fmhess@uiuc.edu>
+Devices: [MeasurementComputing] CIO-DAS16/M1 (cio-das16/m1)
+Status: works
+
+This driver supports a single board - the CIO-DAS16/M1.
+As far as I know, there are no other boards that have
+the same register layout.  Even the CIO-DAS16/M1/16 is
+significantly different.
+
+I was _barely_ able to reach the full 1 MHz capability
+of this board, using a hard real-time interrupt
+(set the TRIG_RT flag in your comedi_cmd and use
+rtlinux or RTAI).  The board can't do dma, so the bottleneck is
+pulling the data across the ISA bus.  I timed the interrupt
+handler, and it took my computer ~470 microseconds to pull 512
+samples from the board.  So at 1 Mhz sampling rate,
+expect your CPU to be spending almost all of its
+time in the interrupt handler.
+
+This board has some unusual restrictions for its channel/gain list.  If the
+list has 2 or more channels in it, then two conditions must be satisfied:
+(1) - even/odd channels must appear at even/odd indices in the list
+(2) - the list must have an even number of entries.
+
+Options:
+        [0] - base io address
+        [1] - irq (optional, but you probably want it)
+
+irq can be omitted, although the cmd interface will not work without it.
+
+
+
+Driver: das1800.o
+Description: Keithley Metrabyte DAS1800 (& compatibles)
+Author: Frank Mori Hess <fmhess@uiuc.edu>
+Devices: [Keithley Metrabyte] DAS-1701ST (das-1701st),
+  DAS-1701ST-DA (das-1701st-da), DAS-1701/AO (das-1701ao),
+  DAS-1702ST (das-1702st), DAS-1702ST-DA (das-1702st-da),
+  DAS-1702HR (das-1702hr), DAS-1702HR-DA (das-1702hr-da),
+  DAS-1702/AO (das-1702ao), DAS-1801ST (das-1801st),
+  DAS-1801ST-DA (das-1801st-da), DAS-1801HC (das-1801hc),
+  DAS-1801AO (das-1801ao), DAS-1802ST (das-1802st),
+  DAS-1802ST-DA (das-1802st-da), DAS-1802HR (das-1802hr),
+  DAS-1802HR-DA (das-1802hr-da), DAS-1802HC (das-1802hc),
+  DAS-1802AO (das-1802ao)
+Status: works
+
+The waveform analog output on the 'ao' cards is not supported.
+If you need it, send me (Frank Hess) an email.
+
+Configuration options:
+  [0] - I/O port base address
+  [1] - IRQ (optional, required for timed or externally triggered conversions)
+  [2] - DMA0 (optional, requires irq)
+  [3] - DMA1 (optional, requires irq and dma0)
+
+
+
+Driver: das6402.o
+Description: Keithley Metrabyte DAS6402 (& compatibles)
+Author: Oystein Svendsen <svendsen@pvv.org>
+Status: unknown
+Devices: [Keithley Metrabyte] DAS6402 (das6402)
+
+
+
+Driver: das800.o
+Description: Keithley Metrabyte DAS800 (& compatibles)
+Author: Frank Mori Hess <fmhess@uiuc.edu>
+Devices: [Keithley Metrabyte] DAS-800 (das-800), DAS-801 (das-801),
+  DAS-802 (das-802),
+  [Measurement Computing] CIO-DAS800 (cio-das800),
+  CIO-DAS801 (cio-das801), CIO-DAS802 (cio-das802),
+  CIO-DAS802/16 (cio-das802/16)
+Status: works, cio-das802/16 untested - email me if you have tested it
+
+Configuration options:
+  [0] - I/O port base address
+  [1] - IRQ (optional, required for timed or externally triggered conversions)
+
+
+
+Driver: dt2801.o
+Description: Data Translation DT2801 series and DT01-EZ
+Author: ds
+Status: works
+Devices: [Data Translation] DT2801 (dt2801), DT2801-A, DT2801/5716A,
+  DT2805, DT2805/5716A, DT2808, DT2818, DT2809, DT01-EZ
+
+This driver can autoprobe the type of board.
+
+Configuration options:
+  [0] - I/O port base address
+  [1] - unused
+  [2] - A/D reference 0=differential, 1=single-ended
+  [3] - A/D range
+          0 = [-10,10]
+         1 = [0,10]
+  [4] - D/A 0 range
+          0 = [-10,10]
+         1 = [-5,5]
+         2 = [-2.5,2.5]
+         3 = [0,10]
+         4 = [0,5]
+  [5] - D/A 1 range (same choices)
+
+
+
+Driver: dt2811.o
+Description: Data Translation DT2811
+Author: ds
+Devices: [Data Translation] DT2811-PGL (dt2811-pgl), DT2811-PGH (dt2811-pgh)
+Status: works
+
+Configuration options:
+  [0] - I/O port base address
+  [1] - IRQ, although this is currently unused
+  [2] - A/D reference
+          0 = signle-ended
+          1 = differential
+         2 = pseudo-differential (common reference)
+  [3] - A/D range
+          0 = [-5,5]
+         1 = [-2.5,2.5]
+         2 = [0,5]
+  [4] - D/A 0 range (same choices)
+  [4] - D/A 1 range (same choices)
+
+
+
+Driver: dt2814.o
+Description: Data Translation DT2814
+Author: ds
+Status: complete
+Devices: [Data Translation] DT2814 (dt2814)
+
+Configuration options:
+  [0] - I/O port base address
+  [1] - IRQ
+
+This card has 16 analog inputs multiplexed onto a 12 bit ADC.  There
+is a minimally useful onboard clock.  The base frequency for the
+clock is selected by jumpers, and the clock divider can be selected
+via programmed I/O.  Unfortunately, the clock divider can only be
+a power of 10, from 1 to 10^7, of which only 3 or 4 are useful.  In
+addition, the clock does not seem to be very accurate.
+
+
+
+Driver: dt2815.o
+Description: Data Translation DT2815
+Author: ds
+Status: mostly complete, untested
+Devices: [Data Translation] DT2815 (dt2815)
+
+I'm not sure anyone has ever tested this board.  If you have information
+contrary, please update.
+
+Configuration options:
+  [0] - I/O port base base address
+  [1] - IRQ (unused)
+  [2] - Voltage unipolar/bipolar configuration
+          0 == unipolar 5V  (0V -- +5V)
+         1 == bipolar 5V  (-5V -- +5V)
+  [3] - Current offset configuration
+          0 == disabled  (0mA -- +32mAV)
+          1 == enabled  (+4mA -- +20mAV)
+  [4] - Firmware program configuration
+          0 == program 1 (see manual table 5-4)
+          1 == program 2 (see manual table 5-4)
+          2 == program 3 (see manual table 5-4)
+          3 == program 4 (see manual table 5-4)
+  [5] - Analog output 0 range configuration
+          0 == voltage
+          1 == current
+  [6] - Analog output 1 range configuration (same options)
+  [7] - Analog output 2 range configuration (same options)
+  [8] - Analog output 3 range configuration (same options)
+  [9] - Analog output 4 range configuration (same options)
+  [10] - Analog output 5 range configuration (same options)
+  [11] - Analog output 6 range configuration (same options)
+  [12] - Analog output 7 range configuration (same options)
+
+
+
+Driver: dt2817.o
+Description: Data Translation DT2817
+Author: ds
+Status: complete
+Devices: [Data Translation] DT2817 (dt2817)
+
+A very simple digital I/O card.  Four banks of 8 lines, each bank
+is configurable for input or output.  One wonders why it takes a
+50 page manual to describe this thing.
+
+The driver (which, btw, is much less than 50 pages) has 1 subdevice
+with 32 channels, configurable in groups of 8.
+
+Configuration options:
+  [0] - I/O port base base address
+
+
+
+Driver: dt282x.o
+Description: Data Translation DT2821 series (including DT-EZ)
+Author: ds
+Devices: [Data Translation] DT2821 (dt2821), DT2823 (dt2823),
+  DT2824-PGH (dt2824-pgh), DT2824-PGL (dt2824-pgl), DT2825 (dt2825),
+  DT2827 (dt2827), DT2828 (dt2828), DT21-EZ (dt21-ez), DT23-EZ (dt23-ez),
+  DT24-EZ (dt24-ez), DT24-EZ-PGL (dt24-ez-pgl)
+Status: complete
+Updated: Wed, 22 Aug 2001 17:11:34 -0700
+
+Configuration options:
+  [0] - I/O port base address
+  [1] - IRQ
+  [2] - DMA 1
+  [3] - DMA 2
+  [4] - AI jumpered for 0=single ended, 1=differential
+  [5] - AI jumpered for 0=straight binary, 1=2's complement
+  [6] - AO 0 jumpered for 0=straight binary, 1=2's complement
+  [7] - AO 1 jumpered for 0=straight binary, 1=2's complement
+  [8] - AI jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5]
+  [9] - AO 0 jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5],
+        4=[-2.5,2.5]
+  [10]- A0 1 jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5],
+        4=[-2.5,2.5]
+
+Notes:
+  - AO commands might be broken.
+  - If you try to run a command on both the AI and AO subdevices
+    simultaneously, bad things will happen.  The driver needs to
+    be fixed to check for this situation and return an error.
+
+
+
+Driver: dt3000.o
+Description: Data Translation DT3000 series
+Author: ds
+Devices: [Data Translation] DT3001 (dt3000), DT3001-PGL, DT3002, DT3003,
+  DT3003-PGL, DT3004, DT3005, DT3004-200
+Status: untested
+
+
+
+Driver: fl512.o
+Description: unknown
+Author: unknown
+Devices: [unknown] FL512 (fl512)
+
+Digital I/O is not supported.
+
+Configuration options:
+  [0] - I/O port base address
+
+
+
+Driver: icp_multi.o
+Description: Inova ICP Multi
+Author: Anne Smorthit <anne.smorthit@sfwte.ch>
+Devices: [Inova] ICP Multi (icp_multi)
+
+
+
+
+Driver: ii_pci20kc.o
+Description: Intelligent Instruments PCI-20001C carrier board
+Author: Markus Kempf <kempf@matsci.uni-sb.de>
+Devices: [Intelligent Instrumentation] PCI-20001C (ii_pci20kc)
+Status: works
+
+Supports the PCI-20001 C-2a Carrier board, and could probably support
+the other carrier boards with small modifications.  Modules supported
+are:
+       PCI-20006 M-2 16-bit analog output module
+       PCI-20341 M-1A 16-bit analog input module
+
+Options:
+  0   Board base address
+  1   IRQ
+  2   first option for module 1
+  3   second option for module 1
+  4   first option for module 2
+  5   second option for module 2
+  6   first option for module 3
+  7   second option for module 3
+
+options for PCI-20006M:
+  first:   Analog output channel 0 range configuration
+             0  bipolar 10  (-10V -- +10V)
+             1  unipolar 10  (0V -- +10V)
+             2  bipolar 5  (-5V -- 5V)
+  second:  Analog output channel 1 range configuration
+
+options for PCI-20341M:
+  first:   Analog input gain configuration
+             0  1
+             1  10
+             2  100
+             3  200
+
+
+
+Driver: mpc8260cpm.o
+Description: MPC8260 CPM module generic digital I/O lines
+Devices: [Motorola] MPC8260 CPM (mpc8260cpm)
+Author: ds
+
+This driver is specific to the Motorola MPC8260 processor, allowing
+you to access the processor's generic digital I/O lines.
+
+
+
+Driver: multiq3.o
+Description: Quanser Consulting MultiQ-3
+Author: Anders Blomdell <anders.blomdell@control.lth.se>
+Status: works
+Devices: [Quanser Consulting] MultiQ-3 (multiq3)
+
+
+
+
+Driver: ni_670x.o
+Description: National Instruments 670x
+Author: Bart Joris <bjoris@advalvas.be>
+Updated: Wed, 22 Aug 2001 22:47:32 -0700
+Devices: [National Instruments] PCI-6703 (ni_670x), PCI-6704
+
+The driver currently does not recognize the 6704, because the PCI
+ID is not known.
+
+
+
+Driver: ni_at_a2150.o
+Description: National Instruments AT-A2150
+Author: Frank Mori Hess
+Status: works
+Devices: [National Instruments] AT-A2150C (at_a2150c), AT-2150S (at_a2150s)
+
+If you want to ac couple the board's inputs, use AREF_OTHER.
+
+Configuration options:
+  [0] - I/O port base address
+  [1] - IRQ (optional, required for timed conversions)
+  [2] - DMA (optional, required for timed conversions)
+
+
+
+
+Driver: ni_atmio.o
+Description: National Instruments AT-MIO-E series
+Author: ds
+Devices: [National Instruments] AT-MIO-16E-1 (ni_atmio),
+  AT-MIO-16E-2, AT-MIO-16E-10, AT-MIO-16DE-10, AT-MIO-64E-3,
+  AT-MIO-16XE-50, AT-MIO-16XE-10, AT-AI-16XE-10
+
+The isapnptools package is required to use this board.  Use isapnp to
+configure the I/O base for the board, and then pass the same value as
+a parameter in comedi_config.  A sample isapnp.conf file is included
+in the etc/ directory.
+
+Assuming that the NI spec is correct, the driver should correctly
+identify every board in the series.  Each channel should have the
+appropriate parameters, i.e., input/output ranges, number of bits,
+etc.  If the driver fails to recognize your card or does not have
+the correct parameters, please contact me.
+
+Comedilib includes a utility to autocalibrate these boards.  The
+boards seem to boot into a state where the all calibration DACs
+are at one extreme of their range, thus the default calibration
+is terrible.  Calibration at boot is strongly encouraged.
+
+External triggering is supported for some events.  The channel index
+(scan_begin_arg, etc.) maps to PFI0 - PFI9.
+
+
+
+Driver: ni_atmio16d.o
+Description: National Instruments AT-MIO-16D
+Author: Chris R. Baugher <baugher@enteract.com>
+Status: unknown
+Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d)
+
+
+
+Driver: ni_labpc.o
+Description: National Instruments Lab-PC (& compatibles)
+Author: Frank Mori Hess <fmhess@users.sourceforge.net>
+Devices: [National Instruments] DAQCard-1200 (daqcard-1200), Lab-PC-1200 (labpc-1200),
+  Lab-PC-1200AI (labpc-1200ai), Lab-PC+ (lab-pc+), PCI-1200 (pci-1200)
+Status: Works (tested with lab-pc-1200).  For the older Lab-PC+, not all input
+  ranges and analog references will work, the available
+  ranges/arefs will depend on how you have configured
+  the jumpers on your board (see your owner's manual).
+
+Configuration options - ISA boards:
+  [0] - I/O port base address
+  [1] - IRQ (optional, required for timed or externally triggered conversions)
+  [2] - DMA channel (optional)
+
+Configuration options - PCI boards:
+  [0] - bus (optional)
+  [1] - slot (optional)
+
+Configuration options - PCMCIA boards:
+  none
+
+Lab-pc+ has quirky chanlist when scanning multiple channels.  Scan sequence must start
+at highest channel, then decrement down to channel 0.  1200 series cards can scan down
+like lab-pc+ or scan up from channel zero.
+
+
+
+
+Driver: ni_mio_cs.o
+Description: National Instruments DAQCard E series
+Author: ds
+Status: works
+Devices: [National Instruments] DAQCard-AI-16XE-50 (ni_mio_cs),
+  DAQCard-AI-16E-4, DAQCard-6062E, DAQCard-6024E
+
+See the notes in the ni_atmio.o driver.
+
+
+
+Driver: ni_pcidio.o
+Description: National Instruments PCI-DIO32HS, PCI-DIO96, PCI-6533, PCI-6503
+Author: ds
+Status: works in immediate mode
+Devices: [National Instruments] PCI-DIO-32HS (ni_pcidio), PXI-6533,
+  PCI-DIO-96, PCI-DIO-96B, PXI-6508, PCI-6503, PCI-6503B, PCI-6503X,
+  PXI-6503
+
+The DIO-96 appears as four 8255 subdevices.  See the 8255
+driver notes for details.
+
+The DIO32HS board appears as one subdevice, with 32 channels.
+Each channel is individually I/O configurable.  The channel order,
+as one might guess, is 0=A0, 1=A1, 2=A2, ... 8=B0, 16=C0, 24=D0.
+
+DMA is halfway completed, but not operational, for the PCI-DIO32HS.
+
+This driver could be easily modified to support AT-MIO32HS and
+AT-MIO96.
+
+
+
+Driver: ni_pcimio.o
+Description: National Instruments PCI-MIO-E series (all boards)
+Author: ds
+Status: mainly limited by Comedi infrastructure
+Devices: [National Instruments] PCI-MIO-16XE-50 (ni_pcimio),
+  PCI-MIO-16XE-10, PXI-6030E, PCI-MIO-16E-1, PCI-MIO-16E-4, PCI-6040E,
+  PXI-6040E, PCI-6031E, PCI-6032E, PCI-6033E, PCI-6071E, PCI-6023E,
+  PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, PCI-6035E, PCI-6052E,
+  PCI-6110E, PCI-6111E, PCI-6711, PCI-6713, PXI-6071E, PXI-6070E,
+  PXI-6052E, PCI-6036E
+
+These boards are almost identical to the AT-MIO E series, except that
+they use the PCI bus instead of ISA (i.e., AT).  See the notes above for
+ni_atmio.o for additional information about these boards.
+
+Comedi knows the PCI ID codes for many of the boards in this series,
+but the NI documentation is incomplete in this matter.  If you have
+a PCI-MIO board that Comedi doesn't recognize, send me the PCI device
+ID, as can be found in /proc/pci or the output of lspci.  The vendor
+code for National Instruments is 0x1093.  I will include the ID in
+the next version.
+
+DMA is halfway completed, but not yet operational.
+
+
+
+Driver: pcl711.o
+Description: Advantech PCL-711 and 711b, ADLink ACL-8112
+Authors: ds, Janne Jalkanen <jalkanen@cs.hut.fi>, Eric Bunn <ebu@cs.hut.fi>
+Status: mostly complete
+Devices: [Advantech] PCL-711 (pcl711), PCL-711B (pcl711b),
+  [AdLink] ACL-8112HG (acl8112hg), ACL-8112DG (acl8112dg)
+
+Since these boards do not have DMA or FIFOs, only immediate mode is
+supported.
+
+
+
+
+Driver: pcl724.o
+Description: Advantech PCL-724, PCL-722, PCL-731 ADLink ACL-7122, ACL-7124,
+  PET-48DIO
+Author: Michal Dobes <majkl@tesnet.cz>
+Devices: [Advantech] PCL-724 (pcl724), PCL-722 (pcl722), PCL-731 (pcl731),
+  [ADLink] ACL-7122 (acl7122), ACL-7124 (acl7124), PET-48DIO (pet48dio)
+Status: untested
+
+This is driver for digital I/O boards PCL-722/724/731 with 144/24/48 DIO
+and for digital I/O boards ACL-7122/7124/PET-48DIO with 144/24/48 DIO.
+It need 8255.o for operations and only immediate mode is supported.
+See the source for configuration details.
+
+
+
+Driver: pcl725.o
+Description: Advantech PCL-725 (& compatibles)
+Author: ds
+Status: unknown
+Devices: [Advantech] PCL-725 (pcl725)
+
+
+
+Driver: pcl726.o
+Description: Advantech PCL-726 & compatibles
+Author: ds
+Status: untested
+Devices: [Advantech] PCL-726 (pcl726), PCL-727 (pcl727), PCL-728 (pcl728),
+  [ADLink] ACL-6126 (acl6126), ACL-6128 (acl6128)
+
+Interrupts are not supported.
+
+    Options for PCL-726:
+     [0] - IO Base
+     [2]...[7] - D/A output range for channel 1-6: 
+               0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 
+              4: 4-20mA, 5: unknown (external reference)
+              
+    Options for PCL-727:
+     [0] - IO Base
+     [2]...[13] - D/A output range for channel 1-12: 
+               0: 0-5V, 1: 0-10V, 2: +/-5V, 
+              3: 4-20mA
+              
+    Options for PCL-728 and ACL-6128:
+     [0] - IO Base
+     [2], [3] - D/A output range for channel 1 and 2: 
+               0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 
+              4: 4-20mA, 5: 0-20mA
+              
+    Options for ACL-6126:
+     [0] - IO Base
+     [1] - IRQ (0=disable, 3, 5, 6, 7, 9, 10, 11, 12, 15)
+     [2]...[7] - D/A output range for channel 1-6: 
+               0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 
+              4: 4-20mA
+     NOTE: IRQ operations isn't now supported.
+
+
+
+Driver: pcl812.o
+Description: Advantech PCL-812/PG, PCL-813/B,
+             ADLink ACL-8112DG/HG/PG, ACL-8113, ACL-8216,
+             ICP DAS A-821PGH/PGL/PGL-NDA, A-822PGH/PGL, A-823PGH/PGL, A-826PG,
+             ICP DAS ISO-813
+Author: Michal Dobes <majkl@tesnet.cz>
+Devices: [Advantech] PCL-812 (pcl812), PCL-812PG (pcl812pg),
+  PCL-813 (pcl813), PCL-813B (pcl813b), [ADLink] ACL-8112DG (acl8112dg),
+  ACL-8112HG (acl8112hg), ACL-8113 (acl-8113), ACL-8216 (acl8216),
+  [ICP] ISO-813 (iso813), A-821PGH (a821pgh), A-821PGL (a821pgl),
+  A-821PGL-NDA (a821pclnda), A-822PGH (a822pgh), A-822PGL (a822pgl),
+  A-823PGH (a823pgh), A-823PGL (a823pgl), A-826PG (a826pg)
+Status: works (I hope. My board fire up under my hands
+               and I cann't test all features.)
+
+This driver supports insn and cmd interfaces. Some boards support only insn
+becouse their hardware don't allow more (PCL-813/B, ACL-8113, ISO-813).
+Data transfer over DMA is supported only when you measure only one
+channel, this is too hardware limitation of these boards.
+See the head of the source file pcl812.c for configuration options.
+
+
+
+Driver: pcl818.o
+Description: Advantech PCL-818 cards, PCL-718
+Author: Michal Dobes <majkl@tesnet.cz>
+Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h),
+  PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818),
+  PCL-718 (pcl718)
+Status: works
+
+All cards have 16 SE/8 DIFF ADCs, one or two DACs, 16 DI and 16 DO.
+Differences are only at maximal sample speed, range list and FIFO
+support.
+The driver support AI mode 0, 1, 3 other subdevices (AO, DI, DO) support
+only mode 0. If DMA/FIFO/INT are disabled then AI support only mode 0.
+PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO
+but this code is untested.
+A word or two about DMA. Driver support DMA operations at two ways:
+1) DMA uses two buffers and after one is filled then is generated
+   INT and DMA restart with second buffer. With this mode I'm unable run
+   more that 80Ksamples/secs without data dropouts on K6/233.
+2) DMA uses one buffer and run in autoinit mode and the data are
+   from DMA buffer moved on the fly with 2kHz interrupts from RTC.
+   This mode is used if the interrupt 8 is available for allocation.
+   If not, then first DMA mode is used. With this I can run at
+   full speed one card (100ksamples/secs) or two cards with
+   60ksamples/secs each (more is problem on account of ISA limitations).
+   To use this mode you must have compiled  kernel with disabled
+   "Enhanced Real Time Clock Support".
+   Maybe you can have problems if you use xntpd or similar.
+   If you've data dropouts with DMA mode 2 then:
+    a) disable IDE DMA
+    b) switch text mode console to fb.
+See the head of the source file pcl818.c for configuration options.
+
+
+
+Driver: pcm3730.o
+Description: PCM3730
+Author: Blaine Lee
+Devices: [Advantech] PCM-3730 (pcm3730)
+
+Configuration options:
+  [0] - I/O port base
+
+
+
+Driver: pcmad.o
+Description: Winsystems PCM-A/D12, PCM-A/D16
+Author: ds
+Devices: [Winsystems] PCM-A/D12 (pcmad12), PCM-A/D16 (pcmad16)
+Status: untested
+
+This driver was written on a bet that I couldn't write a driver
+in less than 2 hours.  I won the bet, but never got paid.  =(
+
+Configuration options:
+  [0] - I/O port base
+  [1] - unused
+  [2] - Analog input reference
+          0 = single ended
+          1 = differential
+  [3] - Analog input encoding (must match jumpers)
+          0 = straight binary
+          1 = two's complement
+
+
+
+Driver: poc.o
+Description: Generic driver for very simple devices
+Device names: dac02
+Author: ds
+Devices: [Keithley Metrabyte] DAC-02 (dac02)
+
+This driver is indended to support very simple ISA-based devices,
+including:
+  dac02 - Keithley DAC-02 analog output board
+
+Configuration options:
+  [0] - I/O port base
+
+
+
+Driver: quatech_daqp_cs.o
+Description: Quatech DAQP PCMCIA data capture cards
+Author: Brent Baccala <baccala@freesoft.org>
+Status: unkown
+Devices: [Quatech] DAQP-208 (daqp), DAQP-308
+
+
+
+Driver: rtd520.o
+Description: Real Time Devices PCI4520/DM7520
+Author: Dan Christian
+Devices: [Real Time Devices] DM7520HR-1 (DM7520), DM7520HR-8 (DM7520-8),
+  PCI4520 (PCI4520), PCI4520-8 (PCI4520-8)
+
+Configuration options:
+  [0] - PCI bus of device (optional)
+          If bus/slot is not specified, the first available PCI
+          device will be used.
+  [1] - PCI slot of device (optional)
+
+
+
+Driver: rti800.o
+Description: Analog Devices RTI-800/815
+Author: ds
+Status: unknown
+Devices: [Analog Devices] RTI-800 (rti800), RTI-815 (rti815)
+
+Configuration options:
+  [0] - I/O port base address
+  [1] - IRQ
+  [2] - A/D reference
+          0 = differential
+          1 = pseudodifferential (common)
+          2 = single-ended
+  [3] - A/D range
+          0 = [-10,10]
+          1 = [-5,5]
+          2 = [0,10]
+  [4] - A/D encoding
+          0 = two's complement
+          1 = straight binary
+  [5] - DAC 0 range
+          0 = [-10,10]
+          1 = [0,10]
+  [5] - DAC 0 encoding
+          0 = two's complement
+          1 = straight binary
+  [6] - DAC 1 range (same as DAC 0)
+  [7] - DAC 1 encoding (same as DAC 0)
+
+
+
+Driver: rti802.o
+Description: Analog Devices RTI-802
+Author: Anders Blomdell <anders.blomdell@control.lth.se>
+Devices: [Analog Devices] RTI-802 (rti802)
+Status: works
+
+
+
+Driver: skel.o
+Description: Skeleton driver, an example for driver writers
+Devices:
+Author: ds
+
+This driver is a documented example on how Comedi drivers are
+written.
+
+
+
+Driver: ssv_dnp.o
+Description: SSV Embedded Systems DIL/Net-PC
+Author: Robert Schwebel <robert@schwebel.de>
+Devices: [SSV Embedded Systems] DIL/Net-PC 1486 (dnp-1486)
+
+
+
diff --git a/doc/docbook/funcref b/doc/docbook/funcref
new file mode 100644 (file)
index 0000000..2141896
--- /dev/null
@@ -0,0 +1,355 @@
+Function: comedi_close -- close a Comedi device
+Retval: int
+Param: comedi * device
+Description:
+ Close a device previously opened by comedi_open().
+
+Function: comedi_open -- open a Comedi device
+Retval: comedi_t
+Param: const char * filename
+Description:
+ Open a Comedi device represented by the file filename.
+
+Function: comedi_loglevel -- change Comedilib logging properties
+Retval: int
+Param: int loglevel
+Description:
+
+Function: comedi_perror -- print a Comedilib error message
+Retval: void
+Param: const char * s
+Description:
+
+Function: comedi_strerror -- return string describing Comedilib error code
+Retval: char *
+Param: int errnum
+Description:
+
+Function: comedi_errno -- number of last Comedilib error
+Retval: int
+Param: void
+Description:
+
+Function: comedi_fileno -- integer descriptor of Comedilib device
+Retval: int
+Param: comedi_t * device
+Description:
+
+Function: comedi_get_n_subdevices -- number of subdevices 
+Retval: int
+Param: comedi_t * device
+Description:
+
+Function: comedi_get_version_code -- Comedi version code
+Retval: int
+Param: comedi_t * device
+Description:
+
+Function: comedi_get_driver_name -- Comedi driver name
+Retval: char *
+Param: comedi_t * device
+Description:
+
+Function: comedi_get_board_name -- Comedi device name
+Retval: char *
+Param: comedi_t * device
+Description:
+
+Function: comedi_get_subdevice_type -- type of subdevice
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Description:
+
+Function: comedi_find_subdevice_by_type -- search for subdevice type
+Retval: int
+Param: comedi_t * device
+Param: int type
+Param: unsigned int start_subdevice
+Description:
+
+Function: comedi_get_subdevice_flags -- properties of subdevice
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Description:
+
+Function: comedi_get_n_channels -- number of subdevice channels
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Description:
+
+Function: comedi_range_is_chan_specific -- range information depends on channel
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Description:
+
+Function: comedi_maxdata_is_chan_specific -- maximum sample depends on channel
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Description:
+
+Function: comedi_get_maxdata -- maximum sample of channel
+Retval: lsampl_t
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int channel
+Description:
+
+Function: comedi_get_n_ranges -- number of ranges of channel
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int channel
+Description:
+
+Function: comedi_get_range -- range information of channel
+Retval: comedi_range *
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int channel
+Param: unsigned int range
+Description:
+
+Function: comedi_find_range -- search for range
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int channel
+Param: unsigned int unit
+Param: double min
+Param: double max
+Description:
+
+Function: comedi_get_buffer_size -- streaming buffer size of subdevice
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Description:
+
+Function: comedi_get_max_buffer_size -- maximum streaming buffer size
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Description:
+
+Function: comedi_set_buffer_size -- streaming buffer size of subdevice
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int size
+Description:
+
+Function: comedi_trigger -- perform streaming input/output (deprecated)
+Retval: int
+Param: comedi_t * device
+Param: comedi_trig * trig
+Description:
+Status: deprecated
+
+Function: comedi_do_insnlist -- perform multiple instructions
+Retval: int
+Param: comedi_t * device
+Param: comedi_insnlist * list
+Description:
+
+Function: comedi_do_insn -- perform instruction
+Retval: int
+Param: comedi_t * device
+Param: comedi_insn * instruction
+Description:
+
+Function: comedi_lock -- subdevice reservation
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Description:
+
+Function: comedi_unlock -- subdevice reservation
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Description:
+
+Function: comedi_to_phys -- convert sample to physical units
+Retval: double
+Param: lsampl_t data
+Param: comedi_range * range
+Param: lsampl_t maxdata
+Description:
+
+Function: comedi_from_phys -- convert physical units to sample
+Retval: lsampl_t
+Param: double data
+Param: comedi_range * range
+Param: lsampl_t maxdata
+Description:
+
+Function: comedi_data_read -- read single sample from channel
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int channel
+Param: unsigned int range
+Param: unsigned int aref
+Param: lsampl_t * data
+Description:
+
+Function: comedi_data_write -- write single sample to channel
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int channel
+Param: unsigned int range
+Param: unsigned int aref
+Param: lsampl_t data
+Description:
+
+Function: comedi_dio_config -- change input/output properties of channel
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int channel
+Param: unsigned int direction
+Description:
+
+Function: comedi_dio_read -- read single bit from digital channel
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int channel
+Param: unsigned int * bit
+Description:
+
+Function: comedi_dio_write -- write single bit to digital channel
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int channel
+Param: unsigned int bit
+Description:
+
+Function: comedi_dio_bitfield -- read/write multiple digital channels
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int write_mask
+Param: unsigned int * bits
+Description:
+
+Function: comedi_sv_init -- slowly-varying inputs
+Retval: int
+Param: comedi_sv_t * sv
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int channel
+Description:
+
+Function: comedi_sv_update -- slowly-varying inputs
+Retval: int
+Param: comedi_sv_t * sv
+Description:
+
+Function: comedi_sv_measure -- slowly-varying inputs
+Retval: int
+Param: comedi_sv_t * sv
+Param: double * data
+Description:
+
+Function: comedi_get_cmd_src_mask -- streaming input/output capabilities
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: comedi_cmd * command
+Description:
+
+Function: comedi_get_cmd_generic_timed -- streaming input/output capabilities
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: comedi_cmd * command
+Param: unsigned int period_ns
+Description:
+
+Function: comedi_cancel -- stop streaming input/outpu in progress
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Description:
+
+Function: comedi_command -- start streaming input/output
+Retval: int
+Param: comedi_t * device
+Param: comedi_cmd * command
+Description:
+
+Function: comedi_command_test -- test streaming input/output configuration
+Retval: int
+Param: comedi_t * device
+Param: comedi_cmd * command
+Description:
+
+Function: comedi_poll -- force updating of streaming buffer
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Description:
+
+Function: comedi_set_max_buffer_size -- streaming buffer size of subdevice
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int max_size
+Description:
+
+Function: comedi_get_buffer_contents -- streaming buffer status
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Description:
+
+Function: comedi_mark_buffer_read -- streaming buffer status
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int num_bytes
+Description:
+
+Function: comedi_get_buffer_offset -- streaming buffer status
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Description:
+
+Function: comedi_get_timer -- timer information (deprecated)
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: double frequency
+Param: unsigned int * trigvar
+Param: double * actual_frequency
+Description:
+Status: deprecated
+
+Function: comedi_timed_1chan -- streaming input (deprecated)
+Retval: int
+Param: comedi_t * device
+Param: unsigned int subdevice
+Param: unsigned int channel
+Param: unsigned int range
+Param: unsigned int aref
+Param: double frequency
+Param: unsigned int num_samples
+Param: double * data
+Description:
+Status: deprecated
+
+Function: comedi_set_global_oor_behavior -- out-of-range behavior
+Retval: int
+Param: enum comedi_oor_behavior behavior
+Description:
+Status: alpha
+
diff --git a/doc/docbook/install.sgml b/doc/docbook/install.sgml
new file mode 100644 (file)
index 0000000..5f54875
--- /dev/null
@@ -0,0 +1,234 @@
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
+
+
+<section>
+<title>
+Installation and Configuration
+</title>
+
+<para>
+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.
+</para>
+
+<para>
+To tell the comedi kernel module that you have a particular device, and
+some information about it, you will be running the comedi_config
+command.  Perhaps you should read the man page now.
+</para>
+
+<para>
+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.
+</para>
+
+<para>
+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:
+</para>
+
+
+<screen>
+# ANSI string --&gt;National Instruments, AT-MIO-16E-10&lt;--
+(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)
+))
+</screen>
+
+
+<para>
+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.
+</para>
+
+<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
+</para>
+
+<screen>
+/usr/sbin/comedi_config /dev/comedi0 ni_atmio 0x260,3
+</screen>
+
+<para>
+into <filename>/etc/rc.d/rc.local</filename>.  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.
+</para>
+
+<para>
+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:
+</para>
+
+<!-- XXX
+<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>
+-->
+
+<para>
+(ai=analog input, ao=analog output.)  From this, I decide that
+the appropriate options list is
+</para>
+
+<screen>
+0x200,4,,1,1,1
+</screen>
+
+<para>
+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.
+</para>
+
+<screen>
+/usr/sbin/comedi_config /dev/comedi1 dt2821-f-8di 0x200,4,,1,1,1
+</screen>
+
+<para>
+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):
+</para>
+
+<screen>
+comedi0: ni_atmio: 0x0200 can't find board
+</screen>
+
+<para>
+When it does work, I get:
+</para>
+
+<screen>
+comedi0: ni_atmio: 0x0260 at-mio-16e-10 ( irq = 3 )
+</screen>
+
+<para>
+Note that it also correctly identified my board.
+</para>
+
+
+<section>
+<title>
+Getting information from comedi
+</title>
+
+<para>
+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:
+</para>
+
+<screen>
+cat /proc/comedi
+</screen>
+
+<para>
+Right now, on my computer, this command gives:
+</para>
+
+<screen>
+comedi version 0.6.4
+format string
+ 0: ni_atmio             at-mio-16e-10           7
+ 1: dt282x               dt2821-f-8di            4
+</screen>
+
+<para>
+This is a feature that is not well-developed yet.  Basically, it
+currently tells you driver name, device name, and number of
+subdevices.
+</para>
+
+<para>
+In the <filename>demo/</filename> directory, there is a command called
+<command>info</command>, 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 <filename>/dev/comedi0</filename>.)  ('demo/info /dev/comedi0')
+</para>
+
+<screen>
+overall info:
+  version code: 0x000604
+  driver name: ni_atmio
+  board name: at-mio-16e-10
+  number of subdevices: 7
+subdevice 0:
+  type: 1 (unknown)
+  number of channels: 16
+  max data value: 4095
+...
+</screen>
+
+<para>
+The overall info gives information about the device -- basically
+the same information as /proc/comedi.
+</para>
+
+<para>
+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.
+</para>
+
+<para>
+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.
+</para>
+
+
+</section>
+</section>
diff --git a/doc/docbook/intro.sgml b/doc/docbook/intro.sgml
new file mode 100644 (file)
index 0000000..125bdb5
--- /dev/null
@@ -0,0 +1,315 @@
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
+<!--ignore the error caused by previous line-->
+
+<section>
+
+<title>
+Introduction
+</title>
+
+<para>
+This section gives high-level explanation about which functionality
+you can expect from the software. Details are given in the following
+sections of this document.
+</para>
+
+<section>
+<title>
+What is a "device driver"?
+</title>
+<para>
+A device driver is a piece of software that interfaces a particular
+piece of hardware: a printer, a sound card, a motor drive, etc. It
+translates the primitive, device-dependent commands with which the
+hardware manufacturer want you to configure, read and write the
+electronics of the hardware interface into more abstract and generic
+function calls and data structures for the application programmer.
+</para>
+
+<para>
+David Schleef started the Comedi project to interface
+lots of different cards for measurement and control purposes. This
+type of cards are often called Data AcQuisition cards, or DAQ cards.
+Schleef designed a structure which is a balance between
+modularity (i.e., it's fairly easy to integrate a new card because
+most of the infrastructure part of the driver can be reused) and
+complexity (i.e., the structure doesn't present so much overhead that
+new contributors are scared away from writing their new drivers within
+the Comedi framework). The Comedi project consists of two
+complementary packages: "comedi" (which implements the kernel space
+functionality) and "comedilib" (which implements the user space access
+to the device driver functionality). Comedi works with a standard
+Linux kernel, but also with its real-time extensions RTAI and
+Real-Time Linux.
+</para>
+</section>
+
+<section>
+<title>
+A general DAQ device driver package.
+</title>
+<para>
+From the point of view of system developers, it is worthwhile to
+standardize the structure and API (Application Programming Interface)
+for device drivers as much as possible: 
+</para>
+
+<para>
+  API: devices that offer similar functionalities, should have the same
+  software interface, and their differences should be coped with by
+  parameterizing the interfaces, not by changing the interface for
+  each new device in the family. 
+
+<para>
+  Structure: many electronic interfaces have more than one layer of
+  functionality between the hardware and the operating system, and
+  the device driver code should reflect this fact. For example, many
+  different interface cards use the same PCI driver chips, or use the
+  parallel port to connect to the hardware device. Hence, providing
+  "low-level" device drivers for these PCI chips and parallel ports
+  allows for an increased modularity and re-useability of the software.
+</para>
+
+<para>
+In the case of Linux as the host operating system, device driver
+writers must keep the following Linux-specific issues in mind:
+</para>
+
+<para>
+  Kernel space vs. User space.
+  The Linux operating system has two levels: only privileged processes
+  can run in the kernel, where they have access to all hardware and to
+  all kernel data structures and system calls; normal application
+  programs can run their processes only in user space, where these
+  processes are shielded from each other, and from direct access to
+  hardware and to critical data of the operating system. Device drivers
+  typically must access specific addresses on the bus, and hence use
+  privileged system calls.  Therefore, a device driver has a component
+  in kernel space.  One can write a user space driver for, for example,
+  a device on the parallel port, but in this case, the basic parallel
+  port device driver runs already in the kernel by default; the
+  interaction with the hardware then takes place via the method
+  explained below.
+</para>
+
+<para>
+  Device files or device file system.
+  The users that want to write an application for a particular device,
+  must link their application to the device's device driver. This device
+  driver, however, runs in kernel space, and the user application in
+  user space. So, the operating system provides an interface between
+  both. In Linux or Unix, these interfaces are in the form of "files"
+  in the /dev directory (2.2.x kernels or earlier) or /devfs directory
+  (2.4.x kernels and later). Each device has a representative, and can
+  be accessed by the classical Unix file I/O calls: open, close, read,
+  write, and ioctl.
+</para>
+
+<para>
+  /proc interface.
+  Linux offers a file-like interface to attached devices (and other
+  OS-related information) via the /proc directories. This interface
+  allows to inspect the current status of each device.
+</para>
+
+<para>
+  Direct Memory Access (DMA) vs. Programmed Input/Output (PIO).
+  Almost all devices can be interfaced in PIO mode: the processor is
+  responsible for accessing bus addresses allocated to the device, and
+  to read or write data. Some devices also allow DMA: the device and the
+  memory "talk" to each other directly, without needing the processor.
+  DMA is a feature of the bus, not of the operating system (which has
+  to support its processes to use the feature, of course).
+</para>
+
+<para>
+If the device is to be used in a Real-Time Linux or RTAI application,
+there are a few extra requirements, because not all system calls are
+available in the RTOS kernel of Real-Time Linux or RTAI.
+</para>
+</section>
+
+
+<section>
+<title>
+Policy vs. mechanism.
+</title>
+<para>
+Device drivers are often written by application programmers, that have
+a particular application in mind. For example, one writes a driver for
+the parallel port, because one wants to use it to generate pulses that
+drive a stepper motor. This approach often leads to device drivers
+that depend too much on the application, and are not general enough to
+be re-used for other applications. One golden rule for the device
+driver writer is to separate mechanism and policy:
+</para>
+
+<para>
+  Mechanism.
+  The mechanism part of the device interface is a faithful
+  representation of the bare functionality of the device, independent of
+  what part of the functionality an application will use.
+</para>
+
+<para>
+  Policy.
+  Once a device driver offers a software interface to the mechanism of
+  the device, an application writer can use this mechanism interface to
+  use the device in one particular fashion. That is, some of the data
+  stuctures offered by the mechanism are interpreted in specific
+  physical units, or some of them are taken together because this
+  composition is relevant for the application. For example, a analog
+  output card can be used to generate voltages that are the inputs for
+  the electronic drivers of the motors of a robot; these voltages can be
+  interpreted as setpoints for the desired velocity of these motors, and
+  six of them are taken together to steer one particular robot with
+  six-degrees of freedom. Some of the other outputs of the same physical
+  device can be used by another application program, for example to
+  generate a sine wave that drives a vibration shaker.
+</para>
+</section>
+
+<section>
+<title>
+Overview of Comedi.
+</title>
+<para>
+The supported cards in Comedi have one or more of the following
+features: analog input channels, analog output channels, digital input
+channels, and digital output channels. The digital channels are
+conceptually quite simple, and don't need much configuration: the
+number of channels, their addresses on the bus, and their direction
+(input/output).
+</para>
+
+<para>
+The analog channels are a bit more complicated. Typically, an analog
+channel can be programmed to generate or read a voltage between a
+lower and an upper threshold (e.g., -10V and +10V); the card's
+electronics can be programmed to automatically sample a set of
+channels, in a prescribed order; top buffer sequences of data on the
+board; or to use DMA to dump the data in an available part of memory,
+without intervention from the processor.
+</para>
+
+<para>
+Many interface cards have extra functionality, besides the analog and
+digital channels. For example, an EEPROM for configuration and board
+parameters, calibration inputs, counters and timers, encoders (=
+quadrature counter on two channels), etc. Therefore, Comedi offers
+more than just analog and digital data acquisition.
+</para>
+
+<para>
+The kernel space structures that Comedi uses have the following
+hierarchy:
+</para>
+<para>
+- channel: the lowest-level component, that represents the properties
+  of one single data channel (analog in or out; digital in or out).
+  Each channel has parameters for: the voltage range, the reference
+  voltage, the channel polarity (unipolar, bipolar), a conversion
+  factor between voltages and physical units.
+</para>
+<para>
+- sub-device: a set of functionally identical channels that are
+  physically implemented on the same (chip on an) interface card. For
+  example, a set of 16 identical analog outputs.
+  Each sub-device has parameters for: the number of channels, and the type
+  of the channels.
+</para>
+<para>
+- device: a set of sub-devices that are physically implemented on the
+  same interface card; in other words, the interface card itself.
+  For example, the NI 6024E device has a sub-device with 16 analog input
+  channels, another sub-device with two analog output channels, and a
+  third sub-device with eight digital inputs/outputs.
+  Each device has parameters for: the device identification tag from
+  the manufacturer, the identification tag given by the operating system
+  (in order to discriminate between multiple interface cards of the same
+  type), the number of sub-devices, etc.
+</para>
+
+<para>
+The basic functionalities offered by Comedi are:
+</para>
+<para>
+- instruction: to synchronously perform one single data acquisition on a
+  specified channel, or to perform a configuration on the channel.
+  "Synchronous" means that the calling process blocks until the data
+  acquisition has finished.
+</para>
+<para>
+- scan: repeated instructions on a number of different channels, with a
+  programmed sequence and timing.
+</para>
+<para>
+- command: start or stop an autonomous (and hence aynchronous) data
+  acquisition (i.e., a number of scans) on a specified set of
+  channels. "Autonomous" means: without interaction from the software,
+  i.e., by means of on-board timers or possibly external triggers.
+</para>
+<para>
+This command functionality is not offered by all DAQ cards.  When
+using RTAI or Real-Time Linux, the command functionality is emulated
+through the "comedi_rt_timer" virtual driver.
+The command functionality is very configurable, with respect to the
+choice of events with which to signal the progress of the programmed
+scans: external triggers, end of instruction, etc.
+</para>
+
+<para>
+Comedi not only offers the API to access the functionality of the
+cards, but also to query the capabilities of the installed Comedi
+devices. That is, a user process can find out on-line what channels
+are available, and what their physical parameters are (range,
+direction of input/output, etc.).
+</para>
+
+<para>
+Buffers are an important aspect of device drivers: the data has
+to be stored in such buffers, if the application program cannot
+guarantee to read or write the data as soon as the interface board
+wants to do so. Therefore, Comedi offers functionality to configure
+and manage data buffers.
+</para>
+
+<para>
+Comedi contains more than just procedural function calls: it also
+offers event-driven functionality. The data acquisition can signal
+its completion by means of an interrupt or a callback function call.
+Callbacks are also used to signal errors during the data
+acquisition or when writing to buffers, or at the end of a scan or
+acquisition that has been launched previously to take place
+asynchronously (i.e., the card fills up som shared memory buffer
+autonomously, and only warns the user program after it has finished).
+</para>
+
+<para>
+The mechanisms for synchronization and interrupt handling are a bit
+different when used in a real-time context (i.e., with either RTAI or
+Real-Time Linux), but both are encapsulated behind the same Comedi calls.
+</para>
+
+<para>
+Because multiple devices can all be active at the same time, Comedi
+provides (non-SMP!) locking primitives to ensure atomic operations on
+critical sections of the code or data structures.
+</para>
+
+<para>
+Finally, Comedi offers the above-mentioned "high-level" interaction,
+i.e., at the level of user space device drivers, through file
+operations on entries in the /dev directory (for access to the
+device's functionality), or interactively from the command line
+through the "files" in the /proc directory (which allow to inspect
+the status of a Comedi device).  This high-level interface resides in
+the "comedilib" tarball, which is the user space library, with
+facilities to connect to the kernel space drivers residing in the
+"comedi" tarball.
+</para>
+</section>
+
+
+</section>
+
diff --git a/doc/docbook/mkdr b/doc/docbook/mkdr
new file mode 100755 (executable)
index 0000000..ed475e8
--- /dev/null
@@ -0,0 +1,149 @@
+#!/usr/bin/perl
+# vim: set ts=4:
+
+$manvolnum="3";
+$header="#include &lt;comedilib.h&gt;";
+
+$end = "";
+
+print
+"<!--This file is autogenerated.  Do not edit-->
+<section>
+  <title>
+    Low-level drivers
+  </title>
+";
+
+while(<>){
+       push @lines,$_;
+}
+
+$secend="";
+
+while($s = shift @lines){
+       @x = $s;
+       if($s =~ m/^\w+\:/){
+               $blank=0;
+               chomp $s;
+               $x = $s;
+               LOOP: while($s = shift @lines){
+                       if($s =~ m/^\w+:/ or $s eq "\n"){
+                               unshift @lines, $s;
+                               last LOOP;
+                       }
+                       chomp $s;
+                       $x = "$x $s";
+               }
+               if($x =~ m/^Driver: (.*)/){
+                       $driver = $1;
+               }elsif($x =~ m/^Description: (.*)/){
+                       $description = $1;
+               }elsif($x =~ m/^Devices: (.*)/){
+                       $devices = $1;
+               }elsif($x =~ m/^Author: (.*)/){
+                       $author = $1
+               }
+       }else{
+               if($s eq "\n"){
+                       $blank ++;
+               }else{
+                       $blank = 0;
+               }
+               $comment = $comment . $s;
+       }
+       if($blank==3){
+               $comment =~ s/@/&#64;/g;
+               $comment =~ s/</&lt;/g;
+               $comment =~ s/>/&gt;/g;
+               $author =~ s/@/&#64;/g;
+               $author =~ s/</&lt;/g;
+               $author =~ s/>/&gt;/g;
+               print 
+"
+<section>
+  <title>
+$driver -- $description
+  </title>
+  <para>
+Author: $author
+  </para>
+";
+               if($devices ne ""){
+                       print
+"  <informaltable>
+  <tgroup cols='3' align='left'>
+  <thead>
+  <row>
+  <entry>Manufacturer</entry>
+  <entry>Device</entry>
+  <entry>Name</entry>
+  </row>
+  </thead>
+  <tbody>
+";
+                       while($devices){
+                               $_=$devices;
+                               if(m/^ *\[([^\]]+)\](.*)/){
+                                       $mfr = $1;
+                                       $devices = $2;
+                               }elsif(m/^ *\(([^\)]+)\)(.*)/){
+                                       $name = $1;
+                                       $devices = $2;
+                               }elsif(m/^ *([^\(,]+)(.*)/){
+                                       $dev = $1;
+                                       $devices = $2;
+                                       $dev =~ s/ *$//;
+                               }elsif(m/^ *,(.*)/){
+                                       $devices = $1;
+                                       print
+"    <row>
+      <entry>
+$mfr
+      </entry>
+      <entry>
+$dev
+      </entry>
+      <entry>
+$name
+      </entry>
+    </row>
+";
+                               }else{
+                                       die "parse error";
+                               }
+                       }
+                       print
+"    <row>
+      <entry>
+$mfr
+      </entry>
+      <entry>
+$dev
+      </entry>
+      <entry>
+$name
+      </entry>
+    </row>
+       </tbody>
+       </tgroup>
+       </informaltable>
+";
+               }
+               print
+"
+  <screen>
+$comment
+  </screen>
+</section>";
+               $blank=0;
+
+               $comment="";
+       }
+}
+
+print
+"</section>
+";
+
+exit(0);
+
diff --git a/doc/docbook/mkref b/doc/docbook/mkref
new file mode 100755 (executable)
index 0000000..267c969
--- /dev/null
@@ -0,0 +1,106 @@
+#!/usr/bin/perl
+# vim: set ts=4:
+
+$manvolnum="3";
+$header="#include &lt;comedilib.h&gt;";
+
+$end = "";
+
+print
+"<!--This file is autogenerated.  Do not edit-->
+<section>
+  <title>
+    Comedi Function Reference
+  </title>
+";
+
+while($s = <>){
+       chomp $s;
+       if($s eq ""){
+               print $end;
+               print
+"</refentry>
+";
+               $end = "";
+       }elsif($s =~ m/^Function: (.*)/){
+               $funcname = $1;
+               $refpurpose = "";
+               if($s =~ m/^Function: (.*) -- (.*)/){
+                       $funcname = $1;
+                       $refpurpose = $2;
+               }
+               $refname = $funcname;
+               $refname =~ s/_/-/g;
+               $refname = "func-ref-" . $refname;
+               print $end;
+               print
+"<refentry id=\"$refname\">
+
+  <refmeta>
+    <refentrytitle>$funcname</refentrytitle>
+    <manvolnum>$manvolnum</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>$funcname</refname>
+    <refpurpose>$refpurpose</refpurpose>
+  </refnamediv>
+";
+               $end = "";
+       }elsif($s =~ m/^Retval: (.*)/){
+               print
+"  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>$header</funcsynopsisinfo>
+      <funcprototype>
+        <funcdef>$1 <function>$funcname</function></funcdef>
+";
+               $end =
+"      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+";
+       }elsif($s =~ m/^Param: (.*)/){
+               $p = $1;
+               $p =~ m/(.*) (.*)/;
+               print
+"        <paramdef>$1 <parameter>$2</parameter></paramdef>
+"
+       }elsif($s =~ m/^Description:/){
+               print $end;
+               print
+"  <refsect1>
+    <title>
+      Description
+    </title>
+    <para>
+";
+               $end =
+"    </para>
+  </refsect1>
+";
+       }elsif($s =~ m/^Status: (.*)/){
+               print $end;
+               print
+"  <refsect1>
+    <title>
+      Status
+    </title>
+    <para>
+         $1
+";
+               $end =
+"    </para>
+  </refsect1>
+";
+       }elsif($s =~ m/^ (.*)/){
+               print "$1\n";
+       }
+}
+
+print
+"</section>
+";
+
+exit(0);
+
diff --git a/doc/docbook/other.sgml b/doc/docbook/other.sgml
new file mode 100644 (file)
index 0000000..d5f6303
--- /dev/null
@@ -0,0 +1,672 @@
+<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,&amp;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,&amp;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.
+
diff --git a/doc/docbook/reference.sgml b/doc/docbook/reference.sgml
new file mode 100644 (file)
index 0000000..23899b4
--- /dev/null
@@ -0,0 +1,987 @@
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook V3.1//EN">
+
+<section>
+<title>
+Constants and Macros
+</title>
+
+<section id="ref-macro-CR-PACK">
+<title>
+CR_PACK
+</title>
+
+<para>
+CR_PACK is used to initialize the elements of the chanlist array in the
+comedi_cmd structure, and the chanspec member
+of the comedi_insn structure.
+</para>
+
+<para>
+The channel argument is the channel you wish to use, with the channel
+numbering starting at zero.
+</para>
+
+<para>
+The range is an index, starting at zero, whose meaning
+is device dependent.  The
+comedi_get_n_ranges() and
+comedi_get_range functions
+are useful in discovering information about the available ranges.
+</para>
+
+<para>
+The aref argument indicates what reference you want the device to use.  It
+can be any of the following:
+</para>
+
+<variablelist>
+  <varlistentry>
+    <term>AREF_GROUND</term>
+    <listitem>
+      <para>
+        is for inputs/outputs referenced to ground
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>AREF_COMMON</term>
+    <listitem>
+      <para>
+    is for a `common' reference (the low inputs of all the channels are tied
+together, but are isolated from ground)
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>AREF_DIFF</term>
+    <listitem>
+      <para>
+    is for differential inputs/outputs
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>AREF_OTHER</term>
+    <listitem>
+      <para>
+    is for any reference that does not fit into the above categories
+      </para>
+    </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>
+Particular drivers may or may not use the AREF flags.  If they are
+not supported, they are silently ignored.
+</para>
+</section>
+
+<section id="ref-macro-RANGE-LENGTH">
+<title>
+RANGE_LENGTH (deprecated)
+</title>
+
+<para>
+Rangetype values are library-internal tokens that represent an
+array of range information structures.  These numbers are primarily
+used for communication between the kernel and library.
+</para>
+
+<para>
+The RANGE_LENGTH() macro returns the length of the array that is
+specified by the rangetype token.
+</para>
+
+<para>
+The RANGE_LENGTH() macro is deprecated, and should not be used in
+new applications.  It is scheduled to be removed from the header
+file at version 1.0.  Binary compatibility may be broken for version
+1.1.
+</para>
+</section>
+
+</section>
+
+<section>
+<title>
+Data Types and Structures
+</title>
+
+<section id="ref-type-comedi-t">
+<title>
+comedi_t
+</title>
+
+<para>
+The data type comedi_t is used to represent an open Comedi
+device.  A valid comedi_t pointer is returned by a successful
+call to comedi_open(), and should be used for subsequent
+access to the device.
+It is a transparent type, and pointers to type comedi_t
+should not be dereferenced by the application.
+</para>
+
+</section>
+
+
+<section id="ref-type-sampl-t">
+<title>
+sampl_t
+</title>
+
+
+<para>
+The data type sampl_t is one of the generic types used to represent
+data values in Comedilib.  It is used in a few places where a data type
+shorter than lsampl_t is useful.  On most architectures, sampl_t
+is defined to be uint16.
+</para>
+
+<para>
+Most drivers represent data trasferred by read() and write()
+using sampl_t.  Applications should check the subdevice flag
+SDF_LSAMPL to determine if the subdevice uses sampl_t or
+lsampl_t.
+</para>
+
+</section>
+
+<section id="ref-type-lsampl-t">
+<title>
+lsampl_t
+</title>
+
+<para>
+The data type lsampl_t is the data type typically used to represent
+data values in libcomedi.  On most architectures, lsampl_t is
+defined to be uint32.
+</para>
+</section>
+
+
+<section id="ref-type-comedi-trig">
+<title>
+comedi_trig (deprecated)
+</title>
+
+<programlisting>
+struct comedi_trig_struct{
+       unsigned int subdev;            /* subdevice */
+       unsigned int mode;              /* mode */
+       unsigned int flags;
+       unsigned int n_chan;            /* number of channels */
+       unsigned int *chanlist;         /* channel/range list */
+       sampl_t *data;                  /* data list, size depends on subd flags */
+       unsigned int n;                 /* number of scans */
+       unsigned int trigsrc;
+       unsigned int trigvar;
+       unsigned int trigvar1;
+       unsigned int data_len;
+       unsigned int unused[3];
+}
+</programlisting>
+
+<para>
+The comedi_trig structure is a control structure used by the
+COMEDI_TRIG ioctl, an older method of communicating
+instructions to the driver and hardware.  Use of comedi_trig is
+deprecated, and should not be used in new applications.
+</para>
+</section>
+
+<section id="ref-type-comedi-sv-t">
+<title>
+comedi_sv_t
+</title>
+
+<programlisting>
+struct comedi_sv_struct{
+       comedi_t *dev;
+       unsigned int subdevice;
+       unsigned int chan;
+
+       /* range policy */
+       int range;
+       int aref;
+
+       /* number of measurements to average (for ai) */
+       int n;
+
+       lsampl_t maxdata;
+}
+</programlisting>
+
+<para>
+The comedi_sv_t structure is used by the comedi_sv_*()
+functions to provide a simple method of accurately measuring
+slowly varying inputs.  See the relevant section for more
+details.
+</para>
+</section>
+
+<section id="ref-type-comedi-cmd">
+<title>
+comedi_cmd
+</title>
+
+<programlisting>
+typedef struct comedi_cmd_struct comedi_cmd;
+
+struct comedi_cmd_struct{
+       unsigned int subdev;
+       unsigned int flags;
+
+       unsigned int start_src;
+       unsigned int start_arg;
+
+       unsigned int scan_begin_src;
+       unsigned int scan_begin_arg;
+
+       unsigned int convert_src;
+       unsigned int convert_arg;
+
+       unsigned int scan_end_src;
+       unsigned int scan_end_arg;
+
+       unsigned int stop_src;
+       unsigned int stop_arg;
+
+       unsigned int *chanlist;
+       unsigned int chanlist_len;
+
+       sampl_t *data;
+       unsigned int data_len;
+};
+</programlisting>
+
+<para>
+More information on using commands can be found in the
+command section.
+</para>
+</section>
+
+<section id="ref-type-comedi-insn">
+<title>
+comedi_insn
+</title>
+
+<programlisting>
+typedef struct comedi_insn_struct comedi_insn;
+
+struct comedi_insn_struct{
+       unsigned int insn;
+       unsigned int n;
+       lsampl_t *data;
+       unsigned int subdev;
+       unsigned int chanspec;
+       unsigned int unused[3];
+};
+</programlisting>
+
+<para>
+Comedi instructions are described by the comedi_insn structure.
+Applications send instructions to the driver in order to preform
+control and measurement operations that are done immediately or
+synchronously, i.e., the operations complete before program control
+returns to the application.  In particular, instructions cannot
+describe acquisition that involves timers or external events.
+</para>
+
+<para>
+The field insn determines the type of instruction that is sent
+to the driver.  Valid instruction types are
+</para>
+
+<variablelist>
+  <varlistentry>
+    <term>
+INSN_READ
+    </term>
+    <listitem>
+      <para>
+read values from an input channel
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+INSN_WRITE
+    </term>
+    <listitem>
+      <para>
+write values to an output channel
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+INSN_BITS
+    </term>
+    <listitem>
+      <para>
+read/write values on multiple digital I/O channels
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+INSN_CONFIG
+    </term>
+    <listitem>
+      <para>
+configure a subdevice
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+INSN_GTOD
+    </term>
+    <listitem>
+      <para>
+read a timestamp, identical to gettimeofday()
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+INSN_WAIT
+    </term>
+    <listitem>
+      <para>
+wait a specified number of nanoseconds
+      </para>
+    </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>
+The number of samples to read or write, or the size of the configuration
+structure is specified by the field n, and the buffer for those
+samples by data.  The field subdev is the subdevice index
+that the instruction is sent to.  The field chanspec specifies
+the channel, range, and analog reference (if applicable).
+</para>
+
+<para>
+Instructions can be sent to drivers using comedi_do_insn().
+Multiple instructions can be sent to drivers in the same system
+call using comedi_do_insnlist().
+</para>
+</section>
+
+<section id="ref-type-comedi-range">
+<title>
+comedi_range
+</title>
+
+<programlisting>
+typedef struct{
+       double min;
+       double max;
+       unsigned int unit;
+}comedi_range;
+</programlisting>
+
+<para>
+The comedi_range structure conveys part of the information
+necessary to translate sample values to physical units, in particular,
+the endpoints of the range and the physical unit type.  The
+physical unit type is specified by the field unit, which may
+take the values UNIT_volt for volts, UNIT_mA for milliamps,
+or UNIT_none for unitless.  The endpoints are specified by
+the fields min and max.
+</para>
+</section>
+
+<section id="ref-type-comedi-krange">
+<title>
+comedi_krange
+</title>
+
+<programlisting>
+struct comedi_krange_struct{
+       int min;
+       int max;
+       unsigned int flags;
+};
+</programlisting>
+
+<para>
+The comedi_krange structure is used to transfer range information
+between the driver and Comedilib, and should not normally be used
+by applications.  The structure conveys the same information as the
+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>
+</section>
+
+</section>
+
+<section>
+<title>
+Interface reference
+</title>
+
+<para>
+This chapter is meant to be a reference for some of the advanced
+features of Comedi.
+</para>
+
+<section>
+<title>
+Digital input combining machines
+</title>
+
+<para>
+When one or several digital inputs are used to modify an output
+value, either an accumulator or a single digital line or bit,
+a bitfield structure is typically used in the Comedi interface.
+The digital inputs have two properties, "sensitive" inputs and
+"modifier" inputs.  Edge transitions on sensitive inputs cause
+changes in the output signal, whereas modifier inputs change the
+effect of edge transitions on sensitive inputs.  Note that inputs
+can be both modifier inputs and sensitive inputs.
+</para>
+
+<para>
+For simplification purposes, it is assumed that multiple digital
+inputs do not change simultaneously.
+</para>
+
+<para>
+The combined state of the modifier inputs determine a modifier
+state.  For each combination of modifier state and sensitive
+input, there is a set of bits that determine the effect on the
+output value due to positive or negative transitions of the
+sensitive input.  For each transition direction, there are two
+bits defined as follows:
+</para>
+
+<variablelist>
+  <varlistentry>
+    <term>
+00
+    </term>
+    <listitem>
+      <para>
+transition is ignored
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+01
+    </term>
+    <listitem>
+      <para>
+accumulator is incremented, or output is set
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+10
+    </term>
+    <listitem>
+      <para>
+accumulator is decremented, or output is cleared
+      </para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>
+11
+    </term>
+    <listitem>
+      <para>
+reserved
+      </para>
+    </listitem>
+  </varlistentry>
+</variablelist>
+
+<para>
+For example, a simple digital follower is specified by the bit
+pattern 01 10, because it sets the output on positive transitions
+of the input, and clears the output on negative transitions.  A
+digital inverter is similarily 10 01.  These systems have only
+one sensitive input.
+</para>
+
+<para>
+As another example, a simple up counter, which increments on
+positive transitions of one input, is specified by 01 00.  This
+system has only one sensitive input.
+</para>
+
+<para>
+When multiple digital inputs are used, the inputs are divided
+into two types, inputs which cause changes in the accumulator, and
+those that only modify the meaning of transitions on other inputs.
+Modifier inputs do not require bitfields, but there needs to be
+a bitfield of length 4*(2^(N-1)) for each edge sensitive input,
+where N is the total number of inputs.  Since N is usually 2 or
+3, with only one edge sensitive input, the scaling issues are
+not significant.
+</para>
+</section>
+
+
+<section>
+<title>
+INSN_CONFIG
+</title>
+
+<para>
+Configuration instructions are used to access device and driver features
+that do not fit well into other parts of the Comedi interface.  This
+includes changing the direction of configurable digital I/O lines,
+configuring complex triggering engines, and counter/timer configuration.
+</para>
+
+<para>
+If a specified ID is not supported, the driver must return -EINVAL.
+</para>
+
+
+<section>
+<title>
+Digital I/O configuration
+</title>
+
+<para></para>
+<simplelist>
+  <member>
+    Status: Implemented
+  </member>
+  <member>
+    ID: COMEDI_INPUT, COMEDI_OUTPUT, COMEDI_OPENDRAIN
+  </member>
+  <member>
+    Length: 1
+  </member>
+  <member>
+    Chanspec: used to specify channel
+  </member>
+</simplelist>
+
+<para>
+These IDs are used to configure direction of digital I/O lines.
+Direction is chosen by the ID.  On typical devices, multiple
+channels are grouped together in blocks for determining direction.
+Configuring one channel in a block configures the entire block.
+</para>
+
+<para>
+There should also be a method to read the configuration.
+</para>
+
+<para>
+Errors:  Should return -EINVAL if the ID is not supported.
+</para>
+
+</section>
+
+<section>
+<title>
+Analog conversion configuration
+</title>
+
+<simplelist>
+  <member>
+Status: design
+  </member>
+  <member>
+ID: not assigned
+  </member>
+  <member>
+Length: 
+  </member>
+  <member>
+Chanspec: used to specify channel
+  </member>
+</simplelist>
+
+<para>
+Some devices have the capability to add white noise (dithering) to
+analog input measurement.  This additional noise can then be averaged
+out, to get a more accurate measurement of the input signal.  It
+should not be assumed that channels can be separately configured.
+A simple design can use 1 bit to turn this feature on/off.
+</para>
+
+<para>
+Some devices have the capability of changing the glitch characteristics
+of analog output subsytems.  The default (off) case should be where
+the average settling time is lowest.  A simple design can use 1 bit
+to turn this feature on/off.
+</para>
+
+<para>
+Some devices have a configurable analog filters as part of the analog
+input stage.  A simple designe can use 1 bit to enable/disable the
+filter.  Default is disabled, i.e., the filter being bypassed, or if
+the choice is between two filters, the filter with the largest
+bandwidth.
+</para>
+</section>
+
+<section>
+<title>
+Analog Output Waveform Generation
+</title>
+
+<simplelist>
+  <member>
+Status: design
+  </member>
+  <member>
+ID: not assigned
+  </member>
+  <member>
+Length:
+  </member>
+  <member>
+Chanspec: ignored
+  </member>
+</simplelist>
+
+<para>
+Some devices have the ability to cyclicly loop through samples kept in
+an on-board analog output FIFO.  This config should allow the user to
+enable/disable this mode.
+</para>
+
+<para>
+This config should allow the user to configure the number of samples
+to loop through.  It may be necessary to configure the channels used.
+</para>
+
+</section>
+
+<section>
+<title>
+Extended Triggering
+</title>
+
+<simplelist>
+  <member>
+Status: alpha
+  </member>
+  <member>
+ID: not assigned
+  </member>
+  <member>
+Chanspec: ignored
+  </member>
+</simplelist>
+
+<para>
+This section covers common information for all extended
+triggering configuration, and doesn't describe a particular
+type of extended trigger.
+</para>
+
+<para>
+Extended triggering is used to configure triggering engines that
+do not fit into commands.  In a typical programming sequence, the
+application will use configuration instructions to configure an
+extended trigger, and the issue a command, specifying TRIG_OTHER 
+as one of the trigger sources.
+</para>
+
+<para>
+Extended trigger configuration should be designed in such a way
+that the user can probe for valid parameters, similar to how
+command testing works.  An extended trigger config instruction
+should not configure the hardware directly, rather, the configuration
+should be saved until the subsequent command is issued.  This
+allows more flexibility for future interface changes.
+</para>
+
+<para>
+It has not been decided whether the config stage should return a
+token that is then used as the trigger argument in the command.
+Using tokens is one method to satisfy the problem that extended
+trigger configurations may have subtle compatiblity issues with
+other trigger sources/arguments that can only be determined at
+command test time.  Passing all stages of a command test should
+only be allowed with a properly configured extended trigger.
+</para>
+
+<para>
+Extended triggers must use data[1] as flags.  The upper 16 bits
+are reserved and used only for flags that are common to
+all extended triggers.  The lower 16 bits may be defined by the
+particular type of extended trigger.
+</para>
+
+<para>
+Various types of extended triggers must use data[1] to know which
+event the extended trigger will be assigned to in the command
+structure.  The possible values are an OR'd mask of the following:
+</para>
+
+<itemizedlist>
+  <listitem>
+    <para>
+COMEDI_EV_START
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+COMEDI_EV_SCAN_BEGIN
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+COMEDI_EV_CONVERT
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+COMEDI_EV_SCAN_END
+    </para>
+  </listitem>
+  <listitem>
+    <para>
+COMEDI_EV_STOP
+    </para>
+  </listitem>
+</itemizedlist>
+
+</section>
+
+<section>
+<title>
+Analog Triggering
+</title>
+
+<simplelist>
+  <member>
+Status: alpha
+  </member>
+  <member>
+ID: not assigned
+  </member>
+  <member>
+Implementation: ni_mio_common
+  </member>
+  <member>
+Chanspec: ignored
+  </member>
+</simplelist>
+
+<simplelist>
+  <member>
+data 1  - trigger and combining machine configuration
+  </member>
+  <member>
+data 2  - analog triggering signal chanspec
+  </member>
+  <member>
+data 3  - primary analog level
+  </member>
+  <member>
+data 4  - secondary analog level
+  </member>
+</simplelist>
+
+<para>
+Analog triggering is described by a digital combining machine that
+has two sensitive digital inputs.  The sensitive digital inputs are
+generated by configurable analog comparators.  The analog comparators
+generate a digital 1 when the analog triggering signal is greater
+than the comparator level.  The digital inputs are not modifier
+inputs.  Note, however, there is an effective modifier due to the
+restriction that the primary analog comparator level must be less
+than the secondary analog comparator level.
+</para>
+
+<para>
+If only one analog comparator signal is used, the combining machine
+for the secondary input should be set to ignored, and the secondary
+analog level should be set to 0.
+</para>
+
+<para>
+The interpretation of the chanspec and voltage levels is device
+dependent, but should correspond to similar values of the analog
+input subdevice, if possible.
+</para>
+
+<para>
+Notes:  Reading range information is not addressed.  This makes it
+difficult to convert comparator voltages to data values.
+</para>
+
+<para>
+Possible extensions: A parameter that specifies the necessary time
+that the set condition has to be true before the trigger is generated.
+A parameter that specifies the necessary time that the reset condition
+has to be true before the state machine is reset.
+</para>
+
+</section>
+
+<section>
+<title>
+Bitfield Pattern Matching Extended Trigger
+</title>
+
+<simplelist>
+  <member>
+Status: design
+  </member>
+  <member>
+ID: not assigned
+  </member>
+  <member>
+Chanspec: ignored
+  </member>
+</simplelist>
+
+<simplelist>
+  <member>
+data 1  - trigger flags
+  </member>
+  <member>
+data 2  - mask
+  </member>
+  <member>
+data 3  - pattern
+  </member>
+</simplelist>
+
+<para>
+The pattern matching trigger issues a trigger when all of a specifed 
+set of input lines match a specified pattern.  If the device allows,
+the input lines should correspond to the input lines of a digital input
+subdevice, however, this will necessarily be device dependent.  Each
+possible digital line that can be matched is assigned a bit in the
+mask and pattern.  A bit set in the mask indicates that the
+input line must match the corresponding bit in the pattern.
+A bit cleared in the mask indicates that the input line is ignored.
+</para>
+
+<para>
+Notes: This only allows 32 bits in the pattern/mask, which may be
+too few.  Devices may support selecting different sets of lines from
+which to match a pattern.
+</para>
+
+<para>
+Discovery: The number of bits can be discovered by setting the mask
+to all 1's.  The driver must modify this value and return -EAGAIN.
+</para>
+
+</section>
+
+<section>
+<title>
+Counter configuration
+</title>
+
+<simplelist>
+  <member>
+Status: design
+  </member>
+  <member>
+ID: not assigned
+  </member>
+  <member>
+Chanspec: used to specify counter
+  </member>
+</simplelist>
+
+<simplelist>
+  <member>
+data 1  - trigger configuration
+  </member>
+  <member>
+data 2  - primary input chanspec
+  </member>
+  <member>
+data 3  - primary combining machine configuration
+  </member>
+  <member>
+data 4  - secondary input chanspec
+  </member>
+  <member>
+data 5  - secondary combining machine configuration
+  </member>
+  <member>
+data 6  - latch configuration
+  </member>
+</simplelist>
+
+<para>
+Counters can be operated either in synchronous mode (using insn_read)
+or asynchronous mode (using commands), similar to analog input subdevices.
+The input signal for both modes is the accumulator.
+Commands on counter subdevices are almost always specified using
+scan_begin_src=TRIG_OTHER, with the counter configuration also serving
+as the extended configuration for the scan begin source.
+</para>
+
+<para>
+Counters are made up of an accumulator and a combining machine that
+determines when the accumulator should be incremented or decremented
+based on the values of the input signals.  The combining machine
+optionally determines when the accumulator should be latched and
+put into a buffer.  This feature is used in asynchronous mode.
+</para>
+
+<para>
+Notes: How to access multiple pieces of data acquired at each event?
+</para>
+
+</section>
+
+<section>
+<title>
+One source plus auxiliary counter configuration
+</title>
+
+<simplelist>
+  <member>
+Status: design
+  </member>
+  <member>
+ID: not assigned
+  </member>
+  <member>
+Chanspec: ?
+  </member>
+</simplelist>
+
+<para>
+data[1] is flags, including the flags for the command triggering
+configuration.  If a command is not subsequently issued on the
+subdevice, the command triggering portion of the flags are ignored.
+</para>
+
+<para>
+data[2] determines the mode of operation.  The mode of operation
+is actually a bitfield that encodes what to do for various
+transitions of the source signals.
+</para>
+
+<para>
+data[3] and data[4] determine the primary source for the counter,
+similar to _src and _arg used in commands.
+</para>
+
+
+<para>
+Notes: How to specify which events cause a latch and push, and what
+should get latched.
+</para>
+</section>
+
+</section>
+</section>
+
+
diff --git a/doc/docbook/tutorial.sgml b/doc/docbook/tutorial.sgml
new file mode 100644 (file)
index 0000000..d5f6303
--- /dev/null
@@ -0,0 +1,672 @@
+<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,&amp;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,&amp;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.
+