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]
13 .globl _leds_delay ; unsigned char
16 .globl _leds_init ; void leds_init();
17 .globl _leds_test ; void leds_test();
18 .globl _leds_write ; void leds_write(unsigned int);
19 .globl _leds_write_low ; void leds_write_low(unsigned char);
20 .globl _leds_write_high ; void leds_write_high(unsigned char);
21 .globl _leds_delay_update ; void leds_delay_update();
22 .globl _leds_lock ; void leds_lock();
23 .globl _leds_unlock ; void leds_unlock();
24 .globl _leds_timer2_isr ; void leds_timer2_isr() interrupt 5;
28 INTERVAL = 666 ; 0.1ms (por el clock de 8MHz)
31 DELAY_BASE = 11 ; 16 columnas anda bien con 28 - (len / 2) == 20
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 _leds_delay:: ; Retardo de dibujado configurado
52 delay: ; Contador del retardo actual
54 curr_col: ; Columna que se está dibujando actualmente
57 ; Variables en memoria RAM extendida indirecta (8052)
59 _leds_matrix:: ; Matriz a dibujar
60 .ds LEDS_MAX_COLS * 2 ; 2 bytes por columna
64 lock: ; Variable utilizada para el 'locking', indica si el timer
65 .ds 1 ; estaba andando al momento de lockear para que el unlock
66 ; pueda reactivarlo de ser necesario
68 ; Configuramos el vector de interrupciones para atender el timer2
69 ;.area INTV (ABS, CODE)
71 ; clr tf2 ; limpio bit de interrupción porque para el timer2 no es autom.
75 ; Área de código del programa
82 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
84 ; guardo registros que uso
89 ; leo de la ROM el tamaño por default
90 mov dptr, #DEFAULT_MATRIX_LEN
93 mov _leds_matrix_len, a
95 rlc a ; multiplicamos por 2 porque hay 2 bytes por columna
96 mov r2, a ; tamaño en bytes de la matriz
99 lcall _leds_delay_update
100 mov delay, _leds_delay
102 ; copio imagen por default de la ROM a la RAM
103 mov dptr, #DEFAULT_MATRIX
104 mov r0, #0 ; indice del "array" en la ROM
105 mov r1, #_leds_matrix ; dirección de memoria de la RAM
108 movc a, @a+dptr ; leo de la ROM con el índice
109 mov @r1, a ; escribo en el puntero a la RAM
110 inc r1 ; incremento puntero
111 inc r0 ; incremento índice
112 mov a, r0 ; para comparar
113 cjne a, ar2, proximo$ ; veo si quedan más bytes por leer
115 ; cargo los capture registers
116 mov rcap2l, #<(-INTERVAL) ; low byte del intervalo
117 mov rcap2h, #>(-INTERVAL) ; high byte del intervalo
119 mov t2con, #0x00; setup del timer2 (auto-reload), no lo arrancamos
120 setb tr2 ; largo a correr el timer2
122 mov curr_col, #0 ; inicializo el contador de columna en 0
132 ; Hace una prueba simple de los leds
136 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
138 ; escribo patrones en los leds
158 ; Escribe en los leds.
160 ; void leds_write(unsigned int);
162 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
164 ; guardamos en r0 la parte alta que imprimimos despues
168 mov a, dpl ; de C me viene la parte baja del argumento en el dpl
170 cpl a ; complemento para ver encendidos los "1"
173 mov a, r0 ; de C me viene la parte alta del argumento en el dph
175 cpl a ; complemento para ver encendidos los "1"
182 ; Escribe en los leds del primer latch.
184 ; void leds_write_low(unsigned char);
186 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
189 mov a, dpl ; de C me viene el argumento en el dpl
191 cpl a ; complemento para ver encendidos los "1"
196 ; Escribe en los leds del segundo latch.
198 ; void leds_write_high(unsigned char);
200 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
203 mov a, dpl ; de C me viene el argumento en el dpl
205 cpl a ; complemento para ver encendidos los "1"
210 ; Actualiza el retardo de la matriz según la cantidad de columnas
212 ; void leds_delay_update();
214 ; La fórmula utilizada es: (DELAY_BASE - (leds_matrix_len / 2)) * 0.1 ms
215 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
217 mov a, _leds_matrix_len
227 ; Bloquea el timer de los leds cuando se accede a una zona crítica (P0 y/o P2).
231 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
233 mov c, et2 ; En lock me queda si está el timer andando o no.
235 clr et2 ; Sea como sea, lo paro.
239 ; Desbloquea el timer de los leds.
241 ; void leds_unlock();
243 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
245 jnb lock, 1$ ; Si no estába andando, no hago nada
246 setb et2 ; Si estaba andando lo prendo
251 ; Manejador de la interrupción del timer2 para el uso de los leds.
253 ; void leds_timer2_isr() interrupt 5;
256 ; limpiamos flag del timer2
258 ; vemos si todavía hay que seguir esperando o si ya tenemos que leer
261 ; comenzamos realmente a leer la próxima columna
262 mov delay, _leds_delay
264 ; guardamos en el stack el estado actual de los registros que vamos a usar
271 ; vemos si hay que empezar a leer por la 1ra columna de nuevo
273 cjne a, _leds_matrix_len, 1$
275 ; hay que empezar de nuevo
277 mov a, curr_col ; dejamos en a la columna actual
280 ; multiplicamos por 2 porque hay 2 bytes por columna
284 ; uso r0 como puntero al comienzo de la matriz
285 mov r0, #_leds_matrix
286 add a, r0 ; le sumo al puntero el offset actual segun la columna
289 ; imprimo en LEDS_HIGH
290 mov a, @r0 ; leo el contenido de la matriz
292 cpl a ; complemento para ver encendidos los "1"
295 ; imprimo en LEDS_LOW
296 inc r0 ; busco proximo byte de la columna
297 mov a, @r0 ; leo el contenido de la matriz
299 cpl a ; complemento para ver encendidos los "1"
302 ; avanzamos a la proxima columna
307 ; sacamos nuestra basura del stack
315 reti ; listo! seguimos viaje...
318 ; Provoca un retardo corto.
319 ; Usamos dpl y dph porque son "C-safe".
338 ; .dw 0b0000111111110000 ; columna 0
339 ; .dw 0b0011111111111100 ; columna 1
340 ; .dw 0b0111000000001110 ; columna 2
341 ; .dw 0b0110000000000110 ; columna 3
342 ; .dw 0b1100001100000011 ; columna 4
343 ; .dw 0b1100011000110011 ; columna 5
344 ; .dw 0b1100110000110011 ; columna 6
345 ; .dw 0b1100110000000011 ; columna 7
346 ; .dw 0b1100110000000011 ; columna 8
347 ; .dw 0b1100110000110011 ; columna 9
348 ; .dw 0b1100011000110011 ; columna 10
349 ; .dw 0b1100001100000011 ; columna 11
350 ; .dw 0b0110000000000110 ; columna 12
351 ; .dw 0b0111000000001110 ; columna 13
352 ; .dw 0b0011111111111100 ; columna 14
353 ; .dw 0b0000111111110000 ; columna 15
355 .dw 0b0000011111100000
356 .dw 0b0001111111111000
357 .dw 0b0011100000011100
358 .dw 0b0111110000000110
359 .dw 0b0110111000000110
360 .dw 0b1100011100000011
361 .dw 0b1100001110000011
362 .dw 0b1111111111111111
363 .dw 0b1111111111111111
364 .dw 0b1100001110000011
365 .dw 0b1100011100000011
366 .dw 0b0110111000000110
367 .dw 0b0111110000000110
368 .dw 0b0011100000011100
369 .dw 0b0001111111111000
370 .dw 0b0000011111100000
372 ; .dw 0b1111000000001111 ; columna 0
373 ; .dw 0b1100000000000011 ; columna 1
374 ; .dw 0b1000111111110001 ; columna 2
375 ; .dw 0b1001111111111001 ; columna 3
376 ; .dw 0b0011001111111100 ; columna 4
377 ; .dw 0b0011100111001100 ; columna 5
378 ; .dw 0b0011110011001100 ; columna 6
379 ; .dw 0b0011110011111100 ; columna 7
380 ; .dw 0b0011110011111100 ; columna 8
381 ; .dw 0b0011110011001100 ; columna 9
382 ; .dw 0b0011100111001100 ; columna 01
383 ; .dw 0b0011001111111100 ; columna 00
384 ; .dw 0b1001111111111001 ; columna 01
385 ; .dw 0b1000111111110001 ; columna 03
386 ; .dw 0b1100000000000011 ; columna 04
387 ; .dw 0b1111000000001111 ; columna 05
389 ; .dw 0b0000001111100000 ; columna 0
390 ; .dw 0b0000111110000000 ; columna 1
391 ; .dw 0b0111111000000000 ; columna 2
392 ; .dw 0b1111000000000000 ; columna 3
393 ; .dw 0b0111100000000000 ; columna 4
394 ; .dw 0b0011110000000000 ; columna 5
395 ; .dw 0b0001111000000000 ; columna 6
396 ; .dw 0b0000111100000000 ; columna 7
397 ; .dw 0b0000011110000000 ; columna 8
398 ; .dw 0b0000001111000000 ; columna 9
399 ; .dw 0b0000000111100000 ; columna 10
400 ; .dw 0b0000000011110000 ; columna 11
401 ; .dw 0b0000000001111000 ; columna 12
402 ; .dw 0b0000000000111100 ; columna 13
403 ; .dw 0b0000000000011110 ; columna 14
404 ; .dw 0b0000000000001111 ; columna 15