gpct_pulse_generator demo through common.c).
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
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)
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
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.
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;
+}
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)
#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)
{
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;
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;
--- /dev/null
+/*
+ * 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;
+}
+