Added new gpct_simple_counting demo (shares some code with
authorFrank Mori Hess <fmhess@speakeasy.net>
Mon, 8 Jan 2007 21:53:59 +0000 (21:53 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Mon, 8 Jan 2007 21:53:59 +0000 (21:53 +0000)
gpct_pulse_generator demo through common.c).

demo/Makefile.am
demo/README
demo/common.c
demo/examples.h
demo/gpct_pulse_generator.c
demo/gpct_simple_counting.c [new file with mode: 0644]

index 33b1a6f1975557bd0311bc757829d743e12ca4bc..5f7e151d5b6bc0e7f0b2c568e2af6a65c9e09b3b 100644 (file)
@@ -2,7 +2,8 @@
 noinst_PROGRAMS = \
        antialias ao_waveform ao_mmap apply_cal board_info choose_clock \
        choose_routing cmd dio eeprom_dump gpct_pulse_generator \
-       inp inpn insn ledclock mmap outp poll receiver select \
+       gpct_simple_counting inp inpn insn ledclock \
+       mmap outp poll receiver select \
        sender sigio sv tut1 tut2
 
 noinst_HEADERS = examples.h
@@ -51,6 +52,10 @@ gpct_pulse_generator_SOURCES = gpct_pulse_generator.c common.c
 gpct_pulse_generator_CFLAGS = $(COMEDILIB_CFLAGS)
 gpct_pulse_generator_LDADD = $(COMEDILIB_LIBS)
 
+gpct_simple_counting_SOURCES = gpct_simple_counting.c common.c
+gpct_simple_counting_CFLAGS = $(COMEDILIB_CFLAGS)
+gpct_simple_counting_LDADD = $(COMEDILIB_LIBS)
+
 inp_SOURCES = inp.c common.c
 inp_CFLAGS = $(COMEDILIB_CFLAGS)
 inp_LDADD = $(COMEDILIB_LIBS)
index 4bc64dbed5d327c01f3fdea039a3275cc5e63768..f709fb94f4973a16e6c103230d480dff86d3b7f8 100644 (file)
@@ -69,7 +69,7 @@ eeprom_dump:
        devices/drivers.
 
 gpct_pulse_generator:
-       Causes an NI general-purpose counter subdevice to produce a
+       Configures a NI general-purpose counter subdevice to produce a
        continuous train of pulses on its output.  The -F option specifies
        the pulse period (as a frequency in Hertz), and the argument specifies
        the pulse width (in nanoseconds).  By default, the pulse width will
@@ -78,6 +78,12 @@ gpct_pulse_generator:
        an output line that you can observe (for instance one of the PFI
        lines).
 
+gpct_simple_counting:
+       Configures a NI general-purpose counter subdevice to act as a
+       simple event counter.  You can select the input to the counter
+       using the "choose_clock" demo.  The counter's value can be read
+       out using the "inp" demo.
+
 inp:
        Simple input:  Reads one sample from one channel on one subdevice.
 
index c22470ba4be44123135bd093fe6298c5f81825ec..8be9fc7cd254e3e74e7cc0e5b4fef2836f5c63f5 100644 (file)
@@ -140,3 +140,130 @@ void dump_cmd(FILE *out,comedi_cmd *cmd)
                cmd->stop_arg);
 }
 
