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

📄 rtd520.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	    if (cmd->scan_begin_arg < RTD_MAX_SPEED_1) {		cmd->scan_begin_arg = RTD_MAX_SPEED_1;		rtd_ns_to_timer(&cmd->scan_begin_arg, TRIG_ROUND_UP);		err++;	    }	    if (cmd->scan_begin_arg > RTD_MIN_SPEED_1) {		cmd->scan_begin_arg = RTD_MIN_SPEED_1;		rtd_ns_to_timer(&cmd->scan_begin_arg, TRIG_ROUND_DOWN);		err++;	    }	} else {	    if (cmd->scan_begin_arg < RTD_MAX_SPEED) {		cmd->scan_begin_arg = RTD_MAX_SPEED;		rtd_ns_to_timer(&cmd->scan_begin_arg, TRIG_ROUND_UP);		err++;	    }	    if (cmd->scan_begin_arg > RTD_MIN_SPEED) {		cmd->scan_begin_arg = RTD_MIN_SPEED;		rtd_ns_to_timer(&cmd->scan_begin_arg, TRIG_ROUND_DOWN);		err++;	    }	}    } else {	/* external trigger */	/* should be level/edge, hi/lo specification here */	/* should specify multiple external triggers */	if (cmd->scan_begin_arg > 9) {	    cmd->scan_begin_arg = 9;	    err++;	}    }    if (cmd->convert_src==TRIG_TIMER) {	if (1 == cmd->chanlist_len) {	/* no scanning */	    if (cmd->convert_arg < RTD_MAX_SPEED_1) {		cmd->convert_arg = RTD_MAX_SPEED_1;		rtd_ns_to_timer(&cmd->convert_arg, TRIG_ROUND_UP);		err++;	    }	    if (cmd->convert_arg > RTD_MIN_SPEED_1) {		cmd->convert_arg = RTD_MIN_SPEED_1;		rtd_ns_to_timer(&cmd->convert_arg, TRIG_ROUND_DOWN);		err++;	    }	} else {	    if (cmd->convert_arg < RTD_MAX_SPEED) {		cmd->convert_arg = RTD_MAX_SPEED;		rtd_ns_to_timer(&cmd->convert_arg, TRIG_ROUND_UP);		err++;	    }	    if (cmd->convert_arg > RTD_MIN_SPEED) {		cmd->convert_arg = RTD_MIN_SPEED;		rtd_ns_to_timer(&cmd->convert_arg, TRIG_ROUND_DOWN);		err++;	    }	}    } else {	/* external trigger */	/* see above */	if (cmd->convert_arg > 9) {	    cmd->convert_arg = 9;	    err++;	}    }#if 0    if (cmd->scan_end_arg != cmd->chanlist_len) {	cmd->scan_end_arg = cmd->chanlist_len;	err++;    }#endif    if (cmd->stop_src==TRIG_COUNT) {	/* TODO check for rounding error due to counter wrap */    } else {	/* TRIG_NONE */	if (cmd->stop_arg!=0) {	    cmd->stop_arg=0;	    err++;	}    }    if (err) {	return 3;    }    /* step 4: fix up any arguments */    if (cmd->chanlist_len > RTD_MAX_CHANLIST) {	cmd->chanlist_len = RTD_MAX_CHANLIST;	err++;    }    if (cmd->scan_begin_src == TRIG_TIMER) {	tmp=cmd->scan_begin_arg;	rtd_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){	tmp=cmd->convert_arg;	rtd_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;}/*  Execute a analog in command with many possible triggering options.  The data get stored in the async structure of the subdevice.  This is usually done by an interrupt handler.  Userland gets to the data using read calls.*/static int rtd_ai_cmd (    comedi_device *dev,    comedi_subdevice *s){    comedi_cmd *cmd=&s->async->cmd;    int timer;					/* stop anything currently running */    RtdPacerStopSource (dev, 0);	/* stop on SOFTWARE stop */    RtdPacerStop (dev);			/* make sure PACER is stopped */    RtdAdcConversionSource (dev, 0);	/* software trigger only */    RtdInterruptMask (dev, 0);#ifdef USE_DMA    if (devpriv->flags & DMA0_ACTIVE) { /* cancel anything running */	RtdPlxInterruptWrite (dev,	/* disable any more interrupts */			      RtdPlxInterruptRead (dev) & ~ICS_DMA0_E);	abort_dma (dev, 0);	devpriv->flags &= ~DMA0_ACTIVE;	if (RtdPlxInterruptRead (dev) & ICS_DMA0_A) { /*clear pending int*/	    RtdDma0Control (dev, PLX_CLEAR_DMA_INTR_BIT);	}    }    RtdDma0Reset (dev);			/* reset onboard state */#endif /* USE_DMA */    RtdAdcClearFifo (dev);		/* clear any old data */    RtdInterruptOverrunClear(dev);    devpriv->intCount = 0;    if (! dev->irq) {			/* we need interrupts for this */	DPRINTK ("rtd520: ERROR! No interrupt available!\n");	return -ENXIO;    }    /* start configuration */    /* load channel list and reset CGT */    rtd_load_channelgain_list (dev, cmd->chanlist_len, cmd->chanlist);    /* setup the common case and override if needed */    if (cmd->chanlist_len > 1) {	/*DPRINTK ("rtd520: Multi channel setup\n");*/	RtdPacerStartSource (dev, 0);	/* software triggers pacer */	RtdBurstStartSource (dev, 1);	/* PACER triggers burst */	RtdAdcConversionSource (dev, 2); /* BURST triggers ADC */    } else {				/* single channel */	/*DPRINTK ("rtd520: single channel setup\n");*/	RtdPacerStartSource (dev, 0);	/* software triggers pacer */	RtdAdcConversionSource (dev, 1); /* PACER triggers ADC */    }    RtdAboutCounter (dev, thisboard->fifoLen/2 - 1); /* 1/2 FIFO */    if (TRIG_TIMER == cmd->scan_begin_src) {					/* scan_begin_arg is in nanoseconds */	/* find out how many samples to wait before transferring */	if (cmd->flags & COMEDI_EV_SCAN_END) {	    /* this may generate un-sustainable interrupt rates */	    /* the application is responsible for doing the right thing */	    devpriv->transCount = cmd->chanlist_len;	    devpriv->flags |= SEND_EOS;	} else {	    /* arrange to transfer data periodically */	    devpriv->transCount		= (TRANS_TARGET_PERIOD*cmd->chanlist_len)/cmd->scan_begin_arg;	    if (devpriv->transCount < cmd->chanlist_len) {		/* tranfer after each scan (and avoid 0) */		devpriv->transCount = cmd->chanlist_len;	    } else {			/* make a multiple of scan length */		devpriv->transCount =		    (devpriv->transCount + cmd->chanlist_len - 1)		    / cmd->chanlist_len;		devpriv->transCount *= cmd->chanlist_len;	    }	    devpriv->flags |= SEND_EOS;	}	if (devpriv->transCount >= (thisboard->fifoLen /2)) {	    /* out of counter range, use 1/2 fifo instead */	    devpriv->transCount = 0;	    devpriv->flags &= ~SEND_EOS;	} else {	    /* interrupt for each tranfer */	    RtdAboutCounter (dev, devpriv->transCount-1);	}	DPRINTK ("rtd520: scanLen=%d tranferCount=%d fifoLen=%d\n  scanTime(ns)=%d flags=0x%x\n",		 cmd->chanlist_len, devpriv->transCount, thisboard->fifoLen,		 cmd->scan_begin_arg, devpriv->flags);    } else {				/* unknown timing, just use 1/2 FIFO */	devpriv->transCount = 0;	devpriv->flags &= ~SEND_EOS;    }    RtdPacerClockSource (dev, 1);	/* use INTERNAL 8Mhz clock source */    RtdAboutStopEnable (dev, 1);	/* just interrupt, dont stop */    /* BUG??? these look like enumerated values, but they are bit fields */    /* First, setup when to stop */    switch(cmd->stop_src){    case TRIG_COUNT:			/* stop after N scans */	devpriv->aiCount = cmd->stop_arg * cmd->chanlist_len;	if ((devpriv->transCount > 0)	    && (devpriv->transCount > devpriv->aiCount)) {	    devpriv->transCount = devpriv->aiCount;	}	break;    case TRIG_NONE:			/* stop when cancel is called */	devpriv->aiCount = -1;		/* read forever */	break;    default:	DPRINTK ("rtd520: Warning! ignoring stop_src mode %d\n",		cmd->stop_src);    }    /* Scan timing */    switch (cmd->scan_begin_src) {    case TRIG_TIMER:			/* periodic scanning */	timer=rtd_ns_to_timer(&cmd->scan_begin_arg,TRIG_ROUND_NEAREST);	/* set PACER clock */	/*DPRINTK ("rtd520: loading %d into pacer\n", timer);*/	RtdPacerCounter (dev, timer);	break;    case TRIG_EXT:	RtdPacerStartSource (dev, 1);	/* EXTERNALy trigger pacer */	break;    default:	DPRINTK ("rtd520: Warning! ignoring scan_begin_src mode %d\n",		cmd->scan_begin_src);    }    /* Sample timing within a scan */    switch(cmd->convert_src){    case TRIG_TIMER:			/* periodic */	if (cmd->chanlist_len > 1) {	/* only needed for multi-channel */	    timer=rtd_ns_to_timer(&cmd->convert_arg,TRIG_ROUND_NEAREST);	    /* setup BURST clock */	    /*DPRINTK ("rtd520: loading %d into burst\n", timer);*/	    RtdBurstCounter (dev, timer);	}	break;    case TRIG_EXT:			/* external */	RtdBurstStartSource (dev, 2);	/* EXTERNALy trigger burst */	break;    default:	DPRINTK ("rtd520: Warning! ignoring convert_src mode %d\n",		cmd->convert_src);    }    /* end configuration */    /* This doesn't seem to work.  There is no way to clear an interrupt       that the priority controller has queued! */    RtdInterruptClearMask (dev, ~0); /* clear any existing flags */    RtdInterruptClear (dev);    /* TODO: allow multiple interrupt sources */    if (devpriv->transCount > 0) {	/* transfer every N samples */	RtdInterruptMask (dev, IRQM_ADC_ABOUT_CNT);	DPRINTK ("rtd520: Transferring every %d\n", devpriv->transCount);    }    else {			       /* 1/2 FIFO transfers */#ifdef USE_DMA	devpriv->flags |= DMA0_ACTIVE;		/* point to first transfer in ring */	devpriv->dma0Offset = 0;	RtdDma0Mode (dev, DMA_MODE_BITS);	RtdDma0Next (dev,		/* point to first block */		     devpriv->dma0Chain[DMA_CHAIN_COUNT-1].next);	RtdDma0Source (dev, DMAS_ADFIFO_HALF_FULL); /* set DMA trigger source*/	RtdPlxInterruptWrite (dev,	/* enable interrupt */			      RtdPlxInterruptRead (dev) | ICS_DMA0_E);	/* Must be 2 steps.  See PLX app note about "Starting a DMA transfer"*/	RtdDma0Control (dev, PLX_DMA_EN_BIT); /* enable DMA (clear INTR?) */	RtdDma0Control (dev, PLX_DMA_EN_BIT | PLX_DMA_START_BIT); /*start DMA*/	DPRINTK ("rtd520: Using DMA0 transfers. plxInt %x RtdInt %x\n", 		 RtdPlxInterruptRead (dev), devpriv->intMask);#else /* USE_DMA */	RtdInterruptMask (dev, IRQM_ADC_ABOUT_CNT );	DPRINTK ("rtd520: Transferring every 1/2 FIFO\n");#endif /* USE_DMA */    }    /* BUG: start_src is ASSUMED to be TRIG_NOW */    /* BUG? it seems like things are running before the "start" */    RtdPacerStart (dev);		/* Start PACER */    return 0;}/*  Stop a running data aquisition.*/static int rtd_ai_cancel (    comedi_device *dev,    comedi_subdevice *s){    u16 status;    RtdPacerStopSource (dev, 0);	/* stop on SOFTWARE stop */    RtdPacerStop (dev);			/* Stop PACER */    RtdAdcConversionSource (dev, 0);	/* software trigger only */    RtdInterruptMask (dev, 0);    devpriv->aiCount = 0;		/* stop and don't transfer any more */#ifdef USE_DMA    if (devpriv->flags & DMA0_ACTIVE) {	RtdPlxInterruptWrite (dev,	/* disable any more interrupts */			      RtdPlxInterruptRead (dev) & ~ICS_DMA0_E);	abort_dma (dev, 0);	devpriv->flags &= ~DMA0_ACTIVE;    }#endif /* USE_DMA */    status = RtdInterruptStatus (dev);    DPRINTK("rtd520: Acquisition canceled. %ld ints, intStat=%x, overStat=%x\n",	    devpriv->intCount,	    status,	    0xffff & RtdInterruptOverrunStatus (dev));    return 0;}/*  Given a desired period and the clock period (both in ns),  return the proper counter value (divider-1).  Sets the original period to be the true value.  Note: you have to check if the value is larger than the counter range!*/static int rtd_ns_to_timer_base (    unsigned int *nanosec,		/* desired period (in ns) */    int round_mode,    int base)			/* clock period (in ns) */{    int divider;    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 < 2) divider = 2;	/* min is divide by 2 */    /* Note: we don't check for max, because different timers       have different ranges */    *nanosec=base*divider;    return divider - 1;			/* countdown is divisor+1 */}/*  Given a desired period (in ns),  return the proper counter value (divider-1) for the internal clock.  Sets the original period to be the true value.*/static int rtd_ns_to_timer (    unsigned int *ns,    int round_mode){    return rtd_ns_to_timer_base (ns, round_mode, RTD_CLOCK_BASE);}/*  Output one (or more) analog values to a single port as fast as possible.*/static int rtd_ao_winsn (    comedi_device *dev,    comedi_subdevice *s,    comedi_insn *insn,    lsampl_t *data){    int i;    int chan = CR_CHAN (insn->chanspec);    int range = CR_RANGE (insn->chanspec);    /* Configure the output range (table index matches the range values) */    RtdDacRange (dev, chan, range);    /* Writing a list of values to an AO channel is probably not     * very useful, but that's how the interface is defined. */    for (i=0; i < insn->n; ++i){	int	val = data[i] << 3;	int	stat = 0;		/* initialize to avoid bogus warning */	int	ii;	/* VERIFY: comedi range and offset conversions */	if ((range > 1)			/* bipolar */	    && (data[i] < 2048)) {					/* offset and sign extend */	    val = (((int)data[i]) - 2048) << 3;	} else {			/* 

⌨️ 快捷键说明

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