; ARCHIVO TEMPOV7F88TINY.ASM
;              ****** USO DE LA EEPROM ******
;*****DESHABILITA INTERRUPCIONES ANTES DE HACER LA*****
;*****COMPARACION DE LAS HORAS DE ACTIVACION Y DESACTIVACION*****
;*****PERMITE ALMACENAR EN FORMA PERMANENTE DATOS DE*****
;*****ACTIVACION Y DESACTIVACION A PESAR DE SE SUSPENDA*****
;*****EL SUMINISTRO DE ENERGIA A LA TARJETA*****
; TEMPORIZADOR QUE PERMITE CONFIGURAR 2 HORAS DE ACTIVACION 
; Y 2 HORAS DE DESACTIVACION DEL RELEVADOR. 
; GUARDA LOS DATOS TECLEADOS POR EL USUARIO EN EEPROM
; SE INTRODUCE LA HORA A TRAVES
; DEL TECLADO INTRODUCIENDO LOS DIGITOS EN FORMA CONSECUTIVA
; DESPUES DE OPRIMIR EL BOTON DE RESET, 
; EL LCD ESCRIBE LA PALABRA "SET:" Y DEBE ESCRIBIRSE LA HORA
; CON EL FORMATO (EJEMPLO) 074534
; PARA PONER LA HORA 07:45:34 Ó "F" PARA 00:00:00
; DESPUES DE LA PALABRA "ACTI1:" Ó "ACTI2:", SE DA LA HORA DE 
; ACTIVACION O "F" PARA TOMAR EL DATO ALMACENADO PREVIAMENTE EN 
; EEPROM.DESPUES DE LA PALABRA "DESA1:" Ó "DESA2:", SE DA LA HORA
; DE DESACTIVACION Ó "F" PARA TOMAR EL DATO ALMACENADO PREVIAMENTE 
; EN EEPROM.
; EL PROGRAMA IMPLEMENTA UN RELOJ DE TIEMPO REAL MOSTRANDO
; LA HORA, MINUTOS Y SEGUNDOS EN UN DISPLAY LCD DE 16 X 1. 
; SE IMPLEMENTA UNA BASE DE TIEMPO EXACTA POR INTERRUPCIONES. 
; SE USA EL TEMPORIZADOR TMR0 Y SU PREESCALADOR PARA GENERAR 
; 65.536 MILISEGUNDOS POR CADA CICLO DE INTERRUPCION.


; 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> 

BANCO0	MACRO	
			BCF	STATUS,RP0
			BCF	STATUS,RP1
			ENDM
BANCO1	MACRO
			BSF	STATUS,RP0
			BCF	STATUS,RP1
			ENDM
BANCO2	MACRO				;EEADR,EEDATA
			BCF	STATUS,RP0
			BSF	STATUS,RP1
			ENDM
BANCO3	MACRO				;EECON1,EECON2
			BSF	STATUS,RP0
			BSF	STATUS,RP1
			ENDM
#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

;localidades de memoria usadas por el teclado

I		EQU	H'30'		;valor columna (RB0...RB3)
J		EQU	H'31'		;contador 4 rotaciones
K		EQU	H'32'		;valor renglón (RB4..RB7)
PK		EQU	H'33'		;variable subrutina delay
Q		EQU	H'34'		;variable subrutina delay
RK		EQU	H'35'		;variable para checar tecla liberada
N		EQU H'36'
DIG		EQU H'37'		;LOCALIDAD PARA CONTAR DIGITOS EN SETIME

;LOCALIDADES DE MEMORIA USADAS PARA GUARDAR HORAS DE ACTIVACION
;Y DESACTIVACION DEL RELEVADOR