+int arm(comedi_t *device, unsigned subdevice, lsampl_t source)
+{
+       comedi_insn insn;
+       lsampl_t data[2];
+       int retval;
+
+       memset(&insn, 0, sizeof(comedi_insn));
+       insn.insn = INSN_CONFIG;
+       insn.subdev = subdevice;
+       insn.chanspec = 0;
+       insn.data = data;
+       insn.n = sizeof(data) / sizeof(data[0]);
+       data[0] = INSN_CONFIG_ARM;
+       data[1] = source;
+
+       retval = comedi_do_insn(device, &insn);
+       if(retval < 0)
+       {
+               fprintf(stderr, "%s: error:\n", __FUNCTION__);
+               comedi_perror("comedi_do_insn");
+               return retval;
+       }
+       return 0;
+}
+
+/* This resets the count to zero and disarms the counter.  The counter output
+ is set low. */
+int reset_counter(comedi_t *device, unsigned subdevice)
+{
+       comedi_insn insn;
+       lsampl_t data[1];
+       int retval;
+
+       memset(&insn, 0, sizeof(comedi_insn));
+       insn.insn = INSN_CONFIG;
+       insn.subdev = subdevice;
+       insn.chanspec = 0;
+       insn.data = data;
+       insn.n = sizeof(data) / sizeof(data[0]);
+       data[0] = INSN_CONFIG_RESET;
+
+       retval = comedi_do_insn(device, &insn);
+       if(retval < 0)
+       {
+               fprintf(stderr, "%s: error:\n", __FUNCTION__);
+               comedi_perror("comedi_do_insn");
+               return retval;
+       }
+       return 0;
+}
+
+int set_counter_mode(comedi_t *device, unsigned subdevice, lsampl_t mode_bits)
+{
+       comedi_insn insn;
+       lsampl_t data[2];
+       int retval;
+
+       memset(&insn, 0, sizeof(comedi_insn));
+       insn.insn = INSN_CONFIG;
+       insn.subdev = subdevice;
+       insn.chanspec = 0;
+       insn.data = data;
+       insn.n = sizeof(data) / sizeof(data[0]);
+       data[0] = INSN_CONFIG_SET_COUNTER_MODE;
+       data[1] = mode_bits;
+
+       retval = comedi_do_insn(device, &insn);
+       if(retval < 0)
+       {
+               fprintf(stderr, "%s: error:\n", __FUNCTION__);
+               comedi_perror("comedi_do_insn");
+               return retval;
+       }
+       return 0;
+}
+
+int set_clock_source(comedi_t *device, unsigned subdevice, lsampl_t clock, lsampl_t period_ns)
+{
+       comedi_insn insn;
+       lsampl_t data[3];
+       int retval;
+
+       memset(&insn, 0, sizeof(comedi_insn));
+       insn.insn = INSN_CONFIG;
+       insn.subdev = subdevice;
+       insn.chanspec = 0;
+       insn.data = data;
+       insn.n = sizeof(data) / sizeof(data[0]);
+       data[0] = INSN_CONFIG_SET_CLOCK_SRC;
+       data[1] = clock;
+       data[2] = period_ns;
+
+       retval = comedi_do_insn(device, &insn);
+       if(retval < 0)
+       {
+               fprintf(stderr, "%s: error:\n", __FUNCTION__);
+               comedi_perror("comedi_do_insn");
+               return retval;
+       }
+       return 0;
+}
+
+int set_gate_source(comedi_t *device, unsigned subdevice, lsampl_t gate_index, lsampl_t gate_source)
+{
+       comedi_insn insn;
+       lsampl_t data[3];
+       int retval;
+
+       memset(&insn, 0, sizeof(comedi_insn));
+       insn.insn = INSN_CONFIG;
+       insn.subdev = subdevice;
+       insn.chanspec = 0;
+       insn.data = data;
+       insn.n = sizeof(data) / sizeof(data[0]);
+       data[0] = INSN_CONFIG_SET_GATE_SRC;
+       data[1] = gate_index;
+       data[2] = gate_source;
+
+       retval = comedi_do_insn(device, &insn);
+       if(retval < 0)
+       {
+               fprintf(stderr, "%s: error:\n", __FUNCTION__);
+               comedi_perror("comedi_do_insn");
+               return retval;
+       }
+       return 0;
+}
index 37bd87e58269657766c9a375ceb84f8dd432f0e0..5c505848cf252fe3ba7c08d469989a2d96d783be 100644 (file)
@@ -29,7 +29,12 @@ extern void init_parsed_options(struct parsed_options *options);
 extern int parse_options(struct parsed_options *options, int argc, char *argv[]);
 extern char *cmd_src(int src,char *buf);
 extern void dump_cmd(FILE *file,comedi_cmd *cmd);
-
+/* some helper functions used primarily for counter demos */
+extern int arm(comedi_t *device, unsigned subdevice, lsampl_t source);
+extern int reset_counter(comedi_t *device, unsigned subdevice);
+extern int set_counter_mode(comedi_t *device, unsigned subdevice, lsampl_t mode_bits);
+extern int set_clock_source(comedi_t *device, unsigned subdevice, lsampl_t clock, lsampl_t period_ns);
+extern int set_gate_source(comedi_t *device, unsigned subdevice, lsampl_t gate_index, lsampl_t gate_source);
 
 #define sec_to_nsec(x) ((x)*1000000000)
 #define sec_to_usec(x) ((x)*1000000)
index 15099aaa27936d53a5aad764e8362c208ce9c860..4840553e0477dfbcd4eb4d9e3a7036487513e2a6 100644 (file)
 #include <ctype.h>
 #include "examples.h"
 
