|
Sherlock
Consulting Limited |
Red Earth Systems I/O Modules (RESIO)
RESIO API Specification
Document Type |
Technical Reference - Uncontrolled |
Document
Version |
1.5 |
Document
Reference |
RESIO API User Guide.doc |
Date |
20 December 2004 |
Author |
Jason Watton |
Status |
Review |
Total Number of
Pages |
15 |
2004 Sherlock Consulting Limited
No part of this document may be reproduced or
transmitted, in any form or by any means (electronic, mechanical, photocopied,
recorded or otherwise) or stored in any retrieval system of any nature without
the express written permission of Sherlock
Consulting Limited.
Contents
1. Introduction 3
1.1 Product Overview 3
1.2 References 3
1.3 Readership 3
1.4 Acknowledgements 3
1.5 Glossary 3
2. Introduction 4
2.1 General 4
2.2 Purpose 4
2.3 Scope 4
3. System Overview 5
4. RESIO Windows API 6
4.1 Context 6
4.2 Flow Control 7
4.3 Administrative
Functions 7
4.3.1 RESIOGetNumModules 8
4.3.2 RESIO_MAX_TRANSFER_SIZE 8
4.3.3 RESIO_MAX_NUM_MODULES,
RESIO_MIN_MODULE_NO, RESIO_MAX_MODULE_NO 8
4.3.4 RESIO_API_VERSION_STR,
RESIOGetAPIVersion 8
4.4 Module Handling 9
4.4.1 Type RESIO_ERROR_STATUS 9
4.4.2 RESIOOpenModule 9
4.4.3 RESIOReadModule 10
4.4.4 RESIOWriteModule 11
4.4.5 RESIOCloseModule 11
4.4.6 RESIOGetModuleStatus 12
4.5 Module Types and Data
Formats 12
4.5.1 RESDIO8 Modules (Module
Type 5678) 13
4.5.1.1 Read 13
4.5.1.2 Write 13
4.6 Using the API 14
4.7 Example API Use 14
4.8 Coping with Transient
Loss of Modules 14
This document describes the Red Earth Systems I/O Module Application Program Interface (RESIO API).
The RESIO API is a set of functions for providing programming access to the Red Earth Systems range of USB I/O modules.
Ref |
Title |
Author |
Description |
RESTALK |
RESTalk
Test Harness |
Red
Earth Systems Limited |
Description
of the test harness for the RES I/O Modules and their API. |
This document is targeted at any person involved in programming the RES I/O Modules.
This document is a first edition.
This document owes its content to:
All chapters were written by Jason Watton.
All of the above have the right to be identified as authors of the work.
Definitions in the text are shown italicized and bold. Use of terms recently defined elsewhere or a direct quote from elsewhere in the text are shown italicized. Bold and underlining are used for emphasis.
API |
Application Programmer's Interface, a set of functions and declarations which provide the programmer of an application to use an object. |
BIT |
Built-In Test |
Hex |
Hexadecimal |
RESIO |
Red Earth Systems I/O system - a range of simple modules for developers to control electronic I/O from a PC. |
Rx |
Receiver/Reception |
Tx |
Transmitter/Transmission |
mC |
Micro-controller. |
mP |
Microprocessor. |
USB |
Universal Serial Bus - an electrical and signaling standard plus protocol for device communications. |
RESIO is a set of Microsoft Windows® program code providing a programming interface to the range of Red Earth Systems I/O Modules. The Application Program Interface it defines is available both as a static library (.lib) and as a dynamically-linked library (.dll).
This document is the technical specification of the RESIO API.
This guide provides information about the use of the RESIO API and its capabilities.
This guide has been written using version 1.54
of the RESIO API.
This diagram shows the context of the RESIO API in a system using a user-written application. The application RESTalk follows this scheme [RESTALK].
The RESIO device is supplied with static (.lib) and dynamic (.dll) Win32 'C' libraries offering the following Application Program Interface:
Symbol |
Affects |
Type |
Description |
RESIOGetNumModules |
Admin |
Function |
Number of Modules currently available. |
RESIO_MAX_TRANSFER_SIZE |
Admin |
Const |
Maximum amount of data that can be written to or read from any Module in one API Read/Write call. |
RESIO_MAX_NUM_MODULES |
Admin |
Const |
Maximum number of simultaneous modules supported. |
RESIO_MIN_MODULES_NO, RESIO_MAX_MODULE_NO |
Admin |
Const |
Range of values over which Modules are numbered by the API. |
RESIO_API_VERSION_STR |
Admin |
Const |
API version as ASCII string |
RESIOGetAPIVersion |
Admin |
Function |
Returns the zero-terminated ASCII string representing the API version. |
RESIO_ERROR_STATUS |
Module |
Type |
Status of Module. |
RESIOOpenModule |
Module |
Function |
Open a specific Module. |
RESIOReadModule |
Module |
Function |
Read data from a Module. |
RESIOWriteModule |
Module |
Function |
Write data to a Module. |
RESIOCloseModule |
Module |
Function |
Close a specific Module. |
RESIOGetStatus |
Module |
Function |
Get status of a specific Module. |
In the definitions of the functions that follow each parameter is marked as IN, OUT, or IN OUT. This is for information only, and is not 'C' code; it indicates the direction in which information travels into and out of the function:
Return values are implicitly OUT.
The API is linked into, or dynamically loaded by a user-written application to allow the application to access all RESIO modules available on a PC.
More than one RESIO module may be connected to a PC. The application should call the RESIO API to determine the number of modules available, then scan through the modules, opening and reading them, until all modules required for operation are found. Modules not required should be closed for use by another application.
A module is accessed via a Windows handle (1 per module).
No
module may be opened more than once.
This is to prevent contention when writing to the module (and missed inputs). If two processes wish to access the same module they must share the handle to the module. As with files, the handle provides access to the module and should be closed when access is no longer required, as leaving it open will prevent others gaining access to it.
If
you 'lose' (discard or overwrite) an open handle to a module then access to
that module will be impossible until it is unplugged.
The application is responsible for finding
its own modules and assigning them roles. The API supplies a count of modules
available: when each module is then opened,
the API returns a handle to the module, the module type (see 4.5), and a module ID and
each one may be opened and queried for 4 bytes of data, one of which is the
Module ID, which
is configured statically by the user on the module itself (e.g.
by DIP switches). As USB is plug-and-play the order of opening
modules cannot be relied upon to remain constantNote
that the order of enumeration of all the modules cannot be assumed constant:
it is possible for modules to appear at different positions in the list each
time the PC is rebooted (for example)or recovers from a
sleep state. The static module ID, however, allows particular
modules to be identified in the list so that its role in a larger multi-module
system can be assigned, such a control of a robot gripper rather than control
of a camera. Without this function each time the PC was reset a manual
calibration would have to be performed to assign a specific role to a specific
module.
For example, on one power-up cycle of a PC
the API indicates 3 modules found so the API
is called to open modules 0, 1, and 2,
with the following results:and
after configuration the following mapping results:
API
module number (dec) |
Module
returns ID (hex) |
Meaning |
0 |
000 |
Gripper control |
1 |
0011 |
Rotary control |
2 |
0007 |
Camera control |
A subsequent power up changes the order of
enumeration of the modules. This changes the order of
opening when the modules are scanned (0, 1, 2) but the module ID
still indicates correctly the role of each module in the system so
the API Module numbers change but the module IDs still identify each module and
its function uniquely:
API
module number (dec) |
Module
returns ID (hex) |
Meaning |
0 |
|
Rotary control |
1 |
0001 |
Gripper control |
2 |
|
Camera control |
Do not use the API module numbers to
assign a role to each module - they can change.
It is the responsibility of the application to assign a role to each module using the Module ID not the API module number.
The API only uses module numbers when opening modules - e.g. if 3 modules are available, modules 0, 1, and 2 can be opened. Opening a module returns a handle to it which is used in all other calls to the API. Handles are only related to module numbers at the time of opening - loss of a module (e.g. unplugging it) changes the ordering but the handles to the remaining modules remain valid.
The API includes no flow control - the only events it responds to are calls from the application, and the responses to the calls are all made in the same thread, in one pass.
The API and driver are multi-threaded.
These provide facilities which are used by all parts of the API.
WORD RESIOGetNumModules(void);
Returns the number of RESIO modules found in the system. The driver and API can support up to RESIO_MAX_NUM_MODULES simultaneously.
Parameters:
None
Return
values:
WORD
The number of RESDIO modules found in the system. They are implicitly numbered 0 through this value less 1.
#define RESIO_MAX_TRANSFER_SIZE (8U)
This is the maximum amount of data that can be transmitted to (using RESIOWriteModule) or received from (using RESIOReadModule) a Module in one call of the API. Attempting to read more than this will simply return less data; attempting to write more than this is an error.
This symbol is typically used to pre-allocate a buffer of sufficient size to handle any module. Red Earth Systems reserve the right to change this value.
Parameters:
None
Return
values:
(8U)
A constant indicating the maximum amount of data, in bytes, that a Module will ever receive or transmit in one call of the API.
#define RESIO_MAX_NUM_MODULES (256U)
#define RESIO_MIN_MODULE_NO (0U)
#define RESIO_MAX_MODULE_NO (RESIO_MAX_NUM_MODULES-1U)
These are the maximum number of modules supported by the API, the minimum Module number, and the maximum Module number respectively.
Parameters:
None
Return
values:
Constants indicating the maximum number of modules, the minimum Module number, and the maximum Module number supported by the API.
#define RESIO_API_VERSION_STR "v1.5"
const char *RESIOGetAPIVersion(void);
Returns the constant zero-terminated ASCII string representing the version of the API. This may be used for configuration management.
Parameters:
None
Return
values:
const char *
A pointer to a zero-terminated ASCII string representing the version number of the Engine.
These functions are specific to Modules. A Module number must be passed to each one. Valid Module numbers can be determined using the functions and constants in the previous section.
This type is used to indicate success or failure of an API function.
Symbol |
Description |
RESIO_OK |
The function completed successfully. |
RESIO_FAIL |
The function failed. See the documentation for the function. |
RESIO_CONNECT_FAIL |
Connecting to the Module failed. Check the integrity of the USB link. |
RESIO_ALREADY_OPEN |
The Module specified is already opened. Only one client can control any Module at any one time. |
RESIO_INVALID_COMMAND |
A parameter passed to the function is invalid or a call to the function inappropriate at this time. |
RESIO_MISSING |
The Module specified could not be found. |
For more information, see the return value documented with the function called.
RESIO_ERROR_STATUS RESIOOpenModule(
IN BYTE nModuleNo,
OUT HANDLE *pHandle,
OUT WORD *pModuleType,
OUT WORD *pbcdModuleID
);
This opens a specific Module for communication. It is advised not to start opening Modules until RESIOGetNumModules returns the expected number of modules.
The
function, if successful, returns:
·
a handle to the module
for use with other API functions,
·
a module type
(see 4.5),
and
·
a BCD module ID, chosen
by the user, to uniquely identify the
role of the module in a particular installation. Only
BCD values should be used, i.e. 0x0000 through 0x9999, with each hex
digit being in the range 0 through 9.
Note
that if an open Module disconnects and reconnects then any handle to that
module becomes invalid and calls to read and write the Module using that module
handle will fail until the handle is closed and the module reopened. Note that
this can also cause a re-ordering of the Modules. Hence to reacquire a module
the handle to the module lost should be closed, then the application should attempt
to re-scan open all
available modules and read from each module that is not already open to
see if any unopened module has the correct type and ID.
Parameters:
nModuleNo
The Module number to open. This must not have been previously opened.
pHandle
Pointer to a HANDLE to
receive the module handle, or INVALID_HANDLE_VALUE on failure.
pModuleType
Pointer to a word to
receive the module type as defined in 4.5, or
0xFFFF on failure.
pbcdModuleID
Pointer to a word to
receive the module ID, in the range 0x0000 through 0x9999 (with each digit in
the range 0 through 9). If the call fails, this parameter is set to the
exceptional value 0xFFFF.
Return
value:
RESIO_OK
The Module was opened successfully.
RESIO_CONNECT_FAIL
Failed to connect to the Module because it is in an invalid state. Check available resources (e.g. free memory) and the integrity of the USB link, and retry.
RESIO_ALREADY_OPEN
The Module has already been opened. It is inappropriate for two processes to control the same Module.
RESIO_INVALID_COMMAND
The request to the Module was incorrectly formatted. This should never be returned if the API is used correctly. An invalid attempt to open the driver directly can also cause this error.
RESIO_MISSING
No such Module exists.
The open failed for a reason other than those given above.
RESIO_ERROR_STATUS RESIOReadModule(
IN HANDLE hModule,
OUT BYTE *pBuffer,
IN OUT DWORD *pnLength
);
Read data from a Module. Note that pnLength must be set to the size of the buffer supplied on entry, and will be overwritten on return with the amount of data transferred.
The function will not read more than RESIO_MAX_TRANSFER_SIZE bytes (currently 8).
A call to this function will block until data is available, which may take up to 250ms. The call will fail if the handle is invalid, or communication with the opened Module has been lost or interrupted.
The format of the data returned is dependent on the module type attached. See section 4.5.
Parameters:
hModule
Handle to the module to read from.
pBuffer
Points to a buffer to read data into.
pnLength
Must point to the length of the buffer supplied on entry. On return, this will point to the amount of data read into pBuffer, which will be no more than RESIO_MAX_TRANSFER_SIZE.
Return
value:
RESIO_OK
The data was read without problems.
RESIO_FAIL
The read failed. This is invariably because the Module has been lost - i.e. unplugged or disconnected - or reset.
Note:
The call to this function will block (suspend the calling thread) until the data is available, which is usually no more than 250ms.
RESIO_ERROR_STATUS RESIOWriteModule(
IN HANDLE hModule,
IN const BYTE *pBuffer,
IN DWORD nLength
);
Write data to a Module.
The function will not write more than RESIO_MAX_TRANSFER_SIZE bytes (currently 8). An attempt to do so will return an error.
A call to this function will block until the data has been shipped, which may take up to 250ms. The call will fail if the handle is invalid, or communication with the opened Module has been lost or interrupted.
The format of the data sent is dependent on the module type attached. See section 4.5.
Parameters:
hModule
Handle to the module to write to.
pBuffer
Points to a buffer containing the data to send.
nLength
The amount of data to send from the buffer supplied.
Return
value:
RESIO_OK
The data was sent without problems.
RESIO_FAIL
The write failed. This is invariably because the Module has been lost - i.e. unplugged or disconnected - or reset.
Note:
The call to this function will suspend the calling thread until the data is written, which is usually no more than 250ms.
RESIO_ERROR_STATUS RESIOCloseModule(IN HANDLE hModule);
This closes the specified handle to a module. It is not an error if the handle is already closed or INVALID_HANDLE_VALUE.
Parameters:
hModule
Handle to the module to close.
Return
value:
RESIO_OK
The Module was closed successfully.
RESIO_ERROR_STATUS RESIOGetModuleStatus(HANDLE hModule);
Returns the status of the given module.
Parameters:
hModule
Handle to the module to query the status of.
Return value:
Any status value as documented in 4.4.1 and other sections of this document. The commonest return values are, however:
The module is operating OK.
The specified module has been lost or does not exist.
RESIO_FAIL
The function failed. For RESIOReadModule or RESIOWriteModule, this usually indicates loss of USB communications with the module. See section 4.8.
Each type of module has its own format of data. The API functions in section 4.4 allow retrieval of data from, and transmission of data to, each module, but the format (meaning) of this data is specific to the type of module attached. However, the amount of data that is transferred in each read or write transaction cannot exceed RESIO_MAX_TRANSFER_SIZE bytes. This section details the data formats for each type of module.
The
module type is returned by the call to RESIOOpenModule which opened the
module. The following types currently exist:
Module Type (hex) |
Model |
Module description |
5678 |
RESDIO8 |
8 digital inputs + 8 digital outputs |
5679 |
RESDIO16 |
16 digital inputs + 16 digital outputs |
0003 |
RESDI16 |
16 digital inputs |
0004 |
RESDO16 |
16 digital outputs |
0005 |
RESAIO2 |
2 analogue inputs + 2 analogue outputs |
0006 |
RESAI4 |
4 analogue inputs |
0007 |
RESAO4 |
4 analogue outputs |
0008 |
RESDX16 |
16 digital input or output (user-selectable) |
A
combination of Module type and Module ID (both returned by RESIOOpenModule)
allows an application to
uniquely identify a specific module
in a multi-module system.
The module type is the
Product ID from the Device Descriptor on the module.
The module ID is the Device ID (bcdDevice) from the
Device Descriptor on the module.
The following features have not
yet been implemented in firmware for each module:
1.Transmission of the
module type.
2.1.Alteration of theDetermination
and transmission of the module ID (bcdDevice in Device
Descriptor).
This has 8 digital inputs and 8 digital outputs.
The module returns 4 bytes (shown boxed below). The format is not yet static and is subject to change.
|
|
1 |
2 |
3 |
4 |
|
|
|
|
|
|
|
|
|
|
Mod Type |
Mod ID |
Count |
DI 7:0 |
Last Write4 |
Unk |
|
|
|
|
|
|
|
|
|
|
Mod Type - NOT AVAILABLE
The type of this I/O Module (00 = RESDIO8). This is constant between reads. The intention is not to have this here but to have this in the device descriptor so that the full 4 bytes are available for volatile data rather than this (constant) value.
Mod ID - NOT AVAILABLE
The ID (address) of this I/O Module. Any constant value from 0 through 255. This identifies the module to the application program so that the application can distinguish between modules of the same type. See section 4.1. The intention is not to have this here but to have this in the device descriptor so that the full 4 bytes are available for volatile data rather than this (constant) value.
Count
Incrementing count of USB transactions.
DI7:0
The states of the 8 digital input lines.
Last Write4
A record of the last written byte (byte 4 in the last Write transaction).
Unk
Unknown.
Only 4 bytes may be written:
1 |
2 |
3 |
4 |
|
|
|
|
|
|
|
|
|
|
|
|
DO 7:0 |
00 |
00 |
Spare |
|
|
|
|
|
|
|
|
|
|
|
|
DO7:0
The states to drive the 8 digital output lines to.
Spare
This byte can be set to any value and is returned in byte 3 of the next Read transaction.
Dir7:0 - NOT AVAILABLE
The directions of the discrete I/O (identical sense to TRISA/TRISB settings):
Dir |
Direction |
0 |
Output |
1 |
Input |
· The API is available as a static library (lib) or a dynamically-linked library (dll). In both cases, you should link with the assicated RESIO.lib file. If using the dll, the associated (small) RESIO.lib file will orchestrate the loading and sharing of the dll.
·
To use the API you must also link with the setupapi.lib
system library to get the calls to access the driver (this is a system dll).
· All functions are _stdcall. The library and header (RESIO.h) as supplied with the API should correct for this but if the call convention is not adhered to a 'symbol not found' error will occur for all exported functions.
The simplest use of the API follows this pattern:
3.1.Use RESIOReadModule on
each module to determine their Module Type and Module ID and therefore their
role in the system. Record the mapping from role to handle.
4.3. Use
RESIOReadModule and RESIOWriteModule to configure and control the
attached I/O.
5.4. When
finished with the I/O, use RESIOCloseModule on all the opened modules.
The RESIO modules are hot-swappable. Users may unexpectedly unplug, and plug in, modules. The RESIO driver and API do not force errors in these situations - it is the decision of the application writer what to do. The application can attempt to recover the situation, or flag up an error to the user.
If you wish to recover from users unplugging modules, then plugging them back in, for example:
Note that failing to close a handle to a module will prevent access to it until your application exits (when Windows cleans up all open handles).