⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ni_mio_common.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if(cmd->scan_begin_src==TRIG_TIMER){		tmp=cmd->scan_begin_arg;		ni_ns_to_timer(&cmd->scan_begin_arg,cmd->flags&TRIG_ROUND_MASK);		if(tmp!=cmd->scan_begin_arg)err++;	}	if(cmd->convert_src==TRIG_TIMER){		if( boardtype.reg_611x == 0){			tmp=cmd->convert_arg;			ni_ns_to_timer(&cmd->convert_arg,cmd->flags&TRIG_ROUND_MASK);			if(tmp!=cmd->convert_arg)err++;			if(cmd->scan_begin_src==TRIG_TIMER &&			cmd->scan_begin_arg<cmd->convert_arg*cmd->scan_end_arg){				cmd->scan_begin_arg=cmd->convert_arg*cmd->scan_end_arg;				err++;			}		}	}	if(err)return 4;	return 0;}static int ni_ai_cmd(comedi_device *dev,comedi_subdevice *s){	comedi_cmd *cmd=&s->async->cmd;	int timer;	int mode1=0; /* mode1 is needed for both stop and convert */	int mode2=0;	int start_stop_select=0;	unsigned int stop_count;	int interrupt_a_enable=0;		MDPRINTK("ni_ai_cmd\n");	win_out(1,ADC_FIFO_Clear);	ni_load_channelgain_list(dev,cmd->chanlist_len,cmd->chanlist);	/* start configuration */	win_out(AI_Configuration_Start,Joint_Reset_Register);	switch(cmd->start_src){	case TRIG_INT:	case TRIG_NOW:		win_out(AI_START2_Select(0)|			AI_START1_Sync|AI_START1_Edge|AI_START1_Select(0),			AI_Trigger_Select_Register);		break;	case TRIG_EXT:	{		int chan = CR_CHAN(cmd->start_arg);		win_out(AI_START2_Select(0)|			AI_START1_Sync | AI_START1_Edge |			AI_START1_Select(chan + 1),			AI_Trigger_Select_Register);		break;	}	}	mode2 &= ~AI_Pre_Trigger;	mode2 &= ~AI_SC_Initial_Load_Source;	mode2 &= ~AI_SC_Reload_Mode;	win_out(mode2, AI_Mode_2_Register);	start_stop_select |= AI_STOP_Sync;	if( boardtype.reg_611x ){		start_stop_select |= AI_STOP_Polarity;		start_stop_select |= AI_STOP_Select( 31 );	}else{		start_stop_select |= AI_STOP_Select( 19 );	}	win_out(start_stop_select, AI_START_STOP_Select_Register);	devpriv->ai_cmd2 = 0;	switch(cmd->stop_src){	case TRIG_COUNT:		stop_count = cmd->stop_arg - 1;		if( boardtype.reg_611x ){			// have to take 3 stage adc pipeline into account			stop_count += num_adc_stages_611x;		}		/* stage number of scans */		win_out2( stop_count, AI_SC_Load_A_Registers);		mode1 |= AI_Start_Stop | AI_Mode_1_Reserved | AI_Trigger_Once;		win_out(mode1,AI_Mode_1_Register);		/* load SC (Scan Count) */		win_out(AI_SC_Load,AI_Command_1_Register);		devpriv->ai_continuous = 0;		if( stop_count == 0 ){			devpriv->ai_cmd2 |= AI_End_On_End_Of_Scan;			interrupt_a_enable|=AI_STOP_Interrupt_Enable;		}		break;	case TRIG_NONE:		/* stage number of scans */		win_out(0,AI_SC_Load_A_Registers);		win_out(0,AI_SC_Load_A_Registers+1);		mode1 |= AI_Start_Stop | AI_Mode_1_Reserved | AI_Continuous;		win_out(mode1,AI_Mode_1_Register);		/* load SC (Scan Count) */		win_out(AI_SC_Load,AI_Command_1_Register);		devpriv->ai_continuous = 1;		break;	}	switch(cmd->scan_begin_src){	case TRIG_TIMER:		/*			stop bits for non 611x boards			AI_SI_Special_Trigger_Delay=0			AI_Pre_Trigger=0			AI_START_STOP_Select_Register:			AI_START_Polarity=0 (?)	rising edge			AI_START_Edge=1		edge triggered			AI_START_Sync=1 (?)			AI_START_Select=0		SI_TC			AI_STOP_Polarity=0		rising edge			AI_STOP_Edge=0		level			AI_STOP_Sync=1			AI_STOP_Select=19		external pin (configuration mem)		 */		start_stop_select |= AI_START_Edge | AI_START_Sync;		win_out(start_stop_select, AI_START_STOP_Select_Register);		mode2 |= AI_SI_Reload_Mode(0);		/* AI_SI_Initial_Load_Source=A */		mode2 &= ~AI_SI_Initial_Load_Source;		//mode2 |= AI_SC_Reload_Mode;		win_out(mode2, AI_Mode_2_Register);		/* load SI */		timer=ni_ns_to_timer(&cmd->scan_begin_arg,TRIG_ROUND_NEAREST);		win_out2(timer,AI_SI_Load_A_Registers);		win_out(AI_SI_Load,AI_Command_1_Register);		break;	case TRIG_EXT:/* Level trigger usually doesn't work, making it the default * doesn't make sense.  Disabling it. *//*		if( cmd->scan_begin_arg & CR_EDGE ) */		start_stop_select |= AI_START_Edge;		/* AI_START_Polarity==1 is falling edge */		if( cmd->scan_begin_arg & CR_INVERT )			start_stop_select |= AI_START_Polarity;		if( cmd->scan_begin_src != cmd->convert_src ||			( cmd->scan_begin_arg & ~CR_EDGE ) != ( cmd->convert_arg & ~CR_EDGE ) )			start_stop_select |= AI_START_Sync;		start_stop_select |= AI_START_Select(1+(cmd->scan_begin_arg&0xf));		win_out(start_stop_select, AI_START_STOP_Select_Register);		break;	}	switch(cmd->convert_src){	case TRIG_TIMER:	case TRIG_NOW:		if( cmd->convert_arg == 0 || cmd->convert_src == TRIG_NOW )			timer = 1;		else			timer=ni_ns_to_timer(&cmd->convert_arg, TRIG_ROUND_NEAREST);		win_out(1,AI_SI2_Load_A_Register); /* 0,0 does not work. */		win_out(timer,AI_SI2_Load_B_Register);		/* AI_SI2_Reload_Mode = alternate */		/* AI_SI2_Initial_Load_Source = A */		mode2 &= ~AI_SI2_Initial_Load_Source;		mode2 |= AI_SI2_Reload_Mode;		win_out( mode2, AI_Mode_2_Register);		/* AI_SI2_Load */		win_out(AI_SI2_Load,AI_Command_1_Register);		mode2 |= AI_SI2_Reload_Mode; // alternate		mode2 |= AI_SI2_Initial_Load_Source; // B		win_out(mode2,AI_Mode_2_Register);		break;	case TRIG_EXT:		mode1 |= AI_CONVERT_Source_Select(1+cmd->convert_arg);		if( ( cmd->convert_arg & CR_INVERT ) == 0 )			mode1 |= AI_CONVERT_Source_Polarity;		win_out(mode1,AI_Mode_1_Register);		mode2 |= AI_Start_Stop_Gate_Enable | AI_SC_Gate_Enable;		win_out(mode2, AI_Mode_2_Register);		break;	}	if(dev->irq){		/* interrupt on FIFO, errors, SC_TC */		interrupt_a_enable |= AI_Error_Interrupt_Enable|			AI_SC_TC_Interrupt_Enable;#ifndef PCIDMA		interrupt_a_enable|=AI_FIFO_Interrupt_Enable;#endif		if(s->async->cb_mask&COMEDI_CB_EOS){			/* wake on end-of-scan */			devpriv->aimode=AIMODE_SCAN;		}else{			devpriv->aimode=AIMODE_HALF_FULL;		}		switch(devpriv->aimode){		case AIMODE_HALF_FULL:			/*generate FIFO interrupts and DMA requests on half-full */#ifdef PCIDMA			win_out(AI_FIFO_Mode_HF_to_E, AI_Mode_3_Register);#else			win_out(AI_FIFO_Mode_HF, AI_Mode_3_Register);#endif			break;		case AIMODE_SAMPLE:			/*generate FIFO interrupts on non-empty */			win_out(AI_FIFO_Mode_NE, AI_Mode_3_Register);			break;		case AIMODE_SCAN:#ifdef PCIDMA			win_out(AI_FIFO_Mode_NE, AI_Mode_3_Register);#else			win_out(AI_FIFO_Mode_HF, AI_Mode_3_Register);#endif			interrupt_a_enable|=AI_STOP_Interrupt_Enable;			break;		default:			break;		}		win_out(0x3f80,Interrupt_A_Ack_Register); /* clear interrupts */		ni_set_bits(dev, Interrupt_A_Enable_Register, interrupt_a_enable, 1);		MDPRINTK("Interrupt_A_Enable_Register = 0x%04x\n",devpriv->int_a_enable_reg);	}else{		/* interrupt on nothing */		ni_set_bits(dev, Interrupt_A_Enable_Register, ~0, 0);		/* XXX start polling if necessary */		MDPRINTK("interrupting on nothing\n");	}	/* end configuration */	win_out(AI_Configuration_End,Joint_Reset_Register);	switch(cmd->scan_begin_src){	case TRIG_TIMER:		win_out(AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm,			AI_Command_1_Register);		break;	case TRIG_EXT:		/* XXX AI_SI_Arm? */		win_out(AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm,			AI_Command_1_Register);		break;	}#ifdef PCIDMA	ni_ai_setup_MITE_dma(dev,cmd);	//mite_dump_regs(devpriv->mite);#endif	switch(cmd->start_src){	case TRIG_NOW:		/* AI_START1_Pulse */		win_out( AI_START1_Pulse | devpriv->ai_cmd2, AI_Command_2_Register );		s->async->inttrig=NULL;		break;	case TRIG_EXT:		s->async->inttrig=NULL;		break;	case TRIG_INT:		s->async->inttrig=ni_ai_inttrig;		break;	}	MDPRINTK("exit ni_ai_cmd\n");	return 0;}static int ni_ai_inttrig(comedi_device *dev,comedi_subdevice *s,	unsigned int trignum){	if(trignum!=0)return -EINVAL;	win_out( AI_START1_Pulse | devpriv->ai_cmd2, AI_Command_2_Register );	s->async->inttrig=NULL;	return 1;}static int ni_ai_config_analog_trig(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn, lsampl_t *data);static int ni_ai_insn_config(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn, lsampl_t *data){	if(insn->n<1)return -EINVAL;	switch(data[0]){	case INSN_CONFIG_ANALOG_TRIG:		return ni_ai_config_analog_trig(dev,s,insn,data);	case INSN_CONFIG_ALT_SOURCE:		{		unsigned int calib_source;		unsigned int calib_source_adjust;		calib_source = data[1] & 0xf;		calib_source_adjust = ( data[1] >> 4 ) & 0xff;		if(calib_source >= 8)			return -EINVAL;		devpriv->ai_calib_source = calib_source;		if( boardtype.reg_611x ){			ni_writeb( calib_source_adjust, Cal_Gain_Select_611x );		}		return 2;		}	}	return -EINVAL;}static int ni_ai_config_analog_trig(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn, lsampl_t *data){	unsigned int a,b,modebits;	int err=0;	/* data[1] is flags	 * data[2] is analog line	 * data[3] is set level	 * data[4] is reset level */	if(!boardtype.has_analog_trig)return -EINVAL;	if(insn->n!=5)return -EINVAL;	if((data[1]&0xffff0000) != COMEDI_EV_SCAN_BEGIN){		data[1]&=~(COMEDI_EV_SCAN_BEGIN&0xffff);		err++;	}	if(data[2]>=boardtype.n_adchan){		data[2]=boardtype.n_adchan-1;		err++;	}	if(data[3]>255){ /* a */		data[3]=255;		err++;	}	if(data[4]>255){ /* b */		data[4]=255;		err++;	}	/*	 * 00 ignore	 * 01 set	 * 10 reset	 *	 * modes:	 *   1 level:			 +b-   +a-	 *     high mode		00 00 01 10	 *     low mode			00 00 10 01	 *   2 level: (a<b)	 *     hysteresis low mode	10 00 00 01	 *     hysteresis high mode	01 00 00 10	 *     middle mode		10 01 01 10	 */	a=data[3];	b=data[4];	modebits=data[1]&0xff;	if(modebits&0xf0){		/* two level mode */		if(b<a){			/* swap order */			a=data[4];			b=data[3];			modebits=((data[1]&0xf)<<4)|((data[1]&0xf0)>>4);		}		devpriv->atrig_low = a;		devpriv->atrig_high = b;		switch(modebits){		case 0x81:	/* low hysteresis mode */			devpriv->atrig_mode = 6;			break;		case 0x42:	/* high hysteresis mode */			devpriv->atrig_mode = 3;			break;		case 0x96:	/* middle window mode */			devpriv->atrig_mode = 2;			break;		default:			data[1]&=~0xff;			err++;		}	}else{		/* one level mode */		if(b!=0){			data[4]=0;			err++;		}		switch(modebits){		case 0x06:	/* high window mode */			devpriv->atrig_high = a;			devpriv->atrig_mode = 0;			break;		case 0x09:	/* low window mode */			devpriv->atrig_low = a;			devpriv->atrig_mode = 1;			break;		default:			data[1]&=~0xff;			err++;		}	}	if(err)return -EAGAIN;	return 5;}/* munge data from unsigned to 2's complement for analog output bipolar modes */static void ni_ao_munge(comedi_device *dev, comedi_subdevice *s,	void *data, unsigned int num_bytes, unsigned int chan_index ){	comedi_async *async = s->async;	unsigned int range;	unsigned int i;	unsigned int offset;	unsigned int length = num_bytes / sizeof( sampl_t );	sampl_t *array = data;	offset = 1 << (boardtype.aobits - 1);	for(i = 0; i < length; i++)	{		range = CR_RANGE( async->cmd.chanlist[ chan_index ] );		if(boardtype.ao_unipolar == 0 || (range & 1) == 0 )			array[i] -= offset;#ifdef PCIDMA		array[i] = __cpu_to_le16( array[i] );#endif		chan_index++;		chan_index %= async->cmd.chanlist_len;	}}static int ni_ao_config_chanlist(comedi_device *dev, comedi_subdevice *s,	unsigned int chanspec[], unsigned int n_chans){	unsigned int range;	unsigned int chan;	unsigned int conf;	int i, bits;	int invert = 0;	if( boardtype.reg_611x ){		ao_win_out( CLEAR_WG, AO_Misc_611x);		bits = 0;		for(i = 0; i < n_chans; i++){			chan = CR_CHAN( chanspec[i] );			bits |= 1 << chan;			ao_win_out( chan, AO_Waveform_Generation_611x);		}		ao_win_out(bits, AO_Timed_611x);	}else{		for(i=0;i<n_chans;i++){			chan = CR_CHAN(chanspec[i]);			range = CR_RANGE(chanspec[i]);			conf = AO_Channel(chan);			if(boardtype.ao_unipolar){				if((range&1) == 0){					conf |= AO_Bipolar;					invert = (1<<(boardtype.aobits-1));				}else{					invert = 0;				}				if(range&2)					conf |= AO_Ext_Ref;			}else{				conf |= AO_Bipolar;				invert = (1<<(boardtype.aobits-1));			}			/* not all boards can deglitch, but this shouldn't hurt */			if(chanspec[i] & CR_DEGLITCH)				conf |= AO_Deglitch;			/* analog reference */			/* AREF_OTHER connects AO ground to AI ground, i think */			conf |= (CR_AREF(chanspec[i])==AREF_OTHER)? AO_Ground_Ref : 0;			devpriv->ao_conf[chan] = conf;			ni_writew(conf,AO_Configuration);		}	}	return invert;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -