From: Frank Mori Hess Date: Mon, 8 Jan 2007 21:53:59 +0000 (+0000) Subject: Added new gpct_simple_counting demo (shares some code with X-Git-Tag: v0_8_0~37 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=6a0fc4a5e50f8538df4b1aefd6657dc17eda425c;p=comedilib.git Added new gpct_simple_counting demo (shares some code with gpct_pulse_generator demo through common.c). --- diff --git a/demo/Makefile.am b/demo/Makefile.am index 33b1a6f..5f7e151 100644 --- a/demo/Makefile.am +++ b/demo/Makefile.am @@ -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) diff --git a/demo/README b/demo/README index 4bc64db..f709fb9 100644 --- a/demo/README +++ b/demo/README @@ -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. diff --git a/demo/common.c b/demo/common.c index c22470b..8be9fc7 100644 --- a/demo/common.c +++ b/demo/common.c @@ -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; +} diff --git a/demo/examples.h b/demo/examples.h index 37bd87e..5c50584 100644 --- a/demo/examples.h +++ b/demo/examples.h @@ -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) diff --git a/demo/gpct_pulse_generator.c b/demo/gpct_pulse_generator.c index 15099aa..4840553 100644 --- a/demo/gpct_pulse_generator.c +++ b/demo/gpct_pulse_generator.c @@ -33,135 +33,6 @@ #include #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 index 0000000..a8fe244 --- /dev/null +++ b/demo/gpct_simple_counting.c @@ -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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} +