home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Virtual Reality Zone
/
VRZONE.ISO
/
mac
/
PC
/
PCGLOVE
/
GLOVE
/
OBJGLV.ZIP
/
DOC
/
PDRIVER.DOC
< prev
next >
Wrap
Text File
|
1992-09-25
|
9KB
|
226 lines
REND386 POINTER, HEAD TRACKER, AND SWITCHING DEVICE DRIVERS
Written by Dave Stampe, September 1992
Pointer device drivers are compiled in pseudo-tiny mode (code, data in one
segment, stack not assumed in the same segment). The interface is through
an assembly routine at the start of the driver.
During development, the code may be linked with REND386 and appropriate
changes made to POINTER.C to "fake" the load and initialization. See
MEMMODEL for more information. At this stage, all assembly modules
should use the .MODEL LARGE directive.
See the file MEMMODEL for a description of the memory modes, and how to
compile your driver.
-------------------------------
STRUCTURE OF THE POINTER DRIVER
The driver consists of an assembly interface module (linked in first),
a pconfig{} structure giving driver data, and an interperter module
which is called from REND386.
The interperter accepts these commands and arguments:
/* driver call equates: call *driver_pointer with this code */
/* all return *pconfig or integer */
#define DRIVER_INIT 0 /* rtns *pconfig, args = type */
#define DRIVER_RESET 1 /* no rtn, no args */
#define DRIVER_READ 2 /* rtns NULL if no data ready, else *pconfig */
/* args = *pointer, mode */
#define DRIVER_CMD 3 /* args = mode, rtns *pconfig */
#define DRIVER_CHECK 4 /* no args, rtns *pconfig */
#define DRIVER_QUIT 5 /* no args, no rtn */
Calls are usually made thru REND386's interface command, so
avoid returning anything unexpected.
INTERPERTER CALL DEFINITIONS (first argument)
DRIVER_INIT:
First call after loading driver. You may hook all interrupts, but
be sure you know what you're doing! And do not modify the timer interrupt
rate, which will usually be between 140 and 200 ticks per second. Try
to do your interrupt processing AFTER the original call.
ARGS: type (may be used to set driver type, if marked as available
in the pconfig.type field.
RETURNS: Address of pconfig structure of driver.
DRIVER_RESET:
Used to reset the driver, recenter it, etc. No args or return, currently
unused.
DRIVER_READ:
Called to read driver position. The read gives raw device coords if
called in pointer mode, and the "mouse" screen location (scaled to match
the .maxsx and .maxsy parameters in pconfig, which can be changed by
the external software!). The read data is recorded into the *pointer
structure given as an argument.
Note that all scaling, motion detection, etc. is performed by code
in the REND386 pointer interface library. You driver need not handle
this, but it must handle gesture recognition or coding to buttons.
ARGS: mode is P_POINTER or P_SCREEN, which may be or'd with P_CENTER to
request recentering of the device as well.
RETURNS: NULL if no new data, else address of pconfig.
DRIVER_CMD:
Sends a direct command to driver. No commands yet defined.
ARGS: Command word
DRIVER_CHECK:
RETURNS: address of pconfig if everything's OK, else NULL.
DRIVER_QUIT:
Called on exit from the program, in reverse order that drivers were loaded.
Should unhook all interrupts, etc.
THE PCONFIG{} STRUCTURE:
/* configuration structure: part of driver */
/* MUST corresp. to lefthand coord sys or negate scale! */
/* for non- ht devices, the scaling may be adjusted as desired */
typedef struct _pconfig {
long xres, yres, zres; /* position res: mm/tick in <16.16> */
long maxx, maxy, maxz; /* numeric range */
long minx, miny, minz;
long xrres, yrres, zrres; /* rotation res: deg/tick in <16.16 */
long maxxr, maxyr, maxzr; /* numeric range */
long minxr, minyr, minzr; /* min, max: left-hand dir. */
int maxsx, maxsy; /* limits on mouse-mode motion (writable) */
int databits; /* what data is available from device */
int commands; /* what sort of control is available */
int nullkey; /* button code for null keypress */
int flexnum; /* number of flex parameters */
int delay; /* millisec. read delay */
int idelay; /* internal delay in ms */
int rrate; /* max. reads per second possible */
int type; /* suggested useage */
char id[80]; /* id or more data */
} pconfig;
The resolution entries give the true space measurements of each "tick"
(or unit) of the pointer devices's raw resolution. These make it possible
to use a device for head tracking directly. If you wish, you may "fudge"
this factor to expand the spatial range of a device.
Rotational resolution is 1/65536 of the actual <16.16> format of the
rotation resolution. So, for example, the PowerGlove has 12 ticks for its
entire rotation range. The tick must be multiplied by 65536 in the
driver, so that it will scale correctly. These are used by the absscale()
routine.
The max and min are used with the tscale() and rscale() functions to center
and set the range of the pointer device.
The maxsx and maxsy values are used inside the driver to set mouse-emulation
(screen coordinate) range, which goes from 0 to the maximum. The x axis is
positive rigt, the y axis is positive up.
Databits flags what response data is available:
For most mice, you may use button3->button1 | button2
or pass it seperately.
#define P_HASB1 0x0001 /* what buttons we can have */
#define P_HASB2 0x0002 /* also mask for button bits */
#define P_HASB3 0x0004 /* should really return 0x07 for compatibility */
#define P_HASX 0x0008 /* which axes we can read */
#define P_HASY 0x0010
#define P_HASZ 0x0020
#define P_HASRX 0x0040 /* what rotations are available */
#define P_HASRY 0x0080
#define P_HASRZ 0x0100
#define P_HASGEST 0x0200 /* gestural interface */
#define P_HASFLEX 0x0400 /* fingers? */
#define P_HASKEYS 0x0800 /* do we have a keypad? */
#define P_HASSCR 0x1000 /* capable of emulating XY mouse */
The modes word contains bits to represent available modes for reading:
#define P_CENTER 1 /* recenter without reinitializing */
#define P_SCREEN 2 /* screen mouse mode read */
#define P_POINTER 4 /* any extended pointing mode */
The type word has bits to flag what type of uses the device driver may be
useful for:
#define P_NOPOS 0 /* just a keypad or something */
#define P_IS2D 1 /* 2D mouse, for example */
#define P_IS2DP 2 /* 2D, but Z mapped by button */
#define P_IS3D 4 /* 3D mouse, for example */
#define P_IS6D 8 /* 6D mouse, for example */
#define P_IS3DG 16 /* 3D glove-- don't use rot */
#define P_IS6DG 32 /* 6D glove-- use rotation */
#define P_IS3RH 64 /* 3D (rotation) head tracker */
#define P_IS3TH 128 /* 3D (position) head tracker */
#define P_IS6H 256 /* full 6D head tracker */
All other functions are carried out by code in REND386 itself.
If you need more data, look at the files mouseptr.c, drheader.asm,
mkmpd.bat in the driver kit, and mouseptr.c, gloveptr.c, cursors.c, and
pointer.c in the REND386 source.
INTERRUPT HANDLERS
NEVER use the timer interrupt! Hooking the timer interrupt is discouraged,
as the order of initialization of devices is not well-defined. REND386
will hook the timer interrupt, and pass on calls every 55 mS, but if your
code attempts to hook after REND386 has grabbed the timer, you'll get a
call every 6 mS, and the Sega glasses will not synchronize properly.
You may set up serial and other interrupt handlers in your code, but
it must be FARSTACK (see MEMMODEL for more information). You should
remove your handler at the DRIVER_QUIT call. The processing time should
extremely short, as otherwise the joystick driver will become noisy.
---------------------------
HEAD TRACKING DEVICES
These are identical to the pointer devices, except that they need
not support screen-cursor modes, and only the tick-resolution
is used when scaling their output. Recentering is desirable, and
the resolution should correspond to real-world values.
---------------------------
SWITCHING DRIVERS
These are always called from within an interrupt and so must use the
reentrant header and be written entirely in assembler or use the
TINY DS != SS model with no C library calls.
The calls have 2 integer parameters:
int switch_driver(int command, int eye);
where command is one of:
SW_INIT 0
SW_QUIT 1
SW_ADV_SWITCH 2
SW_SYNC_SWITCH 3
SW_INIT and SW_QUIT are self-explanatory. SW_SYNC_SWITCH is done
during vertical retrace, and is the usual time to switch Sega
glasses etc.
SW_ADV_SWITCH occurs 4-6 mS before the vertical
retrace, so is useful for preloading various registers, loading
addresses, etc. It corresponds to the video address register load
for page switching in REND386. Your driver should return 1 if it
wants REND386 to change the video page address, 0 if not.
The eye argument tells your driver which eye's view to display:
LEFT 1
RIGHT 0