From: David Schleef Date: Mon, 21 Jan 2002 11:15:31 +0000 (+0000) Subject: Converting docs to DocBook 3.1 X-Git-Tag: r0_7_18~10 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=f95a0c1eac233b11ca5252307a8de0ccca691325;p=comedilib.git Converting docs to DocBook 3.1 --- diff --git a/doc/docbook/Makefile b/doc/docbook/Makefile new file mode 100644 index 0000000..aa575a4 --- /dev/null +++ b/doc/docbook/Makefile @@ -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 index 0000000..d5f6303 --- /dev/null +++ b/doc/docbook/advanced.sgml @@ -0,0 +1,672 @@ +

+Configuring comedi for your hardware +

+ + +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 comedi_config +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: + + + +# 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) +)) + + + +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 + + +/usr/sbin/comedi_config /dev/comedi0 atmio-E 0x260,3 + + +into /etc/rc.d/rc.local. 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: + + +I/O base +IRQ +1=differential, 0=single ended +ai 0=unipolar, 1=bipolar +ao0 0=unipolar, 1=bipolar +ao1 0=unipolar, 1=bipolar +dma1 +dma2 + + +(ai=analog input, ao=analog output.) From this, I decide that +the appropriate options list is + + +0x200,4,,1,1,1 + + +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. + + +/usr/sbin/comedi_config /dev/comedi1 dt2821-f-8di 0x200,4,,1,1,1 + + +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): + + +comedi0: ni_E: 0x0200 can't find board + + +When it does work, I get: + + +comedi0: ni_E: 0x0260 at-mio-16e-10 ( irq = 3 ) + + +Note that it also correctly identified my board. + + +

+Getting information from comedi +

+ + +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: + +

+ + +cat /proc/comedi + + +Right now, on my computer, this command gives: + + +comedi version 0.6.4 +format string + 0: atmio-E at-mio-16e-10 7 + 1: dt282x dt2821-f-8di 4 + + +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 demo/ directory, there is a command called +info, 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 /dev/comedi0.) ('demo/info /dev/comedi0') + + +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 + +... + + +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. + + + + + + + + +Writing programs that use comedi and comedilib +

+ +Your first comedi program +

+ +This example requires a card that has analog or +digital input. Right to the source: + + +#include /* for printf() */ +#include + +int subdev = 0; /* change this to your input subdevice */ +int chan = 0; /* change this to your channel */ +int range = 0; /* more on this later */ +int aref = AREF_GROUND; /* more on this later */ + +int main(int argc,char *argv[]) +{ + comedi_t *it; + lsampl_t data; + + it=comedi_open("/dev/comedi0"); + + comedi_data_read(it,subdev,chan,range,aref,&data); + + printf("%d\n",data); + + return 0; +} + + + +Should be understandable: open the device, get the data, +print it out. This is basically the guts of demo/inp.c, +without error checking or fancy options. +Compile it using + + +cc tut1.c -lcomedi -o tut1 + + +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. + + +

+Converting samples to voltages +

+ +If you selected an analog input subdevice, you probably noticed +that the output of tut1 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 always 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 + +

+ +typedef struct{ + double min; + double max; + unsigned int unit; +}comedi_range; + + +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 + + +volts=comedi_to_phys(it,data,range,maxdata); + + +and the opposite + + +data=comedi_from_phys(it,volts,range,maxdata); + + + +

+Another section +

+ + +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(): + +

+ +file=comedi_open("/dev/comedi0"); + + +where file is of type (comedi_t *). This function +calls open(), like we did explicitly in a previous +section, but also fills the comedi_t structure with +lots of goodies -- information that we will need to use +soon. + +Specifically, we needed to know maxdata for a specific +subdevice/channel. How about: + + +maxdata=comedi_get_maxdata(file,subdevice,channel); + + +Wow. How easy. And the range type? + + +range_type=comedi_get_rangetype(file,subdevice,channel); + + +Cool. Other information you need to know about a channel +can be gotten in a similar way. + + + +Your second comedi program +

