INSN_CONFIG_SET_ROUTING.
*
*/
+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)
{
data[1] = (devpriv->io_bidirection_pin_reg & (1<<chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->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;
}
{
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;
}
}
}
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
{
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{
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; \
}
/* 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,
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)