Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1818 | Albom | 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ; |
||
3 | ; PSX-Pad for KolibriOS |
||
4 | ; Copyright (C) Jeffrey Amelynck 2008. All rights reserved. |
||
5 | ; |
||
6 | ; hidnplayr@kolibrios.org |
||
7 | ; |
||
8 | ; v0.1 |
||
9 | ; date: 4/09/2008 |
||
10 | ; type: private beta |
||
11 | ; functions implemented: Read raw data from Digital controller and Analog controller with red led. |
||
12 | ; |
||
13 | ; v0.2: |
||
14 | ; date: 5/09/2008 |
||
15 | ; type: public beta |
||
16 | ; functions implemented: Same as above plus converting keycodes from keypad do keyboard scancodes. |
||
17 | ; : To use this function you need a kernel wich can input scancodes using function 18,23. |
||
18 | ; ; I also did some cleanup and speedup |
||
19 | ; |
||
20 | ; |
||
21 | ; v0.2.1 |
||
22 | ; by O. Bogomaz aka Albom, albom85@yandex.ru |
||
23 | ; using of standart kernel function 72.1 |
||
24 | ; |
||
25 | ; |
||
26 | ; TODO: - Multiple controllers |
||
27 | ; - Analog controller(s) |
||
28 | ; |
||
29 | ; |
||
30 | ; More info about PSX/PS2 gamepad protocol: |
||
31 | ; http://curiousinventor.com/guides/ps2 |
||
32 | ; http://www.geocities.com/digitan000/Hardware/22/e22_page.html |
||
33 | ; |
||
34 | ; How to connect your PSX pad to the PC: |
||
35 | ; http://www.emulatronia.com/reportajes/directpad/psxeng/print.htm |
||
36 | ; |
||
37 | ; |
||
38 | ; PSX-Pad for KolibriOS is distributed in the hope that it will be useful, |
||
39 | ; but WITHOUT ANY WARRANTY. |
||
40 | ; No author or distributor accepts responsibility to anyone for the |
||
41 | ; consequences of using it or for whether it serves any particular purpose or |
||
42 | ; works at all, unless he says so in writing. Refer to the GNU General Public |
||
43 | ; License (the "GPL") for full details. |
||
44 | ; |
||
45 | ; Everyone is granted permission to copy, modify and redistribute KolibriOS, |
||
46 | ; but only under the conditions described in the GPL. A copy of this license |
||
47 | ; is supposed to have been given to you along with KolibriOS so you can know |
||
48 | ; your rights and responsibilities. It should be in a file named COPYING. |
||
49 | ; Among other things, the copyright notice and this notice must be preserved |
||
50 | ; on all copies. |
||
51 | ; |
||
52 | |||
53 | use32 |
||
54 | |||
55 | org 0x0 |
||
56 | |||
57 | db 'MENUET01' ; 8 byte id |
||
58 | dd 0x01 ; header version |
||
59 | dd START ; start of code |
||
60 | dd I_END ; size of image |
||
61 | dd 0x100000 ; memory for app |
||
62 | dd 0x100000 ; esp |
||
63 | dd 0x0 , 0x0 ; I_Param , I_Icon |
||
64 | |||
65 | ; Bits on Data Port (outputs for pc) |
||
66 | command equ 0 |
||
67 | attention equ 1 |
||
68 | clock equ 2 |
||
69 | vcc equ (1 shl 3 + 1 shl 4 + 1 shl 5 + 1 shl 6 + 1 shl 7) |
||
70 | |||
71 | ; Bits on Status Port (inputs for PC) |
||
72 | data equ 6 |
||
73 | ack equ 5 |
||
74 | |||
75 | __DEBUG__ equ 1 |
||
76 | __DEBUG_LEVEL__ equ 2 |
||
77 | |||
78 | include '../../macros.inc' |
||
79 | ;include 'fdo.inc' |
||
80 | |||
81 | START: |
||
82 | mov eax, 40 ; Disable notification of all events |
||
83 | xor ebx, ebx |
||
84 | int 0x40 |
||
85 | |||
86 | ; DEBUGF 2,"\nPSX-Pad for KolibriOS v0.2\n\n" |
||
87 | |||
88 | mov eax, 46 ; Ask the kernel if wse may use the LPT port |
||
89 | mov ebx, 0 |
||
90 | movzx ecx, [BASE] |
||
91 | movzx edx, [CONTROL] |
||
92 | int 0x40 |
||
93 | test eax, eax |
||
94 | jz @f |
||
95 | |||
96 | ; DEBUGF 2,"Could not reserve port!\n" |
||
97 | jmp exit |
||
98 | @@: |
||
99 | |||
100 | mov dx, [CONTROL] ; disable bi-directional data port |
||
101 | in al, dx |
||
102 | and al, 0xdf |
||
103 | out dx, al |
||
104 | |||
105 | mov eax, 18 ; read CPU-speed, we'll need it for 100us delay |
||
106 | mov ebx, 5 |
||
107 | int 0x40 ; now we've got the cpuspeed in hz, we need it in Mhz |
||
108 | xor edx, edx |
||
109 | mov ecx, 1000000 |
||
110 | div ecx |
||
111 | mov [CPUSPEED], eax |
||
112 | ; DEBUGF 2,"CPUspeed: %u\n",eax |
||
113 | |||
114 | ; DEBUGF 1,"Raising attention line\n" |
||
115 | call raise_att |
||
116 | |||
117 | ; DEBUGF 1,"Raising Clock\n" |
||
118 | call raise_clk |
||
119 | |||
120 | ; DEBUGF 1,"Powering Up controller\n" |
||
121 | call raise_vcc |
||
122 | |||
123 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
124 | ; |
||
125 | ; All things are ready to go, enter mainloop! |
||
126 | ; |
||
127 | ; This loop constantly poll's the PSX-pad for data |
||
128 | ; |
||
129 | |||
130 | mainloop: |
||
131 | |||
132 | mov eax, 5 ; Lets start by giving the other applications some cpu time, we'll take ours later. |
||
133 | mov ebx, 5 |
||
134 | int 0x40 |
||
135 | |||
136 | ; DEBUGF 1,"Lowering attention line\n" |
||
137 | call lower_att ; We've got the attention from the PSX-Pad now :) (yes, it's active low..) |
||
138 | |||
139 | ; DEBUGF 1,"Sending Startup byte.. " |
||
140 | mov ah, 0x01 ; Startup code |
||
141 | call tx_rx |
||
142 | call wait_for_ack |
||
143 | ; DEBUGF 1,"Rx: %x\n",bl |
||
144 | |||
145 | ; DEBUGF 1,"Request for data.. " |
||
146 | mov ah, 0x42 ; Request for data |
||
147 | call tx_rx |
||
148 | call wait_for_ack |
||
149 | ; DEBUGF 1,"Rx: %x\n",bl |
||
150 | |||
151 | cmp bl, 0x41 |
||
152 | je digital_controller |
||
153 | |||
154 | cmp bl, 0x73 |
||
155 | je analog_red_controller |
||
156 | |||
157 | ; cmp ah, 0x23 |
||
158 | ; je negcon_controller |
||
159 | |||
160 | ; cmp ah, 0x53 |
||
161 | ; je analog_green_controller |
||
162 | |||
163 | ; cmp ah, 0x12 |
||
164 | ; je psx_mouse |
||
165 | |||
166 | |||
167 | ; DEBUGF 2,"Unsupported controller/mode:%x !\n",bl |
||
168 | jmp exit |
||
169 | |||
170 | |||
171 | |||
172 | |||
173 | digital_controller: |
||
174 | call command_idle |
||
175 | call wait_for_ack |
||
176 | ; Right now, we receive 0x5a from the controller, wich means: sending data! |
||
177 | ; DEBUGF 1,"Receiving data.. " |
||
178 | |||
179 | call command_idle |
||
180 | call wait_for_ack |
||
181 | mov byte [digital+1], bl |
||
182 | |||
183 | call command_idle |
||
184 | mov byte [digital+0], bl |
||
185 | |||
186 | ; DEBUGF 1,"Digital data: %x\n",[digital]:4 |
||
187 | |||
188 | mov ax, word [digital_] |
||
189 | xor ax, word [digital] |
||
190 | mov cx, word [digital] |
||
191 | |||
192 | bt ax, 6 ; X |
||
193 | jnc @f |
||
194 | pusha |
||
195 | and cx, 1 shl 6 |
||
196 | shl cx, 1 |
||
197 | add cl, 29 |
||
198 | call sendkey |
||
199 | popa |
||
200 | @@: |
||
201 | |||
202 | bt ax, 5 ; O |
||
203 | jnc @f |
||
204 | pusha |
||
205 | mov cx, word [digital] |
||
206 | and cx, 1 shl 5 |
||
207 | shl cx, 2 |
||
208 | add cl, 56 |
||
209 | call sendkey |
||
210 | popa |
||
211 | @@: |
||
212 | |||
213 | bt ax, 11 ; Start |
||
214 | jnc @f |
||
215 | pusha |
||
216 | mov cx, word [digital] |
||
217 | and cx, 1 shl 11 |
||
218 | shr cx, 4 |
||
219 | add cl, 28 |
||
220 | call sendkey |
||
221 | popa |
||
222 | @@: |
||
223 | |||
224 | bt ax, 8 ; Select |
||
225 | jnc @f |
||
226 | pusha |
||
227 | mov cx, word [digital] |
||
228 | and cx, 1 shl 8 |
||
229 | shr cx, 1 |
||
230 | add cl, 14 |
||
231 | call sendkey |
||
232 | popa |
||
233 | @@: |
||
234 | |||
235 | bt ax, 12 ; up |
||
236 | jnc @f |
||
237 | pusha |
||
238 | mov cl, 224 |
||
239 | call sendkey |
||
240 | mov cx, word [digital] |
||
241 | and cx, 1 shl 12 |
||
242 | shr cx, 5 |
||
243 | add cl, 72 |
||
244 | call sendkey |
||
245 | popa |
||
246 | @@: |
||
247 | |||
248 | bt ax, 13 ; right |
||
249 | jnc @f |
||
250 | pusha |
||
251 | mov cl, 224 |
||
252 | call sendkey |
||
253 | mov cx, word [digital] |
||
254 | and cx, 1 shl 13 |
||
255 | shr cx, 6 |
||
256 | add cl, 77 |
||
257 | call sendkey |
||
258 | popa |
||
259 | @@: |
||
260 | |||
261 | bt ax, 14 ; down |
||
262 | jnc @f |
||
263 | pusha |
||
264 | mov cl, 224 |
||
265 | call sendkey |
||
266 | mov cx, word [digital] |
||
267 | and cx, 1 shl 14 |
||
268 | shr cx, 7 |
||
269 | add cl, 80 |
||
270 | call sendkey |
||
271 | popa |
||
272 | @@: |
||
273 | |||
274 | bt ax, 15 ; left |
||
275 | jnc @f |
||
276 | pusha |
||
277 | mov cl, 224 ; extended key |
||
278 | call sendkey |
||
279 | mov cx, word [digital] |
||
280 | and cx, 1 shl 15 |
||
281 | shr cx, 8 |
||
282 | add cl, 75 ; left |
||
283 | call sendkey |
||
284 | popa |
||
285 | @@: |
||
286 | |||
287 | mov ax, word [digital] |
||
288 | mov word [digital_],ax |
||
289 | |||
290 | call raise_att |
||
291 | jmp mainloop |
||
292 | |||
293 | |||
294 | analog_red_controller: |
||
295 | call command_idle |
||
296 | call wait_for_ack |
||
297 | ; Right now, we receive 0x5a from the controller, wich means: sending data! |
||
298 | ; DEBUGF 1,"Receiving data.. " |
||
299 | |||
300 | call command_idle |
||
301 | call wait_for_ack |
||
302 | mov byte [analog_red+5], bl |
||
303 | |||
304 | call command_idle |
||
305 | call wait_for_ack |
||
306 | mov byte [analog_red+4], bl |
||
307 | |||
308 | call command_idle |
||
309 | call wait_for_ack |
||
310 | mov byte [analog_red+3], bl |
||
311 | |||
312 | call command_idle |
||
313 | call wait_for_ack |
||
314 | mov byte [analog_red+2], bl |
||
315 | |||
316 | call command_idle |
||
317 | call wait_for_ack |
||
318 | mov byte [analog_red+1], bl |
||
319 | |||
320 | call command_idle |
||
321 | mov byte [analog_red+0], bl |
||
322 | |||
323 | |||
324 | ; DEBUGF 2,"Analog data: %x%x\n",[analog_red]:8,[analog_red+4]:4 |
||
325 | call raise_att |
||
326 | jmp mainloop |
||
327 | |||
328 | |||
329 | |||
330 | |||
331 | exit: |
||
332 | mov eax, -1 |
||
333 | int 0x40 |
||
334 | |||
335 | |||
336 | |||
337 | sendkey: ; This function inserts Keyboard Scan-codes into the kernel's queue |
||
338 | ; Scancode is in cl |
||
339 | ; mov eax, 18 |
||
340 | ; mov ebx, 23 |
||
341 | ; int 0x40 |
||
342 | |||
343 | pushad |
||
344 | |||
345 | mov eax, 72 ; <-- standart function (by Albom) |
||
346 | mov ebx, 1 |
||
347 | mov edx, ecx |
||
348 | and edx, 0xff |
||
349 | mov ecx, 2 |
||
350 | int 0x40 |
||
351 | |||
352 | popad |
||
353 | ret |
||
354 | |||
355 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
356 | ; |
||
357 | ; Low-level code starts here |
||
358 | ; |
||
359 | |||
360 | |||
361 | raise_att: |
||
362 | mov al, [PORT_DATA] |
||
363 | bts ax, attention |
||
364 | mov [PORT_DATA], al |
||
365 | |||
366 | mov dx, [BASE] |
||
367 | out dx, al |
||
368 | |||
369 | ret |
||
370 | |||
371 | lower_att: |
||
372 | mov al, [PORT_DATA] |
||
373 | btr ax, attention |
||
374 | mov [PORT_DATA], al |
||
375 | |||
376 | mov dx, [BASE] |
||
377 | out dx, al |
||
378 | |||
379 | ret |
||
380 | |||
381 | |||
382 | |||
383 | |||
384 | raise_clk: |
||
385 | mov al, [PORT_DATA] |
||
386 | bts ax, clock |
||
387 | mov [PORT_DATA], al |
||
388 | |||
389 | mov dx, [BASE] |
||
390 | out dx, al |
||
391 | |||
392 | ret |
||
393 | |||
394 | lower_clk: |
||
395 | mov al, [PORT_DATA] |
||
396 | btr ax, clock |
||
397 | mov [PORT_DATA], al |
||
398 | |||
399 | mov dx, [BASE] |
||
400 | out dx, al |
||
401 | |||
402 | ret |
||
403 | |||
404 | |||
405 | |||
406 | |||
407 | raise_vcc: |
||
408 | mov al, [PORT_DATA] |
||
409 | or al, vcc |
||
410 | mov [PORT_DATA], al |
||
411 | |||
412 | mov dx, [BASE] |
||
413 | out dx, al |
||
414 | |||
415 | ret |
||
416 | |||
417 | lower_vcc: |
||
418 | mov al, [PORT_DATA] |
||
419 | and al, 0xff - vcc |
||
420 | mov [PORT_DATA], al |
||
421 | |||
422 | mov dx, [BASE] |
||
423 | out dx, al |
||
424 | |||
425 | ret |
||
426 | |||
427 | |||
428 | |||
429 | |||
430 | wait_for_ack: |
||
431 | mov dx, [STATUS] |
||
432 | mov ecx, 10000 |
||
433 | .loop: |
||
434 | in al, dx |
||
435 | bt ax, ack |
||
436 | jnc .ack |
||
437 | loop .loop |
||
438 | |||
439 | ; DEBUGF 2,"ACK timeout!\n" |
||
440 | |||
441 | ; pop eax ; balance the stack, we're not doing a ret like we should.. |
||
442 | ; jmp mainloop |
||
443 | |||
444 | .ack: |
||
445 | ; DEBUGF 1,"ACK !\n" |
||
446 | |||
447 | ret |
||
448 | |||
449 | |||
450 | |||
451 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
452 | ; This code comes from Serge's audio driver. |
||
453 | ; If you know a better way to do 100 us wait, please tell me. |
||
454 | ; This RDTSC stuff is know to have a bug in the newer AMD processors. |
||
455 | delay: |
||
456 | |||
457 | push ecx |
||
458 | push edx |
||
459 | push ebx |
||
460 | push eax |
||
461 | |||
462 | mov eax, 100 |
||
463 | mov ecx, [CPUSPEED] |
||
464 | mul ecx |
||
465 | mov ebx, eax ;low |
||
466 | mov ecx, edx ;high |
||
467 | rdtsc |
||
468 | add ebx, eax |
||
469 | adc ecx,edx |
||
470 | @@: |
||
471 | rdtsc |
||
472 | sub eax, ebx |
||
473 | sbb edx, ecx |
||
474 | js @B |
||
475 | |||
476 | pop eax |
||
477 | pop ebx |
||
478 | pop edx |
||
479 | pop ecx |
||
480 | |||
481 | ret |
||
482 | |||
483 | |||
484 | |||
485 | |||
486 | |||
487 | |||
488 | |||
489 | tx_rx: |
||
490 | ; ah = byte to send |
||
491 | ; bl = received byte |
||
492 | mov ecx, 8 |
||
493 | mov bl, 0 |
||
494 | |||
495 | tx_rx_loop: |
||
496 | call delay |
||
497 | call lower_clk |
||
498 | |||
499 | mov dl, ah |
||
500 | and dl, 1 |
||
501 | ; DEBUGF 1,"OUTb:%u ", dl |
||
502 | |||
503 | mov al, [PORT_DATA] |
||
504 | and al, 0xfe |
||
505 | or al, dl |
||
506 | mov [PORT_DATA], al |
||
507 | |||
508 | mov dx, [BASE] |
||
509 | out dx, al |
||
510 | |||
511 | shr ah, 1 |
||
512 | |||
513 | call delay |
||
514 | call raise_clk |
||
515 | |||
516 | mov dx, [STATUS] |
||
517 | in al, dx |
||
518 | |||
519 | shl al, 1 |
||
520 | and al, 1 shl 7 |
||
521 | ; DEBUGF 1,"INb:%x\n", al |
||
522 | shr bl, 1 |
||
523 | or bl, al |
||
524 | |||
525 | loop tx_rx_loop |
||
526 | |||
527 | ret |
||
528 | |||
529 | |||
530 | |||
531 | command_idle: |
||
532 | ; bl = received byte |
||
533 | mov bl, 0 |
||
534 | mov ecx, 8 |
||
535 | |||
536 | command_idle_loop: |
||
537 | call delay |
||
538 | call lower_clk |
||
539 | |||
540 | call delay |
||
541 | call raise_clk |
||
542 | |||
543 | mov dx, [STATUS] |
||
544 | in al, dx |
||
545 | |||
546 | shl al, 1 |
||
547 | and al, 1 shl 7 |
||
548 | |||
549 | shr bl, 1 |
||
550 | or bl, al |
||
551 | |||
552 | loop command_idle_loop |
||
553 | |||
554 | ret |
||
555 | |||
556 | |||
557 | ; DATA AREA |
||
558 | |||
559 | ;include_debug_strings ; ALWAYS present in data section |
||
560 | |||
561 | ; Addresses to PORT |
||
562 | BASE dw 0x378 |
||
563 | STATUS dw 0x379 |
||
564 | CONTROL dw 0x37a |
||
565 | ; Buffer for data port |
||
566 | PORT_DATA db 0 |
||
567 | |||
568 | ; hmm, what would this be... |
||
569 | CPUSPEED dd ? |
||
570 | |||
571 | ; buffers for data from controller |
||
572 | digital rb 2 |
||
573 | digital_ rb 2 ; this buffer is used to find keychanges (if somebody just pressed/released a key) |
||
574 | analog_red rb 6 |
||
575 | analog_red_ rb 6 |
||
576 | |||
577 | I_END:--> |