;************************************************* www.x-robotics.com *******
;---------------- RUTINAS SENSOR HUMEDAD Y TEMPERATURA SHT11 ----------------
;****************************************************************************
;Comandos:
;sht11_Humedad		:Lectura Humedad 16bits devuelve humedad en RH
;sht11_Set8bits		:Configura el sensor para trabajar en modo 8 bits
;sht11_Set14bits	:Configura el sensor para trabajar en modo 14 bits
;sht11_HeaterON		:Conecta el calentador interno anticondensacion
;sht11_HeaterOFF	:Desconecta el calentador interno anticondensacion
;sht11_Reset		:Resetea el sensor sht11
;
;
;----------------------------------------------------------------------------
;  Revision : 1.00   	Fecha: 6/1/2005       Programa para : PIC16F876
; CPU Clock : 4 MHz                      Tiempo instruccion : 1uS
;       WDT : OFF	                      Tipo de reloj : XT
; Code Prot : OFF          		    cfg USART rs232 ; none
;    
;****************************************************************************
		

sincbit		EQU	0x50		;contador envio de bits
Wdata		EQU	0x51		;variable de intercambio de datos
CMData		EQU	0x52		;variable de comandos
RXmsb		EQU	0x53		;registros de recepcion de datos
RXlsb		EQU	0x54
RH		EQU	0x55		;Porcentaje de Humedad Relativa

ACCaLO  	equ     0x61		;Variables de calculos
ACCaHI  	equ     0x60
ACCbLO  	equ     0x63
ACCbHI  	equ     0x62
ACCcLO  	equ     0x65
ACCcHI  	equ     0x64
ACCdLO  	equ     0x67
ACCdHI  	equ     0x66
temp    	equ     0x68
Flags		equ	0x69

;()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()
; ()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()
;()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()		

;Comandos rapidos-------------------------------------------------------------

sht11_Humedad	;LECTURA HUMEDAD 2 bytes
		call 	SHT11_start	;Inicio de transmision
		movlw	b'00000101'
		call	SHT11_CMD	;Envio: Lectura de humedad
		call	waitACK		;espera que llegue ACK desde el sensor
		call	adqtime		;espera que pase el tiempo de adquisicion
		call	readMSB		;lee el byte alto
		call	setACK
		call	readLSB		;lee el byte bajo
		call	setNACK
		call	CalcRH		;Calcula %RH y ajusta linealidad
					;retorna variable RH con dato		
		return			;Retorna
	
		
sht11_Set8bits	;configura el sensor para trabajar en modo 8 bits
		call 	SHT11_start	;Inicio de transmision
		movlw	b'00000111'	;-------------------------------------
		call	SHT11_CMD	;Envio: Lectura en config interna
		call	waitACK		;espera que llegue ACK desde el sensor
		call	readMSB		;lee el byte alto (Dato)
		call	waitACK		;-------------------------------------
		call	readLSB		;lee el byte bajo (CheckSum)
		call	setNACK

		call 	SHT11_start	;Inicio de transmision
		movlw	b'00000110'	;-------------------------------------
		call	SHT11_CMD	;Envio: Escritura en config interna
		call	waitACK		;espera que llegue ACK desde el sensor
		bsf	RXmsb,0		;pone un 1 en el bit adecuado...
		movf	RXmsb,W		;y carga el stats modificado del sensor
		call	SHT11_CMD	;Envio: modificacion de status
		call	waitACK		;espera que llegue ACK desde el sensor

		
		;call 	SHT11_start	;Inicio de transmision
		;movlw	b'00000111'	;-------------------------------------
		;call	SHT11_CMD	;Envio: Lectura en config interna
		;call	waitACK		;espera que llegue ACK desde el sensor
		;call	readLSB		;lee el byte bajo
		;call	setNACK		;-------------------------------------	
			
		return