+ + +Actually, this is the first comedi program again, just +that we've added what we've learned. + + + +#include /* for printf() */ +#include /* also included by comedilib.h */ +#include /* 'cuz we're using comedilib */ + +int subdev = 0; /* change this to your input subdevice */ +int chan = 0; /* change this to your channel */ +int range = 0; /* more on this later */ +int aref = 0; /* more on this later */ + +int main(int argc,char *argv[]) +{ + comedi_t *cf; + int chan=0; + lsampl_t data; + int maxdata,rangetype; + double volts; + + cf=comedi_open("/dev/comedi0"); + + maxdata=comedi_get_maxdata(cf,subdev,chan); + + rangetype=comedi_get_rangetype(cf,subdev,chan); + + comedi_data_read(cf->fd,subdev,chan,range,aref,&data); + + volts=comedi_to_phys(data,rangetype,range,maxdata); + + printf("%d %g\n",data,volts); + + return 0; +} + + + + + + + +

+Application-specific functions +

+ +Digital Input/Output +

+ +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 + + +Slowly-varying inputs +

+ + +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: + +

+ + +you are ultimately limited by "spurious free dynamic range" + + +you need to have _some_ noise on the input channel, +otherwise you will be averaging the same number N times. + + +the more noise you have, the greater your SFDR, but it +takes many more samples to compensate for the increased +noise + + +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. + + + +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. + + +

+Commands +

+ + +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 structure is +used to control acquisition and query the capabilities of a device +(see also , +, and +). + +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 structure. The source types are: + + +TRIG_NONE: don't ever cause an event +TRIG_NOW: cause event to occur immediately +TRIG_FOLLOW: see notes below +TRIG_TIME: cause event to occur at a particular time +TRIG_TIMER: cause event to occur repeatedly at a specific rate +TRIG_COUNT: cause event when count reaches specific value +TRIG_EXT: external signal causes event +TRIG_INT: internal signal causes event +TRIG_OTHER: driver-specific meaning + + +Not all triggers are applicable to all events. Supported triggers +for specific events depend significantly on your particular +device. The +function is useful for determining what triggers a subdevice supports. + +For every trigger, there is a corresponding +argument (the +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 +structure is the index of the subdevice the command is intended for. The + +function can be useful in discovering the index of your desired subdevice. + +The +structure should point to an array whose number of elements is specificed by macro. + +The structure is +TRIG_BOGUS: do the motions?? +TRIG_DITHER: enable dithering?? +TRIG_DEGLITCH: enable deglitching?? +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. +TRIG_CONFIG: perform configuration, not triggering. This is a legacy of the +deprecated comedi_trig_struct, and has no function at present. +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. +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. + +There are also a few flags that indicate how timing arguments should be rounded +if the hardware cannot achieve the exact timing requested. + +TRIG_ROUND_NEAREST: round to nearest supported timing period, the default. +TRIG_ROUND_DOWN: round period down. +TRIG_ROUND_UP: round period up. +TRIG_ROUND_UP_NEXT: this one doesn't do anything, and I don't know what it was intended +to do?? + + +

+ +The typical sequence for executing a command is to first send +the command through + +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 +. 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 index 0000000..a331196 --- /dev/null +++ b/doc/docbook/comedilib.sgml @@ -0,0 +1,69 @@ + + + + + +]> + +

