;**********************************************************************
;*       TECNICAS DIGITALES II           			      *
;**********************************************************************

;Materia: Tecnicas Digitales II
;Proyecto: MEDIDOR DE MONOXIDO DE CARBONO
;Autor: GONZALO FALLINI - ANDRES MONACO
;Fecha: 22 / 12 / 09
;Microcontrolador: PIC16F887

;**********************************************************************
;	CONFIGURACIÓN DE LOS PUERTOS DEL PIC        		      *
;**********************************************************************
;	----------\/----------
;	- RE3     P      RB7 -
; 	- RA0     I      RB6 -
;	- RA1     C      RB5 -
;	- RA2     1      RB4 -
;	- RA3     6      RB3 -
;	- RA4     F      RB2 -
;	- RA5     8      RB1 -
;	- RE0     8      RB0 -
;	- RE1     7      VDD -
;	- RE2		 	 VSS -
;	- VDD		 	 RD7 -
;	- VSS		 	 RD6 -
;	- RA7			 RD5 -
;	- RA6			 RD4 -
;	- RC0			 RC7 -
;	- RC1		 	 RC6 -
;	- RC2		 	 RC5 -
;	- RC3		 	 RC4 -
;	- RD0		 	 RD3 -
;	- RD1		 	 RD2 -
;	----------------------
;
;**********************************************************************
;*	DEFINICIÓN DEL ARCHIVO DE CABECERA PARA EL MICRO   	      *
;**********************************************************************

	INCLUDE "p16F887.inc"
	TITLE		"2do PARCIAL"
  	SUBTITLE	"Tecnicas Digitales II"
  	PROCESSOR       16F887
  	LIST		r = dec, F = INHX8M, MM = ON, T = ON, ST = OFF
	RADIX           HEX
  	__IDLOCS        H'0000'
        ERRORLEVEL      0, -302, -306

;**********************************************************************
;*	DEFINICIÓN DE LOS PARÁMETROS DE GRABACIÓN DEL PIC	      *
;**********************************************************************

	__CONFIG	_CONFIG1, _DEBUG_OFF & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT
	__CONFIG	_CONFIG2, _WRT_OFF & _BOR40V

;**********************************************************************
;*                       DEFINICIÓN DE VARIABLES (RAM)                *
;**********************************************************************

 CBLOCK h'20'	;Comienzo del banco 0 de memoria RAM en el PIC
 ;Aca van las variables
	Contador
	segh
	segl
	minh
	minl
	horash
	horasl
	W_Temp
	STATUS_Temp
	TemP
	NUM1
	NUM2
	PDel0
	PDel1
	TECLA
	cont_24
	cont_sen
	d1
	d2
	d3
	SAMPLE
	DATOH
	DATOH0
	DATOH1
	TEMPO0
	TEMPO1
	DecenaMil			
	UnidadMil		
	Centena			
	Decena	
	Unidad
	N1
	N2
	N3	
 ENDC		;Final de definiciones de variables de RAM
 CBLOCK h'A0'	;Comienzo del banco 1 de memoria RAM en el PIC
 ;Aca van las variables
		
 ENDC		;Final de definiciones de variables de RAM
 CBLOCK h'120'	;Comienzo del banco 2 de memoria RAM en el PIC
 ;Aca van las variables

 ENDC		;Final de definiciones de variables de RAM
 CBLOCK h'1A0'	;Comienzo del banco 3 de memoria RAM en el PIC
 ;Aca van las variables
		
 ENDC		;Final de definiciones de variables de RAM

;**********************************************************************
;*	                 DEFINICION DE MACROS	                      *
;**********************************************************************

BANCO0      MACRO
      bcf   STATUS,RP0
      bcf   STATUS,RP1
      endm

BANCO1      MACRO
      bsf   STATUS,RP0
      bcf   STATUS,RP1
      endm

BANCO2      MACRO
      bsf   STATUS,RP1
      bcf   STATUS,RP0
      endm

BANCO3      MACRO
      bsf   STATUS,RP1
      bsf   STATUS,RP0
      endm

;**********************************************************************
;*			DEFINICIÓN DE ETIQUETAS                       *
;**********************************************************************

#DEFINE BITZ	    STATUS, Z     	 	  ;Bit de cero
#DEFINE BITC	    STATUS, C      		  ;Bit de carry
#DEFINE RS 	    	PORTC,2
#DEFINE EN 	    	PORTC,1

