; **** Encabezado ****
 list p=16F887
 #include P16F887.inc
;Fusibles de configuración
	
 __CONFIG _CONFIG1, _INTRC_OSC_NOCLKOUT & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _IESO_ON & _FCMEN_OFF & _LVP_ON
 __CONFIG _CONFIG2, _BOR4V_BOR40V & _WRT_OFF
;//////////////////////////////////////////////

    cblock  0x20
    TECLA
    STATUSTEMP
    WTEMP
    TMP0
    TMP1
    TMP2
    TMP3
    TMP5
    TMP6
    TEMP
    endc
    
    RS	EQU 0 
    RW	EQU 1
    E	EQU 2
	
    EQUIS   EQU	0x62
    YE	    EQU	0x00
    
    org	0x00
    goto INICIO
    org	0x04	
    goto INTERRUPCION
    
INICIO	
    org	0x05
    
    banksel ANSEL 
    movlw   0x00
    movwf   ANSEL;limpiamos registro ansel, para decirle al pic que las entradas seran digitales
    clrf    ANSELH
    banksel TRISA 
    movlw   0x0F	;para nuestro teclado pondresmos RB4-RB7 como entradas y RB0-RB3 como salidas
    movwf   TRISB	
    clrf    TRISD	;El puerto a seran solo salidas 
    bcf	    OPTION_REG,7    ;Habilitamos los bit de las pull up(resistencias internas)
    movlw   0xFF	;Activamos los pull up de todos los bits
    movwf   WPUB	;del puerto B
    movlw   0x0F    ;Decimos que bits del puerto b
    movwf   IOCB	;serviran para nuestra interrupcion
    banksel PORTA
    clrf    PORTD	;ponemos en 0 nuestra salida
    clrf    PORTB
    call    INICIO_LCD
    bcf	    INTCON,RBIF	    ;Activamos la interrupcion por el puerto B
    bsf	    INTCON,RBIE	    ;Limpiamos la bandera de interrupcion para indicar que nuestro puerto B(Teclado) no ha tenido ningun cambio
    bsf	    INTCON,PEIE	    ;como sera activado por un push button que es un periferico externo al pic, activamos las interrupcines por periferico externo
    bsf     INTCON,GIE	    ;Activamos las interrupciones en gral
   
    clrf    TECLA
    clrf    TEMP
    
PRINCIPAL
    movlw   0X70
    movwf   PORTB
    
    
BARRIDO
    call    DELAY
    rrf	    TECLA,F
    comf    TECLA,W
    movwf   PORTB
    btfss   TECLA,4
    goto    BARRIDO
    call    DELAY
    goto    PRINCIPAL
    
CHECAR_COLUMNA
   movlw    0x77	    ;tecla 1
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    '1'
   call	    WR_DATO
   movwf    PORTC
   goto	    FIN

   movlw    0xB7	    ;tecla2
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    '2'
   call	    WR_DATO
   movwf    PORTC
   goto	    FIN
   
   movlw    0xD7	    ;tecla3
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    '3'
   call	    WR_DATO
   movwf    PORTC
   goto	    FIN
   
   movlw    0xE7	    ;tecla'A'
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    'A'
   call	    WR_DATO
   movwf    PORTD   
   goto	    FIN 
    
   movlw    0x7B	    ;tecla4
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    '4'
   call	    WR_DATO
   movwf    PORTD
   goto	    FIN
   
   movlw    0xBB	    ;tecla 5
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    '5'
   call	    WR_DATO
   movwf    PORTD
   goto	    FIN
   
   movlw    0xDB	    ;tecla 6
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    '6'
   call	    WR_DATO
   movwf    PORTD
   goto	    FIN
   
   movlw    0xEB	    ;tecla 'b'
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    'B'
   call	    WR_DATO
   movwf    PORTD
   goto	    FIN
   
   movlw    0x7D	    ;tecla7
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    '7'
   call	    WR_DATO
   movwf    PORTD
   goto	    FIN
   
   movlw    0xBD	;tecla8
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    '8'
   call	    WR_DATO
   movwf    PORTD
   goto	    FIN
   
   movlw    0xDD	    ;tecla9
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    '9'
   call	    WR_DATO
   movwf    PORTD
   goto	    FIN
   
   movlw    0xED	    ;teclaC
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    'C'
   call	    WR_DATO
   movwf    PORTD   
   goto	    FIN
   
   movlw    0x7E	    ;tecla'd
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    'D'
   call	    WR_DATO
   movwf    PORTD
   goto	    FIN
   
   movlw    0xBE	    ;tecla0
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    '0'
   call	    WR_DATO
   movwf    PORTD
   goto	    FIN
   
   movlw    0xDE	    ;tecla'E'
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    'E'
   call	    WR_DATO
   movwf    PORTD
   goto	    FIN
   
   movlw    0xEE	    ;tecla'F'
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    $+4
   movlw    'F'
   call	    WR_DATO
   movwf    PORTD
   goto	    FIN
   
 
