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 /* peak-to-peak amplitude, in DAC units (i.e., 0-4095) */
62 double amplitude = 4000;
64 /* offset, in DAC units */
67 /* This is the size of chunks we deal with when creating and
68 outputting data. This *could* be 1, but that would be
73 int external_trigger_number = 0;
75 sampl_t data[BUF_LEN];
77 void dds_output(sampl_t *buf,int n);
80 /* This define determines which waveform to use. */
81 #define dds_init_function dds_init_sine
83 void dds_init_sine(void);
84 void dds_init_pseudocycloid(void);
85 void dds_init_sawtooth(void);
87 int main(int argc, char *argv[])
95 unsigned int chanlist[1];
97 parse_options(argc,argv);
100 waveform_frequency = value;
103 dev = comedi_open(filename);
105 fprintf(stderr, "error opening %s\n", 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_INT;
115 cmd.scan_begin_src = TRIG_TIMER;
116 cmd.scan_begin_arg = 1e9/freq;
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 if ((err = comedi_command(dev, &cmd)) < 0) {
135 comedi_perror("comedi_command");
139 m=write(comedi_fileno(dev),data,BUF_LEN*sizeof(sampl_t));
143 memset(&insn, 0, sizeof(comedi_insn));
144 insn.insn = INSN_INTTRIG;
145 comedi_do_insn(dev, &insn);
148 dds_output(data,BUF_LEN);
149 n=BUF_LEN*sizeof(sampl_t);
151 m=write(comedi_fileno(dev),(void *)data+(BUF_LEN*sizeof(sampl_t)-n),n);
156 //printf("m=%d\n",m);
160 //printf("%d\n",total);
168 #define WAVEFORM_SHIFT 16
169 #define WAVEFORM_LEN (1<<WAVEFORM_SHIFT)
170 #define WAVEFORM_MASK (WAVEFORM_LEN-1)
173 sampl_t waveform[WAVEFORM_LEN];
182 adder=waveform_frequency/freq*(1<<16)*(1<<WAVEFORM_SHIFT);
186 /* this is due to a bug in the NI-E driver */
188 for(i=0;i<WAVEFORM_LEN;i++){
194 void dds_output(sampl_t *buf,int n)
200 *p=waveform[(acc>>16)&WAVEFORM_MASK];
207 void dds_init_sine(void)
211 for(i=0;i<WAVEFORM_LEN;i++){
212 waveform[i]=rint(offset+0.5*amplitude*cos(i*2*M_PI/WAVEFORM_LEN));
216 /* Yes, I know this is not the proper equation for a
218 void dds_init_pseudocycloid(void)
223 for(i=0;i<WAVEFORM_LEN/2;i++){
224 t=2*((double)i)/WAVEFORM_LEN;
225 waveform[i]=rint(offset+amplitude*sqrt(1-4*t*t));
227 for(i=WAVEFORM_LEN/2;i<WAVEFORM_LEN;i++){
228 t=2*(1-((double)i)/WAVEFORM_LEN);
229 waveform[i]=rint(offset+amplitude*sqrt(1-t*t));
233 void dds_init_sawtooth(void)
237 for(i=0;i<WAVEFORM_LEN;i++){
238 waveform[i]=rint(offset+amplitude*((double)i)/WAVEFORM_LEN);