;****************************************************************************************************************************
;              MATRIZ 8x8 con scroll de mensaje para PIC 16F84A, reloj a 4Mhz, registro de desplazamiento 74HC164
;****************************************************************************************************************************


 __CONFIG _CP_OFF &_WDT_OFF &_PWRTE_ON &_XT_OSC

              LIST   P=16F84A
              INCLUDE <P16F84A.INC>

              CBLOCK  0x0C
              count			;usado en rutinas de salto
	      count1			;used in delay routine
	      counta			;used in delay routine
	      countb			;used in delay routine
	      tmp1			;almacenamiento temporal
	      tmp2
	      p_temp			;save register
	      s_temp			;save register
	      w_temp			;save register
              offsetL			;registros de la tabla
              offsetH

;registros de rutina transmisión bits a registro de desplazamiento

              EEPROM
              ALMACEN     
              CONTADOR
                    
;registros para matriz

	      row_pos		        ;posicion en fila

              FILA1			;almacenamiento 1
	      FILA2			;almacenamiento 2
	      FILA3			;almacenamiento 3
	      FILA4			;almacenamiento 4
	      FILA5			;almacenamiento 5
	      FILA6			;almacenamiento 6
	      FILA7			;almacenamiento 7
	      FILA8			;almacenamiento 8

	      FILA11			;almacenamiento 11
	      FILA22			;almacenamiento 22
	      FILA33			;almacenamiento 33
	      FILA44			;almacenamiento 44
	      FILA55			;almacenamiento 55
	      FILA66			;almacenamiento 66
	      FILA77			;almacenamiento 77
	      FILA88			;almacenamiento 88

	      ENDC

DO            EQU       6               ;bit de control



	      ORG	0x00
	      goto	INICIO


;****************************************************************************************************************************
;                       SERVICIO DE INTERRUPCION AL QUE SE ATIENDE CUANDO TMR0 SE DESBORDA
;****************************************************************************************************************************


              ORG	0x04            ;vector de interupción


INT           movwf	w_temp		;Salva registro W
	      swapf	STATUS,W	;Swap status con registro W
	      movwf	s_temp		;Salva registro STATUS
	      movfw	PCLATH
	      movwf	p_temp		;Salva PCLATH 


              btfss	row_pos,0	;mira que fila ha sido la última
	      goto	Al_Dos

	      btfss	row_pos,1	;mira que fila ha sido la última
	      goto	Al_Tres

	      btfss	row_pos,2	;mira que fila ha sido la última
	      goto	Al_Cuatro

	      btfss	row_pos,3	;mira que fila ha sido la última
	      goto	Al_Cinco

	      btfss	row_pos,4	;mira que fila ha sido la última
	      goto	Al_Seis

	      btfss	row_pos,5	;mira que fila ha sido la última
	      goto	Al_Siete

	      btfss	row_pos,6	;mira que fila ha sido la última
	      goto	Al_Ocho

              btfss	row_pos,7	;mira que fila ha sido la última
	      goto	Al_Uno
	      

Al_Uno	      movlw	0xFF            ;carga W con B'11111111'
	      movwf	PORTB	        ;apaga todas las filas poniendo 1 en todas las salidas del PORTB
	      movwf	row_pos         ;carga registro con B'11111111'
	      movf	FILA1,w         ;cargo dato extraido de tabla a W
              movwf     ALMACEN         ;registro donde se almacena el dato
              call      TX              ;llama a rutina para meter dato a registro desplazamiento

	      bcf	row_pos,0       ;borro bit 0 de registro previamente cargado con B'11111111'
	      bcf	PORTB,0	        ;borro bit 0 de salida PORTB
	      goto	INTX            ;salto incondicional a subrutina

