Moved comedi_internal_trigger into common.c
[comedilib.git] / demo / ao_mmap.c
1 /*
2  * Asynchronous Analog Output Example
3  * Part of Comedilib
4  *
5  * Copyright (c) 1999,2000 David A. Schleef <ds@schleef.org>
6  * Copyright (c) 2005 Frank Mori Hess <fmhess@@users.sourceforge.net>
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  * Requirements: Analog output device capable of
15  *    asynchronous commands.
16  *
17  * This demo uses an analog output subdevice with an
18  * asynchronous command to generate a waveform.  The
19  * waveform in this example is a sine wave (surprise!).
20  * The waveform data is passed to comedi through
21  * a memory mapping (as opposed to using write()).
22  * The entire buffer is filled once with one period
23  * of the waveform.
24  */
25
26 #include <stdio.h>
27 #include <comedilib.h>
28 #include <fcntl.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <getopt.h>
33 #include <ctype.h>
34 #include <math.h>
35 #include <string.h>
36 #include <sys/mman.h>
37 #include "examples.h"
38
39
40 static void write_waveform(sampl_t *buffer, int size, double amplitude, double offset, int maxdata)
41 {
42         int i;
43
44         for(i = 0; i < size; ++i)
45         {
46                 double temp = (amplitude / 2.) * sin((2. * M_PI * i) / size) + offset;
47                 if(temp < 0.) temp = 0.;
48                 if(temp > maxdata) temp = maxdata;
49                 buffer[i] = (sampl_t)temp;
50         }
51 }
52
53 int main(int argc, char *argv[])
54 {
55         comedi_cmd cmd;
56         int err;
57         comedi_t *dev;
58         unsigned int chanlist[16];
59         unsigned int maxdata;
60         comedi_range *rng;
61         int ret;
62         int size;
63         int num_samples;
64         sampl_t *map;
65         /* peak-to-peak amplitude, in DAC units (i.e., 0-4095) */
66         double amplitude;
67         /* offset, in DAC units */
68         double offset;
69         struct parsed_options options;
70
71         init_parsed_options(&options);
72         options.subdevice = -1;
73         parse_options(&options, argc, argv);
74
75         /* Force n_chan to be 1 */
76         options.n_chan = 1;
77
78         dev = comedi_open(options.filename);
79         if(dev == NULL){
80                 fprintf(stderr, "error opening %s\n", options.filename);
81                 return -1;
82         }
83         if(options.subdevice < 0)
84                 options.subdevice = comedi_find_subdevice_by_type(dev,COMEDI_SUBD_AO, 0);
85
86         maxdata = comedi_get_maxdata(dev, options.subdevice, 0);
87         rng = comedi_get_range(dev, options.subdevice, 0, 0);
88
89         offset = (double)comedi_from_phys(0.0, rng, maxdata);
90         amplitude = (double)comedi_from_phys(1.0, rng, maxdata) - offset;
91
92         memset(&cmd,0,sizeof(cmd));
93         cmd.subdev = options.subdevice;
94         cmd.flags = 0;
95         cmd.start_src = TRIG_INT;
96         cmd.start_arg = 0;
97         cmd.scan_begin_src = TRIG_TIMER;
98         cmd.scan_begin_arg = 1e9 / options.freq;
99         cmd.convert_src = TRIG_NOW;
100         cmd.convert_arg = 0;
101         cmd.scan_end_src = TRIG_COUNT;
102         cmd.scan_end_arg = options.n_chan;
103         cmd.stop_src = TRIG_NONE;
104         cmd.stop_arg = 0;
105
106         cmd.chanlist = chanlist;
107         cmd.chanlist_len = options.n_chan;
108
109         chanlist[0] = CR_PACK(options.channel, options.range, options.aref);
110
111         dump_cmd(stdout, &cmd);
112
113         err = comedi_command_test(dev, &cmd);
114         if (err < 0) {
115                 comedi_perror("comedi_command_test");
116                 exit(1);
117         }
118
119         err = comedi_command_test(dev, &cmd);
120         if (err < 0) {
121                 comedi_perror("comedi_command_test");
122                 exit(1);
123         }
124
125         if ((err = comedi_command(dev, &cmd)) < 0) {
126                 comedi_perror("comedi_command");
127                 exit(1);
128         }
129
130         size = comedi_get_buffer_size(dev, options.subdevice);
131         fprintf(stderr, "buffer size is %d\n", size);
132         map = mmap(NULL, size, PROT_WRITE, MAP_SHARED, comedi_fileno(dev), 0);
133         if(map == MAP_FAILED)
134         {
135                 perror("mmap");
136                 exit(1);
137         }
138         num_samples = size / sizeof(sampl_t);
139         write_waveform(map, num_samples, amplitude, offset, maxdata);
140         if(msync(map, size, MS_SYNC) < 0)
141         {
142                 perror("msync");
143                 exit(1);
144         }
145         printf("marking %i samples as written\n", num_samples);
146         ret = comedi_mark_buffer_written(dev, options.subdevice, size);
147         if(ret < 0)
148         {
149                 comedi_perror("comedi_mark_buffer_written");
150                 exit(1);
151         }
152         ret = comedi_internal_trigger(dev, options.subdevice, 0);
153         if(ret<0){
154                 comedi_perror("comedi_internal_trigger");
155                 exit(1);
156         }
157         while(1)
158         {
159                 int bytes_marked = comedi_get_buffer_contents(dev, options.subdevice);
160                 int bytes_unmarked = size - bytes_marked;
161                 if(bytes_marked < 0)
162                 {
163                         comedi_perror("comedi_get_buffer_contents");
164                         exit(1);
165                 }
166                 if(bytes_unmarked > 0)
167                 {
168                         // this keeps comedi from reporting a buffer underrun
169                         if(comedi_mark_buffer_written(dev, options.subdevice, bytes_unmarked) < 0)
170                         {
171                                 comedi_perror("comedi_mark_buffer_written");
172                                 exit(1);
173                         }
174                         printf("marked %i more samples as written\n", bytes_unmarked / sizeof(sampl_t));
175                 }else
176                         usleep(10000);
177         }
178         return 0;
179 }
180