;**********************************************************************
;*                  	COMANDOS LCD			              *
;**********************************************************************

LIMPIAR	 EQU B'00000001' ;LIMPIA TODA LA PANTALLA
RENGLON1 EQU B'10000000' ;COLOCA EN EL RENGLON 1
RENGLON2 EQU B'11000000' ;COLOCA EN EL RENGLON2
DISON 	 EQU B'00001100' ;ENCIENDE EL DISPLAY
HOME 	 EQU B'00000010' ;VA A LA DIDERCCION 0
SHIFTDL  EQU B'00011100' ;ROTA EL LCD A LA IZQUIERDA
SHIFTDR  EQU B'00011000' ;ROTA EL LCD A LA DERECHA
SHIFTCL  EQU B'00010100' ;ROTA EL CURSOR A LA IZQUIERDA
SHIFTCR  EQU B'00010000' ;ROTA EL CURSOR A LA DERECHA
PORTLCD	 EQU PORTD

;**********************************************************************
;*                     INICIO				              *
;**********************************************************************

   org     0x00

	goto    PPAL

;**********************************************************************
;*		      VECTOR DE INTERRUPCIONES           	      *
;**********************************************************************

   org 0x04			;Comienzo vector de interrupciones
	
	goto	Inicio_ISR
	retfie

;**********************************************************************
;*                     PAGINA 1		0x0005 A 0x07FF	              *
;**********************************************************************

PPAL

;**********************************************************************
;			Inhibe comparadores			      *
;**********************************************************************

	banksel	CM1CON0
	movlw 	0x00
	movwf	CM1CON0		;Deshabilitacion de comparador1
	banksel	CM2CON0
	movlw 	0x00
	movwf	CM2CON0		;Deshabilitacion de comparador2

;**********************************************************************
;			Pull-Ups RB				      *
;**********************************************************************

	banksel	OPTION_REG
	bsf	OPTION_REG,7	;activo pull up PORTB

;**********************************************************************
;			Configuro Puertos			      *
;**********************************************************************

	BANCO1
	movlw	0x0D		;RA0=AN0, RA2,RA3 = VREF, las tres son entradas
	movwf	TRISA		;las demas son salidas.
	movlw	0x0E		;RB0 salida
	movwf	TRISB		;RB1 a RB3 entradas, RB4 a RB7 salidas...esto es para teclado 3x4
	movlw	0x80		;Salida de led, salida a LCD, control memoria serie
	movwf	TRISC		;control Tx-Rx
	movlw	0x00		;Salida para LCD
	movwf	TRISD		;
	movlw	0x08		;RE3 siempre es entrada, las demas las puse como salidas
	movwf	TRISE		;
	BANCO0
	movlw	0x00
	movwf	PORTA
	movwf	PORTB
	movwf	PORTC
	movwf	PORTD
	movwf	PORTE

;**********************************************************************
;			Inicializo variables                          *
;**********************************************************************

	clrf	Contador
	clrf	segh
	clrf	segl
	clrf	minh
	clrf	minl
	clrf	horash
	clrf	horasl
	clrf	W_Temp
	clrf	STATUS_Temp
	clrf	TemP
	clrf	NUM1
	clrf	NUM2
	clrf	PDel0
	clrf	PDel1
	clrf	TECLA
	clrf	cont_24
	clrf	cont_sen
	clrf	d1
	clrf	d2
	clrf	d3
	clrf	SAMPLE
	clrf	DATOH
	clrf	DATOH0
	clrf	DATOH1
	clrf	TEMPO0
	clrf	TEMPO1
	clrf	DecenaMil			
	clrf	UnidadMil		
	clrf	Centena			
	clrf	Decena	
	clrf	Unidad
	movlw	0x30
	movwf	N1
	movwf	N2
	movwf	N3

;**********************************************************************
;			Enciendo ADC			              *
;**********************************************************************

	pagesel	INI_ADC
	call	INI_ADC
	pagesel	$

;**********************************************************************
;			Configuro LCD				      *
;**********************************************************************

	pagesel	INITLCD
	call	INITLCD
	pagesel	$

;**********************************************************************
;		inicializo señales de control sensor		      *
;**********************************************************************

	pagesel	PASO_0
	call	PASO_0
	pagesel	$