ACT2	EQU	H'38'
ACT3	EQU	H'39'
ACT4	EQU	H'3A'
ACT5	EQU	H'3B'
ACT6	EQU	H'3C'
ACT7	EQU	H'3D'
DESAC2	EQU	H'3E'
DESAC3	EQU	H'3F'
DESAC4	EQU	H'40'
DESAC5	EQU	H'41'
DESAC6	EQU	H'42'
DESAC7	EQU	H'43'
ROMBY	EQU	H'44'	;LOCALIDAD PARA ALMACENAMIENTO TEMPORAL
WEB	EQU	H'45'	;TEMPORAL
AACT2	EQU	H'48'
AACT3	EQU	H'49'
AACT4	EQU	H'4A'
AACT5	EQU	H'4B'
AACT6	EQU	H'4C'
AACT7	EQU	H'4D'
DDESAC2	EQU	H'4E'
DDESAC3	EQU	H'4F'
DDESAC4	EQU	H'50'
DDESAC5	EQU	H'51'
DDESAC6	EQU	H'52'
DDESAC7	EQU	H'53'

;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		;DESHABILITA COMPARADORES ANALOGICOS
		CLRF	CVRCON		;DESHABILITA VOLTAJE DE REFERENCIA
		CLRF	ANSEL		;DESHABILITA CONVERTIDORES			
		CLRF	TRISA		;RA0=SALIDA,RA1...RA4=ENTRADAS
		CLRF	TRISB		;RB0...RB7=SALIDAS
		BANCO0			 			
		CLRF	PORTB		;LEDS APAGADOS
		BCF	RELE		;DESHABILITA RELEVADOR
		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
		
		ENDM	

;aquí inicia el programa
		ORG 0
		CLRF PCLATH
		goto begin

;aquí inicia la subrutina de interrupción

		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
		return
		movlw	D'2'
		subwf	CONT7,w
		btfss	ZERO
		return
		call	ceros		;pone en ceros contadores de la hora actual
		call	write
		return
;***
compaq:	movlw	7				;RUTINA COMPARA SI CONTADORES SON IGUALES
		movwf	WEB				;inicializa número de dígitos A COMPARAR
		movlw	CONT7
		movwf	FSR				;inicializa FSR
malla10:	decfsz	WEB		
		goto	siga
DACTO:	bcf		RELE			;desactiva relevador
		return
siga:	movf	INDF,w
		movwf	ROMBY
		movlw	H'1D'			;offset para apuntar a DESAC
		addwf	FSR
		movf	INDF,w
		subwf	ROMBY
		btfss	ZERO
NONIG:	return
IGUAL:	movlw	H'1D'
		subwf	FSR				;deja FSR apuntando de nuevo a CONT
		decf	FSR
		goto 	malla10
;***
ccompaq:	movlw	7				;RUTINA COMPARA SI CONTADORES SON IGUALES
		movwf	WEB				;inicializa número de dígitos A COMPARAR
		movlw	CONT7
		movwf	FSR				;inicializa FSR
mmalla10:	decfsz	WEB		
		goto	ssiga
DDACTO:	bcf		RELE			;desactiva relevador
		return
ssiga:	movf	INDF,w
		movwf	ROMBY
		movlw	H'2D'			;offset para apuntar a DESAC
		addwf	FSR
		movf	INDF,w
		subwf	ROMBY
		btfss	ZERO
NNONIG:	return
IIGUAL:	movlw	H'2D'
		subwf	FSR				;deja FSR apuntando de nuevo a CONT
		decf	FSR
		goto 	mmalla10
;***
;***
compac:	movlw	7				;RUTINA COMPARA SI CONTADORES SON IGUALES
		movwf	WEB				;inicializa número de dígitos A COMPARAR
		movlw	CONT7
		movwf	FSR				;inicializa FSR
malla9:	decfsz	WEB		
		goto	sigo
ACTO:	bsf		RELE			;activa relevador
		return
sigo:	movf	INDF,w
		movwf	ROMBY
		movlw	H'17'			;offset para apuntar a ACT
		addwf	FSR
		movf	INDF,w
		subwf	ROMBY
		btfss	ZERO
NOIG:	return
IGUA:	movlw	H'17'
		subwf	FSR				;deja FSR apuntando de nuevo a CONT
		decf	FSR
		goto 	malla9
;***
ccompac:	movlw	7				;RUTINA COMPARA SI CONTADORES SON IGUALES
		movwf	WEB				;inicializa número de dígitos A COMPARAR
		movlw	CONT7
		movwf	FSR				;inicializa FSR
