Merge branch 'master' of git://comedi.org/git/comedi/comedilib

This commit is contained in:
Ian Abbott 2012-05-03 13:06:46 +01:00
commit 2d82ee25b3
11 changed files with 678 additions and 76 deletions

View file

@ -1,5 +1,5 @@
SUBDIRS = lib comedi_config man testing demo doc swig \
SUBDIRS = lib comedi_config man testing demo comedi_board_info doc swig \
include etc scxi c++
pkgconfigdir = $(libdir)/pkgconfig

View file

@ -0,0 +1,7 @@
bin_PROGRAMS = comedi_board_info
man_MANS = comedi_board_info.1
comedi_board_info_SOURCES = comedi_board_info.c
comedi_board_info_CFLAGS = $(COMEDILIB_CFLAGS)
comedi_board_info_LDADD = $(COMEDILIB_LIBS)

View file

@ -0,0 +1,42 @@
.TH COMEDI_BOARD_INFO "1" "May 2012" "comedi_board_info" "User Commands"
.SH NAME
comedi_board_info \- reports useful information about COMEDI devices
.SH SYNOPSIS
.B comedi_board_info
[\fIOPTIONS\fR] COMEDI_DEVICE
.SH DESCRIPTION
This program reads information about a comedi device and
displays it in a human-readable form. It also
probes the asynchronous acquisition by calling the function
probe_cmd_generic_timed
which provides information about the maximum sampling rate of
the board
and how the card acquires multiple channels (e.g. at once or
one by one).
.TP
\-n NUMBER_OF_CHANNELS
Requests the number of channels for the asynchronous acquisition.
This might influence the maximum sampling rate and the mode how
the comedi device samples the channels.
If the number is higher than the available
channels this will be corrected downwards to the number of available
channels.
.TP
\-F SAMPLING_RATE
Requests a sampling rate for the asynchronous
acquisition. By default this is set to comedi's highest sampling rate
(1GHz) so that the driver is forced to reduce it and will
return the maximum possible sampling rate. This option is only provided
for driver testing and for drivers which do not return the highest
sampling rate.
.TP
\-v
Verbose output.
.TP
\-h
Shows a brief help screen.
.SH "SEE ALSO"
More documentation can be found on
http://www.comedi.org/
.SH AUTHOR
comedi_board_info was written by David Schleef <ds@schleef.org> and Bernd Porr <berndporr@f2s.com>.

View file

