;telcom6.asm asm by ecal
;modif le 05-12-1998 by MB & Denis
;
;       Generateur sons DTMF PCD3312.
; Protocole de communication:
;  Adresse, data.

; Adresse = 48H ou 4Ah.

; Data code sur 6 bits = 04h a 1Fh + 24h a 3Fh  emettent une sonorite.
;                        00h a 03h + 20h a 23h  aucun son.
;       10h a 1Fh sons DTMF:
;         10h = touche 0   14h = touche 4   18h = touche 8   1Ch = touche C
;         11h = touche 1   15h = touche 5   19h = touche 9   1Dh = touche D
;         12h = touche 2   16h = touche 6   1Ah = touche A   1Eh = touche *
;         13h = touche 3   17h = touche 7   1Bh = touche B   1Fh = touche #
;==============================================================================

bsda    equ 097H		      ;port P1.7
bscl    equ 096H		      ;port P1.6
LSCL	Equ 096H		      ;port P1.6
LSDA	Equ 097H		      ;Port P1.7
trig    equ 091H		      ;port P1.1
Led_Port bit 092H                     ;port P1.2

wait1   equ 050h                ;en RAM: compteur pour boucle attente

ecr_buf equ 8000h               ;Buffer d'ecriture I2C. rempl. $1e00 par $8000
lec_buf equ 8100h               ;Buffer de lecture I2C. rempl. $1f00 par $8100
acq     equ 8200h               ;Adresse d'acquittement I2C (00h=OK).

horl    equ 0A0h                ;Adresse PCF8583 horloge calendrier + RAM.
io_1    equ 040h                ;Adresse PCF8574 no1 .
io_2    equ 042h                ;Adresse PCF8574 no2 .
aff4d   equ 070h                ;Adresse SAA1064 (adr = 0V).
dtmf    equ 04Ah                ;Adresse PCD3312 generateur DTMF (A0=1).



; Affectation en memoire interne des 16 registres
; -----------------------------------------------
SRRH  EQU 08H
SRRL  EQU 09H
SDPH  EQU 0AH
SDPL  EQU 0BH
PPH   EQU 0CH
PPL   EQU 0DH
RRH   EQU 0EH
RRL   EQU 0FH
R8H   EQU 10H
R8L   EQU 11H
R9H   EQU 12H
R9L   EQU 13H
RAH   EQU 14H
RAL   EQU 15H
RBH   EQU 16H
RBL   EQU 17H
RCH   EQU 18H
RCL   EQU 19H
RDH   EQU 1AH
RDL   EQU 1BH
REH   EQU 1CH
REL   EQU 1DH
RFH   EQU 1EH
RFL   EQU 1FH




;Debut           Equ 0
;Debut_Prog      Equ 30H

        Org     0
Debut:  ljmp    Debut_Prog
        Org  Debut +3
        Reti                    ;Interrution EX0

        Org  Debut +0BH
        Reti                    ;Interruption du timer 0

        Org  Debut +13H
        Reti                    ;Interrution EX1

        Org  Debut +1BH         ;Interruption du timer 1
        Reti                    ;Interrution EX1

        Org  Debut +23H         ;Uart
        Reti

        Org  Debut +2BH         ;Interruption du timer 2
        Reti


        Org  30H
Debut_Prog:

; Initialisation le pointeur de pile
        Mov  SP,#40H             ;POINTEUR DE PILE EN RAM INTERNE
        Call Init_RamSpace
        
Blink_led:
        clr  Led_Port       ;allume la led
        Call Tempo
        setb Led_Port       ;eteint la led
        Call Tempo
        mov  dptr, #no
        Call ecr_no
        call Tempo
        Jmp  Blink_led

ecr_no:  push  acc
ecr_no1: clr   a
         movc  a,@a+dptr
         jz    ecr_no4  ;si a = 0 , fin du numero
         clr   c        ;c … 0 pour subb sans retenue
         subb  a,#20h   ;convertit chiffre ascii en code dtmf
         lcall ecr_dt
         call  Tempo
         inc   dptr
         mov   a,#00h
         lcall ecr_dt
         call  Tempo
         sjmp  ecr_no1  ;chiffre suivant
ecr_no4: pop   acc
         ret

         





Init_RamSpace:
        Mov  DPTR,#8000H
Continue:
        Clr  A
        Movx @DPTR,A
        Inc  DPTR
        Mov  A,DPH
        Cjne A,#88H,Continue
        Ret




Tempo:
        Mov  R8L,#1d    ; 255 correspond a 212 secondes
