koreth@ssyx.ucsc.edu (Steven Grimm) (03/30/88)
Submitted-by: sirkm@ucscb.ucsc.edu (Greg Anderson) Posting-number: Volume 1, Issue Archive-name: joyread [Lots of STers seem to have trouble reading the joystick ports, which is much more painful on the ST than on the 8-bit. These routines should help make it easier. Note that these are just some routines, and not a complete program. -sg] /*------------------------------------------------------------------------- | Stick.c: Joystick interupt service routine | | Placed in the public domain March 1988 by Greg Anderson. | | The joystick demo by Steve Jankowski was instrumental to | the creation of these routines. | | Many thanks to Steven Grimm for providing essential information | and the aforementioned joystick demo. | |########################################################################## | THESE ROUTINES ONLY WORK UNDER LASER C! THEY MUST BE MODIFIED FOR | OTHER C COMPILERS, _INCLUDING_ MEGAMAX C VERSION 1.xx! | | MegaMax instructions: A4 must be saved somewhere so that it is | available durring the isr. Then, the isr can access joyinf | with "lea joyinf(A4),A1" instead of "lea joyinf,A1". |########################################################################## | | This package sets up an interupt to read the joystick on the | ST. The joystick is read via the ikbd--the intelligent keyboard | interface chip. The ikbd can be placed into "joystick-reading | mode" by sending an appropriate command with Ikbdws(). This has | two effects: first, the mouse is disabled. Second, the ikbd will | be prompted to send a three-byte packet every time one of the | joysticks changes states. The packet is as follows: | | [Stick #] [State of Stick 0] [State of Stick 1] | | The first byte is $FE if stick 0 changed, or $FF if stick 1 | changed. These routines ignore the first byte. | The next two bytes contain the states of sticks 0 and 1. | There values will be the sum of: | | +1 (+128) | | | +4 ---< >--- +8 | | | +2 | | Add the apropriate value if the contact is down. For example, | if stick 0 is NW and the trigger has not been pressed, its | current state will be 1 + 4 = 5. | | These packets are sent to a routine pointed to by "joyvec". | Joyvec is part of the structure returned by Kbdvbase(). Joyvec | can be changed to point to an interupt service routine (isr) of | our devising. If this is done, the isr will find that A0 points | to the first byte of the the packet sent by the ikbd. The isr | must be very short (less than 1ms exicution time). Atari's docs | of Kbdvbase indicate that a copy of the pointer to the packet is | also deposited on the stack; however, this does not appear to be | the case. | | Using these routines: | | Call stick_init() to set up the joystick isr and place the ikbd | into joystick send mode. This will also disable the mouse. | | stick_exit() will return the ikbd to mouse send mode. Your | program should do this before exiting. | | Once the initialize routine has been called, the following | commands are available: | | _stick(n): Return the state of stick N. (See above chart) | stick(n) : Return the direction of stick N. (Minus the trigger) | trig(n) : Return the state of the trigger on stick N. | hstick(n): Return the horizontal position of stick N. (-1 to +1) | vstick(n): Return the vertical position of stick N. | -------------------------------------------------------------------------*/ #include <osbind.h> char ikbdcmd[10]; /* Storage space for ikbd commands */ #define SENDJOY 0x14 /* Send joystick packets */ #define SENDMOUSE 0x08 /* Send mouse packets */ extern joyisr(); /* Interupt service routine follows */ int (*oldjoyvec)(); /* Save old isr vector here */ int initialized = 0; /* Initialized flag */ unsigned char joyinf[2]; /* Holds data for joystick states */ int joytab[4] = { 0, -1, 1, 0 }; #define xstick(v) joytab[ v & 0x03 ] /*------------------------------------------------------------------- | Initialize joystick isr -------------------------------------------------------------------*/ void stick_init() { kbdvecs *KB; /* Do nothing if joystick isr has been initialized */ if (initialized) return; /* Put our isr into the joystick interupt vector slot */ KB = Kbdvbase(); oldjoyvec = KB->joyvec; KB->joyvec = joyisr; /* Tell ikbd to send joystick packets. */ ikbdcmd[0] = SENDJOY; Ikbdws(0, ikbdcmd); initialized = 1; } /*------------------------------------------------------------------- | End joystick mode--go back to sending mouse packets. -------------------------------------------------------------------*/ void stick_exit() { kbdvecs *KB; /* Do nothing if joystick isr not initialized */ if (! initialized) return; /* Tell ikbd to go back to sending mouse packets */ ikbdcmd[0] = SENDMOUSE; Ikbdws(0, ikbdcmd); /* Restore the old joystick interupt vector */ KB = Kbdvbase(); KB->joyvec = oldjoyvec; initialized = 0; } /*------------------------------------------------------------------- | Here is the actual joystick interupt service routine. | Both stick 0 and stick 1 are placed into the variable | "joyinf". -------------------------------------------------------------------*/ asm { joyisr: lea joyinf,A1 /* "joyinf" holds data */ addq.l #1,A0 /* We don't want first byte */ move.b (A0)+,(A1)+ /* Joystick 0 state */ move.b (A0)+,(A1)+ /* Joystick 1 state */ rts } /*------------------------------------------------------------------- | Return the state of stick 0 or stick 1. | Bits 0-3 = stick direction, bit 7 = trigger. -------------------------------------------------------------------*/ int _stick(n) int n; { return(joyinf[n]); } /*------------------------------------------------------------------- | Return the direction bits of stick 0 or stick 1. -------------------------------------------------------------------*/ int stick(n) int n; { return( joyinf[n] & 0x0F ); } /*------------------------------------------------------------------- | Return the state of the trigger of stick n: -------------------------------------------------------------------*/ int trig(n) int n; { return( (joyinf[n] & 0x80) != 0 ); } /*------------------------------------------------------------------- | Return the horizontal state of stick n: | +1 = right, 0 = centered, & -1 = left -------------------------------------------------------------------*/ int hstick(n) int n; { return(xstick(joyinf[n] / 4)); } /*------------------------------------------------------------------- | Return the vertical state of stick n: | +1 = down, 0 = centered, -1 = up. -------------------------------------------------------------------*/ int vstick(n) int n; { return(xstick(joyinf[n])); }