; V0.262 3-WAY PROGRAM CUSTOM MADE FOR ANY AREA
; 31 July 1994 By Ronald L. Gibson
; ADDED "PASSCODE_2"
; BIT PORT ADDRESSES *
;
; PORT A: INPUT ADDRESS (EXTERNAL #4000H) (SHADOW = #1EH) (DATA ONLY)
; PORT A: OUTPUT ADDRESS (EXTERNAL #4000H) (SHADOW = #1FH) (DATA ONLY)
; PORT B INPUT #20H (EXTERNAL #6000H) (SHADOW = #20H)
DTMFR BIT 00H ;PORT B: DTMF RECEIVER: STROBE OUTPUT
RING BIT 01H ;PORT B: RING DETECTOR: INPUT
CPC BIT 02H ;PORT B: PHONE LINE: CHECKS LINE CONDITION, INPUT
;NOT USED BIT 03H ;PORT B:
;NOT USED BIT 04H ;PORT B:
;NOT USED BIT 05H ;PORT B:
;NOT USED BIT 06H ;PORT B:
;NOT USED BIT 07H ;PORT B:
; PORT B OUTPUT #21H (EXTERNAL #6000H) (SHADOW = #21H)
RELAY BIT 08H ;PORT B: RELAY CONNECTS TO ANSWERING MACHINE (OPTION)
MF_G BIT 09H ;PORT B: MF GENERATOR: STROBE INPUT
SWITCHHOOK BIT 0AH ;PORT B: TELEPHONE SWITCHHOOK: OUTPUT
CALLPROG BIT 0BH ;PORT B: CALL PROGRESS GENERATOR: STROBE OUTPUT
DTMFG BIT 0CH ;PORT B: DTMF GENERATOR: STROBE INPUT
;NOT USED BIT 0DH ;PORT B:
;NOT USED BIT 0EH ;PORT B:
;NOT USED BIT 0FH ;PORT B:
; * MISC. FLAGS *
; "STATUS" IMPORTANT BIT FLAG ADDRESSES * (SHADOW = #22H)
_400HZ BIT 10H ;400Hz DIALTONE IS USED (COULD BE MOVED IF NEEDED)
INIT_AC BIT 11H ;RAM IS INITIALIZED FOR LOCAL AREA CODE
INIT_PREFIX BIT 12H ;AT LEAST ONE PREFIX IS PROGRAMMED IN
LOG_OVERFLOW BIT 13H ;EXTERNAL RAM IS FULL OF HISTORY DATA
INIT_LOCAL BIT 14H ;RAM IS INITIALIZED FOR LOCAL PREFIX
N_LOCAL BIT 15H ;LOCAL CALLING IS TURNED OFF
RLY_OPT BIT 16H ;RELAY TO ANSWERING MACHINE OPTION ACTIVE
SECURITY BIT 17H ;TURNS ON SECURITY ACCESS CODE
; "STATUS" TIME RELATED BIT FLAG ADDRESSES * (SHADOW = #23H)
COUNT BIT 18H ;COUNT1 & COUNT2 = ZERO
COUNT_ONE BIT 19H ;ONE COUNT IS REMAINMNG ON COUNT1
TIMEOUT BIT 1AH ;TOTAL TIMEOUT OF CALL HAS REACHED ZERO
TIMEOUT_ONE BIT 1BH ;ONE COUNT LEFT FOR TIMEOUT1 & TIMEOUT2
NEW_LN BIT 1CH ;NEW LINE OF CODE. DETECTING ":"
TIMED_OUT BIT 1DH ;SET IF TIMED OUT WHILE IN WAIT_DIGIT
;NOT USED BIT 1EH
;NOT USED BIT 1FH
; "MORE STATUS" BIT FLAG ADDRESSES * (SHADOW = #24H)
KEY BIT 20H ;KEYBOARD ENTRY
KEYS BIT 21H ;KEY PRESSED, USED WITH KEYDELAY
VALID_DATA BIT 22H ;SET AFTER KEYDELAY VALID & STAYS VALID WHILE PRESSED
DUP BIT 23H ;DUPLICATE AREA CODE FOUND
DSP_DELAY BIT 24H ;SET WHEN WAITING FOR TIMER 1 INTERRUPT (DISPLAY)
ELEVEN BIT 25H ;ELEVEN DIGITS DIALED
NEW_DATA BIT 26H ;FIRST TIME COLLECTING DATA AT TURN ON
MF BIT 27H ;MF DIALING IN PROGRESS
; "MORE STATUS" BIT FLAG ADDRESSES * (SHADOW = #25H)
OK_NUMBER BIT 28H ;PHONE NUMBER IS LOCAL
POUND BIT 29H ;POUND "#" WAS DIALED
STAR BIT 2AH ;STAR "*" WAS DIALED
XFER_OK BIT 2BH ;FILE TRANSFER OK FLAG
E2_HL BIT 2CH ;EEPROM HIGH OR LOW TO BE PROGRAMMED
D_TEMP_F BIT 2DH ;WHAT HALF OF DATA IS BEING PROCESSED
TX_DPTR BIT 2EH ;TRANSMIT EXTERNAL DATA
TX_END BIT 2FH ;END OF TRANSMISSION
; "MORE STATUS" BIT FLAG ADDRESSES * (SHADOW = #26H)
RX_CR BIT 30H ;CARRIGE RETURN DETECTED
RX_BUFF_FULL BIT 31H ;RECEIVE BUFFER FULL
FIX_DONE BIT 32H ;TELLS WHEN "FIX" HAS DETECTED THE END OF THE STRING
;NOT USED BIT 33H
PASSCODE_NOT BIT 34H ;IF A PASSCODE IS VALID
;NOT USED BIT 35H
;NOT USED BIT 36H
;NOT USED BIT 37H
;NOT USED BIT 38-77H ;#27-2EH
; "MORE STATUS" BIT FLAG ADDRESSES * (SHADOW = #2FH)
AC_BIT BIT 78H ;CHECK WHILE ROLLING FOR SCANNING AREA CODE BITS
;NOT_USED BIT 79-7EH
CLOCK_BUSY BIT 7FH ;CHECKS FOR CLOCK BUSY
; CALL PROGRESS GENERATOR TONE VALUES *
DIALTONE EQU 00 ;VALUE FOR DIAL TONE
TONE400 EQU 10H ;VALUE FOR 400Hz TONE
TONE440 EQU 20H ;VALUE FOR 440Hz TONE
RINGTONE EQU 30H ;VALUE FOR RING SIGNAL
TONE4_6 EQU 40H ;VALUE FOR 440Hz & 620Hz
TONE480 EQU 50H ;VALUE FOR 480Hz TONE
BUSYTONE EQU 60H ;VALUE FOR THE BUSY SIGNAL
TONE350 EQU 70H ;VALUE FOR 350Hz TONE
TONE620 EQU 80H ;VALUE FOR 620Hz TONE
ASTERISK EQU 90H ;VALUE FOR THE DTMF "*"
; * MEMORY MAP (EXTERNAL RAM ADDRESSES) *
; 0000-0011H AREA CODE TABLE (AREACODE_LIST)
; 0012-0018H PASSCODE_1 (ACCESS_CODE)
; 0019-0020H (NOT USED)
; 0021H IMPORTANT REGISTER TO SAVE 21H PORT B OUTPUT
; 0020-00FFH (NOT USED)
; 0100-0200H VALID PATTERN AAH SHOWING GOOD DATA IN MEMORY (DON'T ERASE)
; 0201-0211H (NOT USED)
; 0212-09AAH LOCAL PREFIX LIST
; 09AB-7FFFH HISTORY OF CALLS (426)
; * EXTERNAL I/O ADDRESSES *
AREACODE_LIST EQU 0000H ;AREA CODE LIST STARTING ADDRESS
PASSCODE_1 EQU 0012H ;PASSCODE/ACCESS CODE STORAGE
REGISTERS EQU 001FH ;8051 REGISTERS 1F-30H (EXTERNAL STORAGE)
REGISTERS_END EQU 0030H ;LAST OF THE REGISTERS
PREFIX_BASE EQU 0211H ;LOCAL PREFIX BASE ADDRESS
LOG_BASE EQU 09ABH ;FIXED CALL HISTORY BASE ADDRESS
LOG_END EQU 7FF2H ;FIXED ABSOLUTE END OF CALL HISTORY
PORTAX EQU 0A000H ;PORT A EXTERNAL ADDRESS
PORTBX EQU 0B000H ;PORT B EXTERNAL ADDRESS
PORTCX EQU 0C000H ;PORT C EXTERNAL ADDRESS
KEYBOARD EQU 0D000H ;KEYBOARD EXTERNAL ADDRESS
DISPLAY_R EQU 0E000H ;DISPLAY REGISTER (SETUP) EXTERNAL ADDRESS
DISPLAY EQU 0E001H ;DISPLAY DATA EXTERNAL ADDRESS
SECONDS EQU 0F000H ;CLOCK SECONDS
SECONDS_ALARM EQU 0F001H ;CLOCK SECONDS ALARM
MINUTES EQU 0F002H ;CLOCK MINUTES
MINUTES_ALARM EQU 0F003H ;CLOCK MINUTES ALARM
HOURS EQU 0F004H ;CLOCK HOURS
HOURS_ALARM EQU 0F005H ;CLOCK HOURS ALARM
DAY_OF_WEEK EQU 0F006H ;CLOCK DAY OF WEEK
DAY_OF_MONTH EQU 0F007H ;CLOCK DAY OF MONTH
MONTH EQU 0F008H ;CLOCK MONTH
YEAR EQU 0F009H ;CLOCK YEAR
CLOCK_A EQU 0F00AH ;CLOCK REGISTER A
CLOCK_B EQU 0F00BH ;CLOCK REGISTER B
CLOCK_C EQU 0F00CH ;CLOCK REGISTER C
CLOCK_D EQU 0F00DH ;CLOCK REGISTER D
CLOCK_RAM EQU 0F00EH ;STARTING OF 50-BYTES OF RAM IN CLOCK
CLOCK_RAM_END EQU 0F07FH ;END OF CLOCK RAM
; * WORKING REGISTERS R0-R7 *
; * BANK #1 * ;USED WHEN REGISTER BANK #1 IS SELECTED
INDEX1 EQU R0
INDEX2 EQU R1
DIGIT EQU R2 ;TABLE OF STORED TELEPHONE DIGITS
TEMP1 EQU R3 ;TEMP STORAGE #1
TEMP2 EQU R4 ;TEMP STORAGE #2
EXTND_X EQU R5 ;TIME EXTENDING, X-TIMES
LOG_DPL EQU R6 ;STORES THE END OF LOG ADDRESS (PART 1) (DPTR)
LOG_DPH EQU R7 ;STORES THE END OF LOG ADDRESS (PART 2) (DPTR)
; * BANK #2 * ;USED WHEN REGISTER BANK #2 IS SELECTED
FIX_BASER0 EQU R0 ;FIRST DIGIT TO BE CONVERTED TO BCD
FIX_MOVER1 EQU R1 ;STORAGE OF NEW CONVERTED BCD
TIMEOUT1R2 EQU R2 ;TIMEOUT FOR CALL TIME LIMIT OF 15-MINUTES
TIMEOUT2R3 EQU R3
TIMEOUT3R4 EQU R4
COUNT1R5 EQU R6 ;SMALL TIMING LOOP COUNTS
COUNT2R6 EQU R7 ;FOR LARGE TIMING LOOP, WORKS WITH COUNT1
; * BANK #3 * ;USED WHEN REGISTER BANK #3 IS SELECTED
RX_BASER0 EQU R0 ;RECEIVED DIGIT GOES TO VIA R0
ORG 8
FIX_BASE DATA 1
FIX_MOVE DATA 1
TIMEOUT1 DATA 1
TIMEOUT2 DATA 1
TIMEOUT3 DATA 1
COUNT1 DATA 1
COUNT2 DATA 1
ORG 10H
RX_BASE DATA 1
ORG 11H
DPH_TEMP DATA 1 ;TEMPORARY STORAGE FOR DPTR HIGH
DPL_TEMP DATA 1 ;TEMPORARY STORAGE FOR DPTR LOW
DPL_HIGH DATA 1 ;MOVES DATA POINTER WHEN MOVING CALL HISTORY DATA
DPH_HIGH DATA 1 ;MOVES DATA POINTER WHEN MOVING CALL HISTORY DATA
ROL_DATA DATA 1 ;ROLLS THE DATA FOR SCANNING AREA CODE BITS
KEYDELAY DATA 1 ;TIMES TO SCAN FOR VALID DATA (MAX 3)
DSP_TEMP DATA 1 ;STORES VALUE OF "A"
D_TEMP DATA 1 ;LIKE FIX, TEMP STORAGE OF DATA WHILE BEING PROCESSED
DATA_D DATA 1 ;DISPLAY DATA STORAGE AND MANIPUTATION
BUFFER DATA 1 ;STORAGE OF KEY PRESSES
HEX_COUNT DATA 1 ;HEX VALUE COUNT
DIGIT_OFF DATA 1 ;FOR CALCULATING THE END ADDRESS OF THE DIALED NUMBER
KEYCOUNT DATA 1 ;KEY NUMBER THAT WAS PRESSED
PORTAI DATA 1 ;PORT A INPUT SHADOW ADDRESS (#1EH)
PORTAO DATA 1 ;PORT A OUTPUT SHADOW ADDRESS (#1FH)
; * BIT ADDRESSABLE RAM (20-2FH) (BITS 00-7F) *
PORTBI DATA 1 ;PORT B INPUT SHADOW ADDRESS (#20H)
PORTBO DATA 1 ;PORT B OUTPUT SHADOW ADDRESS (#21H)
STATUS DATA 1 ;STATUS BYTE ADDRESS (#22H)
STATUS_TIME DATA 1 ;STATUS_TIME BYTE ADDRESS (#23H)
AREACODE DATA 1 ;0=LOCAL, 1=NEXT, 2=NEXT, 3=NEXT(#24H)
; DEFINE RAM *
ORG 2FH
AREACODE_MASK DATA 1 ;MASKING DATA. TO "AND" or "OR" (BIT ADDRESSABLE)
EXTND DATA 1 ;HOW MANY TIMES THAT THE TIMEOUT CAN BE EXTENDED
RAM EQU $
AREACODE_TEMP DATA 6 ;TEMPORARY STORAGE OF AREA CODE
CODE_S DATA 7 ;TEMPORARY STORAGE OF THE ACCESS CODE
COUNTDONE DATA 1 ;TOTAL NUMBER OF DIGITS THAT WHERE DIALED
DIGIT_D DATA 11 ;TABLE OF STORED TELEPHONE DIGITS
PASSCODE_2 DATA 3 ;TEMPORARY STORAGE OF 2nd PASSCODE ENTERED BY CALLER
PREFIX_CNT DATA 4 ;KEEPS COUNT OF PREFIXES
RX_BUFF DATA 10 ;RECEIVE BUFFER
SUM DATA 1 ;CHECKSUM FOR FILE TRANSFERS
ENDRAM EQU $
; * VECTOR ADDRESSES *
ORG 00H
SJMP RESET0 ;RESET VECTOR
;ORG 03H
;LJMP IEO ;EXTERNAL INTERRUPT #0
ORG 0BH
LJMP TIO ;TIMER 0 INTERRUPT VECTOR
;ORG 13H
;LJMP IE1 ;EXTERNAL INTERRUPT #1
ORG 1BH
LJMP TI1 ;TIMER 1 INTERRUPT VECTOR
ORG 23H
LJMP SERIAL ;SERIAL TRANSMIT AND RECEIVE
; -------------------------- BEGINNING OF CODE ------------------------------
; * INITIALIZATION *
RESET0: MOV SP,#ENDRAM+1 ;SET STACK POINTER TO END OF RAM
RESET1: MOV TMOD,#11H ;TIMER CONFIGURATION, BOTH COUNTERS 16-BIT
MOV TH0,#0FAH
MOV TL0,#00H ;TIMER COUNT, 10mS INTERRUPT
SETB EA ;ENABLE INTERRUPTS
SETB ET0 ;ENABLE TIMER 0 INTERRUPT
MOV P1,#00H ;PORT 1 OUTPUTS
SETB TR0 ;TURN ON TIMER 0
; * DISPLAY SETUP *
MOV DPTR,#DISPLAY_R
MOV A,#39H ;DATA BUS 8-BITS, 2-LINE DISPLAY, 5x7-DOTS
MOVX @DPTR,A ;WRITE THE VALUE TWICE
MOVX @DPTR,A
MOV A,#0FH ;DISPLAY ON, CURSOR ON, BLINKING
MOVX @DPTR,A ;WRITE THE VALUE TWICE
MOVX @DPTR,A
; * CLOCK SETUP *
MOV DPTR,#CLOCK_A ;SET CLOCK SQUARE WAVE OUTPUT AND TIME BASE
MOV A,#00001111B ;4.194304MHz CLOCK, 2Hz SQUARE WAVE (PIN 23)
MOVX @DPTR,A ;OUTPUT DATA
MOV DPTR,#CLOCK_B ;CLOCK CONTROL REGISTER ADDRESS
MOV A,#00001000B ;ENABLE SQUARE WAVE OUTPUT, 12HR CLOCK
MOVX @DPTR,A ;OUTPUT DATA
; * CLEAR DISPLAY *
LCALL CLR_DSP ;CLEAR DISPLAY 1.64mS
MOV DPTR,#D_TITLE ;DISPLAY: "Call Diverter", "by RLG 1/5/95"
LCALL SEND_M ;SEND MESSAGE
; * CHECK EXTERNAL RAM, SEE IF INITIALIZED (0100-0200H) *
MOV DPTR,#30H ;SET RAM BASE ADDRESS
XRAM0: MOVX A,@DPTR ;INPUT DATA FROM RAM
CJNE A,#0AAH,XRAM3 ;CONTINUE IF = AA
INC DPTR ;INCREMENT DATA POINTER
MOV A,DPH
CJNE A,#2,XRAM0 ;IS THE ADDRESS = 200H?
SETB INIT_AC ;SET FLAG
; * RESTORE IMPORTANT REGISTERS *
MOV DPTR,#22H ;ADDRESS OF EXTERNAL MEMORY
MOVX A,@DPTR ;GET EXTERNAL DATA
MOV 22,A ;WRITE TO INTERNAL MEMORY
SJMP START ;BACK TO START
; * SET DEFAULT ACCESS CODE #(555555) *
XRAM3: MOV DPTR,#PASSCODE_1
MOV A,#5
MOVX @DPTR,A ;1st DIGIT
INC DPTR
MOVX @DPTR,A ;2nd DIGIT
INC DPTR
MOVX @DPTR,A ;3rd DIGIT
INC DPTR
MOVX @DPTR,A ;4th DIGIT
INC DPTR
MOVX @DPTR,A ;5th DIGIT
INC DPTR
MOVX @DPTR,A ;6th DIGIT
SETB N_LOCAL ;NO CALL RESTRTCTION
SETB NEW_DATA ;FIRST TIME ON BEFORE ANY INITIALIZATION
LCALL CLRXRAM1
LCALL CLRXRAM2
LCALL CLOCK_SET
; * MAIN CONTROL PROGRAM *
; * SETUP ALL PORTS FOR THE NEXT CALL *
START: MOV SP,#ENDRAM+1 ;RESET STACK POINTER
CLR KEY ;CLEAR KEYBOARD FUNCTION FLAG
CLR TIMED_OUT ;CLEAR TIMED_OUT FLAG SET IN WAIT_DIGIT
MOV PORTBO,#15H ;DISABLE ALL DEVICES ON PORT B
LCALL BOUT ;OUTPUT TO PORT
ANL STATUS,#4 ;RESET ALL BUT BIT 3
; * CLEAR RAM *
CLRRAM: MOV A,#00H ;LOAN ADDRESS OF RAM IN "X"
MOV R0,#RAM ;LOAD INDEX REGISTER WITH BEGINNING ADDRESS
CLRR1: MOV @R0,A ;CLEAR MEMORY ADDRESS 0 + OFFSET IN "X"
INC R0 ;INCREMENT "X"
CJNE R0,#ENDRAM,CLRR1 ;SEE IF "X" = THE ADDRESS OF ENDRAM
; * CHECK FOR RING SIGNAL & CLOCK UPDATES *
STR: LCALL BIN ;INPUT FROM PORT
JB RING,R00 ;CHECK FOR PRESENCE OF RING SIGNAL
JB VALID_DATA,KEYA ;IF KEYBOARD, THEN BRANCH
MOV DPTR,#CLOCK_A ;READ "UPDATE IN PROGRESS" BIT (UIP)
MOVX A,@DPTR ;READ DATA
MOV ROL_DATA,A ;MOVE SO MSB CAN BE CHECKED
JNB CLOCK_BUSY,STR ;CHECK STATUS OF BIT
LCALL UPDATE ;DISPLAY CLOCK DATA
SJMP STR
; * KEYBOARD PRESSED *
KEYA: MOV RX_BASE,#DIGIT_D ;SET UP BASE ADDRESS (NOT USED)
LCALL WAIT_DIGIT ;COLLECT DIGIT
JB TIMED_OUT,START ;START AGAIN IF TIMED OUT
MOV A,DIGIT ;GET DIGIT
CJNE A,#0BH,STR ;IS IT A "*"?
LCALL WAIT_DIGIT ;COLLECT DIGIT
JB TIMED_OUT,START ;START AGAIN IF TIMED OUT
MOV A,DIGIT ;GET DIGIT
CJNE A,#0CH,STR ;IS IT A "#"?
SETB KEY ;SET KEYBOARD MODE
LCALL OPTION ;GOTO OPTION's
SJMP START
; * DELAY TO INSURE OF NO FALSE RING *
R00: LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_RING ;DISPLAY: "...Ring Detected.."
LCALL SEND_M ;SEND MESSAGE
MOV A,#00H
MOV TH0,#0FAH ;RELOAD TIMER COUNT
MOV TL0,#00H ;--------------------------------------------
MOV COUNT1,#3 ;30mS DELAY BEFORE CHECKING THE RING AGAIN |
JNB COUNT,$ ;--------------------------------------------
JNB RING,STR ;SEE IF RING STILL THERE
; * 200mS DELAY INTO THE RING AND CHECK FOR THE RING AGAIN *
MOV TH0,#0FAH ;RELOAD TIMER COUNT
MOV TL0,#00H ;---------------------------------------------
MOV COUNT1,#14H ;200mS DELAY 0 |
RX: JNB COUNT,$ ;---------------------------------------------
LCALL BIN ;INPUT FROM PORT
JB RING,RING1 ;CHECK RING SIGNAL AGAIN
SJMP STR ;GO BACK! AND CHECK RING AGAIN
; * ANSWERING MACHINE OPTION *
; IF AN ANSWERING MACHINE IS HOOKED UP IN SERIES WITH A RELAY, AFTER THE
; ANSWERING MACHINE ANSWERS, IT CHECKS THE LINE FOR BEING OFF-HOOK AND
; THEN WAITS FOR A "#" TO BE DIALED. tHEN THE RELAY IS PULLED IN AND
; DISCONNECTS THE ANSWERING MACHINE FROM THE PHONE LINE AND THEN GIVES
; DIALTONE.
; * CHECK LENGTH OF RING *
RELAY1: LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_RELAY_ON ;DISPLAY: "Relay Option ON"
LCALL SEND_M ;SEND MESSAGE
MOV TH0,#0FAH ;RELOAD TIMER COUNT
MOV TL0,#00H
MOV COUNT2,#1
MOV COUNT1,#0F4H ;5-SECOND DELAY-------------------------------
RELAY2: LCALL BIN ;INPUT FROM PORT0 |
JB RING,RELAY3 ;CHECK FOR RING SIGNAL |
JNB CPC,RING4 ;WAS THE LINE ANSWERED BY ANSWERING MACHINE? |
JNB COUNT,RELAY2 ;CHECK FOR TIMEOUT |
RELAY3: AJMP START ;---------------------------------------------
RING4: MOV RX_BASE,#DIGIT_D ;SETUP LOCATION TO STORE THE INCOMING DIGIT
LCALL WAIT_DIGIT ;COLLECT DIGIT
JB TIMED_OUT,START1 ;START AGAIN IF TIMED OUT
JB POUND,RING5 ;IS IT A "#"?
START1: AJMP START ;ANY OTHER DIGIT, RESTART
RING5: SETB RELAY ;TURN ON RELAY / DISCONNECT ANSWERING MACHINE
LCALL BOUT ;OUTPUT TO PORT
AJMP AGAIN ;BACK TO DIALTONE
; * ANSWER PHONE LINE & GIVE DIAL TONE *
RING1: LCALL BIN ;INPUT FROM PORT
JB RING,RING1 ;CONTINUE WHEN RING GOES AWAY
JB RLY_OPT,RELAY1 ;CHECK FOR RELAY OPTION
AGAIN: JNB _400HZ,REGULAR ;CHECK 400Hz DIALTONE FLAG
MOV A,#TONE400 ;LOAD DIALTONE VALUE TO THE CALL PROGRESS GEN
SJMP NOTREG ;SKIP OVER THE NEXT INSTRUCTION
REGULAR:MOV PORTAI,#DIALTONE ;LOAD DIAL TONE TO CALL PROGRESS GENERATOR
NOTREG: LCALL AOUT ;OUTPUT TO PORT
CLR CALLPROG ;CALL PROGRESS GENERATOR ON
SETB SWITCHHOOK ;ANSWER PHONE LINE
LCALL BOUT ;OUTPUT TO PORT
LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_ANSWER ;DISPLAY: ".Line Answered.."
LCALL SEND_M ;SEND MESSAGE
; * ERASE DIGIT STORAGE WITH FF's *
MOV R0,#DIGIT_D ;BASE ADDRESS FOR ERASURE
NOTR: MOV A,#0FFH
MOV @R0,A ;WRITE TO REGISTER
INC R0 ;INCREMENT TO NEXT LOCATION
CJNE R0,#DIGIT_D+11,NOTR;
; * SETUP STORAGE LOCATION FOR DIGITS *
MOV RX_BASE,#DIGIT_D ;STARTING ADDRESS OF DIGIT STORAGE
LCALL WAIT_DIGIT ;FIRST DIGIT TO BE TESTED
JB TIMED_OUT,START1 ;START AGAIN IF TIMED OUT
; * CHECK FIRST DIGIT DIALED *
JB STAR,OPTN ;IS THE FIRST DIGIT A "*"? GOTO OPTIONS
JB POUND,AGAIN ;IS THE FIRST DIGIT A "#"? BACK TO DIAL-TONE
; * STARTING ADDRESS OF DIGIT STORAGE
CJNE DIGIT,#1,ONESU1
AJMP ONES ;BRANCH IF THE FIRST DIGIT IS A "1"
ONESU1: AJMP ONESU
OPTN: LCALL OPTION
AJMP AGAIN
; * ACCEPT EITHER 7 OR 11 DIGITS *
; ELEVEN DIGITS *
ONES: MOV COUNTDONE,#0AH ;ELEVEN DIGITS MINUS ONE
SETB ELEVEN ;SET ELEVEN DIGITS DIALED
SJMP COLLECT ;IF = "1", BRANCH
; SEVEN DIGITS *
ONESU: MOV COUNTDONE,#06H ;IF IT IS NOT THEN LOAD MAX NUMBER TO BE "7"
CLR ELEVEN
; * COLLECT DIGITS *
COLLECT: LCALL WAIT_DIGIT ;COLLECT DIGIT
JB STAR,RING3 ;IF ANY DIGIT IS THE "*", THEN START OVER
JB POUND,RING3 ;IF ANY DIGIT IS THE "#", THEN START OVER
MOV A,RX_BASE ;LOAD THE OFFSET THAT WAS IN "X"
SUBB A,#DIGIT_D ;SUBTRACT "DIGIT"0ADDRESS FROM "X"'s OFFSET
CJNE A,COUNTDONE,COLLECT;IS THE COUNT DONE?
A_CODE1:JNB SECURITY,CALLOUT ;IF SECURITY NOT ACTIVATED, THEN CALL
LCALL PASSCODE ;CHECK ACCESS CODE
JB TIMED_OUT,START1 ;TIMEDOUT?
JNB PASSCODE_NOT,CALLOUT;VALIDITY OF THE PASSCODE
LCALL LOG ;WRITE DATA TO THE CALLING LOG
AJMP START1
; * CHECK IF PHONE NUMBER IS LOCAL & CALLING OUT OVER THE PHONE LINE *
CALLOUT:JB N_LOCAL,CALLA
LCALL LOCAL ;GOING TO THE LOCAL CALLING AREA LOOK-UP TABLE
JBC OK_NUMBER,CALLA ;IF SET THEN CALL OUT AND CLEAR THE BIT
LJMP AGAIN ;BACK TO DIALTONE
RING3: AJMP AGAIN
; * DIAL "KP" *
CALLA: LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_DIALING_MF ;DISPLAY: "...Dialing MF..."
LCALL SEND_M ;SEND MESSAGE
CLR OK_NUMBER ;CLEAR THE LOCAL AREA TABLE OK FLAG
LCALL BOUT ;OUTPUT TO PORT
MOV TH0,#0FAH ;RELOAD TIMER DATA
MOV TL0,#00H ;---------------------------------------------
MOV COUNT1,#0AH ;100mS DELAY |
CLR MF_G ;TURN OFF MF GENERATOR |
LCALL BOUT ; |
JNB COUNT,$ ;---------------------------------------------
SETB MF_G ;TURN OFF MF GENERATOR
LCALL BOUT ;---------------------------------------------
MOV COUNT1,#0AH ;100mS DELAY |
JNB COUNT,$ ;---------------------------------------------
SETB MF ;SET STATUS BIT FOR MF DIALING
MOV TEMP1,COUNTDONE ;STORE THE COUNTDONE
LCALL DIAL ;MF DIAL THE NUMBER
MOV COUNTDONE,TEMP1 ;RESTORE THE COUNTDONE VALUE
LCALL FLASH ;GOING INTO 3-WAY
MOV TH0,#0FAH ;RELOAD TIMER COUNT
MOV TL0,#00H ;---------------------------------------------
MOV COUNT1,#0C8H ;2-SECOND WAITING TIME FOR DIAL-TONE |
JNB COUNT,$ ;---------------------------------------------
MOV R0,#DIGIT_D ;POINT TO DIGIT GROUP OF NUMBERS TO BE DIALED
LCALL DIAL ;DIAL NUMBER
MOV TH0,#0FAH ;RELOAD TIMER COUNT
MOV TL0,#00H ;---------------------------------------------
MOV COUNT1,#0C8H ;2-SECONDS WAITING TIME FOR DIAL TONE |
JNB COUNT,$ ; |
; ----------------------------------------------
LCALL FLASH ;COME BACK OUT OF 3-WAY
; * TALK MODE *
TALK: LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_TALK ;DISPLAY: "....Talk Mode..."
LCALL SEND_M ;SEND MESSAGE
MOV TIMEOUT3,#1 ;SETTING UP THE 15-MINUTE TIMEOUT PERIOD
MOV TIMEOUT2,#5FH
MOV TIMEOUT1,#90H
TALK1: LCALL BIN ;INPUT FROM PORT
JB CPC,ONEMN1 ;CHECK FOR ONHOOK
JB DTMFR,TDTMF ;CHECK FOR DTMF
SETB RS0
CJNE TIMEOUT3R4,#00H,ONEMN ;CHECK TIMER FOR ONE MINUTE REMAINING
CJNE TIMEOUT2R3,#17H,ONEMN
CJNE TIMEOUT1R2,#70H,ONEMN
MOV PORTAO,#ASTERISK ;INDICATING USMNG THE BUSY TONE
LCALL AOUT
MOV A,#2 ;AND BEEPING 2-TIMES
LCALL BEEPR ;BEEP IF ONE MINUTE REMAINING ON TIMEOUT
ONEMN: CLR RS0
JNB TIMEOUT,TALK1 ;CHECK FOR TIMEOUT
ONEMN1: LJMP START ;RESET IF THE TIMER TIMES OUT
; * DTMF DETECTED WHILE IN TALK *
TDTMF: LCALL BIN ;INPUT FROM PORT
JB DTMFR,TDTMF ;CONTINUE WHEN NO DTMF
LCALL AIN ;LOAD DIGIT
ANL A,#0FH ;MASK UPPER HALF
CJNE A,#0AH,TDDT ;DIALING "0" WILL EXTEND THE TIME 6.8 MINUTES
CJNE EXTND_X,#00H,TDT1 ;CHECK IF MAX. EXTEND "X" TIME'S BEEN REACHED
SJMP TALK2 ;BACK TO TALK MODE
TDT1: MOV TIMEOUT2,#2DH
MOV TIMEOUT1,#94H ;ADD 6.8 MINUTES
DEC EXTND ;DECREMENT THE EXTEND COUNT
LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_EXTEND ;DISPLAY: "Call Extender:"
LCALL SEND_M ;SEND MESSAGE
MOV PORTAO,#RINGTONE ;LOAD WITH RING TONE
LCALL AOUT ;OUTPUT TO PORT
MOV A,#3 ;AND BEEP 3-TIMES
LCALL BEEPR
SJMP TALK1 ;BACK TO TALK MODE
TDDT: CJNE DIGIT,#0CH,TDT2 ;"#" WILL DUMP CALL
AJMP START1
TDT2: CJNE DIGIT,#0BH,TALK1 ;"*" WILL DUMP CALL
AJMP START1
TALK2: MOV PORTAO,#BUSYTONE ;LOAD BUSYTONE
LCALL AOUT ;OUTPUT TO PORT
MOV A,#0AH ;BEEP 10 TIMES
LCALL BEEPR
SJMP TALK1 ;BACK TO TALK MODE
; * HIGH & LOW ALTERNATING TONES *
ALTTONE: LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_ERROR ;DISPLAY: ".Alt Tone Error."
LCALL SEND_M ;SEND MESSAGE
ALT: MOV TEMP1,#00H ;CLEAR COUNT
MOV TH0,#0FAH
MOV TL0,#00H ;RELOAD TIMER COUNT
MOV A,#TONE620 ;LOAD HIGH TONE
LCALL AOUT ;OUTPUT TO PORT
MOV COUNT1,#19H
CLR CALLPROG ;---------------------------------------------
LCALL BOUT ;OUTPUT TO PORT |
JNB COUNT,$ ;TIME 250mS DELAY FOR "ON" TIME |
; ;---------------------------------------------
SETB CALLPROG ;TURN OFF CALL PROGRESS GENERATOR
LCALL BOUT ;OUTPUT TO PORT
MOV PORTAO,#TONE350 ;LOAD LOW TONE
LCALL AOUT ;OUTPUT TO PORT
MOV COUNT1,#19H ;---------------------------------------------
;TIME 250mS DELAY FOR "ON" TIME |
CLR CALLPROG ;TURN ON CALL PROGRESS GENERATOR |
LCALL BOUT ;OUTPUT TO PORT |
JNB COUNT,$ ;CHECK FOR THE COUNT DELAY |
; ;---------------------------------------------
SETB CALLPROG ;TURN OFF CALL PROGRESS GENERATOR
LCALL BOUT ;OUTPUT TO PORT
LCALL BIN ;INPUT FROM PORT
JB CPC,TIMINT ;CHECK FOR ONHOOK
DEC TEMP1
CJNE TEMP1,#00H,ALT ;IF = 0 THEN START ALL OVER AGAIN
TIMINT: LJMP START ;BACK TO START
; **** SUBROUTINES ****
; -----------------* INITIAL AREA CODE (1st AREA CODE) *------------------
N_INIT: LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_LOCAL ;DISPLAY:Enter Local, Area Code:
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOV FIX_BASE,#DIGIT_D ;SETUP STARTING ADDRESS FOR "FIX"
MOV FIX_MOVE,#AREACODE_TEMP ;WHERE FIX RESULTS GO TO
MOV RX_BASE,#DIGIT_D ;DTMF STORAGE
N_INI: LCALL WAIT_DIGIT ;COLLECT 1st DIGIT
JB TIMED_OUT,N_TO ;TIMEOUT?
MOV A,DIGIT
CJNE A,#1,N_INI0 ;IS IT A "1"?
SJMP N_INIT ;DO AGAIN
N_INI0: CJNE A,#0AH,N_INI1 ;IS IT A "0"?
SJMP N_INIT ;DO AGAIN
N_INI1: MOV A,DIGIT
CJNE A,#0BH,N_INI2 ;IS IT A "*" ?
SJMP N_INIT ;DO AGAIN
N_INI2: CJNE A,#0CH,N_INI3 ;IS IT A "#" ?
SJMP N_INIT ;DO AGAIN
N_INI3: LCALL WAIT_DIGIT ;2nd DIGIT
JB TIMED_OUT,N_TO
MOV A,DIGIT
CJNE A,#0BH,N_INI4 ;IS IT A "*" ?
SJMP N_INIT
N_INI4: CJNE A,#0CH,N_INI5 ;IS IT A "#" ?
SJMP N_INIT
N_INI5: LCALL WAIT_DIGIT ;3rd DIGIT
JB TIMED_OUT,N_TO ;TIMEDOUT?
CJNE A,#0BH,N_INI6 ;IS IT A "*" ?
SJMP N_INIT
N_INI6: CJNE A,#0CH,N_INI7 ;IS IT A "*" ?
SJMP N_INIT
N_TO: RET
; * STORE THE 1st AREA CODE IN EXTERNAL RAM *
N_INI7: MOV DPTR,#00H ;SET BASE LOCATION FOR AREA CODE STORAGE
; * STORE AREA CODES IN EXTERNAL RAM *
N_INIH: MOV A,AREACODE_TEMP ;WHERE AREA CODE IS STORED
MOVX @DPTR,A ;STORE 1+ 1st DIGIT OF AREA CODE IN RAM
INC DPTR ;INCREMENT DATA POINTER
MOV A,AREACODE_TEMP+1 ;2nd & 3rd DIGIT OF AREA CODE IN EXTERNAL RAM
MOVX @DPTR,A ;STORE SECOND & THIRD DIGIT OF AREA CODE
MOV A,#0FFH ;CENTINAL
MOVX @DPTR,A ;OUTPUT CENTINAL (FF)
INC DPTR ;INCREMENT DATA POINTER
LCALL ANY_KEY ;DISPLAY: 'Hit Any Key...'
JB TIMED_OUT,N_TO ;TIMEDOUT?
N_INIG: LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_NEXT_AC ;DISPLAY: "Next Area Code","# to Exit"
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOV RX_BASE,#DIGIT_D ;SET UP FOR STORING DIGITS
MOV FIX_BASE,#DIGIT_D ;STARTING ADDRESS FOR FIX
MOV FIX_MOVE,#AREACODE_TEMP ;STORAGE AFTER FIX
LCALL WAIT_DIGIT ;COLLECT 1st DIGIT OF NEXT AREA CODE
JB TIMED_OUT,N_TO ;TIMEDOUT?
MOV A,DIGIT ;GET DIGIT
CJNE A,#1,N_INI8 ;IS IT A "1"?
SJMP N_INIG ;COLLECT MORE DIGITS
N_INI8: CJNE A,#0AH,N_INI9 ;IS IT A "0"?
SJMP N_INI7 ;DO AGAIN
N_INI9: CJNE A,#0BH,N_INIA ;IS IT A "*"?
SJMP N_INI7 ;DO AGAIN
N_INIA: CJNE A,#0CH,N_INIB ;IS IT A "#"?
SETB INIT_AC ;AREA CODES HAVE BEEN INITIALIZED
SJMP ADD_NUM1 ;GOTO ADDING PREFIXES
N_INIB: LCALL ONE_FIX ;APPEND "1" TO BCD
MOV A,DIGIT ;GET COLLECTED DIGIT
LCALL FIX_ONE ;COMBINE TO BCD
LCALL WAIT_DIGIT ;COLLECT 2nd DIGIT
JB TIMED_OUT,N_TO ;TIMEDOUT?
MOV A,DIGIT ;CHECK DIGIT VALUE
CJNE A,#0BH,N_INIC ;IS IT A "*"?
SJMP N_INI7 ;DO AGAIN
N_INIC: CJNE A,#0CH,N_INID ;IS IT A "#"?
SETB INIT_AC
SJMP ADD_NUM1
N_INID: LCALL WAIT_DIGIT ;COLLECT 3rd DIGIT
JB TIMED_OUT,N_TO ;TIMEDOUT?
MOV A,DIGIT ;CHECK DIGIT VALUE
CJNE A,#0BH,N_INIE ;IS IT A "*"?
SJMP N_INI7 ;DO AGAIN
N_INIE: CJNE A,#0CH,N_INIF ;IS IT A "#"?
SETB INIT_AC ;PROGRAMMING DONE, SET INIT_AC
SJMP ADD_NUM1 ;BACK TO ADDING PREFIXES
N_INIZ: AJMP N_INIG
N_INIF: LCALL FIX_ONE ;COMBINE TO (BCD)
MOV A,AREACODE_TEMP
MOVX @DPTR,A ;WRITE FIRST TWO DIGITS TO RAM
INC DPTR ;TO NEXT LOCATION
MOV A,AREACODE_TEMP+1
MOVX @DPTR,A ;WRITE REMAINING AREACODE TO RAM
INC DPTR ;TO NEXT LOCATION
MOV A,#0FFH ;CENTINAL
MOVX @DPTR,A ;WRITE CENTINAL TO RAM
MOV A,DPL ;CHECK FOR MAX AREACODES
CJNE A,#18H,N_INIG
LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_AC_MAXED
LCALL SEND_M ;DISPLAY: 'Maximum Codes...'
POP DPH
POP DPL
; -----------------------* ADD AREA CODE & PREFIX *------------------------
ADD_NUM:PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
JNB INIT_AC,N_INIZ ;LOCAL CALLING NOT INITIALIZED?
ADD_NUM1: LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_ENTER_AC ;DISPLAY: "Enter Area Code, & Prefix:"
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOV RX_BASE,#DIGIT_D ;DIGIT RECEIVE LOCATION
MOV FIX_BASE,#DIGIT_D ;BASE ADDRESS FOR FIX
MOV FIX_MOVE,#AREACODE_TEMP;STORAGE OF DIGITS AFTER FIX (BCD)
LCALL WAIT_DIGIT ;COLLECT 1st DIGIT
JB TIMED_OUT,ADD_TO ;TIMEDOUT?
MOV A,DIGIT ;GET COLLECTED DIGIT
CJNE A,#1,ADD_N2 ;IS IT A "1" ?
SJMP ADD_NUM1
ADD_N2: CJNE A,#0AH,ADD_N3 ;IS IT A "0" ?
SJMP ADD_NUM1
ADD_N3: CJNE A,#0BH,ADD_N4 ;IS IT A "*" ?
SJMP ADD_NUM1
ADD_N4: CJNE A,#0CH,ADD_N5 ;IS IT A "#" ?
LCALL T_PREFIX ;TOTAL ALL OF THE PREFIXES
CLR N_LOCAL ;CLEAR NO CALL RESTRICTION
POP ACC ;EXIT
POP DPH
POP DPL
RET
ADD_N5: LCALL WAIT_DIGIT ;COLLECT 2nd DIGIT
JB TIMED_OUT,ADD_TO ;TIMEDOUT?
MOV A,DIGIT
CJNE A,#0BH,ADD_N6
SJMP ADD_NUM1
ADD_N6: CJNE A,#0CH,ADD_N7 ;IS IT A "#" ?
LCALL T_PREFIX ;TOTAL ALL PREFIXES
CLR N_LOCAL ;CLEAR NO CALL RESTRICTION
POP ACC ;EXIT
POP DPH
POP DPL
RET
ADD_N7: LCALL WAIT_DIGIT ;COLLECT 3rd DIGIT
JB TIMED_OUT,ADD_TO ;TIMEDOUT?
CJNE A,#0BH,ADD_N8 ;IS IT A "*" ?
AJMP ADD_NUM1
ADD_N8: CJNE A,#0CH,ADD_N9 ;IS IT A "#" ?
LCALL T_PREFIX ;TOTAL ALL PREFIXES
ADD_TO: POP ACC ;EXIT
POP DPH
POP DPL
RET
ADD_N9: PUSH DPL
PUSH DPH
MOV DPTR,#D_DASH
LCALL SEND_M ;DISPLAY: SEND "-"
POP DPH
POP DPL
LCALL WAIT_DIGIT ;4th DIGIT
JB TIMED_OUT,ADD_TO ;TIMEDOUT?
MOV A,DIGIT
CJNE A,#1,ADD_NA ;DOES THE PREFIX START WITH "1" ?
AJMP ADD_NUM1
ADD_NA: CJNE A,#0BH,ADD_NB ;IS IT A "*" ?
AJMP ADD_NUM1
ADD_NB: CJNE A,#0CH,ADD_NC ;IS IT A "#" ?
LCALL T_PREFIX ;TOTAL ALL PREFIXES
CLR N_LOCAL ;CLEAR NO CALL RESTRICTION
POP ACC
POP DPH
POP DPL
RET
ADD_NC: LCALL WAIT_DIGIT ;5th DIGIT
JB TIMED_OUT,ADD_TO ;TIMEDOUT?
MOV A,DIGIT
CJNE A,#0BH,ADD_ND ;IS IT A "*" ?
AJMP ADD_NUM1
ADD_ND: CJNE A,#0CH,ADD_NE ;IS IT A "#" ?
LCALL T_PREFIX ;TOTAL ALL PREFIXES
CLR N_LOCAL ;CLEAR NO CALL RESTRICTION
POP ACC
POP DPH
POP DPL
RET
ADD_NE: LCALL WAIT_DIGIT ;6th DIGIT
JB TIMED_OUT,ADD_TO ;TIMEDOUT?
MOV A,DIGIT
CJNE A,#0BH,ADD_NF ;IS IT A "*" ?
AJMP ADD_NUM1
ADD_NF: CJNE A,#0CH,ADD_NG ;IS IT A "#" ?
LCALL T_PREFIX ;TOTAL ALL PREFIXES
CLR N_LOCAL ;CLEAR NO CALL RESTRICTION
POP ACC
POP DPH
POP DPL
RET
ADD_NG: LCALL ONE_FIX ;(BCD) PREFIX A "1" TO 1st DIGIT OF AREACODE
LCALL FIX_ONE ;(BCD) SECOND TWO DIGITS OF THE AREACODE
LCALL ZERO_FIX ;(BCD) PREFIX A "0" TO 1st DIGIT OF PREFIX
LCALL FIX_ONE ;(BCD) SECOND TWO DIGITS OF THE PREFIX
LCALL DUPLICATE ;CHECK FOR THE AREACODE
JNB DUP,ADD_ACODE ;FIND DUPLICATE IN AREACODE TABLE?
MOV DPH,AREACODE_TEMP+2 ;LOAD THE REAL ADDRESS
MOV DPL,AREACODE_TEMP+3
MOVX A,@DPTR ;GET THE PRESENT VALUE
ORL A,AREACODE_MASK ;MASK IN THE DATA
MOVX @DPTR,A ;WRITE BACK TO MEMORY
LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_ADDED
LCALL SEND_M ;DISPLAY: 'Added: '
LCALL ANY_KEY ;DISPLAY: ;Hit Any Key...'
AJMP ADD_TO
ADD_ACODE: AJMP ADD_AC
; * DISPLAY TOTAL PREFIXES IN LIST *
T_PREFIX: LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_TOTAL_PREFIX
LCALL SEND_M ;DISPLAY MESSAGE ".Total Prefixes."
MOV PREFIX_CNT,#0
MOV PREFIX_CNT+1,#0 ;CLEAR COUNTERS
MOV PREFIX_CNT+2,30
MOV PREFIX_CNT+3,#0
MOV DPTR,#PREFIX_BASE
T_PRE: MOV ROL_DATA,#1 ;SET SHIFT DATA TO 1
MOVX A,@DPTR ;GET DATA
T_PRE0: JNB AC_BIT,T_PRE1 ;CHECK BIT
INC PREFIX_CNT ;INCREMENT COUNT
MOV A,PREFIX_CNT
CJNE A,#0AH,T_PRE1 ;CHECK FOR OVERFLOW
MOV PREFIX_CNT,#0
INC PREFIX_CNT+1 ;INCREMENT COUNT
MOV A,PREFIX_CNT+1
CJNE A,#0AH,T_PRE1 ;CHECK FOR OVERFLOW
MOV PREFIX_CNT+1,#0
INC PREFIX_CNT+2 ;INCREMENT COUNT
MOV A,PREFIX_CNT+2
CJNE A,#0AH,T_PRE1 ;CHECK FOR OVERFLOW
MOV PREFIX_CNT+2,#0
INC PREFIX_CNT+3 ;INCREMENT COUNT
T_PRE1: RR A ;ROLL/SHIFT DATA
DJNZ ROL_DATA,T_PRE0 ;CHECK FOR ZERO COUNT, DECREMENT AND JUMP
INC DPTR ;INCREMENT DATA POINTER
MOV A,DPL
CJNE A,#0ABH,T_PRE2 ;CHECK LOWER HALF OF DPTR
MOV DPL,#11H ;IF = ABH, THEN SET TO 11H (SKIP AB-10H)
INC DPH ;INCREMENT UPPER HALF OF DPTR
T_PRE2: MOV A,DPH
CJNE A,#0AH,T_PRE ;CHECK FOR END OF PREFIX TABLE
MOV A,PREFIX_CNT+3 ;CHANGE TO ASCII AND SEND TO DISPLAY
LCALL SEND_D
MOV A,PREFIX_CNT+2
LCALL SEND_D
MOV A,PREFIX_CNT+1
LCALL SEND_D
MOV A,PREFIX_CNT
LCALL SEND_D
T_PRE3: POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; * ADD AREA CODE QUESTION *
ADD_AC: LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_ADD_AC ;DISPLAY: "Add Area Code" "#=Yes / *=No"
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
N_AC3: MOV RX_BASE,#DIGIT_D
LCALL WAIT_DIGIT ;RECEIVE COMMAND "*" OR "#"
JB TIMED_OUT,T_PRE3 ;TIMEDOUT?
MOV A,DIGIT
CJNE A,#0CH,N_AC4 ;IS IT A "#"?
SJMP YES_AC
N_AC4: CJNE A,#0BH,N_AC3 ;IS IT A "*"?
AJMP ADD_NUM1 ;ADD ANOTHER PREFIX
; * YES, ADD AREA CODE *
YES_AC: MOV DPTR,#AREACODE_LIST ;SETUP STARTING ADDRESS
YES_A: MOVX A,@DPTR
CJNE A,#0FFH,N_FF ;CHECK VALUE FOR (FFH)
MOV A,AREACODE_TEMP ;WRITE DATA FIRST TWO DIGITS (AREA CODE)
MOVX @DPTR,A ;OUTPUT DATA
INC DPTR ;INCREMENT POINTER (AREA CODE)
MOV A,AREACODE_TEMP+1 ;WRITE DATA SECOND TWO DIGITS (AREA CODE)
MOVX @DPTR,A ;OUTPUT DATA
INC DPTR ;INCREMENT POINTER
MOV A,#0FFH ;WRITE THE END CENTINAL
MOVX @DPTR,A ;OUTPUT DATA
LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_NEW_AC ;DISPLAY: "New Areacode","Saved:"
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOV A,AREACODE_TEMP ;DISPLAY AREA CODE (1st DIGIT)
ANL A,#00001111B ;MASK UPPER HALF
LCALL SEND_D ;SEND TO DISPLAY
MOV A,AREACODE_TEMP+1 ;DISPLAY AREA CODE (2nd DIGIT)
SWAP A ;SWAP NIBBLES
ANL A,#00001111B
LCALL SEND_D ;SEND TO DISPLAY
MOV A,AREACODE_TEMP+1 ;DISPLAY AREA CODE (3rd DIGIT)
ANL A,#00001111B
LCALL SEND_D ;SEND TO DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_DASH ;DISPLAY: "-"
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOV A,AREACODE_TEMP+2 ;DISPLAY PREFIX (1st DIGIT)
MOV DPH,A ;LOAD PREFIX (UPPER HALF)
LCALL SEND_D ;SEND TO DISPLAY
MOV A,AREACODE_TEMP+3 ;DISPLAY PREFIX (2nd DIGIT)
SWAP A ;SWAP NIBBLES
ANL A,#0000111B
LCALL SEND_D ;SEND TO DISPLAY
MOV A,AREACODE_TEMP+3 ;DISPLAY PREFIX (3rd DIGIT)
MOV A,DPL ;LOAD PREFIX (LOWER HALF)
ANL A,#00001111B
LCALL SEND_D ;SEND TO DISPLAY
LCALL ANY_KEY ;DISPLAY: 'Hit Any Key...'
AJMP ADD_NUM1 ;ADD ANOTHER PREFIX
N_FF: INC DPTR ;NEXT LOCATION
SJMP YES_A
; -----------* SCAN THE PREFIXES IN MEMORY AND DISPLAY THEM *--------------
N_SCAN: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
MOV DPTR,#210H ;BASE ADDRESS FOR PREFIXES
N_SCAN1: LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_LOCAL_LIST ;DISPLAY: "Local List:"
LCALL SEND_M ;SEND MESSAGE
POP DPH ;RESTORE PREFIX ADDRESS
POP DPL
N_SCAN2:INC DPTR ;INCREMENT TO NEXT (PREFIX) ADDRESS
MOVX A,@DPTR ;READ EXTERNAL MEMORY
MOV AREACODE_MASK,A ;STORE DATA
CJNE A,#00H,N_PREF ;IS IT A "0"
MOV A,DPH ;CHECK FOR END OF TABLE
CJNE A,#0AH,N_SCAN1 ;IS IT THE END?
SJMP END_SCAN ;END THE SCAN
N_PREF: MOV DPL_TEMP,#00H ;CLEAR "DPTR" TEMPORARY STORAGE
MOV DPH_TEMP,#00H ;= TO AREA CODE TABLE BASE ADDRESS
PUSH DPL ;PUSH (PREFIX ADDRESS)
PUSH DPH
MOV DPL,DPL_TEMP ;LOAD (AREA CODE) TABLE BASE ADDRESS
MOV DPH,DPH_TEMP
N_PRE: JB AC_BIT,N_PRE2 ;CHECK AN AREA CODE BIT
RR A ;ROLL DATA RIGHT
MOV AREACODE_MASK,A ;NEW DATA VALUE
INC DPTR ;NEXT (AREA CODE) IN TABLE
INC DPTR
N_PRE1: MOVX A,@DPTR ;READ EXTERNAL MEMORY
CJNE A,#0FFH,N_PRE ;CHECK FOR END OF AREA CODE TABLE
MOV DPH_TEMP,DPH ;STORE (AREA CODE) ADDRESS
MOV DPL_TEMP,DPL
POP DPH ;RESTORE (PREFIX) ADDRESS
POP DPL
INC DPTR ;INCREMENT TO NEXT PREFIX
SJMP N_SCAN1
N_PRE2: MOVX A,@DPTR ;READ 1st DIGIT OF AREA CODE
MOV AREACODE_TEMP,A ;1+ FIRST DIGIT OF AREA CODE
INC DPTR ;INCREMENT POINTER
MOVX A,@DPTR ;READ 2nd & 3rd DIGIT OF AREA CODE
MOV AREACODE_TEMP+1,A
MOVX A,@DPTR ;READ 2nd & 3rd DIGIT OF AREA CODE
POP DPH ;RESTORE PREFIX ADDRESS
POP DPL
MOV A,DPH ;GET 1st DIGIT
MOV AREACODE_TEMP+2,A
MOV A,DPL ;GET 2nd & 3rd DIGIT
MOV AREACODE_TEMP+3,A
LCALL SEND_AC_P ;SEND ALL BCD VALUES AREACODE_TEMP TO DISPLAY
LCALL ANY_KEY ;DISPLAY: 'Press Any Key...'
MOV A,DIGIT
CJNE A,#0CH,N_SCAN1 ;DISPLAY NEXT AREA CODE/PREFIX IF NOT '#'
END_SCAN: LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_END_LIST ;DISPLAY: "End of list"
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
LCALL ANY_KEY ;HIT ANY KEY
END_SCAN1:
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; -----------* DELETE THE PREFIX FROM THE EXTERNAL RAM TABLE *-------------
NOTHG: LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_NOTHING ;DISPLAY: "Nothing to DEL","Press a Key"
LCALL SEND_M ;SEND MESSAGE
LCALL ANY_KEY ;DISPLAY: 'Hit Any Key...'
DEL_NUM:PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
DEL_N1: LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_DELETE ;DISPLAY: "Delete Area Code","& Prefix:"
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOV RX_BASE,#DIGIT_D ;SETUP DIGIT STORAGE
MOV FIX_BASE,#DIGIT_D ;SETUP FIX BASE ADDRESS
MOV FIX_MOVE,#AREACODE_TEMP;SETUP FIX MOVE STORAGE
JNB INIT_LOCAL,NOTHG ;NOTHING TO DELETE
LCALL WAIT_DIGIT ;COLLECT 1st DIGIT
JB TIMED_OUT,DEL_TO ;TIMEDOUT?
MOV A,DIGIT ;GET DIGIT
CJNE A,#1,DEL_N2 ;IS THIS A "1"?
SJMP DEL_N1
DEL_N2: CJNE A,#0AH,DEL_N3 ;IS IT A "0" ?
AJMP DEL_N1
DEL_N3: CJNE A,#0BH,DEL_N4 ;IS IT A "*" ?
AJMP DEL_N1
DEL_N4: CJNE A,#0CH,DEL_N5 ;IS IT A "#" ?
LCALL T_PREFIX ;TOTAL ALL PREFIXES
POP ACC
POP DPH
POP DPL
RET
DEL_N5: LCALL WAIT_DIGIT ;COLLECT 2nd DIGIT
JB TIMED_OUT,DEL_TO ;TIMEDOUT?
MOV A,DIGIT
CJNE A,#0BH,DEL_N6 ;IS IT A "*" ?
AJMP DEL_N1
DEL_N6: CJNE A,#0CH,DEL_N7 ;IS IT A "#" ?
LCALL T_PREFIX ;TOTAL ALL PREFIXES
DEL_TO: POP ACC
POP DPH
POP DPL
RET
DEL_N7: LCALL WAIT_DIGIT ;COLLECT 3rd DIGIT
JB TIMED_OUT,DEL_TO ;TIMEDOUT?
MOV A,DIGIT
CJNE A,#0BH,DEL_N8 ;IS IT A "*" ?
AJMP DEL_N1
DEL_N8: CJNE A,#0CH,DEL_N9 ;IS IT A "#" ?
LCALL T_PREFIX ;TOTAL ALL PREFIXES
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
DEL_N9: PUSH DPL
PUSH DPH
MOV DPTR,#D_DASH
LCALL SEND_M ;DISPLAY: SEND "-"
POP DPH
POP DPL
LCALL WAIT_DIGIT ;COLLECT 4th DIGIT
JB TIMED_OUT,DEL_TO ;TIMEDOUT?
MOV A,DIGIT
CJNE A,#1,DEL_NA ;IS IT A "1" ?
AJMP DEL_N1
DEL_NA: CJNE A,#0BH,DEL_NB ;IS IT A "*" ?
AJMP DEL_N1
DEL_NB: CJNE A,#0CH,DEL_NC ;IS IT A "#" ?
LCALL T_PREFIX ;TOTAL ALL PREFIXES
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
DEL_NC: LCALL WAIT_DIGIT ;COLLECT th DIGIT
JB TIMED_OUT,DEL_TO ;TIMEDOUT?
MOV A,DIGIT
CJNE A,#0BH,DEL_ND ;IS IT A "*" ?
AJMP DEL_N1
DEL_ND: CJNE A,#0CH,DEL_NE ;IS IT A "#" ?
LCALL T_PREFIX ;TOTAL ALL PREFIXES
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
DEL_NE: LCALL WAIT_DIGIT ;COLLECT 6th DIGIT
JB TIMED_OUT,DEL_TO ;TIMEDOUT?
MOV A,DIGIT
CJNE A,#0BH,DEL_NF ;IS IT A "*" ?
AJMP DEL_N1
DEL_NF: CJNE A,#0CH,DEL_NG ;IS IT A "#" ?
LCALL T_PREFIX ;TOTAL ALL PREFIXES
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
DEL_NG: LCALL ONE_FIX
LCALL FIX_ONE
LCALL ZERO_FIX
LCALL FIX_ONE
LCALL DUPLICATE ;FIND AREACODE
JNB DUP,NOTHG1 ;CHECK IF AREACODE IS FOUND
MOV DPH,AREACODE_TEMP+2 ;LOAD PREFIX INTO "DPTR"
MOV DPL,AREACODE_TEMP+3
MOVX A,@DPTR ;INPUT DATA
XCH A,AREACODE_MASK ;GET AREACODE MASK
CPL A ;COMPLIMENT (INVERT) ALL BITS
XCH A,AREACODE_MASK ;SWAP BACK
ANL A,TEMP1 ;MASK DATA
MOVX @DPTR,A ;WRITE BACK DATA TO MEMORY
CLR INIT_LOCAL ;CLEAR LOCAL CALLING AREA INITIALIZATION
LCALL ANY_KEY ;DISPLAY: 'Hit Any Key...'
AJMP DEL_NUM ;GO BACK AGAIN
NOTHG1: AJMP NOTHG
; * STORE NUMBER AND CLOCK DATA IN EXTERNAL RAM (HISTORY) *
LOG: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
MOV DPL,LOG_DPL ;GET LOG POINTER
MOV DPH,LOG_DPH
JNB PASSCODE_NOT,STO0 ;CHECK IF PASSCODES WHERE VALID
CLR PASSCODE_NOT ;CLEAR PASSCODE FAILURE FLAG
MOV A,#1 ;WRITE PASSCODE FAILURE TO LOG
MOVX @DPTR,A
INC DPTR ;INCREMENT TO NEXT LOCATION
MOV A,PASSCODE_2 ;WRITE 1st PASSCODE TO LOG
MOVX @DPTR,A
INC DPTR
MOV A,PASSCODE_2+1
MOVX @DPTR,A
INC DPTR
MOV A,PASSCODE_2+3
MOVX @DPTR,A
INC DPTR
MOV FIX_BASE,#CODE_S ;CONVERT 2nd PASSCODE FOR STORAGE
MOV FIX_MOVE,#PASSCODE_2
LCALL FIX ;FIX ALL UNTIL IT SEES FF
MOV A,PASSCODE_2 ;WRITE 2st PASSCODE TO LOG
MOVX @DPTR,A
INC DPTR
MOV A,PASSCODE_2+1
MOVX @DPTR,A
INC DPTR
MOV A,PASSCODE_2+3
MOVX @DPTR,A
INC DPTR
MOV LOG_DPL,DPL ;STORE LOG POINTER
MOV LOG_DPH,DPH
SJMP STO4 ;WRITE TIME/DATE TO LOG
STO0: MOV A,#0
MOVX @DPTR,A ;VALID TRANSACTION CODE WRITTEN TO LOG
MOV LOG_DPL,DPL ;STORE LOG POINTER
MOV LOG_DPH,DPH
JB ELEVEN,STO1 ;ELEVEN (11) DIGITS ?
MOV DPTR,#0 ;GET LOCAL AREACODE, PUT IT IN AREACODE_TEMP
MOVX A,@DPTR
INC DPTR
MOV AREACODE_TEMP+1,A
MOV FIX_MOVE,#AREACODE_TEMP+2;SETUP FIX MOVE
MOV FIX_BASE,#DIGIT_D ;SETUP FIX BASE
LCALL FIX ;FIX ALL UNTIL IT SEES FF
SJMP STO2
STO1: MOV FIX_MOVE,#AREACODE_TEMP
MOV FIX_BASE,#DIGIT_D
LCALL FIX ;FIX ALL UNTIL IT SEES FF
STO2: MOV DPL,LOG_DPL ;RESTORE "LOG" ADDRESS
MOV DPH,LOG_DPH
MOV R0,#AREACODE_TEMP ;SET BASE ADDRESS
STO3: MOV A,@R0
MOVX @DPTR,A
INC R0
INC DPTR
CJNE R0,#AREACODE_TEMP+6,STO3
STO4: PUSH DPL
PUSH DPH
MOV DPTR,#MONTH ;MONTH
MOVX A,@DPTR
POP DPH
POP DPL
MOVX @DPTR,A
INC DPTR
PUSH DPL
PUSH DPH
MOV DPTR,#DAY_OF_MONTH ;DAY
MOVX A,@DPTR
POP DPH
POP DPL
MOVX @DPTR,A
INC DPTR
PUSH DPL
PUSH DPH
MOV DPTR,#HOURS ;HOURS
MOVX A,@DPTR
POP DPH
POP DPL
MOVX @DPTR,A
INC DPTR
PUSH DPL
PUSH DPH
MOV DPTR,#MINUTES ;MINUTES
MOVX A,@DPTR
POP DPH
POP DPL
MOVX @DPTR,A
INC DPTR
MOV A,#0FFH ;END CENTINAL (FF)
MOVX @DPTR,A
INC DPTR
MOV LOG_DPL,DPL ;STORE END OF "LOG" ADDRESS
MOV LOG_DPH,DPH
CJNE LOG_DPH,#3FH,MOV_3 ;FIND CLOSE TO END OF RAM
; * MOVES THE DATA DOWN WHEN FULL *
MOV DPTR,#LOG_BASE ;SET UP BASE ADDRESS
MOV_0: INC DPTR
MOVX A,@DPTR ;GET DATA, TRY TO FIND END OF 1st ENTRY
CJNE A,#0FFH,MOV_0 ;END OF 1st ENTRY?
MOV_1: INC DPTR
MOVX A,@DPTR ;GET DATA, TRY TO FIND END OF 2nd ENTRY
CJNE A,#0FFH,MOV_1 ;END OF 2nd ENTRY
INC DPTR
MOV DPL_HIGH,DPL
MOV DPH_HIGH,DPH
MOV DPTR,#LOG_BASE
PUSH DPL
PUSH DPH
MOV DPL,DPL_HIGH
MOV DPH,DPH_HIGH
MOV_2: MOVX A,@DPTR ;GET DATA TO MOVE
INC DPTR
MOV DPL_HIGH,DPL
MOV DPH_HIGH,DPH
POP DPH
POP DPL
MOVX @DPTR,A ;MOVE DATA TO NEW LOCATION
INC DPTR
PUSH DPL
PUSH DPH
MOV DPL,DPL_HIGH
MOV DPH,DPH_HIGH
MOV A,LOG_DPH
CJNE A,DPH,MOV_2
MOV A,LOG_DPL
CJNE A,DPL,MOV_2 ;IS IT THE END?
MOVX A,@DPTR ;GET LAST PIECE OF DATA TO MOVE
POP DPH
POP DPL
MOVX @DPTR,A
MOV LOG_DPH,DPH
MOV LOG_DPL,DPL
MOV_3: POP ACC
POP DPH
POP DPL
RET
; ------------------* CHECKING FOR DUPLICATE AREA CODE *-------------------
DUPLICATE:
PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
CLR DUP ;CLEAR DUPLICATE FLAG
MOV AREACODE_MASK,#1 ;CLEAR AREA CODE COUNT
MOV R0,#00H ;START AT BASE ADDRESS
DUP_1: CJNE R0,#7,DUP_2
SJMP DUP_END
DUP_2: MOVX A,@R0 ;INPUT DATA
CJNE A,AREACODE_TEMP,NO_END1 ;IF = ,THEN CONTINUE
INC R0 ;INCREMENT DATA POINTER
MOVX A,@R0 ;INPUT DATA
CJNE A,AREACODE_TEMP+1,NO_END2
SETB DUP
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
NO_END1:CJNE A,#0FFH,NO_END3 ;CHECK FOR END
DUP_END:POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
NO_END2:CJNE A,#0FFH,NO_END4 ;CHECK FOR END
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
NO_END3:INC R0 ;INCREMENT RAM POINTER
NO_END4:INC R0 ;INCREMENT RAM POINTER
MOV A,AREACODE_MASK ;GET
RL A ;ROTATE LEFT
MOV AREACODE_MASK,A ;PUT BACK
SJMP DUP_1 ;GO BACK AND GET MORE
; -------------------* LOCAL CALLING AREA LOOKUP *-------------------------
LOCAL: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
MOV A,DIGIT_D ;GET 1st DIGIT
CJNE A,#1,L_3 ;IS IT A "1"?
; * PREFIX TO DPTR ADDRESS CONVERSION (11-DIGITS) *
MOV FIX_BASE,#DIGIT_D ;SET FIX BASE ADDRESS
MOV FIX_MOVE,#AREACODE_TEMP;SET FIX DATA MOVE
LCALL FIX_ONE ;1st DIGIT
LCALL FIX_ONE ;2nd DIGIT
LCALL FIX_ONE ;3rd DIGIT
LCALL FIX_ONE ;4th DIGIT
MOV A,AREACODE_TEMP
ORL A,#0FH ;MASK
MOV AREACODE_TEMP,A
LCALL DUPLICATE ;FIND WHAT AREA CODE & CHECK FOR DUPLICATE
JB DUP,L_1
CLR OK_NUMBER
POP ACC
POP DPH
POP DPL
RET
L_1: MOV DPH,AREACODE_TEMP+3
MOV DPL,AREACODE_TEMP+4 ;LOAD INTO DPTR
; * CHECKING SET BIT *
L_2: MOVX A,@DPTR ;GET DATA
ANL A,AREACODE_MASK ;MASK OUT OTHER BITS
CJNE A,#00H,L_END1 ;MATCH?
CLR OK_NUMBER ;NO MATCH
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
L_END1: SETB OK_NUMBER ;MATCH, SET LOCAL BIT
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; * PREFIX TO DPTR ADDRESS CONVERSION (7-DIGIT) *
L_3: MOV FIX_BASE,#DIGIT_D
MOV FIX_MOVE,#AREACODE_TEMP
LCALL FIX_ONE
LCALL FIX_ONE
MOV DPH,AREACODE_TEMP
MOV DPL,AREACODE_TEMP+1 ;LOAD INTO DPTR
MOV TEMP1,#1
SJMP L_2
; * TWO DIGITS POINTED TO BY R0, DESTINATION (BCD) BY R1 *
FIX: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
SETB RS0 ;SET TO 2nd BANK OF REGISTERS
FIX0: MOV A,@R0 ;GET THE DATA
CJNE A,#0FFH,FIX2 ;CHECK TO SEE IF IT IS THE END (FF)
SETB FIX_DONE ;IT IS DONE SO SET THE FLAG AND EXIT
CLR RS0 ;RESET BACK TO MAIN REGISTER GROUP
POP ACC
POP DPH
POP DPL
RET
FIX2: SWAP A ;PUT IN UPPER NIBBLE
ANL A,#0F0H ;MASK OUT UNWANTED DATA
INC R0 ;INCREMENT GET DATA POINTER
MOV DIGIT,A ;MOVE IT INTO DIGIT FOR A WHILE
MOV A,@R0 ;GET ANOTHER ONE
ANL A,#0FH ;MASK OUT UNWANTED NIBBLE
ADD A,DIGIT ;ADD THE TWO TOGETHER
MOV @R1,A ;MOVE THE DATA TO DESTINATION
INC R0 ;INCREMENT TO NEXT
INC R1 ;INCREMENT TO NEXT
SJMP FIX0 ;DO AGAIN
; * COMBINES TO BCD ONE TIME *
FIX_ONE:PUSH DPL
PUSH DPH
PUSH ACC
SETB RS0
MOV A,@R0
ANL A,#0FH
SWAP A
ADD A,@R0
MOV @R1,A
INC R0
INC R1
CLR RS0
POP ACC
POP DPH
POP DPL
RET
; * PLACES A "1" IN THE UPPER NIBBLE *
ONE_FIX:PUSH DPL
PUSH DPH
PUSH ACC
SETB RS0 ;SET TO 2nd REGISTER BANK
MOV A,@R0 ;GET THE DATA
ANL A,#0FH ;MASK OUT UPPER NIBBLE
ADD A,#10H ;ADD A "1" TO THE UPPER NIBBLE FOR THE 1+
MOV @R1,A ;MOVE DATA TO DESTINATION
INC R0 ;INCREMENT TO NEXT
INC R1 ;INCREMENT TO NEXT
CLR RS0 ;BACK TO 1st REGISTER BANK
POP ACC
POP DPH
POP DPL
RET
; * PLACES A "0" IN THE UPPER NIBBLE *
ZERO_FIX:PUSH DPL
PUSH DPH
PUSH ACC
SETB RS0 ;SET TO 2nd REGISTER BANK
MOV A,@R0 ;GET THE DATA
ANL A,#0FH ;MASK OUT UPPER NIBBLE
MOV @R1,A ;MOVE THE DATA TO DESTINATION
INC R0 ;INCREMENT TO NEXT
INC R1 ;INCREMENT TO NEXT
CLR RS0 ;BACK TO 1st REGISTER BANK
POP ACC
POP DPH
POP DPL
RET
; * CHANGE OPTIONS AND ACCESS CODE *
; CHANGING THE ACCESS CODE
; THE "*" WILL LET THE PROGRAM INTO HERE. DEFAULT ACCESS CODE IS "555555" AND
; YOU DIAL THE "#" TO ACTIVATE IT. TO CHANGE THE DEFAULT, DIAL THE
; DEFAULT OR OLD ACCESS CODE, THEN THE NEW CODE.
; * CHECK IF SECURITY BIT IS SET *
OPTION: PUSH DPL
PUSH DPH
PUSH ACC
LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_OPTIONS
LCALL SEND_M ;DISPLAY: "....Options.....2
MOV PORTAO,#DIALTONE ;OUTPUT DIALTONE DATA
LCALL AOUT ;OUTPUT TO PORT
MOV A,#6 ;SETUP TO
LCALL BEEPR ;BEEP 6-TIMES
CLR CALLPROG ;TURN ON THE DIALTONE
LCALL BOUT ;OUTPUT TO PORT
OPTION1:JNB SECURITY,OPT1 ;IF SECURITY NOT ON, SKIP NEXT INSTRUCTION
;IF THE ACCESS CODE IS ENABLED, THE ONLY WAY
LCALL PASSCODE ; TO BE ABLE TO CHANGE THIS ACCESS CODE IS
;TO FIRST ENTER THE ACCESS CODE, THEN
;ENTER THE NEW ONE
JB TIMED_OUT,RING2
JNB PASSCODE_NOT,OPT1 ;VALIDITY OF THE PASSCODE
LCALL LOG ;WRITE DATA TO THE CALLING LOG
SJMP RING2
OPT1: MOV R0,#CODE_S ; LOAD ADDRESS TO WHERE THE CODE IS STORED
LCALL WAIT_DIGIT ;COLLECT THE FIRST DIGIT OF SIX
JB TIMED_OUT,RING2 ;START AGAIN IF TIMED OUT
JB POUND,SECDEF ;IF "#" THEN USE DEFAULT ACCESS CODE
JB STAR,OPT ;IF "*" THEN GOTO OPTIONS
LCALL FIVEDIGIT ;COLLECT FIVE DIGITS
JB TIMED_OUT,RING2
JB POUND,RING2 ;BACK TO DIALTONE IF POUND IS DIALED
JB STAR,RING2 ;BACK TO DIALTONE IF STAR IS DIALED
MOV DPTR,#PASSCODE_1 ;ACCESS CODE STARTING ADDRESS
MOV A,CODE_S ;RELOCATE THEM FROM "CODE_S to ACCESS CODE"
MOVX @DPTR,A ;1st DIGIT
INC DPTR ;INCREMENT DATA POINTER
MOV A,CODE_S+1
MOVX @DPTR,A ;2nd DIGIT
INC DPTR ;INCREMENT DATA POINTER
MOV A,CODE_S+2
MOVX @DPTR,A ;3rd DIGIT
INC DPTR ;INCREMENT DATA POINTER
MOV A,CODE_S+3
MOVX @DPTR,A ;4th DIGIT
INC DPTR ;INCREMENT DATA POINTER
MOV A,CODE_S+4
MOVX @DPTR,A ;5th DIGIT
INC DPTR ;INCREMENT DATA POINTER
MOV A,CODE_S+5
MOVX @DPTR,A ;6th DIGIT
SECDEF: SETB SECURITY ;TURN ON THE SECURITY BIT TO ACTIVATE CODE
OPTBPR: MOV PORTAO,#ASTERISK ;LOAD STAR
LCALL AOUT ;OUTPUT TO PORT
MOV A,#6 ;BEEP 6-TIMES
LCALL BEEPR ;BEEP SAYING THAT THE OPTIONS IS FINNISHED
RING2: POP ACC
POP DPH
POP DPL
RET ;GET DIAL TONE BACK AND READY TO DIAL AGAIN
; * FEATURE OPTIONS *
OPT: CLR STAR ;CLEAR STAR FLAG
JB POUND,RING2 ;IF POUND "#" WAS DIALED, THEN EXIT
LCALL PASSCODE ;NEED ACCESS CODE BEFORE CHANGING OPTIONS
JB TIMED_OUT,RING2 ;TIMEDOUT?
JNB PASSCODE_NOT,OPTA
LCALL LOG ;WRITE DATA TO THE CALLING LOG
SJMP RING2
OPTA: MOV RX_BASE,#DIGIT_D ;STARTING ADDRESS OF DIGIT STORAGE
LCALL WAIT_DIGIT ;COLLECTING OPTION CODE
JB TIMED_OUT,RING2
JB STAR,RING2 ;IF "*" IS DIALED, THEN BACK TO DIAL-TONE
JB POUND,RING2 ;IF "#" IS DIALED, THEN BACK TO DIAL-TONE
; * CHECK WHAT OPTION WAS DIALED *
CJNE DIGIT,#1,OPT0 ;IF "1" THEN SCAN CALL HISTORY
LCALL HISTORY ;GOTO HISTORY OF PHONE CALLS
AJMP OPTBPR ;OPTION BEEPER
OPT0: CJNE DIGIT,#2,OPT2 ;IF "2" THEN ADD AREA CODE & PREFIX
JNB N_LOCAL,OPT00 ;CHECK FOR NO CALL RESTRICTION FLAG
MOV R0,#0
MOVX A,@R0 ;GET 1st AREACODE TO SEE IF IT IS THERE
CJNE A,#0FFH,OPT00
LCALL N_INIT ;INITIALIZE IF IT IS NOT THERE
AJMP OPTBPR
OPT00: LCALL ADD_NUM ;GOTO ADDING A PREFIX
AJMP OPTBPR ;OPTION BEEPER
OPT2: CJNE DIGIT,#3,OPT3 ;IF "3" THEN DELETE AREA CODE/PREFIX ENTRY
LCALL DEL_NUM ;GOTO DELETMNG A PREFIX
AJMP OPTBPR ;OPTION BEEPER
OPT3: CJNE DIGIT,#4,OPT4 ;IF "4" THEN REGULAR DIALTONE WILL BE USED
LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_DIALTONE_S
LCALL SEND_M ;DISPLAY: "Regular Dialtone"
CLR _400HZ ;CHANGE TO REGULAR DIALTONE
AJMP OPTBPR ;OPTION BEEPER
OPT4: CJNE DIGIT,#5,OPT5 ;IF "5" THEN 400Hz DIALTONE WILL BE USED
LCALL CLR_DSP
MOV DPTR,#D_DIALTONE_400
LCALL SEND_M ;DISPLAY: "400Hz Dialtone"
SETB _400HZ ;CHANGE TO 400Hz DIALTONE
AJMP OPTBPR ;OPTION BEEPER
OPT5: CJNE DIGIT,#6,OPT6 ;IF "6" THEN DISABLE RELAY OPTION
LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_RELAY_OFF
LCALL SEND_M ;DISPLAY: "Relay Option OFF"
CLR RLY_OPT ;TURN RELAY OPTION OFF
AJMP OPTBPR ;OPTION BEEPER
OPT6: CJNE DIGIT,#7,OPT7 ;IF "7" THEN ENABLE THE RELAY OPTION
LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_RELAY_ON
LCALL SEND_M ;DISPLAY: "Relay Option ON"
SETB RLY_OPT ;TURN RELAY OPTION ON
AJMP OPTBPR ;OPTION BEEPER
OPT7: CJNE DIGIT,#8,OPT8 ;IF "8" THEN DISABLE LOCAL CALLING
LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_LOCAL_DISABLE
LCALL SEND_M ;DISPLAY: "Local Disabled"
SETB N_LOCAL ;LOCAL CALLING ONLY DISABLED
AJMP OPTBPR ;OPTION BEEPER
OPT8: CJNE DIGIT,#9,OPT9 ;IF "9" THEN ENABLE LOCAL CALLING
LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_LOCAL_ENABLE
LCALL SEND_M ;DISPLAY: "Local Enable"
MOV R0,#0
MOVX A,@R0
CJNE A,#0FFH,OPT80
LCALL N_INIT ;INITIALIZE IF IT CANNOT BE FOUND
AJMP OPTBPR ;OPTION BEEPER
OPT80: SETB N_LOCAL ;KEEP SET FOR NO CALL RESTRICTION
AJMP OPTBPR
OPT9: CJNE DIGIT,#0AH,RING2A ;IF "0" THEN EXTEND TIME
LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_EXTEND ;DISPLAY: "Call Extender:"
MOV R0,#DIGIT_D ;STARTING ADDRESS OF DIGIT STORAGE
LCALL WAIT_DIGIT ;COLLECT DIGIT, X-Times
JB TIMED_OUT,RING2A
MOV EXTND_X,A ;MOVE X-TIMES TO EXTEND IN EXTND_X
AJMP OPTBPR ;OPTION BEEPER
RING2A: AJMP RING2
; ------------------------* DIALING ROUTINE *------------------------------
; * DIALS THE OUTBOUND NUMBER *
DIAL: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_DIALING ;DISPLAY "..Dialing Out.."
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOV A,#DIGIT_D ;DIGIT PHONE NUMBER OFFSET ADDRESS
ADD A,COUNTDONE
MOV DIGIT_OFF,A ;END ADDRESS OF DIALED NUMBER
CLR POUND ;CLEAR THE POUND FLAG
DIAL2: MOV R0,A ;OFFSET INTO INDEX R0
MOV A,@R0 ;LOAD A WITH FIRST DIGIT + OFFSET
POUND2: LCALL AOUT ;OUTPUT TO PORTA
JB MF,MF3 ;SEE IF MF DIALING IS NEEDED
SETB DTMFG ;TURN ON DTMF GENERATOR
LCALL BOUT ;OUTPUT TO PORT
SJMP MF4
MF3: CLR MF_G ;TURN ON THE MF GENERATOR
LCALL BOUT ;OUTPUT TO PORT
MF4: MOV TH0,#0FAH
MOV TL0,#00H ;RELOAD TIMER COUNT
MOV COUNT1,#0AH ;---------------------------------------------
;100mS DTMF ON-TIME |
DIALA: CLR COUNT ; |
; ;---------------------------------------------
CLR DTMFG ;TURN OFF DTMF GENERATOR
SETB MF_G ;TURN OFF MF GENERATOR
LCALL BOUT ;OUTPUT TO PORT
MOV COUNT1,#0AH ;---------------------------------------------
;100mS DTMF OFF-TIME |
DIALB: JNB COUNT,$ ; |
; ;---------------------------------------------
JB POUND,DIAL_D ;CHECK FOR LAST DIGIT SO POUND CAN BE DIALED
MOV A,R0
CJNE A,DIGIT_OFF,DIAL1 ;SEE IF IT IS DONE DIALING
SJMP DIAL_D ;FINNISHED DIALING? THEN GO TO TALK MODE
DIAL1: INC R0 ;INCREMENT POINTER TO THE NEXT DIGIT
SJMP DIAL2
DIAL_D: JB POUND,DIAL_D2 ;CHECK IF POUND SHOULD BE DIALED
SETB POUND ;SET THE POUND STATUS BIT
JB MF,DIAL_D1 ;CHECK FOR THE MF STATUS BIT
MOV A,#0CH ;VALUE FOR DIALING THE "#"
SJMP POUND2
DIAL_D1:MOV A,#0BH ;VALUE FOR DIALING "ST"
SJMP POUND2
DIAL_D2:CLR POUND ;CLEAR THE POUND STATUS BIT
CLR MF ;CLEAR THE MF STATUS BIT
MOV COUNTDONE,#00H ;SO NOT TO CONFLICT WITH DISPLAY ROUTINE AND
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; --------* WAIT LOOP WAITING FOR DIGITS AND KEYS TO BE DIALED *-----------
; STAYS IN A THIRTY SECOND TIMING LOOP WAITING FOR THE DTMF STROBE LINE
; AND SETS THE STAR AND POUND FLAGS WHEN THEY ARE RECEIVED
;
WAIT_DIGIT:
PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
CLR TIMED_OUT ;CLEAR TIMED OUT FLAG
SETB RS0
SETB RS1 ;SET TO REGISTER BANK 3
SETB CALLPROG ;TURN OFF DIALTONE
LCALL BOUT ;OUTPUT TO PORT
CLR STAR ;CLEAR BOTH STAR & POUND FLAGS
CLR POUND
MOV TH0,#0FAH ;RELOAD TIMER COUNT
MOV TL0,#00H
MOV COUNT2,#0BH ;---------------------------------------------
MOV COUNT1,#0BAH ;30-SECOND TIMER,WAITING FOR DIGITS |
WAITLP: LCALL BIN ;INPUT FROM PORT |
JB DTMFR,WAITLP1 ;CHECK THE DTMF STROBE LINE |
JB VALID_DATA,WAITKEY ;CHECK FOR KEYBOARD ENTRY |
JNB COUNT,WAITLP ;HAS THE TIMER TIMED OUT? |
SETB TIMED_OUT ;---------------------------------------------
SJMP TONENP2
WAITKEY: LCALL SEND_D ;SEND CHARACTER
JB VALID_DATA,$ ;CONTINUE WHEN KEY IS DEPRESSED
SJMP TONEOK
WAITLP1: LCALL BIN ;INPUT FROM PORT
JB DTMFR,WAITLP1 ;CONTINUE WHEN NO DTMF
TONEOK: MOV COUNT1,#00H
MOV COUNT2,#00H
JNB KEY,TONEO ;CHECK FOR KEYBOARD ENTRY
MOV A,BUFFER
SJMP TONEK
TONEO: LCALL AIN ;INPUT FROM PORT
ANL A,#0FH ;MASK OUT THE UNWANTED HALF
TONEK: MOV @RX_BASER0,A ;STORE THE DATA
MOV DIGIT,A ;SECOND STORAGE FOR DTMF OR KEYBOARD
CJNE A,#0BH,TONENP1 ;IS IT A "*"
SETB STAR ;SET THE STAR FLAG WHEN THE "*" IS DETECTED
TONENP1:CJNE A,#0CH,TONENP ;IS IT A "#"
SETB POUND ;SET THE POUND FLAG WHEN THE "#" IS DETECTED
TONENP: CJNE RX_BASER0,#DIGIT_D,TONENP2;1st DIGIT?
CJNE A,#1,TONENP2
SETB ELEVEN
TONENP2:INC R0 ;RLG
CLR RS1
CLR RS0 ;BACK TO REGISTER BANK #1
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; -------------------------* PRESS ANY KEY *-------------------------------
ANY_KEY:
PUSH ACC
PUSH DPL
PUSH DPH
MOV DPTR ,#D_PRESS_ANY
LCALL SEND_M ;DISPLAY: 'Press Any Key...'
LCALL WAIT_DIGIT
POP DPH
POP DPL
POP ACC
RET
; -------------------------* COLLECT FIVE DIGITS *-------------------------
FIVEDIGIT:
PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
MOV A,#5 ;COUNTDOWN8FIVE TIMES FOR FIVE DIGITS
FIVE_D: LCALL WAIT_DIGIT ;COLLECT A DIGIT
JB TIMED_OUT,EXIT ;TIMEDOUT?
JB STAR,EXIT ;EXIT IF IT IS A "*"
JB POUND,EXIT ;EXIT IF IT IS A "#"
DEC A ;DECREMENT "A"
CJNE A,#00H,FIVE_D ;COLLECT ANOTHER DIGIT IF "A" IS NOT ZERO
EXIT: POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; -----------------------* CHECK PRESENT ACCESS CODE *---------------------
PASSCODE:
PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
PASS1: MOV A,#0FFH ;CLEAR 2nd PASSCODE SPACE
MOV PASSCODE_2,A
MOV PASSCODE_1+1,A
MOV PASSCODE_2+2,A
MOV CODE_S,A
MOV CODE_S+1,A
MOV CODE_S+2,A
MOV CODE_S+3,A
MOV CODE_S+4,A
MOV CODE_S+5,A
MOV CODE_S+6,A
CLR CALLPROG ;TURN ON THE DIALTONE
LCALL BOUT ;OUTPUT TO PORT
LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_ACCESS
LCALL SEND_M ;DISPLAY: "....Passcode....","..#:"
POP DPH
POP DPL
MOV DPTR,#PASSCODE_1 ;LOAD ADDRESS OF STORAGE
MOV RX_BASE,#CODE_S
LCALL WAIT_DIGIT ;FIRST OF SIX DIGITS TO STORE
JB STAR,PASS1 ; IF "*" IS DIALED, DO AGAIN
JB POUND,PASS1 ; IF "#" IS DIALED, DO AGAIN
LCALL FIVEDIGIT ;COLLECT FIVE DIGITS
JB TIMED_OUT,CODE_P ;TIMEDOUT?
JB POUND,PASS1 ;BRANCH IF "#", USED TO CORRECT AN error
JB STAR,PASS1 ;BRANCH IF "*", USED TO CORRECT AN error
MOVX A,@DPTR
INC DPTR
CJNE A,CODE_S,ALTN
MOVX A,@DPTR
INC DPTR
CJNE A,CODE_S+1,ALTN ;COMPAIR FIRST DIGIT
MOVX A,@DPTR
INC DPTR
CJNE A,CODE_S+2,ALTN ;COMPAIR FIRST DIGIT
MOVX A,@DPTR
INC DPTR
CJNE A,CODE_S+3,ALTN ;COMPAIR FIRST DIGIT
MOVX A,@DPTR
INC DPTR
CJNE A,CODE_S+4,ALTN ;COMPAIR FIRST DIGIT
MOVX A,@DPTR
CJNE A,CODE_S+5,ALTN ;COMPAIR FIRST DIGIT
CODE_P: CLR PASSCODE_NOT
CODE_P1:POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
ALTN: SETB PASSCODE_NOT ;NOT A VALID PASSCODE
MOV FIX_BASE,#CODE_S
MOV FIX_MOVE,#PASSCODE_2
LCALL FIX ;FIX ALL UNTIL IT SEES FF
MOV A,#0FFH
MOV CODE_S,A ;CLEAR PASSCODE AREA
MOV CODE_S+1,A
MOV CODE_S+2,A
MOV CODE_S+3,A
MOV CODE_S+4,A
MOV CODE_S+5,A
MOV CODE_S+6,A
CLR CALLPROG ;TURN ON DIALTONE
LCALL BOUT ;OUTPUT TO PORT
PUSH DPL
PUSH DPH
MOV DPTR,#D_TRY_AGAIN
LCALL SEND_M ;DISPLAY: "Try it Again...."
POP DPH
POP DPL
MOV DPTR,#PASSCODE_1 ;LOAD ADDRESS OF STORAGE
MOV RX_BASE,#CODE_S
LCALL WAIT_DIGIT ;FIRST OF SIX DIGITS TO STORE
JB STAR,ALTN ; IF "*" IS DIALED, GOTO ALTERNATING TONES
JB POUND,ALTN ; IF "#" IS DIALED, GOTO ALTERNATING TONES
LCALL FIVEDIGIT ;COLLECT FIVE DIGITS
JB TIMED_OUT,CODE_P ;TIMEDOUT?
JB POUND,ALTN ;BRANCH IF "#", USED TO CORRECT AN error
JB STAR,ALTN ;BRANCH IF "*", USED TO CORRECT AN error
MOVX A,@DPTR
INC DPTR
CJNE A,CODE_S,CODE_P
MOVX A,@DPTR
INC DPTR
CJNE A,CODE_S+1,CODE_P ;COMPAIR FIRST DIGIT
MOVX A,@DPTR
INC DPTR
CJNE A,CODE_S+2,CODE_P ;COMPAIR FIRST DIGIT
MOVX A,@DPTR
INC DPTR
CJNE A,CODE_S+3,CODE_P ;COMPAIR FIRST DIGIT
MOVX A,@DPTR
INC DPTR
CJNE A,CODE_S+4,CODE_P ;COMPAIR FIRST DIGIT
MOVX A,@DPTR
CJNE A,CODE_S+5,CODE_P ;COMPAIR FIRST DIGIT
CLR PASSCODE_NOT
SJMP CODE_P1
; --------------* CONFORMATION BEEP FOR DIFFERENT FUNCTIONS *--------------
; LOAD "A" WITH THE AMOUNT OF BEEPS
BEEPR: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
MOV TEMP1,A ;SET UP NUMBER OF BEEPS
TOBP3: MOV TH0,#0FAH ;RELOAD TIMER COUNT
MOV TL0,#00H
MOV COUNT1,#19H ;---------------------------------------------
CLR CALLPROG ;TURN ON THE CALL PROGRESS GENERATOR 200mS |
LCALL BOUT ;OUTPUT TO PORT |
TOBP1: JNB COUNT,$ ;TEST TO SEE IF THE COUNT IS FINNISHED |
; ;---------------------------------------------
DEC TEMP1 ;DECREMENT REPITITION COUNT
SETB CALLPROG ;TURN OFF CALL PROGRESS GENERATOR
LCALL BOUT ;OUTPUT TO PORT
MOV COUNT1,#19H ;---------------------------------------------
;200mS BEEP TONE OFF-TIME |
TOBP2: JNB COUNT,$ ;TEST TO SEE IF THE COUNT IS FINNISHED |
; ;---------------------------------------------
DJNZ TEMP1,TOBP3 ;DECREMENT REPITITION COUNT
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; ------------------------* FLASH THE SWITCHHOOK *-------------------------
; * PLACE INTO AND OUT OF 3-WAY *
FLASH: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
LCALL CLR_DSP ;CLEAR DISPLAY
MOV DPTR,#D_FLASH ;DISPLAY: "Flash Swtichhook"
LCALL SEND_M ;SEND MESSAGE
CLR SWITCHHOOK ;HANG UP PHONE LINE
LCALL BOUT ;OUTPUT TO PORT
MOV TH0,#0FAH ;RELOAD TIMER COUNT
MOV TL0,#00H
MOV COUNT1,#32H ;---------------------------------------------
;500mS DELAY HANG-UP TIME |
TW2: JNB COUNT,$ ; |
; ;---------------------------------------------
SETB SWITCHHOOK ;ANSWER PHONE LINE
LCALL BOUT ;OUTPUT TO PORT
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; ------------------------* DISPLAY ROUTINES *-----------------------------
; * CONVERT NUMBERS TO ASCII AND DISPLAY *
SEND_D: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
CJNE A,#0BH,N_STR
MOV TEMP1,A
MOV A,#2AH ;CONVERT NUMBER FOR "*" FROM 0BH TO 2AH
SJMP DS1
N_STR: CJNE A,#0CH,N_PND
MOV TEMP1,A
MOV A,#23H ;CONVERT NUMBER FOR "#" FROM 0CH TO 23H
SJMP DS1
N_PND: CJNE A,#0AH,N_10
MOV TEMP1,A
MOV A,#30H ;CONVERT "0" FROM 0AH TO 30H
SJMP DS1
N_10: MOV TEMP1,A
ADD A,#30H ;CONVERT DIGITS BY ADDING 30H
DS1: MOV DPTR,#DISPLAY ;EXTERNAL ACCESS
MOVX @DPTR,A ;OUTPUT TO PORT
MOV A,TEMP1 ;RESTORE OLD VALUE
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET ;RETURN FROM SUBROUTINE
; ------------------------* SEND MESSAGE *---------------------------------
; * 40uS TIME FOR DISPLAY OPERATION *
SEND_M: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
MOV A,#00H ;SET TO POINT
MOV DSP_TEMP,A ;KEEPS VALUE OF "A"
SND_M: MOVC A,@A+DPTR ;READ DISPLAY DATA FROM PROGRAM MEMORY
CJNE A,#-1,END_CHR ;CHECK IF END (-1)
MOV DPH_TEMP,DPH ;STORE DPTR HIGH (DISPLAY ADDRESS HIGH)
MOV DPL_TEMP,DPL ;STORE DPTR LOW (DISPLAY ADDRESS LOW)
MOV DPTR,#DISPLAY ;DISPLAY ADDRESS
MOVX @DPTR,A ;OUTPUT CHARACTER TO DISPLAY
INC DSP_TEMP ;INCREMENT TO NEXT CHARACTER
MOV DPH,DPH_TEMP ;RELOAD DPTR HIGH
MOV DPL,DPL_TEMP ;RELOAD DPTR LOW
MOV A,DSP_TEMP ;RELOAD POINT VALUE
SJMP SND_M ;GET NEXT CHARACTER
END_CHR:POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; ------------------------* CLEAR DISPLAY *--------------------------------
CLR_DSP:PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
MOV DPTR,#DISPLAY_R
MOV A,#1 ;VALUE TO CLEAR SCREEN
MOVX @DPTR,A ;WRITE TO DISPLAY
MOV TH0,#0FEH ;LOAD TIMER 0
MOV TL0,#0F0H
MOV COUNT1,#01H ;10mS DELAY
JNB COUNT,$ ;WAIT UNTIL CLEARED
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; * DISPLAY THE "HISTORY" OF CALLS *
HISTORY:PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
MOV DPTR,#LOG_BASE ;SET TO BASE ADDRESS
HIS_0: LCALL CLR_DSP
MOVX A,@DPTR ;GET DATA
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
INC DPTR
HIS_2: MOVX A,@DPTR ;AREACODE (2nd DIGIT)
SWAP A
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
MOVX A,@DPTR ;AREACODE (3rd DIGIT)
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
INC DPTR
PUSH DPL
PUSH DPH
MOV DPTR,#D_DASH ;DISPLAY: "-"
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOVX A,@DPTR ;PREFIX (1st DIGIT)
SWAP A
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
MOVX A,@DPTR ;PREFIX (2nd DIGIT)
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
INC DPTR
MOVX A,@DPTR ;PREFIX (3rd DIGIT)
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
PUSH DPL
PUSH DPH
MOV DPTR,#D_DASH ;DISPLAY: "-"
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOVX A,@DPTR ;NUMBER (4th DIGIT)
ANL A,#00001111B ;MASK
LCALL SEND_D
INC DPTR
MOVX A,@DPTR ;NUMBER (5th DIGIT)
SWAP A
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
MOVX A,@DPTR ;NUMBER (6th DIGIT)
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
INC DPTR
MOVX A,@DPTR ;NUMBER (7th DIGIT)
SWAP A
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
INC DPTR
PUSH DPL
PUSH DPH
MOV DPTR,#D_4_SPACES ;GET TO THE NEXT LINE ON THE DISPLAY
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOVX A,@DPTR ;MONTH (1st DIGIT)
SWAP A
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
MOVX A,@DPTR ;MONTH (2nd DIGIT)
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
PUSH DPL
PUSH DPH
MOV DPTR,#D_SLASH ;DISPLAY: "/"
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
INC DPTR
MOVX A,@DPTR ;DAY OF MONTH (1st DIGIT)
SWAP A
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
MOVX A,@DPTR ;DAY OF MONTH (2nd DIGIT)
ANL A,#0000111B ;MASK
LCALL SEND_D ;SEND DATA
PUSH DPL
PUSH DPH
MOV DPTR,#D_SLASH ;DISPLAY: "/"
LCALL SEND_M ;SEND MESSAGE
MOV DPTR,#D_SPACE ;ONE SPACE
LCALL SEND_M ;SEND SPACE
POP DPH
POP DPL
MOVX A,@DPTR ;HOUR (1st DIGIT)
MOV ROL_DATA,A
SWAP A
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
MOVX A,@DPTR ;HOUR (2nd DIGIT)
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
PUSH DPL
PUSH DPH
MOVX A,@DPTR ;MINUTE (1st DIGIT)
SWAP A
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
MOVX A,@DPTR ;MINUTE (2nd DIGIT)
ANL A,#00001111B ;MASK
LCALL SEND_D ;SEND DATA
PUSH DPL
PUSH DPH
JB CLOCK_BUSY,HIS_2B
MOV DPTR,#D_AM ;DISPLAY: " AM"
LCALL SEND_M ;SEND MESSAGE
SJMP HIS_2C
HIS_2B: MOV DPTR,#D_PM ;DISPLAY: " PM"
LCALL SEND_M ;SEND MESSAGE
HIS_2C: POP DPH
POP DPL
INC DPTR
MOV A,LOG_DPH
CJNE A,DPH,HIS_3A
MOV A,LOG_DPL
CJNE A,DPH,HIS_3A ;IS IT THE END OF HISTORY RAM ?
HIS_4: POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
HIS_3: INC DPTR
HIS_3A: MOVX A,@DPTR ;GET CENTINAL
CJNE A,#0FFH,HIS_3
INC DPTR
PUSH DPL
PUSH DPH
MOV RX_BASE,#DIGIT_D
LCALL WAIT_DIGIT
JB TIMED_OUT,HIS_4 ;TIMEDOUT?
CJNE A,#0CH,HIS_4 ;IS IT A "#" ?
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
AJMP HIS_0
; **** CLOCK ****
; ------------------------* SETTING THE CLOCK *----------------------------
CLOCK_SET:
PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
; * YEAR * RECEIVING DATA TO SET THE CLOCK
LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_ENTER_YEAR ;DISPLAY: "Enter Year 19"
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOV RX_BASE,#DIGIT_D ;RECEIVED DIGIT LOCATION
MOV FIX_BASE,#DIGIT_D ;SET FIX BASE ADDRESS
MOV FIX_MOVE,#AREACODE_TEMP;SET FOR FIX MOVE
LCALL WAIT_DIGIT ;COLLECT 1st DIGIT
JB TIMED_OUT,E_CTO1 ;TIMEDOUT?
MOV A,DIGIT ;GET DIGIT
CJNE A,#0AH,E_CL0 ;IS IT A "0"? (1st DIGIT)
PUSH DPL
PUSH DPH
MOV DPTR,#D_ENTER_Y_2 ;DISPLAY: "Enter Year 20"
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOV A,#00H ;DOING OVER SO..
LCALL SEND_D ;SEND NEW DATA (SEND '0')
E_CL0: LCALL WAIT_DIGIT ;COLLECT 2nd DIGIT
JB TIMED_OUT,E_CTO1 ;TIMEDOUT?
MOV A,DIGIT ;GET DIGIT
LCALL FIX_ONE ;MAKE INTO BCD (2nd HALF)
LCALL ANY_KEY ;DISPLAY: 'Hit Any Key...'
; * MONTH *
E_CL1A: LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_ENTER_MONTH ;DISPLAY: "Enter Month: "
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOV RX_BASE,#DIGIT_D ;SET BASE ADDRESS (NOT USED)
LCALL WAIT_DIGIT ;GET 1st DIGIT
CJNE A,#0AH,E_CL2 ;IS IT A "0"? (1st DIGIT)
MOV A,#00H
LCALL WAIT_DIGIT ;COLLECT 2nd DIGIT
JB TIMED_OUT,E_CTO1 ;TIMEDOUT?
MOV A,DIGIT ;GET DIGIT
CJNE A,#0AH,E_CL2A ;IS IT A "0"? (2nd DIGIT)
DEC R1 ;MOVE BACK POINTER
SJMP E_CL1A
E_CTO1: POP ACC
POP DPH
POP DPL
RET
E_CL2A: LCALL FIX_ONE ;MONTH: 01-09
SJMP E_CL5
E_CL2: CJNE A,#1,E_CL1A ;IS IT A "1"? (1st DIGIT)
E_CL2B: MOV RX_BASE,DIGIT_D
LCALL WAIT_DIGIT ;COLLECT 2nd DIGIT
JB TIMED_OUT,E_CTO1 ;TIMEDOUT?
MOV A,DIGIT ;GET DIGIT
CJNE A,#0AH,E_CL3 ;IS IT A "0"? (2nd DIGIT)
MOV A,#00H
SJMP E_CL5
E_CL3: CJNE A,#1,E_CL4 ;IS IT A "1"? (2nd DIGIT)
SJMP E_CL5
E_CL4: CJNE A,#2,E_CL2B ;IS IT A "2"? (2nd DIGIT)
E_CL5: LCALL FIX_ONE ;MAKE INTO BCD
LCALL ANY_KEY ;DISPLAY: 'Hit Any Key...'
; * DAY *
E_CL5A: LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_ENTER_DAY ;DISPLAY: "Enter Day: "
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOV RX_BASE,#DIGIT_D ;SET BASE ADDRESS (NOT USED)
LCALL WAIT_DIGIT ;COLLECT 1st DIGIT
JB TIMED_OUT,E_CTO1 ;TIMEDOUT?
MOV A,DIGIT ;GET DIGIT
CJNE A,#0AH,E_CL6 ;IS IT A "0"? (1st DIGIT)
MOV A,#00H
SJMP E_CLA
E_CL6: CJNE A,#1,E_CL7 ;IS IT A "1"? (1st DIGIT)
SJMP E_CLA
E_CL7: CJNE A,#2,E_CL8 ;IS IT A "2"? (1st DIGIT)
SJMP E_CLA
E_CL8: CJNE A,#3,E_CL5A ;IS IT A "3"? (1st DIGIT)
LCALL WAIT_DIGIT ;COLLECT 2nd DIGIT
JB TIMED_OUT,E_CTO1 ;TIMEDOUT?
MOV A,DIGIT ;GET DIGIT
CJNE A,#00H,E_CL9A ;IS IT A "0"? (2nd DIGIT)
MOV A,#0
SJMP E_CL9B
E_CL5B: DEC R1 ;DO AGAIN IF > 31
SJMP E_CL5A
E_CL9A: CJNE A,#1,E_CL5B ;IS IT A "1"? (2nd DIGIT)
E_CL9B: LCALL FIX_ONE ;MAKE INTO BCD
LCALL ANY_KEY ;DISPLAY: 'Hit Any Key...'
SJMP E_CLB
E_CLA: LCALL WAIT_DIGIT ;COLLECT 2nd DIGIT
JB TIMED_OUT,E_CTO2 ;TIMEDOUT?
MOV A,DIGIT ;GET DIGIT
CJNE A,#0AH,E_CLAA ;IS IT A "0"? (2nd DIGIT)
DEC R1
SJMP E_CL5A
E_CLAA: LCALL FIX_ONE ;MAKE INTO BCD
LCALL ANY_KEY ;DISPLAY: 'Hit Any Key...'
; * HOUR *
E_CLB: LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_ENTER_HOUR ;DISPLAY: "Enter Hour: "
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
MOV RX_BASE,#DIGIT_D ;SET BASE ADDRESS (NOT USED)
LCALL WAIT_DIGIT ;COLLECT 1st DIGIT
MOV A,DIGIT ;GET DIGIT
CJNE A,#0AH,E_CLD ;IS IT A "0"? (1st DIGIT)
MOV A,#0
LCALL WAIT_DIGIT ;COLLECT 2nd DIGIT
JB TIMED_OUT,E_CTO2 ;TIMEDOUT?
MOV A,DIGIT ;GET DIGIT
CJNE A,#0AH,E_CLC ;IS IT A "0"? (2nd DIGIT)
E_CLBA: DEC R1 ;GO BACK, DO OVER
SJMP E_CLB
E_CLC: MOV A,#0
LCALL FIX_ONE ;MAKE INTO BCD
SJMP E_CLH
E_CTO2: POP ACC
POP DPH
POP DPL
RET
E_CLD: CJNE A,#1,E_CLB ;IS IT A "1"? (1st DIGIT)
LCALL WAIT_DIGIT ;COLLECT 2nd DIGIT
JB TIMED_OUT,E_CTO2 ;TIMEDOUT?
MOV A,DIGIT ;GET DIGIT
CJNE A,#0AH,E_CLE ;IS IT A "0"? (2nd DIGIT)
MOV A,#0
SJMP E_CLG
E_CLE: CJNE A,#1,E_CLF ;IS IT A "1"? (2nd DIGIT)
SJMP E_CLG
E_CLF: CJNE A,#2,E_CLBA ;IS IT A "2"? (2nd DIGIT)
E_CLG: LCALL FIX_ONE ;MAKE INTO BCD
; * AM-PM *
E_CLH: PUSH DPL
PUSH DPH
MOV DPTR,#D_AM_PM ;DISPLAY: " *=AM #=PM "
LCALL SEND_M ;SEND MESSAGE
POP DPH
POP DPL
E_CLI: MOV RX_BASE,#DIGIT_D ;SET BASE ADDRESS, (NOT USED)
LCALL WAIT_DIGIT ;COLLECT DIGIT
MOV A,DIGIT ;GET DIGIT
CJNE A,#0BH,E_CLIA ;IS IT A "*"?
SJMP E_CLJ
E_CLIA: CJNE A,#0CH,E_CLH ;IS IT A "#"?
DEC R1 ;POINT BACK ONE
MOV A,@R1 ;GET DATA
ORL A,#10000000B ;TURN ON BIT
MOV @R1,A ;WRITE DATA BACK
LCALL ANY_KEY ;DISPLAY: 'Hit Any Key...'
; * MINUTE *
E_CLJ: LCALL CLR_DSP ;CLEAR DISPLAY
PUSH DPL
PUSH DPH
MOV DPTR,#D_ENTER_MIN ;DISPLAY: "Minutes: "
LCALL SEND_M
POP DPH
POP DPL
MOV RX_BASE,#DIGIT_D ;SET BASE ADDRESS (NOT USED)
LCALL WAIT_DIGIT ;COLLECT 1st DIGIT
JB TIMED_OUT,E_CTO ;TIMEDOUT?
MOV A,DIGIT ;GET DIGIT
CJNE A,#0AH,E_CLK ;IS IT A "0"? (1st DIGIT)
MOV A,#0
SJMP E_CLQ
E_CLK: CJNE A,#1,E_CLL ;IS IT A "1"? (1st DIGIT)
SJMP E_CLQ
E_CLL: CJNE A,#2,E_CLM ;IS IT A "2"? (1st DIGIT)
SJMP E_CLQ
E_CLM: CJNE A,#3,E_CLN ;IS IT A "3"? (1st DIGIT)
SJMP E_CLQ
E_CLN: CJNE A,#4,E_CLP ;IS IT A "4"? (1st DIGIT)
SJMP E_CLQ
E_CLP: CJNE A,#5,E_CLJ ;IS IT A "5"? (1st DIGIT)
E_CLQ: LCALL WAIT_DIGIT ;COLLECT 2nd DIGIT
JB TIMED_OUT,E_CTO ;TIMEDOUT?
MOV A,DIGIT ;GET DIGIT
LCALL FIX_ONE ;MAKE INTO BCD
LCALL ANY_KEY ;DISPLAY: 'Hit Any Key...'
; * WRITE DATA TO CLOCK *
MOV DPTR,#CLOCK_B ;CLOCK REGISTER B
MOVX A,@DPTR ;GET DATA FROM CLOCK REGISTER B
ORL A,#10000000B ;TURN ON "SET" BIT
MOVX @DPTR,A ;WRITE BACK TO CLOCK REGISTER B
MOV DPTR,#YEAR ;CLOCK "YEAR" ADDRESS
MOV R1,#AREACODE_TEMP ;SET BASE ADDRESS
MOV A,@R1 ;GET YEAR DATA
MOVX @DPTR,A ;WRITE TO "YEAR"
INC R1 ;NEXT TEMP STORAGE ADDRESS
DEC DPL ;MONTH ADDRESS
MOV A,@R1 ;GET MONTH DATA
MOVX @DPTR,A ;WRITE "MONTH" DATA
INC R1 ;NEXT TEMP STORAGE ADDRESS
DEC DPL ;DAY ADDRESS
MOV A,@R1 ;GET DAY ADDRESS
MOVX @DPTR,A ;WRITE "DAY" ADDRESS
INC R1 ;NEXT TEMP STORAGE ADDRESS
DEC DPL
DEC DPL
DEC DPL ;HOUR ADDRESS
MOV A,@R1 ;GET HOUR DATA
MOVX @DPTR,A ;WRITE "HOUR" ADDRESS
INC R1 ;NEXT TEMP STORAGE ADDRESS
DEC DPL
DEC DPL ;MINUTE ADDRESS
MOV A,@R1 ;GET MINUTE DATA
MOVX @DPTR,A ;WRITE "MINUTE" DATA
DEC DPL
DEC DPL ;SECONDS ADDRESS
MOV A,#0 ;DATA TO BE WRITTEN
MOVX @DPTR,A ;WRITE "SECONDS" DATA
MOV DPTR,#CLOCK_B ;SET ADDRESS, REGISTER B
MOVX A,@DPTR ;READ DATA FROM REGISTER B
ANL A,#01111111B ;TURN ON "SET" BIT
MOVX @DPTR,A ;WRITE DATA TO REGISTER B
E_CTO: POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; ---------------------* READ CLOCK DATA/UPDATE TIME *---------------------
UPDATE: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
MOV DPTR,#CLOCK_A
CL_1A: MOVX A,@DPTR
MOV ROL_DATA,A ;SET UP TO CHECK MSB
JB CLOCK_BUSY,UPDATE ;READ BUSY BIT, CONTINUE WHEN IT GOES AWAY
MOV DPTR,#MONTH
MOVX A,@DPTR ;READ DATA
LCALL D_BCD ;SEND MONTH TO DISPLAY
MOV DPTR,#D_SLASH
LCALL SEND_M ;SEND "/"
MOV DPTR,#DAY_OF_MONTH
MOVX A,@DPTR ;READ DATA
LCALL D_BCD ;SEND DAY of MONTH TO DISPLAY
MOV DPTR,#D_SLASH ;DISPLAY "/"
LCALL SEND_M ;SEND MESSAGE
MOV DPTR,#YEAR
MOVX A,@DPTR ;READ DATA
LCALL D_BCD ;SEND YEAR TO DISPLAY
MOV DPTR,#DAY_OF_WEEK
MOVX A,@DPTR ;READ DATA
CJNE A,#1,CL_1B
MOV DPTR,#D_SUNDAY ;SEND " SUN" TO DISPLAY
SJMP CL_1H
CL_1B: CJNE A,#2,CL_1C
MOV DPTR,#D_MONDAY ;SEND " MON" TO DISPLAY
SJMP CL_1H
CL_1C: CJNE A,#3,CL_1D
MOV DPTR,#D_TUESDAY ;SEND " TUE" TO DISPLAY
SJMP CL_1H
CL_1D: CJNE A,#4,CL_1E
MOV DPTR,#D_WEDNESDAY ;SEND " WED" TO DISPLAY
SJMP CL_1H
CL_1E: CJNE A,#5,CL_1F
MOV DPTR,#D_THURSDAY ;SEND " THU" TO DISPLAY
SJMP CL_1H
CL_1F: CJNE A,#6,CL_1G
MOV DPTR,#D_FRIDAY ;SEND " FRI" TO DISPLAY
SJMP CL_1H
CL_1G: MOV DPTR,#D_SATURDAY ;SEND " SAT" TO DISPLAY
CL_1H: LCALL SEND_M
MOV DPTR,#D_4_SPACES ;GOING TO THE NEXT LINE OF THE DISPLAY
LCALL SEND_M
MOV DPTR,#HOURS
MOVX A,@DPTR ;READ DATA
MOV ROL_DATA,A ;MOVE DATA FOR TESTING MSB (AM-PM)
LCALL D_BCD ;SEND HOUR TO DISPLAY
MOV DPTR,#D_COLON ;SEND ":"
LCALL SEND_M
MOV DPTR,#MINUTES
MOVX A,@DPTR ;READ DATA
LCALL D_BCD ;SEND MINUTES TO DISPLAY
MOV DPTR,#D_COLON ;SEND ":"
LCALL SEND_M
MOV DPTR,#SECONDS
MOVX A,@DPTR ;READ DATA
LCALL D_BCD ;SEND SECONDS TO DISPLAY
JB CLOCK_BUSY,CL_2
MOV DPTR,#D_AM ;SEND " AM" TO THE DISPLAY
LCALL SEND_M
SJMP CL_4
CL_2: MOV DPTR,#D_PM ;SEND " PM" TO THE DISPLAY
LCALL SEND_M
; * DAYLIGHT SAVINGS *
CL_4: MOV DPTR,#D_DAYLIGHT ;DISPLAY: "Daylight Savings",
LCALL SEND_M ; "Enable? *=Y #=N"
MOV RX_BASE,DIGIT_D ;BASE ADDRESS (NOT USED)
LCALL WAIT_DIGIT ;COLLECT DIGIT
MOV A,DIGIT ;GET DIGIT
CJNE A,#0BH,CL_5 ;IS IT A "*"?
MOV DPTR,#CLOCK_B
MOVX A,@DPTR ;READ DATA
ORL A,#00000001B ;SET LSB
MOVX @DPTR,A ;WRITE DATA
SJMP CL_6
CL_5: CJNE A,#0CH,CL_4 ;IS IT A "#"?
MOV DPTR,#CLOCK_B
MOVX A,@DPTR ;READ DATA
ANL A,#11111110B ;CLEAR LSB
MOVX @DPTR,A ;WRITE DATA
CL_6: POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; ----------* SEND ALL IN AREACODE_TEMP TO THE DISPLAY *-------------------
SEND_AC_P:
PUSH ACC
PUSH DPL
PUSH DPH
SETB RS0
MOV A,AREACODE_TEMP
ANL A,#0FH
LCALL SEND_D
MOV A,AREACODE_TEMP+1
SWAP A
ANL A,#0FH
LCALL SEND_D
MOV A,AREACODE_TEMP+1
ANL A,#0FH
LCALL SEND_D
MOV DPTR,#D_DASH
LCALL SEND_M
MOV A,AREACODE_TEMP+2
SWAP A
ANL A,#0FH
LCALL SEND_D
MOV A,AREACODE_TEMP+2
ANL A,#0FH
LCALL SEND_D
MOV A,AREACODE_TEMP+3
SWAP A
ANL A,#0FH
LCALL SEND_D
CLR RS0
POP DPH
POP DPL
POP ACC
RET
; ----------* COLLECT EXTERNAL DATA & SEND BCD VALUE TO DISPLAY *----------
D_BCD: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
MOVX A,@DPTR ;INPUT DATA FROM EXTERNAL MEMORY
SWAP A ;SWAP NIBBLES
ANL A,#00001111B ;MASK OUT UPPER HALF
LCALL SEND_D ;OUTPUT DATA TO DISPLAY
MOVX A,@DPTR ;INPUT DATA
ANL A,#00001111B ;MASK OUT UPPER HALP
LCALL SEND_D ;OUTPUT DATA TO DISPLAY
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; ------------------* PORT SUBROUTINES, EXTERNAL ADDRESS *-----------------
; * PORT B OUTPUT *
BOUT: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
MOV DPTR,#PORTBX ;EXTERNAL ACCESS
MOV A,PORTBO ;LOAD PORT B VALUE
MOVX @DPTR,A ;OUTPUT TO PORT
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; * PORT B INPUT *
BIN: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
MOV DPTR,#PORTBX ;EXTERNAL ACCESS
MOVX A,@DPTR ;INPUT FROM PORT
MOV PORTBI,A ;WRITE PORT B VALUE
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; * PORT A OUTPUT *
AOUT: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
MOV DPTR,#PORTAX ;EXTERNAL ACCESS
MOV A,PORTAO ;LOAD PORT A VALUE
MOVX @DPTR,A ;OUTPUT TO PORT
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; * PORT A INPUT *
AIN: PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
MOV DPTR,#PORTAX ;EXTERNAL ACCESS
MOVX A,@DPTR ;INPUT FROM PORT
MOV PORTAI,A ;WRITE PORT A VALUE
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RET
; -------------------------* CLEAR EXTERNAL RAM *--------------------------
CLRXRAM1:
MOV DPTR,#0 ;LOAD RAM STARTING ADDRESS
XRAM1: MOV A,#0AAH ;LOAD VALUE TO BE WRITTEN TO 0002-01FFH (AAH)
MOVX @DPTR,A ;OUTPUT DATA
INC DPTR ;INCREMENT POINTER
MOV A,DPH
CJNE A,#2,XRAM1 ;IS ADDRESS = 200H?
SETB INIT_AC ;SET FLAG
RET
CLRXRAM2:
MOV DPTR,#200H ;STARTING ADDRESS
XRAM2: MOV A,#0 ;LOAD VALUE TO BE WRITTEN TO 0200-3FFFH (00H)
MOVX @DPTR,A ;OUTPUT DATA
INC DPTR ;INCREMENT POINTER
MOV A,DPH ;CHECK UPPER DATA POINTER FOR END (3F00H)
CJNE A,#3FH,XRAM2
MOV A,DPH ;CHECK LOWER DATA POINTER FOR END (FFH)
CJNE A,#0FFH,XRAM2
RET
; --------------- RECEIVE DATA IN INTEL HEX & WRITE TO EEPROM ---------------
E2_PROGRAM:
JB E2_HL,E2_P1
LCALL WU_L ;UNPROTECT LOWER HALF
SJMP E2_P2
E2_P1: LCALL WU_U ;WRITE UNPROTECT EEPROM
E2_P2: MOV SUM,#00H ;CLEAR CHECKSUM
CLR P0.2 ;DISABLE I/O ADDRESSING
SETB P0.3 ;ENABLE WR* SIGNAL TO EEPROM
E2_PROG: LCALL RCV_HEX ;GET DATA
JNB NEW_LN,E2_PROG ;CHECK FOR ':'
CJNE A,#00H,E2_PR0 ;CHECK FOR ZERO BYTES
E2_PR: LCALL RCV_HEX ;GET DATA
CJNE A,#0FFH,E2_PR0 ;END OF FILE
SETB XFER_OK ;SET TRANSFER OK FLAG
JB E2_HL,E2_P3
LCALL WP_L ;WRITE PROTECT LOWER EEPROM
SJMP E2_P4
E2_P3: LCALL WP_U ;WRITE PROTECT EEPROM
E2_P4: SETB P0.2 ;ENABLE I/O ADDRESSING
CLR P0.3 ;DISABLE WR* SIGNAL TO EEPROM
RET
E2_PR0: MOV HEX_COUNT,A ;STORE HEX BYTE COUNT
SUBB A,SUM ;SUBTRACT CHECKSUM FROM ACC
MOV SUM,A ;MOVE NEW CHECKSUM VALUE TO SUM
LCALL RCV_HEX ;GET DATA
MOV DPH,A ;STORE HIGH DPTR
SUBB A,SUM ;SUBTRACT CHECKSUM FROM ACC
MOV SUM,A ;MOVE NEW CHECKSUM VALUE TO SUM
LCALL RCV_HEX ;GET DATA
MOV DPL,A ;STORE LOW DPTR
SUBB A,SUM ;SUBTRACT CHECKSUM FROM ACC
MOV SUM,A ;MOVE NEW CHECKSUM VALUE TO SUM
LCALL RCV_HEX ;GET DATA
CJNE A,#02H,E2_PR3 ;CHECK FOR BEGINNING OF FILE
E2_PR1: SUBB A,SUM ;SUBTRACT CHECKSUM FROM ACC
MOV SUM,A ;MOVE NEW CHECKSUM VALUE TO SUM
LCALL RCV_HEX
SUBB A,SUM ;SUBTRACT CHECKSUM FROM ACC
MOV SUM,A ;MOVE NEW CHECKSUM VALUE TO SUM
DJNZ HEX_COUNT,E2_PR1 ;LAST OF THE DATA?
LCALL RCV_HEX
CPL A ;COMPLEMENT ACCUMULATOR
CJNE A,SUM,E2_ERR ;ERROR FOUND?
E2_PR2: LCALL RCV_HEX ;GET DATA
CJNE A,#':',E2_PR2 ;COLLECT UNTIL NEW LINE
SJMP E2_PROG ;START NEW LINE
E2_PR3: LCALL RCV_HEX ;GET DATA
MOVX @DPTR,A ;OUTPUT DATA
SUBB A,SUM ;SUBTRACT CHECKSUM FROM ACC
MOV SUM,A ;MOVE NEW CHECKSUM VALUE TO SUM
INC DPTR ;INCREMENT DATA POINTER
DJNZ HEX_COUNT,E2_PR3 ;CHECK HEX_COUNT FOR ZERO
CPL A ;COMPLEMENT ACC
CJNE A,SUM,E2_ERR ;ERROR FOUND
LCALL RCV_HEX ;GET DATA FOR CHECK SUM
SJMP E2_PROG ;GET ANOTHER LINE
E2_ERR: CLR XFER_OK ;CLEAR TRANSFER OK FLAG
LCALL WP_U ;WRITE PROTECT EEPROM
SETB P0.2 ;ENABLE I/O ADDRESSING
CLR P0.3 ;DISABLE WR* SIGNAL TO EEPROM
RET
; * RECEIVE DATA AND COMBINE TWO NIBBLES TO ONE BYTE *
RCV_HEX:CLR NEW_LN ;CLEAR NEW LINE OF CODE FLAG
MOV TH0,#0FAH
MOV TL0,#00H ;RELOAD TIMER
MOV COUNT2,#03H
MOV COUNT1,#0D0H ;DELAY 20-SECONDS
RCV: JB RI,RCV_A ;CHECK RECEIVE INTERRUPT BIT
JNB COUNT,RCV ;TIMEOUT?
SJMP E2_ERR ;TIMED OUT, ERROR
RCV_A: CLR RI ;CLEAR RECEIVED DATA FLAG
MOV A,SBUF ;GET DATA
CJNE A,#':',RCV_1 ;CHECK FOR ':'
SETB NEW_LN ;SET NEW LINE FLAG
RET
RCV_1: CJNE A,#41H,RCV_2 ;IS IT AN 'A'?
MOV A,#0AH
SJMP RCV_8
RCV_2: CJNE A,#42H,RCV_3 ;IS IT AN 'B'?
MOV A,#0BH
SJMP RCV_8
RCV_3: CJNE A,#43H,RCV_4 ;IS IT AN 'C'?
MOV A,#0CH
SJMP RCV_8
RCV_4: CJNE A,#44H,RCV_5 ;IS IT AN 'D'?
MOV A,#0DH
SJMP RCV_8
RCV_5: CJNE A,#45H,RCV_6 ;IS IT AN 'E'?
MOV A,#0EH
SJMP RCV_8
RCV_6: CJNE A,#46H,RCV_7 ;IS IT AN 'F'?
MOV A,#0FH
SJMP RCV_8
RCV_7: ANL A,#0FH ;MASK OUT UPPER HALF
RCV_8: JB D_TEMP_F,RCV_9
SWAP A ;SWAP NIBBLES
MOV D_TEMP,A ;STORE DATA
SETB D_TEMP_F ;SET DATA TEMP FLAG
SJMP RCV_HEX
RCV_9: CLR D_TEMP_F ;CLEAR DATA TEMP FLAG
ADD A,D_TEMP ;ADD BOTH NIBBLES
RET
; * WRITE PROTECT EEPROM (UPPER ADDRESS) *
WP_U: MOV DPTR,#2555H
MOV A,#0AAH
MOVX @DPTR,A
MOV DPTR,#1AAAH
MOV A,#55H
MOVX @DPTR,A
MOV DPTR,#2555H
MOV A,#0A0H
MOVX @DPTR,A ;MAKE SURE LAST ADDRESS 2FFF IS WRITTEN TO
RET
; * WRITE PROTECT EEPROM (LOWER ADDRESS) *
WP_L: MOV DPTR,#1555H
MOV A,#0AAH
MOVX @DPTR,A
MOV DPTR,#0AAAH
MOV A,#55H
MOVX @DPTR,A
MOV DPTR,#1555H
MOV A,#0A0H
MOVX @DPTR,A ;MAKE SURE LAST ADDRESS 1FFF IS WRITTEN TO
RET
; * UN-WRITEPROTECT EEPROM (UPPER ADDRESS) *
WU_U: MOV DPTR,#2555H
MOV A,#55H
MOVX @DPTR,A
MOV DPTR,#1AAAH
MOV A,#55H
MOVX @DPTR,A
MOV DPTR,#2555H
MOV A,#80H
MOVX @DPTR,A
MOV A,#0AAH
MOVX @DPTR,A
MOV DPTR,#1AAAH
MOV A,#55H
MOVX @DPTR,A
MOV DPTR,#2555H
MOV A,#20H
MOVX @DPTR,A
RET
; * UN-WRITEPROTECT EEPROM (LOWER ADDRESS) *
WU_L: MOV DPTR,#1555H
MOV A,#55H
MOVX @DPTR,A
MOV DPTR,#0AAAH
MOV A,#55H
MOVX @DPTR,A
MOV DPTR,#1555H
MOV A,#80H
MOVX @DPTR,A
MOV A,#0AAH
MOVX @DPTR,A
MOV DPTR,#0AAAH
MOV A,#55H
MOVX @DPTR,A
MOV DPTR,#1555H
MOV A,#20H
MOVX @DPTR,A
RET
; ************************* TIMER 0 INTERRUPT *****************************
; * MOVE PORT & STATUS REGISTERS TO EXTERNAL RAM *
TIO: MOV TH0,#0FAH
MOV TL0,#00H ;RELOAD TIMER COUNT
PUSH DPL ;REGISTERS TO STACK
PUSH DPH
PUSH ACC
SETB RS0 ;SET TO BANK 2 OF WORKING REGISTERS
MOV A,22H ;GET DATA OF REGISTER #22H
MOV DPTR,#REGISTERS ;STARTING EXTERNAL ADDRESS FOR REGISTERS
MOVX @DPTR,A ;STORE REGISTER VALUE
; * COUNT1 & COUNT2 LOOPS *
JB COUNT,DEC20 ;CHECK FOR COUNT
JBC COUNT_ONE,LAST_C ;CHECK FOR LAST COUNT, CLEAR COUNT_ONE FLAG
CJNE COUNT1R5,#1,DEC20 ;IS COUNT1 = 1?
CJNE COUNT2R6,#0,DEC2 ;IS COUNT2 = 0? (LAST COUNT)
SETB COUNT_ONE
SJMP DEC22
DEC20: CJNE COUNT1R5,#0,DEC22 ;IS COUNT1 = 0?
CJNE COUNT2R6,#0,DEC2 ;IS COUNT2 = 0?
CLR COUNT
SJMP TO_1
LAST_C: SETB COUNT ;SET IF LAST COUNT
SJMP DEC22
DEC2: DEC COUNT2R6 ;DECREMENT COUNT2
DEC22: DEC COUNT1R5 ;DECREMENT COUNT1
; * TIMEOUT1, TIMEOUT2, & TIMEOUT3 LOOPS *
TO_1: JB TIMEOUT,DEC30 ;CHECK FOR COUNT
JBC TIMEOUT_ONE,LAST_CNT;CHECK FOR LAST COUNT, CLEAR TIMEOUT_ONE FLAG
CJNE TIMEOUT1R2,#1,DEC30;IS TIMEOUT1 = 1?
CJNE TIMEOUT2R3,#0,DEC32;IS TIMEOUT2 = 0?
CJNE TIMEOUT3R4,#0,DEC33;IS TIMEOUT3 = 0? (LAST COUNT)
SETB TIMEOUT_ONE ;SET LAST COUNT (TIMEOUT_ONE)
SJMP DEC31 ;SCAN KEYBOARD
DEC30: CJNE TIMEOUT1R2,#0,DEC31;IS TIMEOUT1 = 0?
CJNE TIMEOUT2R3,#0,DEC32;IS TIMEOUT2 = 0?
CJNE TIMEOUT3R4,#0,DEC33;IS TIMEOUT3 = 0?
CLR TIMEOUT ;CLEAR TIMEOUT FLAG
SJMP KEYSCAN ;ALL = 0, THEN SCAN KEYBOARD
LAST_CNT:
SETB TIMEOUT ;SET TIMEOUT FLAG
SJMP DEC31
DEC33: DEC TIMEOUT3R4 ;DECREMENT TIMEOUT3
DEC32: DEC TIMEOUT2R3 ;DECREMENT TIMEOUT2
DEC31: DEC TIMEOUT1R2 ;DECREMENT TIMEOUT1
CLR RS0 ;BACK TO BANK 1 OF WORKING REGISTERS
; -------------------------* KEYBOARD SCAN *-------------------------------
KEYSCAN:MOV A,#0FFH ;RESET KEYBOARD LINES
SETB P0.0
SETB P0.1 ;SET KEYBOARD STROBES
MOV BUFFER,#0 ;CLEAR BUFFER
KEY0: CLR P0.0 ;TIE SCAN LINE #1 LOW
MOV DPTR,#KEYBOARD ;EXTERNAL ACCESS
MOVX A,@DPTR ;INPUT FROM PORT
LCALL SCAN ;IS THE NUMBER 1-8?
MOV A,KEYDELAY
CJNE A,#3,KEY2 ;IF = 3 (30mS), THEN SET VALID_DATA
SETB VALID_DATA
SJMP NOKEY1
KEY2: JB KEYS,INC_DELAY
MOV DPTR,#KEYBOARD ;EXTERNAL ACCESS
SETB P0.0
CLR P0.1 ;TIE SCAN LINE #2 LOW
MOVX A,@DPTR ;INPUT FROM PORT
LCALL SCAN ;IS THE NUMBER 9-F?
JB KEYS,KEY2A
MOV KEYDELAY,#0 ;CLEAR IF NO KEY PRESSED
CLR VALID_DATA
KEY2A: MOV A,KEYDELAY
CJNE A,#5,KEY3 ;IF =5 (50mS), THEN SET VALID_DATA
SETB VALID_DATA
SJMP NOKEY1
KEY3: CLR VALID_DATA
SJMP INC_DELAY
SCAN: CLR VALID_DATA
INC KEYCOUNT
CJNE A,#11111110B,K1 ;KEY "1" or "7"?
SJMP K8
K1: INC KEYCOUNT
CJNE A,#11111101B,K2 ;KEY "2" or "8"?
SJMP K8
K2: INC KEYCOUNT
CJNE A,#11111011B,K3 ;KEY "3" or "9"?
SJMP K8
K3: INC KEYCOUNT
CJNE A,#11110111B,K4 ;KEY "4" or "A"?
SJMP K8
K4: INC KEYCOUNT
CJNE A,#11101111B,K5 ;KEY "5" or "*"?
SJMP K8
K5: INC KEYCOUNT
CJNE A,#11011111B,K10 ;KEY "6" or "#"?
K8: MOV BUFFER,KEYCOUNT
SETB KEYS ;FIRST SCAN VALID
K9: CLR RS0
POP ACC
POP DPH
POP DPL
RET
K10: CLR VALID_DATA ;NO KEYS? THEN CLEAR ALL THREE
CLR KEYS
MOV KEYDELAY,#0
CLR RS0
POP ACC
POP DPH
POP DPL
RET
INC_DELAY:
INC KEYDELAY
NOKEY1: CLR RS0
POP ACC
POP DPH
POP DPL ;REGISTERS FROM STACK
RETI
; ************************** TIMER 1 INTERRUPT ******************************
TI1: MOV TL1,#0F4H ;1200 BAUD RATE
RETI ;RETURN FROM INTERRUPT
; ------------------------- SERIAL PORT INTERRUPT ---------------------------
SERIAL: JB RI,RX_I ;CHECK RECEIVE INTERRUPT FLAG
JB TI,TX_I ;CHECK TRANSMIT INTERRUPT FLAG
SJMP RX_2 ;INTERRUPT HANDLER
TX_I: CLR TI ;CLEAR TRANSMIT INTERRUPT FLAG
JNB TX_DPTR,TX_1 ;NO JUMP, SEND DATA FROM EXTERNAL MEMORY
MOVX A,@DPTR ;GET DATA FROM EXTERNAL MEMORY
CJNE A,#0FFH,TX_1 ;CHECK FOR DATA END OF STRING
SETB TX_END ;SET END OF TRANSMITION FLAG
RETI ;RETURN FROM INTERRUPT
TX_1: MOV SBUF,A ;OUTPUT DATA TO SERIAL PORT
INC DPTR ;INCREMENT DATA POINTER
RETI ;RETURN FROM INTERRUPT
RX_I: CLR RI ;CLEAR RECEIVE INTERRUPT FLAG
MOV A,SBUF ;INPUT DATA FROM SERIAL PORT
CLR RX_CR ;CLEAR CARRIGE RETURN FLAG
CJNE A,#0DH,RX_1 ;CHECK FOR CARRIGE RETURN CHARACTER
SETB RX_CR ;SET CARRIGE RETURN DETECT FLAG
RETI ;RETURN FROM INTERRUPT
RX_1: CLR RX_BUFF_FULL ;CLEAR RECEIVE BUFFER FULL FLAG
MOV @R0,SBUF ;MOVE DATA TO RECEIVE BUFFER
INC R0 ;INCREMENT POINTER
CJNE R0,#RX_BUFF+11,RX_2;CHECK FOR FULL RECEIVE BUFFER
SETB RX_BUFF_FULL ;SET RECEIVE BUFFER FULL FLAG
RX_2: RETI ;RETURN FROM INTERRUPT
; * DISPLAY DATA *
D_AC_MAXED: DB 'Maximum Codes...',-1
D_ACCESS: DB '....Passcode....',0DH,0AH,'..#:',-1
D_ADD_AC: DB '.Add Area Code?.',0DH,0AH,' #=Yes / *=No',-1
D_ADDED: DB 'Added: ',-1
D_ALREADY: DB '.Already Added..',0DH,0AH,'..Press a Key...',-1
D_AM: DB ' AM',-1
D_AM_PM: DB ' *=AM #=PM ',-1
D_ANSWER: DB '.Line Answered..',-1
D_COLON: DB ':',-1
D_DASH: DB '-',-1
D_DAYLIGHT: DB 'Daylight Savings',0DH,0AH,'Enable? *=Y #=N',-1
D_DELETE: DB 'Delete Area Code',0DH,0AH,'& Prefix:',-1
D_DIALING: DB '..Dialing Out...',0DH,0AH,':',-1
D_DIALING_MF: DB '...Dialing MF...',-1
D_DIALTONE_400: DB ' 400Hz Dialtone',-1
D_DIALTONE_S: DB 'Regular Dialtone',-1
D_END_LIST: DB '..End of List...',-1
D_ENTER_AC: DB 'Enter Area Code.',0DH,0AH,'& Prefix:',-1
D_ENTER_DAY: DB 'Enter Day: ',-1
D_ENTER_HOUR: DB 'Enter Hour: ',-1
D_ENTER_MIN: DB 'Minutes: ',-1
D_ENTER_MONTH: DB 'Enter Month: ',-1
D_ENTER_YEAR: DB 'Enter Year: 19',-1
D_ENTER_Y_2: DB 'Enter Year: 20',-1
D_ERROR: DB '.Alt Tone Error.',-1
D_EXTEND: DB 'Call Extender:',-1
D_FLASH: DB 'Flash Swtichhook',-1
D_FRIDAY: DB ' Fri',-1
D_LOCAL: DB '..Enter Local...',0DH,0AH,'Area Code:',-1
D_LOCAL_DISABLE:DB 'Local Disabled',-1
D_LOCAL_ENABLE: DB 'Local Enabled',-1
D_LOCAL_LIST: DB '..Local List:...',-1
D_MONDAY: DB ' Mon',-1
D_NEW_AC: DB '.New Area Code..',0DH,0AH,'Saved:',-1
D_NEXT_AC: DB '.Next Area Code.',0DH,0AH,'..or # to Exit..',-1
D_NOTHING: DB '...Nothing to...',0DH,0AH,'.....Delete.....',-1
D_OFF: DB ' Off',-1
D_ON: DB ' On',-1
D_OPTIONS: DB '....Options.....',0DH,0AH,'#',-1
D_PM: DB ' PM',-1
D_POUND: DB '#',-1
D_PRESS_ANY: DB 0DH,0AH,'Press Any Key...',-1
D_RING: DB '..Line Ringing..',-1
D_RELAY_OFF: DB 'Relay Option OFF',-1
D_RELAY_ON: DB 'Relay Option ON',-1
D_SATURDAY: DB ' Sat',-1
D_SLASH: DB '/',-1
D_SPACE: DB ' ',-1
D_STAR: DB '*',-1
D_SUNDAY: DB ' Sun',-1
D_TALK: DB '....Talk Mode...',-1
D_THURSDAY: DB ' Thu',-1
D_TITLE: DB '.Call Diverter..',0DH,0AH,'by RLG 1/5/95',-1
D_TO_EXIT: DB 'Press # to Exit.',-1
D_TOTAL_PREFIX: DB '.Total Prefixes.',0DH,0AH,-1
D_TUESDAY: DB ' Tue',-1
D_TRY_AGAIN: DB 'Try it Again....',0DH,0AH,-1
D_WEDNESDAY: DB ' Wed',-1
D_4_SPACES: DB ' ',-1
D_7_SPACES: DB ' ',-1
ORG 1FFFH
ENDCODE: DB 0
END