- From: Anders Blomdell <anders.blomdell_at_control.lth.se>
- Date: Wed, 27 Jun 2007 12:15:52 +0200
Frank Mori Hess wrote: > I'd prefer you add a different insn_config id, since the a/b/z inputs > aren't really gates. I'd go with a generic configure source, like > INSN_CONFIG_SET_SOURCE that is otherwise similar to > INSN_CONFIG_SET_GATE_SRC, that can be used as a catch-all for configuring > sources for things other than gates (or clocks). Done: INSN_CONFIG_SET_OTHER_SRC > Also, you should define > a new enum + inline functions for the possible a/b/z sources, even if they > are mostly the same as the gate sources, especially since other than the > PFI pins they are unknown (right?). Done > Your demo should use the same command line options as the other demos, as > far as possible, and not conflict with them (the -a option). getopt(..., "f:s:A:B:Z:I:") > Probably the > easiest way to handle the generic options would be to split > a "parse_option" function you could use out of the inside of the while > loop in "parse_options" in demo/common.c. I'll pass that to someone else :-) > It would be nice if your demo explicitly set the index phase bits to > something, just so it's clear to the reader that its something they might > need to think about. Done Patches attached. Regards Anders Blomdell -- Anders Blomdell Email: anders.blomdell_at_control.lth.se Department of Automatic Control Lund University Phone: +46 46 222 4625 P.O. Box 118 Fax: +46 46 138118 SE-221 00 Lund, Sweden
/*
* NI quadrature encoder example.
* Part of Comedilib
*
* Copyright (c) 2007 Anders Blomdell <anders.blomdell_at_control.lth.se>
*
* 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 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;
}
Index: comedi/comedi_fops.c
===================================================================
RCS file: /cvs/comedi/comedi/comedi/comedi_fops.c,v
retrieving revision 1.186
diff -u -b -r1.186 comedi_fops.c
--- comedi/comedi_fops.c 1 May 2007 21:16:15 -0000 1.186
+++ comedi/comedi_fops.c 27 Jun 2007 10:13:37 -0000
_at__at_ -638,6 +638,7 _at__at_
case INSN_CONFIG_GET_GATE_SRC:
case INSN_CONFIG_SET_CLOCK_SRC:
case INSN_CONFIG_GET_CLOCK_SRC:
+ case INSN_CONFIG_SET_OTHER_SRC:
case INSN_CONFIG_GET_COUNTER_STATUS:
if(insn->n == 3) return 0;
break;
Index: comedi/drivers/ni_mio_common.c
===================================================================
RCS file: /cvs/comedi/comedi/comedi/drivers/ni_mio_common.c,v
retrieving revision 1.299
diff -u -b -r1.299 ni_mio_common.c
--- comedi/drivers/ni_mio_common.c 8 May 2007 14:28:21 -0000 1.299
+++ comedi/drivers/ni_mio_common.c 27 Jun 2007 10:13:38 -0000
_at__at_ -3313,6 +3313,13 _at__at_
case NITIO_G1_Second_Gate_Reg:
ni_writew(bits, M_Offset_G1_Second_Gate);
break;
+ case NITIO_G0_ABZ_Reg:
+ ni_writew(bits, M_Offset_G0_MSeries_ABZ);
+ break;
+ case NITIO_G1_ABZ_Reg:
+ ni_writew(bits, M_Offset_G1_MSeries_ABZ);
+ break;
+
/* 32 bit registers */
case NITIO_G0_LoadA_Reg:
case NITIO_G1_LoadA_Reg:
Index: comedi/drivers/ni_tio.c
===================================================================
RCS file: /cvs/comedi/comedi/comedi/drivers/ni_tio.c,v
retrieving revision 1.14
diff -u -b -r1.14 ni_tio.c
--- comedi/drivers/ni_tio.c 26 Apr 2007 17:43:44 -0000 1.14
+++ comedi/drivers/ni_tio.c 27 Jun 2007 10:13:39 -0000
_at__at_ -322,6 +322,23 _at__at_
return 0;
}
+static inline enum ni_gpct_register NITIO_Gi_ABZ_Reg(int counter_index)
+{
+ switch(counter_index)
+ {
+ case 0:
+ return NITIO_G0_ABZ_Reg;
+ break;
+ case 1:
+ return NITIO_G1_ABZ_Reg;
+ break;
+ default:
+ BUG();
+ break;
+ }
+ return 0;
+}
+
enum Gi_Auto_Increment_Reg_Bits
{
Gi_Auto_Increment_Mask = 0xff
_at__at_ -1607,6 +1624,41 _at__at_
return 0;
}
+static int ni_tio_set_other_src(struct ni_gpct *counter,
+ unsigned index, lsampl_t source)
+{
+ if (counter->variant == ni_gpct_variant_m_series &&
+ (index == NI_GPCT_SOURCE_ENCODER_A ||
+ index == NI_GPCT_SOURCE_ENCODER_B ||
+ index == NI_GPCT_SOURCE_ENCODER_Z)) {
+ unsigned int abz_reg, shift, mask;
+ abz_reg = NITIO_Gi_ABZ_Reg(counter->counter_index);
+
+ switch(index) {
+ case NI_GPCT_SOURCE_ENCODER_A:
+ shift = 10;
+ break;
+ case NI_GPCT_SOURCE_ENCODER_B:
+ shift = 5;
+ break;
+ case NI_GPCT_SOURCE_ENCODER_Z:
+ shift = 0;
+ break;
+ }
+ mask = 0x1f << shift;
+ if (source > 0x1f) {
+ /* Disable gate */
+ source = 0x1f;
+ }
+ counter->regs[abz_reg] &= ~mask;
+ counter->regs[abz_reg] |= source << shift;
+ counter->write_register(counter, counter->regs[abz_reg], abz_reg);
+ printk("%s %x %d %d\n", __FUNCTION__, counter->regs[abz_reg], index, source);
+ return 0;
+ }
+ return -EINVAL;
+}
+
static unsigned ni_660x_first_gate_to_generic_gate_source(unsigned ni_660x_gate_select)
{
unsigned i;
_at__at_ -1875,6 +1927,9 _at__at_
case INSN_CONFIG_GET_GATE_SRC:
return ni_tio_get_gate_src(counter, data[1], &data[2]);
break;
+ case INSN_CONFIG_SET_OTHER_SRC:
+ return ni_tio_set_other_src(counter, data[1], data[2]);
+ break;
case INSN_CONFIG_RESET:
ni_tio_reset_count_and_disarm(counter);
return 0;
Index: comedi/drivers/ni_tio.h
===================================================================
RCS file: /cvs/comedi/comedi/comedi/drivers/ni_tio.h,v
retrieving revision 1.6
diff -u -b -r1.6 ni_tio.h
--- comedi/drivers/ni_tio.h 26 Apr 2007 17:43:44 -0000 1.6
+++ comedi/drivers/ni_tio.h 27 Jun 2007 10:13:39 -0000
_at__at_ -86,6 +86,8 _at__at_
NITIO_G1_DMA_Status_Reg,
NITIO_G2_DMA_Status_Reg,
NITIO_G3_DMA_Status_Reg,
+ NITIO_G0_ABZ_Reg,
+ NITIO_G1_ABZ_Reg,
NITIO_Num_Registers,
};
Index: include/linux/comedi.h
===================================================================
RCS file: /cvs/comedi/comedi/include/linux/comedi.h,v
retrieving revision 1.69
diff -u -b -r1.69 comedi.h
--- include/linux/comedi.h 26 Feb 2007 17:23:50 -0000 1.69
+++ include/linux/comedi.h 27 Jun 2007 10:13:39 -0000
_at__at_ -250,6 +250,8 _at__at_
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,
_at__at_ -643,6 +645,32 _at__at_
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
Index: demo/Makefile.am
===================================================================
RCS file: /cvs/comedi/comedilib/demo/Makefile.am,v
retrieving revision 1.7
diff -u -r1.7 Makefile.am
--- demo/Makefile.am 8 Jan 2007 21:53:59 -0000 1.7
+++ demo/Makefile.am 27 Jun 2007 10:11:55 -0000
_at__at_ -1,7 +1,7 _at__at_
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
_at__at_ -48,6 +48,10 _at__at_
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)
Index: include/comedi.h
===================================================================
RCS file: /cvs/comedi/comedilib/include/comedi.h,v
retrieving revision 1.38
diff -u -r1.38 comedi.h
--- include/comedi.h 26 Feb 2007 17:24:24 -0000 1.38
+++ include/comedi.h 27 Jun 2007 10:11:55 -0000
_at__at_ -250,6 +250,8 _at__at_
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,
_at__at_ -643,6 +645,32 _at__at_
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
Received on 2007-06-27Z09:15:52