Anda di halaman 1dari 14

IOCARDs DRIVER

version 1.1

Cockpitware Janvier 2011


TABLE OF CONTENTS

1. Summary

2. Initializing the driver

3. USB expansion cards


3.a – Reading the A/D channels
3.b – Manipulating inputs
3.c – Manipulating outputs
3.d – Writing to displays
3.e – Displaying many digits: Registering Display
3.f – Playing with rotary encoders
3.g – increasing speed of rotary encoders
3.h – Reading rotary encoders
3.i – Connecting rotary encoders to displays

4. USB servos card


4.a – Sending a setpoint to the servo-controler
4.b – Reading the A/D channels

5. USB keys card

ANNEX: ERROR CODES


1. Introduction

This driver in its present version is designed to handle up to 20 IOCARDs. The


supported models are :

- USB expansion for Master Cards


- USB Servomotor cards
- USB keyboard card

The driver scans all connected boards at startup time and assigns them a device
number from 0 to 19. This number will be used to address the card. You can
combine any number of the abovementionned types of card, the only restriction
being that the number of card is equal or below 20.

The driver is written in C++, and expose C functions that can be called from
most languages. A visual basic sample is given, which allow you to test the
functionalities, and to read the device numbers attributed to your hardware.

Important: in this version, no effort was made to handle hot-plugging of


devices. The principle is that your hardware will usually be always connected to
the PC, and there is no reason to add hardware during system use.
However, it is quite easy to handle hot-plugging and this will be added later.
For now, if you wish to change the hardware configuration, restart the driver to
complete cards detection.

As far as we know, the IOCARDs provide no mechanism to label the different


cards (to set a card address). So the only way to address different cards of
similar nature (for example 2 usb expansion cards), is by using their device
number. This means that you have to know it beforehand, and it can be found
using the utility supplied in this SDK. These device numbers are sensitive to your
usb ports configuration, so you should first plug all cards in the way it will be
used, get the device numbers, and use it in your programming work.

Licensing
This software is copyrighted. The copies are digitally tagged to identify
their initial origin.

Two types of licenses exist:

personal use license: you may use this driver for your own private use.
Redistribution of software including this driver is strictly prohibited. You must
obtain it from www.cockpitware.com.

Developer license: you are entitled to redistribute this driver along with your
software, in an unlimited number of copies. This is subject to the payment of a
fee. Pleas contact olivier at cockpitware.com if you are interested.
2. Initializing the driver

All hardware being connected, call the InitUSBCardParams(file,handle)


function with two arguments:

- file : reference (pointer) to a text file handle, which will be used to log
information, and can be useful for debugging.
- handle : A window handle, corresponding to your application window, so
the driver can send messages to your window.

Then, additional parameters must be sent, like the number of master cards
connected to each USB expansion card, and the numbers of A/D channels in use
on each expansion card. For this purpose, use the following functions :

SetMasterCardNbr(int dev, int nb)

To set the number nb of master cards in use on the USB expansion card, the
USB expansion card being labelled by dev. IMPORTANT : the call to
SetMasterCardNbr must occur BEFORE the call of InitUSBCardParams, in the case
where you use mastercards and the usb expansion cards. Otherwise,
unpredictable behaviour may occur (unitialized pointers).

SetMasterADNbr(int dev, int nb)

To set the number nb of A/D channels in use on the USB expansion card labelled
by dev.

Then you can start to send commands to all cards and get information from
them, using different functions listed below.

3. USB expansion cards

3.a – Reading the A/D channels

Each USB exp card has 4 A/D channel. Each channel can read an input voltage
between 0 and 5V, and convert it in a 8bit value : 0 for 0 volt and 255 for 5
volts. You can get the value present on a given A/D channel by using the
function:

C version :

int GetMasterAD(int dev, int channel)


Basic :

GetMasterAD(ByVal dev As Integer, ByVal channel As Integer) As Integer

dev is the device number of the given USB expansion card, and channel is the
A/D channel number to read (from 0 to 3). A value between 0 and 255 is
returned. A negative returned value is an error code : -1 indicates an improper
channel number, and -10 a improper device number.

3.b – Manipulating inputs

Each master card has 72 inputs, so 288 inputs per USB expansion card, labelled
from 0 to 287.

Input Number Input rank Master card


0..71 1st to 71th on MC1 1
72..143 1st to 71th on MC2 2
144..215 1st to 71th on MC3 3
216..287 1st to 71th on MC4 4

They can be read using

C version :

int GetMasterInput(int dev, int n)

Basic version :

GetMasterInput(ByVal dev As Integer, ByVal n As Integer) As Integer

dev is the device number (0..19) and n is the input number, as indicated in the
table above. The returned value is either 0 or 1, to indicate that the input is ON
or OFF, or a negative value to indicate an error condition (see function table in
annex).

You may also want to write the initial state of an input buffer. Real hardware
input are read when they change, and their state is stored in a buffer. In
particular cases, it may be interesting to change this value. In particular, the
USB microcode (in the device on some versions of the usb expansion cards)
suffers from an initialization bug where the 9th input of a group is not always well
initialized at startup. The value of this buffer may be changed by the following
command:

C version :

int SetMasterInput(int dev, int n, int value)

With the following function, you can test whether any input has changed:
C version :

bool GetMasterInputChange(int dev)

Beware that reading any input with the GetMasterInput function resets the state
of the GetMasterInputChange function until the next change. You need to read all
the inputs to determine all those that have changed.

3.c – Manipulating outputs

The output structure is more complicated, with holes in the output


mapping.

Output Number Output rank Master card


11..55 1 to 45th on MC1
st
1
75..119 1st to 45th on MC2 2
139..183 1st to 45th on MC3 3
203..247 1st to 45th on MC4 4

If you try to set an output in the “output gap” (for example between 0 and 11, or
183 and 203), nothing will happen (it will be intercepted by the driver).

To set an output, you must call the following function:

C version :

int SetOutput(int dev, int output, int value)

Basic:

SetOutput(ByVal dev As Integer, ByVal n As Integer) As Integer

The returned value is either 0 for success, or a negative value to indicate an


error condition (see function table in annex).

In some case, it may be interesting to be able to read the state of the output
internal buffer (the value that was previously set on the output). This is achieved
using the function :

int ReadOutput(int dev, int num)

Button helpers

Very often, it is useful to simulate a “bistable” push button. This means a


temporary push button that toggles between the ON and OFF state when you
push it. This is achieved with the following function, example in C:
int RegisterPushButton(int dev, int num, int initial)

You register the input “num” at device “dev” as being a pushbutton, with initial
state “initial (0 or 1)”. You can then read its state (0 or 1) using:

int ReadPushButton(int dev, int num)

3.d – Writing to displays

Each master card can connect to 4 display cards, each having 16 digits, so 64
display per master card. So, a USB expansion card can hold up to 256 displays.

The displays (single digits) are labelled from 0 to 255 for each USB expansion
card:

Display 0 – 63 = 1st display card


Display 64 – 127 = 2nd display card
Display 128 – 191 = 3rd display card
Display 192 – 255 = 4th display card

They can be set using

C version :

int SetDisplay(int dev, int display, int value)

Basic version :

SetDisplay(ByVal dev As Integer, ByVal display As Integer, ByVal value


As Integer) As Integer

dev is the device number (0..19) and display is the display number, between 0
and 255. value correspond to the digit value, and can take the following values :

value on
display
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 Blank
248 -
249 6
250 t
251 d
252 Intensity
control

Intensity control : not available in this version – will be fixed soon.


All other values than those in the table will be ignored, and give a return value
for numerical error (-1).
Otherwise, the returned value is either 0 to indicate success, or a negative value
to indicate an error condition (see function table in annex).