sht11_Set14bits	;configura el sensor para trabajar en modo 14 bits
		call 	SHT11_start	;Inicio de transmision
		movlw	b'00000111'	;-------------------------------------
		call	SHT11_CMD	;Envio: Lectura en config interna
		call	waitACK		;espera que llegue ACK desde el sensor
		call	readMSB		;lee el byte alto (Dato)
		call	waitACK		;-------------------------------------
		call	readLSB		;lee el byte bajo (CheckSum)
		call	setNACK	
		
		call 	SHT11_start	;Inicio de transmision
		movlw	b'00000110'	;-------------------------------------
		call	SHT11_CMD	;Envio: Escritura en config interna
		call	waitACK		;espera que llegue ACK desde el sensor
		bcf	RXmsb,0		;pone un 1 en el bit adecuado...
		movf	RXmsb,W		;y carga el stats modificado del sensor
		call	SHT11_CMD	;Envio: modificacion de status
		call	waitACK		;espera que llegue ACK desde el sensor
		return	

sht11_HeaterON	;conecta el calentador interno anticondensacion
		call 	SHT11_start	;Inicio de transmision
		movlw	b'00000111'	;-------------------------------------
		call	SHT11_CMD	;Envio: Lectura en config interna
		call	waitACK		;espera que llegue ACK desde el sensor
		call	readMSB		;lee el byte alto (Dato)
		call	waitACK		;-------------------------------------
		call	readLSB		;lee el byte bajo (CheckSum)
		call	setNACK	

		call 	SHT11_start	;Inicio de transmision
		movlw	b'00000110'	;-------------------------------------
		call	SHT11_CMD	;Envio: Escritura en config interna
		call	waitACK		;espera que llegue ACK desde el sensor
		bsf	RXmsb,2		;pone un 1 en el bit adecuado...
		movf	RXmsb,W		;y carga el stats modificado del sensor
		call	SHT11_CMD	;Envio: modificacion de status
		call	waitACK		;espera que llegue ACK desde el sensor
		return	

sht11_HeaterOFF	;desconecta el calentador interno anticondensacion
		call 	SHT11_start	;Inicio de transmision
		movlw	b'00000111'	;-------------------------------------
		call	SHT11_CMD	;Envio: Lectura en config interna
		call	waitACK		;espera que llegue ACK desde el sensor
		call	readMSB		;lee el byte alto (Dato)
		call	waitACK		;-------------------------------------
		call	readLSB		;lee el byte bajo (CheckSum)
		call	setNACK	

		call 	SHT11_start	;Inicio de transmision
		movlw	b'00000110'	;-------------------------------------
		call	SHT11_CMD	;Envio: Escritura en config interna
		call	waitACK		;espera que llegue ACK desde el sensor
		bcf	RXmsb,2		;pone un 1 en el bit adecuado...
		movf	RXmsb,W		;y carga el stats modificado del sensor
		call	SHT11_CMD	;Envio: modificacion de status
		call	waitACK		;espera que llegue ACK desde el sensor
		return	
		

sht11_Reset	;Resetea el sensor sht11
		call 	SHT11_start	;Inicio de transmision
		movlw	b'00011110'	;-------------------------------------
		call	SHT11_CMD	;Envio: Lectura en config interna
		;espera de 11mS al menos despues de esta instruccion
		return

;()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()
; ()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()
;()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()
		

;==============================================================================
;-------------------------------R U T I N A S----------------------------------

;///////////////////////////////////////////////////////////////////////////
;Protocolo de inicio de transmision		
SHT11_start	;transmision start
		bsf	STATUS,RP0	;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
		bcf	STATUS,RP1
		bcf	TRISB,0		;puertos como salida
		bcf	TRISB,1
		bcf	STATUS,RP0	;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_-

		bsf	PORTB,0		;DATA a 1 (por defecto)
		nop			;espera un poco
		nop
		
		bsf	PORTB,1		;CLK
		bcf	PORTB,0		;DATA	(pulso bajo)
		bcf	PORTB,1		;CLK
		bsf	PORTB,1		;CLK
		bsf	PORTB,0		;DATA (por defecto alto)
		bcf	PORTB,1		;CLK
		return
;===========================================================================
;---------------------------------------------------------------------------



;///////////////////////////////////////////////////////////////////////////
;Manda comando de lectura de humedad
SHT11_CMD	movwf	CMData		;guarda el comando en variable
		clrf	sincbit
		bcf	STATUS,C	;borra carry
		bsf	STATUS,RP0	;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
		bcf	TRISB,0		;pone DATA port,0 como salida
		bcf	STATUS,RP0	;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
		
cont_send	rlf	CMData,F	;rota a la izquierda, bit alto en carry
;. . . . . . . . . . . . . . . . . . . . . .
;envio de datos segun el protocolo del sht11
send_data	btfsc	STATUS,C	;comprueba si es 1 o 0
		goto	uno		;
  					;
cero		bcf	PORTB,1		;SCK  falling edge -_
		bcf	PORTB,0		;DATA change
		bsf	PORTB,1		;SCK  rising edge  _-
		goto	sht11_compTX	;salta

uno		bcf	PORTB,1		;SCK  falling edge -_
		bsf	PORTB,0		;DATA change
		bsf	PORTB,1		;SCK  rising edge  _-
;. . . . . . . . . . . . . . . . . . . . . .
;Comprobacion para 8 rotaciones, una por bit del comando.
sht11_compTX    movlw 	.7		;comprobacion 8 bits
                subwf   sincbit,W       ;Compara 
                btfsc   STATUS,Z        ;Es el ultimo?             
                return			;Si, >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                incf    sincbit,f       ;Incrementa numero de sincbit
                goto    cont_send	;Vuelve a escribir
;===========================================================================
;---------------------------------------------------------------------------



;///////////////////////////////////////////////////////////////////////////
;Espera la llegada de ACK desde el sensor
waitACK		;espera el ACK del sensor
		bsf	STATUS,RP0	;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
		bsf	TRISB,0		;pone DATA port,0 como entrada
		bcf	STATUS,RP0	;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_-	
		
		nop
		nop
		nop
		nop
		
ACKrx		bcf	PORTB,1		;SCK  falling edge
		nop
		nop			;5uS de retardo
		nop
		nop
		nop
		bsf	PORTB,1		;SCK  rising edge
		btfsc	PORTB,0		;comprueba data
		goto	ACKrx		;NO, bucle
		bcf	PORTB,1		;SCK  falling edge estado bajo por defecto
		return

;ack desde SHT11 detectado y llegada de datos			
adqtime		btfsc	PORTB,0		;comprueba data
		goto	adqtime		;NO, bucle
		return
;===========================================================================
;---------------------------------------------------------------------------



;///////////////////////////////////////////////////////////////////////////
;LECTURA DE DATOS DESDE EL SHT11 (Byte alto)
readMSB		clrf	RXmsb		;limpia registro
		bsf	RXmsb,0		;pone un 1 que indicara en carry el final

leemsb		bcf	PORTB,1		;SCK  falling edge
		bsf	PORTB,1		;SCK  rising edge
		btfss	PORTB,0		;lee data
		goto	es_ceromsb

es_unomsb	rlf	RXmsb,f		;rota a la izquierda
		bsf	RXmsb,0		;pone un 1  en el bit 0
		btfss	STATUS,C	;salio la marca por carry?
		goto	leemsb		;continua y captura el siguiente bit
		return

es_ceromsb	rlf	RXmsb,f		;rota a la izquierda
		bcf	RXmsb,0		;pone un 0  en el bit 0
		btfss	STATUS,C	;salio la marca por carry?
		goto	leemsb		;continua y captura el siguiente bit
		return			;retorna
;===========================================================================
;---------------------------------------------------------------------------



;///////////////////////////////////////////////////////////////////////////
;LECTURA DE DATOS DESDE EL SHT11 (Byte bajo)	
readLSB		clrf	RXlsb		;limpia registro
		bsf	RXlsb,0		;pone un 1 que indicara en carry el final

leelsb		bcf	PORTB,1		;SCK  falling edge
		bsf	PORTB,1		;SCK  rising edge
		btfss	PORTB,0		;lee data
		goto	es_cerolsb

es_unolsb	rlf	RXlsb,f		;rota a la izquierda
		bsf	RXlsb,0		;pone un 1  en el bit 0
		btfss	STATUS,C	;salio la marca por carry?
		goto	leelsb		;continua y captura el siguiente bit
		return

es_cerolsb	rlf	RXlsb,f		;rota a la izquierda
		bcf	RXlsb,0		;pone un 0  en el bit 0
		btfss	STATUS,C	;salio la marca por carry?
		goto	leelsb		;continua y captura el siguiente bit
		return			;retorna
;===========================================================================
;---------------------------------------------------------------------------


	
;///////////////////////////////////////////////////////////////////////////
setACK		bsf	STATUS,RP0	;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
		bcf	TRISB,0		;pone DATA port,0 como salida
		bcf	STATUS,RP0	;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
			
		bcf	PORTB,1		;SCK  falling edge
		bcf	PORTB,0		;DATA change nivel logico 0
		bsf	PORTB,1		;SCK  rising edge
		nop
		nop
		nop
		nop
		nop
		nop
		nop
		nop
		
		;bsf	PORTB,0		;DATA change nivel logico 1(reposo)
		
		bsf	STATUS,RP0	;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
		bsf	TRISB,0		;pone DATA port,0 como entrada
		bcf	STATUS,RP0	;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
		return
;===========================================================================
;---------------------------------------------------------------------------



;///////////////////////////////////////////////////////////////////////////
setNACK		bsf	STATUS,RP0	;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
		bcf	TRISB,0		;pone DATA port,0 como salida
		bcf	STATUS,RP0	;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
			
		bcf	PORTB,1		;SCK  falling edge
		bsf	PORTB,0		;DATA change nivel logico 0
		bsf	PORTB,1		;SCK  rising edge
		nop
		bcf	PORTB,1		;baja clk
		
		bsf	STATUS,RP0	;banco 1 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
		bsf	TRISB,0		;pone DATA port,0 como entrada
		bcf	STATUS,RP0	;banco 0 _-_-_-_-_-_-_-_-_-_-_-_-_-_-
		return
;===========================================================================
;---------------------------------------------------------------------------




;///////////////////////////////////////////////////////////////////////////
CalcRH		;RH% calculos de linealidad. (a*RH%+b)/256
		movlw	.0		;0		;MultiplicLO
		movwf	ACCaHI
		movf	RXlsb,W	      	;lectura 8 bits	;MultiplicHI
		movwf	ACCaLO
		
		
		movlw	.108		
		subwf	RXlsb,W
		btfsc	STATUS,C
		goto	calcA2
		
;-------------- Si lectura menor o igual a 107...
calcA1		movlw	.143		;A		;ResultLLO
		movwf	ACCbLO
		movlw	.0		;A		;ResultHHI
		movwf	ACCbHI
		
		call	D_mpyS 		;multiplica (A*RH)
		;el resultado esta en ACCcHI,ACCcLO		

		;resta 512 del resultado
		
		;comprueba si el dato es mayor de 512
		;si fuera menor.. pone como resultado 512
		;si es mayor.. resta 2 a MSB que equivale a 512
		;del dato de 16bits		
		movlw	.3		;resta 2
		subwf	ACCcHI,W	
		btfss	STATUS,C
		goto 	menord2		;mayor de 2



mayord2		;si es mayor de 512.. resta 512 al resultado
		;y luego comprueba que el resultado no sea menor de 512
		movlw	.2
		subwf	ACCcHI,F	;resta 512 al dato alto 

		movlw	.3		;si el resultado es 
		subwf	ACCcHI,W	;menor de 512...
		btfss	STATUS,C
		goto 	menord2		;mayor de 2
		goto	calccont	;si es mayor continua

menord2		;si es menor de 2 pone como resultado 512
		movlw	.2
		movwf	ACCcHI		;resultado=512
		clrf	ACCcLO
		goto	calccont	;continua con los calculos


		
		goto	calccont
		