Al_Dos	      movlw	0xFF            ;carga W con B'11111111'
	      movwf	PORTB    	;apaga todas las filas poniendo 1 en todas las salidas del PORTB
	      movwf	row_pos         ;carga registro con B'11111111'
	      movf	FILA2,w         ;cargo dato extraido de tabla a W
              movwf     ALMACEN         ;registro donde se almacena el dato
              call      TX              ;llama a rutina para meter dato a registro desplazamiento

	      bcf	row_pos,1       ;borro bit 1 de registro previamente cargado con B'11111111'
	      bcf	PORTB,1	        ;borro bit 1 de salida PORTB
	      goto	INTX            ;salto incondicional a subrutina

Al_Tres	      movlw	0xFF            ;carga W con B'11111111'
	      movwf	PORTB   	;
	      movwf	row_pos         ;
	      movf	FILA3,w         ;
              movwf     ALMACEN         ;registro donde se almacena el dato
              call      TX              ;llama a rutina para meter dato a registro desplazamiento

	      bcf	row_pos,2       ;
	      bcf	PORTB,2	        ;
	      goto	INTX            ;

Al_Cuatro     movlw	0xFF            ;carga W con B'11111111'
	      movwf	PORTB    	;
	      movwf	row_pos         ;
	      movf	FILA4,w         ;
              movwf     ALMACEN         ;registro donde se almacena el dato
              call      TX              ;llama a rutina para meter dato a registro desplazamiento

              bcf	row_pos,3       ;
	      bcf	PORTB,3	        ;
	      goto	INTX            ;

Al_Cinco      movlw	0xFF            ;carga W con B'11111111'
	      movwf	PORTB   	;
	      movwf	row_pos         ;
	      movf	FILA5,w         ;
              movwf     ALMACEN         ;registro donde se almacena el dato
              call      TX              ;llama a rutina para meter dato a registro desplazamiento

	      bcf	row_pos,4       ;
	      bcf	PORTB,4	        ;
	      goto	INTX            ;

Al_Seis	      movlw	0xFF            ;carga W con B'11111111'
	      movwf	PORTB   	;
	      movwf	row_pos         ;
	      movf	FILA6,w         ;
              movwf     ALMACEN         ;registro donde se almacena el dato
              call      TX              ;llama a rutina para meter dato a registro desplazamiento

	      bcf	row_pos,5       ;
	      bcf	PORTB,5	        ;
	      goto	INTX            ;

Al_Siete      movlw	0xFF            ;carga W con B'11111111'
	      movwf	PORTB    	;
	      movwf	row_pos         ;
	      movf	FILA7,w         ;
              movwf     ALMACEN         ;registro donde se almacena el dato
              call      TX              ;llama a rutina para meter dato a registro desplazamiento

	      bcf	row_pos,6       ;
	      bcf	PORTB,6	        ;
	      goto	INTX            ;

Al_Ocho       movlw	0xFF            ;carga W con B'11111111'
	      movwf	PORTB   	;
	      movwf	row_pos         ;
	      movf	FILA8,w         ;
              movwf     ALMACEN         ;registro donde se almacena el dato
              call      TX              ;llama a rutina para meter dato a registro desplazamiento

              bcf	row_pos,7       ;
	      bcf	PORTB,7	        ;
	      goto	INTX            ;

INTX          movfw	p_temp
	      movwf	PCLATH		;Restaura PCLATH
	      swapf	s_temp,W
	      movwf	STATUS		;Restaura registro STATUS
	      swapf	w_temp,F
	      swapf	w_temp,W	;Restaura registro W


              MOVLW	D'240'  	;cargo w con 240
	      MOVWF	TMR0	        ;y lo paso a TMR0
              bcf       INTCON,T0IF     ;pone a 0 flag afectado antes de regresar de interrupción
              bsf       INTCON,T0IE     ;pone a 1 flag afectado antes de regresar de interrupción
	      retfie                    ;retorno de la interrupción


;****************************************************************************************************************************
;                        INICIALIZACIÓN DEL PROGRAMA Y RUTINA DE INTERRUPCIÓN POR DESBORDAMIENTO DEL TMR0
;****************************************************************************************************************************