NoTimeDelay:
        Mov  REH,#0FFH
        Mov  REL,#0FFH
        Call DELAI
        Djnz R8L,NoTimeDelay
        Ret


;***********************************************
;  SIMULATION DE LA MACRO DELAI
;    APPEL:  MOV REH,#TEMPOH
;            MOV REH,#TEMPOL   VALEUR CALCULEE EN DECIMAL ET CONVERTIE EN HEXA
;            CALL DELAI
;  T= TEMPO*38,14uS + 124uS 

DELAI:  PUSH ACC
        INC REL
        INC REH
        MOV A,#3

TEMPO1: JZ SAUT
        DEC A
        NOP
        NOP
        NOP
REVIEN1: NOP
        JMP BCL1
SAUT:   MOV A,#3
        JMP REVIEN1

BCL1:   NOP
        DJNZ REL,TEMPO1

        JZ SAUT1
        DEC A
        NOP
        NOP
        NOP
REVIEN2: NOP
        JMP BCL2
SAUT1:  MOV A,#3
        JMP REVIEN2

BCL2:   DEC REL
        DJNZ REH,TEMPO1

        POP ACC
        RET




reset:  acall   init_rs

tone0:	mov     a,#21h
        acall   ecr_dt
        mov     a,#0ffh
	acall   wait
	mov     a,#0ffh
	acall   wait
	mov     a,#0ffh
	acall   wait
	mov     a,#00h
	acall   ecr_dt
	mov     a,#0ffh
        acall   wait
        mov     a,#0ffh
        acall   wait
        mov     a,#0ffh
        acall   wait
	acall   i2c_lec
        mov     dptr, #acq
        movx    a,@dptr
        acall   affacc          ;Affiche la valeur ACQ.
	acall   esp_rx
	jmp     tone0


wait:   mov     r7,#0ffh         ;attente A*255*255*2 uS@11.0592 Mhz
waitx:  mov     r6,#0ffh
wait2:  djnz    r6,wait2
        djnz    r7,waitx
        djnz    acc,wait
        ret

;=============================================================================
; Routines de gestion generateur DTMF PCD3312:
;       ECR_DT : Ecriture sur PCD3312.

;------- Ecriture d'un octet sur PCD3312 ( A=octet a ecrire).
ecr_dt: push dph
        push dpl
        push acc

        Clr  C
        Mov  A,#25H             ;adresse du PCD3312
        Call SLAVE
        Clr  C
        Mov  A,#25H
        Call SLAVE
        pop  acc
        Clr  C
        call EBYTE

        pop  dpl
        pop  dph
        ret

;        Jc   DefautBus_I2c

;        Mov  dptr,#ecr_buf
;        Movx A,@DPTR
;        Mov  B,A                ;nbre d'octet a envoyer
;        Inc  DPL

SendData:
        Movx A,@DPTR            ;Acc=data a envoyer
        Call EBYTE
        Inc  DPL
        Djnz B,SendData

        Call STOP

DefautBus_I2c:
        Pop B
        pop dpl
        pop dph
        ret                     ;Erreur d'acquittement non geree.


;=============================================================================
; Routines de gestion interface logiciel I2C:
;       I2C_ECR : Ecriture sur composant I2C.
;       I2C_LEC : Lecture sur composant I2C.


;------- Ecriture sur composant I2C.
i2c_ecr push acc
        push dph
        push dpl

        SETB trig
        SETB bsda
        SETB bscl
        CLR trig

ecrit:  MOV DPTR,#ecr_buf
        MOVX A,@DPTR
        LCALL start
        JC end
        INC DPTR
        MOVX A,@DPTR
        MOV R1,A

trans:  INC DPTR
        MOVX A,@DPTR
        LCALL mtdat
        JC end
        DJNZ R1,trans
end:    LCALL stop

        pop dpl
        pop dph
        pop acc
        RET
;
;
;
start:  CLR bsda
        NOP
        NOP
        NOP
        NOP
        CLR bscl
mtdat:  MOV R2,#08H
        NOP
mstdat: RLC A
        MOV bsda,C
        SETB bscl
        NOP
        NOP
        NOP
        NOP
        NOP
        CLR bscl
        NOP
        DJNZ R2,mstdat
        SETB bsda
        NOP
        NOP
        SETB bscl
        NOP
        MOV C,bsda
        NOP
        NOP
        CLR bscl
        RET