In some case, you need to check the values in a display. You can use the
following function to read the display buffer :

C version :

int ReadDisplay(int dev, int display)

Most often, it is important to display numbers, constituted of many digits.


Provided that the displays are consecutive, you can use the following function to
display a number made of several digits :

int DisplayNumber(int dev, int num, int format, int value)

Here, the format parameter is the number of digits (7 segments displays) used
to display the number.

3.e – Displaying many digits: Registering Display

Most of the time, you want to display a multi-digit number, for ex. 357
To simplify your life and avoid you to manipulate decimal coded binary and other
funny things, this is included in this driver.

You need to declare that a display will be associated with others to display the
multi-digit number. The displays used MUST be in consecutive order.

Example: we want to display a heading (3 digit number), using the 7-segment


displays numbered 19, 20 and 21 on the mastercard with device number 0

We will call the following function:

C version :

int RegisterDisplay(int dev, int num, int format)

Basic version :

RegisterDisplay (ByVal dev As Integer, ByVal num As Integer, ByVal


format As Integer) As Integer
Where dev is the device number of the USB expansion card, num is the number
of the first display, and format is the number of displays used.

In our example, call:


RegisterDisplay(0, 19, 3)

Then, you can display a number of several digits on your registered display, by
calling :

int SetRegisteredDisplay(int dev, int num, int value)

Following our example, to write 236 on the 3 displays starting at position 19 on


device 0, registered above, we call SetRegisteredDisplay(0, 19, 236)

Then, it may also useful to blank a whole group of digits, forming a registered
display. This can be made with :

int BlankRegisteredDisplay(int dev, int num)

Using the same example: BlankRegisteredDisplay(0,19)

3.f – Playing with rotary encoders

In most cases, you also need to use rotary encoders. In this version, Gray
rotary encoders, using two entries of a mastercard are fully supported. You need
to declare them with:

C version:

int SetGray(int dev, int num, int input, int type, int initial int high,
int low, int incr)

Basic version:

SetGray(ByVal dev As Integer, ByVal num As Integer,


ByVal input As Integer, ByVal type As Integer,
ByVal initial As Integer, ByVal high As Integer,
ByVal low As Integer, ByVal incr As Integer
) As Integer
The meaning of the parameters is given in the table below:

Parameter Meaning
Device number (USB expansion card)
dev

Label (number 1..127) of the gray


num encoder. This number will be used in
other function to refer to this particular
encoder. 127 encoders are possible per
USB expansion card.
First entry number, the encoder will
input use two consecutive entries, in the
same group of nine entries in the
mastercard.
Only two values are possible :
0 – circular type encoder. The value
will increase till maximum, then will
switch to the minimum value. Typical
type case is for heading, where the encoder
must go to 0 after 359, circularly.
1 – linear type encoder. The values are
bound between minimum and
maximum. Once a limit is reached, it
cannot go further.
initial Initial value of the encoder
high Higher limit
low Lower limit
incr Increment for each pulse (can be
negative)

The returned value is either 0 or 1, to indicate that the input is ON or OFF, or a


negative value to indicate an error condition (see function table in annex).

3.g – increasing speed of rotary encoders

It is often very handy that the increment increases with the rotating speed of the
rotary encoder, so you can reach a distant setpoint more easily. This is controlled
by an acceleration parameter, which is set by the function:

C version :

int SetGrayAcceleration (int dev, int num, int accel)

Basic version :

SetGrayAcceleration(ByVal dev As Integer, ByVal num As Integer,


ByVal accel As Integer) As Integer
Dev is the USB expansion card device number, num is the gray encoder label
(see 3-f), and accel is the acceleration parameter from 0 to 100.

3.h – Reading rotary encoders

Of course, the most important thing is to be able to read the encoder value. You
can do so with:

C version :

int ReadGray(int dev, int num)

Basic version :

