Merge branch 'master' of git://comedi.org/git/comedi/comedilib
This commit is contained in:
commit
2d82ee25b3
11 changed files with 678 additions and 76 deletions
|
@ -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
|
||||
|
|
7
comedi_board_info/Makefile.am
Normal file
7
comedi_board_info/Makefile.am
Normal 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)
|
42
comedi_board_info/comedi_board_info.1
Normal file
42
comedi_board_info/comedi_board_info.1
Normal 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>.
|
316
comedi_board_info/comedi_board_info.c
Normal file
316
comedi_board_info/comedi_board_info.c
Normal 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;
|
||||
}
|
||||
|
|
@ -275,6 +275,7 @@ fi
|
|||
AC_CONFIG_FILES(
|
||||
Makefile
|
||||
comedi_config/Makefile
|
||||
comedi_board_info/Makefile
|
||||
c++/Makefile
|
||||
c++/include/Makefile
|
||||
etc/Makefile
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
156
demo/pwm.c
Normal 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;
|
||||
}
|
186
doc/install.xml
186
doc/install.xml
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue