* Introduction

	This is the readme for the PCL812 dsp card driver. In this file you
will find information about the card and how to use the driver. This code is
distributed under the GNU public license, see COPYING for details. The code
is in beta stage, so don't expect too much from it. *I* consider it still
beta because it hasn't been tested enough, but it seems to work perfectly
for what I've tested. The driver is no longer maintained, so if you find
bugs don't email me unless you want to continue with this project (I can't
maintain it mostly because I haven't any PCL812 at home :(

* The PCL-812PG. Technical description

   The PCL-812 is an ISA DSP from Advantech wich has:

	- 16 analog inputs (12 bit res.)
	-  2 analog outputs (unipolar/bipolar via switches, 12 bit res.)
	-  1 digital input (16 bits)
	-  1 digital output (16 bits)
	-  3 timers (16 bit each), two in cascade and the third for
				   general usage

   This card features Polling, Interrupts and DMA modes (you can switch
modes via ioctl()).
   Timers 1 and 2 are typically used to generate a frequency, an A/D rate.
You will also control timers via ioctls.
   After intalling the driver (see INSTALL), you'll find the channels mapped
in these files:

-- Analog inputs (read only)

   /dev/adc0
   /dev/adc1
       .
       .
       .
   /dev/adc15  

-- Analog outputs (write only)

   /dev/dac0
   /dev/dac1


-- Digital Input/Output (read write)

   /dev/dio

   Note that the analog inputs and outputs have 12 bit resolution, so you'll
have to read 2 bytes from these files (read(fd,&buff,2)). If you read just 1
byte, you'll get the lowest 8 bits from the 12. If you read 4 bytes, you'll
have 2 samples, 2 bytes for sample -from the 16 bits, just the lowest 12 are
significant, 4 highest will always be zero-. Se examples read.c and write.c.
The same goes for analog outputs and digital I/O. This is a character device
driver, so no one stops you from reading/writing just one byte -getting the
lower part-.
   If you want to convert the data readen to a specific voltage, use this
formula:

   Volts= MiniumVoltage+ Resolution(Volts)*DataReaden;

 i.e, if the dsp is set to read -10..+10V, resolution will be 20/2^12==
20/4096. 


* Ioctl's

 ioctl(int fd, int request, long arg);

 request can be:

 PCL_SET_GAIN, to configure the internal OpAmp. You specify the gain in the
argument. Gain can be 0..4: 0==x1, 1==x2, 2==x4, 3==x8, 4==x16. Gains avobe
4 are invalid.

 PCL_SET_MODE_CONTROL. With this request you configure the card mode
(Polling, Interrupt or DMA). Use PCL_SET_MODE_POLLING,
PCL_SET_MODE_INTERRUPT, and PCL_SET_MODE_DMA defined in pcl.h. Interrupt and
DMA modes are normally used with timers. i.e you specify a sample rate
programing the timers and then switch to DMA mode.

 PCL_SET_TIMER_CONTROL. This is the request used to handle the timers
operation. With it you can specify the waveform, the mode and the base
(binary or octal). You must program timers 1 and 2 to specify the sampling
rate, remember that timer 0 is for general purposes.
  For this request, the argument should be some definitions contained in
pcl.h OR'ed, i.e:

	ioctl(fd,PCL_SET_TIMER_CONTROL,PCL_SET_TIMER1|PCL_COUNTER_SQUARE_WAVE 
		|PCL_COUNTER_BINARY);

	ioctl(fd,PCL_SET_TIMER_CONTROL,PCL_SET_TIMER2|PCL_COUNTER_SQUARE_WAVE 
		|PCL_COUNTER_BINARY);

 Now you have programed the timers mode, you can load them with the
frequency value. See below. If the timers operation doesn't look very clear,
refer to some electronics book that talks about the i8253 chip wich the card
uses.

 PCL_SET_COUNTERn. Note that the 'n' can be 0, 1 or 2. This request is used
to store a value into a timer. i.e, if you do

	ioctl(fd,PCL_SET_COUNTER1,30);
	ioctl(fd,PCL_SET_COUNTER2,30);

 and then switch to DMA mode, you will be reading at 2Mhz/30/30=2.2Khz:

 2Mhz--> Timer2 -> 2Mhz/30 -> Timer1 -> 2Mhz/30/30 -> Trigger signal (pulses
at 2.2Khz). 
   

 PCL_READ_COUNTERn. Use this to read a timer value (useless unless you are
using low -very low- frequencies). Argument should be the pointer to the
short int *value:
 
  short int value;
  ioctl(fd,PCL_READ_COUNTER2,&value);

---
 Happy Linuxing!
 Dani Pardo, dani@enpl.es
