;
;					EJEMPLO 2.23
;
;				Autor: Mikel Etxebarria
;			(c) Microsystems Engineering (Bilbao)
;
;Ejemplo para simulación y/o MicroPIC Trainer
;
;El manejo de la pantalla LCD. Un simple generador de mensajes.
;
;Este ejemplo pretende realizar un generador de mensajes para el LCD. Con RA4 a "1", el
;sistema está en el modo de programación. En este modo el mensaje se graba en la EEPROM
;de datos. Con RA4 a "0" entramos en el modo de reproducción. El mensaje grabado en la
;EEPROM se visualiza sobre el LCD.
; 
;Cuando el interruptor RA3 está a nivel "1", en la posición actual del cursor van apare-
;ciendo secuencialmente los distintos caracateres disponibles. Al ponerlo a "0" se selec-
;ciona el actual y se graba en la EEPROM. Al pasar nuevamente a "1" se selecciona el si-
;guiente carácter.
;
;Debe recordarse que las líneas RA0-RA2 actúan ahora como salida de señales de control hacia 
;el LCD. Al estar conectadas con sendos interruptores en la MicroPIC Trainer, estos deben
;estar a nivel lógico "1" permanentemente.

		List	p=16F84		;Tipo de procesador
		include	"P16F84.INC"	;Definiciones de registros internos
                    		
Lcd_var		equ	0x0c		;Variables (2) de las rutinas de manejo del LCD
Delay_Cont	equ	0x0e		;Variable para la temporización
Temporal_1	equ	0x0f		;Variable temporal
Temporal_2	equ	0x10		;Variable temporal
Cur_Pos		equ	0x11		;Posición del cursor

		org	0x00		;Vector de Reset
		goto	Inicio
		org	0x05		;Salva vector de interrupción

		include	"LCD_Cxx.inc"	;Incluye las rutinas de manejo del LCD

;*********************************************************************************
;Delay_20_ms: Esta rutina de temporización tiene por objeto eleiminar el "efecto
;rebote" de los periféricos electromecánicos. Realiza un delay de 20 mS. Si el PIC
;trabaja a una frecuencia de 4MHz, el TMR0 evoluciona cada uS. Si queremos tempori-
;zar 20000 uS (20 mS) con un preescaler de 128, el TMR0 deberá contar 156 eventos
;(156 * 128). El valor 156 equivale a 9c hex. y como el TMR0 es ascedente habrá que
;cargar su complemento a 1 (63 hex.).

Delay_20_ms:	bcf	INTCON,T0IF	;Desconecta el flag de rebosamiento
		movlw	0x63		;Complemento hex. de 156
		movwf	TMR0		;carga el TMR0
Delay_20_ms_1	clrwdt			;Refrescar el WDT
		btfss	INTCON,T0IF	;Rebasamiento del TMR0 ??
		goto	Delay_20_ms_1	;Todavía no
		bcf	INTCON,T0IF	;Ahora si, reponer el flag
		return