mmalla9:	decfsz	WEB		
		goto	ssigo
AACTO:	bsf		RELE			;activa relevador
		return
ssigo:	movf	INDF,w
		movwf	ROMBY
		movlw	H'27'			;offset para apuntar a ACT
		addwf	FSR
		movf	INDF,w
		subwf	ROMBY
		btfss	ZERO
NNOIG:	return
IIGUA:	movlw	H'27'
		subwf	FSR				;deja FSR apuntando de nuevo a CONT
		decf	FSR
		goto 	mmalla9
;***
			

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	setime		;recibe hora del teclado y la pone en contadores
		movlw	CONT2
		movwf	FSR
		call	write
		call	delay3
		call	delay3
		call	activa		;RECIBE HORA DE ACTIVACIÓN Y GUARDA EN LOCALIDADES		
		movlw	ACT2
		movwf	FSR
		call	write		;aquí se escriben en el LCD
		call	delay3
		call	delay3
		BANCO1
		movlw	ACT2		;prepara dirección para transferir a EEPROM
		movwf	FSR			
		movlw	0
		BANCO2
		movwf	EEADR		;prepara dirección inicial en EEPROM
		call	E2WRT		;aquí tranfiere a EEPROM
		BANCO0
;***
call	aactiva		;RECIBE HORA DE ACTIVACIÓN Y GUARDA EN LOCALIDADES		
		movlw	AACT2
		movwf	FSR
		call	write		;aquí se escriben en el LCD
		call	delay3
		call	delay3
		BANCO1
		movlw	AACT2		;prepara dirección para transferir a EEPROM
		movwf	FSR			
		movlw	H'10'
		BANCO2
		movwf	EEADR		;prepara dirección inicial en EEPROM
		call	E2WRT		;aquí tranfiere a EEPROM
		BANCO0
;***
		BANCO0
		call	desac		;aquí se teclea la hora de desactivación
		movlw	DESAC2
		movwf	FSR
		call	write		;aquí se escribe en el LCD
		call	delay3
		call	delay3
		BANCO1
		movlw	DESAC2	;DIRECCION INICIAL MEMORIA DATOS
		movwf	FSR
		movlw	7		;DIRECCION INICIAL EN EEPROM
		BANCO2
		movwf	EEADR						
		call	E2WRT	;guarda 6 datos en EEPROM
		BANCO0
;***
BANCO0
		call	ddesac		;aquí se teclea la hora de desactivación
		movlw	DDESAC2
		movwf	FSR
		call	write		;aquí se escribe en el LCD
		call	delay3
		call	delay3
		BANCO1
		movlw	DDESAC2	;DIRECCION INICIAL MEMORIA DATOS
		movwf	FSR
		movlw	H'17'		;DIRECCION INICIAL EN EEPROM
		BANCO2
		movwf	EEADR						
		call	E2WRT	;guarda 6 datos en EEPROM
		BANCO0
;***
		BANCO0
		call	timo		;ESCRIBE EL LETRERO "TIME"
		movlw	CONT2
		movwf	FSR			;prepara direccionamiento indirecto
		call	write		;escribe hora, el contenido de contadores en LCD	
		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		;verifica si llegó a hora 23:59:59
		BCF		TIE			;***DESACTIVA INTERRUPCIONES
		call	compac		;compara si es hora de activar1
		call	ccompac		;compara si es hora de activar2
		call	compaq		;compara si es hora de desactiva1
		call	ccompaq		;compara si es hora de desactiva2
		BSF		TIE			;***ACTIVA INTERRUPCIONES
		goto	sigue

;modifique estos parámetros si desea cambiar la hora de inicio y vuelva a
;aplicar el comando "quickbuild" para ensamblar el programa.

