* N64C2PC V1.3 QRT 180499
* 24 MHz Version digital version 
* 4 axis, 4 buttons
*
* V1.1 direction/C-buttons and Start/R-button is handled
*      same, L button switches between 33%, 66%, 100% speed 
*      for direction/C-buttons
* V1.2 avoids hanginging in waiting loops
* V1.3 shorter code, new LED handling

* 8051 Assembler bit-assignments
* PSW
CY      BIT     $D7
AC      BIT     $D6
F0      BIT     $D5
RS1     BIT     $D4
RS0     BIT     $D3
OV      BIT     $D2
P       BIT     $D0
* TCON
TF1     BIT     $8F
TR1     BIT     $8E
TF0     BIT     $8D
TR0     BIT     $8C
IE1     BIT     $8B
IT1     BIT     $8A
IE0     BIT     $89
IT0     BIT     $88
* T2CON
TR2     BIT     $CA
TF2     BIT     $CF
* IE 
EA      BIT     $AF
ES      BIT     $AC
ET1     BIT     $AB
EX1     BIT     $AA
ET0     BIT     $A9
EX0     BIT     $A8
ET2     BIT     $AD
* IP 
PS      BIT     $BC
PT1     BIT     $BB
PX1     BIT     $BA
PT0     BIT     $B9
PX0     BIT     $B8
PT2     BIT     $BD
* P3
RD      BIT     $B7
WR      BIT     $B6
T1      BIT     $B5
T0      BIT     $B4
INT1    BIT     $B3
INT0    BIT     $B2
TXD     BIT     $B1
RXD     BIT     $B0
* SCON
SM0     BIT     $9F
SM1     BIT     $9E
SM2     BIT     $9D
REN     BIT     $9C
TB8     BIT     $9B
RB8     BIT     $9A
TI      BIT     $99
RI      BIT     $98

*********************************************************************

        ORG     $0000           ROM Starts here
        LJMP    main
*        ORG     $0003
*        LJMP    Ext0Int         
        ORG     $000b
        LJMP    Timer0Int       
*        ORG     $0013
*        LJMP    Ext1Int        
        ORG     $001b
        LJMP    Timer1Int       
*        ORG     $0023
*        LJMP    SerInt          
*        ORG     $002b
*        LJMP    Timer2Int       
        
?R0     EQU     0           
?R1     EQU     ?R0+1         
?R2     EQU     ?R0+2       
?R3     EQU     ?R0+3          
?R4     EQU     ?R0+4
?R5     EQU     ?R0+5
?R6     EQU     ?R0+6
?R7     EQU     ?R0+7

joyaxt      DATA    $08         (2 byte)
joyayt      DATA    $0a         (2 byte)
joybxt      DATA    $0c         (2 byte)
joybyt      DATA    $0e         (2 byte)
speed       DATA    $10         speed for direction

lbpress     BIT     $00         1=left button pressed
tomode      BIT     $01         1=timeout mode

* bit00       BIT     $00         (byte $20)
* bit7f       BIT     $7f         (byte $2f)

* mem18       DATA    $30
* mem48       DATA    $5f

stack       DATA    $60         ...$7f

JOYAX       EQU     P1.0        PC joystick A x      
JOYAY       EQU     P1.1        PC joystick A y
JOYBX       EQU     P1.2        PC joystick B x
JOYBY       EQU     P1.3        PC joystick B y
DATA        EQU     P3.7        one line controller data
CLED        EQU     P3.5        control LED

MID         EQU     512         cycles
MAXC        EQU     1024/16     cycles
FSPEED      EQU     120         100% speed for direction
ISPEED      EQU     40          increase speed 1/3
TOCYCLES    EQU     15          ca. 0.5s = 15*2^16*0,5us

*********************************************************************

main
        mov     IE,#0           all IR's disable and delete
        mov     SP,#(stack-1)   stack init

        acall   maininit