;
;
;
stop:   MOV DPTR,#acq
        CLR A
        RLC A
        MOVX @DPTR,A
        CLR bsda
        SETB bscl
        NOP
        NOP
        NOP
        NOP
        NOP
        SETB bsda
        SETB trig
        RET
;
;

;------- Lecture sur composant I2C.
i2c_lec push acc
        push dph
        push dpl

        SETB trig
        SETB bsda
        SETB bscl
        CLR trig
        MOV DPTR,#lec_buf
        MOVX A,@DPTR
        MOV R3,A
        MOV DPTR,#lec_buf+1
        MOVX A,@DPTR
        JZ lect
        MOV A,R3
        LCALL start
        JC end1
        MOV DPTR,#lec_buf+1
        MOVX A,@DPTR
        MOV R1,A

trans1: INC DPTR
        MOVX A,@DPTR
        LCALL mtdat
        JC end1
        DJNZ R1,trans1
        SETB bsda
        SETB bscl
        CLR trig
        NOP
        NOP
        NOP
        NOP

lect:   MOV A,R3
        INC A
        LCALL start
        JC end1
        INC DPTR
        MOVX A,@DPTR
        DEC A
        INC DPTR
        JZ suite                ;Modifie de la version originale (jc -> jz).
        MOV R1,A

transi: LCALL read
        LCALL ack
        MOVX @DPTR,A
        INC DPTR
        DJNZ R1,transi
suite:  LCALL read
        LCALL nack
        MOVX @DPTR,A
end1:   LCALL stop

        pop dpl
        pop dph
        pop acc
        RET
;
;
;
read:   MOV R2,#08H
        CLR A
reads:  SETB bsda
        NOP
        SETB bscl
        NOP
        NOP
        MOV C,bsda
        NOP
        CLR bscl
        RLC A
        DJNZ R2,reads
        RET
;
;
;
ack:    CLR bsda
        NOP
        SETB bscl
        NOP
        NOP
        NOP
        NOP
        NOP
        CLR bscl
        RET
;
;
;
nack:   SETB bsda
        SETB bscl
        NOP
        NOP
        NOP
        NOP
        NOP
        CLR bscl
        RET
;
;------------------------------------------------------------------------------
;Routines d'afficha en hexa. des registres A et DPTR sur terminal.
;       AFFACC : Affiche A en hexa. sur le terminal.
;       AFFDPT : Affiche DPTR en hexa. sur le terminal.
;       AFFNL  : Saut de ligne sur terminal.

;------- Affiche A en hexa. sur le terminal.
affacc  push acc
        acall affbyte
        mov a,#20h              ;Espace.
        acall tx_rs             ;Envoi sur RS232.
        pop acc
        ret

;------- Affiche A en hexa. sur le terminal sans espace de fin.
affbyte push acc
        push acc
        swap a                  ;Inverse les quartets.
        anl a,#0Fh
        acall affqt             ;Envoi caractère 1ier quartet.
        pop acc
        anl a,#0Fh
        acall affqt             ;Envoi caractère 2ième quartet.
        pop acc
        ret

affqt   cjne a,#0Ah,affq1       ;Saut si A <> 0Ah.
affq1   jc affq2                ;Saut si A < 0Ah.
        add a,#07h              ;+37h si > 0Ah.
affq2   add a,#30h              ;+30h si < 0Ah.
        acall tx_rs             ;Envoi sur RS232.
        ret

;------- Affiche DPTR en hexa. sur le terminal.
affdptr push acc
        mov a,dph
        acall affbyte           ;Affiche DPH.
        mov a,dpl
        acall affbyte           ;Affiche DPL.
        mov a,#20h              ;Espace.
        acall tx_rs             ;Envoi sur RS232.
        pop acc
        ret

;------- Saut de ligne sur terminal.
affnl   push acc
        mov a,#0Dh
        lcall tx_rs
        mov a,#0Ah
        lcall tx_rs             ;Saut de ligne.
        pop acc
        ret

;------------------------------------------------------------------------------
; Routines d'Init,transmission et reception de caractere sur le port UART.
;       INIT_RS : Initialisation UART.
;       TX_RS   : Transmission de caractere.
;       RX_RS   : Reception avec attente de caractere.
;       ESP_RX  ; Quitte le programme si un espace recu sur UART.

;------- Initialisation UART.
init_rs mov scon,#8Ah           ;Voir livre 8051 p.145 rt photocopies Elektor.
;probleme= 9A : sm0,sm1 =10 donc 9 bits UART,fixed data rate!
        mov tmod,#20h           ;8 bits 1 stop.
        mov th1,#0FDh           ;9600 Bds.
        mov tl1,#0FDh
        setb tcon.7             ;Met TR1 a 1.
        ret

