/* * selet.c - Example of using select() with Comedi * Part of Comedilib * * Copyright (c) 1999,2000 David A. Schleef <ds@schleef.org> * * This file may be freely modified, distributed, and combined with * other software, as long as proper attribution is given in the * source code. */ /* * An example for using select() with asynchronous input. This * example requires an asynchronous input subdevice that can * handle TRIG_TIMER as a scan_begin_src. */ #include <stdio.h> #include <comedilib.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <getopt.h> #include <ctype.h> #include <string.h> #include <sys/time.h> #include "examples.h" #define N_SCANS 10 #define N_CHANS 16 double freq = 1000; #define BUFSZ 1000 sampl_t buf[BUFSZ]; int n_chans = 1; int n_scans = 10; unsigned int chanlist[4]; comedi_t *device; void prepare_cmd(comedi_t *dev,comedi_cmd *cmd); void do_cmd(comedi_t *dev,comedi_cmd *cmd); #define sec_to_nsec(x) ((x)*1000000000) #define sec_to_usec(x) ((x)*1000000) #define sec_to_msec(x) ((x)*1000) #define msec_to_nsec(x) ((x)*1000000) #define msec_to_usec(x) ((x)*1000) #define usec_to_nsec(x) ((x)*1000) int main(int argc, char *argv[]) { comedi_cmd cmd; int i; parse_options(argc,argv); device = comedi_open(filename); if(!device){ perror(filename); exit(1); } fcntl(comedi_fileno(device),F_SETFL,O_NONBLOCK); for(i=0;i<n_chans;i++){ chanlist[i]=CR_PACK(channel+i,range,aref); } prepare_cmd(device,&cmd); do_cmd(device,&cmd); return 0; } void do_cmd(comedi_t *dev,comedi_cmd *cmd) { int total=0; int ret; int go; fd_set rdset; struct timeval timeout; ret=comedi_command_test(dev,cmd); printf("test ret=%d\n",ret); if(ret<0){ printf("errno=%d\n",errno); comedi_perror("comedi_command_test"); return; } dump_cmd(cmd); ret=comedi_command_test(dev,cmd); printf("test ret=%d\n",ret); if(ret<0){ printf("errno=%d\n",errno); comedi_perror("comedi_command_test"); return; } dump_cmd(cmd); ret=comedi_command(dev,cmd); printf("ret=%d\n",ret); if(ret<0){ printf("errno=%d\n",errno); comedi_perror("comedi_command"); return; } go=1; while(go){ FD_ZERO(&rdset); FD_SET(comedi_fileno(device),&rdset); timeout.tv_sec = 0; timeout.tv_usec = 50000; ret = select(comedi_fileno(dev)+1,&rdset,NULL,NULL,&timeout); printf("select returned %d\n",ret); if(ret<0){ perror("select"); }else if(ret==0){ /* hit timeout */ printf("timeout\n"); }else if(FD_ISSET(comedi_fileno(device),&rdset)){ /* comedi file descriptor became ready */ printf("comedi file descriptor ready\n"); ret=read(comedi_fileno(dev),buf,sizeof(buf)); printf("read returned %d\n",ret); if(ret<0){ if(errno==EAGAIN){ go = 0; perror("read"); } }else if(ret==0){ go = 0; }else{ int i; total+=ret; //printf("read %d %d\n",ret,total); for(i=0;i<ret/sizeof(sampl_t);i++){ printf("%d\n",buf[i]); } } }else{ /* unknown file descriptor became ready */ printf("unknown file descriptor ready\n"); } } } /* * This part of the demo measures channels 1, 2, 3, 4 at a rate of * 10 khz, with the inter-sample time at 10 us (100 khz). The number * of scans measured is 10. This is analogous to the old mode2 * acquisition. */ void prepare_cmd(comedi_t *dev,comedi_cmd *cmd) { memset(cmd,0,sizeof(*cmd)); /* the subdevice that the command is sent to */ cmd->subdev = subdevice; /* flags */ cmd->flags = TRIG_WAKE_EOS; //cmd.flags = 0; /* each event requires a trigger, which is specified by a source and an argument. For example, to specify an external digital line 3 as a source, you would use src=TRIG_EXT and arg=3. */ /* In this case, we specify using TRIG_NOW to start * acquisition immediately when the command is issued. * The argument of TRIG_NOW is "number of nsec after * NOW", but no driver supports it yet. Also, no driver * currently supports using a start_src other than * TRIG_NOW. */ cmd->start_src = TRIG_NOW; cmd->start_arg = 0; /* The timing of the beginning of each scan is controlled * by scan_begin. TRIG_TIMER specifies that scan_start * events occur periodically at a rate of scan_begin_arg * nanoseconds between scans. */ cmd->scan_begin_src = TRIG_TIMER; cmd->scan_begin_arg = msec_to_nsec(100); /* The timing between each sample in a scan is controlled * by convert. Like above, TRIG_TIMER specifies that * convert events occur periodically at a rate of convert_arg * nanoseconds between scans. */ cmd->convert_src = TRIG_TIMER; cmd->convert_arg = msec_to_nsec(1); /* The end of each scan is almost always specified using * TRIG_COUNT, with the argument being the same as the * number of channels in the chanlist. You could probably * find a device that allows something else, but it would * be strange. */ cmd->scan_end_src = TRIG_COUNT; cmd->scan_end_arg = n_chans; /* number of channels */ /* The end of acquisition is controlled by stop_src and * stop_arg. The src will typically be TRIG_COUNT or * TRIG_NONE. Specifying TRIG_COUNT will stop acquisition * after stop_arg number of scans, or TRIG_NONE will * cause acquisition to continue until stopped using * comedi_cancel(). */ cmd->stop_src = TRIG_COUNT; cmd->stop_arg = n_scans; /* the channel list determined which channels are sampled. In general, chanlist_len is the same as scan_end_arg. Most boards require this. */ cmd->chanlist = chanlist; cmd->chanlist_len = n_chans; }