?ma0    
        acall   prepajoyt       prepare joy A timing
        acall   prepbjoyt       prepare joy B timing
        setb    CLED            LED off
        
        jnb     JOYAX,*         wait for pc pulse
        anl     P1,#%11110000   pull joy lines down
        orl     TCON,#%01010000 start both timers
        cpl     CLED            invert LED
        acall   joybtiming

        jb      TR0,*           wait for both timers ready
        jb      TR1,*
        
        acall   inittom         timout mode on
        
        mov     A,#$01          get controllerbytes
        acall   sendbyteA
        acall   getbytes
        
        clr     tomode          timeout mode off
        clr     TR0             stop timer 0
        
        acall   handlebuttons
        
        sjmp    ?ma0

*********************************************************************

joybtiming
        mov     R2,#MAXC        MAXC * 16 cycles for whole loop    
        mov     R0,joybxt       
        mov     R1,joybyt

?jb1    cjne    R0,#0,?jb2      2 cycles
        orl     P1,#%00000100   2           joybx
        nop                     1
        nop                     1
        nop                     1
?jb4    cjne    R1,#0,?jb3      2
        orl     P1,#%00001000   2           joyby
        nop                     1
        nop                     1
        nop                     1
?jb5    djnz    R2,?jb1         2           one loop = 16 cycles

        ret

?jb2    inc     R0              1 cycles
        nop                     1
        nop                     1
        sjmp    ?jb4            2

?jb3    inc     R1              1
        nop                     1
        nop                     1
        sjmp    ?jb5            2

*********************************************************************

maininit
        anl     TMOD,#$f0       T0 vorbereiten ohne T1 zu verändern
        orl     TMOD,#$01       Gate0=0, c/t0=0, Mode1=01 16-bit
        clr     PT0             Timer0 Priorität
        clr     TR0             do not start T0

        anl     TMOD,#$0f       T1 vorbereiten ohne T0 zu verändern
        orl     TMOD,#$10       Gate1=0, c/t1=0, Mode1=01 16-bit
        clr     PT1             Timer1 Priorität
        clr     TR1             do not start T1

        setb    ET0             T0-IR enable
        setb    ET1             T1-IR enable
        setb    EA              all IR's enable

        clr     A
        mov     $20,A           clear flags
        mov     R5,A            joy B middle position
        mov     R6,A            joy A middle position x
        mov     R7,A            joy A middle position y
        mov     speed,#FSPEED   full speed for direction     

        ret

*********************************************************************

prepajoyt
        mov     A,R6            joy x
        mov     R0,#joyaxt+1    target address        
        acall   calctiming

        mov     A,R7            joy y
        cpl     A               invert axis
        inc     A               complement to two
        mov     R0,#joyayt+1    target address
        acall   calctiming

        mov     TL0,joyaxt
        mov     TH0,joyaxt+1
        mov     TL1,joyayt
        mov     TH1,joyayt+1
        
        ret
        
*********************************************************************

prepbjoyt
        mov     A,R4            direction-buttons or
        orl     A,R5            c-buttons
        push    A               save buttons
        xch     A,B

        mov     A,#0            assume middle position
        jnb     B.0,?pb1        test button right
        mov     A,speed         right
?pb1    jnb     B.1,?pb2        test button left
        mov     A,speed         left            
        cpl     A               negitve
        inc     A
?pb2    mov     R0,#joybxt+1    target address
        acall   calctiming        
        acall   div16                

        pop     B               restore buttons
        mov     A,#0            assume middle position
        jnb     B.2,?pb3        test button down
        mov     A,speed         down
?pb3    jnb     B.3,?pb4        test button up
        mov     A,speed         up 
        cpl     A               negative
        inc     A           
?pb4    mov     R0,#joybyt+1    target address
        acall   calctiming        
        acall   div16

        ret

*********************************************************************

handlebuttons
        mov     A,R5            button status 2
        anl     A,#%00010000    isolate R-button
        orl     A,R4            OR button status 1
        
        cpl     A               negative logic
        orl     A,#%00001111    keep joy lines high
        mov     P1,A            output

        mov     A,R5            button status 2
        jnb     A.5,?lp1        L-button pressed?
        setb    lbpress         yes, set flag
        ret 

?lp1    jnb     lbpress,?lp2    L not pressed, flag set?
        clr     lbpress         yes, clear flag
        mov     A,speed         
        add     A,#ISPEED           speed + increase
        cjne    A,#(FSPEED+1),?lp4  speed <= FSPEED?
