;============================================================
;	TP RELAYS ON PORT 0		DTMF ON PORT 1
;	STATUS    ON PORT 2		
; ===========================================================

	;$MOD51
	
	LED 	 EQU P1.7
	TONE_D	 EQU P3.6
	TONE_B	 EQU P3.4
	REL1	 EQU P3.0	; LINE CHANGE-OVER RELAY
	REL2	 EQU P3.1	; RINGING RELAY
	MELODY	 EQU P3.7	; UM66T MELODY GENRATOR
	ZERO	 EQU 10
	F10 	 BIT 78H	; BIT FLAG
	F11 	 BIT 79H 
	Ph 	 BIT 7AH  

	On_Hook MACRO		; HOOK SWITCH ON P1.6 
	SETB P1.6		
	ENDM

	Off_Hook MACRO 		; HOOK SWITCH ON P1.6 
	CLR P1.6
	ENDM


;=============================================================
;		    INTERRUPT VECTOR TABLE 
;=============================================================
	
	ORG 00H	 		; ENTRY ADDRESS FOR 89C51 RESET
	AJMP MAIN 		; MAIN STARTS BEYOND INTERRUPT VECTOR SPACE

	ORG 1BH 		; VECTOR ADDRESS FOR INTERRUPT
	SETB Ph			; MARK "THIS IS A PHONE CALL"
	AJMP PHONE		; JUMP TO PHONE CALL SERVICE
	

;=============================================================
; 				M A I N 
;=============================================================
	
	ORG 02CH    	   	; START BEYOND THE VECTOR TABLE
MAIN:
	ACALL INITIALIZE_SUB 	; INITILIZE CONTRO RAGISTER(TMOD & IE)
START:
	CLR LED
	ACALL SCAN_TPs
	JB F10,INTERCOM
	
	SETB LED
	ACALL SCAN_TPs
	JB F10,INTERCOM
	
	AJMP START


;============================================================
;			INTERCOM SERVICE
;============================================================

INTERCOM:
	CLR F10			; RESET FLAG
	Off_Hook  		; DISABLE PHONE CALL
	SETB TONE_D		; ON DIAL TONE
	SETB TONE_B		; ON BUSY TONE
	CLR LED			; ON LED PERMANENTLY
	CPL A
	MOV P0,A		; CONNECT SCANED No. TO SPEACH-BUS
	
	ACALL GET_DIAL_NUM	; GET NUMBER TO CALL
	
	CJNE A,#0FFH,INTERNAL	; IF DIAL=FF THEN PHONE CALL FROM INTERCOM 
	CLR REL1		; CONNECT SPEACH-BUS TO PHONE LINE
	Off_Hook 		; OFF-HOOK SYSTEM
	CLR LED			; ON LED PERMANENTLY
	AJMP EXTERNAL_CALL
	
INTERNAL:
	MOV R3,A		; SAVE SUBSCRIBER No. INTO R3
	ANL A,P0
	MOV P0,A		; CONNECT DIALED No. TO SPEACH-BUS	

	MOV A,R3		; PROCESSING FOR CHECKING SUBSCRIBER
	ANL A,P2		; AND SUBCRIBER WITH CALLER
	
	ACALL BELL		; RING THE BELL
EXTERNAL_CALL:
	ACALL DELAY_HS

SPEACH:	MOV A,P2
	CJNE A,#255,SPEACH	; IF CALL COMPLETE THEN RESET SYSTEM
	ACALL RST_SYSTEM	; ELSE WAIT HERE
	AJMP START


;============================================================
;THIS ROUTINE CHECKED TP'S STATUS IF ANY OFF_HOOK FOUND SERVICE
;PROVIDED HIM
;============================================================

SCAN_TPs:			; FLASHING LED WITH SCANING TPs
	MOV R0,#76
LOOP:	MOV R1,#250

_1:	MOV A,#1		; START POINTER WITH ONE
	JB P2.0,_2
	SETB F10
	AJMP OUT

_2:	RL A
	JB P2.1,_3
	SETB F10
	AJMP OUT
	
_3:	RL A
	JB P2.2,_4
	SETB F10
	AJMP OUT
	
_4:	RL A
	JB P2.3,_5
	SETB F10
	AJMP OUT
	
_5:	RL A
	JB P2.4,_6
	SETB F10
	AJMP OUT
	
_6:	RL A
	JB P2.5,_7
	SETB F10
	AJMP OUT
	
_7:	RL A
	JB P2.6,_8
	SETB F10
	AJMP OUT
	
_8:	RL A
	JB P2.7,BACK
	SETB F10
	AJMP OUT

BACK:	DJNZ R1,_1
	DJNZ R0,LOOP
OUT:	RET			; RETURN FROM SUB ROUTINE


;============================================================
;     THIS ROUTINE RINGING THE BELL ON DIALED NUMBER
;============================================================

BELL:	
	CLR TONE_D		; OFF DIAL TONE
	CLR REL2		; ON BELL RELAY
	ACALL DELAY		; RING BELL FOR ONE MINIT
	SETB REL2		; OFF BELL RELAY
	
	ACALL DELAY
	JB F10,RET1
	ACALL DELAY1
	JB F10,RET1
	ACALL DELAY1
	JB F10,RET1	
	AJMP BELL
RET1:	RET


;============================================================
;	CHECK TELEPHONE'S STATUS UPTO ONE SECOND
;		IF PIKED UP THEN SET FLAG
;============================================================

DELAY1:				; ONE SECOND DELAY WITH STATUS CHECKING
	MOV R0,#4
LOOP11:	MOV R1,#250
LOOP12:	MOV R2,#250
LOOP13: CJNE A,P2,NOT_EQ
	SETB F10			; MARK SUBSCRIBER READY TO TALK
	AJMP RET2
