Copy Link
Add to Bookmark
Report

Joystick interrupt service routine

atari's profile picture
Published in 
atari
 · 13 Dec 2020

Stick.c: Joystick interrupt 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 during the isr. Then, the isr can access joyinf with "lea joyinf(A4),A1" instead of "lea joyinf,A1".
###############################

This package sets up an interrupt 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 appropriate 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 interrupt 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 execution 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.

Stick.c

#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]));
}

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT