En realidad te lo voy a tratar de explicar con un ejemplo y no con codigo. Luego vos vas a tener que realizarlo.
Direccionamiento directo, indirecto, punteros: Todos nombres raros, primero te voy a aclarar esto..
Direccionamiento directo, usando las definiciones de tu programa:
DATOS es lo mismo que 0x05, por lo tanto esa instrucción es MOVF 0x05, W . A la instrucción le estas dando el valor de la dirección a la cual acceder. Junto con la parte alta definida por los bits RP0 y RP1 crean la dirección 0x005 y se accede a esta... En resumen.. Directo = Darle la dirección.
Direccionamiento indirecto, supongamos que quiero acceder a la dirección RAM 0x05, estonces cargo mi valor en el registro FSR el cual es mi
puntero, el puntero apunta a la direccion que yo quiero acceder y luego lo accedo desde el registro INDF. Ejemplo, guardar 0xFE en la direccion 0x05
MOVLW 0x05
MOVWF FSR
MOVLW 0xFE
MOVWF INDF
Para que hacer semejante codigo para guardar un valor te preguntaras, pero ahora veamos si yo quiero llenar las direcciones RAM 0x30 a 0x4F, con los valores 0x11. Si lo hago con direccionamiento directo necesitaria 32 instrucciones, uno por cada direccion mas uno de carga. Con direccionamiento indirecto es mas sencillo.
RELLENAR_RAM:
MOVLW 0x30 ;Cargo la dirección inicial
MOVWF FSR
LOOP:
MOVLW 0x11 ;Guardo el dato a donde dice FSR
MOVWF INDF
INCF FSR, F ; Incremento FSR, es decir ahora cuando acceda a INDF va a ser en la otra posición de memoria
SUBLW FSR, 0x50 ; Reviso que no me pase.
BTFSS STATUS,Z ; Si llegue a los 0x50 Salgo, sino repito el LOOP para seguir llenandolo
GOTO LOOP
RETURN
-------------------------------------------------------------------------------------------
Ahora vamos a diferenciar dos conceptos parecido pero distintos.
Puntero: Contiene la DIRECCION a la cual queres acceder.
Indice: Contiene la posicion en una tabla.
Si observaste en los ejemplos de antes yo use la RAM, porque el PIC16F887 solo permite el direccionamiento indirecto de la RAM, los PIC18 poseen otras funcionalidades que permiten el acceso a la FLASH de mas misma forma.
Pero tus tablas estan realizadas en la FLASH, por lo que nos vamos a tener que manejar con
indices.
¿Como rotar la letra?Sabes que tenes 8 Filas y 8 Columnas, por lo tanto SABES que son 8 datos. Voy a hacer un ejemplo con una matriz 3 x 3. El cual van a ser 3 datos.
0 1 0
1 1 0
1 0 1
Suponete que quiero que se muestren los leds como arriba. Y quiero que rote. Puedo hacerlo de varias formas, que al rotar se produzca un wrap, es decir aparezca de nuevo en la primer linea:
-----------------------> Rotando
0 1 0 0 0 1 1 0 0
1 1 0 0 1 1 1 0 1
1 0 1 1 1 0 0 1 1
O que desaparezca y luego aparezca de nuevo
-----------------------------------------------------------------------> Rotando
0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0
1 1 0 0 1 1 0 0 1 0 0 0 0 0 0 1 0 0
1 0 1 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0
Pensemos como hacer la mas complicada que es la de abajo. Para que desaparezca
La primera vez muestro todo como si fuera fijo, tomando los datos de la tabla, comienzo desde el indice 0. Y muestro todo.
La segunda vez la primer columna la quiero en 0, y luego lo demas, tiene que comenzar desde el indice 0. Hasta un total de 3 datos.
La tercera vez la primera y la segunda columna la quiero en 0, y luego lo demas, tiene que comenzar desde el indice 0. Hasta un total de 3 datos.
Para que aparezca
Solo debemos mostrar la ultima, y luego 2 mas todo 0. 3 datos en total
Mostrar las ultimas 2 y luego todo 0. 3 datos en total.
Siempre son 3 datos. Por lo tanto el loop en este caso se mantiene en los 3 datos que habíamos hablado antes, en tu caso 8. Solamente necesitamos "1 variable mas" que nos indique CUANDO comenzar a mostrar lo de la tabla, o si mostrar o no. Aca entra tu ingenio.
Una idea que se me ocurre en este momento, no la considero la mejor. Pero por ejemplo para mostrar, podria agregar una parte de codigo que revise si el valor de indice que llevo a la TABLADATOS, sea menor a 8, o mayor a 7, como te sea mas comodo. De esa forma tener una variable mas que me diga desde donde comenzar, por ejemplo, COMIENZA = 0.
CONTADATOS = COMIENZA.
SI CONTADATOS > 7 ?
Si -> POngo un 0
No -> Llamo a TABLADATOS
Cuando quiera rotar, solo hago COMIENZA -1 , y ya con eso logro que comienze antes. Por ejemplo
Al ser COMIENZA 0xFF. En la primer vuelta CONTADATOS es mayor a 7, y por lo tanto se envia un 0 y no se llama a la tabla. Luego en la proxima pasada (de los 8 datos) se va a incrementar CONTADATOS y pasa a tener un valor de 0, y es decir en la segunda columna tendria lo que se mostraba en la primera. Asi hasta los 8 datos.
Observa que en mi ejemplo solo modifico lo que aparecen en las columnas, es decir la parte de los datos y no de los comunes como tenes en TABLAFILAS. Esa parte siempre va rotando y cumpliendo sus 8 datos como siempre.
Y si quiero que aparezca? Primero tengo que detectar cuando COMIENZA llego a hacer desaparecer todo. De forma sencilla
Con 0xFF hicimos desaparecer la primera, con 0xFE hasta la segunda, es decir el complemento a 2 de las filas que queremos hacer desaparecer.
El complemento a 2 se saca de la siguiente forma. Si quiero el complemento a 2 de 1, entonces primero hago el complemento y luego le sumo 1, en este ejemplo
0000 0001 -> complementado (negado) es -> 1111 1110, si le sumo 1 queda 1111 1111 = 0xFF
A los 8 datos me desaparece todo, pero yo quiero que desaparezca todo como en el ejemplo, por lo tanto debo detectar a los 9. Hago el complemento a 2 de 9
0000 1001 -> 1111 0110 +1 -> 1111 0111 = 0xF7
Es decir... Cuando detecte que COMIENZA es 0xF7, procedo a asignarle el valor 0x07, asi CONTADATOS comienza con el valor 7, y muestra la ultima fila de la tabla.
Continuo restando CONTADATOS como al mostrar.
En resumen el codigo sin mayores cambios
COMIENZA = 0
Loop:
CONTADATOS = COMIENZA.
; Comienzo de la muestra de las letras
REPITO 8 veces (CONTAROTAR):
¿CONTADATOS mayor a 7 ?
Si -> POngo un 0
No -> Llamo a TABLADATOS
Llamo a TABLAFILAS indicado por CONTAROTAR
MUESTRO
; Fin de la muestra de las letras, repetir para aumentar el tiempo de desplazamiento.
COMIENZA = COMIENZA - 1
¿COMIENZA igual a 0xF7?
Si-> COMIENZA = 0x07
Goto Loop
Fin del pseudocodigo. En resumen, estas creando un INDICE para decirle donde comenzar. E implementando unas protecciones sobre la tabla para no excederte de los valores permitidos. Es todo lo que hay que agregar.
PD: Si no me equivoco este PIC puede leer la Flah mediante lo que es la EEPROM, no me fije en eso.