;ESTA RUTINA REQUIERE QUE EN FSR SE ENCUENTRE CARGADO LA
;DIRECCION DE INICIO DE LOS DATOS DE LA HORA A DESPLEGAR
write	movlw	h'c7'		;escribe la hora, contenido de contadores en el LCD
		call	puco
		movlw	h'30'
		addwf	INDF,w		;convierte a ASCII
		call 	puda
		movlw	h'c6'
		call	puco
		incf	FSR
		movlw	h'30'
		addwf 	INDF,w
		call	puda
		movlw	h'c5'
		call	puco
		movlw	':'
		call	puda
		movlw	h'c4'
		call	puco
		incf	FSR
		movlw	h'30'
		addwf	INDF,w
		call 	puda
		movlw	h'c3'
		call	puco
		incf	FSR
		movlw	h'30'
		addwf	INDF,w
		call 	puda
		movlw	h'c2'
		call	puco
		movlw	':'
		call	puda
		movlw	h'c1'
		call	puco
		incf	FSR
		movlw	h'30'
		addwf	INDF,w
		call	puda
		movlw	h'c0'
		call	puco
		incf	FSR
		movlw	h'30'
		addwf	INDF,w
		call	puda
		return
timo:	movlw	h'80'	;escribe letrero "TIME"
		call 	puco
		movlw	'H'
		call	puda
		movlw	'O'
		call	puda
		movlw	'R'
		call	puda
		movlw	'A'
		call	puda
		return
		
;aquí inician subrutinas para el manejo del LCD

puco	movwf	PORTB		;escribe comando en puertoB
		call 	delay		;50 milisegundos
		bsf		PORTA,2
		bcf		PORTA,1
		call 	delay
		bcf		PORTA,2
		bcf		PORTA,1
		call 	delay
		bsf		PORTA,2
		bcf		PORTA,1
		call 	delay
		return
puda	movwf	PORTB		;escribe dato en puertoB
		call 	delay		;50 milisegundos
		bsf		PORTA,2
		bsf		PORTA,1
		call 	delay
		bcf		PORTA,2
		bsf		PORTA,1
		call 	delay
		bsf		PORTA,2
		bsf		PORTA,1
		call 	delay
		return

;aquí inician las subrutinas de retraso

delay		movlw	D'35'		;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
		return

;------------------------------------------------------------------------
;AQUI USUARIO INTRODUCE LA HORA INICIAL DESDE EL TECLADO
;GUARDA LOS DATOS EN CONTADORES
desac:	LCD
		movlw	'D'
		call	puda
		movlw	'E'
		call	puda
		movlw	'S'
		call	puda
		movlw	'1'
		call	puda
		movlw	':'
		call	puda
		movlw	h'C0'
		call 	puco
		movlw	6		;inicializa número de dígitos en la hora
		movwf	DIG		;guarda en localidad
		movlw	DESAC7	;INICIALIZA DIRECCION PRIMER DIGITO
		movwf	FSR		;INICIALIZA FSR PARA direccionamiento indirecto
		call	malla8	;lee 6 dígitos de teclado
		movwf	WEB			;almacenamiento temporal de w
		sublw	H'46'
		btfss	STATUS,Z
		goto	sigue4
		movf	WEB,w		;reestablece el valor en w
		BANCO1
		movlw	DESAC2		;INICIALIZA DIRECCION MEMORIA DATOS
		movwf	FSR
		movlw	7
		BANCO2
		movwf	EEADR
		call	E2RD		;lee 6 datos de EEPROM a memoria
		BANCO0		
		return
sigue4: movf	WEB,w		;reestablece calor de w
		return
;***
ddesac:	LCD
		movlw	'D'
		call	puda
		movlw	'E'
		call	puda
		movlw	'S'
		call	puda
		movlw	'2'
		call	puda
		movlw	':'
		call	puda
		movlw	h'C0'
		call 	puco
		movlw	6		;inicializa número de dígitos en la hora
		movwf	DIG		;guarda en localidad
		movlw	DDESAC7	;INICIALIZA DIRECCION PRIMER DIGITO
		movwf	FSR		;INICIALIZA FSR PARA direccionamiento indirecto
		call	malla8	;lee 6 dígitos de teclado
		movwf	WEB			;almacenamiento temporal de w
		sublw	H'46'
		btfss	STATUS,Z
		goto	ssigue4
		movf	WEB,w		;reestablece el valor en w
		BANCO1
		movlw	DDESAC2		;INICIALIZA DIRECCION MEMORIA DATOS
		movwf	FSR
		movlw	H'17'
		BANCO2
		movwf	EEADR
		call	E2RD		;lee 6 datos de EEPROM a memoria
		BANCO0		
		return
