|

|
|
Programming the RB Series
Response Pads
Last
Revision: July 25, 2002
The information in this article applies to:
Programmers who want to
write their own software to communicate with the Cedrus RB-400, RB-410,
RB-600, RB-610, RB-420, and RB-620 response pads
Summary
Cedrus' RB Series are directly supported by SuperLab. However, a number of users expressed an interest in using these popular
response pads in their own applications. This document offers some technical information
needed in order to write your own code.
Technical Details
The RB Series response pads send
one and only one byte every time the state of one of the keys changes. See
the document The RB Series Response
Pads Protocol for information on the byte format.
Programming
Notes
For the RB-400 or RB-600 response
pads, open
the serial port using 8-N-1 parameters at 2400 baud.
For the RB-410 or RB-610 response
pads, open
the serial port using 8-N-1 parameters at 9600 baud.
For the RB-420 or RB-620
response pads, open the serial port using 8-N-1 parameters at 9600, 19200,
or 38400 baud, depending on the DIP switch settings.
Programming Example
Here is a sample source code on how to program
the RB-4x0 and RB-6x0 response pads. This sample consists of the following four
functions:
Platforms
The sample code shown here is written for Windows
95 or later. The essential part is in the
CedrusGetButtonResponse function. For other platforms, the main changes affect how the
serial port is opened, read, and closed:
For Windows 3.1, you need to
call the functions OpenComm, ReadComm, and CloseComm.
On the Macintosh, the needed
functions are OpenDriver, SerSetBuf, SerGetBuf,
FSRead, and CloseDriver.
Controlling the Serial Port
The following code is for controlling the serial
port:
#include
"windows.h"
// A few definitions to make the C code a
// little more readable
#define EQ ==
#define NE
!=
#define LT
<
#define LE
<=
#define GE
>=
#define GT
>
#define AND
&&
// Logical operators
#define OR
||
#define NOT
!
#define bAND
&
// Binary operators
#define bOR
|
#define bNOT
~
#define bXOR
^
// Function prototypes
HANDLE CedrusOpenSerialPort (int nPortNum, int nBaudRate);
int
CedrusFlushSerialPort (HANDLE nPortHandle);
void CedrusCloseSerialPort (HANDLE nPortHandle);
int
CedrusGetButtonResponse (HANDLE nPortHandle, int nRBModel);
HANDLE CedrusOpenSerialPort (int nPortNum, int nBaudRate)
{
// -- nPortNum should be set to 1 to open COM1,
// 2 to open COM2, etc.
// -- nBaudRate should be a valid baud rate,
// e.g. 2400 or 9600
//
// This function returns -1 if it fails. If
// successful, it returns a "port handle" that
// is passed to other functions afterwards
// to access or close the serial port.
char port_name[8];
HANDLE port_handle;
wsprintf (port_name, "COM%d", nPortNum);
port_handle = CreateFile (port_name,
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (port_handle EQ INVALID_HANDLE_VALUE)
{
port_handle = (HANDLE) -1;
// Return error
}
else
{
DCB
dcb;
int
status;
COMMTIMEOUTS ct;
status = GetCommState (port_handle, &dcb);
// Setup serial port for
8-N-1
// (8 bits, no parity, 1 stop bit)
if (status NE 0)
{
dcb.BaudRate =
nBaudRate;
dcb.ByteSize = (unsigned char) 8;
dcb.Parity = 0;
dcb.StopBits = 0;
dcb.fBinary = 1;
//
No EOF check
status = SetCommState
(port_handle, &dcb);
}
// Setup timeouts
ct.ReadIntervalTimeout = MAXDWORD;
ct.ReadTotalTimeoutMultiplier = 0;
ct.ReadTotalTimeoutConstant = 0;
ct.WriteTotalTimeoutMultiplier = 0;
ct.WriteTotalTimeoutConstant = 5000;
SetCommTimeouts (port_handle, &ct);
status = SetupComm (port_handle, 128, 128);
CedrusFlushSerialPort (port_handle);
}
return port_handle;
}
int CedrusFlushSerialPort
(HANDLE nPortHandle)
{
int status = 0;
short done = FALSE;
char
serial_buff[100];
DWORD bytes_read;
while (NOT done)
{
status = ReadFile (nPortHandle, serial_buff,
sizeof(serial_buff),
&bytes_read, NULL);
if (status EQ 0)
done = TRUE;
// Error?!
if (status NE 0
AND
bytes_read LT sizeof(serial_buff))
{
done = TRUE;
}
}
return status;
}
void CedrusCloseSerialPort
(HANDLE nPortHandle)
{
CloseHandle (nPortHandle);
}
Checking the Status of the
Buttons
The following code keeps looping until a
pushbutton has been pressed on the response pad:
int CedrusGetButtonResponse
(HANDLE nPortHandle, int nRBModel)
{
// nRBModel should be 1 for RB-400/RB-410,
or
//
2 for RB-600/RB-610
short rb4x0[6] = {-1,
-1, 0, 1, 2, 3 };
short rb6x0[6] = {0, 5, 1, 2, 3, 4 };
int num_bytes;
int i, k;
int button_pressed = FALSE;
short buttons_status;
short status;
char
serial_buff[6];
DWORD comm_status;
CedrusFlushSerialPort (nPortHandle);
while (NOT button_pressed)
{
k = -1;
serial_buff[0] = '\0';
num_bytes = 0;
buttons_status = 0;
// See if a byte come
from the serial port
status = ReadFile (nPortHandle, serial_buff,
1, &comm_status, NULL);
if (status NE 0)
num_bytes = (short)
comm_status;
// Clear any overflow or
other erros that might occur
if (status EQ 0)
ClearCommError
(nPortHandle, &comm_status, NULL);
// Convert to positive
logic w/o the negative sign
if (num_bytes GT 0)
buttons_status = (bNOT
serial_buff[0]) bAND 0x003f;
if (buttons_status GT 0)
{
i = 0;
//
This loop converts from an integer
// to a bit number from
0 to 5
while
(i LT 6)
{
if ((1 << i) bAND buttons_status)
{
k = i;
break;
}
i++;
}
//
Re-map bit number to actual
// button, depending on
model
if
(nRBModel EQ 2)
button_pressed = rb6x0[k] + 1;
else
button_pressed = rb4x0[k] + 1;
}
}
return button_pressed;
}
That's it. The following sample code will simply call the functions shown above to
illustrate how they are called and used:
void CedrusTestResponseBox (void)
{
HANDLE hPort;
// Demo code for the RB-610
// Open COM2 at 9600 baud (use 2400 for RB-400/RB-600)
hPort = CedrusOpenSerialPort (2, 9600);
if (hPort NE (HANDLE) -1)
{
int key_pressed;
char
ch_buff[100];
// Get response from
RB-610. Change second
// parameter from 2 to 1 if
using the RB-400
// or RB-410.
key_pressed = CedrusGetButtonResponse (hPort,
1);
// Display a message to
show the result
wsprintf (ch_buff, "Button number %d was
pressed!",
key_pressed);
MessageBox (NULL, ch_buff, "Cedrus Code
Snippet",
MB_OK | MB_ICONINFORMATION);
CedrusCloseSerialPort (hPort);
}
}
This code sample has been compiled and tested
using Visual C++ 5.0.
|