1 ; vim: set filetype=asx8051 et sw=4 sts=4 :
5 .optsdcc -mmcs51 --model-small
7 ; Constantes "públicas"
8 LEDS_MAX_COLS = 32 ; Cantidad máxima de columnas
11 .globl _leds_matrix_len ; unsigned char
12 .globl _leds_matrix ; unsigned int[LEDS_MAX_COLS]
15 .globl _leds_init ; void leds_init();
16 .globl _leds_test ; void leds_test();
17 .globl _leds_write ; void leds_write(unsigned int);
18 .globl _leds_write_low ; void leds_write_low(unsigned char);
19 .globl _leds_write_high ; void leds_write_high(unsigned char);
20 .globl _leds_delay_update ; void leds_delay_update();
21 .globl _leds_lock ; void leds_lock();
22 .globl _leds_unlock ; void leds_unlock();
23 .globl _leds_timer2_isr ; void leds_timer2_isr() interrupt 5;
27 LEDS_LOW = 0x0080 ; posición de xdata donde está el latch 1
28 LEDS_HIGH = 0x00c0 ; posición de xdata donde está el latch 2
29 DELAY_FACTOR = 0 ; base del contador para el retardo
30 DELAY_BASE = 13 ; punto medio del retardo
31 DELAY_DIVISOR = 3 ; divisor para la cantidad de columnas
33 ; Área de bancos de registros
34 .area REG_BANK_0 (REL,OVR,DATA)
36 ; Usamos siempre banco 0
46 ; Variables es memoria RAM común
48 _leds_matrix_len:: ; Cantidad de columnas de la matriz
50 curr_col: ; Columna que se está dibujando actualmente
53 ; Variables en memoria RAM extendida indirecta (8052)
55 _leds_matrix:: ; Matriz a dibujar
56 .ds LEDS_MAX_COLS * 2 ; 2 bytes por columna
60 lock: ; Variable utilizada para el 'locking', indica si el timer
61 .ds 1 ; estaba andando al momento de lockear para que el unlock
62 ; pueda reactivarlo de ser necesario
64 ; Configuramos el vector de interrupciones para atender el timer2
65 ;.area INTV (ABS, CODE)
67 ; clr tf2 ; limpio bit de interrupción porque para el timer2 no es autom.
71 ; Área de código del programa
78 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
80 ; guardo registros que uso
85 ; leo de la ROM el tamaño por default
86 mov dptr, #DEFAULT_MATRIX_LEN
89 mov _leds_matrix_len, a
91 rlc a ; multiplicamos por 2 porque hay 2 bytes por columna
92 mov r2, a ; tamaño en bytes de la matriz
95 mov rcap2l, #-DELAY_FACTOR ; base del retardo
96 lcall _leds_delay_update
98 ; copio imagen por default de la ROM a la RAM
99 mov dptr, #DEFAULT_MATRIX
100 mov r0, #0 ; indice del "array" en la ROM
101 mov r1, #_leds_matrix ; dirección de memoria de la RAM
104 movc a, @a+dptr ; leo de la ROM con el índice
105 mov @r1, a ; escribo en el puntero a la RAM
106 inc r1 ; incremento puntero
107 inc r0 ; incremento índice
108 mov a, r0 ; para comparar
109 cjne a, ar2, proximo$ ; veo si quedan más bytes por leer
111 mov t2con, #0x00; setup del timer2 (auto-reload), no lo arrancamos
112 setb tr2 ; largo a correr el timer2
114 mov curr_col, #0 ; inicializo el contador de columna en 0
124 ; Hace una prueba simple de los leds
128 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
130 ; escribo patrones en los leds
150 ; Escribe en los leds.
152 ; void leds_write(unsigned int);
154 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
156 ; guardamos en r0 la parte alta que imprimimos despues
160 mov a, dpl ; de C me viene la parte baja del argumento en el dpl
162 cpl a ; complemento para ver encendidos los "1"
165 mov a, r0 ; de C me viene la parte alta del argumento en el dph
167 cpl a ; complemento para ver encendidos los "1"
174 ; Escribe en los leds del primer latch.
176 ; void leds_write_low(unsigned char);
178 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
181 mov a, dpl ; de C me viene el argumento en el dpl
183 cpl a ; complemento para ver encendidos los "1"
188 ; Escribe en los leds del segundo latch.
190 ; void leds_write_high(unsigned char);
192 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
195 mov a, dpl ; de C me viene el argumento en el dpl
197 cpl a ; complemento para ver encendidos los "1"
202 ; Actualiza el retardo de la matriz según la cantidad de columnas
204 ; void leds_delay_update();
206 ; La fórmula utilizada es:
207 ; DELAY_FACTOR * (DELAY_BASE - (leds_matrix_len / DELAY_DIVISOR))
208 ; En realidad ya está cargado rcap2l DELAY_FACTOR (constante) y en rcap2h se
209 ; carga el resultado de:
210 ; DELAY_BASE - (leds_matrix_len / DELAY_DIVISOR)
211 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
213 push b ; uso b, lo guardo
214 mov a, _leds_matrix_len
215 mov b, #DELAY_DIVISOR
216 div ab ; en a me queda leds_matrix_len / DELAY_DIVISOR
219 subb a, dpl ; en a me queda DELAY_BASE - leds_matrix_len / DELAY_DIVISOR
220 jnb cy, 1$ ; Si leds_matrix_len / DELAY_DIVISOR > DELAY_BASE
221 mov a, #1 ; ponemos 1 para que no quede nulo el intervalo (o 'negativo')
222 1$: ; Si no, seguimos como siempre
223 mov dpl, a ; complemento a la base
226 mov rcap2h, a ; Cargo el nuevo retardo
231 ; Bloquea el timer de los leds cuando se accede a una zona crítica (P0 y/o P2).
235 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
237 mov c, et2 ; En lock me queda si está el timer andando o no.
239 clr et2 ; Sea como sea, lo paro.
243 ; Desbloquea el timer de los leds.
245 ; void leds_unlock();
247 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
249 jnb lock, 1$ ; Si no estába andando, no hago nada
250 setb et2 ; Si estaba andando lo prendo
255 ; Manejador de la interrupción del timer2 para el uso de los leds.
257 ; void leds_timer2_isr() interrupt 5;
260 ; limpiamos flag del timer2
263 ; guardamos en el stack el estado actual de los registros que vamos a usar
270 ; vemos si hay que empezar a leer por la 1ra columna de nuevo
272 cjne a, _leds_matrix_len, 1$
274 ; hay que empezar de nuevo
276 mov a, curr_col ; dejamos en a la columna actual
279 ; multiplicamos por 2 porque hay 2 bytes por columna
283 ; uso r0 como puntero al comienzo de la matriz
284 mov r0, #_leds_matrix
285 add a, r0 ; le sumo al puntero el offset actual segun la columna
288 ; imprimo en LEDS_HIGH
289 mov a, @r0 ; leo el contenido de la matriz
291 cpl a ; complemento para ver encendidos los "1"
294 ; imprimo en LEDS_LOW
295 inc r0 ; busco proximo byte de la columna
296 mov a, @r0 ; leo el contenido de la matriz
298 cpl a ; complemento para ver encendidos los "1"
301 ; avanzamos a la proxima columna
306 ; sacamos nuestra basura del stack
313 reti ; listo! seguimos viaje...
316 ; Provoca un retardo corto.
317 ; Usamos dpl y dph porque son "C-safe".
336 .dw 0b0000111111110000 ; columna 0
337 .dw 0b0011111111111100 ; columna 1
338 .dw 0b0111000000001110 ; columna 2
339 .dw 0b0110000000000110 ; columna 3
340 .dw 0b1100001100000011 ; columna 4
341 .dw 0b1100011000110011 ; columna 5
342 .dw 0b1100110000110011 ; columna 6
343 .dw 0b1100110000000011 ; columna 7
344 .dw 0b1100110000000011 ; columna 8
345 .dw 0b1100110000110011 ; columna 9
346 .dw 0b1100011000110011 ; columna 10
347 .dw 0b1100001100000011 ; columna 11
348 .dw 0b0110000000000110 ; columna 12
349 .dw 0b0111000000001110 ; columna 13
350 .dw 0b0011111111111100 ; columna 14
351 .dw 0b0000111111110000 ; columna 15
353 ; .dw 0b0000011111100000
354 ; .dw 0b0001111111111000
355 ; .dw 0b0011100000011100
356 ; .dw 0b0111110000000110
357 ; .dw 0b0110111000000110
358 ; .dw 0b1100011100000011
359 ; .dw 0b1100001110000011
360 ; .dw 0b1111111111111111
361 ; .dw 0b1111111111111111
362 ; .dw 0b1100001110000011
363 ; .dw 0b1100011100000011
364 ; .dw 0b0110111000000110
365 ; .dw 0b0111110000000110
366 ; .dw 0b0011100000011100
367 ; .dw 0b0001111111111000
368 ; .dw 0b0000011111100000
370 ; .dw 0b1111000000001111 ; columna 0
371 ; .dw 0b1100000000000011 ; columna 1
372 ; .dw 0b1000111111110001 ; columna 2
373 ; .dw 0b1001111111111001 ; columna 3
374 ; .dw 0b0011001111111100 ; columna 4
375 ; .dw 0b0011100111001100 ; columna 5
376 ; .dw 0b0011110011001100 ; columna 6
377 ; .dw 0b0011110011111100 ; columna 7
378 ; .dw 0b0011110011111100 ; columna 8
379 ; .dw 0b0011110011001100 ; columna 9
380 ; .dw 0b0011100111001100 ; columna 01
381 ; .dw 0b0011001111111100 ; columna 00
382 ; .dw 0b1001111111111001 ; columna 01
383 ; .dw 0b1000111111110001 ; columna 03
384 ; .dw 0b1100000000000011 ; columna 04
385 ; .dw 0b1111000000001111 ; columna 05
387 ; .dw 0b0000001111100000 ; columna 0
388 ; .dw 0b0000111110000000 ; columna 1
389 ; .dw 0b0111111000000000 ; columna 2
390 ; .dw 0b1111000000000000 ; columna 3
391 ; .dw 0b0111100000000000 ; columna 4
392 ; .dw 0b0011110000000000 ; columna 5
393 ; .dw 0b0001111000000000 ; columna 6
394 ; .dw 0b0000111100000000 ; columna 7
395 ; .dw 0b0000011110000000 ; columna 8
396 ; .dw 0b0000001111000000 ; columna 9
397 ; .dw 0b0000000111100000 ; columna 10
398 ; .dw 0b0000000011110000 ; columna 11
399 ; .dw 0b0000000001111000 ; columna 12
400 ; .dw 0b0000000000111100 ; columna 13
401 ; .dw 0b0000000000011110 ; columna 14
402 ; .dw 0b0000000000001111 ; columna 15