added some comments, including advice on how to make interrupt handler run at hard...
[comedilib.git] / demo / cmd.c
1 /*
2  * Example of using commands - asynchronous input
3  * Part of Comedilib
4  *
5  * Copyright (c) 1999,2000 David A. Schleef <ds@schleef.org>
6  *
7  * This file may be freely modified, distributed, and combined with
8  * other software, as long as proper attribution is given in the
9  * source code.
10  */
11
12 /*
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.
16  */
17
18 #include <stdio.h>
19 #include <comedilib.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <sys/ioctl.h>
23 #include <errno.h>
24 #include <getopt.h>
25 #include <ctype.h>
26 #include <string.h>
27 #include "examples.h"
28
29 #define N_SCANS         10
30 #define N_CHANS         16
31
32 int subdevice = 0;
33 int chan=0;
34 int range = 0;
35 int aref = AREF_GROUND;
36 double freq = 1000;
37
38 #define BUFSZ 1000
39 char buf[BUFSZ];
40
41
42 void do_cmd_1(comedi_t *dev);
43 void do_cmd_2(comedi_t *dev);
44 void do_cmd(comedi_t *dev,comedi_cmd *cmd);
45 void dump_cmd(comedi_cmd *cmd);
46
47 int main(int argc, char *argv[])
48 {
49         char *fn = NULL;
50         comedi_t *dev;
51
52         fn = "/dev/comedi0";
53
54         dev = comedi_open(fn);
55         if(!dev){
56                 perror(fn);
57                 exit(1);
58         }
59
60         fcntl(comedi_fileno(dev),F_SETFL,O_NONBLOCK);
61
62         do_cmd_1(dev);
63
64         return 0;
65 }
66
67 void do_cmd(comedi_t *dev,comedi_cmd *cmd)
68 {
69         unsigned int *chanlist;
70         int n_chans;
71         int total=0;
72         int ret;
73         int go;
74
75         chanlist = cmd->chanlist;
76         n_chans = cmd->chanlist_len;
77
78         ret=ioctl(comedi_fileno(dev),COMEDI_CMDTEST,cmd);
79
80         printf("test ret=%d\n",ret);
81         if(ret<0){
82                 printf("errno=%d\n",errno);
83                 perror("ioctl");
84                 return;
85         }
86
87         dump_cmd(cmd);
88
89         /* restoring the chanlist stuff in this way is only required
90          * for comedi versions before 0.7.56
91          */ 
92         cmd->chanlist =         chanlist;
93         cmd->chanlist_len =     n_chans;
94
95         ret=ioctl(comedi_fileno(dev),COMEDI_CMDTEST,cmd);
96
97         printf("test ret=%d\n",ret);
98         if(ret<0){
99                 printf("errno=%d\n",errno);
100                 comedi_perror("ioctl");
101                 return;
102         }
103
104         dump_cmd(cmd);
105
106         cmd->chanlist =         chanlist;
107         cmd->chanlist_len =     n_chans;
108
109         ret=ioctl(comedi_fileno(dev),COMEDI_CMD,cmd);
110
111         printf("ret=%d\n",ret);
112         if(ret<0){
113                 printf("errno=%d\n",errno);
114                 comedi_perror("ioctl");
115                 return;
116         }
117
118         go=1;
119         while(go){
120                 ret=read(comedi_fileno(dev),buf,BUFSZ);
121                 if(ret<0){
122                         if(errno==EAGAIN){
123                                 usleep(10000);
124                         }else{
125                                 go = 0;
126                                 perror("read");
127                         }
128                 }else if(ret==0){
129                         go = 0;
130                 }else{
131                         total+=ret;
132                         printf("read %d %d\n",ret,total);
133                 }
134         }
135 }
136
137 /*
138  * This part of the demo measures channels 1, 2, 3, 4 at a rate of
139  * 10 khz, with the inter-sample time at 10 us (100 khz).  The number
140  * of scans measured is 10.  This is analogous to the old mode2
141  * acquisition.
142  */
143 void do_cmd_1(comedi_t *dev)
144 {
145         comedi_cmd cmd;
146         unsigned int chanlist[4];
147
148         memset(&cmd,0,sizeof(cmd));
149
150         /* the subdevice that the command is sent to */
151         cmd.subdev =    subdevice;
152
153         /* flags */
154         cmd.flags =     0;
155         /* the TRIG_RT flag will ask that the driver's interrupt handler be
156          * run at hard real time priority if you have a real time OS
157          */ 
158         //cmd.flags |= TRIG_RT; 
159
160         /* each event requires a trigger, which is specified
161            by a source and an argument.  For example, to specify
162            an external digital line 3 as a source, you would use
163            src=TRIG_EXT and arg=3. */
164
165         /* In this case, we specify using TRIG_NOW to start
166          * acquisition immediately when the command is issued.  
167          * The argument of TRIG_NOW is "number of nsec after
168          * NOW", but no driver supports it yet.  Also, no driver
169          * currently supports using a start_src other than
170          * TRIG_NOW.  */
171         cmd.start_src =         TRIG_NOW;
172         cmd.start_arg =         0;
173
174         /* The timing of the beginning of each scan is controlled
175          * by scan_begin.  TRIG_TIMER specifies that scan_start
176          * events occur periodically at a rate of scan_begin_arg
177          * nanoseconds between scans. */
178         cmd.scan_begin_src =    TRIG_TIMER;
179         cmd.scan_begin_arg =    100000; /* in ns */
180
181         /* The timing between each sample in a scan is controlled
182          * by convert.  Like above, TRIG_TIMER specifies that
183          * convert events occur periodically at a rate of convert_arg
184          * nanoseconds between scans. */
185         cmd.convert_src =       TRIG_TIMER;
186         cmd.convert_arg =       10000;          /* in ns */
187
188         /* The end of each scan is almost always specified using
189          * TRIG_COUNT, with the argument being the same as the
190          * number of channels in the chanlist.  You could probably
191          * find a device that allows something else, but it would
192          * be strange. */
193         cmd.scan_end_src =      TRIG_COUNT;
194         cmd.scan_end_arg =      4;              /* number of channels */
195
196         /* The end of acquisition is controlled by stop_src and
197          * stop_arg.  The src will typically be TRIG_COUNT or
198          * TRIG_NONE.  Specifying TRIG_COUNT will stop acquisition
199          * after stop_arg number of scans, or TRIG_NONE will
200          * cause acquisition to continue until stopped using
201          * comedi_cancel(). */
202 #if 1
203         cmd.stop_src =          TRIG_COUNT;
204         cmd.stop_arg =          100;
205 #else
206         cmd.stop_src =          TRIG_NONE;
207         cmd.stop_arg =          0;
208 #endif
209
210         /* the channel list determined which channels are sampled.
211            In general, chanlist_len is the same as scan_end_arg.  Most
212            boards require this.  */
213         cmd.chanlist =          chanlist;
214         cmd.chanlist_len =      4;
215
216         chanlist[0]=CR_PACK(0,range,aref);
217         chanlist[1]=CR_PACK(1,range,aref);
218         chanlist[2]=CR_PACK(2,range,aref);
219         chanlist[3]=CR_PACK(3,range,aref);
220
221         do_cmd(dev,&cmd);
222 }
223
224 void do_cmd_2(comedi_t *dev)
225 {
226         comedi_cmd cmd;
227         unsigned int chanlist[4];
228
229         memset(&cmd,0,sizeof(cmd));
230
231         /* the subdevice that the command is sent to */
232         cmd.subdev =    subdevice;
233
234         /* flags */
235         cmd.flags =     0;
236
237         /* each event requires a trigger, which is specified
238            by a source and an argument.  For example, to specify
239            an external digital line 3 as a source, you would use
240            src=TRIG_EXT and arg=3. */
241
242         cmd.start_src =         TRIG_NOW;
243         cmd.start_arg =         0;
244
245         cmd.scan_begin_src =    TRIG_TIMER;
246         cmd.scan_begin_arg =    1;      /* in ns */
247
248         cmd.convert_src =       TRIG_TIMER;
249         cmd.convert_arg =       1;              /* in ns */
250
251         cmd.scan_end_src =      TRIG_COUNT;
252         cmd.scan_end_arg =      4;              /* number of channels */
253
254 #if 1
255         cmd.stop_src =          TRIG_COUNT;
256         cmd.stop_arg =          100;
257 #else
258         cmd.stop_src =          TRIG_NONE;
259         cmd.stop_arg =          0;
260 #endif
261
262         /* the channel list determined which channels are sampled.
263            In general, chanlist_len is the same as scan_end_arg.  Most
264            boards require this.  */
265         cmd.chanlist =          chanlist;
266         cmd.chanlist_len =      4;
267
268         chanlist[0]=CR_PACK(0,range,aref);
269         chanlist[1]=CR_PACK(1,range,aref);
270         chanlist[2]=CR_PACK(2,range,aref);
271         chanlist[3]=CR_PACK(3,range,aref);
272
273         do_cmd(dev,&cmd);
274 }
275
276 char *cmd_src(int src,char *buf)
277 {
278         buf[0]=0;
279
280         if(src&TRIG_NONE)strcat(buf,"none|");
281         if(src&TRIG_NOW)strcat(buf,"now|");
282         if(src&TRIG_FOLLOW)strcat(buf, "follow|");
283         if(src&TRIG_TIME)strcat(buf, "time|");
284         if(src&TRIG_TIMER)strcat(buf, "timer|");
285         if(src&TRIG_COUNT)strcat(buf, "count|");
286         if(src&TRIG_EXT)strcat(buf, "ext|");
287         if(src&TRIG_INT)strcat(buf, "int|");
288
289         if(strlen(buf)==0){
290                 sprintf(buf,"unknown(0x%02x)",src);
291         }else{
292                 buf[strlen(buf)-1]=0;
293         }
294
295         return buf;
296 }
297
298
299 void dump_cmd(comedi_cmd *cmd)
300 {
301         char buf[100];
302
303         printf("start: %s %d\n",
304                 cmd_src(cmd->start_src,buf),
305                 cmd->start_arg);
306
307         printf("scan_begin: %s %d\n",
308                 cmd_src(cmd->scan_begin_src,buf),
309                 cmd->scan_begin_arg);
310
311         printf("convert: %s %d\n",
312                 cmd_src(cmd->convert_src,buf),
313                 cmd->convert_arg);
314
315         printf("scan_end: %s %d\n",
316                 cmd_src(cmd->scan_end_src,buf),
317                 cmd->scan_end_arg);
318
319         printf("stop: %s %d\n",
320                 cmd_src(cmd->stop_src,buf),
321                 cmd->stop_arg);
322 }
323