Added digital output command demo.
authorFrank Mori Hess <fmhess@speakeasy.net>
Mon, 13 Aug 2007 21:21:39 +0000 (21:21 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Mon, 13 Aug 2007 21:21:39 +0000 (21:21 +0000)
demo/Makefile.am
demo/do_waveform.c [new file with mode: 0644]

index b770e700c13f28814cebf11e802fd387190d456a..676542081034a88b523384c393768f77cde01a13 100644 (file)
@@ -1,7 +1,7 @@
 
 noinst_PROGRAMS = \
        antialias ao_waveform ao_mmap apply_cal board_info choose_clock choose_filter \
-       choose_routing cmd dio eeprom_dump gpct_buffered_counting \
+       choose_routing cmd do_waveform dio eeprom_dump gpct_buffered_counting \
        gpct_encoder gpct_pulse_generator \
        gpct_simple_counting inp inpn insn ledclock \
        mmap outp poll receiver select \
@@ -49,6 +49,10 @@ dio_SOURCES = dio.c common.c
 dio_CFLAGS = $(COMEDILIB_CFLAGS)
 dio_LDADD = $(COMEDILIB_LIBS)
 
+do_waveform_SOURCES = do_waveform.c common.c
+do_waveform_CFLAGS = $(COMEDILIB_CFLAGS)
+do_waveform_LDADD = $(COMEDILIB_LIBS)
+
 eeprom_dump_SOURCES = eeprom_dump.c common.c
 eeprom_dump_CFLAGS = $(COMEDILIB_CFLAGS)
 eeprom_dump_LDADD = $(COMEDILIB_LIBS)
diff --git a/demo/do_waveform.c b/demo/do_waveform.c
new file mode 100644 (file)
index 0000000..1af25e1
--- /dev/null
@@ -0,0 +1,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;
+}