;*********************************************************************************
;Delay_var: Esta rutina de propósito general realiza una temporización variable
;entre 50 mS y 12.8". Se emplea un preescaler de 256 y al TMR0 se le carga con 195. 
;La velocidad de trabajo es de 4Mhz y por tanto el TMR0 se incrementa cada uS. De 
;esta forma, el TMR0 debe contar 195 eventos que, con un preescaler de 256 hace una
;intervalo total de 50000 uS/50 mS (195 * 256). El valor 195 hay que expresarlo
;en Hex. (c3) y como el TMR0 es ascendente habrá que cargar su complemento (3C hex.)
;Dicho intervalo de 50 mS se repite tantes veces como indique la variable "Delay_cont",
;es por ello que el delay mínimo es de 50 mS ("Delay_cont=1) y el máxima de 12.8" 
;(Delay_cont=255).

Delay_var:	bcf	INTCON,T0IF	;Desconecta el flag de rebosamiento
		movlw	0x3c		;Complemento hex. de 195
		movwf	TMR0		;carga el TMR0
Intervalo	clrwdt			;Refrescar el WDT
		btfss	INTCON,T0IF	;Rebasamiento del TMR0 ??
		goto	Intervalo	;Todavía no		
		decfsz	Delay_Cont,F	;Decrementa contador de intervalos
		goto	Delay_var	;Repite el intervalo de 50 mS
		return	

;****************************************************************************************
;EE_Write: Graba un byte en la EEPROM de datos. La dirección será la contenida en EEADR y
;el dato se le supone previamente metido en EEDATA

EE_Write        bsf     STATUS,RP0	;Selecciona banco 1
                bsf     EECON1,WREN	;Permiso de escritura
                movlw   b'01010101'
                movwf   EECON2
                movlw   b'10101010'
                movwf   EECON2		;Secuencia establecida por Microchip
                bsf     EECON1,WR	;Orden de escritura
                bcf     EECON1,WREN	;Desconecta permiso de escritura
Wait            btfss   EECON1,EEIF	;Testear flag de fin de escritura
                goto    Wait
                bcf     EECON1,EEIF	;Reponer flag de fin de escritura
                bcf     STATUS,RP0	;Selección banco 0
                return

;**************************************************************************************
;EE_Read: Leer un byte de la EEPROM. Se supone al registro EEADR cargado con la direc-
;ción a leer. En EEDATA aparecerá el dato leído.

EE_Read         bsf     STATUS,RP0	;Selección de banco 1
                bsf     EECON1,RD	;Orden de lectura
                bcf     STATUS,RP0	;Selección de banco 0
                return

;**********************************************************************************
;
Inicio	        clrf 	PORTB		;Borra los latch de salida
		bsf	STATUS,RP0	;Selecciona banco 1
		clrf	TRISB		;Puerta B se configura como salida
		movlw	b'00011000'		
		movwf	TRISA		;RA0-RA2 salidas, RA3-RA4 entradas				
		movlw	b'00000111'
		movwf	OPTION_REG	;Preescaler de 256 para el TMR0
		bcf	STATUS,RP0	;Selecciona banco 0	
		movlw	0x80
		movwf	Cur_Pos		;Posición inicial del cursor
		call	LCD_INI		;Secuencia de inicio del LCD
		movlw	b'00000001'
		call	LCD_REG		;Borra LCD y Home
		movlw	b'00001110'
		call	LCD_REG		;Envía instrucción: LCD ON, Cursor ON y blink OFF
		clrf	EEADR		;Dirección inicial de la EEPROM

Loop		btfss	PORTA,4		;Modo programación ??
		goto	Reproducir	;No, modo de reproducción

Programar	movlw	0x20
		movwf	Temporal_1	;Primer carácter ASCII		
Programar_1	btfss	PORTA,3		;Grabar el byte en EEPROM ??
		goto	Grabar		;Si
		movf	Cur_Pos,W
		call	LCD_REG		;Coloca el cursor
		movf	Temporal_1,W
		call	LCD_DATO	;Visualiza el carácter
		movlw	.10
		movwf	Delay_Cont
		call	Delay_var	;Temporiza 0.5 segundos
		incf	Temporal_1,F	;Siguiente caracter ASCII
		btfss	Temporal_1,7	;Es el último carácter ASCII ??
		goto	Programar_1	;No
		goto	Programar	;Si, empezar desde el primero

Grabar		call	Delay_20_ms	;Elimina rebotes
		decf	Temporal_1,W
		movwf	EEDATA		;Dato a grabar en la EEPROM
		call	EE_Write	;Graba el carácter
		incf	EEADR,F		;Siguiente dirección EEPROM
		clrf	EEDATA
		call	EE_Write	;Graba 0x00
		incf	Cur_Pos,F	;Siguiente posición del cursor
Grabar_1	clrwdt			;Refrescar el WDT
		btfss	PORTA,3		;Esperar a que RA3 vuelva a "1"
		goto	Grabar_1
		call	Delay_20_ms	;Eliminar rebotes
		goto	Loop		;Siguiente caracter del mensaje

Reproducir	movlw	b'00000001'
		call	LCD_REG		;Borra LCD y Home
		movlw	b'00001100'
		call	LCD_REG		;LCD = ON, cursor = OFF
		clrf	EEADR		;Dirección inicial EEPROM

Reproducir_0	clrwdt			;Refresco del WDT		
		call	EE_Read		;Lee carácter de la EEPROM
		movf	EEDATA,F
		btfsc	STATUS,Z	;Es el último del mensaje ?? (0x00)
		goto	Reproducir_1	;Si
		movf	EEDATA,W
		call	LCD_DATO	;Visualiza el caracter
		incf	EEADR,F		;Siguiente carácter
		goto	Reproducir_0

Reproducir_1	movlw	.40
		movwf	Delay_Cont
		call	Delay_var	;Mantiene el mensaje 2 segundos

;**************************** SECUENCIA DE PARPADEO **********************************
Blink		movlw	.6
		movwf	Temporal_2	;Inicia contador de parpadeos
Blink_1		movlw	b'00001100'
		call	LCD_REG		;LCD en ON
		movlw	.5
		movwf	Delay_Cont
		call	Delay_var	;Temporiza 0.25 segundos
		movlw	b'00001000'
		call	LCD_REG		;LCD en OFF
		movlw	.5
		movwf	Delay_Cont
		call	Delay_var	;Temporiza 0.25 segundos
		decfsz	Temporal_2,F
		goto	Blink_1		;Repite el parpadeo
		movlw	.20
		movwf	Delay_Cont
		call	Delay_var	;Temporiza 1 segundo
		goto	Loop
	
		end			;Fin del programa fuente

