i
i
i
i
i
i
i
i
502 17. Programming Input and Force Feedback
The endpoint descriptor has 6 fields occupying 7 bytes. It specifies how
the USB device is to be driven; for example, by the interrupt mech-
anism with a polling interval of 10 ms that allows the PC to receive
position updates 100 times per second.
The HID descriptor has 7 fields occupying 9 bytes. It informs the PC
of the number of report descriptors and to which USB standard it is
working, e.g., USB 1.
The report descriptor is the one that specifies the format of the data being
sent by the USB device; for example, 6 bytes of data to the PC. There
is no correct way of writing this report, as any one of several variations
could produce a similar result. To emulate a common joystick device,
for example, the descriptor would specify a single byte of data for each
of the six inputs in the follo wing order: throttle setting, x-axis position,
y-axis position, z-axis position, slider setting and rotational position
about the z-axis. Table 17.1 shows how the fields in a descriptor table
would be set in order to emulate such a joystick. When attached to a
PC, the game controllers dialog box would announce the presence of
the device and show its properties, as illustrated in Figure 17.5. Such
a device could then use DirectInput to read the joystick axis positions
and use them as coordinates in an absolute 3D frame of reference for
the end effector of an experimental haptic device, or an experimental
3D location sensor or indeed any device that can interface to an analog
voltage in the range [0, 5V ].
A full description of the descriptor tables for HIDs is given in the HID
usage tables [19].
Figure 17.5. A USB device configured with the device descriptor given in Table 17.1
will appear to Windows like a joystick device and can be calibrated as such and used
by DirectInput application programs in the same way that a joystick would.
i
i
i
i
i
i
i
i
17.5. Interfacing Custom VR Hardware with the Applications 503
Not only does the embedded microcontroller program have to provide
correct enumeration of the USB descriptors for the device it is emulating, it
must also configure its own A /D converters and move the data from the input
registers to the RAM locations where the USB interface expects them to be.
This will differ from PIC to PIC, but typically the PIC program will provide
an interrupt handler to service an interrupt from the USB interface. In re-
sponse to the interrupt, either enumeration or data transfer from the internal
buffer to PC will take place. The PIC program will also go through an initial-
ization procedure to load the USB descriptors, configure its A/D converters
for input and then enter a n infinite loop to alternate between reading from
the A/D input and writing to the USB data transfer buffer. Examples of PIC
program design may be found in [4] and specifics of the Microchip 167865
from its datasheet [6].
17.5.3 Accessing the USB HID Directly from C/C++
Using the hardware described in the previous section as an illustration, it is
perfectly possible to read the emulated joystick status and position via the
DirectInput API. Indeed, we could read two, three or more attached joysticks
using DirectInput. Nevertheless, it may be that a custom interface which
can pick up the nine-byte data stream directly is more useful. This can be
done without having to resort to the trouble of writing a full Windows device
driver.
Any HID USB interface devices can be accessed directly from an appli-
cation program written in C/C++ by simply using the Win32 API functions
ReadFile(...) and WriteFile(...).
Listings 17.7 and 17.8 show how this is done for the pseudo-joystick
device discussed in Section 17.5.2. We will need a few components from
the Windows device driver development kit (DDK). Specifically, the header
files
hidusage.h, hidpi.h and setupapi.h need to be included in our ap-
plication code, since functions they define are called during initialization.
They themselves require the header file
pshpack4.h from the DDK, and
the application must be linked with the DDK stub libraries hid.lib and
setupapi.lib. We only need a few functions from these, but it is easer to
find the header and stub libraries than to make them up yourself. Microsoft
used to make the DDK freely available for download, but that has been with-
drawn. Nevertheless it is easy to find the necessary files with a Web search.
Reading from the device is done in a separate thread function (see List-
ing17.8),sothatitcanexecuteatahighpriority,justasthehapticservo
i
i
i
i
i
i
i
i
504 17. Programming Input and Force Feedback
threads do for controlling force rendering. Ho w the device is initialized and
data acquisition threads are started is shown in Listing 17.7. The application
program searches for two devices with appropriate product IDs (these match
the ones set in the device descriptors as part of the PIC firmware). Func-
tion
FindUSBHID(..) searches all the installed HIDs looking for the desired
vendor and product ID. Function FindHID(int index) (see the full code
listings on CD for the source code of this function) calls into the Windows
DDK to obtain a file handle for the first or second HID device installed on
extern float x_rjoy_pos; // variables to hold the x-y-z joystick position
extern float y_rjoy_pos;
extern float z_rjoy_pos;
extern BOOL bLoop; // set to TRUE elsewhere to terminate thread
static void UpdateHID1(PVOID pparams){ // haptic servo - loop
int i,n;
BYTE f[9]; // the USB HID delivers up to a 9 byte frame
float xl,yl,zl;
// external flag to terminate thread
bLoop=TRUE;
// wait in continuous loop till thread terminates
while(bLoop){
// Read the 7 bytes of data from the USB - HID frame. Put this
for(i=0;i<4;i++){
// in a loop to discard any frames that arrived since last read.
ReadFile(h1,f,9,&n,NULL);
// n=number of bytes read if we got less than seven we’ve got the lot
if(n < 7)break;
}
xl=((float)(f[2]))/255.0; // x joystick position is in byte[2] of USB frame
yl=((float)(f[3]))/255.0;
zl=((float)(f[4]))/255.0;
x_rjoy_pos=(2.0
*
xl-1.0) // scale joystick values to [-1, +1] range
y_rjoy_pos=(2.0
*
yl-1.0);
z_rjoy_pos=(2.0
*
zl-1.0);
Sleep(20); // put the thread to sleep for 20 ms
}
_endthread();
return;
}
Listing 17.8. The data acquisition function. The USB devices appear as standard
conventional Windows files, thus a
ReadFile(h1,...) statement will retrieve
up to nine bytes from the latest USB frame obtained by Windows from the device.
Executing the read command four times purges any buffered frames. Doing this
ensures that we get the latest position data.
i
i
i
i
i
i
i
i
17.6. Summary 505
the computer, as defined by the argument index. Once the last device has
been checked, the function returns the code
INVALID HANDLE VALUE.Toget
the vendor and product ID, the DDK function HidD GetAttributes() is
called to fill out the fields in a HIDD ATTRIBUTES structure. The structure
members contain the information we have been looking for.
17.6 Summary
In this chapter, we have looked at a varied assortment of programming meth-
ods for acquiring human input from sources other than the traditional key-
board and mouse. A sense of touch, two-handed input and force feedback
are all vital elements for VR, whether it be on the desktop or in a large-scale
environmental simulation suite. In the next and final chapter, we shall seek
to bring together the elements of graphics, multimedia and a mix of input
methods in some example projects.
Bibliography
[1] J. Axelson. USB Complete: Everything You Need to Develop Custom USB Periph-
erals, Third Edition. Madison, WI: Lakeview Research, 2005.
[2] HAL. “Haptic Library ”. http://edm.uhasselt.be/software/hal/.
[3] J. Hyde. USB Design by Example: A Practical Guide to Building I/O Devices,
Second Edition. Por tland, OR: Intel Press, 2001.
[4] J. Iovine. PIC Microcontroller Project Book: For PIC Basic and PIC Basic Pro
Compilers, Second Edition. Boston, MA: McGraw-Hill, 2004.
[5] I. Mack. PhD Differentiation Report. School of Electrical Engineering,
Queens University Belfast, 2005. http://www.ee.qub.ac.uk/graphics/reports/
mack
report 2005.pdf.
[6] Microchip Technology Inc. “DS41124C”. http://ww1.microchip.com/
downloads/en/devicedoc/41124c.pdf, 2000.
[7] Microsoft Corporation. “DirectX SDK”. http://msdn.microsoft.com/directx/
sdk/, 2006.
[8] W. Oney. Programming the Microsoft Windows Driver Model, Second Edition.
Redmond, WA: Microsoft Press, 2002.
[9] “OpenTracker”. http://studierstube.icg.tu- graz.ac.at/opentracker/, 2006.
i
i
i
i
i
i
i
i
506 17. Programming Input and Force Feedback
[10] OSG Community. “OpenSceneGraph”. http://www.openscenegraph.org,
2007.
[11] Proton+. PIC 2.1.5.3 User Manual. Cambridge, UK: Crownhill Associates,
2004.
[12] G. Reitmayr and D. Schmalstieg. An Open Software Architecture for Virtual
Reality Interaction”. In Proceedings of the ACM Symposium on Virtual Reality
Software and Technology, pp. 47–54. New York: ACM Press, 2001.
[13] A. Rubini and J. Corbet. Linux Device Drivers, Second Edition. Sebastopol,
CA: O’Reilly, 2001.
[14] SensAble Technologies, Inc. “GHOST SDK Support”. http://www.sensable.
com/support-ghost-sdk.htm.
[15] SensAble Technologies, Inc. “Haptic Devices”. http://sensable.com/
products-haptic-devices.htm.
[16] SensAble Technologies, Inc. “OpenHaptics Toolkit”. http://www.sensable.com/
support-openhaptics.htm.
[17] SenseGraphics AB. “H3D API”. http://www.h3d.org/, 2006.
[18] R. Taylor et al. “VRPN: A Device-Independent, Network-Transparent VR Pe-
ripheral System”. In Proceedings of the AC M Symposium on Virtual Reality Soft -
ware and Technology, pp. 55–61. New York: ACM Press, 2001.
[19] USB Implementers Forum. “USB HID Usage Tables Version 1.11”. http://
www.usb.org/developers/devclass
docs/Hut1 11.pdf, 2001.
[20] Virtual Reality Peripheral Network”. http://www.cs.unc.edu/Research/vrpn/,
2007.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.173.78