Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
180 lines (151 sloc) 8.69 KB
This is a port of the old PCI-AI12-16 data acquision driver for Linux to
a more recent kernel version (2.6.34 as of right now.)
Note, the license does not seem to work well with the GPL, so it can not
be distributed with the rest of the Linux kernel source tree. I have
only forward ported the driver, fixing the obvious build warnings and
errors. I do not know if it works at all, or even what to do with this
Please address any questions to the original author, not me.
The original README is below and the original source code, with
userspace testing code, is in the original/ subdirectory.
Greg Kroah-Hartman <>
March 16, 2010
PCI-AI12-16 Data acquisition board driver documentation.
Sun Mar 2 21:03:43 EDST 2003 Richard B. Johnson
Many D/A Converter input boards and their software tend
to take over your computer. This driver does not. The
normal mode of operation has it quietly acquiring data
on all of its input channels all of the time. The data
from each of the channels is also filtered, using an
IIR filter, to help remove noise. When a user program
wants to read the data, it just reads a structure
(buffer) containing the data from all 16 channels.
It can do this at any time without upsetting the
on-going conversion cycles.
The other mode of operation is to acquire data on any
single channel as fast as is possible. All of the
parameters are settable. Using this mode, you can
convert data up to about a 2.0 microsecond rate even
without a FIFO on the board.
In all cases, the data is presented to the API (you)
as an ordinary `int`, having been properly sign-extended,
etc. Since it has only 12 effective bits, it produces
data from -2048 to +2048 counts. You scale this to
whatever you want.
I downloaded the stuff that was supposed to be a Linux
driver for this board. It expected me to have some kind
of special environment installed. I gave up. Instead of
using that Linux stuff, I wrote a new driver. The driver
implements the Unix/Linux way of accessing hardware by
using device files. Using simple system calls like open(),
close(), read(), and ioctl(), you can access all the
functions of this board. Further, you don't need to be
concerned with the specifics of the hardware. The driver
does that. You can set up the board how you want it using
ioctl() function calls. This is all documented in the
header file, adcboard.h.
The present code uses a device major number of 177 for
access to the driver. You can change that to any unused
major number and re-compile the driver. The driver is
designed as a module for Linux versions 2.4.n on up. It
would have to be modified to work with version 2.5 because
the Linux developers keep changing the driver interface.
The program, tester, tests all the functions of the
board. It also shows how to use the driver because it
tests everything. Read the comments in tester.c, in
particular how to set up a filter. The driver provides
a built-in IIR filter that reduces real-world noise quite
well. It is not good to average data values in user-
mode code because the time at which the averaging occurs
is more-or-less random. The user, therefore, creates a
filter with a random pole which produces random results.
Not good. This driver provides a filter with distinct
characteristics, synchronized to the data-acquisition
interval. The filter uses fixed-point mathematics and
never accumulates a round-off error. The usual averaging
methods use division which has a round-off error that
eventually accumulates to the value of 1 less than the
divisor. The method used here accumulates no round-
off error so you end up filtering the data without
accumulating a bias. Although the instantaneous error
could be as large at 1 less than the divisor, the average
error is zero. I should have patented this 30 years
ago when I invented it in the days of 8-bit processors.
To make the driver and its test-code, execute `make clean'.
Then execute `make'. This should compile without warnings
if you have the Linux source-code installed in the correct
place. If not, you need to install the source-code for
the Linux version you are using in the correct place.
If your Linux version is 2.4.1, the correct place to install
the Linux source-code is in /usr/src/linux-2.4.1. As long
as the kernel you are using supports modules, you do not
need to actually build the kernel from its source but you
do need to configure the source so that the links to the
header files are correctly set. The source-code for this
driver needs only to interface with the header files in
the source-code tree.
To install the driver, you execute `ismod adcboard.o`.
If you want a GPL license within the code to prevent unrelated
panics from saying "tainted", execute `insmod ioadc.o` instead.
This second object file contains the GPL signature as well
as the driver code. Read the source, license.c, to find out
what it's about. It's about politics and a certain jerk who
wants to take credit for the work of thousands of individuals,
When you install the driver, it automatically determines
what resources are required and sets them up accordingly.
If you execute `dmesg` or read one of the log files in
/var/log, you will see:
ACCES I/O PRODUCTS PCI-AI12-16 A: Version = V1.1
ACCES I/O PRODUCTS PCI-AI12-16 A: I/O length = 16
ACCES I/O PRODUCTS PCI-AI12-16 A: Interrupt = 10
ACCES I/O PRODUCTS PCI-AI12-16 A: Dev. major = 177
ACCES I/O PRODUCTS PCI-AI12-16 A: Patches to
ACCES I/O PRODUCTS PCI-AI12-16 A: Initialization complete
The actual I/O space may be different on your machine, that's
what PnP is all about. This driver is designed to be able to
share an interrupt and it can also operate in a machine with
two or more CPUs.
If the board with a FIFO has been detected, the product
identification will look as shown. If there is no FIFO
on your board, the "A" at the end will be missing.
After the device driver module is installed, you can execute
`tester` to watch it work. Review the source-code, tester.c
to see how to integrate the new driver and its interface into
your application. Good luck. Notice from the source code,
tester.c, you can make a special device "file" anywhere.
they do not have to be in "/dev". In the test program, I
just create one if I found that one doesn't exist. A device-
file is just a "trick" to associate a file-descriptor with
a "major-number". Your code never actually accesses this
"file" so it's not a bottleneck. Also note that the first
invocation of `tester` must be by root to create the required
device file in the test directory.
In the "real world", you would probably create the correct
device-file in /dev so everybody could access it. You would,
after becoming root, execute:
mknod /dev/ADC c 177 0
chown root.sys /dev/ADC
chmod 666 /dev/ADC
You can execute in the source-code directory
to perform this same feat if your fingers are cold. If you
change the major-number, remember to update this file.
Then, change the file-name in tester.c so you can use the
new device file you created.
Once you are satisfied with the driver, you can modify one
of the system start-up files to load the module automatically
each time you boot. Probably the easiest thing to do is to
add two lines to /etc/modules.conf. First, add, near its
beginning: "path[ioadc]=/complete/path/to/driver" (no quotes).
Second, anywhere, add: "alias char-major-177 ioadc" (no quotes).
Then execute `depmod ioadc`. The driver will be loaded as
soon as you need it, and will be unloaded after a few hours
of inactivity. It will continue to be reloaded anytime you
need it.
If you add any additional functionality or find some bugs, please
send me a patch.
Richard B. Johnson