;************************************ Mensaje*******************************************
;
; El mdulo LCD visualiza un mensaje largo (ms de 16 caracteres) que se desplaza a lo largo
; de la pantalla. Se utiliza la subrutina LCD_MensajeMovimiento de la librera LCD_MENS.INC.
; 
; ZONA DE DATOS **********************************************************************

    LIST        P=16F84A
    INCLUDE        
    __CONFIG    _CP_OFF &  _WDT_OFF & _PWRTE_ON & _XT_OSC

    CBLOCK  0x0C
    ENDC

; ZONA DE CDIGOS ********************************************************************

    ORG    0
Inicio
    call    LCD_Inicializa            ; Prepara la pantalla.
Principal
    movlw    Mensaje0                ; Apunta al mensaje.
    call    LCD_MensajeMovimiento
    goto    Principal                ; Repite la visualizacin.

; "Mensajes" ----------------------------------------------------------------------------
;
Mensajes
    addwf    PCL,F
Mensaje0                            ; Posicin inicial del mensaje.
    DT "           "                ; Espacios en blanco al principio para mejor
    DT "HOLA MUY BUENOS DIAS  "
    DT "UNIVERSIDAD NACIONAL ABIERTA Y A DISTANCIA UNAD  "    ; visualizacin.
       DT "TECNOLOGIA EN ELECTRONICA  "
    DT "FRANCISCO JAVIER HILARON NOVOA. "
    DT "                ", 0x0        ; Espacios en blanco al final.

    
    
    



;-----------------------LIBRERAS--------------------------------------------------

;**************************** Librera "LCD_4BIT.INC" ***********************************

; ZONA DE DATOS *********************************************************************

    CBLOCK
    LCD_Dato
    LCD_GuardaDato
    LCD_GuardaTRISB
    LCD_Auxiliar1
    LCD_Auxiliar2
    ENDC

LCD_CaracteresPorLinea    EQU    .16            ; Nmero de caracteres por lnea de la pantalla.

#DEFINE  LCD_PinRS    PORTA,0
#DEFINE  LCD_PinRW    PORTA,1
#DEFINE  LCD_PinEnable    PORTA,2
#DEFINE  LCD_BusDatos    PORTB

; Subrutina "LCD_Inicializa" ------------------------------------------------------------
;
; Inicializacin del mdulo LCD: Configura funciones del LCD, produce reset por software,
; borra memoria y enciende pantalla. El fabricante especifica que para garantizar la
; configuracin inicial hay que hacerla como sigue:
;
LCD_Inicializa
    bsf        STATUS,RP0                ; Configura las lneas conectadas al pines RS,
    bcf        LCD_PinRS                ; R/W y E.
    bcf        LCD_PinEnable
    bcf        LCD_PinRW
    bcf        STATUS,RP0
    bcf        LCD_PinRW                ; En caso de que est conectado le indica
                                    ; que se va a escribir en el LCD.
    bcf        LCD_PinEnable            ; Impide funcionamiento del LCD poniendo E=0.
    bcf     LCD_PinRS                ; Activa el Modo Comando poniendo RS=0.
    call    Retardo_20ms
    movlw    b'00110000'    
    call    LCD_EscribeLCD            ; Escribe el dato en el LCD.
    call    Retardo_5ms    
    movlw    b'00110000'    
    call    LCD_EscribeLCD
    call    Retardo_200micros
    movlw    b'00110000'    
    call    LCD_EscribeLCD
    call    Retardo_20micros        ; Este retardo es necesario para simular en PROTEUS.
    movlw    b'00100000'                ; Interface de 4 bits.
    call    LCD_EscribeLCD
    call    Retardo_20micros        ; Este retardo es necesario para simular en PROTEUS.
    
; Ahora configura el resto de los parmetros: 

    call    LCD_2Lineas4Bits5x7        ; LCD de 2 lneas y caracteres de 5x7 puntos.
    call    LCD_Borra                ; Pantalla encendida y limpia. Cursor al principio
    call    LCD_CursorOFF            ; de la lnea 1. Cursor apagado.
    call    LCD_CursorIncr            ; Cursor en modo incrementar.
    return

; Subrutina "LCD_EscribeLCD" -----------------------------------------------------------
;
; Enva el dato del registro de trabajo W al bus de dato y produce un pequeo pulso en el pin
; Enable del LCD. Para no alterar el contenido de las lneas de la parte baja del Puerto B que
; no son utilizadas para el LCD (pines RB3:RB0), primero se lee estas lneas y despus se
; vuelve a enviar este dato sin cambiarlo.

