2005-01-17 20:20:26 +00:00
|
|
|
/*
|
|
|
|
* Asynchronous Analog Output Example
|
|
|
|
* Part of Comedilib
|
|
|
|
*
|
|
|
|
* Copyright (c) 1999,2000 David A. Schleef <ds@schleef.org>
|
|
|
|
* Copyright (c) 2005 Frank Mori Hess <fmhess@@users.sourceforge.net>
|
|
|
|
*
|
|
|
|
* 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!).
|
|
|
|
* The waveform data is passed to comedi through
|
|
|
|
* a memory mapping (as opposed to using write()).
|
|
|
|
* The entire buffer is filled once with one period
|
|
|
|
* of the waveform.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <comedilib.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include "examples.h"
|
|
|
|
|
|
|
|
|
|
|
|
static void write_waveform(sampl_t *buffer, int size, double amplitude, double offset, int maxdata)
|
|
|
|
{
|
|
|
|
int i;
|
2007-01-03 21:14:53 +00:00
|
|
|
|
2005-01-17 20:20:26 +00:00
|
|
|
for(i = 0; i < size; ++i)
|
|
|
|
{
|
|
|
|
double temp = (amplitude / 2.) * sin((2. * M_PI * i) / size) + offset;
|
|
|
|
if(temp < 0.) temp = 0.;
|
|
|
|
if(temp > maxdata) temp = maxdata;
|
|
|
|
buffer[i] = (sampl_t)temp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
comedi_cmd cmd;
|
|
|
|
int err;
|
|
|
|
comedi_t *dev;
|
|
|
|
unsigned int chanlist[16];
|
|
|
|
unsigned int maxdata;
|
|
|
|
comedi_range *rng;
|
|
|
|
int ret;
|
|
|
|
int size;
|
2005-01-23 03:11:30 +00:00
|
|
|
int num_samples;
|
2005-01-17 20:20:26 +00:00
|
|
|
sampl_t *map;
|
|
|
|
/* peak-to-peak amplitude, in DAC units (i.e., 0-4095) */
|
|
|
|
double amplitude;
|
|
|
|
/* offset, in DAC units */
|
|
|
|
double offset;
|
2007-01-03 21:14:53 +00:00
|
|
|
struct parsed_options options;
|
2005-01-17 20:20:26 +00:00
|
|
|
|
2007-01-03 21:14:53 +00:00
|
|
|
init_parsed_options(&options);
|
|
|
|
options.subdevice = -1;
|
|
|
|
parse_options(&options, argc, argv);
|
2005-01-17 20:20:26 +00:00
|
|
|
|
|
|
|
/* Force n_chan to be 1 */
|
2007-01-03 21:14:53 +00:00
|
|
|
options.n_chan = 1;
|
2005-01-17 20:20:26 +00:00
|
|
|
|
2007-01-03 21:14:53 +00:00
|
|
|
dev = comedi_open(options.filename);
|
2005-01-17 20:20:26 +00:00
|
|
|
if(dev == NULL){
|
2007-01-03 21:14:53 +00:00
|
|
|
fprintf(stderr, "error opening %s\n", options.filename);
|
2005-01-17 20:20:26 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2007-01-03 21:14:53 +00:00
|
|
|
if(options.subdevice < 0)
|
|
|
|
options.subdevice = comedi_find_subdevice_by_type(dev,COMEDI_SUBD_AO, 0);
|
2005-01-17 20:20:26 +00:00
|
|
|
|
2007-01-03 21:14:53 +00:00
|
|
|
maxdata = comedi_get_maxdata(dev, options.subdevice, 0);
|
|
|
|
rng = comedi_get_range(dev, options.subdevice, 0, 0);
|
2005-01-17 20:20:26 +00:00
|
|
|
|
|
|
|
offset = (double)comedi_from_phys(0.0, rng, maxdata);
|
|
|
|
amplitude = (double)comedi_from_phys(1.0, rng, maxdata) - offset;
|
|
|
|
|
|
|
|
memset(&cmd,0,sizeof(cmd));
|
2007-01-03 21:14:53 +00:00
|
|
|
cmd.subdev = options.subdevice;
|
2005-01-17 20:20:26 +00:00
|
|
|
cmd.flags = 0;
|
|
|
|
cmd.start_src = TRIG_INT;
|
|
|
|
cmd.start_arg = 0;
|
|
|
|
cmd.scan_begin_src = TRIG_TIMER;
|
2007-01-03 21:14:53 +00:00
|
|
|
cmd.scan_begin_arg = 1e9 / options.freq;
|
2005-01-17 20:20:26 +00:00
|
|
|
cmd.convert_src = TRIG_NOW;
|
|
|
|
cmd.convert_arg = 0;
|
|
|
|
cmd.scan_end_src = TRIG_COUNT;
|
2007-01-03 21:14:53 +00:00
|
|
|
cmd.scan_end_arg = options.n_chan;
|
2005-01-17 20:20:26 +00:00
|
|
|
cmd.stop_src = TRIG_NONE;
|
|
|
|
cmd.stop_arg = 0;
|
|
|
|
|
|
|
|
cmd.chanlist = chanlist;
|
2007-01-03 21:14:53 +00:00
|
|
|
cmd.chanlist_len = options.n_chan;
|
2005-01-17 20:20:26 +00:00
|
|
|
|
2007-01-03 21:14:53 +00:00
|
|
|
chanlist[0] = CR_PACK(options.channel, options.range, options.aref);
|
2005-01-17 20:20:26 +00:00
|
|
|
|
2007-01-03 21:14:53 +00:00
|
|
|
dump_cmd(stdout, &cmd);
|
2005-01-17 20:20:26 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2016-05-13 17:19:10 +01:00
|
|
|
/*
|
|
|
|
* The 'write' subdevice needs to be correct for 'mmap', below, to
|
|
|
|
* map the correct buffer!
|
|
|
|
*/
|
|
|
|
comedi_set_write_subdevice(dev, cmd.subdev);
|
|
|
|
ret = comedi_get_write_subdevice(dev);
|
|
|
|
if (ret < 0 || ret != cmd.subdev) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"failed to change 'write' subdevice from %d to %d\n",
|
|
|
|
ret, cmd.subdev);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2005-01-17 20:20:26 +00:00
|
|
|
if ((err = comedi_command(dev, &cmd)) < 0) {
|
|
|
|
comedi_perror("comedi_command");
|
|
|
|
exit(1);
|
|
|
|
}
|
2007-01-03 21:14:53 +00:00
|
|
|
|
|
|
|
size = comedi_get_buffer_size(dev, options.subdevice);
|
2005-01-17 20:20:26 +00:00
|
|
|
fprintf(stderr, "buffer size is %d\n", size);
|
|
|
|
map = mmap(NULL, size, PROT_WRITE, MAP_SHARED, comedi_fileno(dev), 0);
|
|
|
|
if(map == MAP_FAILED)
|
|
|
|
{
|
|
|
|
perror("mmap");
|
|
|
|
exit(1);
|
|
|
|
}
|
2005-01-23 03:11:30 +00:00
|
|
|
num_samples = size / sizeof(sampl_t);
|
|
|
|
write_waveform(map, num_samples, amplitude, offset, maxdata);
|
|
|
|
printf("marking %i samples as written\n", num_samples);
|
2007-01-03 21:14:53 +00:00
|
|
|
ret = comedi_mark_buffer_written(dev, options.subdevice, size);
|
2005-01-23 03:11:30 +00:00
|
|
|
if(ret < 0)
|
2005-01-22 14:31:20 +00:00
|
|
|
{
|
|
|
|
comedi_perror("comedi_mark_buffer_written");
|
|
|
|
exit(1);
|
|
|
|
}
|
2007-01-03 21:14:53 +00:00
|
|
|
ret = comedi_internal_trigger(dev, options.subdevice, 0);
|
2005-01-17 20:20:26 +00:00
|
|
|
if(ret<0){
|
2005-01-23 03:11:30 +00:00
|
|
|
comedi_perror("comedi_internal_trigger");
|
2005-01-17 20:20:26 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
2005-01-23 03:11:30 +00:00
|
|
|
while(1)
|
|
|
|
{
|
2007-01-03 21:14:53 +00:00
|
|
|
int bytes_marked = comedi_get_buffer_contents(dev, options.subdevice);
|
2006-05-02 02:09:02 +00:00
|
|
|
int bytes_unmarked = size - bytes_marked;
|
2005-01-23 03:11:30 +00:00
|
|
|
if(bytes_marked < 0)
|
2005-01-17 20:20:26 +00:00
|
|
|
{
|
|
|
|
comedi_perror("comedi_get_buffer_contents");
|
|
|
|
exit(1);
|
|
|
|
}
|
2005-01-23 03:11:30 +00:00
|
|
|
if(bytes_unmarked > 0)
|
2005-01-17 20:20:26 +00:00
|
|
|
{
|
2005-01-23 03:11:30 +00:00
|
|
|
// this keeps comedi from reporting a buffer underrun
|
2007-01-03 21:14:53 +00:00
|
|
|
if(comedi_mark_buffer_written(dev, options.subdevice, bytes_unmarked) < 0)
|
2005-01-23 03:11:30 +00:00
|
|
|
{
|
|
|
|
comedi_perror("comedi_mark_buffer_written");
|
|
|
|
exit(1);
|
|
|
|
}
|
2013-11-08 13:12:01 +00:00
|
|
|
printf("marked %lu more samples as written\n", (unsigned long)bytes_unmarked / sizeof(sampl_t));
|
2005-01-23 03:11:30 +00:00
|
|
|
}else
|
|
|
|
usleep(10000);
|
2005-01-17 20:20:26 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|