;**********************************************************************
;			Configuro TMR0				      *
;**********************************************************************	

	BANCO1
	movlw	b'00000111'	; Se selecciona TMR0 modo temporizador y preescaler de 1/256.-
	movwf	OPTION_REG
	BANCO0
	movlw	0x3D		; Cargamos 61 en TMR0 para lograr aprox. 50ms.-
	movwf	TMR0
	clrf	Contador	; Iniciamos contador.-
	movlw	b'10100000'	; Habilitamos GIE y T0IE (interrupción del TMR0)
	movwf	INTCON

;**********************************************************************
;                     Subrutina PROGRAMA                              *
;**********************************************************************

PROGRAMA
	bcf	PORTE,0

	pagesel	CONV_PPM
	call	CONV_PPM	;convierto el valor del adc a PPM
	pagesel	$

	pagesel	Binario_BCD
	call	Binario_BCD	; obtengo centena, decena y unidad
	pagesel	$

	pagesel	conv_ascii
	call	conv_ascii	;le sumo 0x30 y lo paso a ascii
	pagesel	$

	pagesel	MOST_CLK
	call	MOST_CLK	;muestro el reloj en la pantallita LCD
	pagesel	$

	pagesel	MOST_PPM
	call	MOST_PPM	;muestro las PPM en la pantallita LCD
	pagesel	$

	bcf	STATUS,Z
	bcf	STATUS,C

	pagesel	TECLADO
	call	TECLADO
	pagesel	$

	movlw	0x02		;si toco la tecla 2 voy a setear la hora
	subwf	TECLA,0
	btfsc	STATUS,Z
	goto	SET_RELOJ

;	movlw	0x07		;si toco la tecla 7 leo memoria y transmito a la PC
;	subwf	TECLA,0
;	btfsc	STATUS,Z
;	goto	RD_MEM_TX

;	movlw	0x09		;si toco la tecla 9 limpio la memoria
;	subwf	TECLA,0
;	btfsc	STATUS,Z
;	goto	CLR_MEM

;	movlw	0x0B		;si toco la tecla 0 reseteo el circuito
;	subwf	TECLA,0
;	btfsc	STATUS,Z
;	goto	RESE_T

	goto	PROGRAMA	

;**********************************************************************
;*                     PAGINA 2		0x0800 A 0x0FFF		      *
;**********************************************************************

;**********************************************************************
;*                     Subrutina TECLADO            	              *
;**********************************************************************

TECLADO
INTERR
	pagesel	MOST_CLK
	call	MOST_CLK
	pagesel	$

	movlw	0xF0			;Activar parte alta del puerto A
	movwf	PORTB
	btfsc	PORTB,1			;verifico que fila se presiono
	goto	SCANTEC			
	btfsc	PORTB,2			
	goto	SCANTEC			
	btfsc	PORTB,3
	goto	SCANTEC
	goto	INTERR
UNINT
	btfsc	PORTB,1			; esta subrrutina
	goto	UNINT			; se encarga de asegurarse que ya no
	btfsc	PORTB,2			; haya ninguna tecla apretada para
	goto	UNINT			; continuar con el programa. Si no se
	btfsc	PORTB,3			; usara, el programa leería miles de
	goto	UNINT			; veces el mismo caracter, pero
	return				; normalmente se quiere leerlo una
					; sola vez.
