;THIS PROGRAM CONTROLS THE LINE ;CONCENTRATOR FOR 6 LINES AND ;31 STATIONS. IT IS TARGETED ;FOR AN 8749 AT 10.00 MHZ. ;CALL CONCENTRATOR TBLPHN.ASM ;VERSION 1.0 MARCH 8,1987 ;BY BILL HEIDEMAN ;INTERNAL DATA TMCT0 EQU 32 ;8.0 MSEC TIMER CNTR MATRIX EQU 33 ;CROSS POINT MATRIX (32) SWTNEW EQU 65 ;NEW SWITCH VALUES (4) SWTLST EQU 69 ;LAST SWITCH VALUES (4) SWTVAL EQU 73 ;DEBOUNCED SWITCH (4) DIPSWT EQU 77 ;DIP SWITCH VALUES ATDLFG EQU 78 ;AUTO DIAL ON FLG ANSFLG EQU 79 ;STATION ANSWR FLG (4) DBOUT EQU 83 ;DATA BUS OUTPUT WORD ANSWR EQU 84 ;ANSWR BUFFER WRITE PNTR ANSBUF EQU 85 ;STATIONS ANSWERED BUFF (23) DSPOT EQU 108 ;CARD READER OUTPUT BUF (5) DSPCNT EQU 113 ;BUFFER COUNTER STAPTR EQU 114 ;STATION POINTER TONCNT EQU 115 ;CARD READER TONE COUNT BUFPTR EQU 116 ;AUTO DIAL BUFFER PNTR CODSEL EQU 117 ;LINE CODE TO DIAL PASTMR EQU 118 ;PAUSE TIMER LINSEL EQU 119 ;LINE IN PROCESS (BIT PATTERN) STASEL EQU 120 ;STATION IN PROCESS (BINARY) P1SAV EQU 121 ;P1 PORT SAVER OPTLST EQU 122 ;OPTO LAST VALUE (2) OPTVAL EQU 124 ;OPTO DEBN VALUE (2) TMTGL EQU 126 ;.25 MSEC TIMER TMCT1 EQU 127 ;50 MSEC TIMER ; F1 AUTO DIAL TOGGLE BIT ORG 000H RESTRT: JMP MAIN ;MAIN RESET ORG 002H DB 17H ;IDENT BYTE ORG 003H EXTI: RETR ;EXTERNAL INTER ;THIS IS THE REAL TIME CLOCK, ALL REAL ;TIME EVENTS ARE CALLED FROM HERE. ORG 007H TINT: SEL RB1 MOV R7,A ;SAVE ACC MOV A,#0FBH ;RESET TIMER TO .25 MSEC MOV T,A STRT T ;RESET TIMER ORL P2,#18H ;DISABLE MATRIX IN A,P1 MOV R0,#P1SAV MOV @R0,A ;SAVE P1 CALL DSOT ;DO CARD READER OUTPUT MOV R0,#TMTGL MOV A,@R0 INC @R0 ;INCR .25 MSEC TIMER JB0 TINT1 ;IF ODD TIME MOV R0,#TMCT0 INC @R0 ;INCR TIMER MOV A,@R0 ANL A,#0FH JNZ TINT1 ;IF NOT 8 MSEC CALL SWRD ;READ HOOK SWITCHES CALL SWDB ;DO SWITCH DEBN MOV R0,#TMCT0 MOV A,@R0 ANL A,#3FH JNZ TINT1 ;JUMP IF NOT 32 MSEC MOV A,@R0 SWAP A RR A RR A ANL A,#3 ;FORM POINTER ADD A,#JMPTBL JMPP @A ;DO JUMP JMPTBL: DB ANSJMP DB LNCJMP DB TONJMP DB BSYJMP ANSJMP: CALL ANSW ;DO ANSWER JMP TINT1 LNCJMP: CALL LNCN ;DO LINE CONNECT JMP TINT1 TONJMP: CALL TONE ;DO TONE OUTPUT JMP TINT1 BSYJMP: CALL BSYC ;DO BUSY CONNECT TINT1: MOV R0,#TMCT1 INC @R0 MOV A,@R0 XRL A,#0B8H JNZ TINT2 ;IF NOT 50 MSEC MOV @R0,A ;RESET TIMER CALL ATDL ;DO AUTO DIAL TINT2: MOV R0,#DSPCNT MOV A,@R0 XRL A,#120 JNZ TINT3 ;IF NOT TRAIL "0" CALL CDRD ;DO CARD READ CALL FKTN ;DO FAKE TONE TINT3: MOV R0,#P1SAV MOV A,@R0 ORL A,#0F0H OUTL P1,A ;RESTORE P1 MOV A,R7 ;RESTORE ACC RETR ;THIS IS THE MAIN LOOP, ALL NON TIME ;CRITICAL FUNCTIONS ARE CALLED FROM ;HERE. MAIN: MOV R0,#10H CLR A MOV R2,#112 ;CLEAR ALL RAM MAIN1: MOV @R0,A INC R0 DJNZ R2,MAIN1 MOV A,#0F0H OUTL P1,A ;SET UP PORTS MOV A,#18H OUTL P2,A MOV R0,#CODSEL MOV @R0,#0FFH ;SET UP CODE SEL MOV R0,#DSPOT MOV @R0,#1 ;SET FIRST SCAN MOV A,#0C4H ;START TIMER MOV T,A STRT T EN TCNTI MAIN2: CALL MXCN ;DO MATRIX CONNECT JMP MAIN2 ;THIS ROUTINE CONVERTS THE BINARY ;KEY NUMBERS INTO ROW/COL FORMAT. RCTBL: DB 28H ;0 DB 11H ;1 DB 21H ;2 DB 41H ;3 DB 12H ;4 DB 22H ;5 DB 42H ;6 DB 14H ;7 DB 24H ;8 DB 44H ;9 DB 28H ;0 DB 18H ;* DB 48H ;# RCCONV: ADD A,#RCTBL ;ADD TABLE OFFSET MOVP A,@A ;READ TABLE RET ;THIS ROUTINE GENERATES THE FAKE TONES ;WHEN A CARD IS ENTERED INTO THE CARD ;READER. IT IS CALLED DURING THE TRAILING ;0 FIELD. (REAL TIME). FKTN: MOV R0,#TONCNT MOV A,@R0 JZ FKTN2 ;IF NOT ACTIVE DEC A MOV @R0,A ;UPDATE COUNTER JB0 FKTN2 ;DO PAUSE MOV R2,#50 MOV R0,#10H FKTN1: ADD A,@R0 ;FORM TONE PNTR INC R0 ;FROM GARBAGE DJNZ R2,FKTN1 ANL A,#7 ;LIMIT BOUNDS ADD A,#RCTBL MOVP A,@A ;READ TONE TABLE CPL A MOV R0,#DSPOT+3 MOV @R0,A ;WRITE TONE VALUE RET FKTN2: MOV R0,#DSPOT+3 MOV @R0,#0FFH ;CLEAR TONE RET ;THIS ROUTINE CONNECTS THE CROSS POINT ;SWITCHES ACCORDING TO THE SWITCH MATRIX. ;IT IS CALLED FROM MAIN. ORG 100H MXCN: MOV R1,#MATRIX MOV R3,#0 ;BIT COUNT MOV R4,#1 ;BIT MASK MOV R5,#0 ;CHIP SELECT ORL P2,#18H ;DISABLE SELECTS ANL P2,#0F8H ;WRITE CHIP SEL MXCN1: MOV A,#0F0H ;SET BIT SELECT ORL A,R3 OUTL P1,A MOV A,@R1 ;GET MATRIX DATA ANL A,R4 ;FIND BIT JNZ MXCN6 ;IF SET ANL P2,#7FH ;SET DATA=0 MXCN2: MOV A,R5 JB3 MXCN9 ;IF UPPER MUX ANL P2,#0F7H ;STROBE LOWER ORL P2,#18H MXCNA: MOV A,R3 ;SET BIT COUNT ADD A,#4 MOV R3,A XRL A,#19 JZ MXCN7 ;IF CHIP DONE MOV A,R3 JB4 MXCN4 ;IF COLUMN DONE MXCN3: MOV A,R4 RL A MOV R4,A ;ROTATE BIT MASK JMP MXCN1 MXCN4: INC R1 ;INCR MEM PNTR MOV A,#0F1H ADD A,R3 MOV R3,A ;SUBTRACT 15 MOV A,R5 JB0 MXCN5 ;IF ODD CHIP SEL MOV R4,#1 JMP MXCN1 MXCN5: MOV R4,#10H ;SET UP UPPER JMP MXCN1 MXCN6: ORL P2,#80H ;SET DATA=1 JMP MXCN2 MXCN7: INC R5 ;INCR CHIP SEL MOV R3,#0 ;RESET BIT COUNT ANL P2,#0F8H MOV A,R5 CPL A JB0 MXCNZ ;IF NO 1'S ORL P2,#1 MXCNZ: JB1 MXCNY ;IF NO 2'S ORL P2,#2 MXCNY: JB2 MXCNX ;IF NO 4'S ORL P2,#4 MXCNX: MOV A,R5 XRL A,#0FH JNZ MXCNB ;IF NOT DONE RET MXCNB: MOV A,R5 JB0 MXCN8 ;IF ODD SELECT INC R1 ;INCR MEM PNTR MOV R4,#1 JMP MXCN1 MXCN8: DEC R1 ;RESET MEM PNTR DEC R1 DEC R1 MOV R4,#10H JMP MXCN1 MXCN9: ANL P2,#0EFH ;STROBE UPPER ORL P2,#18H JMP MXCNA ;THIS ROUTINE READS THE HOOK AND DIP ;SWITCHES AND FORMATS THEM INTO BYTE ;VALUES. IT IS CALLED EVERY 8 MSEC. SWRD: MOV R1,#SWTNEW CLR A MOV R3,A MOV R4,A MOV R5,A ;CLEAR TEMPORARY DATA SWRD1: MOV A,R5 ORL A,#0F0H ;SET UP ADDR OUTL P1,A IN A,P1 SWAP A ANL A,#1 ;READ LOWER DATA ORL A,R3 ;OR WITH LAST BIT RL A MOV R3,A IN A,P1 SWAP A RL A ANL A,#1 ;READ UPPER DATA ORL A,R4 ;OR WITH LAST RL A MOV R4,A INC R5 ;INCR COUNTER MOV A,R5 JB4 SWRD2 ;IF ALL DONE XRL A,#8 JNZ SWRD1 ;IF NOT DONE MOV A,R3 MOV @R1,A ;WRITE D1 TO D8 INC R1 MOV A,R4 MOV @R1,A ;WRITE D9 TO D16 CLR A MOV R3,A ;CLEAR TEMPORARY MOV R4,A JMP SWRD1 SWRD2: INC R1 MOV A,R3 MOV @R1,A ;WRITE D17 TO D24 INC R1 MOV A,R4 MOV @R1,A ;WRITE D18 TO D32 RET ;THIS ROUTINE READS THE DIP SWITCHES AND FORMS ;THEM INTO A SINGLE BYTE. IT IS CALLED EVERY ;32 MSEC. DPRD: MOV R1,#DIPSWT MOV R5,#0F0H MOV R3,#0 DPRD1: MOV A,R5 OUTL P1,A ;WRITE ADDR IN A,P1 RL A ANL A,#1 ;READ DATA ORL A,R3 RL A MOV R3,A ;SAVE READ INC R5 MOV A,R5 CPL A JB3 DPRD1 ;IF NOT DONE MOV A,R3 MOV @R1,A ;WRITE RESULT RET ;THIS ROUTINE DEBOUNCES THE SWITCH DATA ;WITH THE TWO EQUAL READ METHOD. IT IS ;CALLED EVERY 8 MSEC. ORG 200H SWDB: MOV R0,#SWTNEW MOV R1,#SWTLST MOV A,@R0 XRL A,@R1 ;XRL NEW AND LAST MOV R3,A INC R0 INC R1 MOV A,@R0 XRL A,@R1 MOV R4,A ;DO OTHERS INC R0 INC R1 MOV A,@R0 XRL A,@R1 MOV R5,A INC R0 INC R1 MOV A,@R0 XRL A,@R1 MOV R6,A MOV R0,#SWTVAL ;ANL VALUE WITH XOR MOV A,@R0 ANL A,R3 MOV @R0,A INC R0 MOV A,@R0 ANL A,R4 MOV @R0,A INC R0 MOV A,@R0 ANL A,R5 MOV @R0,A INC R0 MOV A,@R0 ANL A,R6 MOV @R0,A MOV R0,#SWTNEW MOV R1,#SWTVAL MOV A,R3 CPL A ANL A,@R0 ;ANL NEW WITH CAP XOR ORL A,@R1 ;OR IN VALUE MOV @R1,A INC R0 INC R1 MOV A,R4 CPL A ANL A,@R0 ORL A,@R1 MOV @R1,A INC R0 INC R1 MOV A,R5 CPL A ANL A,@R0 ORL A,@R1 MOV @R1,A INC R0 INC R1 MOV A,R6 CPL A ANL A,@R0 ORL A,@R1 MOV @R1,A MOV R0,#SWTNEW MOV R1,#SWTLST MOV R2,#4 SWDB1: MOV A,@R0 ;UPDATE LAST VALUES MOV @R1,A INC R0 INC R1 DJNZ R2,SWDB1 RET ;THIS ROUTINE ANSW THE REQUESTING ;STATIONS AND PLACES THEM ONTO TO ;THE ANSWER STACK. IT ALSO TAKES ;CARE OF ABBANDONNED CALLS. IT IS ;CALLED EVERY 128 MSEC. ANSW: MOV R6,#0 ;LAP COUNTER MOV R5,#1 ;BIT MASK MOV R4,#SWTVAL MOV R1,#ANSFLG ANSW1: MOV A,R4 MOV R0,A MOV A,@R0 ;READ SWITCH VAL ANL A,R5 JZ ANSW5 ;IF NOT OFF HOOK MOV A,@R1 ANL A,R5 JZ ANSW4 ;JUMP IF NOT ANSW ANSW2: MOV A,R5 ;SET UP NEXT RL A MOV R5,A CPL A JB0 ANSW3 ;JUMP IF OVER INC R1 INC R4 ANSW3: INC R6 MOV A,R6 XRL A,#31 JNZ ANSW1 ;JUMP IF NOT DONE RET ANSW4: JT1 ANSWA ;IF NO CARD READER MOV A,R6 ADD A,#0F1H JC ANSWA ;IF NO CARD SLOT MOV A,R6 RL A SWAP A ANL A,#3 ;FORM BYTE PNTR ADD A,#OPTVAL MOV R0,A MOV A,@R0 ;READ OPTO DATA ANL A,R5 JZ ANSW2 ;IF NO CARD IN ANSWA: MOV R0,#ANSWR MOV A,@R0 ;GET WRITE PNTR MOV R2,A ;SAVE XRL A,#23 JZ ANSW8 ;IF STACK OVER FLOW INC @R0 ;INCR WRITE PNTR MOV A,@R1 ;SET ANS FLG ORL A,R5 MOV @R1,A ADD A,#ANSBUF MOV R0,A MOV A,R6 MOV @R0,A ;WRITE STATION TO STACK JMP ANSW2 ANSW5: MOV A,@R1 ANL A,R5 JZ ANSW2 ;JUMP IF NOT ANSWRED MOV A,R5 CPL A ANL A,@R1 MOV @R1,A ;CLEAR ANSWRED MOV A,R6 ADD A,#MATRIX MOV R0,A MOV @R0,#0 ;DISCONNECT LINE MOV R0,#ANSWR MOV A,@R0 JZ ANSW2 ;IF NO BUFFER ADD A,#ANSBUF ;SET UP LIMIT MOV R2,A ;R2 HAS WRITE PNTR MOV R0,#ANSBUF ANSW6: MOV A,@R0 ;READ STACK XRL A,R6 JZ ANSW7 ;JUMP IF ON STACK INC R0 ;INCR BUFFER PNTR MOV A,R0 XRL A,R2 JNZ ANSW6 ;JUMP IF NOT DONE JMP ANSW2 ANSW7: INC R0 MOV A,@R0 ;FIX UP STACK DEC R0 MOV @R0,A INC R0 MOV A,R0 XRL A,R2 JNZ ANSW7 ;JUMP IF NOT DONE MOV R0,#ANSWR MOV A,@R0 DEC A MOV @R0,A ;DECR WRITE PNTR JMP ANSW2 ANSW8: MOV A,R6 ADD A,#MATRIX MOV R0,A MOV @R0,#40H ;SET LINE TO BUSY JMP ANSW2 ;THIS IS THE TABLE FOR THE SPECIAL ;STATION CODES. IT IS FOR TESTING ;ONLY. THE ACTUAL TABLE MUST BE ;OVERLAYED. ORG 300H CODTBL: DB 0CH,1,0,1,0,0,1,0BH DB 0CH,1,0,1,0,0,2,0BH DB 0CH,1,0,1,0,0,3,0BH DB 0CH,1,0,1,0,0,4,0BH DB 0CH,1,0,1,0,0,5,0BH DB 0CH,1,0,1,0,0,6,0BH DB 0CH,1,0,1,0,0,7,0BH DB 0CH,1,0,1,0,0,8,0BH DB 0CH,1,0,1,0,0,9,0BH DB 0CH,1,0,1,0,1,0,0BH DB 0CH,1,0,1,0,1,1,0BH DB 0CH,1,0,1,0,1,2,0BH DB 0CH,1,0,1,0,1,3,0BH DB 0CH,1,0,1,0,1,4,0BH DB 0CH,1,0,1,0,1,5,0BH DB 0CH,1,0,1,0,1,6,0BH DB 0CH,1,0,1,0,1,7,0BH DB 0CH,1,0,1,0,1,8,0BH DB 0CH,1,0,1,0,1,9,0BH DB 0CH,1,0,1,0,2,0,0BH DB 0CH,1,0,1,0,2,1,0BH DB 0CH,1,0,1,0,2,2,0BH DB 0CH,1,0,1,0,2,3,0BH DB 0CH,1,0,1,0,2,4,0BH DB 0CH,1,0,1,0,2,5,0BH DB 0CH,1,0,1,0,2,6,0BH DB 0CH,1,0,1,0,2,7,0BH DB 0CH,1,0,1,0,2,8,0BH DB 0CH,1,0,1,0,2,9,0BH DB 0CH,1,0,1,0,3,0,0BH DB 0CH,1,0,1,0,3,1,0BH ;THIS ROUTINE FORMS THE STATION TABLE ;POINTER FROM THE STATION NUMBER. IT ;IS CALLED FROM LNCN (REAL TIME). ORG 400H TBPT: MOV R2,A ;SAVE COUNT JZ TBPT2 ;IF NO OFFSET CLR A TBPT1: ADD A,#8 ;FOR EACH COUNT DJNZ R2,TBPT1 TBPT2: RET ;THIS ROUTINE READS THE SWITCH MATRIX ;AND DETERMINES IF A LINE IS BUSY. LNST: MOV R0,#MATRIX MOV R2,#32 CLR A LNST1: ORL A,@R0 INC R0 DJNZ R2,LNST1 ;IF NOT DONE MOV R2,A ;SAVE MOV R0,#DIPSWT MOV A,@R0 ANL A,#7 ;AND OFF GARBAGE MOV R3,A ;SET UP CNTR JNZ LNST2 ;IF >0 MOV R3,#1 LNST2: CLR A CLR C CPL C ;SET UP MASK LNST3: RLC A CPL C DJNZ R3,LNST3 ;FORM ENA MASK CPL A ORL A,R2 ORL A,#0C0H ;FORM DIS MASK RET ;0=OPEN ;THIS ROUTINE HANDLES THE STATIONS ;FROM THE ANSWER STACK. IT IS CALLED ;EVERY 128 MSEC. LNCN: MOV R0,#PASTMR MOV A,@R0 JZ LNCN1 ;IF TIMER OFF RET LNCN1: MOV R0,#ATDLFG MOV A,@R0 JNZ LNCN6 ;IF AUTO DIAL ON MOV R0,#ANSWR MOV A,@R0 JNZ LNCN2 ;IF STACK ON RET LNCN2: CALL LNST ;GET LINE STATUS ANL A,#3FH MOV R2,A ;SAVE LINE STATUS XRL A,#3FH JNZ LNCN3 ;IF LINE AVAIL RET LNCN3: MOV A,R2 CALL LNFM ;FORM LINE CONNECT MOV R0,#ANSBUF MOV A,@R0 ;READ STATION TO ANS MOV R4,A ;SAVE MOV R0,#STASEL MOV @R0,A ;WRITE STATION SEL MOV A,R4 CALL TBPT ;FORM TABLE CNTR MOV R0,#CODSEL MOV @R0,A ;SAVE WHICH LINE CALL STKP ;UPDATE STACK MOV R0,#ATDLFG ;SET AUTO DIAL MOV @R0,#0FFH MOV R0,#PASTMR MOV @R0,#5 ;SET PAUSE TIMER MOV R0,#LINSEL ;CONNECT TO STA 32 MOV A,@R0 MOV R0,#MATRIX+31 MOV @R0,A RET LNCN6: MOV @R0,#0 ;CLEAR AUTO DIAL MOV R0,#MATRIX+31 MOV @R0,#0 ;CLEAR FROM STA 32 MOV R0,#STASEL MOV A,@R0 MOV R2,A ;SAVE STATION SEL RR A RR A RR A ANL A,#3 ADD A,#ANSFLG MOV R0,A MOV A,@R0 XCH A,R2 ;R2 HAS ANSFLG ANL A,#7 XCH A,R2 INC R2 LNCN7: RRC A DJNZ R2,LNCN7 JNC LNCN8 ;IF NOT ANS CALL STCN LNCN8: RET ;THIS ROUTINE ROTATES THE STACK BY ONE ;POSITION WHEN CALLED FROM LNCN (REAL ;(TIME). STKP: MOV R0,#ANSBUF+1 MOV R2,#24 STKP1: MOV A,@R0 DEC R0 MOV @R0,A INC R0 INC R0 DJNZ R2,STKP1 MOV R0,#ANSWR MOV A,@R0 DEC A MOV @R0,A ;DECR WRITE PNTR RET ;THIS ROUTINE DOES THE STATION CONNECT ORG 500H STCN: MOV R0,#LINSEL MOV A,@R0 MOV R2,A MOV R0,#STASEL MOV A,@R0 ;CONNECT LINE TO STA ADD A,#MATRIX MOV R0,A MOV A,R2 MOV @R0,A RET ;THIS ROUTINE FORMS THE LINE SELECT ;BIT PATTERN. LNFM: MOV R2,#80H LNFM1: XCH A,R2 RL A XCH A,R2 RRC A JC LNFM1 ;IF USED MOV R0,#LINSEL MOV A,R2 MOV @R0,A ;WRITE SELECT RET ;THIS ROUTINE DOES THE AUTO DIAL. IT ;IS CALLED EVERY 128 MSEC. ATDL: MOV R0,#PASTMR MOV A,@R0 JNZ ATDL1 ;IF TIMER ON RET ATDL1: XRL A,#1 JZ ATDL2 ;IF TIMER=1 MOV A,@R0 DEC A MOV @R0,A ;DECR TIMER RET ATDL2: CPL F1 JF1 ATDL3 ;IF TIME EVEN MOV R0,#DBOUT MOV A,@R0 ANL A,#80H MOV @R0,A OUTL BUS,A ;WRITE 0 TO ENCODER RET ATDL3: MOV R0,#BUFPTR MOV A,@R0 XRL A,#8 JNZ ATDL4 ;IF NOT DONE MOV R0,#PASTMR MOV @R0,#0 ;CLEAR PAUSE TIMER MOV R0,#BUFPTR MOV @R0,#0 ;CLEAR PNTR MOV R0,#CODSEL MOV @R0,#0FFH ;RESET CODE SELECT RET ATDL4: MOV A,@R0 INC @R0 MOV R0,#CODSEL ADD A,@R0 ;FORM PNTR MOVP3 A,@A ;READ TABLE CALL RCCONV ;DO R/C CONV MOV R2,A MOV R0,#DBOUT MOV A,@R0 ANL A,#80H ORL A,R2 ;OR IN NEW MOV @R0,A OUTL BUS,A RET ;THIS ROUTINE CONNECTS THE OVER FLOW ;STATIONS TO THE BUSY LINE. IT IS ;CALLED EVERY 128 MSEC. BSYC: CALL LNST ;GET LINE STATUS ANL A,#3FH MOV R2,#6 MOV R3,#0 ;# OF UNUSED LINES BSYC1: RRC A JC BSYC2 ;IF LINE IN USE INC R3 BSYC2: DJNZ R2,BSYC1 MOV R1,#ANSBUF MOV R0,#ANSWR MOV A,@R0 JZ BSYC6 ;IF NO STACK ADD A,#ANSBUF MOV R4,A ;FORM UPPER LIM BSYC4: MOV A,R3 JZ BSYC5 ;IF UNUSED=0 DEC R3 INC R1 MOV A,R1 XRL A,R4 JNZ BSYC4 ;IF STILL IN STACK RET BSYC5: MOV A,@R1 ;READ STAT ADD A,#MATRIX MOV R0,A MOV @R0,#40H ;SET BUSY INC R1 MOV R0,#ANSWR MOV A,@R0 ADD A,#ANSBUF XRL A,R1 JNZ BSYC5 ;IF NOT ALL BSYC6: RET ;THIS ROUTINE TOGGLES THE BUSY TONE ;WHEN CALLED EVERY 128 MSEC. TONE: MOV R0,#DBOUT MOV A,@R0 XRL A,#80H MOV @R0,A OUTL BUS,A RET ;THIS ROUTINE OUTPUTS THE SERIAL BITS ;TO THE 5451 DISPLAY CHIP. IT IS CALLED ;EVERY 0.25 MSEC FROM THE REAL TIME ;CLOCK. DSOT: MOV R0,#DSPCNT MOV A,@R0 INC @R0 ;INCR COUNTER MOV R5,A ;SAVE COUNTER JB0 DSOT3 ;IF ODD TIME ANL P2,#0BFH ;SET CLOCK=0 XRL A,#144 JZ DSOT5 ;JUMP IF COUNT=144 MOV A,R5 ADD A,#0B9H JC DSOT2 ;JUMP IF COUNT>70 MOV A,R5 CLR C RRC A ;DIVIDE BY TWO DEC A ;ADJUST FOR LEADING 0 RR A RR A RR A ANL A,#7 ;FORM BYTE COUNTER ADD A,#DSPOT MOV R0,A MOV A,R5 RR A ;DIVIDE BY TWO ANL A,#7 ;SET UP LOOP COUNTER MOV R2,A JNZ DSOT0 ;JUMP IF COUNT NOT 0 MOV R2,#8 ;SET LOOP FOR 8 DSOT0: MOV A,@R0 DSOT1: RRC A DJNZ R2,DSOT1 ;FIND BIT JC DSOT4 ;JUMP IF BIT=1 DSOT2: ANL P2,#0DFH ;SET DATA=0 RET DSOT3: ORL P2,#40H ;SET CLOCK=1 RET DSOT4: ORL P2,#20H ;SET DATA=1 RET DSOT5: MOV @R0,#1 ;RESET COUNTER ORL P2,#20H ;SET START BIT RET ;THIS ROUTINE MANAGES THE SCANNING DATA ;FROM THE CARD READER. IT IS CALLED ;DURING THE TRAILING 0 FIELD (REAL TIME). ORG 600H CDRD: MOV R1,#STAPTR MOV A,@R1 RL A SWAP A ANL A,#3 ;FORM OFFSET MOV R5,A ;SAVE OFFSET MOV A,@R1 ;FORM BIT MASK ANL A,#7 MOV R4,A INC R4 MOV A,#80H ;FIND BIT CDRD1: RL A DJNZ R4,CDRD1 MOV R4,A ;SAVE BIT MASK JT0 CDRD2 ;IF CARD IN CLR A CDRD2: MOV R6,A ;SAVE NEW DATA MOV A,#OPTLST ADD A,R5 MOV R0,A MOV A,@R0 ;READ LAST DATA ANL A,R4 XRL A,R6 JZ CDRD6 ;IF NEW=LAST MOV A,R4 CPL A ANL A,@R0 ;UPDATE LAST ORL A,R6 MOV @R0,A CDRD4: MOV R0,#DSPOT CLR A MOV @R0,A INC R0 MOV @R0,A INC R0 MOV @R0,A ;CLEAR OLD DATA MOV A,@R1 INC A ;INCR STATION PNTR MOV @R1,A XRL A,#15 JNZ CDRD5 ;IF NO OVER FLOW MOV @R1,#0 ;RESET PNTR MOV R0,#DSPOT MOV @R0,#1 ;SET UP FIRST STAT RET CDRD5: MOV A,@R1 RL A SWAP A ANL A,#3 ;FORM DSPOT OFFSET ADD A,#DSPOT MOV R0,A MOV A,R4 RL A MOV @R0,A ;WRITE NEW DATA RET CDRD6: MOV A,#OPTVAL ADD A,R5 MOV R0,A MOV A,@R0 ;READ OPTO VALUE ANL A,R4 XRL A,R6 JZ CDRD4 ;IF NEW=VALUE MOV A,R4 CPL A ANL A,@R0 ORL A,R6 ;UPDATE VALUE MOV @R0,A JT0 CDRD7 ;IF CARD IN MOV R0,#TONCNT MOV @R0,#4 ;SET CARD OUT TONES JMP CDRD4 CDRD7: MOV R0,#TONCNT MOV @R0,#20 ;SET CARD IN TONES JMP CDRD4 END