@ -0,0 +1,316 @@
/*
This program reads information about a comedi device and
displays the information in a human-readable form.
*/
#include <stdio.h>
#include <comedilib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
static char * const default_filename = "/dev/comedi0";
int verbose = 0;
static const char * const subdevice_types[]={
"unused",
"analog input",
"analog output",
"digital input",
"digital output",
"digital I/O",
"counter",
"timer",
"memory",
"calibration",
"processor",
"serial digital I/O",
"pwm"
};
struct subdev_flag {
const char *sdf_define;
unsigned int bitmask;
const char *description;
};
static struct subdev_flag subdev_flags[] = {
{"SDF_MAXDATA",0x0010,"maxdata depends on channel"},
{"SDF_FLAGS",0x0020,"flags depend on channel"},
{"SDF_RANGETYPE",0x0040,"range type depends on channel"},
{"SDF_MODE0",0x0080,"can do mode 0"},
{"SDF_MODE1",0x0100,"can do mode 1"},
{"SDF_MODE2",0x0200,"can do mode 2"},
{"SDF_MODE3",0x0400,"can do mode 3"},
{"SDF_MODE4",0x0800,"can do mode 4"},
{"SDF_SOFT_CALIBRATED",0x2000,"subdevice uses software calibration"},
{"SDF_CMD_WRITE",0x4000,"can do asynchronous output commands"},
{"SDF_CMD_READ",0x8000,"can do asynchronous input commands"},
{"SDF_READABLE",0x00010000,"subdevice can be read"},
{"SDF_WRITABLE",0x00020000,"subdevice can be written"},
{"SDF_INTERNAL",0x00040000,"subdevice does not have externally visible lines"},
{"SDF_GROUND",0x00100000,"can do aref=ground"},
{"SDF_COMMON",0x00200000,"can do aref=common"},
{"SDF_DIFF",0x00400000,"aref=diff"},
{"SDF_OTHER",0x00800000,"can do aref=other"},
{"SDF_DITHER",0x01000000,"can do dithering"},
{"SDF_DEGLITCH",0x02000000,"can do deglitching"},
{"SDF_MMAP",0x04000000,"can do mmap()"},
{"SDF_RUNNING",0x08000000,"subdevice is acquiring data"},
{"SDF_LSAMPL",0x10000000,"subdevice uses 32-bit samples for commands"},
{"SDF_PACKED",0x20000000,"subdevice can do packed DIO"},
{0,0,0}};
void explain_subdevice_flags(char* padding,unsigned int sf) {
int i = 0;
while (subdev_flags[i].sdf_define) {
if (sf & subdev_flags[i].bitmask)
printf("%s%s:%s\n",
padding,
subdev_flags[i].sdf_define,
subdev_flags[i].description);
i++;
}
}
void unit_to_desc(char *udesc,int unit) {
switch(unit) {
case UNIT_volt: strcpy(udesc," V"); break;
case UNIT_mA: strcpy(udesc," mA"); break;
case UNIT_none: strcpy(udesc,""); break;
default: sprintf(udesc," (unknown unit %d)",
unit);
}
}
char *tobinary(char *s,int bits,int n)
{
int bit=1<<n;
char *t=s;
for(;bit;bit>>=1)
*t++=(bits&bit)?'1':'0';
*t=0;
return s;
}
char *cmd_src(int src,char *buf)
{
buf[0]=0;
if(src&TRIG_NONE)strcat(buf,"none|");
if(src&TRIG_NOW)strcat(buf,"now|");
if(src&TRIG_FOLLOW)strcat(buf, "follow|");
if(src&TRIG_TIME)strcat(buf, "time|");
if(src&TRIG_TIMER)strcat(buf, "timer|");
if(src&TRIG_COUNT)strcat(buf, "count|");
if(src&TRIG_EXT)strcat(buf, "ext|");
if(src&TRIG_INT)strcat(buf, "int|");
#ifdef TRIG_OTHER
if(src&TRIG_OTHER)strcat(buf, "other|");
#endif
if(strlen(buf)==0){
sprintf(buf,"unknown(0x%08x)",src);
}else{
buf[strlen(buf)-1]=0;
}
return buf;
}
void probe_cmd_generic_timed(comedi_t *it,int s,int n_channels,int freq_for_generic_timed)
{
comedi_cmd cmd;
char buf[100];
printf(" command structure filled with probe_cmd_generic_timed for %d channels:\n",
n_channels);
if(comedi_get_cmd_generic_timed(it, s, &cmd, n_channels, 1E9/freq_for_generic_timed)<0){
printf(" not supported\n");
}else{
printf(" start: %s %d\n",
cmd_src(cmd.start_src,buf),cmd.start_arg);
printf(" scan_begin: %s %d\n",
cmd_src(cmd.scan_begin_src,buf),cmd.scan_begin_arg);
if (verbose) {
if ((cmd.scan_begin_src == TRIG_TIMER)&&(cmd.scan_begin_arg)) {
printf(" scan_begin_src = TRIG_TIMER:\n"
" The sampling rate is defined per scan\n"
" meaning all channels are sampled at\n"
" the same time. The maximum sampling rate is f=%d Hz\n",
(int)(1E9/cmd.scan_begin_arg));}
}
printf(" convert: %s %d\n",
cmd_src(cmd.convert_src,buf),cmd.convert_arg);
if (verbose) {
if ((cmd.convert_src == TRIG_TIMER)&&(cmd.convert_arg)) {
printf(" convert_src = TRIG_TIMER\n"
" The sampling rate is defined per channel\n"
" meaning that a multiplexer is being switched from\n"
" channel to channel at a maximum rate of %d Hz.\n"
" The overall sampling rate needs to be divided\n"
" by the number of channels and results in f=%d Hz.\n",
(int)(1E9/cmd.convert_arg),
(int)(1E9/cmd.convert_arg/n_channels));
}
}
printf(" scan_end: %s %d\n",
cmd_src(cmd.scan_end_src,buf),cmd.scan_end_arg);
printf(" stop: %s %d\n",
cmd_src(cmd.stop_src,buf),cmd.stop_arg);
}
}
void get_command_stuff(comedi_t *it,int s,int n_chans_for_generic_timed,int freq_for_generic_timed)
{
comedi_cmd cmd;
char buf[100];
if(comedi_get_cmd_src_mask(it,s,&cmd)<0){
printf(" not supported\n");
}else{
printf(" start: %s\n",cmd_src(cmd.start_src,buf));
if (cmd.start_src == TRIG_EXT)
printf(" cmd.start_src allows external trigger (TRIG_EXT),"
" for example from on input pin at the device.\n");
printf(" scan_begin: %s\n",cmd_src(cmd.scan_begin_src,buf));
printf(" convert: %s\n",cmd_src(cmd.convert_src,buf));
printf(" scan_end: %s\n",cmd_src(cmd.scan_end_src,buf));
printf(" stop: %s\n",cmd_src(cmd.stop_src,buf));
probe_cmd_generic_timed(it,s,n_chans_for_generic_timed,freq_for_generic_timed);
}
}
int main(int argc,char *argv[])
{
int i,j;
int n_subdevices,type;
const char *type_str;
int chan,n_chans;
int n_ranges;
int subdev_flags;
comedi_range *rng;
comedi_t *it;
char *filename = default_filename;
char c;
char strtmp[16];
int n_chans_for_generic_timed = 1;
int freq_for_generic_timed = 1E9;
while (-1 != (c = getopt(argc, argv, "hvn:F:"))) {
switch (c) {
case 'n':
n_chans_for_generic_timed = strtoul(optarg, NULL, 0);
break;
case 'F':
freq_for_generic_timed = strtoul(optarg, NULL, 0);
break;
case 'v':
verbose++;
break;
case 'h':
default:
fprintf(stderr,
"usage: comedi_board_info [OPTIONS] COMEDI_DEVICE\n"
" -n number of channels for async command (default 1)\n"
" -F probing sampling rate for async command (default 1Ghz)\n"
" -v verbose output\n"
" -h this help screen\n");
exit(1);
}
}
if(optind < argc) {
filename = argv[optind];
}
it = comedi_open(filename);
if(!it){
comedi_perror(filename);
exit(1);
}
printf("overall info:\n");
printf(" version code: 0x%06x\n", comedi_get_version_code(it));
printf(" driver name: %s\n", comedi_get_driver_name(it));
printf(" board name: %s\n", comedi_get_board_name(it));
printf(" number of subdevices: %d\n", n_subdevices = comedi_get_n_subdevices(it));
for(i = 0; i < n_subdevices; i++){
printf("subdevice %d:\n",i);
type = comedi_get_subdevice_type(it, i);
if(type < (int)(sizeof(subdevice_types) / sizeof(subdevice_types[0]))){
type_str = subdevice_types[type];
}else{
type_str = "UNKNOWN";
}
printf(" type: %d (%s)\n",type,type_str);
if(type==COMEDI_SUBD_UNUSED)
continue;
subdev_flags = comedi_get_subdevice_flags(it, i);
printf(" flags: 0x%08x\n",subdev_flags);
if (verbose) explain_subdevice_flags(" ",subdev_flags);
n_chans=comedi_get_n_channels(it,i);
printf(" number of channels: %d\n",n_chans);
if(!comedi_maxdata_is_chan_specific(it,i)){
printf(" max data value: %lu\n", (unsigned long)comedi_get_maxdata(it,i,0));
}else{
printf(" max data value: (channel specific)\n");
for(chan=0;chan<n_chans;chan++){
printf(" chan%d: %lu\n",chan,
(unsigned long)comedi_get_maxdata(it,i,chan));
}
}
printf(" ranges:\n");
if(!comedi_range_is_chan_specific(it,i)){
n_ranges=comedi_get_n_ranges(it,i,0);
printf(" all chans:");
for(j=0;j<n_ranges;j++){
rng=comedi_get_range(it,i,0,j);
unit_to_desc(strtmp,rng->unit);
printf(" [%g%s,%g%s]",rng->min,strtmp,rng->max,strtmp);
}
printf("\n");
}else{
for(chan=0;chan<n_chans;chan++){
n_ranges=comedi_get_n_ranges(it,i,chan);
printf(" chan%d:",chan);
for(j=0;j<n_ranges;j++){
rng=comedi_get_range(it,i,chan,j);
unit_to_desc(strtmp,rng->unit);
printf(" [%g%s,%g%s]",rng->min,strtmp,rng->max,strtmp);
}
printf("\n");
}
}
printf(" command:\n");
if (n_chans_for_generic_timed>n_chans)
n_chans_for_generic_timed = n_chans;
if (n_chans_for_generic_timed<1)
n_chans_for_generic_timed = 1;
if (freq_for_generic_timed > 1E9)
freq_for_generic_timed = 1E9;
if (freq_for_generic_timed < 1)
freq_for_generic_timed = 1;
get_command_stuff(it,i,n_chans_for_generic_timed,freq_for_generic_timed);
}
return 0;
}