SCANTEC
					;Subrutina que asigna valores para
	clrf	PORTB			;cada tecla diferente del teclado.
	pagesel	DEMORA
	call	DEMORA			;Llamar a Antirrebote de teclado(50mS)
	pagesel	$
	clrw				;Vaciar W

	bsf	PORTB,4			;Activar primera fila
	btfsc	PORTB,1			;Si RB0 = 1, entonces
	movlw	0x01			;el resultado será = 1
	btfsc	PORTB,2			;Si RB1 = 1, entonces
	movlw	0x02			;el resultado será = 2
	btfsc	PORTB,3			; ...
	movlw	0x03
	pagesel	UNINT
	call	UNINT
	pagesel	$

	bcf	PORTB,4			;Desactivar primera fila
	bsf	PORTB,5			;Activar segunda fila
	btfsc	PORTB,1			;Leer y asignar valores
	movlw	0x04
	btfsc	PORTB,2
	movlw	0x05
	btfsc	PORTB,3
	movlw	0x06
	pagesel	UNINT
	call	UNINT
	pagesel	$

	bcf	PORTB,5			;Desactivar segunda fila
	bsf	PORTB,6			;Activar tercera fila
	btfsc	PORTB,1			;Leer y asignar valores
	movlw	0x07
	btfsc	PORTB,2
	movlw	0x08
	btfsc	PORTB,3
	movlw	0x09
	pagesel	UNINT
	call	UNINT
	pagesel	$

	bcf	PORTB,6			;Desactivar tercera fila
	bsf	PORTB,7			;Activar cuarta fila
	btfsc	PORTB,1			;Leer y asignar valores
	movlw	0x0A
	btfsc	PORTB,2
	movlw	0x0B
	btfsc	PORTB,3
	movlw	0x0C
	pagesel	UNINT
	call	UNINT
	pagesel	$

	bcf	PORTB,7			;Desactivar cuarta fila
	movwf	TECLA			;Mover valor final a RESULT
	return

DEMORA 
	movlw     .55       ; 1 set numero de repeticion  (B)
     	movwf     PDel0     ; 1 |
PLoop0
	movlw     .181      ; 1 set numero de repeticion  (A)
     	movwf     PDel1     ; 1 |
PLoop1
	clrwdt              ; 1 clear watchdog
     	clrwdt              ; 1 ciclo delay
     	decfsz    PDel1, 1  ; 1 + (1) es el tiempo 0  ? (A)
     	goto      PLoop1    ; 2 no, loop
     	decfsz    PDel0, 1  ; 1 + (1) es el tiempo 0  ? (B)
     	goto      PLoop0    ; 2 no, loop
     	return              ; 2+2 Fin.

;**********************************************************************
;                SETEO DE LA HORA Y LOS MINUTOS                       *
;**********************************************************************

SET_RELOJ
	bcf	STATUS,Z
	bcf	STATUS,C
	bsf	PORTE,0

	pagesel	TECLADO
	call	TECLADO
	pagesel	$

	movlw	0x04
	subwf	TECLA,0
	btfsc	STATUS,Z
	goto	SET_HS		;si toco 4 voy a setear las horas
	movlw	0x06
	subwf	TECLA,0
	btfsc	STATUS,Z
	goto	SET_MIN		;si toco 6 voy a setear los minutos
	movlw	0x05
	subwf	TECLA,0
	btfsc	STATUS,Z
	goto	VOLVER		;tocando 5 hago OK y vuelvo a setear o a el prog principal
	goto	SET_RELOJ

SET_HS
	pagesel	MOST_CLK
	call	MOST_CLK
	pagesel	$

	bcf	STATUS,Z
	bcf	STATUS,C

	pagesel	TECLADO
	call	TECLADO
	pagesel	$

	movlw	0x01		;si toco 1 incremento el contador de las horas
	subwf	TECLA,0
	btfsc	STATUS,Z
	goto	INC_HS
	movlw	0x05		;tocando 5 hago OK
	subwf	TECLA,0
	btfsc	STATUS,Z
	goto	SET_RELOJ
	goto	SET_HS

INC_HS
	bcf	STATUS,Z
	bcf	STATUS,C
	incf	cont_24
	movlw	d'24'
	subwf	cont_24,0
	btfsc	STATUS,Z
	goto	horas_24
	incf	horasl,1
	movfw	horasl
	movwf	TemP
	movlw	d'10'
	subwf	TemP
	btfss	STATUS,Z
	goto	SET_HS
	clrf	horasl
	incf	horash,1
	goto	SET_HS
horas_24
	clrf	horasl
	clrf	horash
	goto	SET_HS
		
SET_MIN
	pagesel	MOST_CLK
	call	MOST_CLK
	pagesel	$

	bcf	STATUS,Z
	bcf	STATUS,C

	pagesel	TECLADO
	call	TECLADO
	pagesel	$

	movlw	0x03		;si toco 3 incremento el contador de minutos	
	subwf	TECLA,0
	btfsc	STATUS,Z
	goto	INC_MIN
	movlw	0x05		;tocando 5 hago OK
	subwf	TECLA,0
	btfsc	STATUS,Z
	goto	SET_RELOJ
	goto	SET_MIN