INICIO	      bsf 	STATUS,RP0	;voy a banco 1
              MOVLW     B'00000110'     ;cargo w con 00000110
              MOVWF     OPTION_REG      ;el Divisor = 128
              clrf      TRISA           ;puertas A todo salida
              clrf      TRISB           ;puertas B todo salida
              bcf       STATUS,RP0      ;voy a banco 0

              
              movlw	0xFF            ;carga B'11111111'
	      movwf	PORTB	        ;y lo meto en PORTB
              clrf	PORTA		;limpio registro puerta A

              movlw     0XFF            ;meto 255 a los registros para evitar que la primera
                                        ;pantalla esté encendida
              movwf     FILA1
              movwf	FILA2
	      movwf	FILA3
	      movwf	FILA4
	      movwf	FILA5
	      movwf	FILA6
	      movwf	FILA7
	      movwf	FILA8
              
              movlw	0x01            ;cargo con 1 el registro
	      movwf	row_pos         ;de las filas


              MOVLW	D'240'          ;cargo w con 240
	      MOVWF	TMR0	        ;para que el TMR0 se desborde cada 2 ms aprox
                                        ;T = (256 - 240) x 128 x 1 us = 2048 us = 2,048 ms
              movlw	0XA0		;cargo w con 10100000 para
	      movwf	INTCON		;habilitar GIE y T0IE

              
;****************************************************************************************************************************
;Aquí se controla que empiece en la dirección 00x0 de la tabla al empezar, y que vayan saliendo el nº de caracteres
;establecidos en la tabla para que una vez salgan todos volver a empezar desde 0x00.
;****************************************************************************************************************************

		
PRINCIPAL     movlw	0x00		;desplega todos los caracteres de nuevo
	      movwf	tmp1

SALTO	      movf	tmp1,w          ;cargo contenido del tmp1 a W
	      call	CARACTER
	      call	ScrollL8	;scroll para buffer del display
	      incf	tmp1,f
	      movf	tmp1,w
	      sublw	D'24'		;controla el nº de caracteres del texto
                                        ;24 en este caso
	      btfsc	STATUS,C
	      goto 	SALTO
              goto	PRINCIPAL       ;final del SALTO


;****************************************************************************************************************************
;Cada caracter tiene 8 bytes de almacenamiento, nosotros multiplicaremos el index value por 8
;****************************************************************************************************************************


CARACTER      movwf	offsetL
	      clrf	offsetH

	      bcf	STATUS,C	;borra carry
	      rlf	offsetL,f	;multiply index value by 8
	      rlf	offsetH,f

	      bcf	STATUS,C	;borra carry
	      rlf	offsetL,f
	      rlf	offsetH,f

	      bcf	STATUS,C	;borra carry
	      rlf	offsetL,f
	      rlf	offsetH,f

	      call	Tabla1
	      movwf	FILA11			
	      incf	offsetL,f	;incrementa 16 bit el puntero
	      btfsc     STATUS,Z
	      incf	offsetH,f

	      call	Tabla1
	      movwf	FILA22
	      incf	offsetL,f	;incrementa 16 bit el puntero
	      btfsc     STATUS,Z
	      incf	offsetH,f

	      call	Tabla1
	      movwf	FILA33
	      incf	offsetL,f	;incrementa 16 bit el puntero
	      btfsc     STATUS,Z
	      incf	offsetH,f

	      call	Tabla1
	      movwf	FILA44
	      incf	offsetL,f       ;incrementa 16 bit el puntero
	      btfsc     STATUS,Z
	      incf	offsetH,f

	      call	Tabla1
	      movwf	FILA55
	      incf	offsetL,f	;incrementa 16 bit el puntero
	      btfsc     STATUS,Z
	      incf	offsetH,f

	      call	Tabla1
	      movwf	FILA66
	      incf	offsetL,f	;incrementa 16 bit el puntero
	      btfsc     STATUS,Z
	      incf	offsetH,f

	      call	Tabla1
	      movwf	FILA77
	      incf	offsetL,f	;incrementa 16 bit el puntero
	      btfsc     STATUS,Z
	      incf	offsetH,f

	      call	Tabla1
	      movwf	FILA88
              return