View file

@ -275,6 +275,7 @@ fi
AC_CONFIG_FILES(
Makefile
comedi_config/Makefile
comedi_board_info/Makefile
c++/Makefile
c++/include/Makefile
etc/Makefile

View file

@ -4,7 +4,7 @@ noinst_PROGRAMS = \
choose_routing cmd do_waveform dio eeprom_dump gpct_buffered_counting \
gpct_encoder gpct_pulse_generator \
gpct_simple_counting inp inpn insn ledclock \
mmap outp poll receiver select \
mmap outp poll receiver select pwm \
sender sigio sv tut1 tut2 tut3
noinst_HEADERS = examples.h
@ -101,6 +101,11 @@ poll_SOURCES = poll.c common.c
poll_CFLAGS = $(COMEDILIB_CFLAGS)
poll_LDADD = $(COMEDILIB_LIBS)
pwm_SOURCES = pwm.c common.c
pwm_CFLAGS = $(COMEDILIB_CFLAGS)
pwm_LDADD = $(COMEDILIB_LIBS)
receiver_SOURCES = receiver.c common.c
receiver_CFLAGS = $(COMEDILIB_CFLAGS)
receiver_LDADD = $(COMEDILIB_LIBS)

View file

@ -136,6 +136,11 @@ outp <value>:
Write one <value> to one channel of one subdevice. Requires
a digital or analog output subdevice.
pwm:
controls PWM devices. Use the option -N 0 and -N 1 to switch
it on / off respectively. Call with no arguments to get
a help screen.
receiver:
This demo is meant to be used in conjunction with the sender
demo. Receiver requires a digital input subdevice, and sender

View file

@ -106,12 +106,13 @@ int main(int argc, char *argv[])
init_parsed_options(&options);
options.subdevice = -1;
options.n_chan = 0; /* default waveform */
options.n_chan = -1; /* waveform */
parse_options(&options, argc, argv);
/* Use n_chan to select waveform (cheat!) */
fn = options.n_chan;
if(fn < 0 || fn >= NUMFUNCS){
fprintf(stderr,"Use the option '-n' to select another waveform.\n");
fn = 0;
}
@ -158,7 +159,8 @@ int main(int argc, char *argv[])
dds_init(waveform_frequency, options.freq, fn);
dump_cmd(stdout,&cmd);
if (options.verbose)
dump_cmd(stdout,&cmd);
err = comedi_command_test(dev, &cmd);
if (err < 0) {
@ -189,7 +191,8 @@ int main(int argc, char *argv[])
"See the --write-buffer option of comedi_config\n", n);
exit(1);
}
printf("m=%d\n",m);
if (options.verbose)
printf("m=%d\n",m);
ret = comedi_internal_trigger(dev, options.subdevice, 0);
if(ret < 0){
@ -206,7 +209,8 @@ int main(int argc, char *argv[])
perror("write");
exit(0);
}
printf("m=%d\n",m);
if (options.verbose)
printf("m=%d\n",m);
n-=m;
}
total+=BUF_LEN;