LCD_EscribeLCD
    andlw    b'11110000'                ; Se queda con el nibble alto del dato que es el
    movwf    LCD_Dato                ; que hay que enviar y lo guarda.
    movf    LCD_BusDatos,W            ; Lee la informacin actual de la parte baja
    andlw    b'00001111'                ; del Puerto B, que no se debe alterar.
    iorwf    LCD_Dato,F                ; Enviar la parte alta del dato de entrada
                                    ; y en la parte baja lo que haba antes.
    bsf        STATUS,RP0                ; Acceso al Banco 1.
    movf    TRISB,W                    ; Guarda la configuracin que tena antes TRISB.
    movwf    LCD_GuardaTRISB
    movlw    b'00001111'                ; Las 4 lneas inferiores del Puerto B se dejan 
    andwf    PORTB,F                    ; como estaban y las 4 superiores como salida.
    bcf        STATUS,RP0                ; Acceso al Banco 0.
;
    movf    LCD_Dato,W                ; Recupera el dato a enviar.
    movwf    LCD_BusDatos            ; Enva el dato al mdulo LCD.
    bsf        LCD_PinEnable            ; Permite funcionamiento del LCD mediante un pequeo
    bcf        LCD_PinEnable            ; pulso y termina impidiendo el funcionamiento del LCD.
    bsf        STATUS,RP0                ; Acceso al Banco 1. Restaura el antiguo valor en
    movf    LCD_GuardaTRISB,W        ; la configuracin del Puerto B.
    movwf    TRISB
    bcf        STATUS,RP0                ; Acceso al Banco 0.
    return

; Subrutinas variadas para el control del mdulo LCD -----------------------------------------
;
;Los comandos que pueden ser ejecutados son:
;
LCD_CursorIncr                        ; Cursor en modo incrementar.
    movlw    b'00000110'
    goto    LCD_EnviaComando

LCD_CursorOFF                        ; Pantalla encendida y cursor apagado.
    movlw    b'00001100'
    goto    LCD_EnviaComando

LCD_Borra                            ; Borra toda la pantalla, memoria DDRAM y pone el 
    movlw    b'00000001'                ; cursor a principio de la lnea 1.
    goto    LCD_EnviaComando
LCD_2Lineas4Bits5x7                    ; Define la pantalla de 2 lneas, con caracteres
    movlw    b'00101000'                ; de 5x7 puntos y conexin al PIC mediante bus de
;    goto    LCD_EnviaComando        ; 4 bits. 

; Subrutinas "LCD_EnviaComando" y "LCD_Caracter" ------------------------------------
;
; "LCD_EnviaComando". Escribe un comando en el registro del mdulo LCD. La palabra de
; comando ha sido entregada a travs del registro W.  Trabaja en Modo Comando.
; "LCD_Caracter". Escribe en la memoria DDRAM del LCD el carcter ASCII introducido a
; a travs del registro W. Trabaja en Modo Dato.
;
LCD_EnviaComando
    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.
    call    LCD_CodigoCGROM            ; Obtiene el cdigo para correcta visualizacin.

LCD_Envia
    movwf    LCD_GuardaDato            ; Guarda el dato a enviar.
    call    LCD_EscribeLCD            ; Primero enva el nibble alto.
    swapf    LCD_GuardaDato,W        ; Ahora enva el nibble bajo. Para ello pasa el
                                    ; nibble bajo del dato a enviar a parte alta del byte.
    call    LCD_EscribeLCD            ; Se enva al visualizador LCD.
    btfss    LCD_PinRS                ; Debe garantizar una correcta escritura manteniendo 
    call    Retardo_2ms                ; 2 ms en modo comando y 50 s en modo cracter.
    call    Retardo_50micros
    return    

; Subrutina "LCD_CodigoCGROM" -----------------------------------------------------------
;
; A partir del carcter ASCII nmero 127 los cdigos de los caracteres definidos en la
; tabla CGROM del LM016L no coinciden con los cdigos ASCII. As por ejemplo, el cdigo
; ASCII de la "" en la tabla CGRAM del LM016L es EEh.
;
; Esta subrutina convierte los cdigos ASCII de la "", "" y otros, a cdigos CGROM para que
; que puedan ser visualizado en el mdulo LM016L.
; 
; Entrada:    En (W) el cdigo ASCII del carcter que se desea visualizar.
; Salida:    En (W) el cdigo definido en la tabla CGROM.

