From: Frank Mori Hess Date: Fri, 3 Mar 2006 00:58:47 +0000 (+0000) Subject: Patch from terry1@beam.ltd.uk (Terry Barnaby): X-Git-Tag: r0_7_71~51 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=43d7dffff725c41cedf9af1f5fd4287e6936456f;p=comedi.git Patch from terry1@beam.ltd.uk (Terry Barnaby): This patch adds support to comedi for the NI PCI-6143 DAQ card. It also adds support for the NI RTSI trigger bus used to synchronise multiple cards to any ni_pcimio supported card. The patch also requires a patch to the comedilib to support the RTSI. More info on the patch is at: http://www.beam.org.uk/opensource/pci-6143/ --- diff --git a/comedi/drivers/ni_mio_common.c b/comedi/drivers/ni_mio_common.c index 5eebad0b..ca276cac 100644 --- a/comedi/drivers/ni_mio_common.c +++ b/comedi/drivers/ni_mio_common.c @@ -53,6 +53,9 @@ - the interrupt routine needs to be cleaned up - many printk's need to be changed to rt_printk() + + 2006-02-07: S-Series PCI-6143: Support has been added but is not + fully tested as yet. Terry Barnaby, BEAM Ltd. */ //#define DEBUG_INTERRUPT @@ -88,7 +91,9 @@ static short ni_gainlkup[][16]={ /* ai_gain_622x */ { 0, 1, 4, 5}, /* ai_gain_628x */ - { 1, 2, 3, 4, 5, 6, 7} + { 1, 2, 3, 4, 5, 6, 7}, + /* ai_gain_6143 */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, }; static comedi_lrange range_ni_E_ai={ 16, { @@ -166,6 +171,9 @@ static comedi_lrange range_ni_M_ai_628x={ 7, { RANGE( -0.2, 0.2 ), RANGE( -0.1, 0.1 ), }}; +static comedi_lrange range_ni_S_ai_6143 = { 1, { + RANGE( -5, +5 ), +}}; static comedi_lrange range_ni_E_ao_ext = { 4, { RANGE( -10, 10 ), RANGE( 0, 10 ), @@ -180,7 +188,8 @@ static comedi_lrange *ni_range_lkup[]={ &range_ni_E_ai_bipolar4, &range_ni_E_ai_611x, &range_ni_M_ai_622x, - &range_ni_M_ai_628x + &range_ni_M_ai_628x, + &range_ni_S_ai_6143 }; @@ -212,6 +221,12 @@ static int ni_pfi_insn_bits(comedi_device *dev,comedi_subdevice *s, static int ni_pfi_insn_config(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data); +static void ni_rtsi_init(comedi_device *dev); +static int ni_rtsi_insn_bits(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); +static int ni_rtsi_insn_config(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data); + static void caldac_setup(comedi_device *dev,comedi_subdevice *s); static int ni_read_eeprom(comedi_device *dev,int addr); @@ -276,6 +291,8 @@ static void cs5529_config_write(comedi_device *dev, unsigned int value, unsigned static int ni_m_series_pwm_config(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn,lsampl_t *data); +static int ni_6143_pwm_config(comedi_device *dev, comedi_subdevice *s, + comedi_insn *insn, lsampl_t *data); enum aimodes { @@ -297,11 +314,24 @@ static void handle_a_interrupt(comedi_device *dev,unsigned short status, static void handle_b_interrupt(comedi_device *dev,unsigned short status, unsigned int m_status); static void get_last_sample_611x( comedi_device *dev ); +static void get_last_sample_6143( comedi_device *dev ); #ifdef PCIDMA //static void mite_handle_interrupt(comedi_device *dev,unsigned int status); static int ni_ai_drain_dma(comedi_device *dev ); #endif +static void ni_flush_ai_fifo(comedi_device *dev){ + if(boardtype.reg_type == ni_reg_6143){ + // Flush the 6143 data FIFO + ni_writel(0x10, AIFIFO_Control_6143); // Flush fifo + ni_writel(0x00, AIFIFO_Control_6143); // Flush fifo + while(ni_readl(AIFIFO_Status_6143) & 0x10); // Wait for complete + } + else { + devpriv->stc_writew(dev, 1,ADC_FIFO_Clear); + } +} + static void win_out2(comedi_device *dev, uint32_t data, int reg) { devpriv->stc_writew(dev, data >> 16, reg); @@ -563,6 +593,7 @@ static void shutdown_ai_command( comedi_device *dev ) #endif ni_handle_fifo_dregs(dev); get_last_sample_611x(dev); + get_last_sample_6143(dev); ni_set_bits(dev, Interrupt_A_Enable_Register, AI_SC_TC_Interrupt_Enable | AI_START1_Interrupt_Enable| @@ -931,7 +962,26 @@ static void ni_ai_fifo_read(comedi_device *dev,comedi_subdevice *s, data[0] = dl & 0xffff; cfc_write_to_buffer(s, data[0]); } - }else{ + } else if(boardtype.reg_type == ni_reg_6143){ + sampl_t data[2]; + u32 dl; + + // This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed + for(i = 0; i < n / 2; i++){ + dl = ni_readl(AIFIFO_Data_6143); + + data[0] = (dl >> 16) & 0xffff; + data[1] = dl & 0xffff; + cfc_write_array_to_buffer(s, data, sizeof(data)); + } + if(n % 2){ + /* Assume there is a single sample stuck in the FIFO */ + ni_writel(0x01, AIFIFO_Control_6143); // Get stranded sample into FIFO + dl = ni_readl(AIFIFO_Data_6143); + data[0] = (dl >> 16) & 0xffff; + cfc_write_to_buffer(s, data[0]); + } + } else{ if( n > sizeof(devpriv->ai_fifo_buffer) / sizeof(devpriv->ai_fifo_buffer[0])) { comedi_error( dev, "bug! ai_fifo_buffer too small" ); @@ -1004,6 +1054,25 @@ static void ni_handle_fifo_dregs(comedi_device *dev) data[1] = (dl&0xffff); cfc_write_array_to_buffer(s, data, sizeof(data)); } + }else if(boardtype.reg_type == ni_reg_6143){ + i = 0; + while(ni_readl(AIFIFO_Status_6143) & 0x04){ + dl = ni_readl(AIFIFO_Data_6143); + + /* This may get the hi/lo data in the wrong order */ + data[0] = (dl >> 16); + data[1] = (dl & 0xffff); + cfc_write_array_to_buffer(s, data, sizeof(data)); + i += 2; + } + // Check if stranded sample is present + if(ni_readl(AIFIFO_Status_6143) & 0x01){ + ni_writel(0x01, AIFIFO_Control_6143); // Get stranded sample into FIFO + dl = ni_readl(AIFIFO_Data_6143); + data[0] = (dl >> 16) & 0xffff; + cfc_write_to_buffer(s, data[0]); + } + }else{ fifo_empty = devpriv->stc_readw(dev, AI_Status_1_Register) & AI_FIFO_Empty_St; while(fifo_empty == 0) @@ -1036,6 +1105,25 @@ static void get_last_sample_611x( comedi_device *dev ) } } +static void get_last_sample_6143(comedi_device* dev) +{ + comedi_subdevice* s = dev->subdevices + 0; + sampl_t data; + u32 dl; + + if(boardtype.reg_type != ni_reg_6143) return; + + /* Check if there's a single sample stuck in the FIFO */ + if(ni_readl(AIFIFO_Status_6143) & 0x01){ + ni_writel(0x01, AIFIFO_Control_6143); // Get stranded sample into FIFO + dl = ni_readl(AIFIFO_Data_6143); + + /* This may get the hi/lo data in the wrong order */ + data = (dl >> 16) & 0xffff; + cfc_write_to_buffer(s, data); + } +} + static void ni_ai_munge(comedi_device *dev, comedi_subdevice *s, void *data, unsigned int num_bytes, unsigned int chan_index ) { @@ -1078,6 +1166,7 @@ static void ni_ai_setup_MITE_dma(comedi_device *dev,comedi_cmd *cmd) switch(boardtype.reg_type) { case ni_reg_611x: + case ni_reg_6143: mite_prep_dma(mite, AI_DMA_CHAN, 32, 16); break; case ni_reg_m_series: @@ -1135,9 +1224,10 @@ static int ni_ai_reset(comedi_device *dev,comedi_subdevice *s) AI_STOP_Interrupt_Enable| AI_Error_Interrupt_Enable| AI_FIFO_Interrupt_Enable,0); - devpriv->stc_writew(dev, 1,ADC_FIFO_Clear); + ni_flush_ai_fifo(dev); - ni_writeb(0, Misc_Command); + if(boardtype.reg_type != ni_reg_6143) + ni_writeb(0, Misc_Command); devpriv->stc_writew(dev, AI_Disarm, AI_Command_1_Register); /* reset pulses */ devpriv->stc_writew(dev, AI_Start_Stop | AI_Mode_1_Reserved /*| AI_Trigger_Once */, @@ -1154,6 +1244,15 @@ static int ni_ai_reset(comedi_device *dev,comedi_subdevice *s) AI_LOCALMUX_CLK_Output_Select(2) | AI_SC_TC_Output_Select(3) | AI_CONVERT_Output_Select(3),AI_Output_Control_Register); + }else if(boardtype.reg_type == ni_reg_6143){ + devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width | + AI_SOC_Polarity | + AI_LOCALMUX_CLK_Pulse_Width, AI_Personal_Register); + devpriv->stc_writew(dev, AI_SCAN_IN_PROG_Output_Select(3) | + AI_EXTMUX_CLK_Output_Select(0) | + AI_LOCALMUX_CLK_Output_Select(2) | + AI_SC_TC_Output_Select(3) | + AI_CONVERT_Output_Select(2),AI_Output_Control_Register); }else{ devpriv->stc_writew(dev, AI_SHIFTIN_Pulse_Width | AI_SOC_Polarity | @@ -1210,10 +1309,11 @@ static int ni_ai_insn_read(comedi_device *dev,comedi_subdevice *s,comedi_insn *i unsigned int mask; unsigned signbits; unsigned short d; + unsigned long dl; ni_load_channelgain_list(dev,1,&insn->chanspec); - devpriv->stc_writew(dev, 1,ADC_FIFO_Clear); + ni_flush_ai_fifo(dev); mask=(1<ai_offset[0]; @@ -1245,6 +1345,26 @@ static int ni_ai_insn_read(comedi_device *dev,comedi_subdevice *s,comedi_insn *i d += signbits; data[ n ] = d; } + }else if(boardtype.reg_type == ni_reg_6143){ + for(n = 0; n < insn->n; n++){ + devpriv->stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register); + + /* The 6143 has 32-bit FIFOs. You need to strobe a bit to move a single 16bit stranded sample into the FIFO */ + dl = 0; + for(i = 0; i < NI_TIMEOUT; i++){ + if(ni_readl(AIFIFO_Status_6143) & 0x01) + { + ni_writel(0x01, AIFIFO_Control_6143); // Get stranded sample into FIFO + dl = ni_readl(AIFIFO_Data_6143); + break; + } + } + if(i == NI_TIMEOUT){ + rt_printk("ni_mio_common: timeout in 6143 ni_ai_insn_read\n"); + return -ETIME; + } + data[n] = (((dl >> 16) & 0xFFFF) + signbits) & 0xFFFF; + } }else{ for(n=0;nn;n++){ devpriv->stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register); @@ -1401,7 +1521,7 @@ static void ni_load_channelgain_list(comedi_device *dev,unsigned int n_chan, ni_m_series_load_channelgain_list(dev, n_chan, list); return; } - if(n_chan == 1 && boardtype.reg_type != ni_reg_611x){ + if(n_chan == 1 && (boardtype.reg_type != ni_reg_611x) && (boardtype.reg_type != ni_reg_6143)){ if(devpriv->changain_state && devpriv->changain_spec==list[0]){ // ready to go. return; @@ -1414,9 +1534,27 @@ static void ni_load_channelgain_list(comedi_device *dev,unsigned int n_chan, devpriv->stc_writew(dev, 1,Configuration_Memory_Clear); + // Set up Calibration mode if required + if(boardtype.reg_type == ni_reg_6143){ + if((list[0] & CR_ALT_SOURCE) && !devpriv->ai_calib_source_enabled){ + // Strobe Relay enable bit + ni_writew(devpriv->ai_calib_source | Calibration_Channel_6143_RelayOn, Calibration_Channel_6143); + ni_writew(devpriv->ai_calib_source, Calibration_Channel_6143); + devpriv->ai_calib_source_enabled = 1; + msleep_interruptible(100); // Allow relays to change + } + else if(!(list[0] & CR_ALT_SOURCE) && devpriv->ai_calib_source_enabled){ + // Strobe Relay disable bit + ni_writew(devpriv->ai_calib_source | Calibration_Channel_6143_RelayOff, Calibration_Channel_6143); + ni_writew(devpriv->ai_calib_source, Calibration_Channel_6143); + devpriv->ai_calib_source_enabled = 0; + msleep_interruptible(100); // Allow relays to change + } + } + offset=1<<(boardtype.adbits-1); for(i=0;iai_calib_source; }else{ chan=CR_CHAN(list[i]); @@ -1441,6 +1579,8 @@ static void ni_load_channelgain_list(comedi_device *dev,unsigned int n_chan, { if(boardtype.reg_type == ni_reg_611x) aref = AREF_DIFF; + else if(boardtype.reg_type == ni_reg_6143) + aref = AREF_OTHER; switch( aref ) { case AREF_DIFF: @@ -1460,15 +1600,17 @@ static void ni_load_channelgain_list(comedi_device *dev,unsigned int n_chan, ni_writew(hi,Configuration_Memory_High); - lo = range; - if(i == n_chan - 1) lo |= AI_LAST_CHANNEL; - if( dither ) lo |= AI_DITHER; + if(boardtype.reg_type != ni_reg_6143){ + lo = range; + if(i == n_chan - 1) lo |= AI_LAST_CHANNEL; + if( dither ) lo |= AI_DITHER; - ni_writew(lo,Configuration_Memory_Low); + ni_writew(lo,Configuration_Memory_Low); + } } /* prime the channel/gain list */ - if(boardtype.reg_type != ni_reg_611x){ + if((boardtype.reg_type != ni_reg_611x) && (boardtype.reg_type != ni_reg_6143)){ ni_prime_channelgain_list(dev); } } @@ -1553,7 +1695,7 @@ static int ni_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd) /* external trigger */ unsigned int tmp = CR_CHAN(cmd->start_arg); - if(tmp > 9) tmp = 9; + if(tmp > 16) tmp = 16; tmp |= (cmd->start_arg & (CR_INVERT | CR_EDGE)); if(cmd->start_arg != tmp){ cmd->start_arg = tmp; @@ -1579,7 +1721,7 @@ static int ni_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd) /* external trigger */ unsigned int tmp = CR_CHAN(cmd->scan_begin_arg); - if(tmp>9)tmp=9; + if(tmp>16)tmp=16; tmp |= (cmd->scan_begin_arg & (CR_INVERT | CR_EDGE)); if(cmd->scan_begin_arg!=tmp){ cmd->scan_begin_arg = tmp; @@ -1611,7 +1753,7 @@ static int ni_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd) /* external trigger */ unsigned int tmp = CR_CHAN(cmd->convert_arg); - if(tmp>9)tmp=9; + if(tmp>16)tmp=16; tmp |= (cmd->convert_arg&(CR_ALT_FILTER|CR_INVERT)); if(cmd->convert_arg!=tmp){ cmd->convert_arg = tmp; @@ -1692,7 +1834,7 @@ static int ni_ai_cmd(comedi_device *dev,comedi_subdevice *s) comedi_error(dev, "cannot run command without an irq"); return -EIO; } - devpriv->stc_writew(dev, 1,ADC_FIFO_Clear); + ni_flush_ai_fifo(dev); ni_load_channelgain_list(dev,cmd->chanlist_len,cmd->chanlist); @@ -1732,7 +1874,7 @@ static int ni_ai_cmd(comedi_device *dev,comedi_subdevice *s) mode2 &= ~AI_SC_Reload_Mode; devpriv->stc_writew(dev, mode2, AI_Mode_2_Register); - if(cmd->chanlist_len == 1 || boardtype.reg_type == ni_reg_611x){ + if(cmd->chanlist_len == 1 || (boardtype.reg_type == ni_reg_611x) || (boardtype.reg_type == ni_reg_6143)){ start_stop_select |= AI_STOP_Polarity; start_stop_select |= AI_STOP_Select( 31 ); // logic low start_stop_select |= AI_STOP_Sync; @@ -1989,6 +2131,18 @@ static int ni_ai_insn_config(comedi_device *dev,comedi_subdevice *s, return -EINVAL; } devpriv->ai_calib_source = data[1]; + } else if(boardtype.reg_type == ni_reg_6143) + { + unsigned int calib_source; + + calib_source = data[1] & 0xf; + + + if(calib_source > 0xF) + return -EINVAL; + + devpriv->ai_calib_source = calib_source; + ni_writew(calib_source, Calibration_Channel_6143); }else { unsigned int calib_source; @@ -2875,7 +3029,7 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it) return -EINVAL; } - if(alloc_subdevices(dev, 10) < 0) + if(alloc_subdevices(dev, 11) < 0) return -ENOMEM; /* analog input subdevice */ @@ -2903,7 +3057,7 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it) }else{ s->type=COMEDI_SUBD_UNUSED; } - + /* analog output subdevice */ s=dev->subdevices+1; @@ -2986,6 +3140,13 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it) s->n_chan = 1; s->maxdata = 0; ni_writel(0x0, M_Offset_Cal_PWM); + } else if(boardtype.reg_type == ni_reg_6143) + { + // internal PWM analog output used for AI nonlinearity calibration + s->subdev_flags = SDF_INTERNAL; + s->insn_config = &ni_6143_pwm_config; + s->n_chan = 1; + s->maxdata = 0; }else { s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL; @@ -3046,9 +3207,20 @@ static int ni_E_init(comedi_device *dev,comedi_devconfig *it) devpriv->serial_interval_ns = 0; devpriv->serial_hw_mode = 0; + /* RTSI */ + s=dev->subdevices+10; + s->type=COMEDI_SUBD_DIO; + s->subdev_flags=SDF_READABLE|SDF_WRITABLE|SDF_INTERNAL; + s->n_chan=8; + s->maxdata=1; + s->insn_bits = ni_rtsi_insn_bits; + s->insn_config = ni_rtsi_insn_config; + ni_rtsi_init(dev); + /* ai configuration */ ni_ai_reset(dev,dev->subdevices+0); if((boardtype.reg_type & ni_reg_6xxx_mask) == 0){ + // BEAM is this needed for PCI-6143 ?? devpriv->clock_and_fout = Slow_Internal_Time_Divide_By_2 | Slow_Internal_Timebase | @@ -3211,6 +3383,49 @@ static int ni_m_series_pwm_config(comedi_device *dev, comedi_subdevice *s, return 0; } +static int ni_6143_pwm_config(comedi_device *dev, comedi_subdevice *s, + comedi_insn *insn, lsampl_t *data) +{ + unsigned up_count, down_count; + switch(data[0]) + { + case INSN_CONFIG_PWM_OUTPUT: + switch(data[1]) + { + case TRIG_ROUND_NEAREST: + up_count = (data[2] + TIMER_BASE / 2) / TIMER_BASE; + down_count = (data[3] + TIMER_BASE / 2) / TIMER_BASE; + break; + case TRIG_ROUND_DOWN: + up_count = data[2] / TIMER_BASE; + down_count = data[3] / TIMER_BASE; + break; + case TRIG_ROUND_UP: + up_count = (data[2] + TIMER_BASE - 1) / TIMER_BASE; + down_count = (data[3] + TIMER_BASE - 1) / TIMER_BASE; + break; + default: + return -EINVAL; + break; + } + if(up_count * TIMER_BASE != data[2] || + down_count * TIMER_BASE != data[3]) + { + data[2] = up_count * TIMER_BASE; + data[3] = down_count * TIMER_BASE; + return -EAGAIN; + } + ni_writel(up_count, Calibration_HighTime_6143); + ni_writel(down_count, Calibration_LowTime_6143); + return 4; + break; + default: + return -EINVAL; + break; + } + return 0; +} + static void ni_write_caldac(comedi_device *dev,int addr,int val); /* calibration subdevice @@ -3968,7 +4183,7 @@ static int ni_pfi_insn_config(comedi_device *dev,comedi_subdevice *s, { unsigned int chan; - if(insn->n!=1)return -EINVAL; + if(insn->n < 1)return -EINVAL; chan = CR_CHAN(insn->chanspec); if(chan>10)return -EINVAL; @@ -3991,6 +4206,79 @@ static int ni_pfi_insn_config(comedi_device *dev,comedi_subdevice *s, return 1; } +/* + * + * NI RTSI Bus Functions + * + */ +static void ni_rtsi_init(comedi_device *dev) +{ + // Initialises the RTSI bus signal switch to a default state + + // Set clock mode to internal + devpriv->stc_writew(dev, COMEDI_RTSI_CLOCK_MODE_INTERNAL, RTSI_Trig_Direction_Register); + + // Standard internal lines are routed to standard RTSI bus lines + devpriv->stc_writew(dev, 0x3210, RTSI_Trig_A_Output_Register); + devpriv->stc_writew(dev, 0x0654, RTSI_Trig_B_Output_Register); + + // Sets the source and direction of the 4 on board lines +// devpriv->stc_writew(dev, 0x0000, RTSI_Board_Register); +} + +static int ni_rtsi_insn_bits(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) +{ + if(insn->n != 2) return -EINVAL; + + data[1] = 0; + + return 2; +} + +static int ni_rtsi_insn_config(comedi_device *dev,comedi_subdevice *s, + comedi_insn *insn,lsampl_t *data) +{ + unsigned int chan; + unsigned int bit; + + if(insn->n < 1) return -EINVAL; + + if(data[0] == INSN_CONFIG_SET_RTSI_CLOCK_MODE){ + if(data[1] > 3) + return -EINVAL; + + devpriv->rtsi_trig_direction_reg &= ~0x03; + devpriv->rtsi_trig_direction_reg |= data[1]; + devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg, RTSI_Trig_Direction_Register); + } + else { + chan = CR_CHAN(insn->chanspec); + if(chan > 6) return -EINVAL; + + bit = 9 + chan; + + switch(data[0]){ + case INSN_CONFIG_DIO_OUTPUT: + devpriv->rtsi_trig_direction_reg |= (1 << bit); + devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg, RTSI_Trig_Direction_Register); + break; + case INSN_CONFIG_DIO_INPUT: + devpriv->rtsi_trig_direction_reg &= ~(1 << bit); + devpriv->stc_writew(dev, devpriv->rtsi_trig_direction_reg, RTSI_Trig_Direction_Register); + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = (devpriv->rtsi_trig_direction_reg & (1<mite->mite_io_addr + 0x30); } +static void init_6143(comedi_device *dev) +{ + // Disable interrupts + devpriv->stc_writew(dev, 0, Interrupt_Control_Register); + + // Initialise 6143 AI specific bits + ni_writeb(0x00, Magic_6143); // Set G0,G1 DMA mode to E series version + ni_writeb(0x80, PipelineDelay_6143); // Set EOCMode, ADCMode and pipelinedelay + ni_writeb(0x00, EOC_Set_6143); // Set EOC Delay + + ni_writel(boardtype.ai_fifo_depth / 2, AIFIFO_Flag_6143); // Set the FIFO half full level + + // Strobe Relay disable bit + devpriv->ai_calib_source_enabled = 0; + ni_writew(devpriv->ai_calib_source | Calibration_Channel_6143_RelayOff, Calibration_Channel_6143); + ni_writew(devpriv->ai_calib_source, Calibration_Channel_6143); +} + /* cleans up allocated resources */ static int pcimio_detach(comedi_device *dev) { @@ -1309,8 +1347,11 @@ static int pcimio_attach(comedi_device *dev,comedi_devconfig *it) printk(" error setting up mite\n"); return ret; } + if(boardtype.reg_type == ni_reg_m_series) m_series_init_eeprom_buffer(dev); + if(boardtype.reg_type == ni_reg_6143) + init_6143(dev); dev->irq=mite_irq(devpriv->mite); diff --git a/comedi/drivers/ni_stc.h b/comedi/drivers/ni_stc.h index b63b229b..0d98b8d7 100644 --- a/comedi/drivers/ni_stc.h +++ b/comedi/drivers/ni_stc.h @@ -304,6 +304,7 @@ enum AO_FIFO_Mode_Bits #define FOUT_Divider(x) (((x) & 0xf) << 0) #define IO_Bidirection_Pin_Register 57 +#define RTSI_Trig_Direction_Register 58 #define Interrupt_Control_Register 59 #define Interrupt_B_Enable _bit15 @@ -440,6 +441,9 @@ enum AO_Personal_Bits AO_TMRDACWR_Pulse_Width = 1 << 12, AO_Number_Of_DAC_Packages = 1 << 14, // 1 for "single" mode, 0 for "dual" }; +#define RTSI_Trig_A_Output_Register 79 +#define RTSI_Trig_B_Output_Register 80 +#define RTSI_Board_Register 81 #define Write_Strobe_0_Register 82 #define Write_Strobe_1_Register 83 #define Write_Strobe_2_Register 84 @@ -664,6 +668,36 @@ static inline unsigned int AI_CONFIG_CHANNEL( unsigned int channel ) #define AO_Window_Address_611x 0x18 #define AO_Window_Data_611x 0x1e +/* 6143 registers */ +#define Magic_6143 0x19 /* w8 */ +#define G0G1_DMA_Select_6143 0x0B /* w8 */ +#define PipelineDelay_6143 0x1f /* w8 */ +#define EOC_Set_6143 0x1D /* w8 */ +#define AIDMA_Select_6143 0x09 /* w8 */ +#define AIFIFO_Data_6143 0x8C /* w32 */ +#define AIFIFO_Flag_6143 0x84 /* w32 */ +#define AIFIFO_Control_6143 0x88 /* w32 */ +#define AIFIFO_Status_6143 0x88 /* w32 */ +#define AIFIFO_DMAThreshold_6143 0x90 /* w32 */ +#define AIFIFO_Words_Available_6143 0x94 /* w32 */ + +#define Calibration_Channel_6143 0x42 /* w16 */ +#define Calibration_LowTime_6143 0x20 /* w16 */ +#define Calibration_HighTime_6143 0x22 /* w16 */ +#define Relay_Counter_Load_Val__6143 0x4C /* w32 */ +#define Signature_6143 0x50 /* w32 */ +#define Release_Date_6143 0x54 /* w32 */ +#define Release_Oldest_Date_6143 0x58 /* w32 */ + +#define Calibration_Channel_6143_RelayOn 0x8000 /* Calibration relay switch On */ +#define Calibration_Channel_6143_RelayOff 0x4000 /* Calibration relay switch Off */ +#define Calibration_Channel_Gnd_Gnd 0x00 /* Offset Calibration */ +#define Calibration_Channel_2v5_Gnd 0x02 /* 2.5V Reference */ +#define Calibration_Channel_Pwm_Gnd 0x05 /* +/- 5V Self Cal */ +#define Calibration_Channel_2v5_Pwm 0x0a /* PWM Calibration */ +#define Calibration_Channel_Pwm_Pwm 0x0d /* CMRR */ +#define Calibration_Channel_Gnd_Pwm 0x0e /* PWM Calibration */ + /* 671x, 611x registers */ /* 671xi, 611x windowed ao registers */ @@ -757,7 +791,7 @@ enum mite_dma_channel{ GPC1_DMA_CHAN = 3, }; -enum{ ai_gain_16=0, ai_gain_8, ai_gain_14, ai_gain_4, ai_gain_611x, ai_gain_622x, ai_gain_628x }; +enum{ ai_gain_16=0, ai_gain_8, ai_gain_14, ai_gain_4, ai_gain_611x, ai_gain_622x, ai_gain_628x, ai_gain_6143}; enum caldac_enum { caldac_none=0, mb88341, dac8800, dac8043, ad8522, ad8804, ad8842, ad8804_debug }; enum ni_reg_type { @@ -767,7 +801,8 @@ enum ni_reg_type { ni_reg_6713 = 0x4, ni_reg_67xx_mask = 0x6, ni_reg_6xxx_mask = 0x7, - ni_reg_m_series = 0x8 + ni_reg_m_series = 0x8, + ni_reg_6143 = 0x10 }; static comedi_lrange range_ni_E_ao_ext; @@ -1069,6 +1104,7 @@ static ni_board ni_boards[]; int blocksize; \ int n_left; \ unsigned int ai_calib_source; \ + unsigned int ai_calib_source_enabled; \ spinlock_t window_lock; \ \ int changain_state; \ @@ -1104,6 +1140,7 @@ static ni_board ni_boards[]; volatile unsigned short int_a_enable_reg; \ volatile unsigned short int_b_enable_reg; \ unsigned short io_bidirection_pin_reg; \ + unsigned short rtsi_trig_direction_reg; \ \ unsigned short atrig_mode; \ unsigned short atrig_high; \ diff --git a/include/linux/comedi.h b/include/linux/comedi.h index 3a69261f..698ad1e0 100644 --- a/include/linux/comedi.h +++ b/include/linux/comedi.h @@ -246,9 +246,11 @@ enum configuration_ids INSN_CONFIG_SET_CLOCK_SRC = 2003, // Set CTR clock source INSN_CONFIG_GET_CLOCK_SRC = 2004, // Get CTR clock source INSN_CONFIG_8254_SET_MODE = 4097, - INSN_CONFIG_8254_READ_STATUS = 4098 + INSN_CONFIG_8254_READ_STATUS = 4098, + INSN_CONFIG_SET_RTSI_CLOCK_MODE = 5000 // Set RTSI bus clock mode }; + /* ioctls */ #define CIO 'd' @@ -516,6 +518,54 @@ enum i8254_mode I8254_BCD = 1, /* use binary-coded decimal instead of binary (pretty useless) */ I8254_BINARY = 0 }; + +/* RTSI Clock mode */ +#define COMEDI_RTSI_CLOCK_MODE_INTERNAL 0x00 // Internal clock mode +#define COMEDI_RTSI_CLOCK_MODE_OUTPUT 0x01 // Outputs clock to RTSI +#define COMEDI_RTSI_CLOCK_MODE_SLAVE 0x02 // Runs from RTSI clock +#define COMEDI_RTSI_CLOCK_MODE_MASTER 0x03 // Outputs clock to RTSI and runs from this external clock + +/* RTSI BUS pins */ +#define NI_RTSI_0 0 +#define NI_RTSI_1 1 +#define NI_RTSI_2 2 +#define NI_RTSI_3 3 +#define NI_RTSI_4 4 +#define NI_RTSI_5 5 +#define NI_RTSI_6 6 +#define NI_RTSI_7 7 + +/* RTSI BUS pin usage in standard configuration */ +#define NI_RTSI_STD_AI_START1 0 +#define NI_RTSI_STD_AI_START2 1 +#define NI_RTSI_STD_AI_CONV 2 +#define NI_RTSI_STD_CT1_SRC 3 +#define NI_RTSI_STD_CT1_GATE 4 +#define NI_RTSI_STD_AO_SAMP_CLOCK 5 +#define NI_RTSI_STD_AO_START_TRIG 6 +#define NI_RTSI_STD_AI_SAMP_CLOCK 7 +#define NI_RTSI_STD_CTR0_SRC 8 +#define NI_RTSI_STD_CTR0_GATE 9 + +/* NI External Trigger lines */ +#define NI_EXT_PFI_0 0 +#define NI_EXT_PFI_1 1 +#define NI_EXT_PFI_2 2 +#define NI_EXT_PFI_3 3 +#define NI_EXT_PFI_4 4 +#define NI_EXT_PFI_5 5 +#define NI_EXT_PFI_6 6 +#define NI_EXT_PFI_7 7 +#define NI_EXT_PFI_8 8 +#define NI_EXT_PFI_9 9 +#define NI_EXT_RTSI_0 10 +#define NI_EXT_RTSI_1 11 +#define NI_EXT_RTSI_2 12 +#define NI_EXT_RTSI_3 13 +#define NI_EXT_RTSI_4 14 +#define NI_EXT_RTSI_5 15 +#define NI_EXT_RTSI_6 16 + #ifdef __cplusplus } #endif