/* * Asynchronous Analog Output Example * Part of Comedilib * * Copyright (c) 1999,2000 David A. Schleef * * This file may be freely modified, distributed, and combined with * other software, as long as proper attribution is given in the * source code. */ /* * Requirements: Analog output device capable of * asynchronous commands. * * This demo uses an analog output subdevice with an * asynchronous command to generate a waveform. The * waveform in this example is a sine wave (surprise!), * but this can be easily changed to make a generic * function generator. * * The function generation algorithm is the same as * what is typically used in digital function generators. * A 32-bit accumulator is incremented by a phase factor, * which is the amount (in radians) that the generator * advances each time step. The accumulator is then * shifted right by 20 bits, to get a 12 bit offset into * a lookup table. The value in the lookup table at * that offset is then put into a buffer for output to * the DAC. * * [ Actually, the accumulator is only 26 bits, for some * reason. I'll fix this sometime. ] * * On the Comedi side of things, the setup for mode 2 * is similar to analog input, except for the TRIG_WRITE * flag. Once you have issued the command, comedi then * expects you to keep the buffer full of data to output * to the DAC. This is done by write(). Since there * may be a delay between the comedi_command() and a subsequent * write(), you should fill the buffer using write() before * you call comedi_command(), as is done here. * */ #include #include #include #include #include #include #include #include #include #include #include "examples.h" /* frequency of the sine wave to output */ double waveform_frequency = 10.0; /* peak-to-peak amplitude, in DAC units (i.e., 0-4095) */ double amplitude = 4000; /* offset, in DAC units */ double offset = 2048; /* This is the size of chunks we deal with when creating and outputting data. This *could* be 1, but that would be inefficient */ #define BUF_LEN 0x8000 int subdevice; int external_trigger_number = 0; sampl_t data[BUF_LEN]; void dds_output(sampl_t *buf,int n); void dds_init(void); /* This define determines which waveform to use. */ #define dds_init_function dds_init_sine void dds_init_sine(void); void dds_init_pseudocycloid(void); void dds_init_sawtooth(void); int comedi_internal_trigger(comedi_t *dev, unsigned int subd, unsigned int trignum) { comedi_insn insn; lsampl_t data[1]; memset(&insn, 0, sizeof(comedi_insn)); insn.insn = INSN_INTTRIG; insn.subdev = subd; insn.data = data; insn.n = 1; data[0] = trignum; return comedi_do_insn(dev, &insn); } int main(int argc, char *argv[]) { comedi_cmd cmd; int err; int n,m; int total=0; comedi_t *dev; unsigned int chanlist[16]; unsigned int maxdata; comedi_range *rng; int ret; parse_options(argc,argv); /* Force n_chan to be 1 */ n_chan = 1; if(value){ waveform_frequency = value; } dev = comedi_open(filename); if(dev == NULL){ fprintf(stderr, "error opening %s\n", filename); return -1; } subdevice = comedi_find_subdevice_by_type(dev,COMEDI_SUBD_AO,0); maxdata = comedi_get_maxdata(dev,subdevice,0); rng = comedi_get_range(dev,subdevice,0,0); offset = (double)comedi_from_phys(0.0,rng,maxdata); amplitude = (double)comedi_from_phys(1.0,rng,maxdata) - offset; memset(&cmd,0,sizeof(cmd)); cmd.subdev = subdevice; cmd.flags = 0; cmd.start_src = TRIG_INT; cmd.start_arg = 0; cmd.scan_begin_src = TRIG_TIMER; cmd.scan_begin_arg = 1e9/freq; cmd.convert_src = TRIG_NOW; cmd.convert_arg = 0; cmd.scan_end_src = TRIG_COUNT; cmd.scan_end_arg = n_chan; cmd.stop_src = TRIG_NONE; cmd.stop_arg = 0; cmd.chanlist = chanlist; cmd.chanlist_len = n_chan; chanlist[0] = CR_PACK(channel,range,aref); chanlist[1] = CR_PACK(channel+1,range,aref); dds_init(); dump_cmd(stdout,&cmd); err = comedi_command_test(dev, &cmd); if (err < 0) { comedi_perror("comedi_command_test"); exit(1); } err = comedi_command_test(dev, &cmd); if (err < 0) { comedi_perror("comedi_command_test"); exit(1); } if ((err = comedi_command(dev, &cmd)) < 0) { comedi_perror("comedi_command"); exit(1); } dds_output(data,BUF_LEN); n = BUF_LEN * sizeof(sampl_t); m = write(comedi_fileno(dev), (void *)data, n); if(m < 0){ perror("write"); exit(1); }else if(m < n) { fprintf(stderr, "failed to preload output buffer with %i bytes, is it too small?\n" "See the --write-buffer option of comedi_config\n", n); exit(1); } printf("m=%d\n",m); ret = comedi_internal_trigger(dev, subdevice, 0); if(ret<0){ perror("comedi_internal_trigger\n"); exit(1); } while(1){ dds_output(data,BUF_LEN); n=BUF_LEN*sizeof(sampl_t); while(n>0){ m=write(comedi_fileno(dev),(void *)data+(BUF_LEN*sizeof(sampl_t)-n),n); if(m<0){ perror("write"); exit(0); } printf("m=%d\n",m); n-=m; } total+=BUF_LEN; //printf("%d\n",total); } return 0; } #define WAVEFORM_SHIFT 16 #define WAVEFORM_LEN (1<>16)&WAVEFORM_MASK]; p++; acc+=adder; } } void dds_init_sine(void) { int i; for(i=0;i