.FILE "COMM.ASM" *---------------------------------------------------------------------------- * * *COPYRIGHT (C) 1994 BY TV GAMES, INC. *ALL RIGHTS RESERVED * .include C30.EQU .include OBJ.EQU .include MACS.EQU .include MPROC.EQU .include VUNIT.EQU .include CMOS.EQU .include SYSID.EQU .include SYS.EQU .include GLOBALS.EQU .include SNDTAB.EQU .include PALL.EQU .include OBJECTS.EQU .include TEXT.EQU .include COMM.EQU TIME_DELAY .set 18 .globl COMM_MASTER_ERROR_CNT .globl COMM_MASTER_TRANSES .globl COMM_SLAVE_ERROR_CNT .globl COMM_SLAVE_TRANSES .globl COMM_SLAVE_NREADY fbss COMM_MASTER_ERROR_CNT,1 fbss COMM_MASTER_TRANSES,1 fbss COMM_SLAVE_ERROR_CNT,1 fbss COMM_SLAVE_TRANSES,1 fbss COMM_SLAVE_NREADY,1 .bss COMMFLAG,1 ;COMMUNICATIONS IS OVER pbss ONEFLAG,1 pbss TRANSMISSION_ACTIVE,1 ;1=TRUE pbss TRANSMISSION_DEAD,1 ;1=DEAD LINK *---------------------------------------------------------------------------- COMM_INIT: PUSH DP LDP @DIPRAM LDI @DIPRAM,R1 LDI 0,R0 STI R0,@ONEFLAG ;CLEAR OUT ONE PLAYER FLAG LDI C_SLA,R0 TSTB CMDP_MASTER,R1 LDIZ C_MAS,R0 LS 16,R0 LDP @COMMDP STI R0,@COMM_IO LDI C_CE,R0 LS 16,R0 STI R0,@COMM_CTL POP DP RETS *---------------------------------------------------------------------------- RECEIVE_BUFFERI .word RECEIVE_BUFFER COMM_IOI .word COMM_IO CTL EQU COMM_CTL-COMM_IO *---------------------------------------------------------------------------- COMM_ENABLE_INT2: ; ;if slave then enable the interrupt 2 ;(comm int 2) ; LDP @DIPRAM LDI @DIPRAM,R1 TSTB DIP_COMMP,R1 BNZ BABA TSTB CMDP_MASTER,R1 BZ BABA LDI INT2_M,R1 LDP @COMMINTM STI R1,@COMMINTM BABA LDP @COMMINTM OR @COMMINTM,IE SETDP RETS *---------------------------------------------------------------------------- *---------------------------------------------------------------------------- COMM_MASTER_SEND_SYNC: LDI @COMMFLAG,R0 ;DONT INTERRUPT COMMUNICATIONS RETSNZ LDI @DIPRAM,R0 TSTB CMDP_MASTER,R0 RETSNZ DINT ANDN INT2_M,IE ;DISABLE LINK INT2 LDI @COMM_IOI,AR5 ;SETUP I/O REGISTER *TRIGGER INTERRUPT IN SLAVE LDI *AR5,R0 RS 16,R0 AND C_C2,R0 LDI R0,R1 OR C_MAS|C_IRQ,R0 LS 16,R0 STI R0,*AR5 ;INT2 HI COMM_IO NOP NOP NOP LDI C_MAS,R0 OR R1,R0 LS 16,R0 STI R0,*AR5 ;INT2 LO COMM_IO ANDN INT2_M,IF ;REMOVE ANY LATCHED INT RETS *---------------------------------------------------------------------------- * *SET ONE PLAYER GAME (NO LINK) * SETONE: PUSH R0 PUSH AR0 CLRI R0 STI R0,@TRANSMISSION_ACTIVE LDI 1,R0 STI R0,@ONEFLAG LDI @DIPRAM,R0 TSTB CMDP_MASTER,R0 LDIZ C_C2|C_MAS,R0 ;MASTER CASE SEND C2=1 LDINZ C_C1|C_SLA,R0 ;SLAVE CASE SEND C1=1 B ONEX * *CLR ONE PLAYER GAME (NO LINK) * CLRONE: PUSH R0 PUSH AR0 LDI 1,R0 STI R0,@TRANSMISSION_ACTIVE LDI 0,R0 STI R0,@ONEFLAG LDI @DIPRAM,R0 TSTB CMDP_MASTER,R0 LDIZ C_MAS,R0 ;MASTER CASE LDINZ C_SLA,R0 ;SLAVE CASE ONEX LDI @COMM_IOI,AR0 ;SETUP I/O REGISTER LS 16,R0 STI R0,*AR0 POP AR0 POP R0 RETS *---------------------------------------------------------------------------- *COMMUNICATIONS LINK * COMMPAL .set 0990000h ;COMMUNICATIONS PAL COMM_ROUTINE: CLRI AR7 LDP @COMMPAL LDI @COMMPAL,R0 LDI *AR7,R1 SETDP AND 0FH,R0 CMPI 4,R0 ;BAD PAL ? RETSNZ ;YES....QUIT LDI @DIPRAM,R0 ;CHECK FOR COMMUNICATIONS TSTB DIP_COMMP,R0 RETSNZ ;NO COMM_HOLDFORA2D LDI @RDPOT,R1 CMPI 3,R1 BNZ COMM_HOLDFORA2D LDI 1,R1 STI R1,@COMMFLAG ;DONT INTERRUPT COMMUNICATIONS TSTB CMDP_MASTER,R0 ;CHECK MASTER/SLAVE BNZ COMM_SLAVE * *MASTER MUST ALWAYS 0 <- C_IRQE * COMM_MASTER: SETDP LDI @COMM_IOI,AR5 ;SETUP I/O REGISTER *CHECK ONE PLAYER MODE LDI @ONEFLAG,R0 BZ CM1 RETS ;WE'RE IN ONE PLAYER, EXIT CM1 LDI @SEND_BUFFER_A_LEN,R6 ;16 bits LDI @SEND_BUFFER_AI,AR2 CMPI 0,R6 BLE CMERRORL ;ZERO LENGTH, NO MESSAGE CMPI 240H,R6 BGE CMERRORL ;LENGTH ERROR ADDI R6,AR2,AR0 ;ADD 2 NULLS TO THE END DUDES LDI CB_NULL,R2 STI R2,*AR0 STI R2,*+AR0(1) *BEGIN SYNC ROUTINE LDI C_MAS,R0 ;send C2=0 LS 16,R0 STI R0,*AR5 LDI 120,R3 LDI @TRANSMISSION_DEAD,R0 ;GET TIMEOUT VALUES BZ WTLPMI LDI 1,R3 ;WAIT A FRAME IF DEAD ADDI @INFRAMES,R3 CMPI 4,R3 LDIGT 4,R3 WTLPMI LDI *AR5,R0 ;GET C0,C1 RS 16,R0 TSTB C_C1,R0 ;SLAVE C1=1 (ONE PLAYER MODE) BZ CM2 ;NO LDI 0,R0 ;SLAVE IN ONE PLAYER MODE, EXIT STI R0,@TRANSMISSION_ACTIVE STI R0,@TRANSMISSION_DEAD RETS CM2 TSTB C_C0,R0 ;WAIT FOR SLAVE READY SIGNAL BNZ CM3 ;GOT IT... CMPI @INFRAMES,R3 ;WAITING TOO LONG? BGT WTLPMI ;NO, KEEP LOOPING B CMERRORDEAD ;YES, ITS DEAD... CM3 LDI 0,R0 STI R0,@TRANSMISSION_DEAD LDI 1,R0 STI R0,@TRANSMISSION_ACTIVE LDI C_C2|C_MAS,R0 ;SEND C2=1 LS 16,R0 STI R0,*AR5 ADDI 1,R3 ;A LITTLE MORE TIME WTLPMI2 CMPI @INFRAMES,R3 ;WAITING TOO LONG? BLE CMERRORDEAD ;YES, ITS DEAD... LDI *AR5,R0 ;WAIT C0=0 RS 16,R0 TSTB C_C0,R0 BNZ WTLPMI2 LDI C_MAS,R0 ;send C2=0 LS 16,R0 STI R0,*AR5 ; ;END SYNC ROUTINE DINT WTLPMI3 LDI *AR5,R0 ;WAIT C1=1 RS 16,R0 TSTB C_C1,R0 BZ WTLPMI3 LDI C_MAS,R0 LS 16,R0 STI R0,*AR5 LDI C_SND,R0 ;SET DATA CONTROL FOR SEND LS 16,R0 STI R0,*+AR5(CTL) ;COMM_CTL * *SEND MESSAGE LENGTH TO SLAVE *16 BITS LENGTH *MESSAGE LENGTH IS MULT OF 2 * ADDI 1,R6 RS 1,R6 LDI R6,AR6 NOT R6,R7 LDI R7,R5 LSH -8,R7 LDI R6,R4 LSH -8,R6 AND 0FFH,R7 AND 0FFH,R6 AND 0FFH,R5 AND 0FFH,R4 *SEND LENGTH (BYTE 1 MSB) OR C_MAS|C_C2,R6 ; (C2=1) LS 16,R6 STI R6,*AR5 ;SEND C2 HIGH WITH DATA RPTS TIME_DELAY ;HOLD FOR A SEC NOP *SEND LENGTH (BYTE 2 LSB) OR C_MAS,R4 ; (C2=1) LS 16,R4 STI R4,*AR5 ;SEND C2 HIGH WITH DATA RPTS TIME_DELAY ;HOLD FOR A SEC NOP *SEND LENGTH (BYTE 3 MSB COMPLEMENTED) OR C_MAS|C_C2,R7 ; (C2=1) LS 16,R7 STI R7,*AR5 ;SEND C2 HIGH WITH DATA RPTS TIME_DELAY ;HOLD FOR A SEC NOP *SEND LENGTH (BYTE 4 LSB COMPLEMENTED) OR C_MAS,R5 LS 16,R5 STI R5,*AR5 ;SEND C2 LOW WITH DATA RPTS 65 NOP DEC AR6 LDI 0FFh,R4 * * SEND MASTERS BUFFER * LDI 0,R3 ;CHECKSUM *byte1 AND *AR2++,R4,R6 ADDI R6,R3 ;FORM CHECKSUM OR C_MAS|C_C2,R6 ;(C2=1) MSDLP LS 16,R6 STI R6,*AR5 RPTS TIME_DELAY NOP *byte2 AND *AR2++,R4,R6 ADDI R6,R3 OR C_MAS,R6 ;(C2=0) LS 16,R6 STI R6,*AR5 RPTS TIME_DELAY NOP DBUD AR6,MSDLP AND *AR2++,R4,R6 ADDI R6,R3 ;FORM CHECKSUM OR C_MAS|C_C2,R6 ; (C2=1) ;---->DBUD AR6,MSDLP ANDN C_MAS|C_C2,R6 ;ONE TOO MANY... SUBI R6,R3 *SEND THE CHECKSUM AND 0FFFFH,R3 ;MASK CKSUM TO 16 BITS LDI R3,R6 ;SEND MSB RS 8,R6 OR C_MAS|C_C2,R6 ;(C2=1) LS 16,R6 STI R6,*AR5 ;SEND 2 HIGH RPTS TIME_DELAY ;HOLD FOR A SEC NOP LS 24,R3 RS 24,R3 OR C_MAS,R3 ;(C2=0) LS 16,R3 STI R3,*AR5 ;SEND 2 HIGH RPTS TIME_DELAY ;HOLD FOR A SEC NOP LDI C_RCV,R0 ;CHANGE CONTROL TO RECEIVE LS 16,R0 STI R0,*+AR5(CTL) ;@COMM_CTL * * WAIT FOR SLAVE TO SIGNIFY DONE (C1=0) * LDI 30,R5 ;TIMEOUT CML1XX DEC R5 BLT CMERROR10 LDI *AR5,R0 RS 16,R0 TSTB C_C1,R0 BNZ CML1XX * * MASTER TELLS SLAVE IT IS LISTENING (C2=1) * LDI @RECEIVE_BUFFERI,AR2 ;SETUP RECEIVE BUFFER LDI C_C2|C_MAS,R0 ;SET C2=HI LS 16,R0 STI R0,*AR5 * GET SLAVES BUFFER LENGTH * BUFFER LENGTH IS X 2 * 4 BYTES LENGTH MSB, LSB, COMP MSB, COMP LSB * LDP COMM_IO LDI C_C1,R5 LS 16,R5 LDI 300,AR3 PWL2M TSTB @COMM_IO,R5 DBZ AR3,PWL2M TSTB 8000H,AR3 BNZD CMERROR1 ;ERROR IN TIMEOUT NOP LDI 300,AR3 LDI @COMM_IO,R7 ;GET MSB ;---->BNZD CMERROR1 PWL3M TSTB @COMM_IO,R5 DBNZ AR3,PWL3M TSTB 8000H,AR3 BNZD CMERROR2 ;ERROR IN TIMEOUT NOP LDI @COMM_IO,R6 ;GET LSB LS 8,R6 ;---->BNZD CMERROR2 LDI 300,AR3 PWL4M TSTB @COMM_IO,R5 DBZ AR3,PWL4M TSTB 8000H,AR3 BNZD CMERROR1 ;ERROR IN TIMEOUT NOP LDI 300,AR3 NOT @COMM_IO,R4 ;GET MSB COMPLEMENT ;---->BNZD CMERROR1 PWL5M TSTB @COMM_IO,R5 DBNZ AR3,PWL5M TSTB 8000H,AR3 BNZD CMERROR2 ;ERROR IN TIMEOUT NOP NOT @COMM_IO,R2 ;GET LSB COMPLEMENT LS 8,R2 ;---->BNZD CMERROR2 LS 8,R4 LS 8,R7 RS 24,R2 RS 24,R4 RS 24,R6 RS 24,R7 CMPI R2,R6 BNE CMERROR3 ;ERROR IN LENGTH CMPI R4,R7 BNE CMERROR3 ;ERROR IN LENGTH LSH 8,R7 ADDI R6,R7,AR6 CMPI 140H,AR6 ;LENGTH ERROR BGE CMERROR3 ;TOO LONG CMPI 0,AR6 ;SLAVE LENGTH ZERO... BEQ CMERROR3 DEC AR6 ;THIS IS THE LENGTH INDEX * * GET SLAVES BUFFER * SETDP STI AR6,@RBUFF_LEN LDP @COMM_IO CLRI R3 ;RESET CKSUM LDI 0FFH,R2 LSH 16,R2 LDI 300,AR3 WL2M TSTB @COMM_IO,R5 DBZ AR3,WL2M TSTB 8000H,AR3 BNZD CMERROR4 ;YES...QUIT LDI 300,AR3 NOP AND R2,*AR5,R6 ;----> BNZD CMERROR4 ADDI R6,R3 STI R6,*AR2++ WL3M TSTB *AR5,R5 DBNZ AR3,WL3M TSTB 8000H,AR3 BNZD CMERROR5 ;YES...QUIT NOP NOP AND R2,*AR5,R6 ;----> BNZD CMERROR5 DBUD AR6,WL2M ADDI R6,R3 STI R6,*AR2++ LDI 300,AR3 ;---->DBUD AR6,WL2M *GET SLAVES CKSUM WL2MC TSTB @COMM_IO,R5 DBZ AR3,WL2MC TSTB 8000H,AR3 BNZD CMERROR6 ;YES...QUIT NOP LDI 300,AR3 LDI @COMM_IO,R6 ;MSB CKSUM ;----> BNZD CMERROR6 WL3MC TSTB @COMM_IO,R5 DBNZ AR3,WL3MC TSTB 8000H,AR3 BNZD CMERROR7 ;YES...QUIT RS 8,R6 AND 0FF00h,R6 LDI @COMM_IO,R7 ;LSB CKSUM ;----> BNZD CMERROR7 RS 16,R7 AND 0FFh,R7 ADDI R6,R7 RS 16,R3 CMPI R7,R3 BNE CMERROR8 ;CKSUM ERROR M0LENGTH COMM_MASTER_X LDP @COMM_MASTER_TRANSES INCM @COMM_MASTER_TRANSES COMM_MASTER_ERR_X LDI C_MAS,R0 ;SET C2=0 LS 16,R0 STI R0,*AR5 LDI C_RCV,R0 ;SET DATA CONTROL TO RECEIVE LS 16,R0 STI R0,*+AR5(CTL) SETDP LDI 0,R0 STI R0,@COMMFLAG ;COMMUNICATIONS IS OVER EINT RETS .globl CMERROR1 CMERROR1 B COMM_MASTER_ERROR ;LENGTH TIMEOUT CMERROR2 B COMM_MASTER_ERROR ;LENGTH TIMEOUT CMERROR3 B COMM_MASTER_ERROR ;BAD LENGTH CMERROR4 B COMM_MASTER_ERROR ;DATA TIMEOUT CMERROR5 B COMM_MASTER_ERROR ;DATA TIMEOUT CMERROR6 B COMM_MASTER_ERROR ;CKSUM TIMEOUT CMERROR7 B COMM_MASTER_ERROR ;CKSUM TIMEOUT CMERROR8 B COMM_MASTER_ERROR ;BAD CKSUM CMERROR9 B COMM_MASTER_ERROR ;MASTER SEND TIMEOUT CMERROR10 B COMM_MASTER_ERROR ;MASTER END TIMEOUT (SLAVE ERR) CMERRORL B COMM_MASTER_ERROR ;LENGTH TOO LONG CMERRORDEAD LDI 1,R0 ;YES OTHER GAME IS DEAD, LEAVE... STI R0,@TRANSMISSION_DEAD B COMM_MASTER_ERROR ;WENT DEAD... COMM_MASTER_ERROR LDP @COMM_MASTER_TRANSES INCM @COMM_MASTER_ERROR_CNT SETDP LDI 0,R0 STI R0,@RBUFF_LEN ;RECEIVE BUFFER CLEARED ON ERROR ; LDI C_C2|C_MAS,R0 ;SET C2=HI ; LS 16,R0 ; STI R0,*AR5 B COMM_MASTER_ERR_X *---------------------------------------------------------------------------- *---------------------------------------------------------------------------- COMM_IRQ: PUSH ST PUSH DP PUSH R0 ANDN INT2_M,IF ;determine if I am a master being interrupted ; LDP @DIPRAM LDI @DIPRAM,R0 TSTB CMDP_MASTER,R0 BNZ DO_SLAVE_SYNC POP R0 POP DP POP ST RETI DO_SLAVE_SYNC: PUSH R1 PUSH IE LDI INT1_M|INT2_M,IE ;disable everything except TV30 interrupt & comm int ANDN INT2_M,IF ;we wont irq ourself LDP @CPU_WS LDI @CPU_WS,R0 PUSH R0 LDI SOFT_WS,R0 STI R0,@CPU_WS ;sync the systems... ; ; LDP @FIFO_CONTROL LDI @FIFO_CONTROL,R0 ANDN FIFO_CONTROL_DMA_RUNSEL,R0 STI R0,@FIFO_CONTROL WTLP LDI @FIFO_STATUS,R0 AND FIFO_STATUS_FD_CRITICAL,R0 BNZ WTLP ;same LDP @CRT_VCNT LDI @CRT_VCNT,R0 AND 1FFh,R0 ; CMPI 400,R0 ; LDIEQ 1b0h,R0 ; LDIGT 1b1h,R0 ; LDILT 1afh,R0 LDI 1B0H,R1 SUBI 400,R0 CMPI -1,R0 ;GRACE AREA DUDES LDILT 1afh,R1 CMPI 1,R0 LDIGT 1b1h,R1 STI R1,@CRT_VTTL LDI @FIFO_CONTROL,R0 OR FIFO_CONTROL_DMA_RUNSEL,R0 STI R0,@FIFO_CONTROL POP R0 LDP @CPU_WS STI R0,@CPU_WS POP IE POP R1 POP R0 POP DP ; LDI INT1_M|INT2_M|INT3_M|INT0_M,IE POP ST RETI *---------------------------------------------------------------------------- *---------------------------------------------------------------------------- *CALLED FROM THE MAIN LOOP * *SET C0 HIGH *WAIT FOR C2 TO GO HIGH *BEGIN TRANSFER *END OF TRANSFER *SET ALL LOW * * COMM_SLAVE: SETDP LDI @COMM_IOI,AR5 ;AR5=COMM I/O ADDRESS LDI @RECEIVE_BUFFERI,AR2 ;AR2=RECEIVE BUFFER LDI C_C2,R5 ;R5=C_C2 MASK LS 16,R5 *CHECK ONE PLAYER MODE LDI @ONEFLAG,R0 BZ CS1 RETS ;WE'RE IN ONE PLAYER, EXIT CS1 TSTB *AR5,R5 BZ CS2 ;C2=1, MASTER IN ONE PLAYER, EXIT LDI 0,R0 STI R0,@TRANSMISSION_DEAD STI R0,@TRANSMISSION_ACTIVE RETS *SYNC UP CS2 LDI 120,R3 ;WAIT 120 FRAMES IF NOT DEAD LDI @TRANSMISSION_DEAD,R0 ;GET TIMEOUT VALUES BZ CS20 LDI 1,R3 ;WAIT 1 IF DEAD ADDI @INFRAMES,R3 CMPI 4,R3 LDIGT 4,R3 CS20 LDI 1,R0 STI R0,@TRANSMISSION_ACTIVE LDI C_C0|C_SLA,R0 LS 16,R0 STI R0,*AR5 ;SEND C0=1 WTLPI CMPI @INFRAMES,R3 ;WAITING TOO LONG? BLE CSERRORDEAD ;YES, ITS DEAD... TSTB *AR5,R5 ;WAIT C2=1 BZ WTLPI LDI C_SLA,R0 ;SEND C0=0 LS 16,R0 STI R0,*AR5 LDI 0,R0 STI R0,@TRANSMISSION_DEAD LDI 10000,AR3 ;TIMEOUT VALUE WTLPI2 TSTB *AR5,R5 ;WAIT C2=0 DBNZ AR3,WTLPI2 TSTB 8000H,AR3 ;TIMEOUT? BZ CS3 ;NO RETS ;YES, LEAVE *END SYNC CS3 DINT *SET DATA CONTROL TO RECEIVE ;CM_A 1 LDI C_RCV,R0 LS 16,R0 STI R0,*+AR5(CTL) *TELL MASTER WE ARE LISTENING (C0=0,C1=1) LDI C_C1|C_SLA,R0 LS 16,R0 STI R0,*AR5 *GET MASTERS BUFFER LENGTH *BUFFER LENGTH IS X 2 *FIRST BYTE IS LENGTH *SECOND BYTE IS COMPLEMENT OF LENGTH LDP @COMM_IO LDI 300,AR3 PWL2 TSTB @COMM_IO,R5 DBZ AR3,PWL2 TSTB 8000H,AR3 BNZD CSERROR1 ;ERROR IN TIMEOUT NOP LDI 300,AR3 LDI @COMM_IO,R7 ;GET MSB ;---->BNZD CSERROR1 PWL3 TSTB @COMM_IO,R5 DBNZ AR3,PWL3 TSTB 8000H,AR3 BNZD CSERROR2 ;ERROR IN TIMEOUT NOP LDI @COMM_IO,R6 ;GET LSB LS 8,R6 ;---->BNZD CSERROR2 LDI 300,AR3 PWL4 TSTB @COMM_IO,R5 DBZ AR3,PWL4 TSTB 8000H,AR3 BNZD CSERROR1 ;ERROR IN TIMEOUT NOP LDI 300,AR3 NOT @COMM_IO,R4 ;GET MSB COMPLEMENT ;---->BNZD CSERROR1 PWL5 TSTB @COMM_IO,R5 DBNZ AR3,PWL5 TSTB 8000H,AR3 BNZD CSERROR2 ;ERROR IN TIMEOUT NOP NOT @COMM_IO,R2 ;GET LSB COMPLEMENT LS 8,R2 ;---->BND CSERROR2 LS 8,R4 LS 8,R7 RS 24,R2 RS 24,R4 RS 24,R6 RS 24,R7 CMPI R2,R6 BNE CSERROR3 ;ERROR IN LENGTH CMPI R4,R7 BNE CSERROR3 ;ERROR IN LENGTH LSH 8,R7 ADDI R6,R7,AR6 DEC AR6 ;THIS IS THE LENGTH INDEX CMPI 140H,AR6 ;LENGTH ERROR BGE CSERROR3 ;TOO LONG * *GET MASTERS BUFFER * SETDP STI AR6,@RBUFF_LEN LDP @COMM_IO CLRI R3 ;RESET CKSUM LDI 0FFH,R2 LSH 16,R2 LDI 300,AR3 WL2 TSTB @COMM_IO,R5 DBZ AR3,WL2 TSTB 8000H,AR3 BNZD CSERROR4 ;YES...QUIT LDI 300,AR3 NOP AND R2,*AR5,R6 ;----> BNZD CSERROR4 ;YES...QUIT ADDI R6,R3 STI R6,*AR2++ WL3 TSTB *AR5,R5 DBNZ AR3,WL3 TSTB 8000H,AR3 BNZD CSERROR5 ;YES...QUIT NOP NOP AND R2,*AR5,R6 ;----> BNZD CSERROR5 ;YES...QUIT DBUD AR6,WL2 ADDI R6,R3 STI R6,*AR2++ LDI 300,AR3 *GET MASTERS CKSUM WL2C TSTB @COMM_IO,R5 DBZ AR3,WL2C TSTB 8000H,AR3 BNZD CSERROR6 ;YES...QUIT NOP LDI 300,AR3 LDI @COMM_IO,R6 ;MSB CKSUM ;----> BNZD CSERROR6 ;YES...QUIT WL3C TSTB @COMM_IO,R5 DBNZ AR3,WL3C TSTB 8000H,AR3 BNZD CSERROR7 ;YES...QUIT RS 8,R6 AND 0FF00h,R6 LDI @COMM_IO,R7 ;LSB CKSUM ;----> BNZD CSERROR7 ;YES...QUIT RS 16,R7 AND 0FFh,R7 ADDI R6,R7 RS 16,R3 CMPI R7,R3 BNE CSERROR8 ;CKSUM ERROR * LOWER SLAVES C1 * (tell master we are prepared to send) * SETDP LDI C_SLA,R0 LS 16,R0 STI R0,*AR5 * * SLAVE SEND * * WAIT FOR MASTER TO LISTEN (C2=1) LDI 50,R5 ;TIMEOUT CML1S DEC R5 BLT CSERROR9 LDI *AR5,R0 RS 16,R0 TSTB C_C2,R0 BZ CML1S LDI C_SND,R0 ;CHANGE DATA BUFFER DIRECTION TO SEND LS 16,R0 STI R0,*+AR5(CTL) * SEND SLAVE LENGTH *SEND MESSAGE LENGTH TO MASTER *MESSAGE LENGTH IS MULTIPLE OF 2 SETDP LDI @SEND_BUFFER_A_LEN,R6 LDI @SEND_BUFFER_AI,AR2 ADDI R6,AR2,AR0 ;ADD 2 NULLS TO THE END DUDES LDI CB_NULL,R2 STI R2,*AR0 STI R2,*+AR0(1) ADDI 1,R6 RS 1,R6 LDI R6,AR6 NOT R6,R7 LDI R7,R5 LSH -8,R7 LDI R6,R4 LSH -8,R6 AND 0FFH,R7 AND 0FFH,R6 AND 0FFH,R5 AND 0FFH,R4 *SEND LENGTH (BYTE 1 MSB) OR C_SLA|C_C1,R6 ; (C2=1) LS 16,R6 STI R6,*AR5 ;SEND C2 HIGH WITH DATA RPTS TIME_DELAY ;HOLD FOR A SEC NOP *SEND LENGTH (BYTE 2 LSB) OR C_SLA,R4 ; (C2=1) LS 16,R4 STI R4,*AR5 ;SEND C2 HIGH WITH DATA RPTS TIME_DELAY ;HOLD FOR A SEC NOP *SEND LENGTH (BYTE 3 MSB COMPLEMENTED) OR C_SLA|C_C1,R7 ; (C2=1) LS 16,R7 STI R7,*AR5 ;SEND C2 HIGH WITH DATA RPTS TIME_DELAY ;HOLD FOR A SEC NOP *SEND LENGTH (BYTE 4 LSB COMPLEMENTED) OR C_SLA,R5 LS 16,R5 STI R5,*AR5 ;SEND C2 LOW WITH DATA RPTS 65 NOP DEC AR6 LDI 0FFh,R4 * * SLAVE SEND BUFFER TO MASTER * LDI 0,R3 ;CHECKSUM *byte1 AND *AR2++,R4,R6 ADDI R6,R3 ;FORM CHECKSUM OR C_SLA|C_C1,R6 ;(C1=1) SSDLP LS 16,R6 STI R6,*AR5 RPTS TIME_DELAY NOP *byte2 AND *AR2++,R4,R6 ADDI R6,R3 OR C_SLA,R6 ;(C1=0) LS 16,R6 STI R6,*AR5 RPTS TIME_DELAY NOP DBUD AR6,SSDLP AND *AR2++,R4,R6 ADDI R6,R3 ;FORM CHECKSUM OR C_SLA|C_C1,R6 ; (C2=1) ;---->DBUD AR6,SSDLP ANDN C_SLA|C_C1,R6 SUBI R6,R3 ;ONE OVER!!! *SEND THE CHECKSUM AND 0FFFFH,R3 ;MASK CKSUM TO 16 BITS LDI R3,R6 ;SEND MSB RS 8,R6 OR C_SLA|C_C1,R6 ;(C1=1) LS 16,R6 STI R6,*AR5 ;SEND DATA RPTS TIME_DELAY ;HOLD FOR A SEC NOP LS 24,R3 RS 24,R3 OR C_SLA,R3 ;(C1=0) LS 16,R3 STI R3,*AR5 ;SEND DATA RPTS TIME_DELAY ;HOLD FOR A SEC NOP *WAIT FOR MASTER TO INDICATE O.K. C2=0 LENGTHOF0 LDI 50,R5 ;TIMEOUT CML1WT DEC R5 BLT CSERROR11 LDI *AR5,R0 RS 16,R0 TSTB C_C2,R0 BNZ CML1WT COMM_SLAVE_X LDP @COMM_SLAVE_TRANSES INCM @COMM_SLAVE_TRANSES COMM_SLAVE_ERR_X SETDP LDI C_SLA,R0 ;SET C0=0,C1=0, NO ERROR LS 16,R0 STI R0,*AR5 LDI C_RCV,R0 ;CHANGE CONTROL TO RECEIVE LS 16,R0 STI R0,*+AR5(CTL) ;@COMM_CTL LDI 0,R0 STI R0,@COMMFLAG ;COMMUNICATIONS IS OVER EINT RETS CSERROR1 B COMM_SLAVE_ERROR ;LENGTH TIMEOUT CSERROR2 B COMM_SLAVE_ERROR ;LENGTH TIMEOUT CSERROR3 B COMM_SLAVE_ERROR ;BAD LENGTH CSERROR4 B COMM_SLAVE_ERROR ;DATA TIMEOUT CSERROR5 B COMM_SLAVE_ERROR ;DATA TIMEOUT CSERROR6 B COMM_SLAVE_ERROR ;CKSUM TIMEOUT CSERROR7 B COMM_SLAVE_ERROR ;CKSUM TIMEOUT CSERROR8 B COMM_SLAVE_ERROR ;BAD CKSUM CSERROR9 B COMM_SLAVE_ERROR ;SLAVE SEND TIMEOUT CSERROR11 B COMM_SLAVE_ERROR ;MASTER ERROR END TIMEOUT CSERRORDEAD LDI 1,R0 ;YES OTHER GAME IS DEAD, LEAVE... STI R0,@TRANSMISSION_DEAD B COMM_SLAVE_ERROR ;WENT DEAD... COMM_SLAVE_ERROR LDP @COMM_SLAVE_ERROR_CNT INCM @COMM_SLAVE_ERROR_CNT SETDP LDI 0,R0 STI R0,@RBUFF_LEN ;RECEIVE BUFFER CLEARED ON ERROR BU COMM_SLAVE_ERR_X *---------------------------------------------------------------------------- .END