156
demo/pwm.c Normal file
View file

@ -0,0 +1,156 @@
#include <stdio.h>
#include <comedilib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
/*
* A little pwm demo
* Part of Comedilib
*
* Copyright (c) 2012 Bernd Porr <berndporr@f2s.com>
*
* This file may be freely modified, distributed, and combined with
* other software, as long as proper attribution is given in the
* source code.
*/
#include <errno.h>
#include <getopt.h>
#include <ctype.h>
#include <string.h>
#include "examples.h"
// the option -n is used to switch on/off the pwm
int main(int argc, char *argv[])
{
int ret,i;
comedi_insn insn;
lsampl_t d[5];
comedi_t *device;
int freq;
struct parsed_options options;
init_parsed_options(&options);
options.freq = -1;
// we hijack this option to switch it on or off
options.n_scan = -1;
options.value = -1;
parse_options(&options, argc, argv);
if ((options.value==-1)&&(options.n_scan==-1)&&(options.freq==-1)) {
fprintf(stderr,
"Usage: %s OPTIONS duty_cycle\n"
"options: \n"
" -N 0 switches PWM off\n"
" -N 1 switches PWM on\n"
" -N 2 enquires the max value for the duty cycle\n"
" -F FREQ sets the PWM frequency\n",
argv[0]);
}
device = comedi_open(options.filename);
if(!device){
comedi_perror(options.filename);
exit(-1);
}
options.subdevice = comedi_find_subdevice_by_type(device,COMEDI_SUBD_PWM,0);
if (options.verbose)
printf("PWM subdevice autodetection gave subdevice number %d\n",
options.subdevice);
if(options.n_scan==2) {
printf("%d\n",comedi_get_maxdata(device,options.subdevice,0));
close(device);
exit(0);
}
insn.insn=INSN_CONFIG;
insn.data=d;
insn.subdev=options.subdevice;
insn.chanspec=CR_PACK(0,0,0);
if(options.n_scan==1) {
d[0] = INSN_CONFIG_ARM;
d[1] = 0;
insn.n=2;
ret=comedi_do_insn(device,&insn);
if(ret < 0){
fprintf(stderr,"Could not switch on:%d\n",ret);
comedi_perror(options.filename);
exit(-1);
}
}
if(options.n_scan==0) {
d[0] = INSN_CONFIG_DISARM;
d[1] = 0;
insn.n=1;
ret=comedi_do_insn(device,&insn);
if(ret < 0){
fprintf(stderr,"Could not switch off:%d\n",ret);
comedi_perror(options.filename);
exit(-1);
}
}
if(options.freq>0) {
freq = options.freq;
d[0] = INSN_CONFIG_PWM_SET_PERIOD;
d[1] = 1E9/freq;
insn.n=2;
ret=comedi_do_insn(device,&insn);
if(ret < 0){
fprintf(stderr,"Could set frequ:%d\n",ret);
comedi_perror(options.filename);
exit(-1);
}
}
d[0] = INSN_CONFIG_GET_PWM_STATUS;
insn.n=2;
ret=comedi_do_insn(device,&insn);
if(ret < 0){
fprintf(stderr,"Could not get status:%d insn=%d\n",
ret,
d[0]);
comedi_perror(options.filename);
exit(-1);
}
if (options.verbose) {
if (d[1])
fprintf(stderr,
"PWM is on.\n");
else
fprintf(stderr,
"PWM is off.\n");
}
d[0] = INSN_CONFIG_PWM_GET_PERIOD;
insn.n=2;
ret=comedi_do_insn(device,&insn);
if(ret < 0){
fprintf(stderr,"Could get frequ:%d\n",ret);
comedi_perror(options.filename);
exit(-1);
}
freq = 1E9 / d[1];
if (options.verbose)
fprintf(stderr,"PWM frequency is %d\n", freq);
if (options.value>=0)
if(comedi_data_write(device,
options.subdevice,
options.channel,
0,
0,
options.value)<0)
{
fprintf(stderr,"error setting the pwm duty cycle on ");
comedi_perror(options.filename);
exit(1);
}
return 0;
}

