--- /dev/null
+; 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
+
+
--- /dev/null
+/*
+ * Pruebas para ver como hace el assembler para traducir algunas cosas.
+ */
+
+/* typedef unsigned char* ptr_t;
+
+ptr_t leds = 0x80; /* p0 * /
+ptr_t matriz = 0x32;
+ptr_t matriz_len = 0x32; /* tamaño de la matriz en cantidad de columnas * /
+ptr_t matriz_curr_col = 0x31; /* columna actual a mostrar * /
+
+*/
+
+const unsigned char leds_default = 0x1f;
+const unsigned char matriz_default[8] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
+unsigned char leds;
+unsigned char matriz[12];
+unsigned char matriz_len;
+unsigned char matriz_col;
+
+void mostrar_leds()
+{
+ unsigned char i;
+ for (i = 0; i < leds_default; ++i)
+ matriz[i] = matriz_default[i];
+ leds = leds_default;
+ if (!matriz_col) matriz_col = matriz_len;
+ --matriz_col;
+ leds = matriz[matriz_col];
+}
+