A Grail Millennium Project
White Paper
This document is maintained by the author, Lewis A. Sellers, somewhere in the mountains of East Tennessee, the United States of America. It is an informal technical document for a works in progress project called Grail Millennium, or fully, The Minimal Operating System of Object Class Interfaces Holy Grail for the Millennium. In other words, for a new, easy to use, long-lived operating system.
Copyright Notice
This document and all material therein, unless otherwise stated, is Copyright © 1995,1996, Lewis A. Sellers. All Rights Reserved. Permission to distribute this document, in part or full, via electronic means (emailed, posted or archived) or printed copy are granted providing that no charges are involved, reasonable attempt is made to use the most current version, and all credits and copyright notices are retained.
Distribution Rights
All requests for other distribution rights, including incorporation in commercial products, such as books, magazine articles, CD-ROMs, and or computer programs should be made to the primary author Lewis Sellers.
Warranty and disclaimer
This document is provided as is without any express or implied warranties. This is a work-in-progress, and as such will contain outdated or as yet uncorrected or substanstiated assumptions. The author, maintainer and/or contributors assume no responsibility for errors or omissions, or for damages resulting from the use of the information contained herein.
WWW Home Sites
You can currently find home sites to this project at If you can not reach them, or they seem to be down, do a key word search on AltaVista, Lycos, or the Web Crawler search engines.
Contact Email
The primary author of Grail Millennium should be reachable at lsellers@usit.net.
OCI/Spec | C O N T R O L L E R S
DESIGNER
Lewis A. Sellers (aka Minimalist) lsellers@usit.net
DRAFTS
- 0.00 ?/?/95
- 2/6/96 revision 0.01
- 7/31/96 revision 0.02
(a0.02)
Preface
Table of Contents
Legal Notices Who gets sued and why History Changes and who made them Preface About this document and the people that make it
Overview An Overview of the Controller Interface Abstract Virtual Presence Human Virtual Presence Mouse Joystick Light Pen Tablet Pen VR Glove VR Head Tracker
A Controllers Interface Overview
CONCEPT | Lewis A. Sellers lsellers@usit.net keyboardORIGINAL DESIGN | Lewis A. Sellers lsellers@usit.net
joystick
mouse
vr glove
vr headset controller
CONCEPT | Lewis A. Sellers lsellers@usit.net ORIGINAL DESIGN | Lewis A. Sellers lsellers@usit.net
There are two high-level non-hardware specific VR controller interface objects. The less-detailed one is the AVPI, or Abstract Virtual Presense Interface. With this interface you have three points of reference, the Point of Vision (POV), the Point of Body (POB) and the Point of Action (POA). These are typically derived from one piece of hardware and provide a common interface that allows you to switch controller types at will (even to the bizarre) without having to rewrite your applications.
Each of the these abstract points (POV, POB, and POA) have the same set of attributes:
POINT
x, y, z
roll, pitch, yawn
VECTOR
x, y, z
roll, pitch, yawn
All are 16-bits (word) in size. They are updated by whatever hardware device you've choosen to drive the AVPI.
The Point of Vision (POV) describes where you are looking. The Point of Body (POB) describes where your body is. The Point of Action (POA) describes where you are acting upon... ie, where you are pointing your gun, etc. There is also the alternatie POA called POAA. The three points may be the same with some controllers, while others fully support them all in some fashion. If a point is not supported then you get the data for POV.
For example... If you assign a simple joystick to your AVPI then POV, POB, and POA will all be the same. Vector will be interpreted as the change in readings since the last poll. The points roll, pitch and yawn....
The AVPI also has what is called a command matrix. Simply put, this a list of all the buttons on the device. A specific joystick's device driver may or may not assign some of the buttons as command set toggles. For instance, if you have a four button joystick, one of them might be assigned as a set toggle that change the operation of all the other buttons (same as SHIFT, ALT or CTRL on the keyboard). Buttons that change state are state buttons. The others are action buttons.
timebase:
Pressure
We can also send back some form of a tactile response through this interface. While no where near as complex as the other VR controller responses it is sufficient for our purposes here. Each of the four points can recieve a feedback of four types. As to whether these are actually used depends upon your controller and it's object software. At any rate, the feedback is quantified as:
-3 extremely pleasing
-2 pleasure
-1 soft
0 no feedback
1 contact
2 pain
3 severe pain
Pain is easy. The pleasure response is harder. For better quantification you must use the human VR interface.
Interfacing
Umm... ok. How to I get this to work with my joystick or VR glove? The VR_ABSTRACT encapsulates a specific piece of hardware (or hardwares). By default Grail always loads in an object which does nothing. Should you want to use a joystick here you'd call the __OBJECT.Morph VR_ABSTRACT, "VR_ABSTRACT Joystick".
You can also write your own object... even in script. Check out the section on scripts in the kernel.doc for an example.
VR_ABSTRACT.Info
support pov, pob, poa, poaa, response, - resp, +resp
matrix sets, commands
poa swapped with poaa
VR_ABSTRACT.Reset
VR_ABSTRACT.GetPOV
x, y, z
roll, pitch, yawn
VR_ABSTRACT.GetPOB
VR_ABSTRACT.GetPOA
VR_ABSTRACT.GetPOAA
VR_ABSTRACT.ResponsePOV
VR_ABSTRACT.Command
VR_ABSTRACT.CommandMatrix
CONCEPT | Lewis A. Sellers lsellers@usit.net ORIGINAL DESIGN | Lewis A. Sellers lsellers@usit.net
VR_HUMAN.
head
neck
lower torso
upper torso
left hand
right hand
left arm
right arm
left foot
right foot
left leg
right leg
....data
no.
flexions...
pressure at
feedback
data migration path
resolution
point-to-point length defination
commands
CONCEPT | Lewis A. Sellers lsellers@usit.net ORIGINAL DESIGN | Lewis A. Sellers lsellers@usit.net
JOYSTICK.Info
Polled or interrupt?
timebase (ns)
no. buttons
JOYSTICK.Reset
JOYSTICK.Calibration(topx, topy, centerx, centery, rightx, righty, hot_spot, warmup)
Passes the calibration settings to the JOYSTICK object including the hot_spot and warmup variance.
JOYSTICK.Exist
Does the JOYSTICK.xy routine and if it times out (goes to FFFFh) then returns a 0, else returns 1.
JOYSTICK.Button button
0= not press
1= press
2= not exist
JOYSTICK.Buttons
0= not press
1= press
2= not exist
JOYSTICK.xy
Returns the current signed x and y location of joystick.
JOYSTICK.xy_Vector
Returns the directional movement in the x and y directions as -1, 0 and 1. In script it might look like:
(x, y) = JOYSTICK.xy_Vector
JOYSTICK.xy_Acceleration
Returns the change is x and y since the last time it was checked.
CONCEPT | Lewis A. Sellers lsellers@usit.net ORIGINAL DESIGN | Lewis A. Sellers lsellers@usit.net
MOUSE.Info
MOUSE.Rest
MOUSE.ButtonStatus button
0= not press
1= press
2= not exist
MOUSE.xy
MOUSE.xy_Vector
MOUSE.xy_Acceleration
CONCEPT | Lewis A. Sellers lsellers@usit.net ORIGINAL DESIGN | Lewis A. Sellers lsellers@usit.net
The old Motorola 6845 CRT controller chips on the first IBM PC graphics cards had simple light pen support. Some cards still do. These functions directly access those ports.
LIGHTPEN.Info
LIGHTPEN.Reset
LIGHTPEN.Press
LIGHTPEN.xy
LIGHTPEN.xy_Vector
LIGHTPEN.xy_Acceleration
CONCEPT | Lewis A. Sellers lsellers@usit.net ORIGINAL DESIGN | Lewis A. Sellers lsellers@usit.net
TABLETPEN.Info
TABLETPEN.Reset
TABLETPEN.Button
TABLETPEN.Pressure
TABLETPEN.PRESs
TABLETPEN.xy
TABLETPEN.xy_Vector
TABLETPEN.xy_Acceleration
CONCEPT | Lewis A. Sellers lsellers@usit.net ORIGINAL DESIGN | Lewis A. Sellers lsellers@usit.net
VR_GLOVE
VR Head Tracker
CONCEPT | Lewis A. Sellers lsellers@usit.net ORIGINAL DESIGN | Lewis A. Sellers lsellers@usit.net
VR_HEADTRACKER.
KEYBOARD
CONCEPT | Lewis A. Sellers lsellers@usit.net
ORIGINAL DESIGN | Lewis A. Sellers lsellers@usit.net
An IRQ1 (INT 31h) is generated by any press or release of keys on the IBM AT compat keyboard. That keys scancode is sent to port 60h (and 64h) where it is read and translated into an ascii code format. Scancode may consist of more than one byte, and thus require multiple intelligent reads to determine the specific key pressed.
A bit buffer is kept for all translated ascii keys which represents NOTPRESSED if 1 and PRESSED if 0. This is possible because IBM keyboards generate scancode at both the press AND release of a key. Each byte of a scancode is 7 bits, the 8th bit of the scancode byte representing PRESS if 0 or RELEASE if 128.
Light toggling is hardcoded into the keyboard handler. So is general toggling, and the special handling of SHIFT, ALT and CTRL keys. SHIFT, ALT and CTRL generate scancodes, but are not translated into getable ascii keycodes. A seperate bit buffer, contingous to the normal bit buffer, is kept for them. If you wish to determine if they are pressed, you must read their PRESS/RELEASE bit from the buffer.
Special handlers may be linked into the keyboard interrupt for short tasks. Very short tasks.
All keycodes are in word format.
Translate_Scancode_to_KeycodeBuffer()
Directly reads port 64h, getting scancodes into an 8 byte buffer. Once all scancodes are recieved, uses smart lookup tables to quickly getback the appropriate ascii code, store it in the keyboard buffer area before returning UNLESS the scancodes are for any of the SHIFT,ALT or CTRL keys being pressed.
If the scancode is SHIFT, ALT or CTRL their bit buffer is appropriately masked, and this routine returns.
The ascii lookup may be modified by having any of the SHIFT, ALT or CTRL keys PRESSED DOWN or if the CAPS LOCK, NUM LOCK or SHIFT LOCK are toggled ON.
All validily translated ascii codes have their PRESS or RELEASE data masked into a bit buffer. This buffer is currently 101 bits in length (16 bytes allocated) and is access via an associated 101 word long table of valid ascii keycodes.
The INT 31h which is tied to IRQ1 jumps to this routine.
A set of bit-flags are kept in a byte to determine the toggle status of all hardcoded toggled-keys. In this set of bit-flags 0 represents NOT_TOGGLED and 1 represents TOGGLED.
These bit states are flipped every time a toggle-key is PRESSED. Every time a toggle key is pressed, it is checked to see if it also has an assigned keyboard light. The light is turn ON or OFF, appropriately.
SOURCE/LIGHTS:
mov al,0edh ;change lights command
out 64h,al
nop ;wait
mov al,KEYBOARD_TOGGLE_FLAGS
and al,7 ;isolate the first three toggles
out 64h,al
Ö7Â6Â5Â4Â3Â2Â1Â0.
º not used3c3n3sº
ÓÄÁÄÁÄÁÄÁÄÁÒÁÒÁÒ1/2
º º ÈÍ ScrollLock light (0=OFF / 1=ON)
º ÈÍÍÍ NumLock light
ÈÍÍÍÍÍ CapsLock light
IBM KEYBOARD SCANCODE TRANSLATION MATRIX:port data Shift Ctrl Alt 01 ESC 02 1 03 2 04 3 05 4 06 5 07 6 08 7 09 8 0A 9 0B 0 0C - 0D = 0E BackSpace 0F Tab 10 q 11 w 12 e 13 r 14 t 15 y 16 u 17 i 18 o 19 p 1A [ 1B ] 1C Enter 1D Left Ctrl 1E a 1F s 20 d 21 f 22 g 23 h24 j
25 k
26 l
27 ;
28 '
29 '
2A Left Shift
2B \
2C z
2D x
2E c
2F v
30 b
31 n
32 m
33 ,
34 .
35 /
36 Right Shift
37 PrtSc
38 Left Alt
39 Space Bar
3A Caps Lock
3B F1
3C F2
3D F3
3E F4
3F F5
40 F6
41 F7
42 F8
43 F9
44 F10
45 Num Lock
46 Scroll Lock
47 Home
48 Cursor Up
49 PgUp
4A Gray -
4B Cursor Left
4C (gray 5)
4D Cursor right
4E Gray +
4F End
50 Cursor Down
51 PgDn
52 Ins
53 Del
54 Sys Req
E0 1C Gray Enter
E0 1D Right Ctrl
E0 35 Gray /
37 Gray *
E0 38 Right Alt
E0 47 Gray Home
E0 48 Gray C Up
E0 49 Gray PgUp
E0 4B Gray C Left
E0 4D Gray C Right
E0 4F Gray End
E0 50 Gray C Down
E0 51 Gray PgDn
E0 52 Gray Ins
E0 53 Gray Del
57 F11
58 F12
E1 Pause
Caps Lock All asciis from 'a' to 'z' are translated to 'A' to 'Z'. All asciis from 'A' to 'Z' are translated to 'a' to 'z'. Num Lock ?
KeycodeKeycodes are generally in standard ASCII format for cross-platform compatibility reasons. This means that when a key is pressed its scancode is translated directly into ASCII before you ever see it.
Internal Keyboard Structures
dword pointer to current key from keyboard
dword last read pointer
byte ?
byte keyboard_buffersize
word keyboard_bufferlength
dword pointer to buffer
byte KEYBOARD_TOGGLE_FLAGS
bit 0=scroll
1=num
2=caps
3=insert
4=pause
word Key_Buffer[256];
dword keyboard_bitbuffer[4];
keyexist_list []
Keypress Interrupt Handlers
3 (word)Link_Keypress_to_InterruptHandler(int keycode,char *handler)
Will attempt to add a link to the keyboard handler that INT 31h (IRQ1) calls before it IRETs.
3 (void)Unlink_Keypress_from_InterruptHandler(int keypress)
Removes a key from the keyboard interrupt list.
3 (void)Unlink_All_Keypress_from_InterruptHandlers()
Changes the call in the INT 321h handler to pointer to a RET.
3 (word)Number_of_Kepress_InterruptHandlers()
Returns the no of keys monitored. There is a base minimum of 16.
KEYBOARD.Initialize
Sends commands to reset the keyboard microprocessor on IBM AT compats. If all goes well, a 1 (OK) is returned. Otherwise, a 0 (NULL)
PSUEDO SOURCE OF FUNCTION:
mov al,ffh ;reset keyboard, internal diagnostics
out 64h,al
nop ;wait
mov al,f4h ;enable keyboard,clear buffer, and send ACK
out 64h,al
nop ;wait
in al,64h
cmp al,6h ;ack?
jne nokback
nop ;no send echo-back diagnostic
mov al,0eeh
out 64h,al
nop
in al,64h
cmp al,0eeh ; if we recieve 0eeh back, then the keyboard is working.
jne nokback
;now that we know the keyboard seems to be there and functioning,
;let us set the typematic rate to something decent
mov al,0f3h ; send typematic rate & delay change command
out 64h,al
; 0=250ms
; Ö7Â6Â5Â4Â3Â2Â1Â0. 1=500ms
; º03dly3rept rateº 2=750ms
; ÓÒÁÄÁÄÁÄÁÄÁÄÁÄÁÄ1/2 / 3=1000ms
; º ÈË1/4 ÈÍÍÍÍÍÍÍÊÍ bits 0-4 the repeat rate
; º ÈÍÍÍÍÍÍÍÍÍÍÍÍ bits 5-6 initial delay before first repeat
; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ bit 7 is always 0 \
; Value Rate Value Rate
; 0 = 30.0 0Ah = 10.0
; 1 = 26.7 0Dh = 9.2
; 2 = 24.0 10h = 7.5
; 4 = 20.0 14h = 5.0
; 8 = 15.0 1Fh = 2.0
nop ; wait
mov al,2 + 0*32 ; set the delay to 1/4-second with 24 repeats per sec.
mov al,1 ;everything went fine. return 1 (OK).
ret
nokback: ; there was a problem. return 0 (NULL).
xor al,al
ret
KEYBOARD.Deinitialize
Doesn't do anything on IBM PCs clones, but provided for completeness.
KEYBOARD.Get_BufferSize
Returns KEYBOARD_BUFFER_SIZE, from which the buffer size is computed by 2^n. Ranges from 4 to 15, so buffer size is from 16 to 32768. Default is 32 characters.
KEYBOARD.Set_BufferSize length
Sets KEYBOARD_BUFFERSIZE as 2^bs. Valid bitmag from 4 to 15.
KEYBOARD.ClearBuffer
Clears all keys in the key buffer. Makes position equal to lastread position.
KEYBOARD.WriteKey
Puts a key (back?) into keyboard buffer. It has it's uses.
KEYBOARD.ReadKey
Returns the word at the current last-read buffer position unless the current buffer position is equal to it. If a keycode is available it also increases the last-read pointer ahead (by a word). cf. getch().
KEYBOARD.ReadKey_Monitor
Same as readkey() but the pointer is not advanced. cf. kbhit().
KEYBOARD.KeyExist keycode
Looks up the keycode in the KeyExists list and returns a 1 if the key exists on the users keyboard. You of course get a 0 if it can't be found, or its equivilent. The Open-Apple for instances is rarely found on an IBM PC Platform.
KEYBOARD.KeyStatus keycode
Looks up (REP SCAS) the asciikeycode's position in the keyboard bit buffer, then retrieves that bit. If the bit is 0, the key in question is currently down. If it is 1, it is not being pressed. Also looks in the key existance
KEYBOARD.KeyStatus_Direct bitposition
A quicker version of KeyStatus. If you have a table listing the ordering of ascii keycodes internally in the MOSAPI (which should be the same on most all platforms) you can skip the lookup table part and directly grab the appropriate bit from the bit buffer.
KEYBOARD.ToggleStatus key
Returns a 0 if key is not toggled, a 1 if toggled, and a 2 if it does not toggle.
KEYBOARD.LightStatus key
Returns a 1 if light is on, a 0 if light is off and a 2 if no light.
KEYBOARD.xy
KEYBOARD.xy_Vector
KEYBOARD.xy_Acceleration