FIN
    movlw   0x0F
    andwf   PORTB,W
    xorlw   0x0F
    btfss   STATUS,Z
    goto    FIN
    return

DELAY
    movlw   0x1E
    movwf   TMP0
DEL0
    movlw   0x36
    movwf   TMP1
    decfsz  TMP1,F
    goto    $-1
    decfsz  TMP0,F
    goto    DEL0
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    return
    
DELAY_20MS
    movlw   0x96
    movwf   TMP2
DEL00
    movlw   0xDD
    movwf   TMP3
    decfsz  TMP3,F
    goto    $-1
    decfsz  TMP2,F
    goto    DEL00
    return
    
INICIO_INT  ;guardamos registro W y status mientras se hace nuestra interrupcion
    movwf   WTEMP
    swapf   STATUS,W
    movwf   STATUSTEMP
    
INTERRUPCION	;empezamos nuestra interrupcion
   movfw    PORTB
   movwf    TEMP
   btfss    PORTB,4
   goto	    CONTINUAR_INT
   btfss    PORTB,5
   goto	    CONTINUAR_INT
   btfss    PORTB,6
   goto	    CONTINUAR_INT
   btfss    PORTB,7
   goto	    CONTINUAR_INT
   goto	    FIN_INT

CONTINUAR_INT
   call	    DELAY_20MS
   movfw    PORTB
   xorwf    TEMP,W
   btfss    STATUS,Z
   goto	    FIN_INT
   call	    CHECAR_COLUMNA
FIN_INT	    ;Restauramos nuestros valores de status y w a como estaban ante de la interrupcion
   bcf	    INTCON,RBIF 
   swapf   STATUSTEMP,W
   movwf   STATUS
   swapf   WTEMP,F
   swapf   WTEMP,W
   retfie
   
INICIO_LCD
    banksel TRISA
    movlw   0xF8
    movwf   TRISA
;    banksel ADCON1
;    movlw   0x1E
;    movwf   ADCON0
    banksel PORTA   ;pasamos al banco 0
    clrf    PORTA
    call    DELAY_15MS
    
    movlw  0x38
    call   WR_CMD
    movlw  0x38
    call   WR_CMD
    movlw  0x06
    call   WR_CMD
    movlw  0x0E
    call   WR_CMD
    movlw  0x01
    call   WR_CMD
    return
    
WR_DATO	MOVWF	TEMP      ;Guardar la dato en TEMP
	CALL	BUSY   ;Espera a que el display este listo
;	CALL	DELAY
	MOVF	TEMP,W    ;Pone el dato en W
	MOVWF	PORTC	;Envia el dato al display
	BCF	PORTA,RW ;Preparar la escritura (RW=0)
	BSF	PORTA,RS ;Preparado para enviar una orden (RS=1)
	BSF	PORTA,E  ;Preparado para enviar el dato al PUERTOB al display(E=1)
	NOP		;Para segurar 600ns (450ns minimos necesarios)
	NOP
	NOP		;
	BCF	PORTA,E  ;
	clrf	PORTC
	clrf	W
	clrf	TEMP
	RETURN	
	    
    
WR_CMD
    movwf   TEMP
    call    BUSY
    movfw   TEMP
    movwf   PORTC
    bcf	    PORTA,RW
    bcf	    PORTA,RS
    bsf	    PORTA,E
    btfss   PORTA,E
    goto    $-1
    bcf	    PORTA,E
    
BUSY
    banksel TRISB
    movlw   0xFF
    movwf   TRISC
    banksel PORTA
    bsf	    PORTA,RW
    bcf	    PORTA,RS
BUSY10
    bsf	    PORTA,E
    btfss   PORTA,E
    goto    $-1
    movfw   PORTC
    bcf	    PORTA,E
    andlw   0x80
    btfss   STATUS,Z
    goto    BUSY10
    bcf	    PORTA,RW
    banksel TRISB
    movlw   0x00    
    movwf   TRISC
    bcf	    STATUS,RP0
    return

DELAY_15MS
    movlw   EQUIS
    movwf   TMP0
DEL000
    movlw   YE
    movwf   TMP5
DEL1
    decfsz  TMP5,1
    goto    DEL1
    decfsz  TMP6,F
    goto    DEL000
    return

    END