LCD_CodigoCGROM
    movwf    LCD_Dato                ; Guarda el valor del carcter y comprueba si es
LCD_EnheMinuscula                    ; un carcter especial.
    sublw    ''                     ; Es la ""?
    btfss    STATUS,Z
    goto    LCD_EnheMayuscula        ; No es "".
    movlw    b'11101110'                ; Cdigo CGROM de la "".
    movwf    LCD_Dato
    goto    LCD_FinCGROM
LCD_EnheMayuscula
    movf    LCD_Dato,W                ; Recupera el cdigo ASCII de entrada.
    sublw    ''                     ; Es la ""?
    btfss    STATUS,Z
    goto    LCD_Grado                ; No es "".
    movlw    b'11101110'                ; Cdigo CGROM de la "". (No hay smbolo para
    movwf    LCD_Dato                ; la "" mayscula en la CGROM).
    goto    LCD_FinCGROM    
LCD_Grado
    movf    LCD_Dato,W                ; Recupera el cdigo ASCII de entrada.
    sublw    ''                     ; Es el smbolo ""?
    btfss    STATUS,Z
    goto    LCD_FinCGROM            ; No es "".
    movlw    b'11011111'                ; Cdigo CGROM del smbolo "".
    movwf    LCD_Dato
LCD_FinCGROM
    movf    LCD_Dato,W                ; En (W) el cdigo buscado.
    return





;**************************** Librera "LCD_MENS.INC" ********************************


    CBLOCK
    LCD_ApuntaCaracter                ; Indica la posicin del carcter a visualizar
                                    ; respecto del comienzo de todos los mensajes,
                                    ; (posicin de la etiqueta "Mensajes").
    LCD_ValorCaracter                ; Cdigo ASCII del carcter a 
    ENDC                            ; visualizar.

; Los mensajes tienen que estar situados dentro de las 256 primeras posiciones de la 
; memoria de programa, es decir, no pueden superar la direccin 0FFh.

                    ; Vuelve al programa principal.

; Subrutina "LCD_MensajeMovimiento" -----------------------------------------------------
;
; Visualiza un mensaje de mayor longitud que los 16 caracteres que pueden representarse
; en una lnea, por tanto se desplaza a travs de la pantalla.
;
; En el mensaje debe dejarse 16 espacios en blanco, al principio y al final para
; conseguir que el desplazamiento del mensaje sea lo ms legible posible.
;
    CBLOCK    
    LCD_CursorPosicion                ; Contabiliza la posicin del cursor dentro de la
    ENDC                            ; pantalla LCD

LCD_MensajeMovimiento
    movwf    LCD_ApuntaCaracter        ; Posicin del primer carcter del mensaje.
    movlw    Mensajes                ; Halla la posicin relativa del primer carcter
    subwf    LCD_ApuntaCaracter,F    ; del mensaje respecto de la etiqueta "Mensajes".
    decf    LCD_ApuntaCaracter,F    ; Compensa la posicin que ocupa "addwf PCL,F".
LCD_PrimeraPosicion
    clrf    LCD_CursorPosicion        ; El cursor en la posicin 0 de la lnea.
    call    LCD_Borra                ; Se sita en la primera posicin de la lnea 1 y
LCD_VisualizaCaracter                ; borra la pantalla.
    movlw    LCD_CaracteresPorLinea    ; Ha llegado a final de lnea?
    subwf    LCD_CursorPosicion,W
    btfss    STATUS,Z
    goto    LCD_NoEsFinalLinea
LCD_EsFinalLinea
    call    Retardo_200ms            ; Lo mantiene visualizado durante este tiempo.
    call    Retardo_200ms
    movlw    LCD_CaracteresPorLinea-1; Apunta a la posicin del segundo carcter visualizado
    subwf    LCD_ApuntaCaracter,F    ; en pantalla, que ser el primero en la siguiente
    goto    LCD_PrimeraPosicion         ; visualizacin de lnea, para producir el efecto
LCD_NoEsFinalLinea                    ; de desplazamiento hacia la izquierda.
    movf    LCD_ApuntaCaracter,W
    call    Mensajes                ; Obtiene el ASCII del carcter apuntado.
    movwf    LCD_ValorCaracter        ; Guarda el valor de carcter.
    movf    LCD_ValorCaracter,F        ; Lo nico que hace es posicionar flag Z. En caso
    btfsc    STATUS,Z                ; que sea "0x00", que es cdigo indicador final    
    goto    LCD_FinMovimiento        ; de mensaje, sale fuera.