ssigue4: movf	WEB,w		;reestablece calor de w
		return
;***
activa:	LCD
		movlw	'A'
		call	puda
		movlw	'C'
		call	puda
		movlw	'T'
		call	puda
		movlw	'1'
		call	puda
		movlw	':'
		call	puda
		movlw	h'C0'
		call 	puco
		movlw	6		;inicializa número de dígitos en la hora
		movwf	DIG		;guarda en localidad
		movlw	ACT7	;INICIALIZA DIRECCION PRIMER DIGITO
		movwf	FSR		;INICIALIZA FSR PARA direccionamiento indirecto
		call	malla8	;lee 6 dígitos
		movwf	WEB			;almacenamiento temporal de w
		sublw	H'46'
		btfss	STATUS,Z
		goto	sigue3
		movf	WEB,w		;reestablece el valor en w
		BANCO1
		movlw	ACT2		;INICIALIZA DIRECCION MEMORIA DATOS
		movwf	FSR
		movlw	0
		BANCO2
		movwf	EEADR
		call	E2RD		;lee 6 datos de EEPROM a memoria
		BANCO0		
		return
sigue3: movf	WEB,w		;reestablece calor de w
		return
;***
aactiva:	LCD
		movlw	'A'
		call	puda
		movlw	'C'
		call	puda
		movlw	'T'
		call	puda
		movlw	'2'
		call	puda
		movlw	':'
		call	puda
		movlw	h'C0'
		call 	puco
		movlw	6		;inicializa número de dígitos en la hora
		movwf	DIG		;guarda en localidad
		movlw	AACT7	;INICIALIZA DIRECCION PRIMER DIGITO
		movwf	FSR		;INICIALIZA FSR PARA direccionamiento indirecto
		call	malla8	;lee 6 dígitos
		movwf	WEB			;almacenamiento temporal de w
		sublw	H'46'
		btfss	STATUS,Z
		goto	ssigue3
		movf	WEB,w		;reestablece el valor en w
		BANCO1
		movlw	AACT2		;INICIALIZA DIRECCION MEMORIA DATOS
		movwf	FSR
		movlw	H'10'
		BANCO2
		movwf	EEADR
		call	E2RD		;lee 6 datos de EEPROM a memoria
		BANCO0		
		return
ssigue3: movf	WEB,w		;reestablece calor de w
		return
;***
setime:	LCD
		movlw	'S'
		call	puda
		movlw	'E'
		call	puda
		movlw	'T'
		call	puda
		movlw	':'
		call	puda
		movlw	h'C0'
		call 	puco
		movlw	6		;inicializa número de dígitos en la hora
		movwf	DIG		;guarda en localidad
		movlw	CONT7	;INICIALIZA PRIMER DIGITO
		movwf	FSR		;INICIALIZA FSR PARA direccionamiento indirecto
		call	malla8
		movwf	WEB			;almacenamiento temporal de w
		sublw	H'46'
		btfss	STATUS,Z
		goto	sigue2
		movf	WEB,w		;reestablece el valor en w
		call	ceros		;contadores de hora actual=0
		return
sigue2: movf	WEB,w		;reestablece calor de w
		return

;esta subrutina lee 6 dígitos del teclado y los va mostrando en
;el LCD.
malla8:	movlw	3		;PAGINA 3 PARA TABLA
		movwf	PCLATH	;elije página 3 para tabla			
		BSF	STATUS,RP0	;ELIJE EL BANCO DE REGISTROS ESPECIALES 1
		MOVLW	H'F0'		;RB0..RB3=SALIDAS, RB4...RB7=ENTRADAS
		MOVWF	TRISB
		BCF	OPTION_REG,7	;RB4...RB7 CON RESISTENCIAS DE PULL UP
		BCF	STATUS,RP0	;ELIGE EL BANCO 0
vuelta1:	movlw	H'EF'		;listo para iniciar rotación
		movwf	I
		movwf	PORTB
		movlw	D'4'
		movwf	J		;contador de 4 corrimientos
vuelta2:	rrf	I,f		;rotación de bits RB0..RB3 en puerto B
		movfw	I
		movwf	PORTB
		call	delay		;50 ms
		movfw	PORTB		;lee el puerto B
		iorlw	H'0F'		;conserva solo los bits RB4...RB7
		movwf	K
		comf	K,f
		btfss	STATUS,2	;si la lectura es 0, continúa
		goto	teclazo		;si la lectura diferente de 0, teclazo
		decfsz	J,f
		goto	vuelta2
		goto 	vuelta1
teclazo:	movfw	PORTB		;verifica que tecla haya sido liberada
		iorlw	H'0F'
		movwf	N
		comf	N,f
		btfss	STATUS,2
		goto	teclazo		;continúa en loop si tecla aún oprimida
		BANCO1					
		movlw	H'00'
		movwf	TRISB		;programa bits de puerto B como salidas
		BANCO0
		comf	I,f
		movfw	I		;toma valor salida puerto B
		andlw	H'0F'		;solo los bits RB0...RB3
		movwf	I		;regresa el valor a I
		movf	K,w		;lee localidad con contenido de rotación
		andlw	H'F0'		;solo bits D4...D7
		iorwf	I,f		;suma I y K resultado en I
		movf	I,w		;suma I y K, resultado en W
		movwf	PORTB		;escribe puerto B, CODIGO RENGLON COLUMNA
ide:		movlw	D'17'		;pasa a la parte de identificación
		movwf	K		;K = contador de caracteres en la tabla 
loop:		decf	K,f		;decrementa K
		movf	K,w		;transfiere a W
		call	tabla
		subwf	I,w		;regresa de la tabla con caracter
		btfss	STATUS,2	;si I=caracter, se va a etiqueta "found"
		goto 	loop
found:	movf	K,w
		movwf	PORTB		;muestra en leds contenido de offset.
		movlw	D'16'			
		addwf	K,w		;añade 16 localidades a offset
		call	tabla		;trae valor ASCII en tabla, en w
;aquí debe compararse w con 46H que es el código ASCII de la "F"
;si es "F", la subrutina interrumpe la lectura del teclado
;y regresa. 
		movwf	WEB			;almacenamiento temporal de w
		sublw	H'46'
		btfss	STATUS,Z
		goto	seguir
		movf	WEB,w		;reestablece el valor en w
		return
seguir:	movf	WEB,w		;reestablece el valor en w
		movwf	PORTB		;despliega en puerto B
		movwf	I		;guarda caracter ASCII en I
lcd:	movlw	H'00'		;inicia rutina escribir caracter en LCD
		BANCO1			;BANCO 1
		movlw	H'00'
        movwf	TRISB		;bits de puerto B, salidas
		BANCO0			;BANCO 0	  
		movf	I,w		;prepara caracter en W
		addlw	H'D0'	;RESTA 30H EN COMPLEMENTO A DOS
		movwf	INDF		;guarda dígito en binario en contadores
		addlw	H'30'		;suma 30H para conservar código ASCII
		call 	puda		;escribe caracter en LCD
		decf	FSR			;DIRECCIONAMIENTO INDIRECTO DE CONTADOR
		decfsz	DIG,f			;cuenta los dígitos ¿ DIG=6 ?
		goto 	malla8		;va de nuevo a leer teclado
		call	delay3
		return			;fin de rutina, continúa con programa
                           
