📄 adl_pci9118.c
字号:
ch=CR_CHAN(insn->chanspec); if (ch) { chanreg=PCI9118_DA2;} else { chanreg=PCI9118_DA1; } for (n=0; n<insn->n; n++) { outl(data[n], dev->iobase + chanreg); devpriv->ao_data[ch]=data[n]; } return n;}/* ==============================================================================*/static int pci9118_insn_read_ao(comedi_device * dev, comedi_subdevice * s, comedi_insn *insn, lsampl_t *data) { int n,chan; chan=CR_CHAN(insn->chanspec); for (n=0; n<insn->n; n++) data[n]=devpriv->ao_data[chan]; return n;}/*==============================================================================*/static int pci9118_insn_bits_di(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data){ data[1] = inl(dev->iobase + PCI9118_DI) & 0xf; return 2;}/*==============================================================================*/static int pci9118_insn_bits_do(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]); outl(s->state & 0x0f, dev->iobase + PCI9118_DO); } data[1] = s->state; return 2;}/*==============================================================================*/static void interrupt_pci9118_ai_mode4_switch(comedi_device *dev) { devpriv->AdFunctionReg=AdFunction_PDTrg|AdFunction_PETrg|AdFunction_AM; outl(devpriv->AdFunctionReg,dev->iobase+PCI9118_ADFUNC); outl(0x30, dev->iobase + PCI9118_CNTCTRL); outl((devpriv->dmabuf_hw[1-devpriv->dma_actbuf]>>1)&0xff, dev->iobase + PCI9118_CNT0); outl((devpriv->dmabuf_hw[1-devpriv->dma_actbuf]>>9)&0xff, dev->iobase + PCI9118_CNT0); devpriv->AdFunctionReg|=AdFunction_Start; outl(devpriv->AdFunctionReg,dev->iobase+PCI9118_ADFUNC);}/* ============================================================================== Skip a few samples at begin of every scan if is used software generated sample&hold signal*/static int skip_front_samples_16b(comedi_device *dev, comedi_subdevice *s, sampl_t **dma, int *bufs, char x){ unsigned int n; n=devpriv->ai_add_front-devpriv->ai_act_dmapos; // DPRINTK("n=%d bufs=%d *dma=0x%08x dmapos=%d %d\n",n,*bufs,*dma,devpriv->ai_act_dmapos,x); if (*bufs>n) { (*bufs)-=n; (*dma)+=n; devpriv->ai_act_dmapos+=n;// well, whole begin is skipped// DPRINTK("0 bufs=%d *dma=0x%08x dmapos=%d\n",*bufs,*dma,devpriv->ai_act_dmapos); return 0; } else { // we cann't skip all (*dma)+=*bufs; devpriv->ai_act_dmapos+=*bufs; (*bufs)=0;// DPRINTK("1 bufs=%d *dma=0x%08x dmapos=%d\n",*bufs,*dma,devpriv->ai_act_dmapos); return 1; // no more samples in source } return -1;}/*==============================================================================*/static int move_block_from_dma_12bit_16b(comedi_device *dev, comedi_subdevice *s, void *dma_void, int *sampls, int *bufs){ unsigned int cc,sp,chans,chns; sampl_t sampl; uint16_t **dma = (uint16_t **) dma_void; cc=s->async->cur_chan; sp=devpriv->ai_act_scanpos; chans=devpriv->ai_n_chan;// DPRINTK("bufs:%d sampls:%d dmapos=%d cc=%d sp=%d\n",*bufs,*sampls,devpriv->ai_act_dmapos,cc,sp); while (*bufs&&*sampls) { if (devpriv->ai_add_front) // skip added front if (skip_front_samples_16b(dev, s, dma, bufs, 2)) break; chns=chans;// DPRINTK("0 cc=%d sp=%d *bufs=%d *sampls=%d chns=%d/%d dmapos=%d\n",cc,sp,*bufs,*sampls,chns,chans,devpriv->ai_act_dmapos); (*bufs)-=chns-cc; (*sampls)-=chns-cc; if (*sampls<0) { (*bufs)-=*sampls; chns+=*sampls; *sampls=0; }// DPRINTK("1 cc=%d sp=%d *bufs=%d *sampls=%d chns=%d/%d dmapos=%d\n",cc,sp,*bufs,*sampls,chns,chans,devpriv->ai_act_dmapos); if ((*bufs<0)||(*sampls<0)) { s->async->events|=COMEDI_CB_ERROR|COMEDI_CB_EOA; pci9118_ai_cancel(dev,s); comedi_event(dev,s,s->async->events); return -1; } for (;cc<chns;cc++) { sampl=**dma; (*dma)++;#ifdef PCI9118_PARANOIDCHECK if ((sampl & 0x0f00)!=devpriv->chanlist[cc]) { rt_printk("comedi: A/D DMA - data dropout: received channel %04x, expected %04x!\n",(sampl & 0x0f00),devpriv->chanlist[cc]); DPRINTK("comedi: bufs=%d cc=%d sp=%d dmapos=%d chans=%d af=%d ab=%d sampls=%d (dma)=%04x dma=%04x!\n",*bufs,cc,sp,devpriv->ai_act_dmapos,chans,devpriv->ai_add_front,devpriv->ai_add_back,*sampls,*(*dma-1),(int)(*dma-1)); s->async->events|=COMEDI_CB_ERROR|COMEDI_CB_EOA; pci9118_ai_cancel(dev,s); comedi_event(dev,s,s->async->events); return -1; }#endif sampl=((sampl & 0xff)<<4)|((sampl & 0xf000)>>12); // get one sample cfc_write_to_buffer( s, sampl); } sp+=cc; if (cc>=chans) { cc=0; devpriv->ai_act_dmapos=0; if (devpriv->ai_add_back) // drop added one if (*bufs) { (*bufs)--; (*dma)++; } } if(sp>=devpriv->ai_n_scanlen) { // is end of one scan? sp=0; devpriv->ai_act_scan++; if (*sampls) if (devpriv->ai_flags & TRIG_WAKE_EOS) { comedi_event(dev,s,s->async->events); s->async->events=0; } } }// DPRINTK("9 cc=%d sp=%d *bufs=%d *sampls=%d chns=%d/%d dmapos=%d\n",cc,sp,*bufs,*sampls,chns,chans,devpriv->ai_act_dmapos); devpriv->ai_act_scanpos=sp; return 0;}/*==============================================================================*/static int move_block_from_dma_16bit_16b(comedi_device *dev, comedi_subdevice *s, void *dma_void, int *sampls, int *bufs){ unsigned int cc,sp,chans,chns; sampl_t sampl; uint16_t **dma = (uint16_t **) dma_void; cc=s->async->cur_chan; sp=devpriv->ai_act_scanpos; chans=devpriv->ai_n_chan;// DPRINTK("bufs:%d sampls:%d dmapos=%d cc=%d sp=%d\n",*bufs,*sampls,devpriv->ai_act_dmapos,cc,sp); while (*bufs&&*sampls) { if (devpriv->ai_add_front) // skip added front if (skip_front_samples_16b(dev, s, dma, bufs, 2)) break; chns=chans;// DPRINTK("0 cc=%d sp=%d *bufs=%d *sampls=%d chns=%d/%d dmapos=%d\n",cc,sp,*bufs,*sampls,chns,chans,devpriv->ai_act_dmapos); (*bufs)-=chns-cc; (*sampls)-=chns-cc; if (*sampls<0) { (*bufs)-=*sampls; chns+=*sampls; *sampls=0; }// DPRINTK("1 cc=%d sp=%d *bufs=%d *sampls=%d chns=%d/%d dmapos=%d\n",cc,sp,*bufs,*sampls,chns,chans,devpriv->ai_act_dmapos); if ((*bufs<0)||(*sampls<0)) { s->async->events|=COMEDI_CB_ERROR|COMEDI_CB_EOA; pci9118_ai_cancel(dev,s); comedi_event(dev,s,s->async->events); return -1; } for (;cc<chns;cc++) { sampl=**dma; (*dma)++; sampl=(((sampl & 0xff)<<8)|((sampl & 0xff00)>>8))^0x8000; // get one sample cfc_write_to_buffer( s, sampl ); } sp+=cc; if (cc>=chans) { cc=0; devpriv->ai_act_dmapos=0; if (devpriv->ai_add_back) // drop added one if (*bufs) { (*bufs)--; (*dma)++; } } if(sp>=devpriv->ai_n_scanlen) { // is end of one scan? sp=0; devpriv->ai_act_scan++; if (*sampls) if (devpriv->ai_flags & TRIG_WAKE_EOS) { comedi_event(dev,s,s->async->events); s->async->events=0; } } }// DPRINTK("9 cc=%d sp=%d *bufs=%d *sampls=%d chns=%d/%d dmapos=%d\n",cc,sp,*bufs,*sampls,chns,chans,devpriv->ai_act_dmapos); devpriv->ai_act_scanpos=sp; return 0;}/*============================================================================== Skip a few samples at begin of every scan if is used software generated sample&hold signal*/static int skip_front_samples_32b(comedi_device *dev, comedi_subdevice *s, lsampl_t **dma, unsigned int *bufs, char x){ unsigned int n; n=(devpriv->ai_add_front-devpriv->ai_act_dmapos)>>1;// DPRINTK("n=%d bufs=%d *dma=0x%08x dmapos=%d %d\n",n,*bufs,*dma,devpriv->ai_act_dmapos,x); if (*bufs>n) { (*bufs)-=n; (*dma)+=n; devpriv->ai_act_dmapos+=n;// well, whole begin is skipped// DPRINTK("0 bufs=%d *dma=0x%08x dmapos=%d\n",*bufs,*dma,devpriv->ai_act_dmapos); return 0; } else { // we cann't skip all (*dma)+=*bufs; devpriv->ai_act_dmapos+=*bufs; (*bufs)=0;// DPRINTK("1 bufs=%d *dma=0x%08x dmapos=%d\n",*bufs,*dma,devpriv->ai_act_dmapos); return 1; // no more samples in source } return -1;}/*==============================================================================*/static int move_block_from_dma_12bit_32b(comedi_device *dev, comedi_subdevice *s, void *dma_void, int *sampls, int *bufs){ int cc,sp,chans,chns,xx,yy; lsampl_t sampl;#ifdef PCI9118_PARANOIDCHECK lsampl_t *chanlist=(lsampl_t *)devpriv->chanlist;#endif uint32_t ** dma = ( uint32_t ** ) dma_void; cc=s->async->cur_chan; sp=devpriv->ai_act_scanpos; chans=devpriv->ai_n_chan>>1; xx=*bufs>>1; yy=*sampls>>1; while (xx&&yy) { if (devpriv->ai_add_front) // skip added front if (skip_front_samples_32b(dev, s, dma, &xx, 2)) break; chns=chans; xx-=chns-cc; yy-=chns-cc; if (yy<0) { xx-=yy; chns+=yy; yy=0; } for (;cc<chns;cc++) { sampl=**dma; (*dma)++;#ifdef PCI9118_PARANOIDCHECK if ((sampl & 0x000f000f)!=chanlist[cc]) { rt_printk("comedi: A/D DMA - data dropout: received channel %08x, expected %08x!\n",(sampl & 0x000f000f),chanlist[cc]); DPRINTK("comedi: bufs=%d cc=%d sp=%d dmapos=%d chns=%d chans=%d af=%d ab=%d sampls=%d (dma)=%08x dma=%08x!\n",*bufs,cc,sp,devpriv->ai_act_dmapos,chns,chans,devpriv->ai_add_front,devpriv->ai_add_back,*sampls,*(*dma-1),(int)(*dma-1)); s->async->events|=COMEDI_CB_ERROR|COMEDI_CB_EOA; pci9118_ai_cancel(dev,s); comedi_event(dev,s,s->async->events); return -1; }#endif sampl=((sampl & 0xfff0)<<12)|((sampl & 0xfff00000)>>20); cfc_write_long_to_buffer( s, sampl ); } sp+=cc<<1; if (cc>=chans) { cc=0; devpriv->ai_act_dmapos=0; } if(sp>=devpriv->ai_n_scanlen) { // is end of one scan? sp=0; devpriv->ai_act_scan++; if (*sampls) if (devpriv->ai_flags & TRIG_WAKE_EOS) { comedi_event(dev,s,s->async->events); s->async->events=0; } } } *bufs-=*bufs-(xx<<1); *sampls-=*sampls-(yy<<1); devpriv->ai_act_scanpos=sp; return 0;}/*==============================================================================*/static int move_block_from_dma_16bit_32b(comedi_device *dev, comedi_subdevice *s, void *dma_void, int *sampls, int *bufs){ int cc,sp,chans,chns,xx,yy; lsampl_t sampl; uint32_t **dma = ( uint32_t ** ) dma_void; cc=s->async->cur_chan; sp=devpriv->ai_act_scanpos; chans=devpriv->ai_n_chan>>1; xx=*bufs>>1; yy=*sampls>>1; while (xx&&yy) { if (devpriv->ai_add_front) // skip added front if (skip_front_samples_32b(dev, s, dma, &xx, 2)) break; chns=chans; xx-=chns-cc; yy-=chns-cc; if (yy<0) { xx-=yy; chns+=yy; yy=0; } for (;cc<chns;cc++) { sampl=**dma; (*dma)++; sampl=(((sampl & 0xffff)<<16)|((sampl & 0xffff0000)>>16))^0x80008000; cfc_write_long_to_buffer( s, sampl ); } sp+=cc<<1; if (cc>=chans) { cc=0; devpriv->ai_act_dmapos=0; } if(sp>=devpriv->ai_n_scanlen) { // is end of one scan? sp=0; devpriv->ai_act_scan++; if (*sampls) if (devpriv->ai_flags & TRIG_WAKE_EOS) { comedi_event(dev,s,s->async->events); s->async->events=0; } } } *bufs-=*bufs-(xx<<1); *sampls-=*sampls-(yy<<1); devpriv->ai_act_scanpos=sp; return 0;}/* ==============================================================================*/static char pci9118_decode_error_status(comedi_device *dev,comedi_subdevice *s,unsigned char m){ if (m & 0x100) { comedi_error(dev,"A/D FIFO Full status (Fatal Error!)"); devpriv->ai_maskerr&=~0x100L;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -