[net.micro.atari] How to read joystick/mouse ports on 520ST?

Felton.PA@XEROX.ARPA (12/03/85)

>How do I read the joystick ports on the 520ST?


Good Question!  I have asked it twice on the net already. If anyone
knows please post the answer so that we will all know.

Thanks,

John

sansom@trwrba.UUCP (Richard E. Sansom) (12/05/85)

>
>>How do I read the joystick ports on the 520ST?
>
>
>Good Question!  I have asked it twice on the net already. If anyone
>knows please post the answer so that we will all know.
>

(You may be sorry you asked!)  There is quite a bit you have to know to
read thejoystick/mouse ports.  If you don't want to read all of this,
look for part 2 of this document - I'll include a sample source listing
to show you how to do it.

Both the joystick port and the mouse port are controlled by the
"Intelligent Keyboard" (ikbd) which (quoting Atari's documentation)
"communicates with the main processor over a high speed bi-directional
serial interface...", and, "...can function in a variety of modes to
facilitate different applications of the keyboard, joysticks, or mouse."



Keyboard
--------
The keyboard always returns key make/break (press/release)
codes.  The break (release) codes are obtained by ORing 0x80 with the
make (press) codes.  The key codes are defined as follows:

	Code Key		Code Key		Code Key
	--------		--------		--------
	 00   undefined(?)	 10   Q			 20   D
	 01   ESC		 11   W			 21   F
	 02   1			 12   E			 22   G
	 03   2			 13   R			 23   H
	 04   3			 14   T			 24   J
	 05   4			 15   Y			 25   K
	 06   5			 16   U			 26   L
	 07   6			 17   I			 27   ;
	 08   7			 18   O			 28   '
	 09   8			 19   P			 29   `
	 0A   9			 1A   [			 2A   LSHIFT
	 0B   0			 1B   ]			 2B   \
	 0C   -			 1C   RET		 2C   Z
	 0D   ==		 1D   CTRL		 2D   X
	 0E   BS		 1E   A			 2E   C
	 0F   TAB		 1F   S			 2F   V

	Code Key		Code Key		Code Key
	--------		--------		--------
	 30   B			 40   F6		 50   DOWN ARROW
	 31   N			 41   F7		 51   {not used}
	 32   M			 42   F8		 52   INS
	 33   ,			 43   F9		 53   DEL
	 34   .			 44   F10		 54   {not used}
	 35   /			 45   {not used}	 55   {not used}
	 36   RSHIFT		 46   {not used}	 56   {not used}
	 37   {not used}	 47   HOME		 57   {not used}
	 38   ALT		 48   UP ARROW		 58   {not used}
	 39   SPACE		 49   {not used}	 59   {not used}
	 3A   CAPS LOCK		 4A   KEYPAD - 		 5A   {not used}
	 3B   F1		 4B   LEFT ARROW	 5B   {not used}
	 3C   F2		 4C   {not used}	 5C   {not used}
	 3D   F3		 4D   RIGHT ARROW	 5D   {not used}
	 3E   F4		 4E   KEYPAD +		 5E   {not used}
	 3F   F5		 4F   {not used}	 5F   {not used}

	Code Key		Code Key
	--------		--------
	 60   ISO KEY		 70   KEYPAD 0
	 61   UNDO		 71   KEYPAD .
	 62   HELP		 72   KEYPAD ENTER
	 63   KEYPAD (
	 64   KEYPAD )
	 65   KEYPAD /
	 66   KEYPAD *
	 67   KEYPAD 7
	 68   KEYPAD 8
	 69   KEYPAD 9
	 6A   KEYPAD 4
	 6B   KEYPAD 5
	 6C   KEYPAD 6
	 6D   KEYPAD 1
	 6E   KEYPAD 2
	 6F   KEYPAD 3
   
Mouse
-----
There are 3 different ways ikbd can report mouse motion:
relative, absolute, and by converting mouse motion into cursor control
key equivalents.  The mouse buttons can either be treated as part of
the mouse or as additional keyboard keys.

Relative Position Reporting:
When a mouse event (mouse button pressed or released, or motion in
either axis) occurs, ikbd returns a three byte record containing:

	%111110xx	; mouse position record flag
	       ||
	       |------- ; right button state
	       -------- ; left button state
	%xxxxxxxx	; delta X (twos complement integer)
	%xxxxxxxx	; delta Y (twos complement integer)

NOTE - ikbd may return more than threshold delta X or Y since no
relative mouse motion events will be generated during certain
operations.  Also, if the accumulated motion exceeds +127..-128, then
the motion is broken into multiple packets.

Absolute Position Reporting:
Commands exist for reseting the mouse position, setting X & Y scaling,
and interrogating the current mouse position (see below).

Mouse Cursor Key Mode:
ikbd can translate mouse motion into the equivalent cursor keystrokes -
the number of "clicks" per keystroke being independently programable in
each axis.  Mouse motion produces the cursor key make (press) code
immediately followed by the break (release) code for the appropriate
cursor key.  The mouse buttons produce scan codes above those normally
assigned for the largest envisioned keyboard (i.e. LEFT=0x74, RIGHT=0x75).

Joystick
--------
As in mouse reporting, ikbd can report changes in the joystick
state in several different ways: joystick event reporting, joystick
interrogation, joystick monitoring, fire button monitoring, and
joystick key code equivalents.

Joystick Event Reporting:
ikbd will generate a record when the joystick undergoes a change of
state (i.e. when pressing forward, pulling back, or pressing the
trigger).  The event record consists of two bytes:

	%1111111x	; joystick event marker
	        |
	        ------- ; joystick number (0 or 1)
	%x000yyyy
	 |   ||||
	 |   ---------- ; stick position
	 -------------- ; trigger

Joystick Interrogation:
The current state of the joystick ports may be interrogated at any time
by sending the "Interrogate Joystick" command (see below) to ikbd.  The
response is a three byte report:

	0xFD		; joystick report header
	%x000yyyy	; joystick 0
	%x000yyyy	; joystick 1
			;  where x is the trigger
			;  and yyyy is the position

Joystick Monitoring:
It is possible to devote nearly all of the keyboard communications time
to reporting the state of the joystick ports, at a user specified rate
(see below).

Fire Button Monitoring:
A mode exists which permits monitoring a single input bit at the
maximum rate permitted by the serial communications channel.  ikbd
monitors joystick 1 and packs the data, 8 bits per byte for
transmission.

Joystick Key Code Mode:
ikbd may be commanded to translate the use of either joystick into the
equivalent cursor control keys.  Joystick events produce the make
(press) code, immediately followed by the break (release) code for the
appropriate cursor motion.  The trigger produces key scan codes above
those used used by the largest keyboard envisioned.

Power-up Mode
-------------
ikbd performs a number of self-test diagnostics on power-up.  If no
erros are detected, the code 0xF0 is returned.  (Actually, depending on
the version, you may get 0xF1, 0xF2, etc.)  ikbd defaults to mouse
position reporting with threshold unit of 1 in either axis, and the Y=0
origin at the top of the screen, and joystick event reporting mode for
joystick 1, with both buttons being logically assigned to the mouse.
After any joystick commands, ikbd assumes joysticks are connected to
both joystick ports.  Any mouse command (except "Mouse Disable") then
again causes port 0 to be scanned as if it were a mouse, and both
buttons are logically connected to it.

ikbd Commands
-------------
Commands may be sent to ikbdws using the Ikbdws() function (ikbd Write
String):

VOID	Ikbdws(cnt,ptr)
WORD	cnt;		/* number of bytes to send minus 1 */
LONG	ptr;		/* pointer to the string of bytes  */

Reset - return ikbd to power-up state

	0x80
	0x81

Set Mouse Button Action - select mouse button mode

	0x07
	%00000mss	; mouse button action
	      |||	; (m is presumed to be 1 when in 
	      |||	;  Mouse Keycode mode)
	      --------- ; 0wx	mouse button press or release
			;  ||	causes mouse position report
			;  ||	(wx only relevant if in
			;  ||    absolute mouse pos. mode)
			;  |--	1 -> mouse key press causes
			;  |         absolute pos. report
			;  ---  1 -> mouse key release causes
			;	     absolute pos. report
			; 100 = mouse buttons act like keys

Set Relative Mouse Position Reporting (default)

	0x08

Set Absolute Mouse Positioning

	0x09
	Xmsb		; X maximum (scaled mouse clicks)
	Xlsb
	Ymsb		; Y maximum (scaled mouse clicks)
	Ylsb

Select Mouse Keycode Mode

	0x0A
	deltax		; distance in X clicks to return
	deltay		; distance in Y clicks to return

Set Mouse Threshold

	0x0B
	X		; x threshold in clicks
	Y		; y threshold in clicks

Set Mouse Scale

	0x0C
	X		; horz. mouse ticks per internal X
	Y		; vert. mouse ticks per internal Y

Interrogate Mouse Position

	0x0D
returns:	0xF7		; abs. mouse pos. header
		%0000xxxx	; buttons
		     ||||
		     |||------- ; right button down
		     |||        ; since last interrogation
		     ||-------- ; right button up since last...
		     |--------- ; left button down since last...
		     ---------- ; left button up dince last...
		Xmsb		; X coordinate
	        Xlsb
		Ymsb		; Y coordinate
		Ylsb

That's about all I have time for now.  I'll finish up the list of
commands, and give an example (in C source) of how to put all of this
together in a couple of days.

Richard E. Sansom
{decvax,ucbvax,ihnp4}!trwrb!trwrba!sansom

tlz@druxu.UUCP (ZrustTL) (12/07/85)

How do I read the joystick ports on the 520ST via Basic?  I didn't
see STICK() or STRIG() or MOUSE()  :-)  anywhere in my manual.
Where do I peek()?

Thanks!
Terry Zrust   ATTISL Denver (303) 538-4547
-- 
druxu!tlz                                        _
Terry L. Zrust                                  (_)  /~\
AT&T Information Systems                  /~\       /   \/\
11900 North Pecos Street                 /   \ /\  / |   \ \
Denver, Colorado 80234           /\     /     \  \/ /|\   \ \
Mail Stop 30L49                 /  \   /       \ / //|\\   \ \
(303) 538-4547                ___   \_/     ___ \ ///|\\\  _\   
Cornet 374-4547           _________________ _______  |  _________

Felton.PA@XEROX.ARPA (12/09/85)

Richard,

	Thanks for sharing your knowlege of the Atari ST joystick/mouse ports
with us. Not konwing how to access the joysticks has been driving me
crazy for a couple of months now. I am anxiously awaiting the next
exciting installment (especially the example C source code).
	
	
	
John

info-atari@ucbvax.UUCP (12/12/85)

No such info appeared on my net!  PLEASE! HOW DO YOU ACCESS THE
JOYSTICK PORT?   Thanks in advance!

sansom@trwrba.UUCP (Richard E. Sansom) (12/16/85)

Here are the rest of the ikbd commands, and a C program which will
read joystick 0 (sorry it took me so long to get back to this!).

Load Mouse Position

	0x0E
	0x00		; filler (?)
	XMSB		; X coordinate (scaled coordinate system)
	XLSB		;
	YMSB		; Y coordinate
	YLSB

Set Y=0 at Bottom

	0x0F

Set Y=0 at Top

	0x10

Resume - Resume sending data to host (after a pause)

	0x11

Disable Mouse - Disable mouse event reporting (any mouse command resumes)

	0x12

Pause - Stop sending data to the host

	0x13

Set Joystick Event Reporting (default)

	0x14

Set Joystick Interrogate Mode

	0x15

Interrogate Joystick

	0x16

Set Joystick Monitoring

	0x17		;
	rate		; time between samples in hundredths of a second

		Returns: (in packets of two as long as in mode)
			%000000xy
			       ||
			       |--- ; JOYSTICK1 Fire button
			       ---- ; JOYSTICK0 Fire button
			%nnnnmmmm
			 ||||||||
			 ||||------ ; JOYSTICK1 state
			 ---------- ; JOYSTICK0 state

Set Fire Button Monitoring

	0x18
		Returns: (as long as in mode)
			%bbbbbbbb  ; state of JOYSTICK1 packed 8 bits
				   ; per byte

Set Joystick Keycode Mode

	0x19
	RX		; horizontal velocity breakpoint (tenths of seconds)
	RY		; vertical velocity breakpoint (tenths of seconds)
	TX		; horizontal cursor key generation delay (tenths)
	TY		; vertical cursor key generation delay (tenths)
	VX		; horizontal cursor key generation repeat (tenths)
	VY		; vertical cursor key generation repeat (tenths)

Disable Joysticks

	0x1A

Time-of-Day Clock Set

	0x1B
	YY		; year (two least significant digits)
	MM		; month
	DD		; day
	hh		; hour
	mm		; minute 
	ss		; second

	NOTE: all time-of-day data should be sent as packed BCD.

Interrogate Time-of-Day Clock

	0x1C
		Returns:
			0xFC	; time-of-day event header
			YY	; year
			MM	; month
			DD	; day
			hh	; hour
			mm	; minute
			ss	; second

	NOTE: time-of-day data returned as packed BCD.

Memory Load - load ikbd controller memory

	0x20
	ADDRMSB		; address of controller memory (high)
	ADDRLSB		; address of controller memory (low)
	NUM		; number of bytes (0-128)
	{data}

Memory Read - read ikbd controller memory

	0x21
	ADDRMSB		; address of controller memory (high)
	ADDRLSB		; address of controller memory (low)
		Returns:
			0xF6	; status header
			0x20	; memory access
			{data}	; 6 data bytes starting at ADDR

Controller Execute - execute ikbd controller subroutine

	0x22
	ADDRMSB		; address of subroutine in controller
	ADDRLSB		; memory to be called

Status Inquiries
----------------
All status commands are formed by ORing 0x80 with the relevant SET command.
Valid Status Inquiry commands are:

	0x87	mouse button action
	0x88	mouse mode
	0x89
	0x8A
	0x8B	mouse threshold
	0x8C	mouse scale
	0x8F	mouse vertical coordinates
	0x90	(returns 0x0F if Y=0 at bottom, 0x10 if Y=0 at top)
	0x92	mouse enable/disable (0x00=enabled, 0x12=disabled)
	0x94	joystick mode
	0x95
	0x99
	0x9A	joystick enable/disable (0x00=enabled, 0x1A=disabled)

	NOTE: Status Inquiry commands are NOT VALID if the ikbd is in
	      Joystick Monitoring Mode or Fire Button Monitoring Mode.


Phew!  Now that you've got all that stuff memorized, you can forget
most of it.  As far as I can tell, the ST is set-up to not monitor the
joysticks at all!  If you use the  Kbdvbase() call, you will get a
pointer to a structure containing all of the ikbd handlers.  Now, in
the version of TOS I have, the joystick handler vector (joyvec) points
to a RTS (return from subroutine) instruction.  So, since I did not
want to write my own handler, I used the simplest of the joystick
monitoring modes, Joystick Keycode Mode, in the following program.
If I eventually do write a handler, I will post it to the net also.  In
the meantime, enjoy!

-------------------------------------------------------------------------------

/*
 * Atari 520ST Joystick/Keyboard Monitoring Demo
 *
 * Richard E. Sansom  December 1985
 *
 * This is a no-frills program which will monitor joystick 0, and will
 * report joystick events as keystrokes.  No claims are made as to its
 * efficiency (or elegance).
 *
 */

#include <stdio.h>
#include <osbinds.h>

/*
 * defines
 */

#define JOY_UP		0x48
#define JOY_LEFT	0x4B
#define JOY_RIGHT	0x4D
#define JOY_DOWN	0x50
#define JOY_FIRE	0x74

#define TRUE	1
#define FALSE	0

/*
 * globals
 */

static
char	set_joy_key_mode [] = {

		0x19		/* Set Joystick Keycode Mode */
		0x00,0x00,	/* RX, RY */
		0x00,0x00,	/* TX, TY */
		0x01,0x01	/* VX, VY */

	};

static
char	reset_ikbd [] = {

		0x80,0x01	/* Reset */

	};

/*
 * main program
 */

main() {

	int	lo_chr,hi_chr,more;
	long	chr;

/*
 * clear screen, prompt for joystick
 */

	Cconout(0x1B); Cconout(0x45);
	printf("Plug joystick into port 0, hit any key when ready...");
	while (!Cconis())
		;
	Cconin();
	printf("\n");

/*
 * write command string to ikbd
 */

	Ikbdws(6,set_joy_key_mode);

/*
 * loop until 'Q' is hit
 */

	more = TRUE;
	while (more) {
		while (Bconstat(2)) {
			chr = Bconin(2);
			lo_chr = chr & 0x00FF;	/* ascii code */
			hi_chr = chr >> 0x10;	/* scan code  */
			switch (hi_chr) {
				case JOY_UP: {
					printf("Joystick UP ");
					break;	/* Ok, so I'm no purist */
				}
				case JOY_LEFT: {
					printf("Joystick LEFT ");
					break;
				}
				case JOY_RIGHT: {
					printf("Joystick RIGHT ");
					break;
				}
				case JOY_DOWN: {
					printf("Joystick DOWN ");
					break;
				}
				case JOY_FIRE: {
					printf("Joystick FIRE ");
					break;
				}
				default: printf("Keystroke ");
			}
			printf("(scan=0x%x, ascii=0x%x\n)",hi_chr,lo_chr);
			more = !(lo_chr == 'Q');
		}
	}

/*
 * reset ikbd, exit
 */

	Ikbdws(1,reset_ikbd);
	_exit(0);
}

-------------------------------------------------------------------------------

For those of you using the Hippo-C compiler - I've heard that not all
of the ST bios and xbios calls are defined (at least in the documentation),
so you may want to try the following defines, and see what happens.

#define Cconis() conis()
#define Cconin() conin()
#define Bconstat(dev) bios(1,dev)
#define Bconin(dev) bios(2,dev)
#define Ikbdws(cnt,ptr) xbios(25,cnt,ptr)

I don't know if you have a bios() call available, so you may have to
build your own:

	.text
	.global	_bios
_bios:	move.l	(sp)+,.save	; save return address
	trap	#13		; call bios
	move.l	.save,-(sp)	; restore return address
	rts			; return

	.bss
.save	.ds.l			; storage area

You may have to build your own xbios() call also:

	.text
	.global	_xbios
_xbios:	move.l	(sp)+,.save	; save return address
	trap	#14		; call xbios
	move.l	.save,-(sp)	; restore return address
	rts			; return

	.bss
.save	.ds.l			; storage area

I don't know whether the Hippo-C compiler pushes all of its args
on the stack as longs (the DRI compiler does NOT), so you may have to
take that into consideration also.

Richard E. Sansom
{decvax,ucbvax,ihnp4}!trwrb!trwrba!sansom