;##########################################################################
;#                                                                        #
;#                                                                        #
;#                                                                        #
;#   Version 2.0                                    15/12/2007            #
;#                                                                        #
;#                                                                        #
;#     Fichier I2CASM.A51                                                 #
;#                                                                        #
;#------------------------------------------------------------------------#
;#                                                                        #
;#   S/pgm I2cManuel 						          #
;#                                                                        #
;##########################################################################
;
$NOMOD51		; disable predefined 8051 registers
$INCLUDE (8031.INC)	; include CPU definition file (for example, 8052)


        
	public _EmisI2c,RecepI2c,StopI2c,StartI2c,Tempo5MicroS


i2casm segment code
	rseg i2casm


;********************************************************
;* titre : Tempo6MicroS		                       	*
;*------------------------------------------------------*
;*                     				  	*
;* fonction: tempo de 6 µs à 16mhz		    	*
;*  call 2µs,ret 2µs					*
;*							*
;*------------------------------------------------------*
;* param. d'entree : aucun  				*
;********************************************************

Tempo5MicroS:   ;call :2 µs
		nop	;1 µs
		ret	;2µs



;**********************************************************
;* titre : emis_i2c master by   ELECTRO8051	      	  *
;*--------------------------------------------------------*
;*                     				          *
;* fonction: emet un octet sur bus i2c            	  * 
;*--------------------------------------------------------*
;* reg. modifie : A,B,carry 				  *
;* param. d'entree : R7:octet à envoyer			  *
;* param. de sortie: c =1 ack/slave,c=0 pas d'ack du slave*
;* Attend 20µS la montée de SCL si handshake/SCL	  *
;* pour CPU8051 12cycles/instruction 11,0592Mhz	I2C:100khZ*
;**********************************************************
_EmisI2c:
	MOV	B,#8
    	mov     a,R7	;Recup octet à envoyer
 
EMIS1:	CLR	SCL
	nop	
	RLC	A
	MOV	SDA,C    ;Bit info dans SDA
	SETB	SCL 
        JNB SCL,ATTsicl  ;test si stretching scl par slave
EMIS2:	DJNZ	B,EMIS1
EMIS3:	CLR	SCL
	nop
	nop
	SETB	SDA ;Le master laisse floter SDA pour que le slave le tire à 0:ACK du slave	
	MOV	B,#20 ;Durée de l'attente du ACK 10H initialement pour 8051 a 14 Mhz
	SETB	SCL
	JB	SDA,ATTACQ ;le slave doit donner le Ack par un 0 sur SDA        
ACQ:	nop
	nop
	nop
	CLR	SCL
	SETB	C	;C=1:le slave a bien acquitté l'octet écrit dans dans ce dernier

RET2:	RET	;FIN
ATTACQ:		;Attente ACK pendant décrément de B	
	JNB	SDA,ACQ  ;Si ACK reçu Fin
	DJNZ	B,ATTACQ
ARRET:	call StopI2c
	clr c	;C=0 pour indiquer pas ACK 
	SJMP	RET2
ATTsicl:JB	SCL,EMIS2 ;Attente 16 µS max remontée SCL voir specif i2c page 13
	JB	SCL,EMIS2
	JB	SCL,EMIS2
	JB	SCL,EMIS2
	JB	SCL,EMIS2
	JB	SCL,EMIS2
	JB	SCL,EMIS2
	JB	SCL,EMIS2
	SJMP	ARRET   ;Trop long,fin
;********************************************************
;* titre : RecepI2c master by ELECTRO8051        	*
;*------------------------------------------------------*
;*                     				  	*
;* fonction: reçoit un octet sur bus i2c 100khz        	*
;*							*
;*------------------------------------------------------*
;* reg. modifie : A,B      				*
;* param. d'entree : R7 (0x1:ack/master,0/pas ack)     *
;* param. de sortie: octet reçu  dans R7          	*
;* CPU8051 12cycles/instruction 11,0592Mhz I2C:100khZ   *
;*                                    		 	*
;********************************************************
_RecepI2c:          ;le _ signifie que la routine est passee avec une variable
	;PUSH	B
	MOV	B,#8
REC1:	
	CLR	SCL
	call Tempo5MicroS
	SETB	SCL
        JNB SCL,ATTsicl2  ;test si stretching scl par slave
CONT:	MOV	C,SDA
	RLC	A
	DJNZ	B,REC1
	mov B,R7	;sauvegarde de R7 dans B
	mov R7,A    ; résultat dans R7 pour le C    
	CLR	SCL	;genere 1 master dernier byte
 	mov A,B  ;Recup de la valeur initiale de R7
	nop
	nop
	jz  glop	;Si A=0, pas d'ack et saut a glop
	CLR SDA
	sjmp glap
GLOP:	SETB	sda  ;Pas de ack:cas octet unique ou dernier octet si plusieurs
glap:	SETB	SCL	; acknowledge
	call Tempo5MicroS
	clr	SCL
	SETB SDA    
	;POP	B
	RET
ATTsicl2:JB	SCL,CONT ;Attente 16 µS max remontée SCL voir specif i2c page 13
	JB	SCL,CONT
	JB	SCL,CONT
	JB	SCL,CONT
	JB	SCL,CONT
	JB	SCL,CONT
	JB	SCL,CONT
	JB	SCL,CONT
	call StopI2c ;Trop long,fin
	ret
;********************************************************
;* titre : StopI2c		                       	*
;*------------------------------------------------------*
;*                     				  	*
;* fonction: Envoie les conditions de Stop/bus I2c    	*
;*------------------------------------------------------*
;* param. d'entree : aucun  				*
;********************************************************



StopI2c:   
	CLR	SDA
	CLR 	SCL
	SETB	SCL
	Call Tempo5MicroS		;4.7 micro mini	
	SETB	SDA
        RET

;********************************************************
;* titre : StartI2c 		                       	*
;*------------------------------------------------------*
;*                     				  	*
;* fonction: Envoie les conditions de Start/bus I2c    	*
;*------------------------------------------------------*
;* param. d'entree : aucun  				*
;********************************************************



StartI2c:   	setb 	SDA     ;
		setb SCL
		call Tempo5MicroS	;4,7 µs mini
		clr SDA
        	RET




	END