;*************************************************************************************************************************************************
;
;  	PROGRAMA DE PRUEBA DE LECTURA DE UN ID-TAG PARA EVOLUPIC Bootloader 16F88
;	LOS 12 CARACTERES DEL TAG SE MUESTRAN EN UN DISPLAY LCD 16 X 1
;       SE UTILIZA EL DETECTOR-SCANNER ID-12 Y TARJETAS PLASTICAS EM4002
;	Por Moisés Rafael Gutiérrez Damián para Punto Flotante, S.A.	
;
;*************************************************************************************************************************************************

;	CABECERA	**********************************************************************************************************************************

		LIST	P=16F88			; MICROCONTROLADOR A USAR
		INCLUDE	<P16F88.INC>	; LLAMADA A CABECERA

;	CONSTANTES Y DECLARACIONES	******************************************************************************************************************

#DEFINE 	LCD_PinRS		PORTA,1
#DEFINE  	LCD_PinEnable	PORTA,2
#DEFINE  	LCD_BusDatos	PORTB	
#DEFINE		SPEN0			BCF		RCSTA,SPEN	
#DEFINE		SPEN1			BSF		RCSTA,SPEN
#DEFINE		LCD_CaracteresPorLinea	.8


		CBLOCK	0x20			
		LCD_GuardaDato			; TEMPORAL DE DATO A ENVIAR
		R_ContA					; Contadores para los retardos.
		R_ContB
		CONTADOR				; CARACTERES QUE SE RECIBIRÁN
		TEMP					; REGISTRO TEMPORAL DE RECEPCIÓN
		LCD_ApuntaCaracter		; Indica la posición del carácter a visualizar
								; respecto del comienzo de todos los mensajes,
								; (posición de la etiqueta "Mensajes").
		LCD_ValorCaracter		; Código ASCII del carácter
		UNO						; VARIABLES CREADAS PARA GUARDAR LA CADENA DE CARACTERES
		DOS
		TRES
		CUATRO
		CINCO
		SEIS
		SIETE
		OCHO
		NUEVE
		DIEZ
		ONCE
		DOCE
		TRECE
		ENDC

		ORG		0				; INICIO DEL PROGRAMA EN LA PRIMERA LOCACIÓN DE MEMORIA
		CLRF	PCLATH			; SOLICITADO POR EL BOOTLOADER.
		GOTO	INICIO			; DIRECCIONAMOS AL "INICIO" DEL BLOQUE DE INSTRUCCIONES
		ORG		3		


;	RUTINAS	*************************************************************************************************************************************

EscribeLCD
		andlw	b'11110000'				; Se queda con el nibble alto del dato que es el
PULSE
		movwf	LCD_BusDatos			; Envía el dato al módulo LCD.
		bsf		LCD_PinEnable			; Permite funcionamiento del LCD mediante un pequeño
		bcf		LCD_PinEnable			; pulso y termina impidiendo el funcionamiento del LCD.
		return

LCD_Comando
		bcf		LCD_PinRS				; Activa el Modo Comando, poniendo RS=0.
		goto	LCD_Envia
LCD_Caracter
		bsf		LCD_PinRS				; Activa el "Modo Dato", poniendo RS=1.
LCD_Envia
		movwf	LCD_GuardaDato			; Guarda el dato a enviar.
		call	EscribeLCD				; Primero envía el nibble alto.
		swapf	LCD_GuardaDato,W		; Ahora envía el nibble bajo. Para ello pasa el
										; nibble bajo del dato a enviar a parte alta del byte.
		call	EscribeLCD				; Se envía al visualizador LCD.
		MOVLW	.1						; 2 ms en modo comando y 50 µs en modo cáracter.										
		call	Retardos_ms
		return	

Retardos_ms
		movwf	R_ContB				; Aporta 1 ciclo máquina.
R1ms_BucleExterno
		movlw	d'249'				; Aporta Mx1 ciclos máquina. Este es el valor de "K".
		movwf	R_ContA				; Aporta Mx1 ciclos máquina.
R1ms_BucleInterno
		nop							; Aporta KxMx1 ciclos máquina.
		decfsz	R_ContA,F			; (K-1)xMx1 cm (cuando no salta) + Mx2 cm (al saltar).
		goto	R1ms_BucleInterno	; Aporta (K-1)xMx2 ciclos máquina.
		decfsz	R_ContB,F			; (M-1)x1 cm (cuando no salta) + 2 cm (al saltar).
		goto	R1ms_BucleExterno 	; Aporta (M-1)x2 ciclos máquina.
		return						; El salto del retorno aporta 2 ciclos máquina.
		
LCD_Mensaje
	movwf	LCD_ApuntaCaracter		; Posición del primer carácter del mensaje.
	movlw	Mensajes				; Halla la posición relativa del primer carácter
	subwf	LCD_ApuntaCaracter,F	; del mensaje respecto de etiqueta "Mensajes".
	decf	LCD_ApuntaCaracter,F	; Compensa la posición que ocupa "addwf PCL,F".
