2 Copyright 2009, Ifcaro, Volca
3 Licenced under Academic Free License version 3.0
4 Review OpenUsbLd README & LICENSE files for further details.
7 #include "include/usbld.h"
8 #include "include/pad.h"
9 #include "include/ioman.h"
16 // Cpu ticks per one milisecond
17 #define CLOCKS_PER_MILISEC 147456
20 #define DEFAULT_PAD_DELAY 200
26 struct padButtonStatus buttons
;
28 // pad_dma_buf is provided by the user, one buf for each pad
29 // contains the pad's current state
30 char padBuf
[256] __attribute__((aligned(64)));
36 /// current time in miliseconds (last update time)
37 static u32 curtime
= 0;
38 static u32 time_since_last
= 0;
40 static unsigned short pad_count
;
41 static struct pad_data_t pad_data
[MAX_PADS
];
45 static u32 oldpaddata
;
47 static int delaycnt
[16];
48 static int paddelay
[16];
50 // KEY_ to PAD_ conversion table
51 static const int keyToPad
[17] = {
74 static int waitPadReady(struct pad_data_t
* pad
) {
77 // busy wait for the pad to get ready
79 state
= padGetState(pad
->port
, pad
->slot
);
80 } while((state
!= PAD_STATE_STABLE
) && (state
!= PAD_STATE_FINDCTP1
) && (state
!= PAD_STATE_DISCONN
));
85 static int initializePad(struct pad_data_t
* pad
) {
90 // is there any device connected to that port?
91 if (waitPadReady(pad
) == PAD_STATE_DISCONN
) {
92 return 1; // nope, don't waste your time here!
95 // How many different modes can this device operate in?
96 // i.e. get # entrys in the modetable
97 modes
= padInfoMode(pad
->port
, pad
->slot
, PAD_MODETABLE
, -1);
98 LOG("PAD The device has %d modes: ", modes
);
103 for (i
= 0; i
< modes
; i
++) {
104 tmp
= padInfoMode(pad
->port
, pad
->slot
, PAD_MODETABLE
, i
);
111 tmp
= padInfoMode(pad
->port
, pad
->slot
, PAD_MODECURID
, 0);
112 LOG("PAD It is currently using mode %d\n", tmp
);
114 // If modes == 0, this is not a Dual shock controller
115 // (it has no actuator engines)
117 LOG("PAD This is a digital controller?\n");
121 // Verify that the controller has a DUAL SHOCK mode
124 if (padInfoMode(pad
->port
, pad
->slot
, PAD_MODETABLE
, i
) == PAD_TYPE_DUALSHOCK
)
130 LOG("PAD This is no Dual Shock controller\n");
134 // If ExId != 0x0 => This controller has actuator engines
135 // This check should always pass if the Dual Shock test above passed
136 tmp
= padInfoMode(pad
->port
, pad
->slot
, PAD_MODECUREXID
, 0);
138 LOG("PAD This is no Dual Shock controller??\n");
142 LOG("PAD Enabling dual shock functions\n");
144 // When using MMODE_LOCK, user cant change mode with Select button
145 padSetMainMode(pad
->port
, pad
->slot
, PAD_MMODE_DUALSHOCK
, PAD_MMODE_LOCK
);
148 tmp
= padInfoPressMode(pad
->port
, pad
->slot
);
149 LOG("PAD infoPressMode: %d\n", tmp
);
152 tmp
= padEnterPressMode(pad
->port
, pad
->slot
);
153 LOG("PAD enterPressMode: %d\n", tmp
);
156 pad
->actuators
= padInfoAct(pad
->port
, pad
->slot
, -1, 0);
157 LOG("PAD # of actuators: %d\n", pad
->actuators
);
159 if (pad
->actuators
!= 0) {
160 pad
->actAlign
[0] = 0; // Enable small engine
161 pad
->actAlign
[1] = 1; // Enable big engine
162 pad
->actAlign
[2] = 0xff;
163 pad
->actAlign
[3] = 0xff;
164 pad
->actAlign
[4] = 0xff;
165 pad
->actAlign
[5] = 0xff;
168 tmp
= padSetActAlign(pad
->port
, pad
->slot
, pad
->actAlign
);
169 LOG("PAD padSetActAlign: %d\n", tmp
);
171 LOG("PAD Did not find any actuators.\n");
179 static int readPad(struct pad_data_t
* pad
)
183 int ret
= padRead(pad
->port
, pad
->slot
, &pad
->buttons
); // port, slot, buttons
187 u32 newpdata
= 0xffff ^ pad
->buttons
.btns
;
189 if (newpdata
!= 0x0) // something
194 pad
->oldpaddata
= pad
->paddata
;
195 pad
->paddata
= newpdata
;
197 // merge into the global vars
198 paddata
|= pad
->paddata
;
204 /** Returns delay (in miliseconds) specified for the given key.
205 * @param id The button id
206 * @param repeat Boolean value specifying if we want initial key delay (0) or the repeat key delay (1)
207 * @return the delay to the next key event
209 static int getKeyDelay(int id
, int repeat
) {
210 int delay
= paddelay
[id
- 1];
212 // if not in repeat, the delay is enlarged
219 /** polling method. Call every frame. */
222 oldpaddata
= paddata
;
226 u32 newtime
= cpu_ticks() / CLOCKS_PER_MILISEC
;
227 time_since_last
= newtime
- curtime
;
232 for (i
= 0; i
< pad_count
; ++i
) {
233 rslt
|= readPad(&pad_data
[i
]);
236 for (i
= 0; i
< 16; ++i
) {
237 if (getKeyPressed(i
+ 1))
238 delaycnt
[i
] -= time_since_last
;
240 delaycnt
[i
] = getKeyDelay(i
+ 1, 0);
246 /** Key getter with key repeats.
247 * @param id The button ID
248 * @return nonzero if button is being pressed just now
251 if ( (id
<= 0) || (id
>= 17) )
256 // either the button was not pressed this frame, then reset counter and return
257 // or it was, then handle the repetition
259 delaycnt
[kid
] = getKeyDelay(id
, 0);
263 if(!getKeyPressed(id
))
266 if(delaycnt
[kid
] <= 0) {
267 delaycnt
[kid
] = getKeyDelay(id
, 1);
274 /** Detects key-on event. Returns true if the button was not pressed the last frame but is pressed this frame.
275 * @param id The button ID
276 * @return nonzero if button is being pressed just now
278 int getKeyOn(int id
) {
279 if ( (id
<=0) || (id
>=17) )
282 // old v.s. new pad data
283 int keyid
= keyToPad
[id
];
285 return (paddata
& keyid
) && (!(oldpaddata
& keyid
));
288 /** Detects key-off event. Returns true if the button was pressed the last frame but is not pressed this frame.
289 * @param id The button ID
290 * @return nonzero if button is being released
292 int getKeyOff(int id
) {
293 if ( (id
<=0) || (id
>=17) )
296 // old v.s. new pad data
297 int keyid
= keyToPad
[id
];
299 return (!(paddata
& keyid
)) && (oldpaddata
& keyid
);
302 /** Returns true (nonzero) if the button is currently pressed
303 * @param id The button ID
304 * @return nonzero if button is being held
306 int getKeyPressed(int id
) {
307 // old v.s. new pad data
308 int keyid
= keyToPad
[id
];
310 return (paddata
& keyid
);
313 /** Sets the delay to wait for button repetition event to occur.
314 * @param button The button ID
315 * @param btndelay The button delay (in query count)
317 void setButtonDelay(int button
, int btndelay
) {
318 if ( (button
<=0) || (button
>=17) )
321 paddelay
[button
-1] = btndelay
;
324 int getButtonDelay(int button
) {
325 if ( (button
<=0) || (button
>=17) )
328 return paddelay
[button
-1];
331 /** Unloads a single pad.
333 static void unloadPad(struct pad_data_t
* pad
) {
334 padPortClose(pad
->port
, pad
->slot
);
337 /** Unloads all pads. Use to terminate the usage of the pads. */
341 for (i
= 0; i
< pad_count
; ++i
)
342 unloadPad(&pad_data
[i
]);
347 /** Tries to start a single pad.
348 * @param pad The pad data holding structure
349 * @return 0 Error, != 0 Ok */
350 static int startPad(struct pad_data_t
* pad
) {
351 if(padPortOpen(pad
->port
, pad
->slot
, pad
->padBuf
) == 0) {
355 if(!initializePad(pad
)) {
364 * @return Count of dual shock compatible pads. 0 if none present. */
366 // scan for pads that exist... at least one has to be present
369 int maxports
= padGetPortMax();
371 int port
; // 0 -> Connector 1, 1 -> Connector 2
372 int slot
; // Always zero if not using multitap
374 for (port
= 0; port
< maxports
; ++port
) {
375 int maxslots
= padGetSlotMax(port
);
377 for (slot
= 0; slot
< maxslots
; ++slot
) {
379 struct pad_data_t
* cpad
= &pad_data
[pad_count
];
388 if (pad_count
>= MAX_PADS
)
389 break; // enough already!
393 for(n
=0; n
<16; ++n
) {
394 delaycnt
[n
]=DEFAULT_PAD_DELAY
;
395 paddelay
[n
]=DEFAULT_PAD_DELAY
;
401 void padStoreSettings(int* buffer
) {
404 for (i
= 0; i
< 16; i
++)
405 buffer
[i
] = paddelay
[i
];
409 void padRestoreSettings(int* buffer
) {
412 for (i
= 0; i
< 16; i
++)
413 paddelay
[i
] = buffer
[i
];