3a34bb7465d53d2c870355f2880484abdba97813
[AROS.git] / arch / m68k-amiga / lowlevel / readjoyport.c
blob3a34bb7465d53d2c870355f2880484abdba97813
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 #define POTGO_GAMEPAD_PORT0 \
25 (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8)
26 #define POTGO_GAMEPAD_PORT1 \
27 (1 << 15) | (1 << 14) | (1 << 13) | (1 << 12)
30 * ciaapra - (1 << 7) is /FIR1 (port 1, pin 6)
31 * ciaapra - (1 << 6) is /FIR0 (port 0, pin 6)
32 * ciaaddra - 0x03
33 * JOYnDAT:
34 * pin 1 (up) = ((JOYnDAT >> 0) ^ (JOYnDAT >> 1)) & 1
35 * pin 2 (dn) = ((JOYnDAT >> 8) ^ (JOYnDAT >> 9)) & 1
36 * pin 3 (lt) = (JOYnDAT >> 9) & 1
37 * pin 4 (rt) = (JOYnDAT >> 1) & 1
38 * POTGO/POTINP:
39 * port 0: pin 9 (1 << 10), pin 5 (1 << 8)
40 * port 1: pin 9 (1 << 14), pin 5 (1 << 12)
42 static inline ULONG llPollGameCtrl(int port)
44 volatile struct Custom *custom = (struct Custom*)0xdff000;
45 volatile struct CIA *cia = (struct CIA *)0xbfe001;
46 UWORD pot;
47 ULONG bits = 0;
48 UWORD joydat;
49 int i;
50 UBYTE cmask = (port == 0) ? (1 << 6) : (1 << 7);
52 /* Set Pin 5 as output, shift mode */
53 pot = custom->potinp;
54 pot &= ~((port == 0) ? (3 << 8) : (3 << 12));
55 custom->potgo = pot | (port == 0) ? (2 << 8) : (2 << 12);
56 cia->ciapra &= ~cmask;
57 cia->ciaddra |= cmask;
59 /* Shift in the button values */
60 D(bug("Sin: \n"));
61 for (i = 0; i < 9; i++) {
62 cia->ciapra |= cmask;
63 cia->ciapra &= ~cmask;
64 bits <<= 1;
65 bits |= ((custom->potinp >> ((port == 0) ? 10 : 14)) & 1) ? 0 : 1;
66 D(bug(" %d", bits & 1));
68 D(bug("\n"));
70 cia->ciapra &= ~cmask;
71 custom->potgo = pot;
73 if ((bits & 3) != 2) {
74 /* Stuck bits? Probably not a game controller */
75 D(bug("%s: Stuck bits? (0x%04x)\n", __func__, bits));
76 /* Revert to autosense */
77 return 0;
79 bits &= ~3;
80 bits <<= 15;
82 /* Get the joypad bits */
83 joydat = (port == 0) ? custom->joy0dat : custom->joy1dat;
85 if ((joydat >> 1) & 1) {
86 bits |= JPF_JOY_RIGHT;
88 if ((joydat >> 9) & 1) {
89 bits |= JPF_JOY_LEFT;
91 if (((joydat >> 0) ^ (joydat >> 1)) & 1) {
92 bits |= JPF_JOY_DOWN;
94 if (((joydat >> 8) ^ (joydat >> 9)) & 1) {
95 bits |= JPF_JOY_UP;
98 return JP_TYPE_GAMECTLR | bits;
102 * ciaapra - (1 << 7) is /FIR1 (port 2, pin 6)
103 * ciaapra - (1 << 6) is /FIR0 (port 1, pin 6)
104 * ciaaddra - 0x03
105 * JOYnDAT:
106 * pin 1 (up) = ((JOYnDAT >> 0) ^ (JOYnDAT >> 1)) & 1
107 * pin 2 (dn) = ((JOYnDAT >> 8) ^ (JOYnDAT >> 9)) & 1
108 * pin 3 (lt) = (JOYnDAT >> 9) & 1
109 * pin 4 (rt) = (JOYnDAT >> 1) & 1
110 * POTGO/POTINP:
111 * port 1: pin 9 (1 << 10), pin 5 (1 << 8)
112 * port 2: pin 9 (1 << 14), pin 5 (1 << 12)
114 static inline ULONG llPollJoystick(int port)
116 volatile struct Custom *custom = (struct Custom*)0xdff000;
117 volatile struct CIA *cia = (struct CIA *)0xbfe001;
118 ULONG bits = 0;
119 UWORD joydat;
120 UBYTE cmask = (port == 0) ? (1 << 6) : (1 << 7);
122 /* 'red' - /FIRn on CIA Port A */
123 bits |= (cia->ciapra & cmask) ? 0 : JPF_BUTTON_RED;
125 /* 'blue' - Pin 9 on POTINP */
126 bits |= ((custom->potinp >> ((port == 0) ? 10 : 14)) & 1) ? 0 : JPF_BUTTON_BLUE;
128 /* Get the joypad bits */
129 joydat = (port == 0) ? custom->joy0dat : custom->joy1dat;
131 if ((joydat >> 1) & 1) {
132 bits |= JPF_JOY_RIGHT;
134 if ((joydat >> 9) & 1) {
135 bits |= JPF_JOY_LEFT;
137 if (((joydat >> 0) ^ (joydat >> 1)) & 1) {
138 bits |= JPF_JOY_DOWN;
140 if (((joydat >> 8) ^ (joydat >> 9)) & 1) {
141 bits |= JPF_JOY_UP;
144 return JP_TYPE_JOYSTK | bits;
148 ULONG llPortOpen(struct LowLevelBase *LowLevelBase, int port, UWORD *bits)
150 UWORD potbits, potres;
151 ULONG type = LowLevelBase->ll_PortType[port];
152 struct Library *PotgoBase = LowLevelBase->ll_PotgoBase;
153 volatile struct Custom *custom = (struct Custom*)0xdff000;
155 if (type == 0 || type == JP_TYPE_GAMECTLR || type == JP_TYPE_JOYSTK) {
156 if (port == 0)
157 potbits = POTGO_GAMEPAD_PORT0;
158 else
159 potbits = POTGO_GAMEPAD_PORT1;
160 potres = AllocPotBits(potbits);
161 if (potres != potbits) {
162 D(bug("%s: Can't allocate PotGo bits 0x%04x\n", __func__));
164 FreePotBits(potres);
165 type = JP_TYPE_NOTAVAIL;
166 PotgoBase = NULL;
167 } else {
168 /* Set Pin 5 as output, load mode */
169 UWORD pot;
170 pot = custom->potinp;
171 pot &= ~((port == 0) ? (3 << 8) : (3 << 12));
172 custom->potgo = pot | ((port == 0) ? (3 << 8) : (3 << 12));
174 } else {
175 /* No Potgo bits allocated */
176 potbits = 0;
179 /* Handle autosense */
180 if (type == 0) {
181 type = llPollGameCtrl(port);
182 if (type == 0)
183 type = JP_TYPE_JOYSTK;
184 LowLevelBase->ll_PortType[port] = type & JP_TYPE_MASK;
185 D(bug("%s: Autosense: 0x%08x\n", __func__, LowLevelBase->ll_PortType[port]));
188 *bits = potbits;
189 return type;
192 static VOID llPortClose(struct LowLevelBase *LowLevelBase, int port, UWORD potbits)
194 struct Library *PotgoBase = LowLevelBase->ll_PotgoBase;
196 if (potbits) {
197 FreePotBits(potbits);
201 /*****************************************************************************
203 NAME */
205 AROS_LH1(ULONG, ReadJoyPort,
207 /* SYNOPSIS */
208 AROS_LHA(ULONG, port, D0),
210 /* LOCATION */
211 struct LowLevelBase *, LowLevelBase, 5, LowLevel)
213 /* FUNCTION
215 INPUTS
217 RESULT
219 BUGS
221 INTERNALS
223 *****************************************************************************/
225 AROS_LIBFUNC_INIT
227 // D(bug("%s: Port %d\n", __func__, port));
229 if (port == 0 || port == 1) {
230 ULONG state, type;
231 UWORD potbits;
233 type = llPortOpen(LowLevelBase, port, &potbits);
234 switch (type) {
235 case JP_TYPE_GAMECTLR:
236 state = llPollGameCtrl(port);
237 break;
238 case JP_TYPE_JOYSTK:
239 state = llPollJoystick(port);
240 break;
241 default:
242 state = JP_TYPE_UNKNOWN;
243 break;
245 llPortClose(LowLevelBase, port, potbits);
247 return state;
250 return JP_TYPE_NOTAVAIL; // return failure until implemented
252 AROS_LIBFUNC_EXIT
253 } /* ReadJoyPort */