Tabla1  				;reformada la lectura para tablas largas, mas de 255 bytes.
	      movlw	High(Tabla)
	      addwf	offsetH,W
	      movwf	PCLATH
	      movlw	Low(Tabla)
	      addwf	offsetL,w
	      btfsc     STATUS,C
	      incf	PCLATH,f
	      MOVWF     PCL


;****************************************************************************************************************************
;Llamada a rutina y temporización de scroll a izquierdas, el texto pasa de derechas a izquierdas
;****************************************************************************************************************************


ScrollL8      call	ScrollL
	      call	ScrollDelay	
	      call	ScrollL
	      call	ScrollDelay
	      call	ScrollL
	      call	ScrollDelay
	      call	ScrollL
	      call	ScrollDelay	
	      call	ScrollL
	      call	ScrollDelay
	      call	ScrollL
	      call	ScrollDelay
	      call	ScrollL
	      call	ScrollDelay
	      call	ScrollL
	      call	ScrollDelay
	      return


;****************************************************************************************************************************
;Llamada a temporización de la velocidad a la que el texto irá pasando
;****************************************************************************************************************************


ScrollDelay   call	Delay20         ;cambiando aquí el dato podemos pasar mas rapido o mas lento el texto
	      return


;****************************************************************************************************************************
;Rutina de scroll a izquierdas, el texto pasa de derechas a izquierdas
;****************************************************************************************************************************


ScrollL	      bcf	STATUS,C
	      rlf	FILA11,f
	      rlf	FILA1,f
	      bcf	STATUS,C
	      rlf	FILA22,f
	      rlf	FILA2,f
	      bcf	STATUS,C
	      rlf	FILA33,f
	      rlf	FILA3,f
	      bcf	STATUS,C
	      rlf	FILA44,f
	      rlf	FILA4,f
	      bcf	STATUS,C
	      rlf	FILA55,f
	      rlf	FILA5,f
	      bcf	STATUS,C
	      rlf	FILA66,f
	      rlf	FILA6,f
	      bcf	STATUS,C
	      rlf	FILA77,f
	      rlf	FILA7,f
	      bcf	STATUS,C
	      rlf	FILA88,f
	      rlf	FILA8,f
	      return


;****************************************************************************************************************************
;Rutina de tiempos
;****************************************************************************************************************************


Delay1Sec     call	Delay250
	      call	Delay250
	      call	Delay250
	      call	Delay250
	      Return


Delay255      movlw	0xff	        ;delay 255mS
	      goto	d0
Delay250      movlw	d'250'	        ;delay 250mS
	      goto	d0
Delay100      movlw	d'100'	        ;delay 100mS
	      goto	d0
Delay50	      movlw	d'50'	        ;delay 50mS
	      goto	d0
Delay20	      movlw	d'20'	        ;delay 20mS
	      goto	d0
Delay10	      movlw	d'10'	        ;delay 10mS
	      goto	d0
Delay1	      movlw	d'1'	        ;delay 1mS
	      goto	d0
Delay5	      movlw	0x05	        ;delay 5ms
d0	      movwf	count1
d1	      movlw	0xE7
	      movwf	counta
	      movlw	0x04
	      movwf	countb
Delay_0	      decfsz	counta,f
	      goto	$+2
	      decfsz	countb,f
	      goto	Delay_0
	      decfsz	count1,f
	      goto	d1
	      retlw	0x00


;****************************************************************************************************************************
;RUTINA TRANSMISIÓN BITS A REGISTRO 74HC164
;****************************************************************************************************************************


TX            movlw     .8              ;pone 8 en W
              movwf     CONTADOR        ;carga contador con 8


TXLP          bcf       EEPROM,DO       ;a 0 bit DO
              btfsc     ALMACEN,0       ;mira el bit 7 de ALMACEN y salta si es 0
              bsf       EEPROM,DO       ;a 1 bit DO
              call      BITOUT 
              rrf       ALMACEN,F       ;rota a izquierda ALMACEN
              decfsz    CONTADOR,F      ;decrementa contador si es 0 salta
              goto      TXLP
              return 
         
 

