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

 

1.          Introduction

This document describes the Red Earth Systems I/O Module Application Program Interface (RESIO API).

1.1          Product Overview

The RESIO API is a set of functions for providing programming access to the Red Earth Systems range of USB I/O modules.

1.2          References

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.

 

1.3          Readership

This document is targeted at any person involved in programming the RES I/O Modules.

1.4          Acknowledgements

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.

1.5          Glossary

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.

 

2.          Introduction

2.1          General

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).

2.2          Purpose

This document is the technical specification of the RESIO API.

2.3          Scope

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.

 

3.          System Overview

This diagram shows the context of the RESIO API in a system using a user-written application. The application RESTalk follows this scheme [RESTALK].

 


 

 


4.          RESIO Windows API

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.

4.1          Context

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

000A1

Gripper control

1

00111C

Rotary control

2

00072A

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

1C0011

Rotary control

1

0001A

Gripper control

2

2A0007

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.

4.2          Flow Control

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.

4.3          Administrative Functions

These provide facilities which are used by all parts of the API.

4.3.1          RESIOGetNumModules

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.

4.3.2          RESIO_MAX_TRANSFER_SIZE

#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.

4.3.3          RESIO_MAX_NUM_MODULES, RESIO_MIN_MODULE_NO, RESIO_MAX_MODULE_NO

#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.

4.3.4          RESIO_API_VERSION_STR, RESIOGetAPIVersion

#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.

4.4          Module Handling

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.

4.4.1          Type RESIO_ERROR_STATUS

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.

4.4.2          RESIOOpenModule

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.

RESIO_FAIL

The open failed for a reason other than those given above.

4.4.3          RESIOReadModule

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.

4.4.4          RESIOWriteModule

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.

4.4.5          RESIOCloseModule

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.

4.4.6          RESIOGetModuleStatus

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:

RESIO_OK

The module is operating OK.

RESIO_MISSING

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.

4.5          Module Types and Data Formats

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).

 

4.5.1          RESDIO8 Modules (Module Type 5678)

This has 8 digital inputs and 8 digital outputs.

4.5.1.1          Read

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.

4.5.1.2          Write

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

4.6          Using the API

         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.

4.7          Example API Use

The simplest use of the API follows this pattern:

 

  1. Periodically check RESIOGetNumModules until the correct number of modules for your system are ready.
  2. Use RESIOOpenModule to open handles to the modules using module numbers 0, 1, 2, 3 etc. for the number of modules you use. For each opened module, use the returned Module Type and Module ID to determine their role in the system.

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.

 

4.8          Coping with Transient Loss of 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:

 

  1. Reading a module which has been unplugged - even if it is then plugged back in - will return RESIO_FAIL.
  2. Close the handle which failed.
  3. Monitor RESIOGetNumModules for the expected number of modules or a change in count.
  4. Use RESIOOpenModule to attempt to open all modules (0, 1, 2, etc.). Modules already open will return RESIO_ALREADY_OPEN; modules not already open will return RESIO_OK.
  5. Use RESIOReadModule the returned Module Type and Module ID on each module newly opened to determine their Module ID and therefore their role in the system. Record the mapping from role to handle.
  6. Resume operation. Use RESIOReadModule and RESIOWriteModule to configure and control the attached I/O.
  7. When finished with the I/O, use RESIOCloseModule on all the opened modules.

 

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).