2 Copyright © 2013, The AROS Development Team. All rights reserved.
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)
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
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;
52 UBYTE cmask
= (port
== 0) ? (1 << 6) : (1 << 7);
54 /* Set Pin 5 as output, shift mode */
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 */
63 for (i
= 0; i
< 9; i
++) {
65 cia
->ciapra
&= ~cmask
;
67 bits
|= ((custom
->potinp
>> ((port
== 0) ? 10 : 14)) & 1) ? 0 : 1;
68 D(bug(" %d", bits
& 1));
72 cia
->ciapra
&= ~cmask
;
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 */
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) {
93 if (((joydat
>> 0) ^ (joydat
>> 1)) & 1) {
96 if (((joydat
>> 8) ^ (joydat
>> 9)) & 1) {
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)
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
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;
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) {
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
) {
159 potbits
= POTGO_GAMEPAD_PORT0
;
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__
));
167 type
= JP_TYPE_NOTAVAIL
;
170 /* Set Pin 5 as output, load mode */
172 pot
= custom
->potinp
;
173 pot
&= ~((port
== 0) ? (3 << 8) : (3 << 12));
174 custom
->potgo
= pot
| ((port
== 0) ? (3 << 8) : (3 << 12));
177 /* No Potgo bits allocated */
181 /* Handle autosense */
183 type
= llPollGameCtrl(port
);
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
]));
194 static VOID
llPortClose(struct LowLevelBase
*LowLevelBase
, int port
, UWORD potbits
)
196 struct Library
*PotgoBase
= LowLevelBase
->ll_PotgoBase
;
199 FreePotBits(potbits
);
204 AROS_LH1(ULONG
, ReadJoyPort
,
205 AROS_LHA(ULONG
, port
, D0
),
206 struct LowLevelBase
*, LowLevelBase
, 5, LowLevel
)
210 // D(bug("%s: Port %d\n", __func__, port));
212 if (port
== 0 || port
== 1) {
216 type
= llPortOpen(LowLevelBase
, port
, &potbits
);
218 case JP_TYPE_GAMECTLR
:
219 state
= llPollGameCtrl(port
);
222 state
= llPollJoystick(port
);
225 state
= JP_TYPE_UNKNOWN
;
228 llPortClose(LowLevelBase
, port
, potbits
);
233 return JP_TYPE_NOTAVAIL
; // return failure until implemented