+ + + + Comedi Documentation + + + David + Schleef + +
+ ds@schleef.org +
+
+
+ + Frank + Hess + +
+ fmhess@uiuc.edu +
+
+
+
+ +&intro + +&install + +
+ +Writing programs that use Comedi + + +Empty. + +
+ +&drivers + +
+ + Comedi Reference + + + Reference for functions, macros, and constants. + + + &reference + + &funcref + +
+ + + + +
+ diff --git a/doc/docbook/drivers.txt b/doc/docbook/drivers.txt new file mode 100644 index 0000000..d362f40 --- /dev/null +++ b/doc/docbook/drivers.txt @@ -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 +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 +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 +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 , + Frank Mori Hess +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 +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 , Frank Mori Hess +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 +. + + + +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 +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 +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 +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 +Status: unknown +Devices: [Keithley Metrabyte] DAS6402 (das6402) + + + +Driver: das800.o +Description: Keithley Metrabyte DAS800 (& compatibles) +Author: Frank Mori Hess +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 +Devices: [Inova] ICP Multi (icp_multi) + + + + +Driver: ii_pci20kc.o +Description: Intelligent Instruments PCI-20001C carrier board +Author: Markus Kempf +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 +Status: works +Devices: [Quanser Consulting] MultiQ-3 (multiq3) + + + + +Driver: ni_670x.o +Description: National Instruments 670x +Author: Bart Joris +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 +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 +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 , Eric Bunn +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 +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 +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 +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 +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 +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 +Devices: [SSV Embedded Systems] DIL/Net-PC 1486 (dnp-1486) + + + diff --git a/doc/docbook/funcref b/doc/docbook/funcref new file mode 100644 index 0000000..2141896 --- /dev/null +++ b/doc/docbook/funcref @@ -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 index 0000000..5f54875 --- /dev/null +++ b/doc/docbook/install.sgml @@ -0,0 +1,234 @@ + + + +
+ +Installation and Configuration + + + +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 comedi_config +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: + + + + +# 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) +)) + + + + +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 + + + +/usr/sbin/comedi_config /dev/comedi0 ni_atmio 0x260,3 + + + +into /etc/rc.d/rc.local. 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: + + + + + +(ai=analog input, ao=analog output.) From this, I decide that +the appropriate options list is + + + +0x200,4,,1,1,1 + + + +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. + + + +/usr/sbin/comedi_config /dev/comedi1 dt2821-f-8di 0x200,4,,1,1,1 + + + +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): + + + +comedi0: ni_atmio: 0x0200 can't find board + + + +When it does work, I get: + + + +comedi0: ni_atmio: 0x0260 at-mio-16e-10 ( irq = 3 ) + + + +Note that it also correctly identified my board. + + + +
+ +Getting information from comedi + + + +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: + + + +cat /proc/comedi + + + +Right now, on my computer, this command gives: + + + +comedi version 0.6.4 +format string + 0: ni_atmio at-mio-16e-10 7 + 1: dt282x dt2821-f-8di 4 + + + +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 demo/ directory, there is a command called +info, 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 /dev/comedi0.) ('demo/info /dev/comedi0') + + + +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 +... + + + +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. + + + +
+
diff --git a/doc/docbook/intro.sgml b/doc/docbook/intro.sgml new file mode 100644 index 0000000..125bdb5 --- /dev/null +++ b/doc/docbook/intro.sgml @@ -0,0 +1,315 @@ + + + +
+ + +Introduction + + + +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. + + +
+ +What is a "device driver"? + + +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. + + + +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. + +
+ +
+ +A general DAQ device driver package. + + +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: + + + + 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. + + + 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. + + + +In the case of Linux as the host operating system, device driver +writers must keep the following Linux-specific issues in mind: + + + + 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. + + + + 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. + + + + /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. + + + + 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). + + + +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. + +
+ + +
+ +Policy vs. mechanism. + + +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: + + + + 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. + + + + 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. + +
+ +
+ +Overview of Comedi. + + +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). + + + +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. + + + +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. + + + +The kernel space structures that Comedi uses have the following +hierarchy: + + +- 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. + + +- 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. + + +- 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. + + + +The basic functionalities offered by Comedi are: + + +- 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. + + +- scan: repeated instructions on a number of different channels, with a + programmed sequence and timing. + + +- 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. + + +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. + + + +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.). + + + +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. + + + +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). + + + +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. + + + +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. + + + +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. + +
+ + +
+ diff --git a/doc/docbook/mkdr b/doc/docbook/mkdr new file mode 100755 index 0000000..ed475e8 --- /dev/null +++ b/doc/docbook/mkdr @@ -0,0 +1,149 @@ +#!/usr/bin/perl +# vim: set ts=4: + +$manvolnum="3"; +$header="#include <comedilib.h>"; + +$end = ""; + +print +" +
+ + Low-level drivers + +"; + +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/@/@/g; + $comment =~ s//>/g; + $author =~ s/@/@/g; + $author =~ s//>/g; + print +" +
+ +$driver -- $description + + +Author: $author + +"; + if($devices ne ""){ + print +" + + + + Manufacturer + Device + Name + + + +"; + 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 +" + +$mfr + + +$dev + + +$name + + +"; + }else{ + die "parse error"; + } + } + print +" + +$mfr + + +$dev + + +$name + + + + + +"; + } + print +" + +$comment + +
"; + $blank=0; + + $comment=""; + } +} + +print +"
+"; + +exit(0); + diff --git a/doc/docbook/mkref b/doc/docbook/mkref new file mode 100755 index 0000000..267c969 --- /dev/null +++ b/doc/docbook/mkref @@ -0,0 +1,106 @@ +#!/usr/bin/perl +# vim: set ts=4: + +$manvolnum="3"; +$header="#include <comedilib.h>"; + +$end = ""; + +print +" +
+ + Comedi Function Reference + +"; + +while($s = <>){ + chomp $s; + if($s eq ""){ + print $end; + print +" +"; + $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 +" + + + $funcname + $manvolnum + + + + $funcname + $refpurpose + +"; + $end = ""; + }elsif($s =~ m/^Retval: (.*)/){ + print +" + + $header + + $1 $funcname +"; + $end = +" + + +"; + }elsif($s =~ m/^Param: (.*)/){ + $p = $1; + $p =~ m/(.*) (.*)/; + print +" $1 $2 +" + }elsif($s =~ m/^Description:/){ + print $end; + print +" + + Description + + +"; + $end = +" + +"; + }elsif($s =~ m/^Status: (.*)/){ + print $end; + print +" + + Status + + + $1 +"; + $end = +" + +"; + }elsif($s =~ m/^ (.*)/){ + print "$1\n"; + } +} + +print +"
+"; + +exit(0); + diff --git a/doc/docbook/other.sgml b/doc/docbook/other.sgml new file mode 100644 index 0000000..d5f6303 --- /dev/null +++ b/doc/docbook/other.sgml @@ -0,0 +1,672 @@ +

