From 13fac9a3d31ac33657a587e90471d6d1678ce1f0 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Thu, 28 Jun 2007 01:20:21 +0000 Subject: [PATCH] Patch from Anders Blomdell , fixes quadrature encoder counting with NI M-series boards. --- comedi/comedi_fops.c | 1 + comedi/drivers/ni_mio_common.c | 7 +++++ comedi/drivers/ni_tio.c | 55 ++++++++++++++++++++++++++++++++++ comedi/drivers/ni_tio.h | 2 ++ include/linux/comedi.h | 28 +++++++++++++++++ 5 files changed, 93 insertions(+) diff --git a/comedi/comedi_fops.c b/comedi/comedi_fops.c index 2f5a3fa6..824297c8 100644 --- a/comedi/comedi_fops.c +++ b/comedi/comedi_fops.c @@ -638,6 +638,7 @@ static int check_insn_config_length(comedi_insn *insn, lsampl_t *data) 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; diff --git a/comedi/drivers/ni_mio_common.c b/comedi/drivers/ni_mio_common.c index ee4e889e..4caaf5ad 100644 --- a/comedi/drivers/ni_mio_common.c +++ b/comedi/drivers/ni_mio_common.c @@ -3371,6 +3371,13 @@ static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, enum 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: diff --git a/comedi/drivers/ni_tio.c b/comedi/drivers/ni_tio.c index c1898e77..67f3739e 100644 --- a/comedi/drivers/ni_tio.c +++ b/comedi/drivers/ni_tio.c @@ -322,6 +322,23 @@ static inline enum ni_gpct_register NITIO_Gi_DMA_Config_Reg(int counter_index) 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 @@ -1607,6 +1624,41 @@ static int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index, lsa 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; @@ -1875,6 +1927,9 @@ int ni_tio_insn_config(struct ni_gpct *counter, 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; diff --git a/comedi/drivers/ni_tio.h b/comedi/drivers/ni_tio.h index e561088a..bd32398b 100644 --- a/comedi/drivers/ni_tio.h +++ b/comedi/drivers/ni_tio.h @@ -86,6 +86,8 @@ enum ni_gpct_register 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 --git a/include/linux/comedi.h b/include/linux/comedi.h index c4b31c18..7014fc46 100644 --- a/include/linux/comedi.h +++ b/include/linux/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 -- 2.26.2