e62a27047e034715fe1aa1a60146acae4bc334a6
[comedilib.git] / demo / tut3.c
1 /*
2  * Example of using commands - asynchronous input
3  * Part of Comedilib
4  *
5  * Copyright (c) 1999,2000,2001 David A. Schleef <ds@schleef.org>
6  *               2008 Bernd Porr <berndporr@f2s.com>
7  *
8  * This file may be freely modified, distributed, and combined with
9  * other software, as long as proper attribution is given in the
10  * source code.
11  */
12
13 /*
14  * The program is used to test the usbdux sigma board
15  */
16
17 #include <stdio.h>
18 #include <comedilib.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <sys/time.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 extern comedi_t *device;
27
28 struct parsed_options
29 {
30         char *filename;
31         double value;
32         int subdevice;
33         int channel;
34         int aref;
35         int range;
36         int verbose;
37         int n_chan;
38         int n_scan;
39         double freq;
40 };
41
42
43
44 #define BUFSZ 10000
45 char buf[BUFSZ];
46
47 #define N_CHANS 256
48 static unsigned int chanlist[N_CHANS];
49 static comedi_range * range_info[N_CHANS];
50 static lsampl_t maxdata[N_CHANS];
51
52
53 int prepare_cmd_lib(comedi_t *dev, int subdevice, int n_scan, int n_chan, unsigned period_nanosec, comedi_cmd *cmd);
54
55 void do_cmd(comedi_t *dev,comedi_cmd *cmd);
56
57 void print_datum(lsampl_t raw, int channel_index);
58
59 char *cmdtest_messages[]={
60         "success",
61         "invalid source",
62         "source conflict",
63         "invalid argument",
64         "argument conflict",
65         "invalid chanlist",
66 };
67
68 int main(int argc, char *argv[])
69 {
70         comedi_t *dev;
71         comedi_cmd c,*cmd=&c;
72         int ret;
73         int total=0;
74         int i;
75         int subdev_flags;
76         lsampl_t raw;
77
78         struct parsed_options options;
79
80         /* The following variables used in this demo
81          * can be modified by command line
82          * options.  When modifying this demo, you may want to
83          * change them here. */
84         options.filename = "/dev/comedi0";
85         options.subdevice = 0;
86         options.channel = 0;
87         options.range = 0;
88         options.aref = AREF_GROUND;
89         options.n_chan = 2;
90         options.n_scan = 10000;
91         options.freq = 1000.0;
92
93         /* open the device */
94         dev = comedi_open(options.filename);
95         if(!dev){
96                 comedi_perror(options.filename);
97                 exit(1);
98         }
99
100         // Print numbers for clipped inputs
101         comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER);
102
103         /* Set up channel list */
104         for(i = 0; i < options.n_chan; i++){
105                 chanlist[i] = CR_PACK(options.channel + i, options.range, options.aref);
106                 range_info[i] = comedi_get_range(dev, options.subdevice, options.channel, options.range);
107                 maxdata[i] = comedi_get_maxdata(dev, options.subdevice, options.channel);
108         }
109
110         /* prepare_cmd_lib() uses a Comedilib routine to find a
111          * good command for the device.  prepare_cmd() explicitly
112          * creates a command, which may not work for your device. */
113         prepare_cmd_lib(dev, options.subdevice, options.n_scan, options.n_chan, 1e9 / options.freq, cmd);
114
115         /* comedi_command_test() tests a command to see if the
116          * trigger sources and arguments are valid for the subdevice.
117          * If a trigger source is invalid, it will be logically ANDed
118          * with valid values (trigger sources are actually bitmasks),
119          * which may or may not result in a valid trigger source.
120          * If an argument is invalid, it will be adjusted to the
121          * nearest valid value.  In this way, for many commands, you
122          * can test it multiple times until it passes.  Typically,
123          * if you can't get a valid command in two tests, the original
124          * command wasn't specified very well. */
125         ret = comedi_command_test(dev, cmd);
126         if(ret < 0){
127                 comedi_perror("comedi_command_test");
128                 if(errno == EIO){
129                         fprintf(stderr,"Ummm... this subdevice doesn't support commands\n");
130                 }
131                 exit(1);
132         }
133         ret = comedi_command_test(dev, cmd);
134         if(ret < 0){
135                 comedi_perror("comedi_command_test");
136                 exit(1);
137         }
138         fprintf(stderr,"second test returned %d (%s)\n", ret,
139                         cmdtest_messages[ret]);
140         if(ret!=0){
141                 fprintf(stderr, "Error preparing command\n");
142                 exit(1);
143         }
144
145         /* start the command */
146         ret = comedi_command(dev, cmd);
147         if(ret < 0){
148                 comedi_perror("comedi_command");
149                 exit(1);
150         }
151         subdev_flags = comedi_get_subdevice_flags(dev, options.subdevice);
152         while(1){
153                 ret = read(comedi_fileno(dev),buf,BUFSZ);
154                 if(ret < 0){
155                         /* some error occurred */
156                         perror("read");
157                         break;
158                 }else if(ret == 0){
159                         /* reached stop condition */
160                         break;
161                 }else{
162                         static int col = 0;
163                         int bytes_per_sample;
164                         total += ret;
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);
168                         else
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];
173                                 } else {
174                                         raw = ((sampl_t *)buf)[i];
175                                 }
176                                 print_datum(raw, col);
177                                 col++;
178                                 if(col == options.n_chan){
179                                         printf("\n");
180                                         col=0;
181                                 }
182                         }
183                 }
184         }
185
186 }
187
188 /*
189  * This prepares a command in a pretty generic way.  We ask the
190  * library to create a stock command that supports periodic
191  * sampling of data, then modify the parts we want. */
192 int prepare_cmd_lib(comedi_t *dev, int subdevice, int n_scan, int n_chan, unsigned scan_period_nanosec, comedi_cmd *cmd)
193 {
194         int ret;
195
196         memset(cmd,0,sizeof(*cmd));
197
198         /* This comedilib function will get us a generic timed
199          * command for a particular board.  If it returns -1,
200          * that's bad. */
201         ret = comedi_get_cmd_generic_timed(dev, subdevice, cmd, n_chan, scan_period_nanosec);
202         if(ret<0){
203                 printf("comedi_get_cmd_generic_timed failed\n");
204                 return ret;
205         }
206
207         /* Modify parts of the command */
208         cmd->chanlist = chanlist;
209         cmd->chanlist_len = n_chan;
210         if(cmd->stop_src == TRIG_COUNT) cmd->stop_arg = n_scan;
211
212         return 0;
213 }
214
215 void print_datum(lsampl_t raw, int channel_index) {
216         double physical_value;
217         physical_value = comedi_to_phys(raw, range_info[channel_index], maxdata[channel_index]);
218         printf("%#8.6g ",physical_value);
219 }