LCD_VisualizaOtroCaracter
	movf	LCD_ApuntaCaracter,W
	call	Mensajes				; Obtiene el código ASCII del carácter apuntado.
	movwf	LCD_ValorCaracter		; Guarda el valor de carácter.
	movf	LCD_ValorCaracter,F		; Lo único que hace es posicionar flag Z. En caso
	btfsc	STATUS,Z				; que sea "0x00", que es código indicador final	
	goto	LCD_FinMensaje			; de mensaje, sale fuera.
LCD_NoUltimoCaracter
	call	LCD_Caracter			; Visualiza el carácter ASCII leído.
	incf	LCD_ApuntaCaracter,F	; Apunta a la posición del siguiente carácter 
	goto	LCD_VisualizaOtroCaracter	; dentro del mensaje.
LCD_FinMensaje
	return							; Vuelve al programa principal.

;	MENSAJES	********************************************************************************************************************************

Mensajes						
		ADDWF	PCL,F
Mensaje0						; MENSAJE INICIAL
		DT "PRESENTE", 0x00		; Mensaje terminado en 0x00.
Mensaje1						; CONTINUA MENSAJE
		DT " TARJETA", 0x00		; Mensaje terminado en 0x00.
FinMensajes

;	PRINCIPAL	*********************************************************************************************************************************

INICIO
		
		BANKSEL	TRISA			; CONFIGURAMOS LOS PUERTOS
		MOVLW	0x20 			; PUERTO A COMO SALIDAS	
		MOVWF	TRISA
		MOVLW	0x0F			; PUERTO B: RB0-RB3 => ENTRADAS, RB4-RB7 => SALIDAS					
		MOVWF	TRISB			; 
						
		CLRF	ANSEL			; DESHABILITAMOS EL CAD.
		MOVLW	.7
		MOVWF	CMCON
		CLRF	CVRCON			; DESHABILITAMOS LOS COMPARADORES.

		BANKSEL	PORTA
		CLRF	PORTA
		CLRF	PORTB

		BANKSEL	TXSTA
		MOVLW	.25				; 9600 bps
		MOVWF	SPBRG			; 
		MOVLW	0x04			; COMUNICACIÓN ASINCRONA, TX-RX A ALTA VELOCIDAD, DESHABILITAMOS LA TRANSMISIÓN.
		MOVWF	TXSTA

		BANKSEL	RCSTA
		MOVLW	0x90			; HABILITAMOS LA RECEPCIÓN CONTÍNUA.
		MOVWF	RCSTA
		SPEN0					; DESHABILITAMOS EL PUERTO SERIE PARA PODER ESCRIBIR EN EL LCD.

;	INICIALIZA LCD	***************************************************************************************************************************

		MOVLW	.16
		CALL	Retardos_ms
		MOVLW	0X30
		CALL 	PULSE
		MOVLW	.5
		CALL	Retardos_ms
		MOVLW	0X30
		CALL 	PULSE
		MOVLW	.5
		CALL	Retardos_ms
		MOVLW	0X30
		CALL 	PULSE
		MOVLW	.5
		CALL	Retardos_ms
		MOVLW	0X20
		CALL 	PULSE
		MOVLW	.5
		CALL	Retardos_ms
		MOVLW	0X28			;CODIGO INTERFAZ 4 BITS. 38H PARA 8 BITS
		CALL 	LCD_Envia
		MOVLW	0X0C
		CALL 	LCD_Envia
		MOVLW	0X01
		CALL 	LCD_Envia
		MOVLW	0X06
		CALL 	LCD_Envia

;	********************************************************************************************************************************************

		MOVLW	Mensaje0		; PRIMEROS 8 CARACTERES
		CALL	LCD_Mensaje
		MOVLW	0XC0			; LINEA 2
		CALL	LCD_Comando	
		MOVLW	Mensaje1		; SIGUIENTES 8 CARACTERES
		CALL	LCD_Mensaje
		GOTO 	NUEVO
;****************************************************************************************
;ESTAS 5 LINEAS DESBLOQUEAN EL UART. SE BLOQUEA CUANDO RECIBE 3 BYTES SIN HABER SIDO
;LEIDO EL REGISTRO RCREG

RENUEVA
		BCF		RCSTA,CREN	;HABILITA DE NUEVO UART
		BSF		RCSTA,CREN	;BORRA FLAGS DE ERROR
		MOVFW	RCREG			;VACIA LOS BUFFERS, UART LISTO.
		MOVFW	RCREG
		MOVFW	RCREG
