part revert commit 56211
[AROS.git] / arch / m68k-amiga / lowlevel / readjoyport.c
blobe6606390d4a194117aa2b99388929154c1474c3f
1 /*
2 Copyright © 2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
9 #include <aros/debug.h>
11 #include <aros/libcall.h>
12 #include <exec/types.h>
13 #include <libraries/lowlevel.h>
15 #include <devices/timer.h>
17 #include <proto/potgo.h>
19 #include <hardware/cia.h>
20 #include <hardware/custom.h>
22 #include "lowlevel_intern.h"
24 /* See rom/lowlevel/readjoyport.c for documentation */
26 #define POTGO_GAMEPAD_PORT0 \
27 (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8)
28 #define POTGO_GAMEPAD_PORT1 \
29 (1 << 15) | (1 << 14) | (1 << 13) | (1 << 12)
32 * ciaapra - (1 << 7) is /FIR1 (port 1, pin 6)
33 * ciaapra - (1 << 6) is /FIR0 (port 0, pin 6)
34 * ciaaddra - 0x03
35 * JOYnDAT:
36 * pin 1 (up) = ((JOYnDAT >> 0) ^ (JOYnDAT >> 1)) & 1
37 * pin 2 (dn) = ((JOYnDAT >> 8) ^ (JOYnDAT >> 9)) & 1
38 * pin 3 (lt) = (JOYnDAT >> 9) & 1
39 * pin 4 (rt) = (JOYnDAT >> 1) & 1
40 * POTGO/POTINP:
41 * port 0: pin 9 (1 << 10), pin 5 (1 << 8)
42 * port 1: pin 9 (1 << 14), pin 5 (1 << 12)
44 static inline ULONG llPollGameCtrl(int port)
46 volatile struct Custom *custom = (struct Custom*)0xdff000;
47 volatile struct CIA *cia = (struct CIA *)0xbfe001;
48 UWORD pot;
49 ULONG bits = 0;
50 UWORD joydat;
51 int i;
52 UBYTE cmask = (port == 0) ? (1 << 6) : (1 << 7);
54 /* Set Pin 5 as output, shift mode */
55 pot = custom->potinp;
56 pot &= ~((port == 0) ? (3 << 8) : (3 << 12));
57 custom->potgo = pot | (port == 0) ? (2 << 8) : (2 << 12);
58 cia->ciapra &= ~cmask;
59 cia->ciaddra |= cmask;
61 /* Shift in the button values */
62 D(bug("Sin: \n"));
63 for (i = 0; i < 9; i++) {
64 cia->ciapra |= cmask;
65 cia->ciapra &= ~cmask;
66 bits <<= 1;
67 bits |= ((custom->potinp >> ((port == 0) ? 10 : 14)) & 1) ? 0 : 1;
68 D(bug(" %d", bits & 1));
70 D(bug("\n"));
72 cia->ciapra &= ~cmask;
73 custom->potgo = pot;
75 if ((bits & 3) != 2) {
76 /* Stuck bits? Probably not a game controller */
77 D(bug("%s: Stuck bits? (0x%04x)\n", __func__, bits));
78 /* Revert to autosense */
79 return 0;
81 bits &= ~3;
82 bits <<= 15;
84 /* Get the joypad bits */
85 joydat = (port == 0) ? custom->joy0dat : custom->joy1dat;
87 if ((joydat >> 1) & 1) {
88 bits |= JPF_JOY_RIGHT;
90 if ((joydat >> 9) & 1) {
91 bits |= JPF_JOY_LEFT;
93 if (((joydat >> 0) ^ (joydat >> 1)) & 1) {
94 bits |= JPF_JOY_DOWN;
96 if (((joydat >> 8) ^ (joydat >> 9)) & 1) {
97 bits |= JPF_JOY_UP;
100 return JP_TYPE_GAMECTLR | bits;
104 * ciaapra - (1 << 7) is /FIR1 (port 2, pin 6)
105 * ciaapra - (1 << 6) is /FIR0 (port 1, pin 6)
106 * ciaaddra - 0x03
107 * JOYnDAT:
108 * pin 1 (up) = ((JOYnDAT >> 0) ^ (JOYnDAT >> 1)) & 1
109 * pin 2 (dn) = ((JOYnDAT >> 8) ^ (JOYnDAT >> 9)) & 1
110 * pin 3 (lt) = (JOYnDAT >> 9) & 1
111 * pin 4 (rt) = (JOYnDAT >> 1) & 1
112 * POTGO/POTINP:
113 * port 1: pin 9 (1 << 10), pin 5 (1 << 8)
114 * port 2: pin 9 (1 << 14), pin 5 (1 << 12)
116 static inline ULONG llPollJoystick(int port)
118 volatile struct Custom *custom = (struct Custom*)0xdff000;
119 volatile struct CIA *cia = (struct CIA *)0xbfe001;
120 ULONG bits = 0;
121 UWORD joydat;
122 UBYTE cmask = (port == 0) ? (1 << 6) : (1 << 7);
124 /* 'red' - /FIRn on CIA Port A */
125 bits |= (cia->ciapra & cmask) ? 0 : JPF_BUTTON_RED;
127 /* 'blue' - Pin 9 on POTINP */
128 bits |= ((custom->potinp >> ((port == 0) ? 10 : 14)) & 1) ? 0 : JPF_BUTTON_BLUE;
130 /* Get the joypad bits */
131 joydat = (port == 0) ? custom->joy0dat : custom->joy1dat;
133 if ((joydat >> 1) & 1) {
134 bits |= JPF_JOY_RIGHT;
136 if ((joydat >> 9) & 1) {
137 bits |= JPF_JOY_LEFT;
139 if (((joydat >> 0) ^ (joydat >> 1)) & 1) {
140 bits |= JPF_JOY_DOWN;
142 if (((joydat >> 8) ^ (joydat >> 9)) & 1) {
143 bits |= JPF_JOY_UP;
146 return JP_TYPE_JOYSTK | bits;
150 ULONG llPortOpen(struct LowLevelBase *LowLevelBase, int port, UWORD *bits)
152 UWORD potbits, potres;
153 ULONG type = LowLevelBase->ll_PortType[port];
154 struct Library *PotgoBase = LowLevelBase->ll_PotgoBase;
155 volatile struct Custom *custom = (struct Custom*)0xdff000;
157 if (type == 0 || type == JP_TYPE_GAMECTLR || type == JP_TYPE_JOYSTK) {
158 if (port == 0)
159 potbits = POTGO_GAMEPAD_PORT0;
160 else
161 potbits = POTGO_GAMEPAD_PORT1;
162 potres = AllocPotBits(potbits);
163 if (potres != potbits) {
164 D(bug("%s: Can't allocate PotGo bits 0x%04x\n", __func__));
166 FreePotBits(potres);
167 type = JP_TYPE_NOTAVAIL;
168 PotgoBase = NULL;
169 } else {
170 /* Set Pin 5 as output, load mode */
171 UWORD pot;
172 pot = custom->potinp;
173 pot &= ~((port == 0) ? (3 << 8) : (3 << 12));
174 custom->potgo = pot | ((port == 0) ? (3 << 8) : (3 << 12));
176 } else {
177 /* No Potgo bits allocated */
178 potbits = 0;
181 /* Handle autosense */
182 if (type == 0) {
183 type = llPollGameCtrl(port);
184 if (type == 0)
185 type = JP_TYPE_JOYSTK;
186 LowLevelBase->ll_PortType[port] = type & JP_TYPE_MASK;
187 D(bug("%s: Autosense: 0x%08x\n", __func__, LowLevelBase->ll_PortType[port]));
190 *bits = potbits;
191 return type;
194 static VOID llPortClose(struct LowLevelBase *LowLevelBase, int port, UWORD potbits)
196 struct Library *PotgoBase = LowLevelBase->ll_PotgoBase;
198 if (potbits) {
199 FreePotBits(potbits);
204 AROS_LH1(ULONG, ReadJoyPort,
205 AROS_LHA(ULONG, port, D0),
206 struct LowLevelBase *, LowLevelBase, 5, LowLevel)
208 AROS_LIBFUNC_INIT
210 // D(bug("%s: Port %d\n", __func__, port));
212 if (port == 0 || port == 1) {
213 ULONG state, type;
214 UWORD potbits;
216 type = llPortOpen(LowLevelBase, port, &potbits);
217 switch (type) {
218 case JP_TYPE_GAMECTLR:
219 state = llPollGameCtrl(port);
220 break;
221 case JP_TYPE_JOYSTK:
222 state = llPollJoystick(port);
223 break;
224 default:
225 state = JP_TYPE_UNKNOWN;
226 break;
228 llPortClose(LowLevelBase, port, potbits);
230 return state;
233 return JP_TYPE_NOTAVAIL; // return failure until implemented
235 AROS_LIBFUNC_EXIT
236 } /* ReadJoyPort */