View file

@ -164,86 +164,132 @@ comedi0: ni_atmio: 0x0260 at-mio-16e-10 ( irq = 3 )
<para>
So now that you have &comedi; talking to the hardware, try to
talk to &comedi;. Here's some information from comedi's proc
file, which indicates what drivers are loaded and which
boards are configured:
talk to &comedi;.
Call the command <command>comedi_board_info</command>, which provides information
about each subdevice on the board.
Here's part of the output of the <literal>USB-DUX sigma</literal>
board (which is on <filename>/dev/comedi0</filename>), as a result of
the command <command>comedi_board_info -v</command>.
</para>
<screen>
overall info:
version code: 0x00074c
driver name: usbduxsigma
board name: usbduxsigma
number of subdevices: 4
subdevice 0:
type: 1 (analog input)
flags: 0x10119000
SDF_CMD_READ:can do asynchronous input commands
SDF_READABLE:subdevice can be read
SDF_GROUND:can do aref=ground
SDF_LSAMPL:subdevice uses 32-bit samples for commands
number of channels: 16
max data value: 16777215
ranges:
all chans: [-1.325 V,1.325 V]
command:
start: now|int
scan_begin: timer
convert: now
scan_end: count
stop: none|count
command structure filled with probe_cmd_generic_timed for 16 channels:
start: now 0
scan_begin: timer 1000000
scan_begin_src = TRIG_TIMER:
The sampling rate is defined per scan
meaning all channels are sampled at
the same time. The maximum sampling rate is f=1000 Hz
convert: now 0
scan_end: count 16
stop: count 2
subdevice 1:
type: 2 (analog output)
flags: 0x00125000
SDF_CMD_WRITE:can do asynchronous output commands
SDF_WRITABLE:subdevice can be written
SDF_GROUND:can do aref=ground
number of channels: 4
max data value: 255
ranges:
all chans: [0 V,2.5 V]
command:
start: now|int
scan_begin: timer
convert: now
scan_end: count
stop: none|count
command structure filled with probe_cmd_generic_timed for 4 channels:
start: now 0
scan_begin: timer 1000000
scan_begin_src = TRIG_TIMER:
The sampling rate is defined per scan
meaning all channels are sampled at
the same time. The maximum sampling rate is f=1000 Hz
convert: now 0
scan_end: count 4
stop: count 2
subdevice 2:
type: 5 (digital I/O)
flags: 0x00030000
SDF_READABLE:subdevice can be read
SDF_WRITABLE:subdevice can be written
number of channels: 24
max data value: 1
ranges:
all chans: [0 V,5 V]
command:
not supported
subdevice 3:
type: 12 (pwm)
flags: 0x00020100
SDF_MODE1:can do mode 1
SDF_WRITABLE:subdevice can be written
number of channels: 8
max data value: 512
ranges:
all chans: [0,1]
command:
not supported
</screen>
<para>
This board has four subdevices. Devices are separated into
subdevices that each have a distinct purpose; e.g., analog
input, analog output, digital input/output.
</para>
<para>
Here's the information from comedi's proc
file, which indicates what drivers are loaded and which
boards are configured:
</para>
<screen>
cat /proc/comedi
</screen>
<para>
For example, on a computer with an NI pxi-6281 configured on
<filename>/dev/comedi0</filename> and
a pxi-6602 configured on <filename>/dev/comedi1</filename> you might
see something like:
</para>
<screen>
comedi version 0.7.74
comedi version 0.7.76
format string: "%2d: %-20s %-20s %4d",i,driver_name,board_name,n_subdevices
0: ni_pcimio pxi-6281 14
1: ni_660x PXI-6602 10
ni_pcimio:
ni_pcimio
8255:
8255
ni_660x:
ni_660x
0: usbduxsigma usbduxsigma 4
usbduxfast:
usbduxfast
usbduxsigma:
usbduxsigma
</screen>
<para>
This documentation feature is not well-developed yet. Basically, it
currently returns the driver name, the device name, and the number of
subdevices. Following those lines are a list of the comedi kernel
driver modules currently loaded, each followed by a list of the board
names it recognizes (names that can be used with comedi_config).
</para>
<para>
This documentation feature currently returns the driver name, the device name, and the number of
subdevices. Following those lines are a list of the comedi kernel
driver modules currently loaded, each followed by a list of the board
names it recognizes (names that can be used with comedi_config).
</para>
<para>
In the <filename role="directory">demo/</filename> subdirectory of
Comedilib, there is a
command called <command>board_info</command>, which provides information
about each subdevice on the board. Its output can be rather long,
if the board has several subdevices.
Here's part of the output of the <literal>National Instruments</literal>
board (which is on <filename>/dev/comedi0</filename>), as a result of
the command <command>demo/board_info /dev/comedi0</command> (run from the
top-level directory of comedilib):
</para>
<screen>
overall info:
version code: 0x00074a
driver name: ni_atmio
board name: at-mio-16e-10
number of subdevices: 7
subdevice 0:
type: 1 (analog input)
number of channels: 16
max data value: 4095
...
</screen>
<para>
The overall info gives information about the device; basically
the same information as <filename>/proc/comedi</filename>.
</para>
<para>
This board has seven subdevices. Devices are separated into
subdevices that each have a distinct purpose; e.g., analog
input, analog output, digital input/output. This board also
has an EEPROM and calibration DACs that are also subdevices.
</para>
<para>
&comedi; has more information about the device than what is displayed
above, but <command>demo/board_info</command> doesn't currently display
this.
</para>
</section>
</section>
</section>

View file

@ -132,6 +132,26 @@
This technique is used in programs such
as <command>ktimetrace</command> or <command>comedirecord</command>.
</para>
<para>
There are two different ways how a sequence of channels is
measured during asynchronous acquisition (see also the Figure in
the introduction):
<itemizedlist>
<listitem>
The channels are measured with the help
of a multiplexer which switches to the next channel after each measurement.
This means that the sampling rate is divided by the number
of channels.
</listitem>
<listitem>
The channels are all measured at the same time, for example
when every channel has its own converter. In this case the
sampling rate need not to be divided by the number of channels.
</listitem>
</itemizedlist>
How your &comedi; device handles the asynchronous acquisition can be found out
with the command <command>comedi_board_info -v</command>.
</para>
<para>
The program <command>tut3.c</command> demonstrates the
asynchronous acquisition. The general strategy is always