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

📄 dt282x.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		comedi_error(dev, "A/D error");		dt282x_ai_cancel(dev,s);		s->async->events |= COMEDI_CB_ERROR;		comedi_event(dev,s,s->async->events);			return;	}	supcsr = inw(dev->iobase + DT2821_SUPCSR);	/*printk("supcsr=%02x\n",supcsr);*/	if (supcsr & DT2821_DMAD) {		if(devpriv->dma_dir==DMA_MODE_READ)			dt282x_ai_dma_interrupt(dev);		else			dt282x_ao_dma_interrupt(dev);		return;	}	if ((dacsr = inw(dev->iobase + DT2821_DACSR)) & DT2821_DAERR) {#if 0		static int warn = 5;		if(--warn<=0){			disable_irq(dev->irq);			printk("disabling irq\n");		}#endif		comedi_error(dev, "D/A error");		dt282x_ao_cancel(dev,s_ao);		s->async->events |= COMEDI_CB_ERROR;		comedi_event(dev,s_ao,s->async->events);			return;	}	if (adcsr & DT2821_ADDONE) {		data = (sampl_t) inw(dev->iobase + DT2821_ADDAT);		data&=(1<<boardtype.adbits)-1;		if(devpriv->ad_2scomp){			data^=1<<(boardtype.adbits-1);		}		ret = comedi_buf_put( s->async, data );		if(ret==0){			s->async->events |= COMEDI_CB_OVERFLOW;		}		devpriv->nread--;		if(!devpriv->nread){			s->async->events |= COMEDI_CB_EOA;		}else{			if(supcsr&DT2821_SCDN)				update_supcsr(DT2821_STRIG);		}		comedi_event(dev,s,s->async->events);			return;	}}static void dt282x_load_changain(comedi_device * dev, int n, unsigned int *chanlist){	unsigned int i;	unsigned int chan, range;	outw(DT2821_LLE | (n - 1), dev->iobase + DT2821_CHANCSR);	for (i = 0; i < n; i++) {		chan = CR_CHAN(chanlist[i]);		range = CR_RANGE(chanlist[i]);		update_adcsr((range << 4) | (chan));	}	outw(n - 1, dev->iobase + DT2821_CHANCSR);}/* *    Performs a single A/D conversion. *      - Put channel/gain into channel-gain list *      - preload multiplexer *      - trigger conversion and wait for it to finish */static int dt282x_ai_insn_read(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn, lsampl_t *data){	int i;	devpriv->adcsr = DT2821_ADCLK;	update_adcsr(0);	dt282x_load_changain(dev, 1, &insn->chanspec);	update_supcsr(DT2821_PRLD);	wait_for(!mux_busy(),		 comedi_error(dev, "timeout\n");		 return -ETIME;	    );	for(i=0;i<insn->n;i++){		update_supcsr(DT2821_STRIG);		wait_for(ad_done(),			comedi_error(dev, "timeout\n");			return -ETIME;		    );		data[i] = inw(dev->iobase + DT2821_ADDAT) & ((1<<boardtype.adbits)-1);		if (devpriv->ad_2scomp)			data[i] ^= (1 << (boardtype.adbits - 1));	}	return i;}static int dt282x_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,comedi_cmd *cmd){	int err=0;	int tmp;	/* step 1: make sure trigger sources are trivially valid */	tmp=cmd->start_src;	cmd->start_src &= TRIG_NOW;	if(!cmd->start_src || tmp!=cmd->start_src)err++;	tmp=cmd->scan_begin_src;	cmd->scan_begin_src &= TRIG_FOLLOW|TRIG_EXT;	if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++;	tmp=cmd->convert_src;	cmd->convert_src &= TRIG_TIMER;	if(!cmd->convert_src || tmp!=cmd->convert_src)err++;	tmp=cmd->scan_end_src;	cmd->scan_end_src &= TRIG_COUNT;	if(!cmd->scan_end_src || tmp!=cmd->scan_end_src)err++;	tmp=cmd->stop_src;	cmd->stop_src &= TRIG_COUNT|TRIG_NONE;	if(!cmd->stop_src || tmp!=cmd->stop_src)err++;	if(err)return 1;	/* step 2: make sure trigger sources are unique and mutually compatible */	/* note that mutual compatiblity is not an issue here */	if(cmd->scan_begin_src!=TRIG_FOLLOW &&	   cmd->scan_begin_src!=TRIG_EXT)err++;	if(cmd->stop_src!=TRIG_COUNT &&	   cmd->stop_src!=TRIG_NONE)err++;	if(err)return 2;	/* step 3: make sure arguments are trivially compatible */	if(cmd->start_arg!=0){		cmd->start_arg=0;		err++;	}	if(cmd->scan_begin_src==TRIG_FOLLOW){		/* internal trigger */		if(cmd->scan_begin_arg!=0){			cmd->scan_begin_arg=0;			err++;		}	}else{		/* external trigger */		/* should be level/edge, hi/lo specification here */		if(cmd->scan_begin_arg!=0){			cmd->scan_begin_arg=0;			err++;		}	}	if(cmd->convert_arg<4000){		/* XXX board dependent */		cmd->convert_arg=4000;		err++;	}#define SLOWEST_TIMER	(250*(1<<15)*255)	if(cmd->convert_arg>SLOWEST_TIMER){		cmd->convert_arg=SLOWEST_TIMER;		err++;	}	if(cmd->scan_end_arg!=cmd->chanlist_len){		cmd->scan_end_arg=cmd->chanlist_len;		err++;	}	if(cmd->stop_src==TRIG_COUNT){		/* any count is allowed */	}else{		/* TRIG_NONE */		if(cmd->stop_arg!=0){			cmd->stop_arg=0;			err++;		}	}	if(err)return 3;	/* step 4: fix up any arguments */	tmp=cmd->convert_arg;	dt282x_ns_to_timer(&cmd->convert_arg,cmd->flags&TRIG_ROUND_MASK);	if(tmp!=cmd->convert_arg)err++;	if(err)return 4;	return 0;}static int dt282x_ai_cmd(comedi_device * dev, comedi_subdevice * s){	comedi_cmd *cmd=&s->async->cmd;	int timer;	timer=dt282x_ns_to_timer(&cmd->convert_arg,TRIG_ROUND_NEAREST);	outw(timer, dev->iobase + DT2821_TMRCTR);	if(cmd->scan_begin_src==TRIG_FOLLOW){		/* internal trigger */		devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS0;	}else{		/* external trigger */		devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS0 | DT2821_DS1;	}	update_supcsr(DT2821_CLRDMADNE | DT2821_BUFFB | DT2821_ADCINIT);	devpriv->adcsr = 0;	devpriv->ntrig=cmd->stop_arg*cmd->scan_end_arg;	devpriv->nread=devpriv->ntrig;	devpriv->dma_dir=DMA_MODE_READ;	devpriv->current_dma_chan=0;	prep_ai_dma(dev,0,0);	enable_dma(devpriv->dma[0].chan);	if(devpriv->ntrig){		prep_ai_dma(dev,1,0);		enable_dma(devpriv->dma[1].chan);		devpriv->supcsr |= DT2821_DDMA;		update_supcsr(0);	}	devpriv->adcsr = DT2821_ADCLK | DT2821_IADDONE;	update_adcsr(0);	dt282x_load_changain(dev,cmd->chanlist_len,cmd->chanlist);	devpriv->adcsr = DT2821_ADCLK | DT2821_IADDONE;	update_adcsr(0);	update_supcsr(DT2821_PRLD);	wait_for(!mux_busy(),		 comedi_error(dev, "timeout\n");		 return -ETIME;	    );	if(cmd->scan_begin_src==TRIG_FOLLOW){		update_supcsr(DT2821_STRIG);	}else{		devpriv->supcsr |= DT2821_XTRIG;		update_supcsr(0);	}	return 0;}static int dt282x_ai_cancel(comedi_device * dev, comedi_subdevice * s){	devpriv->adcsr=0;	update_adcsr(0);	devpriv->supcsr = 0;	update_supcsr(DT2821_ADCINIT);	return 0;}static int dt282x_ns_to_timer(int *nanosec,int round_mode){	int prescale,base,divider;	for(prescale=0;prescale<16;prescale++){		if(prescale==1)continue;		base=250*(1<<prescale);		switch(round_mode){		case TRIG_ROUND_NEAREST:		default:			divider=(*nanosec+base/2)/base;			break;		case TRIG_ROUND_DOWN:			divider=(*nanosec)/base;			break;		case TRIG_ROUND_UP:			divider=(*nanosec+base-1)/base;			break;		}		if(divider<256){			*nanosec=divider*base;			return (prescale<<8)|(255-divider);		}	}	base=250*(1<<15);	divider=255;	*nanosec=divider*base;	return (15<<8)|(255-divider);}/* *    Analog output routine.  Selects single channel conversion, *      selects correct channel, converts from 2's compliment to *      offset binary if necessary, loads the data into the DAC *      data register, and performs the conversion. */static int dt282x_ao_insn_read(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn, lsampl_t *data){	data[0] = devpriv->ao[CR_CHAN(insn->chanspec)];	return 1;}static int dt282x_ao_insn_write(comedi_device * dev, comedi_subdevice * s,	comedi_insn *insn, lsampl_t *data){	sampl_t d;	unsigned int chan;	chan = CR_CHAN(insn->chanspec);	d = data[0];	d &= (1<<boardtype.dabits)-1;	devpriv->ao[chan] = d;	devpriv->dacsr |= DT2821_SSEL;	if (chan) {		/* select channel */		devpriv->dacsr |= DT2821_YSEL;		if (devpriv->da0_2scomp)			d ^= (1<<(boardtype.dabits-1));	} else {		devpriv->dacsr &= ~DT2821_YSEL;		if (devpriv->da1_2scomp)			d ^= (1<<(boardtype.dabits-1));	}	update_dacsr(0);	outw(d, dev->iobase + DT2821_DADAT);	update_supcsr(DT2821_DACON);	return 1;}static int dt282x_ao_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd){	int err=0;	int tmp;	/* step 1: make sure trigger sources are trivially valid */	tmp=cmd->start_src;	cmd->start_src &= TRIG_INT;	if(!cmd->start_src || tmp!=cmd->start_src)err++;	tmp=cmd->scan_begin_src;	cmd->scan_begin_src &= TRIG_TIMER;	if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++;	tmp=cmd->convert_src;	cmd->convert_src &= TRIG_NOW;	if(!cmd->convert_src || tmp!=cmd->convert_src)err++;	tmp=cmd->scan_end_src;	cmd->scan_end_src &= TRIG_COUNT;	if(!cmd->scan_end_src || tmp!=cmd->scan_end_src)err++;	tmp=cmd->stop_src;	cmd->stop_src &= TRIG_NONE;	if(!cmd->stop_src || tmp!=cmd->stop_src)err++;	if(err)return 1;	/* step 2: make sure trigger sources are unique and mutually compatible */	/* note that mutual compatiblity is not an issue here */	if(cmd->stop_src!=TRIG_COUNT &&	   cmd->stop_src!=TRIG_NONE)err++;	if(err)return 2;	/* step 3: make sure arguments are trivially compatible */	if(cmd->start_arg!=0){		cmd->start_arg=0;		err++;	}	if(cmd->scan_begin_arg < 5000 /* XXX unknown */){		cmd->scan_begin_arg = 5000;		err++;	}	if(cmd->convert_arg != 0){		cmd->convert_arg = 0;		err++;	}	if(cmd->scan_end_arg > 2){		/* XXX chanlist stuff? */		cmd->scan_end_arg = 2;		err++;	}	if(cmd->stop_src==TRIG_COUNT){		/* any count is allowed */	}else{		/* TRIG_NONE */		if(cmd->stop_arg!=0){			cmd->stop_arg=0;			err++;		}	}	if(err)return 3;	/* step 4: fix up any arguments */	tmp=cmd->scan_begin_arg;	dt282x_ns_to_timer(&cmd->scan_begin_arg,cmd->flags&TRIG_ROUND_MASK);	if(tmp!=cmd->scan_begin_arg)err++;	if(err)return 4;	return 0;}static int dt282x_ao_inttrig(comedi_device *dev,comedi_subdevice *s,		unsigned int x){	int size;	if(x!=0)return -EINVAL;	size = comedi_buf_read_n_available(s->async);	if(size>devpriv->dma_maxsize)size=devpriv->dma_maxsize;	if( size == 0){		rt_printk("dt282x: AO underrun\n");		return -EPIPE;	}	comedi_buf_memcpy_from(s->async, 0, devpriv->dma[0].buf, size);	comedi_buf_read_free(s->async, size);	prep_ao_dma(dev,0,size);	enable_dma(devpriv->dma[0].chan);	size = comedi_buf_read_n_available(s->async);	if(size>devpriv->dma_maxsize)size=devpriv->dma_maxsize;	if( size == 0){		rt_printk("dt282x: AO underrun\n");		return -EPIPE;	}	comedi_buf_memcpy_from(s->async, 0, devpriv->dma[1].buf, size);	comedi_buf_read_free(s->async, size);	prep_ao_dma(dev,1,size);	enable_dma(devpriv->dma[1].chan);	update_supcsr(DT2821_STRIG);	s->async->inttrig=NULL;	return 1;}static int dt282x_ao_cmd(comedi_device *dev,comedi_subdevice *s){	int timer;	comedi_cmd *cmd=&s->async->cmd;	devpriv->supcsr = DT2821_ERRINTEN | DT2821_DS1 | DT2821_DDMA;	update_supcsr(DT2821_CLRDMADNE | DT2821_BUFFB | DT2821_DACINIT);	devpriv->ntrig=cmd->stop_arg*cmd->chanlist_len;	devpriv->nread=devpriv->ntrig;	devpriv->dma_dir=DMA_MODE_WRITE;	devpriv->current_dma_chan=0;	timer=dt282x_ns_to_timer(&cmd->scan_begin_arg,TRIG_ROUND_NEAREST);	outw(timer, dev->iobase + DT2821_TMRCTR);	devpriv->dacsr = DT2821_SSEL| DT2821_DACLK | DT2821_IDARDY;	update_dacsr(0);	s->async->inttrig=dt282x_ao_inttrig;	return 0;}static int dt282x_ao_cancel(comedi_device * dev, comedi_subdevice * s){	devpriv->dacsr=0;	update_dacsr(0);	devpriv->supcsr = 0;	update_supcsr(DT2821_DACINIT);	return 0;}static int dt282x_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	if(data[0]){		s->state &= ~data[0];		s->state |= (data[0]&data[1]);		outw(s->state, dev->iobase + DT2821_DIODAT);	}	data[1] = inw(dev->iobase + DT2821_DIODAT);	return 2;}static int dt282x_dio_insn_config(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	int mask;	mask=(CR_CHAN(insn->chanspec)<8)?0x00ff:0xff00;	if(data[0])s->io_bits|=mask;	else s->io_bits&=~mask;	if(s->io_bits&0x00ff)devpriv->dacsr|=DT2821_LBOE;	else devpriv->dacsr&=~DT2821_LBOE;	if(s->io_bits&0xff00)devpriv->dacsr|=DT2821_HBOE;	else devpriv->dacsr&=~DT2821_HBOE;	outw(devpriv->dacsr, dev->iobase + DT2821_DACSR);	return 1;}static comedi_lrange *ai_range_table[]={	&range_dt282x_ai_lo_bipolar,	&range_dt282x_ai_lo_unipolar,	&range_dt282x_ai_5_bipolar,	&range_dt282x_ai_5_unipolar };static comedi_lrange *ai_range_pgl_table[]={	&range_dt282x_ai_hi_bipolar,	&range_dt282x_ai_hi_unipolar };static comedi_lrange *opt_ai_range_lkup(int ispgl,int x){	if(ispgl){		if(x<0 || x>=2)x=0;		return ai_range_pgl_table[x];	}else{		if(x<0 || x>=4)x=0;		return ai_range_table[x];	}}static comedi_lrange *ao_range_table[]={	&range_bipolar10,	&range_unipolar10,	&range_bipolar5,	&range_unipolar5,	&range_bipolar2_5 };static comedi_lrange *opt_ao_range_lkup(int x){	if(x<0 || x>=5)x=0;	return ao_range_table[x];}enum{	opt_iobase=0, opt_irq, opt_dma1, opt_dma2,	/* i/o base, irq, dma channels */	opt_diff,					/* differential */	opt_ai_twos, opt_ao0_twos, opt_ao1_twos, 	/* twos comp */	opt_ai_range, opt_ao0_range, opt_ao1_range,	/* range */};/*   options:   0	i/o base   1	irq   2	dma1   3	dma2   4	0=single ended, 1=differential   5	ai 0=straight binary, 1=2's comp   6	ao0 0=straight binary, 1=2's comp   7	ao1 0=straight binary, 1=2's comp   8	ai 0=

⌨️ 快捷键说明

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