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 int comedi_internal_trigger(comedi_t *dev, unsigned int subd, unsigned int trignum)
45 memset(&insn, 0, sizeof(comedi_insn));
46 insn.insn = INSN_INTTRIG;
53 return comedi_do_insn(dev, &insn);
56 static void write_waveform(sampl_t *buffer, int size, double amplitude, double offset, int maxdata)
60 for(i = 0; i < size; ++i)
62 double temp = (amplitude / 2.) * sin((2. * M_PI * i) / size) + offset;
63 if(temp < 0.) temp = 0.;
64 if(temp > maxdata) temp = maxdata;
65 buffer[i] = (sampl_t)temp;
69 int main(int argc, char *argv[])
74 unsigned int chanlist[16];
81 /* peak-to-peak amplitude, in DAC units (i.e., 0-4095) */
83 /* offset, in DAC units */
85 struct parsed_options options;
87 init_parsed_options(&options);
88 options.subdevice = -1;
89 parse_options(&options, argc, argv);
91 /* Force n_chan to be 1 */
94 dev = comedi_open(options.filename);
96 fprintf(stderr, "error opening %s\n", options.filename);
99 if(options.subdevice < 0)
100 options.subdevice = comedi_find_subdevice_by_type(dev,COMEDI_SUBD_AO, 0);
102 maxdata = comedi_get_maxdata(dev, options.subdevice, 0);
103 rng = comedi_get_range(dev, options.subdevice, 0, 0);
105 offset = (double)comedi_from_phys(0.0, rng, maxdata);
106 amplitude = (double)comedi_from_phys(1.0, rng, maxdata) - offset;
108 memset(&cmd,0,sizeof(cmd));
109 cmd.subdev = options.subdevice;
111 cmd.start_src = TRIG_INT;
113 cmd.scan_begin_src = TRIG_TIMER;
114 cmd.scan_begin_arg = 1e9 / options.freq;
115 cmd.convert_src = TRIG_NOW;
117 cmd.scan_end_src = TRIG_COUNT;
118 cmd.scan_end_arg = options.n_chan;
119 cmd.stop_src = TRIG_NONE;
122 cmd.chanlist = chanlist;
123 cmd.chanlist_len = options.n_chan;
125 chanlist[0] = CR_PACK(options.channel, options.range, options.aref);
127 dump_cmd(stdout, &cmd);
129 err = comedi_command_test(dev, &cmd);
131 comedi_perror("comedi_command_test");
135 err = comedi_command_test(dev, &cmd);
137 comedi_perror("comedi_command_test");
141 if ((err = comedi_command(dev, &cmd)) < 0) {
142 comedi_perror("comedi_command");
146 size = comedi_get_buffer_size(dev, options.subdevice);
147 fprintf(stderr, "buffer size is %d\n", size);
148 map = mmap(NULL, size, PROT_WRITE, MAP_SHARED, comedi_fileno(dev), 0);
149 if(map == MAP_FAILED)
154 num_samples = size / sizeof(sampl_t);
155 write_waveform(map, num_samples, amplitude, offset, maxdata);
156 if(msync(map, size, MS_SYNC) < 0)
161 printf("marking %i samples as written\n", num_samples);
162 ret = comedi_mark_buffer_written(dev, options.subdevice, size);
165 comedi_perror("comedi_mark_buffer_written");
168 ret = comedi_internal_trigger(dev, options.subdevice, 0);
170 comedi_perror("comedi_internal_trigger");
175 int bytes_marked = comedi_get_buffer_contents(dev, options.subdevice);
176 int bytes_unmarked = size - bytes_marked;
179 comedi_perror("comedi_get_buffer_contents");
182 if(bytes_unmarked > 0)
184 // this keeps comedi from reporting a buffer underrun
185 if(comedi_mark_buffer_written(dev, options.subdevice, bytes_unmarked) < 0)
187 comedi_perror("comedi_mark_buffer_written");
190 printf("marked %i more samples as written\n", bytes_unmarked / sizeof(sampl_t));