BITOUT        bsf       STATUS,RP0      ;pagina 1     
              movlw     0X00 
              movwf     TRISA           ;puerta A salida
              bcf       STATUS,RP0      ;pagina 0 
 
              btfss     EEPROM,DO       ;mira el bit DO y salta si vale 1
              goto      BITLOW 
              bsf       PORTA,3         ;pone a 1 DATA
              goto      CLOCK

 
BITLOW        bcf       PORTA,3         ;pone a 0 DATA



;****************************************************************************************************************************
;RUTINA DE TRANSMISIÓN SEÑAL DE RELOJ A REGISTRO 74HC164
;****************************************************************************************************************************


CLOCK         bcf       PORTA,2         ;pone a 0 CLOCK
              nop                       ;espera 1 micros
              nop                       ;otro
              nop                       ;otro
              nop                       ;otro
              bsf       PORTA,2         ;pone a 1 CLOCK
              nop                       ;1 micros 
              return


;****************************************************************************************************************************
;                                              TABLA DE CARACTERES
;****************************************************************************************************************************


Tabla	      
              retlw	D'255'        
              retlw     D'255'
              retlw     D'255'		
              retlw     D'255'	        ;SPACE	
              retlw     D'255'		
              retlw     D'255'		
              retlw     D'255'		
              retlw     D'255'

              retlw     D'51'
              retlw     D'51'
              retlw     D'51'
              retlw     D'51'           ;letra H
              retlw     D'3'
              retlw     D'51'
              retlw     D'51'
              retlw     D'51'

              retlw     D'207'
              retlw     D'51'
              retlw     D'51'
              retlw     D'51'           ;letra O
              retlw     D'51'
              retlw     D'51'
              retlw     D'51'
              retlw     D'207'

              retlw     D'63'
              retlw     D'63'
              retlw     D'63'
              retlw     D'63'           ;letra L
              retlw     D'63'
              retlw     D'63'
              retlw     D'63'
              retlw     D'3'

              retlw     D'207'          
              retlw     D'135'
              retlw     D'51'
              retlw     D'51'           ;letra A
              retlw     D'3'
              retlw     D'51'
              retlw     D'51'
              retlw     D'51'

              retlw	D'255'        
              retlw     D'255'
              retlw     D'255'		
              retlw     D'255'	        ;SPACE	
              retlw     D'255'		
              retlw     D'255'		
              retlw     D'255'		
              retlw     D'255'

              retlw     D'147'
              retlw     D'41'
              retlw     D'41'
              retlw     D'57'           ;letra M
              retlw     D'57'
              retlw     D'57'
              retlw     D'57'
              retlw     D'57'

              retlw     D'51'
              retlw     D'51'
              retlw     D'51'
              retlw     D'51'           ;letra U
              retlw     D'51'
              retlw     D'51'
              retlw     D'51'
              retlw     D'135'

              retlw     D'59'
              retlw     D'27'
              retlw     D'43'
              retlw     D'43'           ;letra N
              retlw     D'43'
              retlw     D'51'
              retlw     D'51'
              retlw     D'59'

              retlw     D'15'          
              retlw     D'55'
              retlw     D'51'
              retlw     D'51'           ;letra D
              retlw     D'51'
              retlw     D'51'
              retlw     D'55'
              retlw     D'15'

              retlw     D'207'
              retlw     D'51'
              retlw     D'51'
              retlw     D'51'           ;letra O
              retlw     D'51'
              retlw     D'51'
              retlw     D'51'
              retlw     D'207'

	      retlw	D'255'        
              retlw     D'255'
              retlw     D'255'		
              retlw     D'255'	        ;SPACE	
              retlw     D'255'		
              retlw     D'255'		
              retlw     D'255'		
              retlw     D'255'

              END

