From c07aac59f122feb8b20f118208052383d3f73289 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Tue, 24 Oct 2006 18:52:22 +0000 Subject: [PATCH] Added support for configuring pfi routing on m-series boards with INSN_CONFIG_SET_ROUTING. --- comedi/drivers/ni_mio_common.c | 93 +++++++++++++++++++++++++++++++++- comedi/drivers/ni_stc.h | 24 +++++++++ include/linux/comedi.h | 42 ++++++++++++++- 3 files changed, 155 insertions(+), 4 deletions(-) diff --git a/comedi/drivers/ni_mio_common.c b/comedi/drivers/ni_mio_common.c index 1a506330..9ab59820 100644 --- a/comedi/drivers/ni_mio_common.c +++ b/comedi/drivers/ni_mio_common.c @@ -4263,6 +4263,88 @@ static int ni_gpct_insn_write(comedi_device *dev,comedi_subdevice *s, * */ +int ni_m_series_set_pfi_routing(comedi_device *dev, unsigned chan, unsigned source) +{ + if((source & 0x1f) != source) return -EINVAL; + const unsigned pfi_reg_index = 1 + chan / 3; + const unsigned array_offset = pfi_reg_index - 1; + devpriv->pfi_output_select_reg[array_offset] &= ~MSeries_PFI_Output_Select_Mask(chan); + devpriv->pfi_output_select_reg[array_offset] |= MSeries_PFI_Output_Select_Bits(chan, source); + ni_writew(devpriv->pfi_output_select_reg[array_offset], M_Offset_PFI_Output_Select(pfi_reg_index)); + return 2; +} + +int ni_old_set_pfi_routing(comedi_device *dev, unsigned chan, unsigned source) +{ + // pre-m-series boards have fixed signals on pfi pins + if(source != ni_old_get_pfi_routing(dev, chan)) return -EINVAL; + return 2; +} + +int ni_set_pfi_routing(comedi_device *dev, unsigned chan, unsigned source) +{ + if(boardtype.reg_type == ni_reg_m_series) + return ni_m_series_set_pfi_routing(dev, chan, source); + else + return ni_old_set_pfi_routing(dev, chan, source); +} + +unsigned ni_m_series_get_pfi_routing(comedi_device *dev, unsigned chan) +{ + const unsigned array_offset = chan / 3; + return MSeries_PFI_Output_Select_Source(chan, devpriv->pfi_output_select_reg[array_offset]); +} + +unsigned ni_old_get_pfi_routing(comedi_device *dev, unsigned chan) +{ + // pre-m-series boards have fixed signals on pfi pins + switch(chan) + { + case 0: + return NI_PFI_OUTPUT_AI_START1; + break; + case 1: + return NI_PFI_OUTPUT_AI_START2; + break; + case 2: + return NI_PFI_OUTPUT_AI_CONVERT; + break; + case 3: + return NI_PFI_OUTPUT_G_SRC1; + break; + case 4: + return NI_PFI_OUTPUT_G_GATE1; + break; + case 5: + return NI_PFI_OUTPUT_AO_UPDATE_N; + break; + case 6: + return NI_PFI_OUTPUT_AO_START1; + break; + case 7: + return NI_PFI_OUTPUT_AI_START_PULSE; + break; + case 8: + return NI_PFI_OUTPUT_G_SRC0; + break; + case 9: + return NI_PFI_OUTPUT_G_GATE0; + break; + default: + rt_printk("%s: bug, unhandled case in switch.\n", __FUNCTION__); + break; + } + return 0; +} + +unsigned ni_get_pfi_routing(comedi_device *dev, unsigned chan) +{ + if(boardtype.reg_type == ni_reg_m_series) + return ni_m_series_get_pfi_routing(dev, chan); + else + return ni_old_get_pfi_routing(dev, chan); +} + static int ni_pfi_insn_bits(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data) { @@ -4293,6 +4375,13 @@ static int ni_pfi_insn_config(comedi_device *dev,comedi_subdevice *s, data[1] = (devpriv->io_bidirection_pin_reg & (1<n; break; + case INSN_CONFIG_SET_ROUTING: + return ni_set_pfi_routing(dev, chan, data[1]); + break; + case INSN_CONFIG_GET_ROUTING: + data[1] = ni_get_pfi_routing(dev, chan); + return 2; + break; default: return -EINVAL; } @@ -4586,8 +4675,8 @@ unsigned ni_get_rtsi_routing(comedi_device *dev, unsigned chan) { if(chan == old_RTSI_clock_channel) return NI_RTSI_OUTPUT_RTSI_OSC; - rt_printk("%s: invalid channel=%i\n", __FUNCTION__, chan); - return -EINVAL; + rt_printk("%s: bug! should never get here?\n", __FUNCTION__); + return 0; } } diff --git a/comedi/drivers/ni_stc.h b/comedi/drivers/ni_stc.h index 9bfafa83..f237fff2 100644 --- a/comedi/drivers/ni_stc.h +++ b/comedi/drivers/ni_stc.h @@ -1040,6 +1040,15 @@ static inline int M_Offset_AO_Reference_Attenuation(int channel) } return offset[channel]; }; +static inline unsigned M_Offset_PFI_Output_Select(unsigned n) +{ + if(n < 1 || n > 6) + { + rt_printk("%s: invalid pfi output select register=%i\n", __FUNCTION__, n); + return M_Offset_PFI_Output_Select_1; + } + return M_Offset_PFI_Output_Select_1 + (n - 1) * 2; +} enum MSeries_AI_Config_FIFO_Data_Bits { @@ -1179,6 +1188,20 @@ static inline unsigned MSeries_Cal_PWM_Low_Time_Bits(unsigned count) return count & 0xffff; } +static inline unsigned MSeries_PFI_Output_Select_Mask(unsigned channel) +{ + return 0x1f << (channel % 3) * 5; +}; +static inline unsigned MSeries_PFI_Output_Select_Bits(unsigned channel, unsigned source) +{ + return (source & 0x1f) << ((channel % 3) * 5); +}; +// inverse to MSeries_PFI_Output_Select_Bits +static inline unsigned MSeries_PFI_Output_Select_Source(unsigned channel, unsigned bits) +{ + return (bits >> ((channel % 3) * 5)) & 0x1f; +}; + #define M_SERIES_EEPROM_SIZE 1024 typedef struct ni_board_struct{ @@ -1273,6 +1296,7 @@ static ni_board ni_boards[]; unsigned short rtsi_trig_direction_reg; \ unsigned short rtsi_trig_a_output_reg; \ unsigned short rtsi_trig_b_output_reg; \ + unsigned short pfi_output_select_reg[6]; \ \ unsigned clock_ns; \ unsigned clock_source; \ diff --git a/include/linux/comedi.h b/include/linux/comedi.h index d6cba930..ae62b1fd 100644 --- a/include/linux/comedi.h +++ b/include/linux/comedi.h @@ -538,9 +538,9 @@ static inline unsigned NI_MIO_PLL_RTSI_CLOCK(unsigned rtsi_channel) } /* Signals which can be routed to an NI RTSI pin with INSN_CONFIG_SET_ROUTING. - The numbers are assigned are not arbitrary, they correspond to the bits required + The numbers assigned are not arbitrary, they correspond to the bits required to program the board. */ -enum ni_rtsi_output +enum ni_rtsi_routing { NI_RTSI_OUTPUT_ADR_START1 = 0, NI_RTSI_OUTPUT_ADR_START2 = 1, @@ -558,6 +558,44 @@ static inline unsigned NI_RTSI_OUTPUT_RTSI_BRD(unsigned n) return NI_RTSI_OUTPUT_RTSI_BRD_0 + n; } +/* Signals which can be routed to an NI PFI pin on an m-series board + with INSN_CONFIG_SET_ROUTING. These numbers are also returned + by INSN_CONFIG_GET_ROUTING on pre-m-series boards, even though + their routing cannot be changed. The numbers assigned are + not arbitrary, they correspond to the bits required + to program the board. */ +enum ni_pfi_routing +{ + NI_PFI_OUTPUT_PFI_DEFAULT = 0, + NI_PFI_OUTPUT_AI_START1 = 1, + NI_PFI_OUTPUT_AI_START2 = 2, + NI_PFI_OUTPUT_AI_CONVERT = 3, + NI_PFI_OUTPUT_G_SRC1 = 4, + NI_PFI_OUTPUT_G_GATE1 = 5, + NI_PFI_OUTPUT_AO_UPDATE_N = 6, + NI_PFI_OUTPUT_AO_START1 = 7, + NI_PFI_OUTPUT_AI_START_PULSE = 8, + NI_PFI_OUTPUT_G_SRC0 = 9, + NI_PFI_OUTPUT_G_GATE0 = 10, + NI_PFI_OUTPUT_EXT_STROBE = 11, + NI_PFI_OUTPUT_AI_EXT_MUX_CLK = 12, + NI_PFI_OUTPUT_GOUT0 = 13, + NI_PFI_OUTPUT_GOUT1 = 14, + NI_PFI_OUTPUT_FREQ_OUT = 15, + NI_PFI_OUTPUT_PFI_DO = 16, + NI_PFI_OUTPUT_I_ATRIG = 17, + NI_PFI_OUTPUT_RTSI0 = 18, + NI_PFI_OUTPUT_PXI_STAR_TRIGGER_IN = 26, + NI_PFI_OUTPUT_SCXI_TRIG1 = 27, + NI_PFI_OUTPUT_DIO_CHANGE_DETECT_RTSI = 28, + NI_PFI_OUTPUT_CDI_SAMPLE = 29, + NI_PFI_OUTPUT_CDO_UPDATE = 30 +}; +static inline unsigned NI_PFI_OUTPUT_RTSI(unsigned rtsi_channel) +{ + return NI_PFI_OUTPUT_RTSI0 + rtsi_channel; +} + /* NI External Trigger lines. These values are not arbitrary, but are related to the bits required to program the board (offset by 1 for historical reasons). */ static inline unsigned NI_EXT_PFI(unsigned pfi_channel) -- 2.26.2