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

📄 me_daq.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   comedi/drivers/me_daq.c   Hardware driver for Meilhaus data acquisition cards:     ME-2000i, ME-2600i, ME-3000vm1   Copyright (C) 2002 Michael Hillmann <hillmann@syscongroup.de>    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*//*Driver: me_daq.oDescription: Driver for the Meilhaus PCI data acquisition cards.Author: Michael Hillmann <hillmann@syscongroup.de>Devices: [Meilhaus] ME-2600i (me_daq), ME-2000iStatus: experimentalSupports:    Analog OutputConfiguration options:    [0] - PCI bus number (optional)    [1] - PCI slot number (optional)    If bus/slot is not specified, the first available PCI    device will be used.*/#include <linux/comedidev.h>#include <linux/pci.h>//#include "me2600_fw.h"#define ME_DRIVER_NAME                 "me_daq"#define ME2000_DEVICE_ID               0x2000#define ME2600_DEVICE_ID               0x2600#define PLX_INTCSR                     0x4C      // PLX interrupt status register#define XILINX_DOWNLOAD_RESET          0x42      // Xilinx registers#define ME_CONTROL_1                   0x0000    // - | W#define   INTERRUPT_ENABLE             (1<<15)#define   COUNTER_B_IRQ                (1<<12)#define   COUNTER_A_IRQ                (1<<11)#define   CHANLIST_READY_IRQ           (1<<10)#define   EXT_IRQ                      (1<<9)#define   ADFIFO_HALFFULL_IRQ          (1<<8)#define   SCAN_COUNT_ENABLE            (1<<5)#define   SIMULTANEOUS_ENABLE          (1<<4)#define   TRIGGER_FALLING_EDGE         (1<<3)#define   CONTINUOUS_MODE              (1<<2)#define   DISABLE_ADC                  (0<<0)#define   SOFTWARE_TRIGGERED_ADC       (1<<0)#define   SCAN_TRIGGERED_ADC           (2<<0)#define   EXT_TRIGGERED_ADC            (3<<0)#define ME_ADC_START                   0x0000    // R | -#define ME_CONTROL_2                   0x0002    // - | W#define   ENABLE_ADFIFO                (1<<10)#define   ENABLE_CHANLIST              (1<<9)#define   ENABLE_PORT_B                (1<<7)#define   ENABLE_PORT_A                (1<<6)#define   ENABLE_COUNTER_B             (1<<4)#define   ENABLE_COUNTER_A             (1<<3)#define   ENABLE_DAC                   (1<<1)#define   BUFFERED_DAC                 (1<<0)#define ME_DAC_UPDATE                  0x0002    // R | -#define ME_STATUS                      0x0004    // R | -#define   COUNTER_B_IRQ_PENDING        (1<<12)#define   COUNTER_A_IRQ_PENDING        (1<<11)#define   CHANLIST_READY_IRQ_PENDING   (1<<10)#define   EXT_IRQ_PENDING              (1<<9)#define   ADFIFO_HALFFULL_IRQ_PENDING  (1<<8)#define   ADFIFO_FULL                  (1<<4)#define   ADFIFO_HALFFULL              (1<<3)#define   ADFIFO_EMPTY                 (1<<2)#define   CHANLIST_FULL                (1<<1)#define   FST_ACTIVE                   (1<<0)#define ME_RESET_INTERRUPT             0x0004    // - | W#define ME_DIO_PORT_A                  0x0006    // R | W#define ME_DIO_PORT_B                  0x0008    // R | W#define ME_TIMER_DATA_0                0x000A    // - | W#define ME_TIMER_DATA_1                0x000C    // - | W#define ME_TIMER_DATA_2                0x000E    // - | W#define ME_CHANNEL_LIST                0x0010    // - | W#define   ADC_UNIPOLAR                 (1<<6)#define   ADC_GAIN_0                   (0<<4)#define   ADC_GAIN_1                   (1<<4)#define   ADC_GAIN_2                   (2<<4)#define   ADC_GAIN_3                   (3<<4)#define ME_READ_AD_FIFO                0x0010    // R | -#define ME_DAC_CONTROL                 0x0012    // - | W#define   DAC_UNIPOLAR_D               (0<<4)#define   DAC_BIPOLAR_D                (1<<4)#define   DAC_UNIPOLAR_C               (0<<5)#define   DAC_BIPOLAR_C                (1<<5)#define   DAC_UNIPOLAR_B               (0<<6)#define   DAC_BIPOLAR_B                (1<<6)#define   DAC_UNIPOLAR_A               (0<<7)#define   DAC_BIPOLAR_A                (1<<7)#define   DAC_GAIN_0_D                 (0<<8)#define   DAC_GAIN_1_D                 (1<<8)#define   DAC_GAIN_0_C                 (0<<9)#define   DAC_GAIN_1_C                 (1<<9)#define   DAC_GAIN_0_B                 (0<<10)#define   DAC_GAIN_1_B                 (1<<10)#define   DAC_GAIN_0_A                 (0<<11)#define   DAC_GAIN_1_A                 (1<<11)#define ME_DAC_CONTROL_UPDATE          0x0012    // R | -#define ME_DAC_DATA_A                  0x0014    // - | W#define ME_DAC_DATA_B                  0x0016    // - | W#define ME_DAC_DATA_C                  0x0018    // - | W#define ME_DAC_DATA_D                  0x001A    // - | W#define ME_COUNTER_ENDDATA_A           0x001C    // - | W#define ME_COUNTER_ENDDATA_B           0x001E    // - | W#define ME_COUNTER_STARTDATA_A         0x0020    // - | W#define ME_COUNTER_VALUE_A             0x0020    // R | -#define ME_COUNTER_STARTDATA_B         0x0022    // - | W#define ME_COUNTER_VALUE_B             0x0022    // R | -//// Function prototypes//static int me_attach(comedi_device *dev, comedi_devconfig *it);static int me_detach(comedi_device *dev);static comedi_lrange me2000_ai_range={  8,  {    BIP_RANGE(10),    BIP_RANGE(5),    BIP_RANGE(2.5),    BIP_RANGE(1.25),    UNI_RANGE(10),    UNI_RANGE(5),    UNI_RANGE(2.5),    UNI_RANGE(1.25)  }};static comedi_lrange me2600_ai_range={  8,  {    BIP_RANGE(10),    BIP_RANGE(5),    BIP_RANGE(2.5),    BIP_RANGE(1.25),    UNI_RANGE(10),    UNI_RANGE(5),    UNI_RANGE(2.5),    UNI_RANGE(1.25)  }};static comedi_lrange me2600_ao_range={  3,  {    BIP_RANGE(10),    BIP_RANGE(5),    UNI_RANGE(10)  }};static struct pci_device_id me_pci_table[] __devinitdata ={  { PCI_VENDOR_ID_MEILHAUS, ME2600_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },  { PCI_VENDOR_ID_MEILHAUS, ME2000_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },  { 0 }};MODULE_DEVICE_TABLE(pci, me_pci_table);//// Board specification structure//typedef struct{  char          *name;              // driver name  int           device_id;  int           ao_channel_nbr;     // DA config  int           ao_resolution;  int           ao_resolution_mask;  comedi_lrange *ao_range_list;  int           ai_channel_nbr;     // AD config  int           ai_resolution;  int           ai_resolution_mask;  comedi_lrange *ai_range_list;  int           dio_channel_nbr;    // DIO config} me_board_struct;static me_board_struct me_boards[] ={  {                                                     // -- ME-2600i --    name:                         ME_DRIVER_NAME,    device_id:                    ME2600_DEVICE_ID,    ao_channel_nbr:               4,                    // Analog Output    ao_resolution:                12,    ao_resolution_mask:           0x0fff,    ao_range_list:                &me2600_ao_range,    ai_channel_nbr:               16,                   // Analog Input    ai_resolution:                12,    ai_resolution_mask:           0x0fff,    ai_range_list:                &me2600_ai_range,    dio_channel_nbr:              32,  },  {                                                     // -- ME-2000i --    name:                         ME_DRIVER_NAME,    device_id:                    ME2000_DEVICE_ID,    ao_channel_nbr:               0,                    // Analog Output    ao_resolution:                0,    ao_resolution_mask:           0,    ao_range_list:                0,    ai_channel_nbr:               16,                   // Analog Input    ai_resolution:                12,    ai_resolution_mask:           0x0fff,    ai_range_list:                &me2000_ai_range,    dio_channel_nbr:              32,  }};#define me_board_nbr (sizeof(me_boards)/sizeof(me_board_struct))static comedi_driver me_driver={  driver_name: ME_DRIVER_NAME,  module:      THIS_MODULE,  attach:      me_attach,  detach:      me_detach,  num_names:   me_board_nbr,  board_name:  me_boards,  offset:      sizeof(me_board_struct),};COMEDI_INITCLEANUP(me_driver);//// Private data structure//typedef struct{  struct pci_dev* pci_device;  unsigned int plx_regbase;         // PLX configuration base address  unsigned int me_regbase;          // Base address of the Meilhaus card  unsigned int plx_regbase_size;    // Size of PLX configuration space  unsigned int me_regbase_size;     // Size of Meilhaus space  unsigned short control_1;         // Mirror of CONTROL_1 register  unsigned short control_2;         // Mirror of CONTROL_2 register  unsigned short dac_control;       // Mirror of the DAC_CONTROL register  int ao_readback[4];               // Mirror of analog output data} me_private_data_struct;#define dev_private ((me_private_data_struct *)dev->private)// ------------------------------------------------------------------//// Helpful functions//// ------------------------------------------------------------------static __inline__ void sleep(unsigned sec){  current->state = TASK_INTERRUPTIBLE;  schedule_timeout(sec*HZ);}// ------------------------------------------------------------------//// DIGITAL INPUT/OUTPUT SECTION//// ------------------------------------------------------------------static int me_dio_insn_config(comedi_device *dev,                              comedi_subdevice *s,                              comedi_insn *insn,                              lsampl_t *data){  int bits;  int mask = 1 << CR_CHAN(insn->chanspec);  /* calculate port */  if(mask & 0x0000ffff) /* Port A in use */  {    bits = 0x0000ffff;    /* Enable Port A */    dev_private->control_2 |= ENABLE_PORT_A;    writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);  }  else                  /* Port B in use */  {    bits = 0xffff0000;    /* Enable Port B */    dev_private->control_2 |= ENABLE_PORT_B;    writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);  }  if(data[0])  /* Config port as output */  {    s->io_bits |= bits;  }  else         /* Config port as input */  {    s->io_bits &= ~bits;  }  return 1;}//// Digital instant input/outputs//static int me_dio_insn_bits(comedi_device *dev,                            comedi_subdevice *s,                            comedi_insn *insn,                            lsampl_t *data){  unsigned int mask = data[0];  s->state &= ~mask;  s->state |= (mask & data[1]);  mask &= s->io_bits;  if(mask & 0x0000ffff) /* Port A */  {    writew((s->state & 0xffff), dev_private->me_regbase + ME_DIO_PORT_A);  }  else  {    data[1] &= ~0x0000ffff;    data[1] |= readw(dev_private->me_regbase + ME_DIO_PORT_A);  }  if(mask & 0xffff0000) /* Port B */  {    writew(((s->state >> 16) & 0xffff), dev_private->me_regbase + ME_DIO_PORT_B);  }  else  {    data[1] &= ~0xffff0000;    data[1] |= readw(dev_private->me_regbase + ME_DIO_PORT_B) << 16;  }  return 2;}// ------------------------------------------------------------------//// ANALOG INPUT SECTION//// ------------------------------------------------------------------//// Analog instant input//static int me_ai_insn_read(comedi_device *dev,                           comedi_subdevice *subdevice,                           comedi_insn *insn,                           lsampl_t *data){  unsigned short value;  int chan = CR_CHAN((&insn->chanspec)[0]);  int rang = CR_RANGE((&insn->chanspec)[0]);  int aref = CR_AREF((&insn->chanspec)[0]);  int i;  /* stop any running conversion */  dev_private->control_1 &= 0xFFFC;  writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);  /* clear chanlist and ad fifo */  dev_private->control_2 &= ~(ENABLE_ADFIFO | ENABLE_CHANLIST);  writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);  /* reset any pending interrupt */  writew(0x00, dev_private->me_regbase + ME_RESET_INTERRUPT);  /* enable the chanlist and ADC fifo */  dev_private->control_2 |= (ENABLE_ADFIFO | ENABLE_CHANLIST);  writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);  /* write to channel list fifo */  value  = chan & 0x0f;                      // b3:b0 are the channel number  value |= (rang & 0x03) << 4;               // b5:b4 are the channel gain  value |= (rang & 0x04) << 4;               // b6 channel polarity  value |= ((aref & AREF_DIFF) ? 0x80 : 0);  // b7 single or differential  writew(value & 0xff, dev_private->me_regbase + ME_CHANNEL_LIST);  /* set ADC mode to software trigger */  dev_private->control_1 |= SOFTWARE_TRIGGERED_ADC;  writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);  /* start conversion by reading from ADC_START */  readw(dev_private->me_regbase + ME_ADC_START);  /* wait for ADC fifo not empty flag */  for(i = 100000; i > 0; i--)  {    if(!(readw(dev_private->me_regbase + ME_STATUS) & 0x0004))    {      break;    }  }  /* get value from ADC fifo*/  if(i)  {    data[0] = (readw(dev_private->me_regbase + ME_READ_AD_FIFO) ^ 0x800) & 0x0FFF;  }  else  {

⌨️ 快捷键说明

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