INC_MIN
	bcf	STATUS,Z
	bcf	STATUS,C
	incf	minl,1
	movfw	minl
	movwf	TemP
	movlw	d'10'
	subwf	TemP
	btfss	STATUS,Z
	goto	SET_MIN
	clrf	minl
	incf	minh,1
	movfw	minh
	movwf	TemP
	movlw	d'6'
	subwf	TemP
	btfsc	STATUS,Z
	clrf	minh
	goto	SET_MIN


VOLVER
	pagesel	PROGRAMA
	goto	PROGRAMA

;**********************************************************************
;*                     PAGINA 3		0x1000 A 0x17FF		      *
;**********************************************************************

;**********************************************************************
;		CODIGO DE LA INTERRUPCION DE TMR0                     *
;**********************************************************************

Inicio_ISR
	movwf	W_Temp		; Copiamos W a un registro Temporario.-
	swapf	STATUS, W	;Invertimos los nibles del registro STATUS.-
	movwf	STATUS_Temp	; Guardamos STATUS en un registro temporal.-

;**** Interrupcion por TMR0 *******************************************
ISR
	btfss	INTCON,T0IF	; Consultamos si es por TMR0.-
	goto	Fin_ISR		; No, entonces restauramos valores.-
	incf	Contador,1	; Si, Incrementamos contador
	movlw	0x14		; Consultamos si se han producido 20 desbordes,
	subwf	Contador,0	; para obtener 1000 ms.-
	btfss	STATUS,Z	;
	goto	Actualizo_TMR0	; No, cargo TMR0 si salgo.-	
	clrf	Contador	; Si, reseteo Contador y controlo Led.-

	pagesel	SEGUNDOS
	call	SEGUNDOS
	pagesel	$

	movlw	d'60'		
	subwf	cont_sen,0
	btfss	STATUS,Z
	goto	ACA1

	pagesel	PASO_1
	call	PASO_1		;activo funete de 0.25, desactivo la de 0.8 y la de 5 y mantengo cerrados los switch
	pagesel	$
ACA1
	movlw	d'149'
	subwf	cont_sen,0
	btfss	STATUS,Z
	goto	ACA2

	pagesel	PASO_2
	call	PASO_2
	pagesel	$
ACA2
	movlw	d'150'
	subwf	cont_sen,0
	btfss	STATUS,Z
	goto	ACA3

	pagesel	PASO_0
	call	PASO_0
	pagesel	$
ACA3		
Actualizo_TMR0			; Actualizo TMR0 para obtener una temporizacion de 1000 ms.-
	movlw	0x3D		; d'61'
	movwf	TMR0
	bcf	INTCON,T0IF	; Borro bandera de control de Interrupcion.-
	goto	Fin_ISR		; Restauro valores.-

;**********Restauramos los valores de W y STATUS***************************

Fin_ISR
	swapf	STATUS_Temp,W	; Invertimos lo nibles de STATUS_Temp.-
	movwf	STATUS
	swapf	W_Temp, f	; Invertimos los nibles y lo guardamos en el mismo registro.-
	swapf	W_Temp,W	; Invertimos los nibles nuevamente y lo guardamos en W.-
	retfie			; retorno de la interrupcion.-

;**************************************************************************

SEGUNDOS
	incf	cont_sen,1
	incf	segl,1
	movfw	segl
	movwf	TemP
	movlw	d'10'
	subwf	TemP
	btfss	STATUS,Z
	return
	clrf	segl
	incf	segh,1
	movfw	segh
	movwf	TemP
	movlw	d'6'
	subwf	TemP
	btfsc	STATUS,Z
	goto	MINUTOS
	return
MINUTOS
	clrf	segh
	incf	minl,1
	movfw	minl
	movwf	TemP
	movlw	d'10'
	subwf	TemP
	btfss	STATUS,Z
	return
	clrf	minl
	incf	minh,1
	movfw	minh
	movwf	TemP
	movlw	d'6'
	subwf	TemP
	btfsc	STATUS,Z
	goto	HORAS
	return
HORAS
	clrf	minh
	incf	cont_24
	movlw	d'24'
	subwf	cont_24,0
	btfsc	STATUS,Z
	goto	horas24
	incf	horasl,1
	movfw	horasl
	movwf	TemP
	movlw	d'10'
	subwf	TemP
	btfss	STATUS,Z
	return
	clrf	horasl
	incf	horash,1
	return
