2 * Asynchronous Analog Output Example
5 * Copyright (c) 1999,2000 David A. Schleef <ds@schleef.org>
6 * Copyright (c) 2005 Frank Mori Hess <fmhess@@users.sourceforge.net>
8 * This file may be freely modified, distributed, and combined with
9 * other software, as long as proper attribution is given in the
14 * Requirements: Analog output device capable of
15 * asynchronous commands.
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
27 #include <comedilib.h>
40 static void write_waveform(sampl_t *buffer, int size, double amplitude, double offset, int maxdata)
44 for(i = 0; i < size; ++i)
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;
53 int main(int argc, char *argv[])
58 unsigned int chanlist[16];
65 /* peak-to-peak amplitude, in DAC units (i.e., 0-4095) */
67 /* offset, in DAC units */
69 struct parsed_options options;
71 init_parsed_options(&options);
72 options.subdevice = -1;
73 parse_options(&options, argc, argv);
75 /* Force n_chan to be 1 */
78 dev = comedi_open(options.filename);
80 fprintf(stderr, "error opening %s\n", options.filename);
83 if(options.subdevice < 0)
84 options.subdevice = comedi_find_subdevice_by_type(dev,COMEDI_SUBD_AO, 0);
86 maxdata = comedi_get_maxdata(dev, options.subdevice, 0);
87 rng = comedi_get_range(dev, options.subdevice, 0, 0);
89 offset = (double)comedi_from_phys(0.0, rng, maxdata);
90 amplitude = (double)comedi_from_phys(1.0, rng, maxdata) - offset;
92 memset(&cmd,0,sizeof(cmd));
93 cmd.subdev = options.subdevice;
95 cmd.start_src = TRIG_INT;
97 cmd.scan_begin_src = TRIG_TIMER;
98 cmd.scan_begin_arg = 1e9 / options.freq;
99 cmd.convert_src = TRIG_NOW;
101 cmd.scan_end_src = TRIG_COUNT;
102 cmd.scan_end_arg = options.n_chan;
103 cmd.stop_src = TRIG_NONE;
106 cmd.chanlist = chanlist;
107 cmd.chanlist_len = options.n_chan;
109 chanlist[0] = CR_PACK(options.channel, options.range, options.aref);
111 dump_cmd(stdout, &cmd);
113 err = comedi_command_test(dev, &cmd);
115 comedi_perror("comedi_command_test");
119 err = comedi_command_test(dev, &cmd);
121 comedi_perror("comedi_command_test");
125 if ((err = comedi_command(dev, &cmd)) < 0) {
126 comedi_perror("comedi_command");
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)
138 num_samples = size / sizeof(sampl_t);
139 write_waveform(map, num_samples, amplitude, offset, maxdata);
140 if(msync(map, size, MS_SYNC) < 0)
145 printf("marking %i samples as written\n", num_samples);
146 ret = comedi_mark_buffer_written(dev, options.subdevice, size);
149 comedi_perror("comedi_mark_buffer_written");
152 ret = comedi_internal_trigger(dev, options.subdevice, 0);
154 comedi_perror("comedi_internal_trigger");
159 int bytes_marked = comedi_get_buffer_contents(dev, options.subdevice);
160 int bytes_unmarked = size - bytes_marked;
163 comedi_perror("comedi_get_buffer_contents");
166 if(bytes_unmarked > 0)
168 // this keeps comedi from reporting a buffer underrun
169 if(comedi_mark_buffer_written(dev, options.subdevice, bytes_unmarked) < 0)
171 comedi_perror("comedi_mark_buffer_written");
174 printf("marked %i more samples as written\n", bytes_unmarked / sizeof(sampl_t));