/usr/share/doc/libcomedi-dev/demo/do_waveform.c is in libcomedi-dev 0.10.2-4.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | /*
* Asynchronous Digital Output Example
* Part of Comedilib
*
* Copyright (c) 1999,2000 David A. Schleef <ds@schleef.org>
* Copyright (c) 2007 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: NI M-Series board.
*
* This demo uses the digital io subdevice with an
* asynchronous command to generate waveforms. The
* waveforms in this example are square waves with
* varying periods depending on the digital output
* channel. Channel N outputs a square wave with
* period 2*(N+1) clocks. The command line argument chooses the
* clock signal for updating the outputs. As a suggestion,
* you might use the output of one of the general
* purpose counters for a clock (the default clock
* source is the output of general purpose counter 0),
* and run the gpct_pulse_generator demo to start the counter
* generating pulses on its output.
*
* Note, you must configure at least one of the digital channels as
* an output (for example by running the dio demo program)
* before running this program. You must also pass the dio
* subdevice file using the -f option, since the default write
* subdevice for the m-series boards is the analog output. For
* example, "dio_waveform -f /dev/comedi0_sub2".
*/
#include <assert.h>
#include <comedilib.h>
#include <ctype.h>
#include <errno.h>
#include "examples.h"
#include <fcntl.h>
#include <malloc.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define BUF_LEN 0x1000
struct test_waveform_generator
{
unsigned *toggle_countdowns;
unsigned num_channels;
lsampl_t last_output;
};
int init_test_waveform_generator(struct test_waveform_generator *generator, unsigned num_channels)
{
unsigned i;
generator->num_channels = num_channels;
generator->toggle_countdowns = malloc(sizeof(unsigned) * num_channels);
if(generator->toggle_countdowns == NULL) return -ENOMEM;
for(i = 0; i < num_channels; ++i)
generator->toggle_countdowns[i] = i + 1;
generator->last_output = 0;
return 0;
}
void cleanup_test_waveform_generator(struct test_waveform_generator *generator)
{
if(generator->toggle_countdowns)
{
free(generator->toggle_countdowns);
generator->toggle_countdowns = NULL;
}
}
void build_waveforms(struct test_waveform_generator *generator, lsampl_t *data, unsigned data_len)
{
unsigned i;
for(i = 0; i < data_len; ++i)
{
unsigned j;
data[i] = generator->last_output;
for(j = 0; j < generator->num_channels; ++j)
{
if(--generator->toggle_countdowns[j] == 0)
{
generator->toggle_countdowns[j] = j + 1;
data[i] ^= 1 << j;
}
}
generator->last_output = data[i];
}
}
int main(int argc, char *argv[])
{
comedi_cmd cmd;
struct parsed_options options;
comedi_t *dev;
int i;
struct test_waveform_generator generator;
lsampl_t *buffer = NULL;
int err;
int n, m;
int total=0;
unsigned int *chanlist;
int ret;
init_parsed_options(&options);
options.subdevice = -1;
options.n_chan = 8;
options.value = NI_CDIO_SCAN_BEGIN_SRC_G0_OUT;
parse_options(&options, argc, argv);
dev = comedi_open(options.filename);
if(dev == NULL){
fprintf(stderr, "error opening %s\n", options.filename);
return -1;
}
if(options.subdevice < 0)
options.subdevice = comedi_find_subdevice_by_type(dev, COMEDI_SUBD_DIO, 0);
memset(&cmd,0,sizeof(cmd));
cmd.subdev = options.subdevice;
cmd.flags = CMDF_WRITE;
cmd.start_src = TRIG_INT;
cmd.start_arg = 0;
cmd.scan_begin_src = TRIG_EXT;
cmd.scan_begin_arg = options.value;
cmd.convert_src = TRIG_NOW;
cmd.convert_arg = 0;
cmd.scan_end_src = TRIG_COUNT;
cmd.scan_end_arg = options.n_chan;
cmd.stop_src = TRIG_NONE;
cmd.stop_arg = 0;
chanlist = malloc(options.n_chan * sizeof(unsigned));
assert(chanlist);
cmd.chanlist = chanlist;
cmd.chanlist_len = options.n_chan;
for(i = 0; i < cmd.chanlist_len; ++i)
{
cmd.chanlist[i] = i;
}
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);
}
err = comedi_command_test(dev, &cmd);
if(err != 0) {
fprintf(stderr, "After 3 passes, comedi_command_test returns %i\n", err);
exit(1);
}
if ((err = comedi_command(dev, &cmd)) < 0) {
comedi_perror("comedi_command");
exit(1);
}
ret = init_test_waveform_generator(&generator, cmd.chanlist_len);
assert(ret == 0);
buffer = malloc(sizeof(lsampl_t) * BUF_LEN);
assert(buffer);
build_waveforms(&generator, buffer, BUF_LEN);
n = BUF_LEN * sizeof(buffer[0]);
m = write(comedi_fileno(dev), buffer, 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, options.subdevice, 0);
if(ret < 0){
perror("comedi_internal_trigger\n");
exit(1);
}
while(1)
{
build_waveforms(&generator, buffer, BUF_LEN);
n = BUF_LEN * sizeof(buffer[0]);
while(n > 0)
{
m = write(comedi_fileno(dev), (void*)(buffer) + (BUF_LEN * sizeof(buffer[0]) - n), n);
if(m < 0){
perror("write");
exit(0);
}
printf("m=%d\n",m);
n -= m;
}
total += BUF_LEN;
//printf("%d\n",total);
}
cleanup_test_waveform_generator(&generator);
free(buffer);
free(chanlist);
return 0;
}
|