- From: Anders Blomdell <anders.blomdell_at_control.lth.se>
- Date: Tue, 26 Jun 2007 13:00:57 +0200
Anders Blomdell wrote:
> Anders Blomdell wrote:
>> Anders Blomdell wrote:
>>> Frank Mori Hess wrote:
>>>> On Thursday 21 June 2007 13:36, you wrote:
>>>>> I know (I'll get to it as soon as I have figured out how to use the NI
>>>>> pci-6221 with quadrature encoders).
>>>> See the enums in comedi.h, in particular enum ni_gpct_mode_bits. You'll
>>>> need to use one of the NI_GPCT_COUNTING_MODE_QUADRATURE_XN_BITS bitfields,
>>>> instead of the NI_GPCT_COUNTING_MODE_NORMAL_BITS that the simple counting
>>>> demo uses. And maybe some of the NI_GPCT_INDEX_* bits. It might actually
>>>> be useful to look at the ni 6601/6602 register level programming manual.
>>> That only partially works, what happens is that whatever
>>> NI_GPCT_COUNTING_MODE_QUADRATURE_XN_BITS is selected, the counter starts to
>>> count down on each edge on CTR{0/1}A (PFI 8/PFI 3) but remains stationary
>>> regardless of activity on CTR{0/1}B (PFI 10/PFI 11). To me this indicates that
>>> the counter is not in encoder mode, because a failure in the routing of the B
>>> signal should result in the counter changing one value only (X0 -> X1 -> X0
>>> transitions should gige one up and one down event). Direction is changed if
>>> NI_GPCT_COUNTING_DIRECTION_UP_BITS is set.
>>>
>>> Where can I find the documentation where M_Offset_G0_Counting_Mode, etc are
>>> found (the only document I have found on NI's site is "NI M Series Register Map
>>> (Preliminay)"
>> The following hack (gleaned after getting a working example in the NI
>> nimhddk_linux26/nimseries register level programming), makes it work:
>>
>> case NITIO_G0_Counting_Mode_Reg:
>> ni_writew(bits, M_Offset_G0_Counting_Mode);
>> bits = 0x26a0;
>> ni_writew(bits, M_Offset_G0_MSeries_ABZ);
>> break;
>>
>> Seems like we (I?) need to add functionality to do the equivalent of (see
>> attached NI/RLP example for context):
>>
>> board->G0_MSeries_ABZ.setG0_A_Select(9);
>> board->G0_MSeries_ABZ.setG0_B_Select(21);
>> board->G0_MSeries_ABZ.flush();
>>
>> any comments on what it should look like (or is it already there, but hidden by
>> my ignorance)?
> I have looked a little more on the comedi code. The functionality seems to be
> lacking (or I'm totally blind). Which of the following implementations is preferred:
>
> 1. Adding INSN_CONFIG_SET_ABZ_SRC, which accepts two arguments:
> index [0=A, 1=B, 2=Z]
> source [1-10=PFI0-PFI9, 21-26=PFI10-PFI15, 31=DISABLED, ...]
>
> 2. Adding INSN_CONFIG_SET_A_SRC, INSN_CONFIG_SET_B_SRC, INSN_CONFIG_SET_Z_SRC,
> which accepts 1 argument:
> source [1-10=PFI0-PFI9, 21-26=PFI10-PFI15, 31=DISABLED, ...]
>
> 3. Modify INSN_CONFIG_SET_GATE_SRC to accept
> index [2=A, 3=B, 4=Z]
> source [1-10=PFI0-PFI9, 21-26=PFI10-PFI15, 31=DISABLED, ...]
>
> 4. None of the above, please fill in a rough sketch on dotted line below:
>
> ...........................................
Selected #3 above, patches to comedi & comedilib are included. Have not got Z
signal to work, but at least A/B works (will get back if I find what is missing)...
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
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 26 Jun 2007 10:43:57 -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 26 Jun 2007 10:43:57 -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_ -1600,6 +1617,25 _at__at_
break;
}
break;
+ case 2:
+ case 3:
+ case 4:
+ if (counter->variant != ni_gpct_variant_m_series) {
+ return -EINVAL;
+ }
+ {
+ const unsigned abz_reg = NITIO_Gi_ABZ_Reg(counter->counter_index);
+ int shift = (4 - gate_index) * 5;
+ int mask = 0x1f << shift;
+ if (gate_source > 0x1f) {
+ /* Disable gate */
+ gate_source = 0x1f;
+ }
+ counter->regs[abz_reg] &= ~mask;
+ counter->regs[abz_reg] |= gate_source << shift;
+ counter->write_register(counter, counter->regs[abz_reg], abz_reg);
+ }
+ break;
default:
return -EINVAL;
break;
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 26 Jun 2007 10:43:57 -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,
};
diff -urbN comedilib.save/demo/gpct_encoder.c comedilib/demo/gpct_encoder.c
--- comedilib.save/demo/gpct_encoder.c 1970-01-01 01:00:00.000000000 +0100
+++ comedilib/demo/gpct_encoder.c 2007-06-26 12:04:32.000000000 +0200
_at__at_ -0,0 +1,110 _at__at_
+/*
+ * 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 ni_gpct_start_encoder(comedi_t *device, unsigned subdevice,
+ int a, int b, int z)
+{
+ int retval;
+ lsampl_t counter_mode;
+
+ retval = reset_counter(device, subdevice);
+
+ set_gate_source(device, subdevice, 0, NI_GPCT_DISABLED_GATE_SELECT);
+ set_gate_source(device, subdevice, 1, NI_GPCT_DISABLED_GATE_SELECT);
+ set_gate_source(device, subdevice, 2, a);
+ set_gate_source(device, subdevice, 3, b);
+ set_gate_source(device, subdevice, 4, 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;
+ }
+ 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_GATE_SELECT;
+ int b = NI_GPCT_DISABLED_GATE_SELECT;
+ int z = NI_GPCT_DISABLED_GATE_SELECT;
+ int retval;
+
+ struct parsed_options options;
+ {
+ int c;
+ while (-1 != (c = getopt(argc, argv, "f:s:a:b:z:"))) {
+ 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_GATE_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_GATE_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_GATE_SELECT(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, a, b, z);
+
+ if(retval < 0) return retval;
+
+ return 0;
+}
diff -urbN comedilib.save/demo/Makefile.am comedilib/demo/Makefile.am
--- comedilib.save/demo/Makefile.am 2007-01-08 22:53:59.000000000 +0100
+++ comedilib/demo/Makefile.am 2007-06-21 17:14:32.000000000 +0200
_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)
Received on 2007-06-26Z10:00:57