ReadGray(ByVal dev As Integer, ByVal num As Integer) As Integer

The returned value is the encoder value.

3.i – Connecting rotary encoders to displays

Finally, most of the time, you want to display the value from a Gray encoder on a
Display. To avoid you the burden of programming this, we have included in the
driver a direct connection from encoders to displays.
Once you have set an encoder with SetGray and a multi-digit display with
RegisterDisplay, you can connect them with:

C version :

int LinkGray(int dev, int num, int devlink, int numlink)

Basic version :

LinkGray (ByVal dev As Integer, ByVal num As Integer, ByVal devlink


As Integer, ByVal numlink As Integer) As Integer

Where dev and num corresponds to the device number (usb expansion card)
and encoder number(label, see 3-f) for the Gray encoder considered. devlink
and numlink correspond to the device and display number of the multi digit
display which must display the encoder values.

Then, after that, when you turn the Gray encoder, the display will automatically
reflect the encoder value (which you can still read with ReadGray).
4. USB servos card

This card allows to control up to 6 servo-motors and has four 8bit A/D channels.

4.a – Sending a setpoint to the servo-controler

Each servo takes a setpoint between 0 and 1023, i.e. the setpoint has
1024 different values (10 bits resolution). The setpoint is given using the
following function:

C version :

int SetServo(int dev, int servo, int setpoint)

Basic version :

SetServo(ByVal dev As Integer, ByVal servo As Integer,


ByVal setpoint As Integer) As Integer

As usual, dev and servo corresponds to the device number (servo card) and
servo number in the given card (0 to 5). Setpoint is the setpoint value
(0..1023).

Return values : 0 for success or negative error code.

4.b – Reading the A/D channels

The A/D channels are 8bit in width, they return values between 0 and 255. There
are four channels, labelled from 1 to 4.

C version :

int GetServoAD(int dev, int channel)

Basic version :

GetServoAD(ByVal dev As Integer, ByVal channel As Integer) As Integer

Return value : the A/D value.


5. USB keys card

This card allows to read a keyboard with up to 88 keys.

The driver can get values from multiple USB key cards. All input are
collected in a buffer. The buffer values are in the form of a two byte unsigned
value. The upper part is the device number, identifying a given keyboard, and
the lower part is the key code for the key which has been pressed.

The key buffer can be read by:

C version :

USHORT GetKBDBuffer ()

Basic version :

GetKBDBuffer () As UShort

Example: a call to GetKBDBuffer returns the decimal value 613. In hexadecimal


it corresponds to 0265, meaning that key with hex code 65 (decimal 101) was
pressed on device #2. The pressed keys are stored in a buffer and subsequent
calls to GetKBDBuffer will read the keys in order.

If you make windows programming, you can benefit from using windows
messages, to be notified in real time of the event of a key pressed.

First register a dedicated user message by calling :

int RegisterKbdMessage();

This will register for you a windows message, so your code can be notified by
windows.

UINT IocardKeybdMsg = RegisterKbdMessage();

Then use a code similar to this one to intercept the corresponding message with
the value (code) of the key pressed :

BOOL CMyApp::PreTranslateMessage(MSG* pMsg)


{
If (pMsg->message == IocardKeybdMsg)
{
// get key code
USHORT keycode = (USHORT) pMsg->wParam;
}
// some other work here

}
ANNEX: ERROR CODES

Name value meaning


ERR_SUCCESS 0 All OK
ERR_VALUE -1 A function parameter is
not in the correct range.
The device number does
ERR_DEVICE_UNKNOWN -10 not correspond to an
existing device
ERR_SYNCHRO_OUT -20 Reserved
Trying to set the value
of a group of displays
ERR_UNREGISTERED -30 with
“SetRegisteredDisplay”
function, without
previously registering
the display.
ERR_INVALID_LICENSE -100 Incorrect license codes

Anda mungkin juga menyukai