;-------------- Si lectura mayor o igual a 108...
calcA2		movlw	.111		;A		;ResultLLO
		movwf	ACCbLO
		movlw	.0		;A		;ResultHHI
		movwf	ACCbHI
		
		call	D_mpyS 		;multiplica (A*RH)
		
		;suma 2893 al resultado
		;suma 11 a MSB(mas acarrero de LSB) y 77 a LSB
		
		;MSB=ACCcHI  LSB=ACCcLO para 16bits de resolucion
		
		movlw	.11
		addwf	ACCcHI		;suma 11 a MSB
		
		movlw	.77		;suma 77 a LSB y si hay acarreo
		addwf	ACCcLO		;se lo suma a LSB
		
		btfsc	STATUS,C	;comprueba el acarreo
		incf	ACCcHI		;suma el acarreo a MSB
					;no hay acarreo y salta
		


calccont	;continua con el calculo de %RH	
		;ahora divide el resultado de 16bits / 256

		;El resultado completo de 32 bits = ( ACCbHI,ACCbLO,ACCcHI,ACCcLO )

		;el resutlado despues de rotar 8 bits es el mismo que 
		;el byte (ACCcHI) correspondiente al byte 2 menos significativo
		
		
		movf	ACCcHI,W
		movwf	RH		;RH = Relative Humidity
		
		return			;retorna con el resultado calculado
		




;=================================================================================
;=================================================================================
;=================================================================================


;*******************************************************************
;                    Double Precision Multiplication
;
;               ( Optimized for Code Size : Looped Code )
;
;*******************************************************************;
;   Multiplication : ACCb(16 bits) * ACCa(16 bits) -> ACCb,ACCc ( 32 bits )
;      (a) Load the 1st operand in location ACCaLO & ACCaHI ( 16 bits )
;      (b) Load the 2nd operand in location ACCbLO & ACCbHI ( 16 bits )
;      (c) CALL D_mpy
;      (d) The 32 bit result is in location ( ACCbHI,ACCbLO,ACCcHI,ACCcLO )
;*******************************************************************;
;
;
;*******************************************************************
;               Double Precision Multiply ( 16x16 -> 32 )
;         ( ACCb*ACCa -> ACCb,ACCc ) : 32 bit output with high word
;  in ACCb ( ACCbHI,ACCbLO ) and low word in ACCc ( ACCcHI,ACCcLO ).
;

D_mpyS                           ;results in ACCb(16 msb's) and ACCc(16 lsb's)
		call    setupmult
		bcf	STATUS,C
mloop   
		rrf     ACCdHI,F       	;rotate d right
		rrf     ACCdLO,F
		btfss   STATUS,C    	;need to add?
		goto    No_add
		movf    ACCaLO,W        ; Addition ( ACCb + ACCa -> ACCb )
		addwf   ACCbLO,F       	;add lsb
		btfsc   STATUS,C    	;add in carry
 		incf    ACCbHI,F
		movf    ACCaHI,W
		addwf   ACCbHI,F       	;add msb

No_add		rrf     ACCbHI,F
		rrf     ACCbLO,F
		rrf     ACCcHI,F
		rrf     ACCcLO,F
		decfsz  temp,F        	 ;loop until all bits checked
		goto    mloop
		goto	end1


;         Double Precision Addition ( ACCb + ACCa -> ACCb )
;
D_add  	        bcf	Flags,C		;Clear temp Carry bit
		movf    ACCaLO,W        ; Addition ( ACCb + ACCa -> ACCb )
		addwf   ACCbLO,F       	;add lsb
		btfsc   STATUS,C    	;add in carry
 		incf    ACCbHI,F
		btfsc	STATUS,C
		bsf	Flags,C	
		movf    ACCaHI,W
		addwf   ACCbHI,F        ;add msb
		btfsc	Flags,C
		bsf	STATUS,C
		return

;
;
;*******************************************************************
;
setupmult  	movlw   .16             ; for 16 shifts
		movwf   temp
		movf    ACCbHI,W        ;move ACCb to ACCd
		movwf   ACCdHI
		movf    ACCbLO,W
		movwf   ACCdLO
		clrf    ACCbHI
		clrf    ACCbLO
		return
;
;****************************************************************
end1		return
