;
;					EJEMPLO 2.24
;
;				Autor: Mikel Etxebarria
;			(c) Microsystems Engineering (Bilbao)
;
;Ejemplo para simulación y/o MicroPIC Trainer
;
;La memoria EEPROM de datos y el LCD.La máquina "SU TURNO", versión mejorada.
;
;Se trata de emular el funcionamiento de las máquinas tipo "SU TURNO" habituales en múltiples
;comercios. Sobre el LCD se visualizará el número del turno actual (2 dígitos). Este se 
;incrementa a cada pulso aplicado por RA4. En la memoria EEPROM del PIC16F84 se almacena el 
;último número visualizado, de forma que, ante un fallo de alimentación (p.e.), se reanude 
;la cuenta en el último número.
;
;Si se parte de que el sistema se emplea por vez primera , se visualiza el 00
;
;Debe recordarse que las líneas RA0-RA2 actúan 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) para rutinas de manejo del LCD
Contador_L	equ	0x0e		;Variable para el contador parte baja
Contador_H	equ	0x0f		;Variable para el contador parte alta
Temporal_1	equ	0x10		;Variable temporal
Temporal_2	equ	0x11		;Variable temporal

		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

;****************************************************************************************
;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

;**********************************************************************************
;Según el valor contenido en el registro W, se devuelve el carácter ASCII a visuali-
;zar en el LCD

Tabla_Mensajes:	movwf	PCL			;Desplazamiento sobre la tabla

;**********************************************************************************
;La directiva dt genera tantas instrucciones retlw como bytes o caracteres contenga
;cerrados entre "

Mens_0		equ	$			;Mens_0 apunta al primer carácter
		dt	"Su TURNO es: ",0x00

;*********************************************************************************
;Delay_20_ms: Esta rutina de temporización tiene por objeto eliminar 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 rebasamiento
		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

;*************************************************************************************
;Mensaje: Esta rutina visualiza en el LCD el mensaje cuyo inicio está  indicado en
;el acumulador. El fin de un mensaje se determina mediante el código 0x00

Mensaje         movwf   Temporal_1      ;Salva posición de la tabla
Mensaje_1       movf    Temporal_1,W    ;Recupera posición de la tabla
                call    Tabla_Mensajes  ;Busca caracter de salida
                movwf   Temporal_2      ;Guarda el caracter
                movf    Temporal_2,F
                btfss   STATUS,Z        ;Mira si es el último
                goto    No_es_ultimo
                return
No_es_ultimo    call    LCD_DATO        ;Visualiza en el LCD
                incf    Temporal_1,F    ;Siguiente caracter
                goto    Mensaje_1

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, resto entradas		
		movlw	b'00000110'
		movwf	OPTION_REG	;Preescaler de 128 para el TMR0
		bcf	STATUS,RP0	;Selecciona banco 0			                                                                         					

		call	LCD_INI		;Secuencia de inicio del LCD
		movlw	b'00001100'
		call	LCD_REG		;Envía instrucción LCD ON, Cursor OFF y Blink OFF

		movlw	Mens_0
		call	Mensaje		;Visualiza Mens_0 (Su TURNO es: )

		clrf	EEADR		;Selecciona dirección 00 de EEPROM				
		call	EE_Read		;Lee byte de la EEPROM
		movlw	0x09
		subwf	EEDATA,W
		btfsc	STATUS,C	;Contador_H mayor de 9 ??		
		goto	Ini_0		;Si, poner a 0 el contador
		goto	Ini_1		;No
Ini_0		clrf	Contador_L
		clrf	Contador_H	;Poner a 0 el contador
		goto	Loop

Ini_1		movf	EEDATA,W
		movwf	Contador_H	;Actualiza Contador_H
		incf	EEADR,F		;Siguiente posición dela EEPROM
		call	EE_Read		;Lee el byte de la EEPROM
		movlw	0x09
		subwf	EEDATA,W
		btfsc	STATUS,C	;Contador_L mayor de 9 ??
		goto	Ini_0		;Si, poner a 0 el contador
		movf	EEDATA,W
		movwf	Contador_L	;Actualiza Contador_L

Loop		movlw	0x8d
		call	LCD_REG		;Posiciona el cursor del LCD
		movf	Contador_H,W
		iorlw	0x30		;Convierte a ASCII Contador_H
		call	LCD_DATO	;Visualiza Contador_H
		movf	Contador_L,W
		iorlw	0x30		;Convierte a ASCII Contador_L
		call	LCD_DATO	;Visualiza contador_L		
		
Wait_0		clrwdt			;Refresca el WDT
		btfss	PORTA,4		;RA4 está a "1" ??
		goto	Wait_0		;No, esperar
		call	Delay_20_ms	;Eliminar rebotes

Wait_1		clrwdt			;Refrescar el WDT
		btfsc	PORTA,4		;RA4 está a "0" ??
		goto	Wait_1		;No, esperar
		call	Delay_20_ms	;Eliminar rebotes. Ha habido un pulso

		incf	Contador_L,F	;Incrementa contador_L
		movlw	.10
		subwf	Contador_L,W
		btfss	STATUS,Z	;Contador mayor de 9 ??
		goto	Write		;No, actualizar EEPROM
		clrf	Contador_L	;Si, Contador_L pasa a 0
		incf	Contador_H,F	;Incrementa Contador_H
		movlw	.10
		subwf	Contador_H,W
		btfss	STATUS,Z	;Contador_H mayor de 9
		goto	Write		;No, actualizar EEPROM
		clrf	Contador_H	;Si, Contador_H pasa a 0

Write		clrf	EEADR		;Selecciona dirección 00 de la EEPROM
		movf	Contador_H,W
		movwf	EEDATA
		call	EE_Write	;Graba Contador_H en la EEPROM
		incf	EEADR,F		;Dirección 01 de la EEPROM
		movf	Contador_L,W
		movwf	EEDATA
		call	EE_Write	;Graba Contador_L en la EEPROM
		goto	Loop


	
		end			;Fin del programa fuente