LCD_NoUltimoCaracter2
    call    LCD_Caracter            ; Visualiza el carcter ASCII ledo.
    incf    LCD_CursorPosicion,F    ; Contabiliza el incremento de posicin del 
                                    ; cursor en la pantalla.
    incf    LCD_ApuntaCaracter,F    ; Apunta a la siguiente posicin por visualizar.
    goto    LCD_VisualizaCaracter    ; Vuelve a visualizar el siguiente carcter
LCD_FinMovimiento                    ; de la lnea.
    return                            ; Vuelve al programa principal.
    

;**************************** Librera "RETARDOS.INC" *********************************

; ZONA DE DATOS *********************************************************************

    CBLOCK
    R_ContA                        ; Contadores para los retardos.
    R_ContB
    R_ContC
    ENDC

; RETARDOS de 20 hasta 500 microsegundos ------------------------------------------------

Retardo_200micros                ; La llamada "call" aporta 2 ciclos mquina.
    nop                            ; Aporta 1 ciclo mquina.
    movlw    d'64'                ; Aporta 1 ciclo mquina. Este es el valor de "K".
    goto    RetardoMicros        ; Aporta 2 ciclos mquina.

Retardo_50micros                ; La llamada "call" aporta 2 ciclos mquina.
    nop                            ; Aporta 1 ciclo mquina.
    movlw    d'14'                ; Aporta 1 ciclo mquina. Este es el valor de "K".
    goto    RetardoMicros        ; Aporta 2 ciclos mquina.

Retardo_20micros                ; La llamada "call" aporta 2 ciclos mquina.
    movlw    d'5'                ; Aporta 1 ciclo mquina. Este es el valor de "K".

RetardoMicros
    movwf    R_ContA                ; Aporta 1 ciclo mquina.
Rmicros_Bucle
    decfsz    R_ContA,F            ; (K-1)x1 cm (cuando no salta) + 2 cm (al saltar).
    goto    Rmicros_Bucle        ; Aporta (K-1)x2 ciclos mquina.
    return                        ; El salto del retorno aporta 2 ciclos mquina.

; RETARDOS de 1 ms hasta 200 ms. --------------------------------------------------------
;
Retardo_200ms                    ; La llamada "call" aporta 2 ciclos mquina.
    movlw    d'200'                ; Aporta 1 ciclo mquina. Este es el valor de "M".
    goto    Retardos_ms            ; Aporta 2 ciclos mquina.

Retardo_20ms                    ; La llamada "call" aporta 2 ciclos mquina.
    movlw    d'20'                ; Aporta 1 ciclo mquina. Este es el valor de "M".
    goto    Retardos_ms            ; Aporta 2 ciclos mquina.

Retardo_5ms                        ; La llamada "call" aporta 2 ciclos mquina.
    movlw    d'5'                ; Aporta 1 ciclo mquina. Este es el valor de "M".
    goto    Retardos_ms            ; Aporta 2 ciclos mquina.

Retardo_2ms                        ; La llamada "call" aporta 2 ciclos mquina.
    movlw    d'2'                ; Aporta 1 ciclo mquina. Este es el valor de "M".
    goto    Retardos_ms            ; Aporta 2 ciclos mquina.

Retardos_ms
    movwf    R_ContB                ; Aporta 1 ciclo mquina.
R1ms_BucleExterno
    movlw    d'249'                ; Aporta Mx1 ciclos mquina. Este es el valor de "K".
    movwf    R_ContA                ; Aporta Mx1 ciclos mquina.
R1ms_BucleInterno
    nop                            ; Aporta KxMx1 ciclos mquina.
    decfsz    R_ContA,F            ; (K-1)xMx1 cm (cuando no salta) + Mx2 cm (al saltar).
    goto    R1ms_BucleInterno    ; Aporta (K-1)xMx2 ciclos mquina.
    decfsz    R_ContB,F            ; (M-1)x1 cm (cuando no salta) + 2 cm (al saltar).
    goto    R1ms_BucleExterno     ; Aporta (M-1)x2 ciclos mquina.
    return                        ; El salto del retorno aporta 2 ciclos mquina.






END                                