+Configuring comedi for your hardware +

+ + +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 comedi_config +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: + + + +# 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) +)) + + + +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 + + +/usr/sbin/comedi_config /dev/comedi0 atmio-E 0x260,3 + + +into /etc/rc.d/rc.local. 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: + + +I/O base +IRQ +1=differential, 0=single ended +ai 0=unipolar, 1=bipolar +ao0 0=unipolar, 1=bipolar +ao1 0=unipolar, 1=bipolar +dma1 +dma2 + + +(ai=analog input, ao=analog output.) From this, I decide that +the appropriate options list is + + +0x200,4,,1,1,1 + + +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. + + +/usr/sbin/comedi_config /dev/comedi1 dt2821-f-8di 0x200,4,,1,1,1 + + +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): + + +comedi0: ni_E: 0x0200 can't find board + + +When it does work, I get: + + +comedi0: ni_E: 0x0260 at-mio-16e-10 ( irq = 3 ) + + +Note that it also correctly identified my board. + + +

+Getting information from comedi +

+ + +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: + +

+ + +cat /proc/comedi + + +Right now, on my computer, this command gives: + + +comedi version 0.6.4 +format string + 0: atmio-E at-mio-16e-10 7 + 1: dt282x dt2821-f-8di 4 + + +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 demo/ directory, there is a command called +info, 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 /dev/comedi0.) ('demo/info /dev/comedi0') + + +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 + +... + + +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. + + + + + + + + +Writing programs that use comedi and comedilib +

+ +Your first comedi program +

+ +This example requires a card that has analog or +digital input. Right to the source: + + +#include /* for printf() */ +#include + +int subdev = 0; /* change this to your input subdevice */ +int chan = 0; /* change this to your channel */ +int range = 0; /* more on this later */ +int aref = AREF_GROUND; /* more on this later */ + +int main(int argc,char *argv[]) +{ + comedi_t *it; + lsampl_t data; + + it=comedi_open("/dev/comedi0"); + + comedi_data_read(it,subdev,chan,range,aref,&data); + + printf("%d\n",data); + + return 0; +} + + + +Should be understandable: open the device, get the data, +print it out. This is basically the guts of demo/inp.c, +without error checking or fancy options. +Compile it using + + +cc tut1.c -lcomedi -o tut1 + + +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. + + +

+Converting samples to voltages +

+ +If you selected an analog input subdevice, you probably noticed +that the output of tut1 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 always 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 + +

+ +typedef struct{ + double min; + double max; + unsigned int unit; +}comedi_range; + + +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 + + +volts=comedi_to_phys(it,data,range,maxdata); + + +and the opposite + + +data=comedi_from_phys(it,volts,range,maxdata); + + + +

