; THIS PROGRAM IS THE CONTROL FOR THE ; 4 LINE CALL ANNOUNCER WITH 2 MINUTE ; MESSAGES. IT IS TARGETED ; FOR AN 8749 RUNNING AT 10.00 MHZ. ; MDA4.ASM BY BILL HEIDEMAN ; VERSION 1.9 NOVEMBER 23,1987 ;***************************************** ; VARIABLES COMCHN EQU 36 ;REMOTE LINE (PRODUCT) LINCNT EQU 4 ;NUMBER OF PHONE LINES RNGDLY EQU 3 ;RING DELAY ; ;***************************************** ; DECLARED DATA TMCT0 EQU 32 ;TIMER COUNTER 0 MATRIX EQU 33 ;CROSS POINT MATRIX (8) DSPOT EQU 41 ;DISPLAY OUTPUT (4) SWITCH EQU 45 ;RAW SWITCH DATA DSPCNT EQU 46 ;DISPLAY BYTE CNTR HVAL EQU 47 ;RAW H LINE VALUE TMCT1 EQU 48 ;TIMER 1 (.5 SEC) HPHAS EQU 49 ;H LINE DEBOUNE CNTR (6) RPHAS EQU 55 ;RING PHASE CNTR (6) RNGCTR EQU 61 ;RING COUNTERS (6) HNGTMR EQU 67 ;HANG-UP DELAY TIMER ;SPARES 68-72 TTLTMR EQU 73 ;TOTAL LINE DISP TMR MATPTR EQU 74 ;MATRIX POINTER DISBLK EQU 75 ;DISPLAY BLANK WORD ; D0=202P READING ; D1=VOICE CODSWT EQU 76 ;CODE SWITCH TONEIN EQU 77 ;INCOMING KEY FROM 202P'S TTLCNT EQU 78 ;TOTAL LINE DISP CNTR PARTAL EQU 79 ;PARTIAL MESSAGE LINES SWTCHG EQU 80 ;CHANGED SWITCH VALUES SWTDCD EQU 81 ;DECODED SWITCH VALUES ; D0=OFF ; D1=RECORD ; D2=ANSWER ; D3=(SPARE) ; D4=32K REPEAT ; D5=32K ; D6=16K HLDEB EQU 82 ;DEBOUNCED H LINES HANGUP EQU 83 ;HANG-UP REQUEST FLGS RECDAT EQU 84 ;VOICE SET-UP DATA ; D3-D0=PHASE ; D5-D4=(SPARE) ; D6=STOP FLAG ; D7=RECORD FLAG SWTLST EQU 85 ;LAST SWITCH READ VALUE SWTDEB EQU 86 ;DEBOUNCED SWITCH VALUE ANSPHS EQU 87 ;ANSWER PHASE TONPHS EQU 88 ;TONE PHASE REPAUS EQU 89 ;REPLAY PAUSE TIMER ; D3-D0=PAUSE BEFORE REPLAY ; D7-D4=PAUSE BEFORE INT ENABLE ;******************************************** ; THESE VALUES MUST STAY TOGETHER CALTTL EQU 90 ;TOTAL CALLS (2 BCD) MINTTL EQU 92 ;TOTAL MINUTES (2 BCD) LINTTL EQU 94 ;TOTAL LINES (2 BCD BY 4) ACTTTL EQU 102 ;TOTAL ACTIVE LINES (2 BCD) ;******************************************** RESCNT EQU 104 ;STAT RESET CNTR RECDON EQU 105 ;RECORDING UPDATED LNSTUS EQU 106 ;LINE STATUS (8) ; 0=IDLE ; D0=RINGING ; D1=ANWERED ; D2=INUSE RECTIM EQU 114 ;RECORDING TIME BCD (2) VOCMD EQU 116 ;VOICE MONITOR COMMAND ; D0=PLAY ; D1=RECORD ; D2=STOP ; D3=REMOTE ; D4=REPEAT ;******************************************* ; THESE VALUES MUST STAY TOGETHER ANSDLY EQU 117 ;ANSWER MONITOR DELAY TONDLY EQU 118 ;TONE MONITOR DELAY RESTMR EQU 119 ;STAT RESET TIMER ;******************************************* VOCBNK EQU 120 ;WHICH VOICE BANK IS ON ; D4 AND D5 SWTOLD EQU 121 ;OLD SWITCH COMMAND REMOTE EQU 122 ;REMOTE MODE FLAG VOCON EQU 123 ;VOICE IS ON FLG ; FF=RECORD ; FE=PLAY PLYTMR EQU 124 ;PLAY TIMER (2) RECTMR EQU 126 ;RECORD TIMER (2) ;F0 READ FLAG ;F1 DISPLAY 1'S ;R7 POWER UP DELAY ;R7' ACC SAVER ;R6' REPEAT DELAY TIMER ;THIS IS THE MAIN RESTART FROM POWER-UP ORG 000H RESTRT: JMP MAIN ;THIS IS THE VERSION IDENTIFIER ORG 002H DB 19H ;VERSION BYTE ;THIS ROUTINE IS THE HARDWARE INTERRUPT ORG 003H EXINT: SEL RB1 MOV R7,A ;STORE STATUS JMP EXNT ;THIS ROUTINE IS THE REAL TIME CLOCK. ;IT IS CALLED EVERY 2 MSEC FROM AN ;INTERNAL TIMER. ORG 007H TMR: SEL RB1 MOV R7,A ;SAVE STATUS MOV A,#0D8H ;RESET TIMER TO 2 MSEC MOV T,A STRT T CALL HLRD ;DO H LINE FILTER MOV R0,#TMCT0 INC @R0 ;INCR TIMER MOV A,@R0 ANL A,#0FH JNZ TMR2 ;IF NOT 32 MSEC CALL DLYS ;DO MONITOR DELAYS CALL VCTM ;DO VOCIE TIMERS CALL SWDB ;DO SWITCH DEBOUNCE MOV R0,#TMCT0 MOV A,@R0 ANL A,#3FH JNZ TMR2 ;IF NOT 128 MSEC CALL RGDT CALL ACTV ;DO ACTIVE LINE CALC CALL PWRP ;DO POWER UP DELAY TMR2: MOV R0,#TMCT0 MOV A,@R0 JNZ TMR4 ;IF NOT .5 SEC MOV R0,#TMCT1 INC @R0 ;INCR .5 SEC TIMER MOV A,@R0 XRL A,#120 JNZ TMR4 ;IF NOT 60 SEC MOV @R0,A ;CLEAR COUNTER CALL MINT ;DO MINUTES TOTAL TMR4: MOV A,R7 RETR ;THIS IS THE MAIN LINE ROUTINE FROM WHICH ALL ;NON TIME CRITICAL ROUTINES ARE CALLED. MAIN: MOV R2,#112 CLR A MOV R0,#10H MAIN1: MOV @R0,A ;CLEAR DATA INC R0 DJNZ R2,MAIN1 OUTL BUS,A ;TURN OFF DISPLAY MOV A,#2CH OUTL P2,A ;INITIALIZE P2 ORL P2,#10H ;RESET VOICE MOV A,#0C0H OUTL P1,A ;INITIALIZE P1 CLR F1 CPL F1 ;SET FLASHING 1'S MOV R0,#ACTTTL+1 MOV @R0,#0FFH ;SET TO BLANK MOV R0,#TTLCNT MOV @R0,#3 ;PRESET COUNT MOV R0,#RECTMR MOV @R0,#80H ;SET FAKE TIME MOV R7,#80H ;SET POWER UP FLAG MOV A,#0FAH MOV T,A STRT T EN TCNTI MAIN2: CALL DSOT ;DO DISPLAY OUTPUT CALL HLIN ;DO H LINE INPUT CALL DGRD ;DO 202P READ CALL VCCT ;DO VOICE CONTROL CALL SWMN ;DO SWITCH MONITOR CALL DSMN ;DO DISPLAY MONITOR CALL ANSW ;DO ANSWER MONITOR CALL VCMN ;DO VOICE MONITOR CALL TNDC ;DO REMOTE TONE DECODE CALL INCK ;DO INTERRUPT CHECK MOV A,T ADD A,#4 JC MAIN2 ;IF TIMER ALMOST UP CALL MXCN ;DO MATRIX CONNECT CALL HNGP ;DO HANG-UP JMP MAIN2 ;THIS ROUTINE IS THE TIMER FOR THE VOICE ;RECORDING. IT IS CALLED EVERY 32 MSEC. VCTM: MOV R1,#VOCON MOV A,@R1 JNZ VCTM1 ;IF VOICE ON MOV A,R6 JZ VCTM0 ;IF REPLAY DELAY OFF DEC R6 RET VCTM0: MOV R0,#REPAUS MOV A,@R0 ANL A,#0FH JZ VCTM7 ;IF REPLAY TIMER OFF DEC A MOV @R0,A ;DECR TIMER JNZ VCTM7 ;IF NOT UP MOV R0,#VOCMD MOV @R0,#1 ;SET PLAY RET VCTM1: MOV R0,#REPAUS MOV A,@R0 ANL A,#0F0H JZ VCTMA ;IF TIMER OFF MOV A,@R0 SWAP A DEC A SWAP A MOV @R0,A ;DECR TIMER VCTMA: MOV A,@R1 INC A JZ VCTM4 ;IF RECORD SET VCTMB: MOV R0,#PLYTMR MOV A,@R0 DEC A MOV @R0,A ;DECR LSB JNZ VCTM3 ;IF NOT 0 INC R0 MOV A,@R0 JZ VCTM2 ;IF TIME UP DEC A MOV @R0,A ;DECR UPPER RET VCTM2: MOV R0,#VOCMD MOV A,@R0 ORL A,#4 ;SET STOP MOV @R0,A MOV R0,#HNGTMR MOV A,@R0 CPL A JB7 VCTMZ ;IF TIMER NOT ARMED MOV @R0,#48 ;SET HANG-UP TIMER VCTMZ: MOV @R1,#0 ;TURN OFF VOICE DIS I CPL A JB4 VCTM3 ;IF REPEAT NOT ON MOV R6,#63 ;SET REPEAT DELAY VCTM3: RET VCTM4: MOV R0,#RECTMR MOV A,@R0 INC A MOV @R0,A ;INCR LSB JNZ VCTM5 ;IF NO O.F. INC R0 INC @R0 ;INCR MSB VCTM5: MOV R0,#RECTMR MOV A,@R0 ANL A,#1FH JNZ VCTM3 ;IF ODD TIME MOV R0,#RECTIM MOV A,@R0 ADD A,#99H ;SUBTR 1 DA A MOV @R0,A JC VCTM3 ;IF NO UNDER FLOW INC R0 MOV A,@R0 JZ VCTM6 ;IF DONE DEC A MOV @R0,A ;FIX UPPER RET VCTM6: DEC R0 MOV @R0,#0 ;FIX UP LSB MOV R0,#REMOTE MOV A,@R0 JNZ VCTM8 ;IF REMOTE REC MOV R0,#VOCMD MOV @R0,#6 ;SET STOP REC VCTM7: RET VCTM8: MOV R0,#TONEIN MOV @R0,#0CH ;SET FAKE STOP RET ;THIS ROUTINE CALCULATES THE TOTAL ;NUMBER OF ACTIVE LINES ON THE MACHINE ;AT THE PRESENT TIME. IT IS CALLED EVERY ;128 MSEC. ACTV: MOV R0,#LNSTUS MOV R2,#LINCNT MOV R3,#0F0H ;SET RESULT ACTV1: MOV A,@R0 CPL A JB1 ACTV2 ;IF NOT ANSWERED INC R3 ACTV2: INC R0 DJNZ R2,ACTV1 ;DO REST MOV R0,#ACTTTL MOV A,R3 MOV @R0,A ;WRITE RESULT RET ;THIS ROUTINE CALCULATES THE TOTAL MINUTES ;THAT ANY LINES ARE ON THE UNIT. IT IS CALLED ;EVERY 60 SECONDS. MINT: MOV R1,#LNSTUS MOV R0,#MINTTL MOV R2,#LINCNT MINT1: MOV A,@R1 ;GET STATUS ANL A,#6 JZ MINT2 ;IF NOT ON MACH CALL INCB ;INCR TOTAL MINT2: INC R1 DJNZ R2,MINT1 ;DO REST RET ;THIS ROUTINE TAKES CARE OF THE MONITOR ;DELAY TIMERS. IF THEY ARE NOT 0, THEY ;ARE DECR TO 0. IT IS CALLED EVERY 32 MSEC. DLYS: MOV R0,#ANSDLY MOV R2,#3 DLYS1: MOV A,@R0 JZ DLYS2 ;IF TIMER=0 DEC A MOV @R0,A ;DECR TIMER DLYS2: INC R0 DJNZ R2,DLYS1 ;DO REST MOV R0,#RESTMR MOV A,@R0 JNZ DLYS3 ;IF TIMER ON MOV R0,#RESCNT MOV @R0,#0 ;CLEAR CNTR DLYS3: MOV R0,#TTLTMR INC @R0 ;INCR TOTAL DISP TMR RET ;THIS ROUTINE READS THE RAW H LINES AND ;DEBOUNCES THEM FOR RING DETECTION. IT ;INCLUDES FAST RING DETECT AND IN USE ;DETECT. ITI IS CALLED EVERY 2 MSEC FROM ;THE REAL TIME CLOCK. HLRD: MOV R5,#1 ;BIT MASK MOV R4,#0 ;LOOP CNTR MOV R1,#HPHAS HLRD0: MOV R0,#HVAL MOV A,@R0 ;GET RAW H LINES ANL A,R5 JZ HLRD5 ;IF HL=0 MOV A,@R1 JB7 HLRD3 ;IF HL WAS 1 HLRD1: MOV @R1,#80H ;SET UP UP HLRD2: INC R4 INC R1 MOV A,R5 RL A MOV R5,A MOV A,R4 XRL A,#LINCNT JNZ HLRD0 ;IF NOT DONE RET HLRD3: XRL A,#0A8H JZ HLRD4 ;UPCNT=80 MSEC MOV A,@R1 INC A ;INCR TIMER JZ HLRD2 ;IF OVERFLOW MOV @R1,A XRL A,#0A0H JZ HLRD8 ;IF JUST MAXED JMP HLRD2 HLRD4: MOV R0,#HLDEB ;SET H VALUE MOV A,@R0 ORL A,R5 MOV @R0,A INC @R1 ;INCR TIMER JMP HLRD2 HLRD5: MOV A,@R1 JB7 HLRD7 ;IF LINE WAS UP INC A ;INCR DOWN TIMER JB7 HLRD2 ;IF OVERFLOW MOV @R1,A MOV R0,#HLDEB MOV A,R5 ;CLEAR H VALUE CPL A ANL A,@R0 MOV @R0,A JMP HLRD2 HLRD7: MOV @R1,#0 ;SET UP DOWN ADD A,#220 JNC HLRD2 ;IF UP<30 MSEC HLRD8: MOV A,#LNSTUS ADD A,R4 MOV R0,A MOV A,@R0 CPL A JB2 HLRD2 ;IF NOT IN USE MOV R0,#HANGUP MOV A,@R0 ORL A,R5 ;SET HANG-UP MOV @R0,A JMP HLRD2 ;THIS ROUTINE DETERMINES IF A LINE IS ;RINGING FROM THE DEBOUNCED H LINE VALUES. ;IT ALSO COUNTS THE RINGS. IT IS CALLED ;EVERY 128 MSEC FROM THE REAL TIME CLOCK. RGDT: MOV R5,#1 ;BIT MASK MOV R4,#0 ;LOOP CNTR MOV R1,#RPHAS RGDT1: MOV R0,#HLDEB MOV A,@R0 ANL A,R5 JZ RGDT5 ;IF H VAL=0 MOV A,@R1 JB7 RGDT3 ;IF H VAL WAS 1 MOV @R1,#80H ;SET UP UP RGDT2: INC R1 INC R4 MOV A,R5 RL A MOV R5,A MOV A,R4 XRL A,#LINCNT JNZ RGDT1 ;IF NOT DONE RET RGDT3: INC A JZ RGDT2 ;IF OVER FLOW MOV @R1,A XRL A,#0A8H JNZ RGDT2 ;IF UP<>5 SEC RGDT4: MOV R0,#HANGUP MOV A,@R0 ORL A,R5 ;SET HANG-UP MOV @R0,A JMP RGDT2 RGDT5: MOV A,@R1 JB7 RGDT6 ;IF H VAL WAS 1 INC A JB7 RGDT2 ;IF DOWN=MAX MOV @R1,A XRL A,#2 JNZ RGDTZ ;IF NOT .25 SEC MOV A,#LNSTUS ADD A,R4 MOV R0,A MOV A,@R0 JB1 RGDT2 ;IF LINE ANSW MOV @R0,#1 ;SET RING MOV A,#RNGCTR ADD A,R4 MOV R0,A INC @R0 ;INCR RING CNTR JMP RGDT2 RGDTZ: MOV A,@R1 XRL A,#24 JNZ RGDT2 ;IF NOT 2.5 SEC MOV A,#LNSTUS ADD A,R4 MOV R0,A MOV @R0,#7 ;SET IN USE MOV A,#RNGCTR ADD A,R4 MOV R0,A MOV @R0,#0 ;CLEAR RING CNTR JMP RGDT2 RGDT6: MOV @R1,#0 ;SET UP DOWN JMP RGDT2 ;THIS ROUTINE OUTPUTS THE DISPLAY DATA TO ;THE 4 DIGIT DISPLAY. IT IS CALLED FROM ;MAIN. ORG 200H DSOT: MOV R0,#DISBLK MOV A,@R0 JZ DSOT1 ;IF NO DISP BLANK RET DSOT1: MOV R1,#DSPCNT MOV A,@R1 ADD A,#DSPOT MOV R0,A ;FORM DATA PNTR MOV A,@R0 ;GET DISP DATA MOV R2,A MOV A,@R1 INC A ;FORM DIGIT SELECT MOV R3,A MOV A,#8 DSOT2: RL A DJNZ R3,DSOT2 ;FORM BIT MOV R3,A ;SAVE SELECT ORL A,R2 ;OR IN DATA OUTL BUS,A ;WRITE TO DISPLAY MOV R0,#TMCT0 MOV A,@R0 ;SYNC DISP TO TIME RR A ANL A,#3 MOV @R1,A ;WRITE DIGIT SELECT MOV R0,#SWITCH MOV A,R3 SWAP A ;GET SELECT JNT1 DSOT3 ;IF SWITCH SET CPL A ANL A,@R0 ;CLEAR BIT MOV @R0,A ;WRITE RESULT RET DSOT3: ORL A,@R0 ;SET BIT MOV @R0,A RET ;THIS ROUTINE READS THE DATA FROM THE 202P'S. ;IT IS CALLED FROM MAIN. DGRD: IN A,P1 CPL A JB7 DGRD2 ;IF NO DATA VALID JF0 DGRD1 ;IF DATA READ CPL F0 ;SET DATA READ MOV R0,#DISBLK MOV A,@R0 ORL A,#1 ;SET DIAPLAY BLANK MOV @R0,A MOVX A,@R0 ;SET BUS TO INPUT INS A,BUS MOV R0,#CODSWT ANL A,#0FH MOV @R0,A ;STORE CODE SWITCH ORL P2,#40H ;SET ENA HIGH INS A,BUS ;READ 202'S MOV R0,#TONEIN ANL A,#0FH MOV @R0,A ANL P2,#0BFH ;CLEAR ENA'S DGRD1: RET DGRD2: CLR F0 ;CLEAR DATA READ MOV R0,#DISBLK MOV A,@R0 JB0 DGRD3 ;IF DIS BLANK RET DGRD3: ANL A,#0FEH ;CLEAR DIS BLANK MOV @R0,A RET ;THIS ROUTINE WRITE THE DATA OUT TO THE CROSS ;POINT MATRIX. IT IS CALLED FROM MAIN. MXCN: MOV R1,#MATPTR MOV A,@R1 RR A RR A ANL A,#7 ;MASK BYTE ADD A,#MATRIX MOV R0,A MOV A,@R0 ;READ MATRIX MOV R5,A ;SAVE MOV A,@R1 ;READ CNTR ANL A,#0FH MOV R3,A MOV R4,#4 MXCN1: ANL P2,#7FH ;CLEAR DATA MOV A,R5 RRC A MOV R5,A JNC MXCN2 ;IF DATA=0 ORL P2,#80H ;SET DATA MXCN2: MOV R0,#VOCBNK MOV A,@R0 ;GET BANK SELECT ORL A,R3 ;SET ADDR ORL A,#0C0H ;SET INPUTS OUTL P1,A ORL P2,#1 ANL P2,#0FEH ;PULSE LOWER MXCN3: INC @R1 ;INCR BIT CNTR INC R3 ;INCR ADDR DJNZ R4,MXCN1 ;IF NOT ALL BITS MOV A,#LINCNT RL A RL A ;FORM LIMIT XRL A,@R1 JZ MXCN4 ;LIMIT POINTER RET MXCN4: MOV @R1,A RET ;THIS ROUTINE READS IN THE RAW H LINE DATA ;TO HVAL. IT IS CALLED FROM MAIN. ;**************** LINE COUNT DEPENDENT ***** HLIN: MOV R2,#8 ;SET BIT MASK MOV R3,#0 ;CLEAR RESULT MOV R4,#LINCNT ;SET LOOP CNTR HLIN1: DEC R4 IN A,P1 ANL A,#0F0H ;MASK OLD SELECT ORL A,R4 ;OR IN NEW ORL A,#0C0H ;SET INPUTS OUTL P1,A ;WRITE OUT INC R4 JNT0 HLIN2 ;IF T0=0 MOV A,R2 ;SET BIT ORL A,R3 MOV R3,A ;SAVE RESULT HLIN2: MOV A,R2 RR A MOV R2,A ;ROTATE MASK DJNZ R4,HLIN1 ;LOOP IF NOT DONE MOV R0,#HVAL MOV A,R3 MOV @R0,A ;UPDATE HVAL RET ;THIS ROUTINE CHECKS TO SEE IF THE START ;BUTTON HAS BEEN PRESSED 3 TIMES WITHIN ;A SHORT TIME TO RESET STATS. IT IS CALLED ;FROM SWMN (MAIN). RSCK: MOV A,R6 JB0 RSCK1 ;IF SW3 IS OFF CLR F1 ;CLEAR DUMMY 1'S MOV R0,#TTLCNT MOV A,@R0 INC A ANL A,#3 ;INCR TOTAL DISP CNT MOV @R0,A MOV R0,#TTLTMR MOV @R0,#0 ;SYNC TIMER MOV R0,#RESCNT MOV A,@R0 INC @R0 ;INCR CNTR MOV R0,#RESTMR JNZ RSCK2 ;IF COUNTER ON MOV @R0,#50 ;SET TIMER RSCK1: RET RSCK2: MOV R2,A ;SAVE COUNT MOV A,@R0 JZ RSCK4 ;IF TIME IS UP MOV A,R2 XRL A,#2 JNZ RSCK1 ;IF COUNT NOT UP MOV R0,#CALTTL CLR A MOV R2,#12 RSCK3: MOV @R0,A ;CLEAR ALL STATS INC R0 DJNZ R2,RSCK3 RET RSCK4: MOV R0,#RESCNT MOV @R0,#0 ;CLEAR CNTR RET ;THIS IS THE TABLE FOR DE-SCRAMBLING THE ;CODE SWITCH INPUT. IT IS USED BY TNDC (MAIN). ORG 300H CODTBL: DB 0 DB 2 DB 1 DB 3 DB 8 ;4 DB 0AH DB 9 DB 0BH DB 4 ;8 DB 6 DB 5 DB 7 ;THIS TABLE IS THE DECODING FOR THE FRONT ;PANEL SWITCHES. SWTTBL: DB 01H ;OLD 3 DB 01H ;3 DB 14H ;5 DB 12H ;7 DB 44H ;9 DB 42H ;B DB 24H ;D DB 22H ;F ;THIS ROUTINE IS THE INTERFACE TO THE VOICE ;CHIP. IT IS CALLED FROM MAIN. VCCT: MOV R1,#RECDAT MOV A,@R1 JNZ VCCT1 ;IF VOICE 1 ON RET VCCT1: MOV R2,A ANL A,#0FH DEC A JZ VCCTE ;IF=1 DEC A JZ VCCTC ;IF=2 DEC A JZ VCCTB ;IF=3 DEC A JZ VCCTA ;IF=4 MOV A,R2 ANL A,#0FH XRL A,#0FH JZ VCCT3 ;IF=15 VCCT2: MOV A,R2 DEC A MOV @R1,A ;DECR PHASE ANL A,#0FH JNZ VCCTZ ;IF NOT DONE MOV @R1,A ;SET DONE MOV R0,#DISBLK MOV A,@R0 ANL A,#0FDH ;CLEAR DISPLAY BLK MOV @R0,A VCCTZ: RET VCCT3: ANL P2,#0EFH ;SET RESET MOV R0,#DISBLK MOV A,@R0 ORL A,#2 ;SET DISP BLANK MOV @R0,A ORL P2,#10H ;CLEAR RESET JMP VCCT2 VCCT6: NOP OUTL BUS,A ;WRITE DATA ANL P2,#0FBH ;STROBE VOICE 1 NOP NOP NOP NOP ;WAIT FOR COMMAND ORL P2,#0CH ;RESET /WR'S JMP VCCT2 VCCT9: CLR A JMP VCCT6 VCCTA: MOV A,R2 CPL A JB7 VCCT9 ;IF PLAY SET MOV A,#80H ;SET RECORD MOV R7,#0 ;CLEAR POWER-UP JMP VCCT6 VCCTB: MOV R0,#SWTDCD MOV A,@R0 JB6 VCCTD ;IF 16K SET MOV A,#53H ;SET 32K SPEED JMP VCCT6 VCCTC: MOV A,#10H ;SET START JMP VCCT6 VCCTD: MOV A,#52H ;SET 16K SPEED JMP VCCT6 VCCTE: MOV A,R2 CPL A JB6 VCCT2 ;IF NOT STOP MOV A,#20H ;SET STOP JMP VCCT6 ;THIS ROUTINE DEBOUNCES THE FRONT PANEL ;SWITCHES. IT IS CALLED EVERY 32 MSEC ;FROM THE REAL TIME CLOCK. SWDB: MOV R0,#SWITCH MOV R1,#SWTLST MOV A,@R0 MOV R2,A ;SAVE PRESENT XRL A,@R1 JZ SWDB1 ;IF OLD=NEW MOV A,R2 MOV @R1,A ;UPDATE OLD RET SWDB1: MOV R0,#SWTDEB MOV A,R2 MOV @R0,A ;UPDATE VALUE RET ;THIS ROUTINE INCREMENTS A 2 BYTE BCD NUMBER ;AS SET IN R0. IT IS REENTERANT. INCB: MOV A,@R0 ADD A,#1 DA A MOV @R0,A ;INCR LSB JC INCB1 ;IF OVERFLOW RET INCB1: INC R0 MOV A,@R0 ADD A,#1 DA A MOV @R0,A RET ;THIS ROUTINE CHECKS THE POWER UP DELAY ;TIMER AND IF ACTIVE DECREMENTS IT TO 0. ;IT IS CALLED EVERY 128 MSEC. PWRP: SEL RB0 MOV A,R7 JZ PWRP1 ;IF TIMER OFF ANL A,#7FH JZ PWRP1 ;IF TIME UP DEC A ORL A,#80H ;RESET POWER UP MOV R7,A ;STORE PWRP1: SEL RB1 MOV R0,#HNGTMR MOV A,@R0 JB7 PWRP2 ;IF TIMER ARMED JZ PWRP2 ;IF TIMER OFF MOV R2,A ;SAVE TIME MOV R0,#VOCON MOV A,@R0 JNZ PWRP3 ;IF VOICE ON MOV A,R2 ;GET TIME DEC A MOV R0,#HNGTMR MOV @R0,A ;DECR TIMER JNZ PWRP2 ;IF TIMER STILL ON MOV R0,#HANGUP MOV A,@R0 ORL A,#8 ;SET HANG-UP MOV @R0,A PWRP2: RET PWRP3: MOV R0,#HNGTMR MOV