2 * Example of using commands - asynchronous input
5 * Copyright (c) 1999,2000,2001 David A. Schleef <ds@schleef.org>
7 * This file may be freely modified, distributed, and combined with
8 * other software, as long as proper attribution is given in the
13 * An example for directly using Comedi commands. Comedi commands
14 * are used for asynchronous acquisition, with the timing controlled
15 * by on-board timers or external events.
19 #include <comedilib.h>
32 unsigned int chanlist[N_CHANS];
35 int prepare_cmd_lib(comedi_t *dev,int subdevice,comedi_cmd *cmd);
36 int prepare_cmd(comedi_t *dev,int subdevice,comedi_cmd *cmd);
38 void do_cmd(comedi_t *dev,comedi_cmd *cmd);
40 char *cmdtest_messages[]={
49 int main(int argc, char *argv[])
56 struct timeval start,end;
58 parse_options(argc,argv);
60 /* The following global variables used in this demo are
61 * defined in common.c, and can be modified by command line
62 * options. When modifying this demo, you may want to
63 * change them here. */
64 //filename = "/dev/comedi0";
74 dev = comedi_open(filename);
76 comedi_perror(filename);
80 /* Set up channel list */
81 for(i=0;i<n_chan;i++){
82 chanlist[i]=CR_PACK(channel+i,range,aref);
85 /* prepare_cmd_lib() uses a Comedilib routine to find a
86 * good command for the device. prepare_cmd() explicitly
87 * creates a command, which may not work for your device. */
88 //prepare_cmd_lib(dev,subdevice,cmd);
89 prepare_cmd(dev,subdevice,cmd);
91 fprintf(stderr,"command before testing:\n");
94 /* comedi_command_test() tests a command to see if the
95 * trigger sources and arguments are valid for the subdevice.
96 * If a trigger source is invalid, it will be logically ANDed
97 * with valid values (trigger sources are actually bitmasks),
98 * which may or may not result in a valid trigger source.
99 * If an argument is invalid, it will be adjusted to the
100 * nearest valid value. In this way, for many commands, you
101 * can test it multiple times until it passes. Typically,
102 * if you can't get a valid command in two tests, the original
103 * command wasn't specified very well. */
104 ret = comedi_command_test(dev,cmd);
106 comedi_perror("comedi_command_test");
108 fprintf(stderr,"Ummm... this subdevice doesn't support commands\n");
112 fprintf(stderr,"first test returned %d (%s)\n",ret,
113 cmdtest_messages[ret]);
114 dump_cmd(stderr,cmd);
116 ret = comedi_command_test(dev,cmd);
118 comedi_perror("comedi_command_test");
121 fprintf(stderr,"second test returned %d (%s)\n",ret,
122 cmdtest_messages[ret]);
124 dump_cmd(stderr,cmd);
125 fprintf(stderr,"Error preparing command\n");
129 /* start the command */
130 ret=comedi_command(dev,cmd);
132 comedi_perror("comedi_command");
136 /* this is only for informational purposes */
137 gettimeofday(&start,NULL);
138 fprintf(stderr,"start time: %ld.%06ld\n",start.tv_sec,start.tv_usec);
141 ret=read(comedi_fileno(dev),buf,BUFSZ);
143 /* some error occurred */
147 /* reached stop condition */
152 if(verbose)fprintf(stderr,"read %d %d\n",ret,total);
153 for(i=0;i<ret/2;i++){
154 printf("%d ",((sampl_t *)buf)[i]);
164 /* this is only for informational purposes */
165 gettimeofday(&end,NULL);
166 fprintf(stderr,"end time: %ld.%06ld\n",end.tv_sec,end.tv_usec);
168 end.tv_sec-=start.tv_sec;
169 if(end.tv_usec<start.tv_usec){
171 end.tv_usec+=1000000;
173 end.tv_usec-=start.tv_usec;
174 fprintf(stderr,"time: %ld.%06ld\n",end.tv_sec,end.tv_usec);
180 * This prepares a command in a pretty generic way. We ask the
181 * library to create a stock command that supports periodic
182 * sampling of data, then modify the parts we want. */
183 int prepare_cmd_lib(comedi_t *dev,int subdevice,comedi_cmd *cmd)
187 /* This comedilib function will get us a generic timed
188 * command for a particular board. If it returns -1,
190 ret = comedi_get_cmd_generic_timed(dev,subdevice,cmd,1e9/freq);
193 /* Modify parts of the command */
194 cmd->chanlist = chanlist;
195 cmd->chanlist_len = n_chan;
197 cmd->scan_end_arg = n_chan;
198 if(cmd->stop_src==TRIG_COUNT)cmd->stop_arg = n_scan;
204 * Set up a command by hand. This will not work on some devices.
205 * There is no single command that will work on all devices.
207 int prepare_cmd(comedi_t *dev,int subdevice,comedi_cmd *cmd)
209 memset(cmd,0,sizeof(*cmd));
211 /* the subdevice that the command is sent to */
212 cmd->subdev = subdevice;
217 /* Wake up at the end of every scan */
218 //cmd->flags |= TRIG_WAKE_EOS;
220 /* Use a real-time interrupt, if available */
221 //cmd->flags |= TRIG_RT;
223 /* each event requires a trigger, which is specified
224 by a source and an argument. For example, to specify
225 an external digital line 3 as a source, you would use
226 src=TRIG_EXT and arg=3. */
228 /* The start of acquisition is controlled by start_src.
229 * TRIG_NOW: The start_src event occurs start_arg nanoseconds
230 * after comedi_command() is called. Currently,
231 * only start_arg=0 is supported.
232 * TRIG_FOLLOW: (For an output device.) The start_src event occurs
233 * when data is written to the buffer.
234 * TRIG_EXT: start event occurs when an external trigger
235 * signal occurs, e.g., a rising edge of a digital
236 * line. start_arg chooses the particular digital
238 * TRIG_INT: start event occurs on a Comedi internal signal,
239 * which is typically caused by an INSN_TRIG
242 cmd->start_src = TRIG_NOW;
245 /* The timing of the beginning of each scan is controlled by
247 * TRIG_TIMER: scan_begin events occur periodically.
248 * The time between scan_begin events is
249 * convert_arg nanoseconds.
250 * TRIG_EXT: scan_begin events occur when an external trigger
251 * signal occurs, e.g., a rising edge of a digital
252 * line. scan_begin_arg chooses the particular digital
254 * TRIG_FOLLOW: scan_begin events occur immediately after a scan_end
256 * The scan_begin_arg that we use here may not be supported exactly
257 * by the device, but it will be adjusted to the nearest supported
258 * value by comedi_command_test(). */
259 cmd->scan_begin_src = TRIG_TIMER;
260 cmd->scan_begin_arg = 1e9/freq; /* in ns */
262 /* The timing between each sample in a scan is controlled by convert.
263 * TRIG_TIMER: Conversion events occur periodically.
264 * The time between convert events is
265 * convert_arg nanoseconds.
266 * TRIG_EXT: Conversion events occur when an external trigger
267 * signal occurs, e.g., a rising edge of a digital
268 * line. convert_arg chooses the particular digital
270 * TRIG_NOW: All conversion events in a scan occur simultaneously.
271 * Even though it is invalid, we specify 1 ns here. It will be
272 * adjusted later to a valid value by comedi_command_test() */
273 cmd->convert_src = TRIG_TIMER;
274 cmd->convert_arg = 1; /* in ns */
276 /* The end of each scan is almost always specified using
277 * TRIG_COUNT, with the argument being the same as the
278 * number of channels in the chanlist. You could probably
279 * find a device that allows something else, but it would
281 cmd->scan_end_src = TRIG_COUNT;
282 cmd->scan_end_arg = n_chan; /* number of channels */
284 /* The end of acquisition is controlled by stop_src and
286 * TRIG_COUNT: stop acquisition after stop_arg scans.
287 * TRIG_NONE: continuous acquisition, until stopped using
290 cmd->stop_src = TRIG_COUNT;
291 cmd->stop_arg = n_scan;
293 /* the channel list determined which channels are sampled.
294 In general, chanlist_len is the same as scan_end_arg. Most
295 boards require this. */
296 cmd->chanlist = chanlist;
297 cmd->chanlist_len = n_chan;