;***************************************************************************************
NUEVO
		MOVLW	.13				; LEEREMOS 13 CARACTERES.
		MOVWF	CONTADOR 		; CARGAMOS NUESTRA VARIABLE DE CUENTA.	
		
		SPEN1
		
		MOVLW	.1
		CALL Retardos_ms
		
ESPERA	
		BTFSS 	PIR1,RCIF		; RECIBIMOS UN CARACTER?.
		GOTO	ESPERA			; NO. SIGUE ESPERANDO.
	    MOVFW 	RCREG	        ; SÍ. COMIENZA RUTINA.
RECIBE
	    MOVWF	TEMP
		MOVFW   CONTADOR    
TABLA		
		ADDWF	PCL,F
		GOTO 	TRECEAVO
		GOTO   	DOCEAVO
		GOTO	ONCEAVO
		GOTO	DECIMO
		GOTO	NOVENO
		GOTO	OCTAVO
		GOTO	SEPTIMO
		GOTO	SEXTO
		GOTO	QUINTO
		GOTO	CUARTO
		GOTO	TERCERO
		GOTO	SEGUNDO
		;GOTO	PRIMERO

PRIMERO
		MOVFW	TEMP
		MOVWF	UNO				; GUARDA EL PRIMER CARACTER.
		GOTO	FIN_CADENA
SEGUNDO
		MOVFW	TEMP
		MOVWF	DOS				; GUARDA EL SEGUNDO CARACTER.
		GOTO	FIN_CADENA
TERCERO
		MOVFW	TEMP
		MOVWF	TRES			; GUARDA EL TERCER CARACTER.
		GOTO	FIN_CADENA
CUARTO
		MOVFW	TEMP
		MOVWF	CUATRO			; GUARDA EL CUARTO CARACTER.
		GOTO	FIN_CADENA
QUINTO
		MOVFW	TEMP
		MOVWF	CINCO			; GUARDO EL QUINTO CARACTER.
		GOTO	FIN_CADENA
SEXTO
		MOVFW	TEMP
		MOVWF	SEIS			; GUARDA EL SEXTO CARACTER.
		GOTO	FIN_CADENA
SEPTIMO
		MOVFW	TEMP
		MOVWF	SIETE			; GUARDA EL SEXTO CARACTER.
		GOTO	FIN_CADENA
OCTAVO
		MOVFW	TEMP
		MOVWF	OCHO			; GUARDA EL OCTAVO CARACTER.
		GOTO	FIN_CADENA
NOVENO
		MOVFW	TEMP
		MOVWF	NUEVE			; GUARDA EL NOVENO CARACTER.
		GOTO	FIN_CADENA
DECIMO
		MOVFW	TEMP
		MOVWF	DIEZ			; GUARDA EL DECIMO CARACTER.
		GOTO	FIN_CADENA
ONCEAVO
		MOVFW	TEMP
		MOVWF	ONCE			; GUARDA EL ONCEAVO CARACTER.
		GOTO	FIN_CADENA
DOCEAVO
		MOVFW	TEMP
		MOVWF	DOCE			; GUARDA EL DOCEAVO CARACTER.
		GOTO	FIN_CADENA
TRECEAVO
		MOVFW	TEMP
		MOVWF	TRECE

FIN_CADENA
		DECFSZ	CONTADOR
		GOTO	ESPERA	


IMPRIME	    
	    SPEN0
	    
	    MOVLW	.1				; ESPERAMOS A QUE SE ESTABILICE EL PUERTO
	    CALL 	Retardos_ms		
			
		MOVLW	0X01			; BORRAMOS LCD
	    CALL	LCD_Comando
	    
	    MOVLW	.1				; ESPERA PARA EL LCD
	    CALL 	Retardos_ms
	    
	    MOVLW	' '
	    CALL	LCD_Caracter
	    MOVLW	' ' 
	    CALL	LCD_Caracter
	    
	    MOVFW	UNO				; IMPRIMIMOS LOS CARACTERES
	    CALL	LCD_Caracter
	    
		MOVFW	DOS				
		CALL	LCD_Caracter

		MOVFW	TRES
		CALL	LCD_Caracter

		MOVFW	CUATRO
		CALL	LCD_Caracter

		MOVFW	CINCO
		CALL	LCD_Caracter
		
		MOVFW	SEIS
		CALL	LCD_Caracter


		MOVLW	0XC0
		CALL	LCD_Comando
		MOVLW	.1
		CALL	Retardos_ms


		MOVFW	SIETE
		CALL	LCD_Caracter

		MOVFW	OCHO
		CALL	LCD_Caracter

		MOVFW	NUEVE
		CALL	LCD_Caracter

		MOVFW	DIEZ
		CALL	LCD_Caracter

		MOVFW	ONCE
		CALL	LCD_Caracter

		MOVFW	DOCE
		CALL	LCD_Caracter

	  	GOTO	RENUEVA		; CICLO INFINITO	




;*************************************************************************************************************************************************	
	END