Added new gpct_simple_counting demo (shares some code with

gpct_pulse_generator demo through common.c).
This commit is contained in:
Frank Mori Hess 2007-01-08 21:53:59 +00:00
parent f80c83a1d0
commit 6a0fc4a5e5
6 changed files with 252 additions and 136 deletions

View 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)

View 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.

View 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;
}

View 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)

View file

@ -33,135 +33,6 @@
#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;

101
demo/gpct_simple_counting.c Normal file
View file

@ -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;
}