National Instruments PCI-6143 COMEDI Driver
Date | 2006-02-07 |
Author | Dr Terry Barnaby, BEAM Ltd |
Introduction
This document lists information on the COMEDI driver for the National instruments PCI-6143 DAQ board.The PCI-6143 is a DAQ card that contains 8 x 16bit Analogue to Digital converters that can simultaneously sample 8 differential analogue signals at up to 256K Samples per sec. It also has two counter/timer modules and 8 bits of digital I/O. No Digital to Analogue converters are provided.
This driver was developed for an internal project that required 3 of these boards synchronised to sample, simultaneously 24 channels of analogue data at 50KHz.
National Instruments support this card via the NIDAQmx-base system. Unfortunately this system is closed source and only supported in binary form on a limited number of Linux distributions. It is also a large lump of software and is not ideal for near real-time systems. National Instruments also produce a DDK kit which is a low level software interface to some of their boards. This uses a generic driver to communicate with boards. Unfortunatately the driver component and associated libraries (the VESA system) is closed source and not compatible with many Linux versions.
For our project, which is a real-time project, we wanted to use the Linux COMEDI system. This is open source and relatively simple. It is not tied to any particular vendors DAQ cards and offers a real-time kernel API. Unfortunately the NI PCI-6143 was not supported, but after some email conversaions with people at NI they agreed to produce and publish the register level documentation for the board.
Thanks are due to Malcolm Borgendale and Alan Armstead of National Instruments for producing the documentation for this board and providing assistance in getting this driver to work.
Overview
The PCI-6143 is a NI S-Series card. It is functionally similar to the NI M-Series and to previous NI cards. All of the main hardware is implemented in a FPGA on board and this emulates much of the original NI discrete chip hardware. In common with other NI boards its main functionality is provided by the STC "System Timing Controller" module. This module, implemented in the FPGA, implements the standard NI STC controller functions with a few minor changes. The PCI-6143's bus interface is provided by a "Mite" compatible interface, again implemented within the FPGA. The PCI-6143 has some additional board registers that provides control of the data FIFO and Calibration configuration.Due to the usage of the STC and Mite API's a lot of the standard Comedi NI driver code will operate the PCI-6143 without change. The main differences are with the FIFO handling and Calibration system.
We choose to add support to the Comedi "ni_pcimio" for this card as it best matched the board. COMEDI Support for the PCI-6143 is fairly complete but some of the functionality has not been fully tested. The board works with interrupts and DMA for data transfer and has low CPU overhead for continuous data acquisitions (around 1% CPU on our system for 8 channels at 50KHz).
As we also needed to synchronise the boards using the NI RTSI bus we have added basic support for the NI RTSI bus to COMEDI for this board and probably all the other NI boards supported by the "ni_pcimio" driver.
The source code for this driver and RTSI additions should be in the COMEDI CVS tree soon.
Notes
- The PCI-6143 has a 32bit FIFO that stores two samples per location. Trying to capture sets of data that is not a multiple of two samples may cause issues.
- The Calibration system of the PCI-6143 is different from other cards, so the COMEDI calibration programs will probably not work.
- The Digital I/O system has not been tested, but should work.
- The Counter/timer system has not been tested but should work.
- The setting of the PWM calibration source has not been tested.
SubDevices
The PCI-6143 "ni_pcimio" driver supports the following sub devices:Number | Type | Description |
---|---|---|
0 | Analogue Input | 8 differential Analogue inputs with a range of +-5Volts simultaineously sampled with 16 bits at up to 250K samples per second. Uses main connector for signal lines. |
2 | Digital I/O | 8 bits of bi-directional digital I/O on main connector. Untested |
4 | Counter/Timers | 2 Counter timers. Untested. |
5 | Calibration | Calibration devices. Sets up calibration source including PWM signal. PWM signal setting is untested. |
6 | Memory | EEPROM containing configuration parameters. Untested. |
7 | Digital I/O | PFI trigger lines on main connector. These lines can be set for input or output and can be used as triggers for capture events. |
9 | Serial | Serial device interface. Calibration DAC's have not been tested. Untested. |
10 | Digital I/O | RTSI bus on secondary connector. This bus provides bi-directional digital lines for synchronsing boards together. |
Source Code
Patch for comedi | comedi-beam-1.patch comedi-beam-2.patch |
Patch for comedilib | comedilib-beam-1.patch comedilib-beam-2.patch |
Development Information
The following link gives information on the PCI-6143 driver development including manuals etc.Testing
We have only done major testing of the driver for our particular usage. We use the following setup:3 * PCI-6143 boards set to continuously and simultaneously sample 24 channels of analogue data at 50KHz.
One of the boards is set as a master and the other two are slaved over the RTSI bus.
Example programs
There are some example programs I used for testing the driver during development.Calibration
The PCI-6143 has a single calibration source that can be connected with relays to all of the input channels simultaneously.The calibration source can be set to one of a number of settings. These are defined as:
Value | Definition | Usage |
---|---|---|
0 | Calibration_Channel_Gnd_Gnd | Offset Calibration |
2 | Calibration_Channel_2v5_Gnd | 2.5V Reference |
5 | Calibration_Channel_Pwm_Gnd | +/- 5V Self Cal |
10 | Calibration_Channel_2v5_Pwm | PWM Calibration |
11 | Calibration_Channel_Pwm_Pwm | CMRR |
14 | Calibration_Channel_Gnd_Pwm | PWM Calibration |
The INSN_CONFIG_ALT_SOURCE sets the calibration source from one of the above settings.
The INSN_CONFIG_PWM_OUTPUT command sets up the PWM signal generator.
The first channel of the data acquisition should have the "CR_ALT_SOURCE" bit set. this enables the calibration input for all of the channels.
RTSI Bus
The RTSI Bus consists of an 48 pin IDC connector on the PCI-6143 and special bus signal lines on PXI boards.There are 8 digital signal lines that are bi-directional.
Each of these signal lines can be configured as an input or output also the signal appearing on the output can be configured to one of many internal board timing signals.
We have added basic RSTI support to enable a board to be set as a master and other boards to be set as slaves.
To simplify the API and code we have hard-coded the actual set of internal timing signals that appear on the RTSI lines and just provide the ability to set the I/O direction of the lines. It would be good to add a new configure command to set up this routing to a different setup.
The COMEDI API is provided as a Digital I/O subdevice number 10 with an extra config command to set up the master clock mode.
This provides a number of configure commands through the COMEDI config API which can be accessed using the comedi_do_insn(), comedi_dio_config() and comedi_dio_get_config() functions.
The config API calls are:
API Command | Description |
---|---|
INSN_CONFIG_SET_RTSI_CLOCK_MODE | This sets the boards main clock mode. The argument defines the setting as one of: COMEDI_RTSI_CLOCK_MODE_INTERNAL - Internal Clock COMEDI_RTSI_CLOCK_MODE_OUTPUT - Run from internal clock and output this on the RTSI bus bit as RTSI_7 COMEDI_RTSI_CLOCK_MODE_SLAVE - Run from the clock on the RTSI bus bit RTSI_7 COMEDI_RTSI_CLOCK_MODE_MASTER - Output the clock on the RTSI bus bit as RTSI_7 and run from this external clock |
INSN_CONFIG_DIO_OUTPUT | Configure the "channel" bit as an output. Channel is one of NI_RTSI_[0-6] |
INSN_CONFIG_DIO_INPUT | Configure the "channel" bit as an input. Channel is one of NI_RTSI_[0-6]. |
INSN_CONFIG_DIO_QUERY | Find the direction of one of the RTSI "channels". Channel is one of NI_RTSI_[0-6]. |
The RTSI bus pins and default output routing is:
Name | Standard Routing | Pin |
---|---|---|
RTSI_0 | NI_RTSI_STD_AI_START1 | 20 |
RTSI_1 | NI_RTSI_STD_AI_START2 | 22 |
RTSI_2 | NI_RTSI_STD_AI_CONV | 24 |
RTSI_3 | NI_RTSI_STD_CT1_SRC | 26 |
RTSI_4 | NI_RTSI_STD_CT1_GATE | 28 |
RTSI_5 | NI_RTSI_STD_AO_SAMP_CLOCK | 30 |
RTSI_6 | NI_RTSI_STD_AO_START_TRIG | 32 |
RTSI_7 or RTSI_CLK | Master Clock | 34 |
The RTSI bus pins are available to be used as trigger inputs for many of the COMEDI trigger functions. To use the RTSI bus pins set the source to be TRIG_EXT and the source argument to be a value between 10 and 16 corresponding to RTSI_0 through RTSI_6. We have provided the defines NI_EXT_PFI_[0-9] and NI_EXT_RTSI_[0-6] to define all the available external trigger sources.
A simple example to set up a device as a master is given below.
void comediEnableMaster(comedi_t* dev){
comedi_insn configCmd;
lsampl_t configData[2];
int ret;
unsigned int d = 0;
// Configure the PFI bus device
memset(&configCmd, 0, sizeof(configCmd));
memset(&configData, 0, sizeof(configData));
configCmd.insn = INSN_CONFIG;
configCmd.subdev = 10;
configCmd.chanspec = 0;
configCmd.n = 2;
configCmd.data = configData;
configCmd.data[0] = INSN_CONFIG_SET_RTSI_CLOCK_MODE;
configCmd.data[1] = COMEDI_RTSI_CLOCK_MODE_MASTER;
ret = comedi_do_insn(dev, &configCmd);
if(ret < 0){
comedi_perror("comedi_command: INSN_CONFIG");
exit(1);
}
// Set direction of the 3 main AI RTSI signals to output
ret = comedi_dio_config(dev, 10, NI_RTSI_0, INSN_CONFIG_DIO_OUTPUT);
ret = comedi_dio_config(dev, 10, NI_RTSI_1, INSN_CONFIG_DIO_OUTPUT);
ret = comedi_dio_config(dev, 10, NI_RTSI_2, INSN_CONFIG_DIO_OUTPUT);
}
An example to slave a device from this master follows:
void comediEnableSlave(comedi_t* dev){
comedi_insn configCmd;
lsampl_t configData[2];
int ret;
unsigned int d = 0;;
// Configure the PFI bus device
memset(&configCmd, 0, sizeof(configCmd));
memset(&configData, 0, sizeof(configData));
configCmd.insn = INSN_CONFIG;
configCmd.subdev = 10;
configCmd.chanspec = 0;
configCmd.n = 2;
configCmd.data = configData;
configCmd.data[0] = INSN_CONFIG_SET_RTSI_CLOCK_MODE;
configCmd.data[1] = COMEDI_RTSI_CLOCK_MODE_SLAVE;
ret = comedi_do_insn(dev, &configCmd);
if(ret < 0){
comedi_perror("comedi_command: INSN_CONFIG");
exit(1);
}
}
int comediSlaveStart(comedi_t* dev){
comedi_cmd cmd;
unsigned int nChannels = 8;
double sampleRate = 50000;
unsigned int chanList[8];
int i;
// Setup chan list
for(i = 0; i < nChannels; i++){
chanList[i] = CR_PACK(i, 0, AREF_GROUND);
}
// Set up command
memset(&cmd, 0, sizeof(cmd));
ret = comedi_get_cmd_generic_timed(dev, subdevice, &cmd, int(1e9/(nChannels * sampleRate)));
if(ret<0){
printf("comedi_get_cmd_generic_timed failed\n");
return ret;
}
cmd.chanlist = chanList;
cmd.chanlist_len = nChannels;
cmd.scan_end_arg = nChannels;
cmd.start_src = TRIG_EXT;
cmd.start_arg = CR_EDGE | NI_EXT_RTSI_0;
cmd.convert_src = TRIG_EXT;
cmd.convert_arg = CR_INVERT | CR_EDGE | NI_EXT_RTSI_2;
cmd.stop_src = TRIG_NONE;
ret = comedi_command(dev0, &cmd0);
if(ret<0){
printf("comedi_command failed\n");
return ret;
}
return 0;
}