?lp4    jc      ?lp3
        mov     A,#ISPEED       no, start with minimum
?lp3    mov     speed,A         save new speed        

?lp2    ret

*********************************************************************

inittom
        clr     A
        mov     TL0,A
        mov     TH0,A
        setb    tomode
        setb    TR0
        ret

*********************************************************************

calctiming
*                               calc timing, expand to 16 bit signed
        mov	    B,#0		    assume high byte positive
        clr     C
        rlc     A               range x2
        jnc     *+4
        dec     B               negative value
        clr     C
        rlc     A               range x2 (now +-512)
        xch     A,B             high byte to A
        rlc     A               rotate C into high byte
        mov     R1,B            low byte in R1
	    mov     R2,A            high byte in R2
       
        mov     A,#MID          low byte
        mov     B,#=MID         high byte
        add     A,R1            add low byte
        xch     A,B
        addc    A,R2            add high byte plus carry
        cpl     A               high byte negate for timer
        xch     A,B             
        cpl     A               low byte
        clr     C               complement to two
        add     A,#1            
        xch     A,B
        addc    A,#0
        mov     [R0],A          and save joy+1    
        xch     A,B
        dec     R0
        mov     [R0],A          joy       
        
        ret

*********************************************************************

div16
        mov     B,[R0]          low byte
        inc     R0
        mov     A,[R0]          high byte

        mov     R1,#4           divide through 16
?di1    rrc     A               high byte bit 0 to C
        xch     A,B             
        rrc     A               C to low byte bit 7
        xch     A,B
        djnz    R1,?di1
        
        dec     R0
        mov     [R0],B          save low byte (high byte is zero)
        
        ret

*********************************************************************

sendbyteA
        mov     R0,#8
        
?sb1    rlc     A               1 cycle
        setb    DATA            1
        nop                     1
        clr     DATA            1
        mov     DATA,C          2
        djnz    R0,?sb1         2
        
        nop                     1
        setb    DATA            1

        clr     DATA            prepare ready to receive signal

        ret        

*********************************************************************

getbytes
        setb    DATA            ready to receive
        
* get button status 1 to R4
        jb      DATA,*          2 cycles    sync to bitstream
        nop                     1
        mov     C,DATA          1           get bit 7
        acall   getbit6         2           get bits 6-1
        mov     C,DATA          1           get bit 0
        rlc     A               1           store bit
        mov     R4,A            1           store byte

* get button status 2 to R5
        jb      DATA,*          2 cycles    sync to bitstream
        nop                     1
        mov     C,DATA          1           get bit 7
        acall   getbit6         2           get bits 6-1
        mov     C,DATA          1           get bit 0
        rlc     A               1           store bit
        mov     R5,A            1           store byte

* get joystick x-position to R6 (signed) 
        jb      DATA,*          2 cycles    sync to bitstream
        nop                     1
        mov     C,DATA          1           get bit 7
        acall   getbit6         2           get bits 6-1
        mov     C,DATA          1           get bit 0
        rlc     A               1           store bit
        mov     R6,A            1           store byte

* get joystick y-position to R7 (signed) 
        jb      DATA,*          2 cycles    sync to bitstream
        nop                     1
        mov     C,DATA          1           get bit 7
        acall   getbit6         2           get bits 6-1
        mov     C,DATA          1           get bit 0
        rlc     A               1           store bit
        mov     R7,A            1           store byte

        ret

*********************************************************************

getbit6
        acall   getbit1         2 cycles
        acall   getbit1         2
        acall   getbit1         2
        acall   getbit1         2       
        acall   getbit1         2
        acall   getbit1         2
        rlc     A               1           store bit
        nop                     1
        nop                     1
        ret                     2
        
*********************************************************************

getbit1
        rlc     A               1 cycles    store bit
        nop                     1
        nop                     1
        mov     C,DATA          1           get bit
        ret                     2
        
*********************************************************************

Timer0Int
        jb      tomode,?t0i1    timeout mode?
        setb    JOYAX           no
        clr     TR0
        reti

?t0i1   mov     A,#main         yes
        push    A
        mov     A,#=main
        push    A
        reti                    restart at main

*********************************************************************

Timer1Int
        setb    JOYAY
        clr     TR1
        reti                    

