; PSXKey V2.04 ; (c)2000 Double Dutch Designs Limited ; Written by Anthony Ball ; Requires 8Mhz AVR AT90xxxx ; Keyboard optional commands, needs 'off', 'sleep', 'on' keys ; off keyboard emulates pad ; sleep keyboard is pad as well as stick inputs ; on keyboard acts as keyboard - along with stick inputs! ; List of changes: ; 1.xx-2.00 change from pic to avr microcontroller, serial to pad ports ; 2.00-2.01 automatic keyboard detection ; 2.01-2.02 multiplexed sega stick input(s) ; 2.02-2.03 pad emulation via keyboard ; 2.03-2.04 crystal & software change from 4Mhz to 8Mhz ; Limitations: ; o Will not function properly with a multitap, this is because of the ; packet length being too long ; Known Bugs: ; o Memory cards plugged into same port will not function properly ; Features: ; o Hardware decode/encode of psx communication data ; o 'On-the-fly' detection & reset of inserted keyboard ; o Interrupt driven keyboard reading ; o Converts keyboard data to single byte for press, another for depress ; o Interrupt driven keyboard control ; o Spurious bit error correction on keyboard data ; o Parity bit checking on keyboard data ; o Multiplexed Sega stick input(s) ; o Psx pad emulation via keyboard .include "4414def.inc" ; .include "2333def.inc" .equ Version=1 ; version number .def DataInput=R0 ; data from program .def Parity=R1 ; parity check .def LastKey=R2 ; character for keyboard .def BufferA0=R4 .def BufferA1=R5 .def BufferA2=R6 .def BufferA3=R7 .def BufferA4=R8 .def BufferA5=R9 .def BufferB0=R10 .def BufferB1=R11 .def BufferB2=R12 .def BufferB3=R13 .def BufferB4=R14 .def BufferB5=R15 .def Psx=R16 ; psx last chr read, chr to write .def ScratchA=R17 ; temp register a .def ScratchB=R18 ; temp register b .def ScratchC=R19 ; temp register c .def Count=R20 ; counter .def IScratch=R21 ; interrupt temp register .def ProcessKey=R22 ; current key being processed .def Mode=R23 ; mode flag .def Dir=R24 ; transfer direction .def Break=R25 ; break flag .def Release=R26 ; release flag .def Enhanced=R27 ; enhanced flag .def LockStatus=R28 ; key lock status .def IScratch2=R29 ; interrupt scratch register 2 .equ SCROLL=0 ; scroll lock on .equ NUM=1 ; num lock on .equ CAPS=2 ; caps lock on .equ DONETEST=3 ; keyboard has just done a selftest .equ EMUA=4 ; emulation mode a .equ EMUB=5 ; emulation mode b .equ STICKA0=4 ; user programmable stick status .equ STICKA1=5 .equ STICKB0=6 .equ STICKB1=7 .equ IOSetLED=$ed .equ IOScanCode=$f0 .equ IOEnable=$f4 .equ IOReset=$fe .equ IOAck=$f4 ; okay responce .equ IOSelfTest=$aa ; selftest performed okay .equ IOFailA=$00 .equ IOFailB=$ff .equ TimeOut=1200 ; timeout value for counter .equ Key_Id=$e ; keyboard id .equ Pad_Id=$4 ; pad id, emulate standard pad .equ KEYCLK=2 ; keyboard clock, out .equ KEYDAT=3 ; keyboard data, bi .equ ACK=6 ; psx ack, out .equ ATT=4 ; psx att, in .equ CMD=5 ; psx cmd, in .equ DAT=6 ; psx dat, out .equ CLK=7 ; psx clk, in .equ Plex=5 ; multiplex select .equ Stick1Up=0 ; stick udlr, plex has to be 1 .equ Stick1Down=1 .equ Stick1Left=2 .equ Stick1Right=3 .equ Stick1A=1 ; with plex=0 .equ Stick1B=1 ; with plex=1 .equ Stick1C=4 ; with plex=1 .equ Stick1START=4 ; with plex=0 .equ Stick2Up=0 ; stick udlr, plex has to be 1 .equ Stick2Down=1 .equ Stick2Left=2 .equ Stick2Right=3 .equ Stick2A=1 ; with plex=0 .equ Stick2B=1 ; with plex=1 .equ Stick2C=4 ; with plex=1 .equ Stick2START=4 ; with plex=0 .equ StickPower=0 .equ PadUp=4 ; psx pad udlr .equ PadDown=6 .equ PadLeft=7 .equ PadRight=5 .equ PadSelect=0 ; select .equ PadX=6 ; x .equ PadO=5 ; o .equ PadStart=3 ; start .equ PadT=4 ; triangle .equ PadS=7 ; square .equ PadL1=2 ; left 1 .equ PadR1=3 ; right 1 .equ PadL2=0 ; left 2 .equ PadR2=1 ; right 2 .equ PadAHi=$60 ; psx pad a layout pt1 .equ PadALo=$61 ; psx pad a layout pt2 .equ PadBHi=$62 ; psx pad b layout pt1 .equ PadBLo=$63 ; psx pad b layout pt2 .equ PadCHi=$64 ; psx pad c layout pt1 .equ PadCLo=$65 ; psx pad c layout pt2 .equ PadDHi=$66 ; psx pad d layout pt1 .equ PadDLo=$67 ; psx pad d layout pt2 .cseg .org 0 Reset: rjmp Start ; run init rjmp Interrupt ; external int0 rjmp Start ; not used (int1) rjmp Start ; not used (capture event) Timer: cpi Dir,1 breq StartOutput cbi DDRD,KEYDAT ; data input clr Count ; timer match reti StartOutput: sbi DDRD,KEYDAT ; data output cbi PORTD,KEYDAT ; data low (start bit) sbi PORTD,KEYCLK ; clock high cbi DDRD,KEYCLK ; clock input clr Parity ; init parity ldi Count,1 reti Interrupt: cpi Count,0 breq IStart cpi Count,9 breq IParity cpi Count,10 breq IStop cpi Dir,0 brne ITx lsr ProcessKey ; shift key right sbis PIND,KEYDAT rjmp IExit sbr ProcessKey,(1<<7) inc Parity rjmp IExit ITx: lsr ProcessKey ; shift key left brcc ITxSkip1 sbi PORTD,KEYDAT ; send a 1 ITxSkip1: brcs ITxSkip0 cbi PORTD,KEYDAT ; send a 0 ITxSkip0: rjmp IExit IStart: clr Parity ; init parity sbic PIND,KEYDAT ; start bit should be low rjmp IError ; start bit is high!!! error... rjmp IExit IParity: cpi Dir,0 brne ITxParity clr IScratch sbis PIND,KEYDAT ; get parity bit in iscratch ldi IScratch,1 eor IScratch,Parity ; is it the same as calculated? andi IScratch,1 breq IExit ; same! cpi ProcessKey,IOAck breq IExit rjmp IError ITxParity: mov IScratch,Parity andi IScratch,1 brne ITxParity1 cbi PORTD,KEYDAT ; pull low rjmp IExit ITxParity1: sbi PORTD,KEYDAT ; pull high rjmp IExit IExit: inc Count IExit2: clr IScratch out TCNT1H,IScratch ; reset counter out TCNT1L,IScratch reti ModeLedNo: mov ProcessKey,LockStatus andi ProcessKey,$7 rjmp IOut ModeLed: ldi ProcessKey,IOSetLED rjmp IOut ModeSetNo: ldi ProcessKey,$02 rjmp IOut ModeSet: ldi ProcessKey,IOScanCode rjmp IOut ModeEnable: ldi ProcessKey,IOEnable rjmp IOut ModeReset: ldi ProcessKey,IOReset clr Break ; break key flag clr Release ; release key flag clr Enhanced ; enhanced key flag rjmp IOut IOut: sbi DDRD,KEYCLK ; clock output cbi PORTD,KEYCLK ; clock low ldi Dir,1 ; direction 1 INext: dec Mode ; next mode!!! IError: clr Count ; reset count for next time rjmp IExit2 IStop: cpi Dir,0 brne ITxStop sbis PIND,KEYDAT ; stop bit should be high rjmp IError ; start bit is low!!! error... cpi ProcessKey,IOAck breq IOkay cpi ProcessKey,IOFailA breq IBad cpi ProcessKey,IOFailB breq IBad cpi ProcessKey,IOSelfTest brne IStore ori LockStatus,1<