horas24
	clrf	horasl
	clrf	horash
	return

;**********************************************************************
;		 señales de control sensor		              *
;**********************************************************************

PASO_0
	clrf	cont_sen
	movlw	0x50
	movwf	PORTA
	return
PASO_1
	movlw	0x60
	movwf	PORTA
	return
PASO_2
	movlw	0x80
	movwf	PORTA

	pagesel	Delay500ms
	call	Delay500ms
	pagesel	$

	pagesel	ADQUI
	call	ADQUI
	pagesel	$

	return

;**********************************************************************
Delay500ms
			;499994 cycles
	movlw	0x03
	movwf	d1
	movlw	0x18
	movwf	d2
	movlw	0x02
	movwf	d3

Delay500ms_0
	decfsz	d1, f
	goto	$+2
	decfsz	d2, f
	goto	$+2
	decfsz	d3, f
	goto	Delay500ms_0
			;2 cycles
	goto	$+1
			;4 cycles (including call)
	return


;**********************************************************************
;*              SUBRUTINA DE ADQUISICION DEL ADC	              *
;**********************************************************************

ADQUI 
	pagesel	SampleTime
	call 	SampleTime 	;RETARDO DE ADQUISICION
	pagesel	$

	bsf 	ADCON0,GO 	;INICIA LA CONVERSION
	btfsc 	ADCON0,GO 	;YA SE TERMINO LA CONVERSION?
	goto 	$-1 		;NO? PREGUNTA DE NUEVO
	banksel ADRESH 		;SI, CONTINUA
	movf 	ADRESH,W 	;LEE LA PARTE MAS SIGNIFICATIVA
	movwf 	DATOH 		;GUARDALO EN DATOH

	pagesel	CONV_PPM
	call	CONV_PPM	;convierto el valor del adc a PPM
	pagesel	$

	pagesel	Binario_BCD
	call	Binario_BCD	; obtengo centena, decena y unidad
	pagesel	$

	pagesel	conv_ascii
	call	conv_ascii	;le sumo 0x30 y lo paso a ascii
	pagesel	$

	pagesel	MOST_PPM
	call	MOST_PPM
	pagesel	$

	return

;***********retardo de adquisicion*************************************

SampleTime
	movlw 	.255
	movwf 	SAMPLE
ESPERA_S 
	nop
	nop
	decfsz 	SAMPLE,F
	goto 	ESPERA_S
	return



;**********************************************************************
;*              convercion del dato a PPM	                      *
;**********************************************************************

CONV_PPM
	movf	DATOH,0
	movwf	DATOH0
;copy accumulator to temporary
	movf	DATOH0, w
	movwf	TEMPO0


;shift accumulator right 4 times
	swapf	DATOH0, w
	andlw	0x0F
	movwf	DATOH0

;add temporary to accumulator
	movf	TEMPO0, w
	addwf	DATOH0, f

;shift accumulator right 3 times
	rrf	DATOH0, f
	clrc
	rrf	DATOH0, f
	clrc
	rrf	DATOH0, f

;add temporary to accumulator
	addwf	DATOH0, f

;shift accumulator right 2 times
	rrf	DATOH0, f
	clrc
	rrf	DATOH0, f

;substract temporary from accumulator
	subwf	DATOH0, f

;shift accumulator right 6 times
	clrf	DATOH1
	skpc
	comf	DATOH1, f
	rlf	DATOH0, f
	rlf	DATOH1, f
	rlf	DATOH0, f
	rlf	DATOH1, f
	movf	DATOH1, w
	movwf	DATOH0

;substract temporary from accumulator
	clrf	DATOH1
	btfsc	DATOH0, 7
	comf	DATOH1, f
	movf	TEMPO0, w
	subwf	DATOH0, f
	movlw	0x01
	skpc
	subwf	DATOH1, f

;shift accumulator right 3 times
	rlf	DATOH1, w
	rrf	DATOH1, f
	rrf	DATOH0, f
	rrf	DATOH1, f
	rrf	DATOH0, f
	rlf	DATOH0, w
	rrf	DATOH0, f

;substract temporary from accumulator
	clrf	DATOH1
	btfsc	DATOH0, 7
	comf	DATOH1, f
	movf	TEMPO0, w
	subwf	DATOH0, f
	movlw	0x01
	skpc
	subwf	DATOH1, f

