+; vim: set filetype=asm51 :
+
+; Fragmento del proyecto que lee la matriz de 8x8 y la muestra a intervalos
+; columna por columna.
+
+
+ ; Constantes
+ LEDS = p0 ; el led de arriba es el más significativo
+ MAT_LEN = 0x30 ; tamaño de la matriz (en columnas)
+ MAT_COL = 0x31 ; columna mostrándose actualmente
+ MATRIZ = 0x32 ; primera columna de la matriz
+ INTERVAL= 0 ; 65535 useg = 65 mseg = 0.06 seg ~= 15 fps
+
+
+ ; Área de inicio (boot)
+ .area BOOT (ABS)
+ .org 0x0000
+ ljmp init
+ ; Vector de interrupción de Timer2
+ .org 0x002B
+ clr tf2 ; Limpia flag de interrupción
+ ljmp timer2handler ; Salta al manejador de interrupción
+
+
+ ; Área de datos por default
+ .area DEFAULTS
+MAT_LEN_D: ; tamaño de la matriz por default
+ .db #8 ; 8x8 por default
+MAT_D: ; matriz por default
+ ; bit 76543210
+ .db #0b01000000 ; columna 0
+ .db #0b00100000 ; columna 1
+ .db #0b00010000 ; columna 2
+ .db #0b00001000 ; columna 3
+ .db #0b00000100 ; columna 4
+ .db #0b00000010 ; columna 5
+ .db #0b00000100 ; columna 6
+ .db #0b00001000 ; columna 7
+ ;
+ ; bit columna
+ ; 7 6 5 4 3 2 1 0
+ ; 7 . . . . . . . .
+ ; 6 . . . . . . . o
+ ; 5 . . . . . . o .
+ ; 4 . . . . . o . .
+ ; 3 o . . . o . . .
+ ; 2 . o . o . . . .
+ ; 1 . . o . . . . .
+ ; 0 . . . . . . . .
+ ;
+ ; --------------->
+ ; dirección de barrido
+
+
+ ; Área del hilo principal del programa
+ .area MAIN
+init:
+;al gas mov LEDS, #0 ; Apaga todos los leds
+ ; Carga tamaño de la matriz default en la memoria
+ mov dptr, #MAT_LEN_D
+;al gas clr a
+ movc a, @a + dptr
+ mov MAT_LEN, a
+
+ ; Carga la matriz default en la memoria
+ mov dptr, #MAT_D ; Dirección de última columna default
+ mov MAT_COL, MAT_LEN ; Uso MAT_COL temporalmente como counter
+loop$:
+ djnz MAT_COL, columna0$
+ mov a, MAT_COL ; Índice de la matriz default
+ movc a, @a + dptr ; Obtengo columna
+ mov r2, a ; Pongo columna en registro temporal
+ mov a, MAT_COL ; Índice de la matriz en memoria
+ add a, #MATRIZ ; Dirección de memoria de la columna
+ mov r0, a ; Uso r0 de puntero
+ mov a, r2 ; Pongo columna a cargar en acumulador
+ mov @r0, a ; *r0 = columna de la matriz default
+ sjmp loop$ ; Volvemos a empezar
+columna0$:
+ clr a ; Falta posición 0
+ movc a, @a + dptr ; Obtengo columna 0
+ mov MATRIZ, a ; La pongo en la matriz en memoria
+ mov MAT_COL, MAT_LEN ; Cargo columna actual
+
+ ; Setup del timer e interrupciones
+ mov rcap2l, #<INTERVAL ; low byte del intervalo
+ mov rcap2h, #>INTERVAL ; high byte del intervalo
+ mov ie, #0b10100000 ; Habilita interrupción timer 2
+ mov t2con, #0b00000100 ; Setup Timer 2 (auto-reload y start)
+ sjmp #. ; Paveamos forever
+
+
+ ; Área del handler del timer2 (dibuja columna actual)
+ .area T2ISR
+timer2handler:
+ push ar0 ; Guardo r0 que voy a usar
+ mov a, MAT_COL
+ jnz sigue$ ; if (MAT_COL == 0)
+ mov MAT_COL, MAT_LEN ; MAT_COL = MAT_LEN;
+sigue$:
+ dec MAT_COL ; MAT_COL--;
+ mov a, MAT_COL ; r0 = MATRIZ + MAT_COL;
+ add a, #MATRIZ
+ mov r0, a
+ mov LEDS, @r0 ; LEDS = *r0;
+ pop ar0 ; Devuelvo r0
+ reti
+
+