From: Frank Mori Hess Date: Thu, 28 Jun 2007 01:22:38 +0000 (+0000) Subject: Demo program for quadrature encoder counting with NI GPCT, from X-Git-Tag: v0_8_0~28 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=9804a8c81dda128683d9feba6130c52fee071267;p=comedilib.git Demo program for quadrature encoder counting with NI GPCT, from Anders Blomdell --- diff --git a/demo/Makefile.am b/demo/Makefile.am index 5f7e151..9e61fee 100644 --- a/demo/Makefile.am +++ b/demo/Makefile.am @@ -1,7 +1,7 @@ noinst_PROGRAMS = \ antialias ao_waveform ao_mmap apply_cal board_info choose_clock \ - choose_routing cmd dio eeprom_dump gpct_pulse_generator \ + choose_routing cmd dio eeprom_dump gpct_encoder gpct_pulse_generator \ gpct_simple_counting inp inpn insn ledclock \ mmap outp poll receiver select \ sender sigio sv tut1 tut2 @@ -48,6 +48,10 @@ eeprom_dump_SOURCES = eeprom_dump.c common.c eeprom_dump_CFLAGS = $(COMEDILIB_CFLAGS) eeprom_dump_LDADD = $(COMEDILIB_LIBS) +gpct_encoder_SOURCES = gpct_encoder.c common.c +gpct_encoder_CFLAGS = $(COMEDILIB_CFLAGS) +gpct_encoder_LDADD = $(COMEDILIB_LIBS) + gpct_pulse_generator_SOURCES = gpct_pulse_generator.c common.c gpct_pulse_generator_CFLAGS = $(COMEDILIB_CFLAGS) gpct_pulse_generator_LDADD = $(COMEDILIB_LIBS) diff --git a/demo/gpct_encoder.c b/demo/gpct_encoder.c new file mode 100644 index 0000000..ad55784 --- /dev/null +++ b/demo/gpct_encoder.c @@ -0,0 +1,149 @@ +/* + * NI quadrature encoder example. + * Part of Comedilib + * + * Copyright (c) 2007 Anders Blomdell + * + * 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 set_source(comedi_t *device, unsigned subdevice, + lsampl_t index, lsampl_t 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_OTHER_SRC; + data[1] = index; + data[2] = 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_encoder(comedi_t *device, unsigned subdevice, + unsigned int initial_value, + int a, int b, int z) +{ + int retval; + lsampl_t counter_mode; + + + retval = reset_counter(device, subdevice); + /* set initial counter value by writing to channel 0 */ + retval = comedi_data_write(device, subdevice, 0, 0, 0, initial_value); + /* set "load a" register to initial_value by writing to channel 1 */ + retval = comedi_data_write(device, subdevice, 1, 0, 0, initial_value); + /* set "load b" register to initial_value by writing to channel 2 */ + retval = comedi_data_write(device, subdevice, 2, 0, 0, initial_value); + + set_gate_source(device, subdevice, 0, NI_GPCT_DISABLED_GATE_SELECT); + set_gate_source(device, subdevice, 1, NI_GPCT_DISABLED_GATE_SELECT); + set_source(device, subdevice, NI_GPCT_SOURCE_ENCODER_A, a); + set_source(device, subdevice, NI_GPCT_SOURCE_ENCODER_B, b); + set_source(device, subdevice, NI_GPCT_SOURCE_ENCODER_Z, z); + + counter_mode = (NI_GPCT_COUNTING_MODE_QUADRATURE_X4_BITS | + NI_GPCT_COUNTING_DIRECTION_HW_UP_DOWN_BITS); + if (z != NI_GPCT_DISABLED_GATE_SELECT) { + counter_mode |= (NI_GPCT_INDEX_ENABLE_BIT | + NI_GPCT_INDEX_PHASE_HIGH_A_HIGH_B_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 = NULL; + int subdevice = -1; + int a = NI_GPCT_DISABLED_OTHER_SELECT; + int b = NI_GPCT_DISABLED_OTHER_SELECT; + int z = NI_GPCT_DISABLED_OTHER_SELECT; + unsigned int initial_value = 0; + int retval; + + struct parsed_options options; + { + int c; + while (-1 != (c = getopt(argc, argv, "f:s:A:B:Z:I:"))) { + switch (c) { + case 'f': + device = comedi_open(optarg); + if(!device) { + comedi_perror(optarg); + exit(-1); + } + break; + case 's': + subdevice = strtoul(optarg, NULL, 0); + break; + case 'A': + /* TODO: Should we pass the value directly, i.e. could anybody + * be interested in values besides PFIx/DISABLED */ + a = NI_GPCT_PFI_OTHER_SELECT(strtoul(optarg, NULL, 0)); + break; + case 'B': + /* TODO: Should we pass the value directly, i.e. could anybody + * be interested in values besides PFIx/DISABLED */ + b = NI_GPCT_PFI_OTHER_SELECT(strtoul(optarg, NULL, 0)); + break; + case 'Z': + /* TODO: Should we pass the value directly, i.e. could anybody + * be interested in values besides PFIx/DISABLED */ + z = NI_GPCT_PFI_OTHER_SELECT(strtoul(optarg, NULL, 0)); + break; + case 'I': + initial_value = strtoul(optarg, NULL, 0); + break; + } + } + } + + /*FIXME: check that device is counter */ + printf("Initiating encoder on subdevice %d.\n", subdevice); + + retval = ni_gpct_start_encoder(device, subdevice, initial_value, a, b, z); + + if(retval < 0) return retval; + + return 0; +} diff --git a/include/comedi.h b/include/comedi.h index c4b31c1..7014fc4 100644 --- a/include/comedi.h +++ b/include/comedi.h @@ -250,6 +250,8 @@ enum configuration_ids INSN_CONFIG_GET_GATE_SRC = 2002, // Get gate source INSN_CONFIG_SET_CLOCK_SRC = 2003, // Set master clock source INSN_CONFIG_GET_CLOCK_SRC = 2004, // Get master clock source + INSN_CONFIG_SET_OTHER_SRC = 2005, // Set other source +// INSN_CONFIG_GET_OTHER_SRC = 2006, // Get other source INSN_CONFIG_SET_COUNTER_MODE = 4097, INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE, /* deprecated */ INSN_CONFIG_8254_READ_STATUS = 4098, @@ -643,6 +645,32 @@ static inline unsigned NI_GPCT_UP_DOWN_PIN_GATE_SELECT(unsigned n) return 0x202 + n; } +/* Possibilities for setting a source with +INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. */ +enum ni_gpct_other_index { + NI_GPCT_SOURCE_ENCODER_A, + NI_GPCT_SOURCE_ENCODER_B, + NI_GPCT_SOURCE_ENCODER_Z +}; +enum ni_gpct_other_select +{ + /* m-series gates */ + // Still unknown, probably only need NI_GPCT_PFI_OTHER_SELECT + NI_GPCT_DISABLED_OTHER_SELECT = 0x8000, +}; +static inline unsigned NI_GPCT_PFI_OTHER_SELECT(unsigned n) +{ + if (n < 10) { + return 0x1 + n; + } else if (n < 16) { + return 0xb + n; + } else { + // Really should report this error somehow + return NI_GPCT_DISABLED_OTHER_SELECT; + } +} + + /* start sources for ni general-purpose counters for use with INSN_CONFIG_ARM */ enum ni_gpct_arm_source