+Another section +

+ + +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(): + +

+ +file=comedi_open("/dev/comedi0"); + + +where file is of type (comedi_t *). This function +calls open(), like we did explicitly in a previous +section, but also fills the comedi_t structure with +lots of goodies -- information that we will need to use +soon. + +Specifically, we needed to know maxdata for a specific +subdevice/channel. How about: + + +maxdata=comedi_get_maxdata(file,subdevice,channel); + + +Wow. How easy. And the range type? + + +range_type=comedi_get_rangetype(file,subdevice,channel); + + +Cool. Other information you need to know about a channel +can be gotten in a similar way. + + + +Your second comedi program +

+ + +Actually, this is the first comedi program again, just +that we've added what we've learned. + + + +#include /* for printf() */ +#include /* also included by comedilib.h */ +#include /* 'cuz we're using comedilib */ + +int subdev = 0; /* change this to your input subdevice */ +int chan = 0; /* change this to your channel */ +int range = 0; /* more on this later */ +int aref = 0; /* more on this later */ + +int main(int argc,char *argv[]) +{ + comedi_t *cf; + int chan=0; + lsampl_t data; + int maxdata,rangetype; + double volts; + + cf=comedi_open("/dev/comedi0"); + + maxdata=comedi_get_maxdata(cf,subdev,chan); + + rangetype=comedi_get_rangetype(cf,subdev,chan); + + comedi_data_read(cf->fd,subdev,chan,range,aref,&data); + + volts=comedi_to_phys(data,rangetype,range,maxdata); + + printf("%d %g\n",data,volts); + + return 0; +} + + + + + + + +

+Application-specific functions +

+ +Digital Input/Output +

+ +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 + + +Slowly-varying inputs +

+ + +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: + +

+ + +you are ultimately limited by "spurious free dynamic range" + + +you need to have _some_ noise on the input channel, +otherwise you will be averaging the same number N times. + + +the more noise you have, the greater your SFDR, but it +takes many more samples to compensate for the increased +noise + + +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. + + + +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. + + +

+Commands +

+ + +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 structure is +used to control acquisition and query the capabilities of a device +(see also , +, and +). + +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 structure. The source types are: + + +TRIG_NONE: don't ever cause an event +TRIG_NOW: cause event to occur immediately +TRIG_FOLLOW: see notes below +TRIG_TIME: cause event to occur at a particular time +TRIG_TIMER: cause event to occur repeatedly at a specific rate +TRIG_COUNT: cause event when count reaches specific value +TRIG_EXT: external signal causes event +TRIG_INT: internal signal causes event +TRIG_OTHER: driver-specific meaning + + +Not all triggers are applicable to all events. Supported triggers +for specific events depend significantly on your particular +device. The +function is useful for determining what triggers a subdevice supports. + +For every trigger, there is a corresponding +argument (the +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 +structure is the index of the subdevice the command is intended for. The + +function can be useful in discovering the index of your desired subdevice. + +The +structure should point to an array whose number of elements is specificed by macro. + +The structure is +TRIG_BOGUS: do the motions?? +TRIG_DITHER: enable dithering?? +TRIG_DEGLITCH: enable deglitching?? +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. +TRIG_CONFIG: perform configuration, not triggering. This is a legacy of the +deprecated comedi_trig_struct, and has no function at present. +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. +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. + +There are also a few flags that indicate how timing arguments should be rounded +if the hardware cannot achieve the exact timing requested. + +TRIG_ROUND_NEAREST: round to nearest supported timing period, the default. +TRIG_ROUND_DOWN: round period down. +TRIG_ROUND_UP: round period up. +TRIG_ROUND_UP_NEXT: this one doesn't do anything, and I don't know what it was intended +to do?? + + +

+ +The typical sequence for executing a command is to first send +the command through + +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 +. 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 index 0000000..23899b4 --- /dev/null +++ b/doc/docbook/reference.sgml @@ -0,0 +1,987 @@ + + +