;init_rs  mov tmod,#2Eh	       ;timer 1 autoreload - 2 arrete.
;  	 mov TH1,#256-3  	       ;baud rate 9600@11.0592 Mhz;
;	 setb TR1
;         mov SCON,#70h           ;init UART mode 1,8 bits 1 stop
;	 ret

;------- Transmission de A.
tx_rs   JNB     scon.1,tx_rs    ;Attend disparition dernier caractere [TI a 1).
        CLR     scon.1          ;TI=0.
        MOV     sbuf,a          ;Demarre emission.
attn:   jnb     TI,attn
        clr     TI
        RET

;------- Reception dans A.
rx_rs   jnb     scon.0,rx_rs    ;Attend reception caractere (RI a 1).
        clr     scon.0          ;indique cherche.
        mov     a,sbuf          ;Lit caractere.
        ret

;------- Quitte le programme si un espace recu sur UART.
esp_rx  jnb scon.0,esp1         ;Retour si pas de reception UART (RI à 0).
        mov a,sbuf              ;Lit caractere sur port UART.
        clr scon.0              ;Indique lu.
        cjne a,#' ',esp1        ;Retour si pas caractere espace.
        pop acc
        pop acc                 ;Enleve adr. de retour de la pile.
esp1    ret                     ;Retour Basic.


;------------------------------------------------------------------------------

;		ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;		³      UTILITAIRES DE GESTION DU BUS I2C       ³
;		ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ



;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³S/P ENVOI START+ADRESSE ESCLAVE+ATTENTE ACQUIT		      ³
;³   APPEL: L'ACCU CONTIENT L'ADRESSE DE L'ESCLAVE		      ³
;³	    LE BIT CARRY : C=1 POUR UNE LECTURE; C=0 POUR UNE ECRITURE³
;³	    CALL SLAVE						      ³
;³   RETOUR:   C=1 SI DEFAUT DU BUS I2C 			      ³
;³   REGISTR RFL: COMPTEUR DE BITS				      ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ




SLAVE:  Push 1
	SETB LSCL
	NOP
	SETB LSDA		;initialisation du bus i2c
        JB   LSDA,BUSOK
	CALL DEBLOC		;deblocage bus i2c
        JNB  LSDA,BUSOUT
BUSOK:  RLC  A                   ;construit l'octet a envoyer dans l'accu
        MOV  R1,#8
        CLR  LSDA
        CLR  C
        CLR  LSCL                ;start condition
SUIV1:  RLC  A
        MOV  LSDA,C              ;emet le bit 
	NOP
	SETB LSCL
        CLR  C
        CLR  LSCL                ;impulsion d'horloge
        DJNZ R1,SUIV1
	SETB LSDA		;relache le bus data pour l'acquit
	NOP
	SETB LSCL		;impulsion d'horloge et test de l'acquit
	NOP
        MOV  C,LSDA
        CLR  LSCL
RETOUR: Pop  1
	RET
BUSOUT: SETB C
        JMP  RETOUR


;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³ENVOI D'UN OCTET + ACQUIT		     ³
;³   APPEL: L'ACCU CONTIENT L'OCTET A ENVOYER³
;³	    CALL EBYTE			     ³
;³   RETOUR:   C=1 SI DEFAUT DU BUS I2C      ³
;³   REGISTR RFL: COMPTEUR DE BITS	     ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
EBYTE:  Push 1
        MOV  R1,#8
	CLR C
SUIV2:	RLC A
	MOV LSDA,C		;emet le bit 
	NOP
	SETB LSCL
	CLR C
	CLR LSCL		;impulsion d'horloge
        DJNZ R1,SUIV2
	SETB LSDA		;relache le bus data pour l'acquit
	NOP
	SETB LSCL		;impulsion d'horloge et test de l'acquit
	NOP
	MOV C,LSDA
	CLR LSCL
PASAQUI: Pop 1
        RET


;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³GENERATION D'UN STOP³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
STOP_:  CLR LSDA
	NOP
	SETB LSCL
	NOP
	SETB LSDA
	RET


;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³DEBLOCAGE DU BUS³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
DEBLOC: PUSH 0
        MOV  R0,#8
PULSEH: CLR  LSCL
	NOP
	SETB LSCL
	NOP
        DJNZ R0,PULSEH
        POP  0
	RET

no      db '0657382017',00h

        end
