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 static unsigned int chanlist[N_CHANS];
33 static comedi_range * range_info[N_CHANS];
34 static lsampl_t maxdata[N_CHANS];
37 int prepare_cmd_lib(comedi_t *dev, int subdevice, int n_scan, int n_chan, unsigned period_nanosec, comedi_cmd *cmd);
39 void do_cmd(comedi_t *dev,comedi_cmd *cmd);
41 void print_datum(lsampl_t raw, int channel_index, short physical);
43 char *cmdtest_messages[]={
52 int main(int argc, char *argv[])
59 struct timeval start,end;
62 struct parsed_options options;
64 init_parsed_options(&options);
65 parse_options(&options, argc, argv);
67 /* The following variables used in this demo
68 * can be modified by command line
69 * options. When modifying this demo, you may want to
70 * change them here. */
71 //options.filename = "/dev/comedi0";
72 //options.subdevice = 0;
73 //options.channel = 0;
75 //options.aref = AREF_GROUND;
77 //options.n_scan = 1000;
78 //options.freq = 1000.0;
81 dev = comedi_open(options.filename);
83 comedi_perror(options.filename);
87 // Print numbers for clipped inputs
88 comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER);
90 /* Set up channel list */
91 for(i = 0; i < options.n_chan; i++){
92 chanlist[i] = CR_PACK(options.channel + i, options.range, options.aref);
93 range_info[i] = comedi_get_range(dev, options.subdevice, options.channel, options.range);
94 maxdata[i] = comedi_get_maxdata(dev, options.subdevice, options.channel);
97 /* prepare_cmd_lib() uses a Comedilib routine to find a
98 * good command for the device. prepare_cmd() explicitly
99 * creates a command, which may not work for your device. */
100 prepare_cmd_lib(dev, options.subdevice, options.n_scan, options.n_chan, 1e9 / options.freq, cmd);
101 //prepare_cmd(dev, options.subdevice, options.n_scan, options.n_chan, 1e9 / options.freq, cmd);
103 fprintf(stderr, "command before testing:\n");
104 dump_cmd(stderr, cmd);
106 /* comedi_command_test() tests a command to see if the
107 * trigger sources and arguments are valid for the subdevice.
108 * If a trigger source is invalid, it will be logically ANDed
109 * with valid values (trigger sources are actually bitmasks),
110 * which may or may not result in a valid trigger source.
111 * If an argument is invalid, it will be adjusted to the
112 * nearest valid value. In this way, for many commands, you
113 * can test it multiple times until it passes. Typically,
114 * if you can't get a valid command in two tests, the original
115 * command wasn't specified very well. */
116 ret = comedi_command_test(dev, cmd);
118 comedi_perror("comedi_command_test");
120 fprintf(stderr,"Ummm... this subdevice doesn't support commands\n");
124 fprintf(stderr,"first test returned %d (%s)\n", ret,
125 cmdtest_messages[ret]);
126 dump_cmd(stderr, cmd);
128 ret = comedi_command_test(dev, cmd);
130 comedi_perror("comedi_command_test");
133 fprintf(stderr,"second test returned %d (%s)\n", ret,
134 cmdtest_messages[ret]);
136 dump_cmd(stderr, cmd);
137 fprintf(stderr, "Error preparing command\n");
141 /* this is only for informational purposes */
142 gettimeofday(&start, NULL);
143 fprintf(stderr,"start time: %ld.%06ld\n", start.tv_sec, start.tv_usec);
145 /* start the command */
146 ret = comedi_command(dev, cmd);
148 comedi_perror("comedi_command");
151 subdev_flags = comedi_get_subdevice_flags(dev, options.subdevice);
153 ret = read(comedi_fileno(dev),buf,BUFSZ);
155 /* some error occurred */
159 /* reached stop condition */
163 int bytes_per_sample;
165 if(options.verbose)fprintf(stderr, "read %d %d\n", ret, total);
166 if(subdev_flags & SDF_LSAMPL)
167 bytes_per_sample = sizeof(lsampl_t);
169 bytes_per_sample = sizeof(sampl_t);
170 for(i = 0; i < ret / bytes_per_sample; i++){
171 if(subdev_flags & SDF_LSAMPL) {
172 raw = ((lsampl_t *)buf)[i];
174 raw = ((sampl_t *)buf)[i];
176 print_datum(raw, col, options.physical);
178 if(col == options.n_chan){
186 /* this is only for informational purposes */
187 gettimeofday(&end,NULL);
188 fprintf(stderr,"end time: %ld.%06ld\n", end.tv_sec, end.tv_usec);
190 end.tv_sec -= start.tv_sec;
191 if(end.tv_usec < start.tv_usec){
193 end.tv_usec += 1000000;
195 end.tv_usec -= start.tv_usec;
196 fprintf(stderr,"time: %ld.%06ld\n", end.tv_sec, end.tv_usec);
202 * This prepares a command in a pretty generic way. We ask the
203 * library to create a stock command that supports periodic
204 * sampling of data, then modify the parts we want. */
205 int prepare_cmd_lib(comedi_t *dev, int subdevice, int n_scan, int n_chan, unsigned scan_period_nanosec, comedi_cmd *cmd)
209 memset(cmd,0,sizeof(*cmd));
211 /* This comedilib function will get us a generic timed
212 * command for a particular board. If it returns -1,
214 ret = comedi_get_cmd_generic_timed(dev, subdevice, cmd, n_chan, scan_period_nanosec);
216 printf("comedi_get_cmd_generic_timed failed\n");
220 /* Modify parts of the command */
221 cmd->chanlist = chanlist;
222 cmd->chanlist_len = n_chan;
223 if(cmd->stop_src == TRIG_COUNT) cmd->stop_arg = n_scan;
229 * Set up a command by hand. This will not work on some devices.
230 * There is no single command that will work on all devices.
232 int prepare_cmd(comedi_t *dev, int subdevice, int n_scan, int n_chan, unsigned period_nanosec, comedi_cmd *cmd)
234 memset(cmd,0,sizeof(*cmd));
236 /* the subdevice that the command is sent to */
237 cmd->subdev = subdevice;
242 /* Wake up at the end of every scan */
243 //cmd->flags |= TRIG_WAKE_EOS;
245 /* Use a real-time interrupt, if available */
246 //cmd->flags |= TRIG_RT;
248 /* each event requires a trigger, which is specified
249 by a source and an argument. For example, to specify
250 an external digital line 3 as a source, you would use
251 src=TRIG_EXT and arg=3. */
253 /* The start of acquisition is controlled by start_src.
254 * TRIG_NOW: The start_src event occurs start_arg nanoseconds
255 * after comedi_command() is called. Currently,
256 * only start_arg=0 is supported.
257 * TRIG_FOLLOW: (For an output device.) The start_src event occurs
258 * when data is written to the buffer.
259 * TRIG_EXT: start event occurs when an external trigger
260 * signal occurs, e.g., a rising edge of a digital
261 * line. start_arg chooses the particular digital
263 * TRIG_INT: start event occurs on a Comedi internal signal,
264 * which is typically caused by an INSN_TRIG
267 cmd->start_src = TRIG_NOW;
270 /* The timing of the beginning of each scan is controlled by
272 * TRIG_TIMER: scan_begin events occur periodically.
273 * The time between scan_begin events is
274 * convert_arg nanoseconds.
275 * TRIG_EXT: scan_begin events occur when an external trigger
276 * signal occurs, e.g., a rising edge of a digital
277 * line. scan_begin_arg chooses the particular digital
279 * TRIG_FOLLOW: scan_begin events occur immediately after a scan_end
281 * The scan_begin_arg that we use here may not be supported exactly
282 * by the device, but it will be adjusted to the nearest supported
283 * value by comedi_command_test(). */
284 cmd->scan_begin_src = TRIG_TIMER;
285 cmd->scan_begin_arg = period_nanosec; /* in ns */
287 /* The timing between each sample in a scan is controlled by convert.
288 * TRIG_TIMER: Conversion events occur periodically.
289 * The time between convert events is
290 * convert_arg nanoseconds.
291 * TRIG_EXT: Conversion events occur when an external trigger
292 * signal occurs, e.g., a rising edge of a digital
293 * line. convert_arg chooses the particular digital
295 * TRIG_NOW: All conversion events in a scan occur simultaneously.
296 * Even though it is invalid, we specify 1 ns here. It will be
297 * adjusted later to a valid value by comedi_command_test() */
298 cmd->convert_src = TRIG_TIMER;
299 cmd->convert_arg = 1; /* in ns */
301 /* The end of each scan is almost always specified using
302 * TRIG_COUNT, with the argument being the same as the
303 * number of channels in the chanlist. You could probably
304 * find a device that allows something else, but it would
306 cmd->scan_end_src = TRIG_COUNT;
307 cmd->scan_end_arg = n_chan; /* number of channels */
309 /* The end of acquisition is controlled by stop_src and
311 * TRIG_COUNT: stop acquisition after stop_arg scans.
312 * TRIG_NONE: continuous acquisition, until stopped using
315 cmd->stop_src = TRIG_COUNT;
316 cmd->stop_arg = n_scan;
318 /* the channel list determined which channels are sampled.
319 In general, chanlist_len is the same as scan_end_arg. Most
320 boards require this. */
321 cmd->chanlist = chanlist;
322 cmd->chanlist_len = n_chan;
327 void print_datum(lsampl_t raw, int channel_index, short physical) {
328 double physical_value;
332 physical_value = comedi_to_phys(raw, range_info[channel_index], maxdata[channel_index]);
333 printf("%#8.6g ",physical_value);