+ +Constants and Macros + + +
+ +CR_PACK + + + +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. + + + +The channel argument is the channel you wish to use, with the channel +numbering starting at zero. + + + +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. + + + +The aref argument indicates what reference you want the device to use. It +can be any of the following: + + + + + AREF_GROUND + + + is for inputs/outputs referenced to ground + + + + + AREF_COMMON + + + is for a `common' reference (the low inputs of all the channels are tied +together, but are isolated from ground) + + + + + AREF_DIFF + + + is for differential inputs/outputs + + + + + AREF_OTHER + + + is for any reference that does not fit into the above categories + + + + + + +Particular drivers may or may not use the AREF flags. If they are +not supported, they are silently ignored. + +
+ +
+ +RANGE_LENGTH (deprecated) + + + +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. + + + +The RANGE_LENGTH() macro returns the length of the array that is +specified by the rangetype token. + + + +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. + +
+ +
+ +
+ +Data Types and Structures + + +
+ +comedi_t + + + +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. + + +
+ + +
+ +sampl_t + + + + +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. + + + +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. + + +
+ +
+ +lsampl_t + + + +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. + +
+ + +
+ +comedi_trig (deprecated) + + + +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]; +} + + + +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. + +
+ +
+ +comedi_sv_t + + + +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; +} + + + +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. + +
+ +
+ +comedi_cmd + + + +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; +}; + + + +More information on using commands can be found in the +command section. + +
+ +
+ +comedi_insn + + + +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]; +}; + + + +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. + + + +The field insn determines the type of instruction that is sent +to the driver. Valid instruction types are + + + + + +INSN_READ + + + +read values from an input channel + + + + + +INSN_WRITE + + + +write values to an output channel + + + + + +INSN_BITS + + + +read/write values on multiple digital I/O channels + + + + + +INSN_CONFIG + + + +configure a subdevice + + + + + +INSN_GTOD + + + +read a timestamp, identical to gettimeofday() + + + + + +INSN_WAIT + + + +wait a specified number of nanoseconds + + + + + + +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). + + + +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(). + +
+ +
+ +comedi_range + + + +typedef struct{ + double min; + double max; + unsigned int unit; +}comedi_range; + + + +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. + +
+ +
+ +comedi_krange + + + +struct comedi_krange_struct{ + int min; + int max; + unsigned int flags; +}; + + + +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. + +
+ +
+ +
+ +Interface reference + + + +This chapter is meant to be a reference for some of the advanced +features of Comedi. + + +
+ +Digital input combining machines + + + +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. + + + +For simplification purposes, it is assumed that multiple digital +inputs do not change simultaneously. + + + +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: + + + + + +00 + + + +transition is ignored + + + + + +01 + + + +accumulator is incremented, or output is set + + + + + +10 + + + +accumulator is decremented, or output is cleared + + + + + +11 + + + +reserved + + + + + + +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. + + + +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. + + + +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. + +
+ + +
+ +INSN_CONFIG + + + +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. + + + +If a specified ID is not supported, the driver must return -EINVAL. + + + +
+ +Digital I/O configuration + + + + + + Status: Implemented + + + ID: COMEDI_INPUT, COMEDI_OUTPUT, COMEDI_OPENDRAIN + + + Length: 1 + + + Chanspec: used to specify channel + + + + +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. + + + +There should also be a method to read the configuration. + + + +Errors: Should return -EINVAL if the ID is not supported. + + +
+ +
+ +Analog conversion configuration + + + + +Status: design + + +ID: not assigned + + +Length: + + +Chanspec: used to specify channel + + + + +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. + + + +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. + + + +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. + +
+ +
+ +Analog Output Waveform Generation + + + + +Status: design + + +ID: not assigned + + +Length: + + +Chanspec: ignored + + + + +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. + + + +This config should allow the user to configure the number of samples +to loop through. It may be necessary to configure the channels used. + + +
+ +
+ +Extended Triggering + + + + +Status: alpha + + +ID: not assigned + + +Chanspec: ignored + + + + +This section covers common information for all extended +triggering configuration, and doesn't describe a particular +type of extended trigger. + + + +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. + + + +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. + + + +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. + + + +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. + + + +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: + + + + + +COMEDI_EV_START + + + + +COMEDI_EV_SCAN_BEGIN + + + + +COMEDI_EV_CONVERT + + + + +COMEDI_EV_SCAN_END + + + + +COMEDI_EV_STOP + + + + +
+ +
+ +Analog Triggering + + + + +Status: alpha + + +ID: not assigned + + +Implementation: ni_mio_common + + +Chanspec: ignored + + + + + +data 1 - trigger and combining machine configuration + + +data 2 - analog triggering signal chanspec + + +data 3 - primary analog level + + +data 4 - secondary analog level + + + + +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. + + + +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. + + + +The interpretation of the chanspec and voltage levels is device +dependent, but should correspond to similar values of the analog +input subdevice, if possible. + + + +Notes: Reading range information is not addressed. This makes it +difficult to convert comparator voltages to data values. + + + +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. + + +
+ +
+ +Bitfield Pattern Matching Extended Trigger + + + + +Status: design + + +ID: not assigned + + +Chanspec: ignored + + + + + +data 1 - trigger flags + + +data 2 - mask + + +data 3 - pattern + + + + +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. + + + +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. + + + +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. + + +
+ +
+ +Counter configuration + + + + +Status: design + + +ID: not assigned + + +Chanspec: used to specify counter + + + + + +data 1 - trigger configuration + + +data 2 - primary input chanspec + + +data 3 - primary combining machine configuration + + +data 4 - secondary input chanspec + + +data 5 - secondary combining machine configuration + + +data 6 - latch configuration + + + + +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. + + + +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. + + + +Notes: How to access multiple pieces of data acquired at each event? + + +
+ +
+ +One source plus auxiliary counter configuration + + + + +Status: design + + +ID: not assigned + + +Chanspec: ? + + + + +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. + + + +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. + + + +data[3] and data[4] determine the primary source for the counter, +similar to _src and _arg used in commands. + + + + +Notes: How to specify which events cause a latch and push, and what +should get latched. + +
+ +
+
+ + diff --git a/doc/docbook/tutorial.sgml b/doc/docbook/tutorial.sgml new file mode 100644 index 0000000..d5f6303 --- /dev/null +++ b/doc/docbook/tutorial.sgml @@ -0,0 +1,672 @@ +

+Configuring comedi for your hardware +

+ + +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 comedi_config +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: + + + +# 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) +)) + + + +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 + + +/usr/sbin/comedi_config /dev/comedi0 atmio-E 0x260,3 + + +into /etc/rc.d/rc.local. 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: + + +I/O base +IRQ +1=differential, 0=single ended +ai 0=unipolar, 1=bipolar +ao0 0=unipolar, 1=bipolar +ao1 0=unipolar, 1=bipolar +dma1 +dma2 + + +(ai=analog input, ao=analog output.) From this, I decide that +the appropriate options list is + + +0x200,4,,1,1,1 + + +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. + + +/usr/sbin/comedi_config /dev/comedi1 dt2821-f-8di 0x200,4,,1,1,1 + + +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): + + +comedi0: ni_E: 0x0200 can't find board + + +When it does work, I get: + + +comedi0: ni_E: 0x0260 at-mio-16e-10 ( irq = 3 ) + + +Note that it also correctly identified my board. + + +

+Getting information from comedi +

+ + +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: + +

+ + +cat /proc/comedi + + +Right now, on my computer, this command gives: + + +comedi version 0.6.4 +format string + 0: atmio-E at-mio-16e-10 7 + 1: dt282x dt2821-f-8di 4 + + +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 demo/ directory, there is a command called +info, 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 /dev/comedi0.) ('demo/info /dev/comedi0') + + +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 + +... + + +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. + + + + + + + + +Writing programs that use comedi and comedilib +

+ +Your first comedi program +

+ +This example requires a card that has analog or +digital input. Right to the source: + + +#include /* for printf() */ +#include + +int subdev = 0; /* change this to your input subdevice */ +int chan = 0; /* change this to your channel */ +int range = 0; /* more on this later */ +int aref = AREF_GROUND; /* more on this later */ + +int main(int argc,char *argv[]) +{ + comedi_t *it; + lsampl_t data; + + it=comedi_open("/dev/comedi0"); + + comedi_data_read(it,subdev,chan,range,aref,&data); + + printf("%d\n",data); + + return 0; +} + + + +Should be understandable: open the device, get the data, +print it out. This is basically the guts of demo/inp.c, +without error checking or fancy options. +Compile it using + + +cc tut1.c -lcomedi -o tut1 + + +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. + + +

+Converting samples to voltages +

+ +If you selected an analog input subdevice, you probably noticed +that the output of tut1 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 always 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 + +

+ +typedef struct{ + double min; + double max; + unsigned int unit; +}comedi_range; + + +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 + + +volts=comedi_to_phys(it,data,range,maxdata); + + +and the opposite + + +data=comedi_from_phys(it,volts,range,maxdata); + + + +

+Another section +

+ + +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(): + +

+ +file=comedi_open("/dev/comedi0"); + + +where file is of type (comedi_t *). This function +calls open(), like we did explicitly in a previous +section, but also fills the comedi_t structure with +lots of goodies -- information that we will need to use +soon. + +Specifically, we needed to know maxdata for a specific +subdevice/channel. How about: + + +maxdata=comedi_get_maxdata(file,subdevice,channel); + + +Wow. How easy. And the range type? + + +range_type=comedi_get_rangetype(file,subdevice,channel); + + +Cool. Other information you need to know about a channel +can be gotten in a similar way. + + + +Your second comedi program +

+ + +Actually, this is the first comedi program again, just +that we've added what we've learned. + + + +#include /* for printf() */ +#include /* also included by comedilib.h */ +#include /* 'cuz we're using comedilib */ + +int subdev = 0; /* change this to your input subdevice */ +int chan = 0; /* change this to your channel */ +int range = 0; /* more on this later */ +int aref = 0; /* more on this later */ + +int main(int argc,char *argv[]) +{ + comedi_t *cf; + int chan=0; + lsampl_t data; + int maxdata,rangetype; + double volts; + + cf=comedi_open("/dev/comedi0"); + + maxdata=comedi_get_maxdata(cf,subdev,chan); + + rangetype=comedi_get_rangetype(cf,subdev,chan); + + comedi_data_read(cf->fd,subdev,chan,range,aref,&data); + + volts=comedi_to_phys(data,rangetype,range,maxdata); + + printf("%d %g\n",data,volts); + + return 0; +} + + + + + + + +

+Application-specific functions +

+ +Digital Input/Output +

+ +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 + + +Slowly-varying inputs +

+ + +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: + +

+ + +you are ultimately limited by "spurious free dynamic range" + + +you need to have _some_ noise on the input channel, +otherwise you will be averaging the same number N times. + + +the more noise you have, the greater your SFDR, but it +takes many more samples to compensate for the increased +noise + + +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. + + + +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. + + +

+Commands +

+ + +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 structure is +used to control acquisition and query the capabilities of a device +(see also , +, and +). + +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 structure. The source types are: + + +TRIG_NONE: don't ever cause an event +TRIG_NOW: cause event to occur immediately +TRIG_FOLLOW: see notes below +TRIG_TIME: cause event to occur at a particular time +TRIG_TIMER: cause event to occur repeatedly at a specific rate +TRIG_COUNT: cause event when count reaches specific value +TRIG_EXT: external signal causes event +TRIG_INT: internal signal causes event +TRIG_OTHER: driver-specific meaning + + +Not all triggers are applicable to all events. Supported triggers +for specific events depend significantly on your particular +device. The +function is useful for determining what triggers a subdevice supports. + +For every trigger, there is a corresponding +argument (the +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 +structure is the index of the subdevice the command is intended for. The + +function can be useful in discovering the index of your desired subdevice. + +The +structure should point to an array whose number of elements is specificed by macro. + +The structure is +TRIG_BOGUS: do the motions?? +TRIG_DITHER: enable dithering?? +TRIG_DEGLITCH: enable deglitching?? +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. +TRIG_CONFIG: perform configuration, not triggering. This is a legacy of the +deprecated comedi_trig_struct, and has no function at present. +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. +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. + +There are also a few flags that indicate how timing arguments should be rounded +if the hardware cannot achieve the exact timing requested. + +TRIG_ROUND_NEAREST: round to nearest supported timing period, the default. +TRIG_ROUND_DOWN: round period down. +TRIG_ROUND_UP: round period up. +TRIG_ROUND_UP_NEXT: this one doesn't do anything, and I don't know what it was intended +to do?? + + +

+ +The typical sequence for executing a command is to first send +the command through + +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 +. For input/output commands, data +is read from or written to the device file /dev/comedi[0..3] you are using. +