diff options
| author | Lameguy64 <lameguy64@gmail.com> | 2021-10-25 10:51:50 +0800 |
|---|---|---|
| committer | Lameguy64 <lameguy64@gmail.com> | 2021-10-25 10:51:50 +0800 |
| commit | 538f28cfbbbb8163ab8a96de77d6887123856c81 (patch) | |
| tree | a3108f05c038d0f43f2e96ae4d2d34ce4da225b4 /indev/psxpad | |
| parent | 7718b576b7aba725455ce510ee9632067a65f0d7 (diff) | |
| download | psn00bsdk-538f28cfbbbb8163ab8a96de77d6887123856c81.tar.gz | |
Added indev directory
Diffstat (limited to 'indev/psxpad')
| -rw-r--r-- | indev/psxpad/card.s | 377 | ||||
| -rw-r--r-- | indev/psxpad/main.c | 399 | ||||
| -rw-r--r-- | indev/psxpad/makefile | 39 | ||||
| -rw-r--r-- | indev/psxpad/pad.s | 264 |
4 files changed, 1079 insertions, 0 deletions
diff --git a/indev/psxpad/card.s b/indev/psxpad/card.s new file mode 100644 index 0000000..2732194 --- /dev/null +++ b/indev/psxpad/card.s @@ -0,0 +1,377 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + +_CardCSum: + + # a0 - base csum + # a1 - data pointer + # a2 - length + + lbu $v0, 0($a1) + addi $a2, -1 + xor $a0, $v0 + bgtz $a2, _CardCSum + addiu $a1, 1 + + jr $ra + move $v0, $a0 + + +.global _CardWrite +.type _CardWrite, @function +_CardWrite: + + # a0 - port number + # a1 - pointer to 128 byte buffer + # a2 - sector number + + # return values: + # 0 - ok + # 1 - no device + # 2 - timeout + # 3 - bad checksum + # 4 - bad sector + + # note: you must wait at least two vsyncs between each sector write + + addiu $sp, -4 + sw $ra, 0($sp) + + lui $t0, IOBASE + + li $v0, 0x1003 # TX Enable, Joypad port select + andi $a0, 1 + sll $a0, 13 + or $v0, $a0 # Select port 2 if a0 is 1 + + sh $v0, JOY_CTRL($t0) # Set to Joypad control interface + + jal _wait # Delay for analog pads + li $v0, 310 # (needs optimization testing) + +# May cause issues with third party adapters such as Brook wireless +#.Lread_empty_fifo_write: # Flush the RX FIFO just in case +# lbu $v1, JOY_TXRX($t0) +# lhu $v0, JOY_STAT($t0) +# nop +# andi $v0, 0x2 +# bnez $v0, .Lread_empty_fifo_write +# nop + + lhu $v1, JOY_CTRL($t0) + nop + or $v1, 0x10 + sh $v1, JOY_CTRL($t0) + + jal _CardExchng # Send device check byte + li $a0, 0x81 + andi $v1, $v0, 0x100 # No card if exchange timed out + bnez $v1, .Lno_device_write + addiu $v0, $0 , 1 + + jal _wait # 1st exchange needs 27microsec after ACK + li $v0, 190 # (e.g. 7 as usual + an extra 20) + + jal _CardExchng # Send write command + li $a0, 0x57 + andi $v1, $v0, 0x100 # No card if exchange timed out + bnez $v1, .Lno_device_write + addiu $v0, $0 , 1 + + jal _CardExchng # Receive card ID bytes + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lwrite_timeout + addiu $v0, $0 , 2 + jal _CardExchng + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lwrite_timeout + addiu $v0, $0 , 2 + + jal _CardExchng # Send address bytes + srl $a0, $a2, 8 + andi $v1, $v0, 0x100 + bnez $v1, .Lwrite_timeout + addiu $v0, $0 , 2 + jal _CardExchng + andi $a0, $a2, 0xFF + andi $v1, $v0, 0x100 + bnez $v1, .Lwrite_timeout + addiu $v0, $0 , 2 + + srl $t1, $a2, 8 # Checksum address by MSB xor LSB + andi $v0, $a2, 0xFF + xor $t1, $v0 + + move $a2, $0 # Send data and compute checksum +.Lwrite_loop: + lbu $a0, 0($a1) + addiu $a1, 1 + jal _CardExchng + xor $t1, $a0 + addiu $a2, 1 + blt $a2, 128, .Lwrite_loop + nop + + jal _CardExchng # Send checksum byte + move $a0, $t1 + andi $v1, $v0, 0x100 + bnez $v1, .Lwrite_timeout + addiu $v0, $0 , 2 + + jal _CardExchng # Receive card acknowledge bytes + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lwrite_timeout + addiu $v0, $0 , 2 + jal _CardExchng + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lwrite_timeout + addiu $v0, $0 , 2 + + sb $0 , JOY_TXRX($t0) # Gets end byte + nop +.Lsend_wait_end_write: + lhu $v0, JOY_STAT($t0) + nop + andi $v0, 0x6 + bne $v0, 0x6, .Lsend_wait_end_write + nop + lbu $v0, JOY_TXRX($t0) + nop + + beq $v0, 0x4e, .Lwrite_timeout # Bad checksum + addiu $v0, $0 , 3 + beq $v0, 0xff, .Lwrite_timeout # Bad sector + addiu $v0, $0 , 4 + + move $v0, $0 + +.Lwrite_timeout: +.Lno_device_write: + + sh $0 , JOY_CTRL($t0) # Apparently required + + lw $ra, 0($sp) + addiu $sp, 4 + jr $ra + nop + + +.global _CardRead +.type _CardRead, @function +_CardRead: + + # a0 - port number + # a1 - pointer to 128 byte buffer + # a2 - sector number + + addiu $sp, -12 + sw $ra, 0($sp) + sw $a1, 4($sp) + sw $a2, 8($sp) + + lui $t0, IOBASE + + li $v0, 0x1003 # TX Enable, Joypad port select + andi $a0, 1 + sll $a0, 13 + or $v0, $a0 # Select port 2 if a0 is 1 + + sh $v0, JOY_CTRL($t0) # Set to Joypad control interface + + jal _wait # Delay for analog pads (needs testing) + li $v0, 310 + +# May cause issues with third party adapters such as Brook wireless +#.Lread_empty_fifo: # Flush the RX FIFO just in case +# lbu $v1, JOY_TXRX($t0) +# lhu $v0, JOY_STAT($t0) +# nop +# andi $v0, 0x2 +# bnez $v0, .Lread_empty_fifo +# nop + + lhu $v1, JOY_CTRL($t0) + nop + or $v1, 0x10 + sh $v1, JOY_CTRL($t0) + + jal _CardExchng # Send device check byte + li $a0, 0x81 + andi $v1, $v0, 0x100 # No card if exchange timed out + bnez $v1, .Lno_device + addiu $v0, $0 , 1 + + jal _wait # 1st exchange needs 27microsec after ACK + li $v0, 190 # (e.g. 7 as usual + an extra 20) + + jal _CardExchng # Send read command + li $a0, 0x52 + andi $v1, $v0, 0x100 # No card if exchange timed out + bnez $v1, .Lno_device + addiu $v0, $0 , 2 + + jal _CardExchng # Receive card ID bytes + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lno_device + addiu $v0, $0 , 3 + jal _CardExchng + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lno_device + addiu $v0, $0 , 4 + + jal _CardExchng # Send address + srl $a0, $a2, 8 + andi $v1, $v0, 0x100 + bnez $v1, .Lno_device + addiu $v0, $0 , 5 + jal _CardExchng + andi $a0, $a2, 0xFF + andi $v1, $v0, 0x100 + bnez $v1, .Lno_device + addiu $v0, $0 , 6 + + sb $0 , JOY_TXRX($t0) # Receive command acknowledge 1 + nop +.Lsend_wait: + lhu $v0, JOY_STAT($t0) + nop + andi $v0, 0x4 + beqz $v0, .Lsend_wait + nop + move $v1, $0 + lui $a0, 0xBFC0 +.Lwait_ack: + bgt $v1, 30000, .Lread_timeout + addiu $v0, $0, 10 + lhu $v0, JOY_STAT($t0) + lw $0 , 4($a0) + lw $0 , 0($a0) + andi $v0, 0x202 + bne $v0, 0x202, .Lwait_ack + addiu $v1, 1 + lhu $v1, JOY_CTRL($t0) + lbu $v0, JOY_TXRX($t0) + or $v1, 0x10 + sh $v1, JOY_CTRL($t0) + + jal _CardExchng # Receive command acknowledge 2 + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lno_device + addiu $v0, $0 , 7 + + jal _CardExchng # Receive confirmed address MSB + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lno_device + addiu $v0, $0 , 8 + + jal _CardExchng # Receive confirmed address LSB + move $a0, $0 + andi $v1, $v0, 0x100 + bnez $v1, .Lno_device + addiu $v0, $0 , 9 + + move $a2, $0 +.Ltransfer_loop: + jal _CardExchng + move $a0, $0 + sb $v0, 0($a1) + addiu $a2, 1 + blt $a2, 128, .Ltransfer_loop + addiu $a1, 1 + + jal _CardExchng # Gets checksum byte + move $a0, $0 + move $a3, $v0 + + sb $0 , JOY_TXRX($t0) # Gets end byte + nop +.Lsend_wait_end: + lhu $v1, JOY_STAT($t0) + nop + andi $v1, 0x6 + bne $v1, 0x6, .Lsend_wait_end + nop + lbu $v1, JOY_TXRX($t0) + nop + + lw $a2, 8($sp) + lw $a1, 4($sp) + andi $v1, $a2, 0xff + srl $a2, 8 + xor $a0, $a2, $v1 + jal _CardCSum + li $a2, 128 + + bne $v0, $a3, .Lno_device + addiu $v0, $0 , -1 + + move $v0, $0 +.Lread_timeout: +.Lno_device: + + sh $0 , JOY_CTRL($t0) # Apparently required + + lw $ra, 0($sp) + addiu $sp, 12 + jr $ra + nop + + +.global _CardExchng +.type _CardExchng, @function +_CardExchng: + + lui $t0, IOBASE + + sb $a0, JOY_TXRX($t0) + nop +.Lsend_wait_exchg: + lhu $v0, JOY_STAT($t0) + nop + andi $v0, 0x4 + beqz $v0, .Lsend_wait_exchg + nop + + lui $a0, 0xBFC0 + move $v1, $0 +.Lwait_ack_exchg: + bgt $v1, 500, .Ltimeout + lhu $v0, JOY_STAT($t0) + lw $0 , 4($a0) + lw $0 , 0($a0) + andi $v0, 0x202 + bne $v0, 0x202, .Lwait_ack_exchg + addiu $v1, 1 + + b .Ldone + nop + +.Ltimeout: + + lbu $v0, JOY_TXRX($t0) + nop + b .Lexit_exchg + ori $v0, 0x100 + +.Ldone: + + lhu $v1, JOY_CTRL($t0) + lbu $v0, JOY_TXRX($t0) + or $v1, 0x10 + sh $v1, JOY_CTRL($t0) + +.Lexit_exchg: + + jr $ra + nop diff --git a/indev/psxpad/main.c b/indev/psxpad/main.c new file mode 100644 index 0000000..e8a6181 --- /dev/null +++ b/indev/psxpad/main.c @@ -0,0 +1,399 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <malloc.h> +#include <psxetc.h> +#include <psxgte.h> +#include <psxgpu.h> +#include <psxapi.h> +#include <siofs.h> + +#define OT_LEN 8 + +#define SCREEN_XRES 320 +#define SCREEN_YRES 240 + +#define CENTER_X SCREEN_XRES/2 +#define CENTER_Y SCREEN_YRES/2 + + +/* Display and drawing environments */ +DISPENV disp[2]; +DRAWENV draw[2]; + +char pribuff[2][16384]; /* Primitive packet buffers */ +unsigned int ot[2][OT_LEN]; /* Ordering tables */ +char *nextpri; /* Pointer to next packet buffer offset */ +int db = 0; /* Double buffer index */ + + +void init() { + + int i; + + /* Reset GPU (also installs event handler for VSync) */ + printf("Init GPU... "); + ResetGraph( 0 ); + printf("Done.\n"); + + + printf("Set video mode... "); + + /* Set display and draw environment parameters */ + SetDefDispEnv( &disp[0], 0, 0, SCREEN_XRES, SCREEN_YRES ); + SetDefDrawEnv( &draw[0], 0, SCREEN_YRES, SCREEN_XRES, SCREEN_YRES ); + SetDefDispEnv( &disp[1], 0, SCREEN_YRES, SCREEN_XRES, SCREEN_YRES ); + SetDefDrawEnv( &draw[1], 0, 0, SCREEN_XRES, SCREEN_YRES ); + + //disp[0].isinter = 1; /* Enable interlace (required for hires) */ + //disp[1].isinter = 1; + + /* Set clear color, area clear and dither processing */ + setRGB0( &draw[0], 63, 0, 127 ); + draw[0].isbg = 1; + draw[0].dtd = 1; + + setRGB0( &draw[1], 63, 0, 127 ); + draw[1].isbg = 1; + draw[1].dtd = 1; + + /* Apply the display and drawing environments */ + PutDispEnv( &disp[1] ); + PutDrawEnv( &draw[1] ); + + /* Enable video output */ + SetDispMask( 1 ); + + printf("Done.\n"); + + + FntLoad( 960, 0 ); + FntOpen( 8, 16, 304, 216, 0, 100 ); + +} + +extern void _InitPadDirect(void); +extern int _PadReadDirect(int port, unsigned char *data, int len); +extern int _CardRead(int port, unsigned char *data, int lba); +extern int _CardWrite(int port, unsigned char *data, int lba); +extern int _PadExchng(int byte); +extern void _PadSetPort(int port); + +extern unsigned char _pad_mot_values[]; + +unsigned char padbuff[2][34]; + + +char *hex_tbl = "0123456789ABCDEF"; + +void byte2str(unsigned char *in, int bytes, char *out) +{ + int i; + + for( i=0; i<bytes; i++ ) + { + *out = hex_tbl[in[i]>>4]; out++; + *out = hex_tbl[in[i]&0xF]; out++; + } + + *out = 0x0; +} + +unsigned char card_buff[128]; + +void dump_data(unsigned char *buff) +{ + int ix,iy; + + for( iy=0; iy<8; iy++ ) + { + for( ix=0; ix<16; ix++ ) + { + printf( "%02x", *buff ); + buff++; + } + printf( "\n" ); + } +} + +void TurnOnVibrators(void) +{ + _PadSetPort(0); + + if( _PadExchng(0x01) & 0x100 ) + { + ExitCriticalSection(); + return; + } + + if( _PadExchng(0x43) & 0x100 ) + { + ExitCriticalSection(); + return; + } + + _PadExchng(0x00); + _PadExchng(0x01); + + while( !(_PadExchng(0) & 0x100) ); + + _PadSetPort(2); + + ExitCriticalSection(); + VSync(0); + EnterCriticalSection(); + + // Set analog state + _PadSetPort(0); + + _PadExchng(0x01); + _PadExchng(0x4D); + _PadExchng(0x00); + + _PadExchng(0x00); + _PadExchng(0x01); + _PadExchng(0xFF); + _PadExchng(0xFF); + _PadExchng(0xFF); + _PadExchng(0xFF); + + _PadSetPort(2); + + ExitCriticalSection(); + VSync(0); + EnterCriticalSection(); + + // Exit configuration mode + _PadSetPort(0); + + _PadExchng(0x01); + _PadExchng(0x43); + _PadExchng(0x00); + _PadExchng(0x00); + + while( !(_PadExchng(0) & 0x100) ); + + _PadSetPort(2); + + ExitCriticalSection(); + VSync(0); +} + +void TurnOnAnalog(void) +{ + EnterCriticalSection(); + + // Enter configuration mode + _PadSetPort(0); + + if( _PadExchng(0x01) & 0x100 ) + { + ExitCriticalSection(); + return; + } + + if( _PadExchng(0x43) & 0x100 ) + { + ExitCriticalSection(); + return; + } + + _PadExchng(0x00); + _PadExchng(0x01); + + while( !(_PadExchng(0) & 0x100) ); + + _PadSetPort(2); + + ExitCriticalSection(); + VSync(0); + EnterCriticalSection(); + + // Set analog state + _PadSetPort(0); + + _PadExchng(0x01); + _PadExchng(0x44); + _PadExchng(0x00); + _PadExchng(0x01); // 0 - analog off, 1 - analog on + _PadExchng(0x02); + + while( !(_PadExchng(0) & 0x100) ); + + _PadSetPort(2); + + ExitCriticalSection(); + VSync(0); + EnterCriticalSection(); + + // Exit configuration mode + _PadSetPort(0); + + _PadExchng(0x01); + _PadExchng(0x43); + _PadExchng(0x00); + _PadExchng(0x00); + + while( !(_PadExchng(0) & 0x100) ); + + _PadSetPort(2); + + ExitCriticalSection(); + VSync(0); +} + +int main(int argc, const char* argv[]) { + + DR_TPAGE *tpri; + + int i,j,counter=0,fd; + char textbuff[64]; + char *memcard_image,*p; + + /* Init graphics and stuff before doing anything else */ + init(); + + _InitPadDirect(); + + + /* + if( fsInit(115200) >= 0 ) + { + printf("Loading memory card image... "); + + fd = fsOpen("cardimage.bin", FS_READ|FS_BINARY); + + if( fd < 0 ) + { + printf("File not found\n"); + } + else + { + memcard_image = (char*)malloc(131072); + + fsRead(fd, memcard_image, 131072); + + fsClose(fd); + + printf("Done.\n"); + + p = memcard_image; + for( j=0; j<1024; j++ ) + { + i = _CardWrite(0, p, j); + printf("Writing memory card (%d/1024)... \r", j); + if( i ) + printf("\nError %d at sector %d\n", i, j); + p += 128; + // Memory cards need at least 2 vsyncs between each write + // apparently + VSync(2); + } + + } + } + else + { + fd = -1; + memcard_image = NULL; + } + */ + + /* + for( j=0; j<1024; j++ ) + { + memset( card_buff, 0xff, 128 ); + i = _CardRead( 0, card_buff, j ); + + printf("Reading memory card (%d/1024)... \r", j); + + if( i != 0 ) + { + printf("\nPotential read error at sector %d\n", j); + } + + if( fd >= 0 ) + fsWrite(fd, (u_char*)card_buff, 128); + + if( i ) + break; + } + + if( fd >= 0 ) + fsClose(fd); + + printf("\nSuccessfully read entire memory card\n"); + */ + + /* + i = _CardRead( 0, card_buff, j ); + printf("Clearing memory card FAT.\n"); + memset( card_buff, 0xff, 128 ); + for(j=0; j<4; j++) + { + i = _CardWrite( 0, card_buff, 4 ); + printf("_CardWrite returned %d\n", i); + VSync(2); + } + */ + + + TurnOnAnalog(); + TurnOnVibrators(); + + /* Main loop */ + printf("Entering loop...\n"); + + while(1) { + + /* + if((counter>>4)&0x1) + { + _pad_mot_values[0] = 0xff; + } + else + { + _pad_mot_values[0] = 0x0; + } + */ + + i = _PadReadDirect(0, padbuff[0], 34); + //_PadReadDirect(1, padbuff[1], 34); + + FntPrint( -1, "HELLO WORLD %d\n", counter ); + + byte2str( padbuff[0], i, textbuff ); + FntPrint( -1, "P1:%s\n", textbuff ); + //byte2str( padbuff[1], 8, textbuff ); + //FntPrint( -1, "P2:%s\n", textbuff ); + + /* Clear ordering table and set start address of primitive */ + /* buffer for next frame */ + ClearOTagR( ot[db], OT_LEN ); + nextpri = pribuff[db]; + + + + /* Wait for GPU and VSync */ + FntFlush(-1); + DrawSync( 0 ); + VSync( 0 ); + + /* Since draw.isbg is non-zero this clears the screen */ + PutDispEnv( &disp[db] ); + PutDrawEnv( &draw[db] ); + + /* Begin drawing the new frame */ + DrawOTag( ot[db]+(OT_LEN-1) ); + + /* Alternate to the next buffer */ + db = !db; + + /* Increment counter for the snake animation */ + counter++; + + } + + return 0; + +} diff --git a/indev/psxpad/makefile b/indev/psxpad/makefile new file mode 100644 index 0000000..ab6a733 --- /dev/null +++ b/indev/psxpad/makefile @@ -0,0 +1,39 @@ +include ../../examples/sdk-common.mk + +TARGET = libpad.elf + +CFILES = $(notdir $(wildcard *.c)) +CPPFILES = $(notdir $(wildcard *.cpp)) +AFILES = $(notdir $(wildcard *.s)) + +OFILES = $(addprefix build/,$(CFILES:.c=.o) $(CPPFILES:.cpp=.o) $(AFILES:.s=.o)) + +INCLUDE += +LIBDIRS += + +LIBS = -lsiofs -lpsxsio -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lc + +CFLAGS = -g -O2 -fno-builtin -fdata-sections -ffunction-sections +CPPFLAGS = $(CFLAGS) -fno-exceptions +AFLAGS = -g -msoft-float +LDFLAGS = -g -Ttext=0x80010000 -gc-sections -T $(GCC_BASE)/mipsel-unknown-elf/lib/ldscripts/elf32elmip.x + +CC = $(PREFIX)gcc +CXX = $(PREFIX)g++ +AS = $(PREFIX)as +LD = $(PREFIX)ld + +all: $(OFILES) + $(LD) $(LDFLAGS) $(LIBDIRS) $(OFILES) $(LIBS) -o $(TARGET) + elf2x -q $(TARGET) + +build/%.o: %.c + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +build/%.o: %.s + @mkdir -p $(dir $@) + $(CC) $(AFLAGS) $(INCLUDE) -c $< -o $@ + +clean: + rm -rf build $(TARGET) $(TARGET:.elf=.exe) diff --git a/indev/psxpad/pad.s b/indev/psxpad/pad.s new file mode 100644 index 0000000..0fa66aa --- /dev/null +++ b/indev/psxpad/pad.s @@ -0,0 +1,264 @@ +.set noreorder
+
+.include "hwregs_a.h"
+
+.section .text
+
+.global _InitPadDirect
+.type _InitPadDirect, @function
+_InitPadDirect:
+
+ addiu $sp, -4
+ sw $ra, 0($sp)
+
+ lui $t0, IOBASE
+
+ # Interface setup
+ li $v0, 0x40 # Interface reset
+ sh $v0, JOY_CTRL($t0)
+ li $v0, 0x88 # 250kHz clock rate
+ sh $v0, JOY_BAUD($t0)
+ li $v0, 0x0d # 8-bit, no parity, x1 multiplier
+ sh $v0, JOY_MODE($t0)
+ li $v0, 0x1003 # JOY1, TX enabled
+ sh $v0, JOY_CTRL($t0)
+
+ jal _wait
+ li $v0, 1000
+
+ # Empty RX fifo
+.Lempty_fifo:
+ lbu $v1, JOY_TXRX($t0)
+ lhu $v0, JOY_STAT($t0)
+ nop
+ andi $v0, 0x2
+ bnez $v0, .Lempty_fifo
+ nop
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ nop
+
+
+.global _PadSetPort
+.type _PadSetPort, @function
+_PadSetPort:
+ addiu $sp, -4
+ sw $ra, 0($sp)
+
+ lui $t0, IOBASE
+
+ beq $a0, 2, .Lstop_comms
+ nop
+
+ li $v0, 0x1003 # TX Enable, Joypad port select
+ andi $a0, 1
+ sll $a0, 13
+ or $v0, $a0 # Select port 2 if a0 is 1
+
+ sh $v0, JOY_CTRL($t0) # Set to Joypad control interface
+
+ jal _wait # Delay for analog pads (needs testing)
+ li $v0, 500
+
+.Lread_empty_fifo_set: # Flush the RX FIFO just in case
+ lbu $v1, JOY_TXRX($t0)
+ lhu $v0, JOY_STAT($t0)
+ nop
+ andi $v0, 0x2
+ bnez $v0, .Lread_empty_fifo_set
+ nop
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ nop
+
+.Lstop_comms:
+
+ sh $0 , JOY_CTRL($t0)
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ nop
+
+
+.global _PadReadDirect
+.type _PadReadDirect, @function
+_PadReadDirect:
+
+ # a0 - port number
+ # a1 - device data buffer
+ # a2 - data max length
+
+ addiu $sp, -4
+ sw $ra, 0($sp)
+
+ lui $t0, IOBASE
+
+ li $v0, 0x1003 # TX Enable, Joypad port select
+ andi $a0, 1
+ sll $a0, 13
+ or $v0, $a0 # Select port 2 if a0 is 1
+
+ sh $v0, JOY_CTRL($t0) # Set to Joypad control interface
+
+ jal _wait # Delay for analog pads (needs testing)
+ li $v0, 310
+
+# May cause issues with third party adapters such as Brook wireless
+#.Lread_empty_fifo: # Flush the RX FIFO just in case
+# lbu $v1, JOY_TXRX($t0)
+# lhu $v0, JOY_STAT($t0)
+# nop
+# andi $v0, 0x2
+# bnez $v0, .Lread_empty_fifo
+# nop
+
+ jal _PadExchng # Send device check byte
+ li $a0, 0x01
+
+ andi $v1, $v0, 0x100 # No pad if exchange timed out
+ bnez $v1, .Lno_device
+ addiu $v0, $0 , 1
+
+ sb $v0, 0($a1)
+ addiu $a1, 1
+
+ jal _wait # 1st exchange needs 27microsec after ACK
+ li $v0, 190 # (e.g. 7 as usual + an extra 20)
+
+ jal _PadExchng # Send command byte
+ li $a0, 0x42
+
+ sb $v0, 0($a1)
+ addiu $a1, 1
+ addiu $a2, -2
+
+ jal _PadExchng # Send 0 for pads, 1 for multitap
+ move $a0, $0 # Read is usually 0x5A
+
+ addi $a3, $0 , 1
+
+ la $t1, _pad_mot_values
+
+.Lread_loop: # Read until buffer full, or no more data
+
+ lbu $a0, 0($t1)
+ nop
+ beqz $a0, .Lskip_mot
+ nop
+
+ jal _PadExchng
+ nop
+
+ b .Ldone_exchg
+ addiu $t1, 1
+
+.Lskip_mot:
+
+ jal _PadExchng # when ACK is no longer triggered
+ move $a0, $0
+
+.Ldone_exchg:
+
+ sb $v0, 0($a1)
+
+ andi $v0, 0x100
+ bnez $v0, .Lread_end
+ addi $a3, 1
+
+ addiu $a2, -1
+ bgtz $a2, .Lread_loop
+ addiu $a1, 1
+
+.Lread_end:
+
+ b .Lexit
+ move $v0, $a3
+
+.Lno_device:
+
+ addiu $v0, $0 , -1
+ sb $v0, 0($a1)
+
+.Lexit:
+
+ sh $0 , JOY_CTRL($t0)
+
+ lw $ra, 0($sp)
+ addiu $sp, 4
+ jr $ra
+ nop
+
+
+.global _PadExchng
+.type _PadExchng, @function
+_PadExchng:
+
+ lui $t0, IOBASE
+
+ sb $a0, JOY_TXRX($t0)
+ nop
+.Lsend_wait:
+ lhu $v0, JOY_STAT($t0)
+ nop
+ andi $v0, 0x4
+ beqz $v0, .Lsend_wait
+ nop
+
+ move $v1, $0
+.Lwait_ack:
+ bgt $v1, 100, .Ltimeout
+ lhu $v0, JOY_STAT($t0)
+ nop
+ andi $v0, 0x202
+ bne $v0, 0x202, .Lwait_ack
+ addiu $v1, 1
+
+ b .Ldone
+ nop
+
+.Ltimeout:
+
+ lbu $v0, JOY_TXRX($t0)
+ nop
+ b .Lexit_exchg
+ ori $v0, 0x100
+
+.Ldone:
+
+ lhu $v1, JOY_CTRL($t0)
+ lbu $v0, JOY_TXRX($t0)
+ or $v1, 0x10
+ sh $v1, JOY_CTRL($t0)
+
+.Lexit_exchg:
+
+ jr $ra
+ nop
+
+
+.global _wait
+.type _wait, @function
+_wait:
+ addiu $v0, -1
+ bgtz $v0, _wait
+ nop
+ jr $ra
+ nop
+
+
+.section .data
+
+.global _pad_mot_values
+.type _pad_mot_values, @object
+_pad_mot_values:
+ .byte 0 # Small motor
+ .byte 0 # Big motor
+ .byte 0
+ .byte 0
+
+
|