NOT_EQ: DJNZ R2,LOOP13
	DJNZ R1,LOOP12
	DJNZ R0,LOOP11
RET2:	RET


;============================================================
; 			ONE SECOND DELAY	
;============================================================

DELAY:				; ONE SECOND DELAY
	MOV R0,#4
LOOP1:	MOV R1,#250
LOOP2:	MOV R2,#250
LOOP3: 	NOP
	NOP
	DJNZ R2,LOOP3
	DJNZ R1,LOOP2
	DJNZ R0,LOOP1
	RET
	

;============================================================
;	   READ DIALED NUMBER,RE-CHECK IF 0, * OR #
;============================================================

GET_DIAL_NUM:
	JNB P1.4,$		; WAIT FOR KEY PRESS (STROB)
	MOV A,P1		; READ DIALED NUMBER
	ANL A,#00001111B	; REMOVE EXTRA BITS	
	
	CJNE A,#ZERO,STERIK	;
	JB Ph,GET_DIAL_NUM	; IF ZERO FROM PHONE CALL THEN READ AGAIN
	MOV A,#0FFH		; TRUNK CALL FROM INTERCOM
	AJMP RET3

STERIK: CJNE A,#11,HASH		; IF STERIK, READ AGAIN
	AJMP GET_DIAL_NUM 

HASH:	CJNE A,#12,NINE		; IF HASH, READ AGAIN
	AJMP GET_DIAL_NUM 

NINE:	CJNE A,#9,DECODE
	JNB Ph,GET_DIAL_NUM	; DIAL=9 & NOT A PHONE THEN READ AGAIN
	MOV A,#252		; SELECT TO ALL (VIRTUALY 8)
	AJMP RET3
	
DECODE:	DEC A
	MOV R1,A
	MOV A,#1
ROTATE:	RL A
	DJNZ R1,ROTATE
	CPL A
RET3:	RET


;=============================================================
; 			RESET ALL SYSTEM
;=============================================================	

RST_SYSTEM:
	CLR TONE_D		; OFF DIAL-TONE
	CLR TONE_B		; OFF BUSY-TONE
	CLR F10			; RESET FLAG
	CLR Ph			; CLEAR PHONE CALL FLAG
	CLR F11
	MOV P0,#255		; OFF ALL TPs RELAYS
	SETB REL1		; OFF CHANGE-OVER RELAY
	SETB TR1		; START TIMER/COUNTER
	On_Hook			; ENABLE PHONE CALL
	RET


;============================================================
;			INITIALIZE SYSTEM
;============================================================

INITIALIZE_SUB:         	; SET UP CONTROL REGISTERS
	MOV TMOD, #01100000B 	; TIMER 1 IS SET FOR MODE 2, COUNTER OPERATION
	MOV   IE, #10001000B 	; ENABLE TIMER/COUNTER 1 INTERRUPT
	MOV  TH1, #219		; AUTO RELOAD VALUE(INT1 TL1) EACH TIME AFTER OVERFLOW.
	MOV  TL1, #219  	; DEMO TIMER IS INITIALISED WITH (256-39=217)
				; TO COUNT 39(2BELL)EVENTS
	CLR TONE_D		; OFF DIAL-TONE
	CLR TONE_B		; OFF BUSY-TONE
	SETB TR1 		; START COUNTER 1
	RET


;=============================================================
; 			PHONE CALL SERVICE
;=============================================================

PHONE:
	CLR TR1  		; STOP TIMER1
	Off_Hook 		; OFF-HOOK SYSTEM
	CLR LED			; ON LED PERMANENTLY
	ACALL UM66		; PLAY MELODY
	
	CLR REL1		; CONNECT SPEACH-BUS TO PHONE LINE
NEXT:	ACALL GET_DIAL_NUM	; GET NUMBER TO CALL
	SETB REL1		; DISCONNECT FOR BELL
	
	MOV P0,A		; CONNECT DIALED No. TO SPEACH-BUS
	ACALL BELL		; RING THE BELL
	CLR REL1		; CONNECT SPEACH-BUS TO PHONE LINE
	ACALL DELAY_HS		; PROVIDE HALF SECOND DELAY
	
BUSY: 	MOV A,P2
	CJNE A,#255,BUSY	; IF CALL NOT COMPLETE, WAIT ARROUND HERE
	
	JB F11,RESET		; CHECK FOR SECOND CALL
	MOV P0,#255		; DISCONNECT ALL TELEPHONES
	SETB TONE_B		; ON BUSY TONE
	SETB F11		; MARK FOR SECOND PHONE CALL
	CLR  F10		; RESET FLAG
	AJMP NEXT		; GO FOR NEXT PHONE CALL

RESET:	ACALL RST_SYSTEM	; END CALL
	RETI


;===================================================================
; 			PLAY MELODY (UM66)
;===================================================================

UM66:	CLR  MELODY		; PLAY MELODY AS GREETING MESSAGE
	ACALL DELAY		; FOR FIVE SECOND
	ACALL DELAY
	ACALL DELAY
	ACALL DELAY		
	ACALL DELAY		
	SETB MELODY		; STOP MELODY
	RET


;====================================================================
;	  HALF SECOND DELAY TO ESTABLISHED THE RELAY CONTECTS
;====================================================================

DELAY_HS:			; HALF SECOND DELAY
	MOV R0,#2
LOOP21:	MOV R1,#250
LOOP22:	MOV R2,#250
LOOP23: NOP
	NOP
	DJNZ R2,LOOP23
	DJNZ R1,LOOP22
	DJNZ R0,LOOP21
	RET

END