2 * Asynchronous Analog Output Example
5 * Copyright (c) 1999,2000 David A. Schleef <ds@schleef.org>
7 * This file may be freely modified, distributed, and combined with
8 * other software, as long as proper attribution is given in the
13 * Requirements: Analog output device capable of
14 * asynchronous commands.
16 * This demo uses an analog output subdevice with an
17 * asynchronous command to generate a waveform. The
18 * waveform in this example is a sine wave (surprise!),
19 * but this can be easily changed to make a generic
22 * The function generation algorithm is the same as
23 * what is typically used in digital function generators.
24 * A 32-bit accumulator is incremented by a phase factor,
25 * which is the amount (in radians) that the generator
26 * advances each time step. The accumulator is then
27 * shifted right by 20 bits, to get a 12 bit offset into
28 * a lookup table. The value in the lookup table at
29 * that offset is then put into a buffer for output to
32 * [ Actually, the accumulator is only 26 bits, for some
33 * reason. I'll fix this sometime. ]
35 * On the Comedi side of things, the setup for mode 2
36 * is similar to analog input, except for the TRIG_WRITE
37 * flag. Once you have issued the command, comedi then
38 * expects you to keep the buffer full of data to output
39 * to the DAC. This is done by write(). Since there
40 * may be a delay between the comedi_command() and a subsequent
41 * write(), you should fill the buffer using write() before
42 * you call comedi_command(), as is done here.
47 #include <comedilib.h>
58 /* frequency of the sine wave to output */
59 double waveform_frequency = 100.0;
61 /* update rate for the DAC, typically much higher than
62 the frequency of the sine wave. */
63 double update_frequency = 50000.0;
65 /* peak-to-peak amplitude, in DAC units (i.e., 0-4095) */
66 double amplitude = 4000;
68 /* offset, in DAC units */
71 /* This is the size of chunks we deal with when creating and
72 outputting data. This *could* be 1, but that would be
77 int external_trigger_number = 0;
79 sampl_t data[BUF_LEN];
81 void dds_output(sampl_t *buf,int n);
84 /* This define determines which waveform to use. */
85 #define dds_init_function dds_init_sine
87 void dds_init_sine(void);
88 void dds_init_pseudocycloid(void);
89 void dds_init_sawtooth(void);
91 int main(int argc, char *argv[])
98 unsigned int chanlist[1];
100 parse_options(argc,argv);
103 waveform_frequency = value;
106 dev = comedi_open(filename);
108 subdevice = comedi_find_subdevice_by_type(dev,COMEDI_SUBD_AO,0);
110 memset(&cmd,0,sizeof(cmd));
111 cmd.subdev = subdevice;
113 cmd.start_src = TRIG_NOW;
115 cmd.scan_begin_src = TRIG_TIMER;
116 cmd.scan_begin_arg = 1e9/update_frequency;
117 cmd.convert_src = TRIG_NOW;
119 cmd.scan_end_src = TRIG_COUNT;
120 cmd.scan_end_arg = 1;
121 cmd.stop_src = TRIG_NONE;
124 cmd.chanlist = chanlist;
125 cmd.chanlist_len = 1;
127 chanlist[0] = CR_PACK(channel,range,aref);
131 dds_output(data,BUF_LEN);
132 dds_output(data,BUF_LEN);
134 m=write(comedi_fileno(dev),data,BUF_LEN*sizeof(sampl_t));
138 if ((err = comedi_command(dev, &cmd)) < 0) {
139 comedi_perror("comedi_command");
143 dds_output(data,BUF_LEN);
144 n=BUF_LEN*sizeof(sampl_t);
146 m=write(comedi_fileno(dev),(void *)data+(BUF_LEN*sizeof(sampl_t)-n),n);
151 //printf("m=%d\n",m);
155 //printf("%d\n",total);
163 #define WAVEFORM_SHIFT 16
164 #define WAVEFORM_LEN (1<<WAVEFORM_SHIFT)
165 #define WAVEFORM_MASK (WAVEFORM_LEN-1)
168 sampl_t waveform[WAVEFORM_LEN];
177 adder=waveform_frequency/update_frequency*(1<<16)*(1<<WAVEFORM_SHIFT);
181 /* this is due to a bug in the NI-E driver */
183 for(i=0;i<WAVEFORM_LEN;i++){
189 void dds_output(sampl_t *buf,int n)
195 *p=waveform[(acc>>16)&WAVEFORM_MASK];
202 void dds_init_sine(void)
206 for(i=0;i<WAVEFORM_LEN;i++){
207 waveform[i]=rint(offset+0.5*amplitude*cos(i*2*M_PI/WAVEFORM_LEN));
211 /* Yes, I know this is not the proper equation for a
213 void dds_init_pseudocycloid(void)
218 for(i=0;i<WAVEFORM_LEN/2;i++){
219 t=2*((double)i)/WAVEFORM_LEN;
220 waveform[i]=rint(offset+amplitude*sqrt(1-4*t*t));
222 for(i=WAVEFORM_LEN/2;i<WAVEFORM_LEN;i++){
223 t=2*(1-((double)i)/WAVEFORM_LEN);
224 waveform[i]=rint(offset+amplitude*sqrt(1-t*t));
228 void dds_init_sawtooth(void)
232 for(i=0;i<WAVEFORM_LEN;i++){
233 waveform[i]=rint(offset+amplitude*((double)i)/WAVEFORM_LEN);