> # A Grail Millennium Project

> # White Paper

> History | Preface | TOC

> ##### 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
> - http://www.dwc.edu/grail/
> - http://www.usit.net/public/bcannon/grail/
> 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.

> Preface | TOC

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

> TOC

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

> TOC

> # A Controllers Interface Overview

> CONCEPT | Lewis A. Sellers lsellers@usit.net

> ORIGINAL DESIGN | Lewis A. Sellers lsellers@usit.net

> keyboard

> joystick

> mouse

> vr glove

> vr headset controller

> TOC

> # Abstract Virtual Presence

> 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

> TOC

> # Human Virtual Presence

> 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

> TOC

> # Joystick

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

> TOC

> # Mouse

> 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

> TOC

> # LIGHTPEN

> 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

> TOC

> # TABLET PEN

> 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

> TOC

> # VR Glove

> CONCEPT | Lewis A. Sellers lsellers@usit.net

> ORIGINAL DESIGN | Lewis A. Sellers lsellers@usit.net

> VR_GLOVE

> TOC

> # VR Head Tracker

> CONCEPT | Lewis A. Sellers lsellers@usit.net

> ORIGINAL DESIGN | Lewis A. Sellers lsellers@usit.net

> VR_HEADTRACKER.

> TOC

> # 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           h
> >     24           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 	?

> >     Keycode
> >     Keycodes 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