; ARCHIVO RTC V3F88.ASM
; CODIGO FUENTE PARA EL MICROCONTROLADOR PIC16F88 

; PROGRAMA DE PARA IMPLEMENTAR UN RELOJ DE TIEMPO REAL MOSTRANDO
; LA HORA, MINUTOS Y SEGUNDOS EN UN DISPLAY LCD DE 16 X 1. 
; SE USO COMO BASE EL PROGRAMA
; "MINUTO.ASM" QUE UNA BASE DE TIEMPO EXACTA DE UN MINUTO
; POR INTERRUPCIONES. 
; SE USA EL TEMPORIZADOR TMR0 Y SU PREESCALADOR PARA GENERAR 
; 65.536 MILISEGUNDOS POR CADA CICLO DE INTERRUPCION.
; LA HORA DE INICIO PUEDE MODIFICARSE EN LA RUTINA "seto".


; VERSION PARA OSCILADOR CRISTAL 4 MHZ

; CPU configuration
; 	(It's a 16F88, XT OSCILADOR
; 	watchdog timer off, power-up timer on)

	processor 16f88
	include	  <p16f88.inc> 

#DEFINE	BANCO0	BCF	STATUS,RP0
#DEFINE	BANCO1	BSF	STATUS,RP0
#DEFINE	GLOB	INTCON,7			;BANDERA GLOBAL INTERRUPT ENABLE
#DEFINE	TIE		INTCON,5			;BANDERA TMR0 INTERRUPT ENABLE
#DEFINE	TOCS	OPTION_REG,5			;BANDERA PARA USAR CLOK INTERNO EN TMR0
#DEFINE	ZERO	STATUS,2			;BANDERA "Z" EN STATUS
#DEFINE	FLAG	INTCON,2			;BANDERA DE INTERRUPCION DE TEMPO
#DEFINE	RELE	PORTA,0				;BIT DEL RELEVADOR

;localidades de memoria usadas por el RTC
CONT1	EQU	H'20'		;CONTADOR DE CICLOS DE 65.5 MILISEGUNDOS. 
						;15 CICLOS ES APROX. UN SEGUNDO
CONT2	EQU	H'21'		;CONTADOR DE UNIDADES DE SEGUNDOS. 
CONT3	EQU	H'22'		;CONTADOR DECENAS DE SEGUNDOS
CONT4	EQU	H'23'		;CONTADOR UNIDADES DE MINUTO
CONT5	EQU	H'24'		;CONTADOR DECENAS DE MINUTO
CONT6	EQU 	H'25'		;CONTADOR UNIDADES DE HORA
CONT7	EQU 	H'26'		;CONTADOR DECENAS DE HORA
DUMMY	EQU 	H'27'	
DILEY	EQU	H'28'		;CONTADOR DELAY PARA AJUSTE FINO
L	EQU	H'29'		;variable subrutina delay
M	EQU	H'2A'		;variable subrutina delay

;valores usados por el LCD
eight		equ	H'38'		
clear		equ	H'01'
home		equ	H'03'
cursor		equ	H'0F'
renglon1	equ 	H'80'
renglon2	equ 	H'C0'

PUERTOS	MACRO		;INICIALIZA PUERTOS A Y B
		BANCO0
		bcf		RCSTA,SPEN	;DESHABILITA UART
		BANCO1
		movlw	7
		movwf	CMCON
		clrf	CVRCON
		clrf	ANSEL	
		MOVLW	H'00'	;RB0..RB7=SALIDAS, RA0...RA4=SALIDAS
		MOVWF	TRISB
		MOVWF	TRISA
		ENDM

LCD		MACRO		;INICIALIZA LCD
		BANCO0
		movlw	eight	;envía 4 comandos
		call 	puco
		movlw	clear
		call 	puco
		movlw	home
		call 	puco
		movlw	cursor
		call 	puco
		movlw	renglon1
		call 	puco
		movlw	renglon2
		call	puco
		ENDM	

;aquí inicia el programa
		org 0
		
		clrf	PCLATH
inicio		goto	begin		;salta a inicio del programa

		org 	H'4'		;subrutina de interrupción en la dirección 4				
int		BANCO0			;aquí inicia la subrutina de interrupción
		call	diley		;retraso para ajuste fino del tiempo
		call	diley
		clrf	TMR0
		bcf	FLAG		;apaga bandera de interrupción del TMR0		
		incf	CONT1,f		;incrementa contador de 65.5 ms.
		movlw	D'15'
		subwf	CONT1,w		;prueba si la cuenta es igual a 15
		btfss	ZERO		;bandera Z encendida?
		goto	retfi
seg1		BANCO0	
		incf	PORTB,f		;cuenta segundos en el puerto B
		clrf	CONT1		;CONT1=0
		incf	CONT2,f		;incrementa contador de segundos
		movlw	H'C7'
		call	puco
		movlw	H'30'
		addwf	CONT2,w
		call	verify		;verifica si es '3A'
		call	puda
		movlw	D'10'
		subwf	CONT2,w		;prueba si la cuenta es igual a 9
		btfss	ZERO		;Z = 1 ?
		goto	retfi
seg10		clrf	CONT2	
		incf	CONT3,f	
		movlw	H'C6'
		call	puco
		movlw	H'30'
		addwf	CONT3,w
		call	verify2
		call	puda			
		movlw	D'6'
		subwf	CONT3,w
		btfss	ZERO
		goto	retfi
min1		clrf	CONT3
		incf	CONT4,f
		movlw	H'C4'
		call	puco
		movlw	H'30'
		addwf	CONT4,w
		call	verify
		call	puda
		movlw	D'10'
		subwf	CONT4,w
		btfss	ZERO
		goto	retfi