;shift accumulator right 6 times
	rlf	DATOH0, f
	rlf	DATOH1, f
	rlf	DATOH0, f
	rlf	DATOH1, f
	movf	DATOH1, w
	movwf	DATOH0

;add temporary to accumulator
	movf	TEMPO0, w
	addwf	DATOH0, f

;shift accumulator right 1 times
	clrc
	rrf	DATOH0, f

;add temporary to accumulator
	addwf	DATOH0, f

;shift accumulator right 2 times
	rrf	DATOH0, f
	clrc
	rrf	DATOH0, f

;substract temporary from accumulator
	subwf	DATOH0, f

;shift accumulator right 3 times
	rrf	DATOH0, f
	movlw	0x80
	xorwf	DATOH0, f	;invert bit shifted from carry
	rlf	DATOH0, w
	rrf	DATOH0, f
	rlf	DATOH0, w
	rrf	DATOH0, f

;shift temporary left 2 times
	clrc
	rlf	TEMPO0, f
	clrf	TEMPO1
	rlf	TEMPO1, f
	rlf	TEMPO0, f
	rlf	TEMPO1, f

;add temporary to accumulator
	clrf	DATOH1
	btfsc	DATOH0, 7
	comf	DATOH1, f
	movf	TEMPO0, w
	addwf	DATOH0, f
	movf	TEMPO1, w
	skpnc
	incfsz	TEMPO1, w
	addwf	DATOH1, f

;shift accumulator right once and
;increment if carry set
	clrc
	rrf	DATOH1, f
	rrf	DATOH0, f
	skpc
	goto	no_inc
	incf	DATOH0, f
	skpnz
	incf	DATOH1, f
no_inc
	return

;**********************************************************************
;*              convierto de binario a BCD	                      *
;**********************************************************************

Binario_BCD
	swapf 	DATOH0,w
	andlw 	0x0F
	addlw 	0xF0
	movwf 	UnidadMil
	addwf 	UnidadMil,f
	addlw 	0xE2
	movwf 	Centena
	addlw 	0x32
	movwf 	Unidad
	movf 	DATOH0,w
	andlw 	0x0F
	addwf 	Centena,f
	addwf 	Centena,f
	addwf 	Unidad,f
	addlw 	0xE9
	movwf 	Decena
	addwf 	Decena,f
	addwf 	Decena,f
	swapf 	DATOH1,w
	andlw 	0x0F
	addwf 	Decena,f
	addwf 	Unidad,f
	rlf 	Decena,f
	rlf 	Unidad,f
	comf 	Unidad,f
	rlf 	Unidad,f
	movf 	DATOH1,w
	andlw 	0x0F
	addwf 	Unidad,f
	rlf 	UnidadMil,f
	movlw 	0x07
	movwf 	DecenaMil
	movlw 	0x0A
Lb1	
	addwf 	Unidad,f
	decf 	Decena,f
	btfss	STATUS,C
	goto 	Lb1
Lb2
	addwf 	Decena,f
	decf 	Centena,f
	btfss 	STATUS,C
	goto 	Lb2
Lb3
	addwf 	Centena,f
	decf 	UnidadMil,f
	btfss 	STATUS,C
	goto 	Lb3
Lb4
	addwf 	UnidadMil,f
	decf 	DecenaMil,f
	btfss 	STATUS,C
	goto 	Lb4
	return

;**********************************************************************
;*              convercion de BCD a ASCII	                      *
;**********************************************************************

conv_ascii
	movlw	0x30
	addwf	Centena,0
	movwf	N1
	movlw	0x30
	addwf	Decena,0
	movwf	N2
	movlw	0x30
	addwf	Unidad,0
	movwf	N3
	return	

;**********************************************************************
;*                     PAGINA 4		0x1800 A 0x1FFF		      *
;**********************************************************************

;**********************************************************************
;*                    subrutina inicializacion del ADC         	      *
;**********************************************************************