org 300H					;posiciona tabla en página 3
tabla		addwf	PCL,f	
		retlw	H'11'		;'0'AQUI EMPIEZAN CODIGOS RENGLON COLUMNA
		retlw	H'12'		;'1'
		retlw	H'14'		;'2'
		retlw	H'18'		;'3'
		retlw	H'21'		;'4'
		retlw	H'22'		;'5'
		retlw	H'24'		;'6'
		retlw	H'28'		;'7'
		retlw	H'41'		;'8'
		retlw	H'42'		;'9'
		retlw	H'44'		;'A'
		retlw	H'48'		;'B'
		retlw	H'81'		;'C'
		retlw	H'82'		;'D'
		retlw	H'84'		;'E'
		retlw	H'88'		;'F'
		retlw	H'30'		;'0'AQUI EMPIEZAN CODIGOS 
		retlw	H'31'		;'1'
		retlw	H'32'		;'2'
		retlw	H'33'		;'3'
		retlw	H'34'		;'4'
		retlw	H'35'		;'5'
		retlw	H'36'		;'6'
		retlw	H'37'		;'7'
		retlw	H'38'		;'8'
		retlw	H'39'		;'9'
		retlw	H'41'		;'A'
		retlw	H'42'		;'B'
		retlw	H'43'		;'C'
		retlw	H'44'		;'D'
		retlw	H'45'		;'E'
		retlw	H'46'		;'F'

;esta subrutina transfiere hacia EEPROM 6 datos.
;en FSR está la dirección inicial de memoria de datos
;en EEADR está la dirección inicial de EEPROM

E2WRT: 	movlw	6
		movwf	DIG			;son 6 datos
E2WRT2:	movf	INDF,w		;direccionamiento indirecto
		BANCO2
		movwf	EEDATA		;dato listo en registro
		call	EEWR		;escribe en EEPROM
		incf	FSR
		BANCO2
		incf	EEADR
		decfsz	DIG			;decrementa contador de datos
		goto	E2WRT2
		return

;esta subrutina transfiere 6 bytes de la EEPROM hacia la
;memoria de datos. en FSR está la dirección de
;inicio de memoria de datos y en EEADR la dirección
;de inicio de la EEPROM
E2RD:	movlw	6
		movwf	DIG
E2RD2:	call	EERD	;lee dato de EEPROM
		movwf	INDF	;TRANSFIERE A MEMORIA DE DATOS
		incf	FSR
		incf	EEADR
		decfsz	DIG		;decrementa contador de datos
		goto	E2RD2
		return

;subrutina para escribir dato en EEPROM
;para usar esta subrutina, debe escribirse antes la dirección DE LA EEPROM
;en el registro EEADR (BANCO0) y el dato en el registro EEDATA (BANCO0)
;la rutina regresa una vez que el dato fue escrito en la localidad deseada.

EEWR:	BANCO3					;HABILITA EL BANCO 3
		BCF		EECON1,EEPGD	;APUNTA HACIA EEPROM DE DATOS		
		BSF		EECON1,WREN		;HABILITA ESCRITURA EN EEPROM
		bcf     INTCON, GIE     ;DESHABILITA INTERRUPCIONES    
		MOVLW	H'55'			;PREPARA SECUENCIA DE SEGURIDAD
		MOVWF	EECON2			;ESCRIBE PRIMER DATO DE SECUENCIA
		MOVLW	H'AA'			;SEGUNDO DATO
		MOVWF	EECON2			;ESCRIBE SEGUNDO DATO DE SECUENCIA
		BSF		EECON1,WR		;INICIA CICLO DE ESCRITURA
EW:		btfsc   EECON1,WR       ;MALLA PARA ESPERAR AL FINAL DEL CICLO
        goto    EW              ;SI WR=1, CICLO DE ESCRITURA AUN NO TERMINA
		bcf     EECON1, WREN    ;DESHABILITA ESCRITURA
		bsf     INTCON, GIE     ;HABILITA INTERRUPCIONES     		
		RETURN

;subrutina para leer dato de EEPROM
;para usar esta subrutina, debe escribirse antes la dirección deseada
;en el registro EEADR (BANCO0). La rutina regresa con el dato en w.
EERD: 	BANCO3
		BCF		EECON1,EEPGD			
		BSF		EECON1,RD		;HABILITA EL BIT 0 (RD) DEL REGISTRO EECON1		
		BANCO2
		MOVF	EEDATA,W		;TRANSFIERE EL DATO EN EEDATA A W,
		RETURN      
			
		end
	



		