min10		clrf	CONT4
		incf	CONT5,f
		movlw	H'C3'
		call	puco
		movlw	H'30'
		addwf	CONT5,w
		call	verify2
		call	puda
		movlw	D'6'
		subwf	CONT5,w
		btfss	ZERO
		goto	retfi
hora1		clrf	CONT5
		incf	CONT6,f
		movlw	H'C1'
		call	puco
		movlw	H'30'
		addwf	CONT6,w
		call	verify
		call	puda
		movlw	D'10'
		subwf	CONT6,w
		btfss	ZERO
		goto	retfi	
hora10		clrf	CONT6
		incf	CONT7,f
		movlw	H'C0'
		call	puco
		movlw	H'30'
		addwf	CONT7,w
		call	puda
		goto	retfi	
retfi		bsf	TIE		;reactiva la interrupción
		retfie

ceros		clrf	CONT1		;pone en ceros todos los contadores
		clrf	CONT2
		clrf	CONT3
		clrf	CONT4
		clrf	CONT5
		clrf	CONT6
		clrf	CONT7
		return

hora24		movlw	D'4'		;verifica si llegó a 24:00:00
		subwf	CONT6,w
		btfss	ZERO
		goto	sigue
		movlw	D'2'
		subwf	CONT7,w
		btfss	ZERO
		goto	sigue
		call	ceros
		call	write
		return	

diley		movlw	D'187'		;subrutina de retraso para ajuste fino 187
		movwf	DILEY
malla		decfsz	DILEY
		goto 	malla
		return
verify		movwf	DUMMY
		movlw	H'3A'
		subwf	DUMMY,w
		btfss	ZERO
		goto 	salto2	
		movlw	H'30'
		return
salto2		movfw	DUMMY
		return
verify2		movwf	DUMMY
		movlw	H'36'
		subwf	DUMMY,w
		btfss	ZERO
		goto 	salto3	
		movlw	H'30'
		return
salto3		movfw	DUMMY
		return

;aquí inicia el programa principal

begin		PUERTOS
		LCD
		call	seto
		call	write			
		movlw	B'00000111'	;HABILITA TEMPORIZADOR Y CLOCK INTERNO
					;preescalador divide entre 256
		BANCO1
		movwf	OPTION_REG
		BANCO0
		bcf	RELE		;APAGA RELEVADOR
		clrf	PORTB
		movlw	D'00'
		movwf	TMR0		;INICIALIZA TEMPORIZADOR=00	
		bsf	GLOB		;habilita interrupciones global
		bsf	TIE		;habilita interrupción del temporizador.
		clrf	PORTB
sigue		call	hora24
		goto	sigue

;modifique estos parámetros si desea cambiar la hora de inicio y vuelva a
;aplicar el comando "quickbuild" para ensamblar el programa.

seto		movlw	d'0'		;segundos
		movwf	CONT2		
		movlw	d'0'		;decenas de segundos
		movwf	CONT3		
		movlw	d'0'		;minutos
		movwf	CONT4
		movlw	d'2'		;decenas de minutos
		movwf	CONT5
		movlw	d'5'		;horas
		movwf	CONT6
		movlw	d'1'		;decenas de horas
		movwf	CONT7
		return
write		movlw	h'c7'		;escribe la hora en el LCD
		call	puco
		movlw	h'30'
		addwf	CONT2,w
		call 	puda
		movlw	h'c6'
		call	puco
		movlw	h'30'
		addwf 	CONT3,w
		call	puda
		movlw	h'c5'
		call	puco
		movlw	':'
		call	puda
		movlw	h'c4'
		call	puco
		movlw	h'30'
		addwf	CONT4,w
		call 	puda
		movlw	h'c3'
		call	puco
		movlw	h'30'
		addwf	CONT5,w
		call 	puda
		movlw	h'c2'
		call	puco
		movlw	':'
		call	puda
		movlw	h'c1'
		call	puco
		movlw	h'30'
		addwf	CONT6,w
		call	puda
		movlw	h'c0'
		call	puco
		movlw	h'30'
		addwf	CONT7,w
		call	puda
		movlw	h'80'
		call 	puco
		movlw	'T'
		call	puda
		movlw	'I'
		call	puda
		movlw	'M'
		call	puda
		movlw	'E'
		call	puda
		return
		
		
;aquí inician subrutinas para el manejo del LCD

puco		movwf	PORTB		;escribe comando en puertoB
		call 	delay		;50 milisegundos
		movlw	H'04'		;RS=0, EN=1
		movwf	PORTA
		call 	delay
		movlw	H'00'		;RS=0, EN=0
		movwf	PORTA
		call 	delay
		movlw	H'04'
		movwf	PORTA
		call 	delay
		return
puda		movwf	PORTB		;escribe dato en puertoB
		call 	delay		;50 milisegundos
		movlw	H'06'		;RS=1, EN=1
		movwf	PORTA
		call 	delay
		movlw	H'02'		;RS=1, EN=0
		movwf	PORTA
		call 	delay
		movlw	H'06'
		movwf	PORTA
		call 	delay
		return

;aquí inician las subrutinas de retraso

delay		movlw	D'25'		;10 milisegundos
		movwf	M
malla3		movwf	L
malla2		decfsz	L,f
		goto	malla2	
		decfsz	M,f
		goto	malla3
		return	
delay2		movlw	D'250'		;250 milisegundos
		movwf	M
malla5		movwf	L
malla4		decfsz	L,f
		goto	malla4	
		decfsz	M,f
		goto	malla5
		return
delay3		call	delay2		;1 segundo
		call	delay2
		call	delay2



		end