-/*FIXME: move helper functions to common.c so they can be used on other (mostly counter) examples*/
-
-int arm(comedi_t *device, unsigned subdevice, lsampl_t source)
-{
-       comedi_insn insn;
-       lsampl_t data[2];
-       int retval;
-
-       memset(&insn, 0, sizeof(comedi_insn));
-       insn.insn = INSN_CONFIG;
-       insn.subdev = subdevice;
-       insn.chanspec = 0;
-       insn.data = data;
-       insn.n = sizeof(data) / sizeof(data[0]);
-       data[0] = INSN_CONFIG_ARM;
-       data[1] = source;
-
-       retval = comedi_do_insn(device, &insn);
-       if(retval < 0)
-       {
-               fprintf(stderr, "%s: error:\n", __FUNCTION__);
-               comedi_perror("comedi_do_insn");
-               return retval;
-       }
-       return 0;
-}
-
-/* This resets the count to zero and disarms the counter.  The counter output
- is set low. */
-int reset_counter(comedi_t *device, unsigned subdevice)
-{
-       comedi_insn insn;
-       lsampl_t data[1];
-       int retval;
-
-       memset(&insn, 0, sizeof(comedi_insn));
-       insn.insn = INSN_CONFIG;
-       insn.subdev = subdevice;
-       insn.chanspec = 0;
-       insn.data = data;
-       insn.n = sizeof(data) / sizeof(data[0]);
-       data[0] = INSN_CONFIG_RESET;
-
-       retval = comedi_do_insn(device, &insn);
-       if(retval < 0)
-       {
-               fprintf(stderr, "%s: error:\n", __FUNCTION__);
-               comedi_perror("comedi_do_insn");
-               return retval;
-       }
-       return 0;
-}
-
-int set_counter_mode(comedi_t *device, unsigned subdevice, lsampl_t mode_bits)
-{
-       comedi_insn insn;
-       lsampl_t data[2];
-       int retval;
-
-       memset(&insn, 0, sizeof(comedi_insn));
-       insn.insn = INSN_CONFIG;
-       insn.subdev = subdevice;
-       insn.chanspec = 0;
-       insn.data = data;
-       insn.n = sizeof(data) / sizeof(data[0]);
-       data[0] = INSN_CONFIG_SET_COUNTER_MODE;
-       data[1] = mode_bits;
-
-       retval = comedi_do_insn(device, &insn);
-       if(retval < 0)
-       {
-               fprintf(stderr, "%s: error:\n", __FUNCTION__);
-               comedi_perror("comedi_do_insn");
-               return retval;
-       }
-       return 0;
-}
-
-int set_clock_source(comedi_t *device, unsigned subdevice, lsampl_t clock, lsampl_t period_ns)
-{
-       comedi_insn insn;
-       lsampl_t data[3];
-       int retval;
-
-       memset(&insn, 0, sizeof(comedi_insn));
-       insn.insn = INSN_CONFIG;
-       insn.subdev = subdevice;
-       insn.chanspec = 0;
-       insn.data = data;
-       insn.n = sizeof(data) / sizeof(data[0]);
-       data[0] = INSN_CONFIG_SET_CLOCK_SRC;
-       data[1] = clock;
-       data[2] = period_ns;
-
-       retval = comedi_do_insn(device, &insn);
-       if(retval < 0)
-       {
-               fprintf(stderr, "%s: error:\n", __FUNCTION__);
-               comedi_perror("comedi_do_insn");
-               return retval;
-       }
-       return 0;
-}
-
-int set_gate_source(comedi_t *device, unsigned subdevice, lsampl_t gate_index, lsampl_t gate_source)
-{
-       comedi_insn insn;
-       lsampl_t data[3];
-       int retval;
-
-       memset(&insn, 0, sizeof(comedi_insn));
-       insn.insn = INSN_CONFIG;
-       insn.subdev = subdevice;
-       insn.chanspec = 0;
-       insn.data = data;
-       insn.n = sizeof(data) / sizeof(data[0]);
-       data[0] = INSN_CONFIG_SET_GATE_SRC;
-       data[1] = gate_index;
-       data[2] = gate_source;
-
-       retval = comedi_do_insn(device, &insn);
-       if(retval < 0)
-       {
-               fprintf(stderr, "%s: error:\n", __FUNCTION__);
-               comedi_perror("comedi_do_insn");
-               return retval;
-       }
-       return 0;
-}
 
 int ni_gpct_start_pulse_generator(comedi_t *device, unsigned subdevice, unsigned period_ns, unsigned up_time_ns)
 {
@@ -169,10 +40,7 @@ int ni_gpct_start_pulse_generator(comedi_t *device, unsigned subdevice, unsigned
        lsampl_t counter_mode;
        const unsigned clock_period_ns = 50;    /* 20MHz clock */
        unsigned up_ticks, down_ticks;
-/*
-FIXME:
-How is output initialized to known state for toggling (reset?)
-*/
+
        retval = reset_counter(device, subdevice);
        if(retval < 0) return retval;
 
@@ -196,6 +64,10 @@ How is output initialized to known state for toggling (reset?)
        counter_mode |= NI_GPCT_COUNTING_DIRECTION_DOWN_BITS;
        // initialize load source as load b register
        counter_mode |= NI_GPCT_LOAD_B_SELECT_BIT;
+       // don't stop on terminal count
+       counter_mode |= NI_GPCT_STOP_ON_GATE_BITS;
+       // don't disarm on terminal count or gate signal
+       counter_mode |= NI_GPCT_NO_HARDWARE_DISARM_BITS;
        retval = set_counter_mode(device, subdevice, counter_mode);
        if(retval < 0) return retval;
 
diff --git a/demo/gpct_simple_counting.c b/demo/gpct_simple_counting.c
new file mode 100644 (file)
index 0000000..a8fe244
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * NI general-purpose counter example.  Configures the counter to
+ * start simple event counting.  The counter's value can be read
+ * with the inp demo.  Different clock sources can be chosen
+ * with the choose_clock demo.
+ * Part of Comedilib
+ *
+ * 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:  A board with a National Instruments general-purpose
+ * counter, and comedi driver version 0.7.74 or newer.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <comedilib.h>
+#include <math.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <ctype.h>
+#include "examples.h"
+
+int ni_gpct_start_simple_event_counting(comedi_t *device, unsigned subdevice, unsigned period_ns, unsigned up_time_ns)
+{
+       int retval;
+       lsampl_t counter_mode;
+
+       retval = reset_counter(device, subdevice);
+       if(retval < 0) return retval;
+
+       retval = set_gate_source(device, subdevice, 0, NI_GPCT_DISABLED_GATE_SELECT | CR_EDGE);
+       if(retval < 0) return retval;
+       retval = set_gate_source(device, subdevice, 1, NI_GPCT_DISABLED_GATE_SELECT | CR_EDGE);
+       if(retval < 0)
+       {
+               fprintf(stderr, "Failed to set second gate source.  This is expected for older boards (e-series, etc.)\n"
+                       "that don't have a second gate.\n");
+       }
+
+       counter_mode = NI_GPCT_COUNTING_MODE_NORMAL_BITS;
+       // output pulse on terminal count (doesn't really matter for this application)
+       counter_mode |= NI_GPCT_OUTPUT_TC_PULSE_BITS;
+       /* Don't alternate the reload source between the load a and load b registers.
+               Doesn't really matter here, since we aren't going to be reloading the counter.
+       */
+       counter_mode |= NI_GPCT_RELOAD_SOURCE_FIXED_BITS;
+       // count up
+       counter_mode |= NI_GPCT_COUNTING_DIRECTION_UP_BITS;
+       // don't stop on terminal count
+       counter_mode |= NI_GPCT_STOP_ON_GATE_BITS;
+       // don't disarm on terminal count or gate signal
+       counter_mode |= NI_GPCT_NO_HARDWARE_DISARM_BITS;
+       retval = set_counter_mode(device, subdevice, counter_mode);
+       if(retval < 0) return retval;
+
+       retval = arm(device, subdevice, NI_GPCT_ARM_IMMEDIATE);
+       if(retval < 0) return retval;
+
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       comedi_t *device;
+       unsigned up_time;
+       unsigned period_ns;
+       int retval;
+       struct parsed_options options;
+
+       init_parsed_options(&options);
+       options.value = -1.;
+       parse_options(&options, argc, argv);
+       period_ns = lrint(1e9 / options.freq);
+       if(options.value < 0.)
+               up_time = period_ns / 2;
+       else
+               up_time = lrint(options.value);
+       device = comedi_open(options.filename);
+       if(!device)
+       {
+               comedi_perror(options.filename);
+               exit(-1);
+       }
+       /*FIXME: check that device is counter */
+       printf("Initiating simple event counting on subdevice %d.\n", options.subdevice);
+
+       retval = ni_gpct_start_simple_event_counting(device, options.subdevice, period_ns, up_time);
+       if(retval < 0) return retval;
+       return 0;
+}
+