INI_ADC
	banksel ADCON1
	movlw 	B'00110000' 	;JUSTIFICACIÓN A LA IZQUIERDA
	movwf 	ADCON1 		;Vss referencia y V=1v ref+ externa
	banksel TRISA 		;
	nop
	nop
	bsf 	TRISA,0 	;PONEMOS A RA0 COMO ENTRADA
	bsf	TRISA,2		;PONEMOS A RA2 COMO ENTRADA
	bsf	TRISA,3 	;PONEMOS A RA3 COMO ENTRADA
	banksel	ANSEL
	bsf	ANSEL,0		;AN0
	bsf	ANSEL,2		;AN2 para entrada de referencia
	bsf	ANSEL,3		;AN3 para entrada de referencia
	banksel ANSELH 		;
	clrf 	ANSELH		;
	banksel ADCON0 		;
	movlw 	B'11000001' 	;ELEGIMOS EL RELOJ Frc DEL ADC
	movwf 	ADCON0 		;Y ENCENDEMOS EL CONVERTIDOR
	BANCO0
	return

;**********************************************************************
;*                    subrutina inicializacion del LCD         	      *
;**********************************************************************

INITLCD
	movlw 	B'00110000';1
	pagesel	CMD
	call  	CMD
	pagesel	$

	movlw 	B'00110000';2
	pagesel	CMD
	call  	CMD
	pagesel	$

	movlw 	B'00110000';3
	pagesel	CMD
	call  	CMD
	pagesel	$

	movlw 	B'00111100';4
	pagesel	CMD
	call  	CMD
	pagesel	$

	movlw 	B'00001000';5
	pagesel	CMD
	call  	CMD
	pagesel	$

	movlw 	B'00000001';6
	pagesel	CMD
	call  	CMD
	pagesel	$

	movlw 	B'00000110';7
	pagesel	CMD
	call  	CMD
	pagesel	$

	movlw 	DISON;8
	pagesel	CMD
	call  	CMD
	pagesel	$

	movlw 	HOME
	pagesel	CMD
	call  	CMD
	pagesel	$

	return

;**************SUBRUTINA QUE ENVIA LOS COMANDOS A LA LCD****************

CMD 
	movwf 	PORTLCD
	bcf   	RS
	nop
	nop
	nop
	bsf   	EN

	pagesel	RETARDO
	call  	RETARDO
	pagesel	$

	bcf   	EN
	return

;*******SUBRUTINA QUE ENVIA LOS CARACTERES A LA LCD*********************

DATO 
	movwf 	PORTLCD
	bsf   	RS
	nop
	nop
	nop
	bsf   	EN

	pagesel	RETARDO
	call  	RETARDO
	pagesel	$

	bcf   	EN
	return

;************************************************************************

RETARDO				;retardo 5ms	;4993 cycles
	movlw	0xE6
	movwf	NUM1
	movlw	0x04
	movwf	NUM2
espera
	decfsz	NUM1, f
	goto	$+2
	decfsz	NUM2, f
	goto	espera
			;3 cycles
	goto	$+1
	nop
			;4 cycles (including call)
	return


;**********************************************************************
;*                    MOSTRAR RTC EN RENGLON 1         	              *
;**********************************************************************
MOST_CLK
	movlw 	B'10000000'
	pagesel	CMD
	call  	CMD
	pagesel	$
	
	movlw 	'H'
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw	'O'
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	'R'
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	'A'
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	':'
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw	' '
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	' '
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	' '
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw	0x30
	addwf	horash,w
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw	0x30
	addwf	horasl,w
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw	':'
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	0x30
	addwf	minh,w
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	0x30
	addwf	minl,w
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw	':'
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	0x30
	addwf	segh,w
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	0x30
	addwf	segl,w
	pagesel	DATO
	call 	DATO
	pagesel	$

	return

;**********************************************************************
;*                    MOSTRAR PPM EN RENGLON 2         	              *
;**********************************************************************

MOST_PPM
	movlw 	B'11000000'
	pagesel	CMD
	call  	CMD
	pagesel	$
	
	movlw 	' '
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw	' '
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw	' '
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	' '
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	'P'
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	'P'
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	'M'
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	':'
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	' '
	pagesel	DATO
	call 	DATO
	pagesel	$

	movf	N1,0
	pagesel	DATO
	call 	DATO
	pagesel	$

	movf	N2,0
	pagesel	DATO
	call 	DATO
	pagesel	$

	movf	N3,0
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	' '
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	' '
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	' '
	pagesel	DATO
	call 	DATO
	pagesel	$

	movlw 	' '
	pagesel	DATO
	call 	DATO
	pagesel	$


	return
;**********************************************************************	

	END

















