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_timer2_isr ; void leds_timer2_isr() interrupt 5;
26 ; UN CICLO DE MAQUINA SON 1.6666 useg (clock 8MHz)
27 INTERVAL = 65000 ; 0.05ms (por el clock de 8MHz)
30 DELAY_BASE = 28 ; 16 columnas anda bien con 28 - (len / 2) == 20
32 ; Área de bancos de registros
33 .area REG_BANK_0 (REL,OVR,DATA)
35 ; Usamos siempre banco 0
45 ; Variables es memoria RAM común
55 ; Variables en memoria RAM extendida indirecta (8052)
58 .ds LEDS_MAX_COLS * 2 ; 2 bytes por columna
61 ; Configuramos el vector de interrupciones para atender el timer2
62 ;.area INTV (ABS, CODE)
64 ; clr tf2 ; limpio bit de interrupción porque para el timer2 no es autom.
68 ; Área de código del programa
75 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
77 ; guardo registros que uso
82 ; leo de la ROM el tamaño por default
83 mov dptr, #DEFAULT_MATRIX_LEN
86 mov _leds_matrix_len, a
88 rlc a ; multiplicamos por 2 porque hay 2 bytes por columna
89 mov r2, a ; tamaño en bytes de la matriz
92 lcall _leds_delay_update
93 mov delay, _leds_delay
95 ; copio imagen por default de la ROM a la RAM
96 mov dptr, #DEFAULT_MATRIX
97 mov r0, #0 ; indice del "array" en la ROM
98 mov r1, #_leds_matrix ; dirección de memoria de la RAM
101 movc a, @a+dptr ; leo de la ROM con el índice
102 mov @r1, a ; escribo en el puntero a la RAM
103 inc r1 ; incremento puntero
104 inc r0 ; incremento índice
105 mov a, r0 ; para comparar
106 cjne a, ar2, proximo$ ; veo si quedan más bytes por leer
108 ; cargo los capture registers
109 mov rcap2l, #<(-INTERVAL) ; low byte del intervalo
110 mov rcap2h, #>(-INTERVAL) ; high byte del intervalo
112 mov t2con, #0x00; setup del timer2 (auto-reload), no lo arrancamos
113 setb et2 ; habilito interrupcion timer2 (IE.5)
115 mov curr_col, #0 ; inicializo el contador de columna en 0
125 ; Hace una prueba simple de los leds
129 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
131 ; escribo patrones en los leds
151 ; Escribe en los leds.
153 ; void leds_write(unsigned int);
155 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
157 ; guardamos en r0 la parte alta que imprimimos despues
161 mov a, dpl ; de C me viene la parte baja del argumento en el dpl
163 cpl a ; complemento para ver encendidos los "1"
166 mov a, r0 ; de C me viene la parte alta del argumento en el dph
168 cpl a ; complemento para ver encendidos los "1"
175 ; Escribe en los leds del primer latch.
177 ; void leds_write_low(unsigned char);
179 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
182 mov a, dpl ; de C me viene el argumento en el dpl
184 cpl a ; complemento para ver encendidos los "1"
189 ; Escribe en los leds del segundo latch.
191 ; void leds_write_high(unsigned char);
193 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
196 mov a, dpl ; de C me viene el argumento en el dpl
198 cpl a ; complemento para ver encendidos los "1"
203 ; Actualiza el retardo de la matriz según la cantidad de columnas
205 ; void leds_delay_update();
207 ; La fórmula utilizada es: (DELAY_BASE - (leds_matrix_len / 2)) * 0.1 ms
208 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
210 mov a, _leds_matrix_len
220 ; Manejador de la interrupción del timer2 para el uso de los leds.
222 ; void leds_timer2_isr() interrupt 5;
225 ; vemos si todavía hay que seguir esperando o si ya tenemos que leer
228 ; comenzamos realmente a leer la próxima columna
229 mov delay, _leds_delay
231 ; guardamos en el stack el estado actual de los registros que vamos a usar
238 ; vemos si hay que empezar a leer por la 1ra columna de nuevo
240 cjne a, _leds_matrix_len, 1$
242 ; hay que empezar de nuevo
244 mov a, curr_col ; dejamos en a la columna actual
247 ; multiplicamos por 2 porque hay 2 bytes por columna
251 ; uso r0 como puntero al comienzo de la matriz
252 mov r0, #_leds_matrix
253 add a, r0 ; le sumo al puntero el offset actual segun la columna
256 ; imprimo en LEDS_HIGH
257 mov a, @r0 ; leo el contenido de la matriz
259 cpl a ; complemento para ver encendidos los "1"
262 ; imprimo en LEDS_LOW
263 inc r0 ; busco proximo byte de la columna
264 mov a, @r0 ; leo el contenido de la matriz
266 cpl a ; complemento para ver encendidos los "1"
269 ; avanzamos a la proxima columna
274 ; sacamos nuestra basura del stack
282 reti ; listo! seguimos viaje...
285 ; Provoca un retardo corto.
286 ; Usamos dpl y dph porque son "C-safe".
305 ; .dw 0b0000111111110000 ; columna 0
306 ; .dw 0b0011111111111100 ; columna 1
307 ; .dw 0b0111000000001110 ; columna 2
308 ; .dw 0b0110000000000110 ; columna 3
309 ; .dw 0b1100001100000011 ; columna 4
310 ; .dw 0b1100011000110011 ; columna 5
311 ; .dw 0b1100110000110011 ; columna 6
312 ; .dw 0b1100110000000011 ; columna 7
313 ; .dw 0b1100110000000011 ; columna 8
314 ; .dw 0b1100110000110011 ; columna 9
315 ; .dw 0b1100011000110011 ; columna 10
316 ; .dw 0b1100001100000011 ; columna 11
317 ; .dw 0b0110000000000110 ; columna 12
318 ; .dw 0b0111000000001110 ; columna 13
319 ; .dw 0b0011111111111100 ; columna 14
320 ; .dw 0b0000111111110000 ; columna 15
322 .dw 0b0000011111100000
323 .dw 0b0001111111111000
324 .dw 0b0011100000011100
325 .dw 0b0111110000000110
326 .dw 0b0110111000000110
327 .dw 0b1100011100000011
328 .dw 0b1100001110000011
329 .dw 0b1111111111111111
330 .dw 0b1111111111111111
331 .dw 0b1100001110000011
332 .dw 0b1100011100000011
333 .dw 0b0110111000000110
334 .dw 0b0111110000000110
335 .dw 0b0011100000011100
336 .dw 0b0001111111111000
337 .dw 0b0000011111100000
339 ; .dw 0b1111000000001111 ; columna 0
340 ; .dw 0b1100000000000011 ; columna 1
341 ; .dw 0b1000111111110001 ; columna 2
342 ; .dw 0b1001111111111001 ; columna 3
343 ; .dw 0b0011001111111100 ; columna 4
344 ; .dw 0b0011100111001100 ; columna 5
345 ; .dw 0b0011110011001100 ; columna 6
346 ; .dw 0b0011110011111100 ; columna 7
347 ; .dw 0b0011110011111100 ; columna 8
348 ; .dw 0b0011110011001100 ; columna 9
349 ; .dw 0b0011100111001100 ; columna 01
350 ; .dw 0b0011001111111100 ; columna 00
351 ; .dw 0b1001111111111001 ; columna 01
352 ; .dw 0b1000111111110001 ; columna 03
353 ; .dw 0b1100000000000011 ; columna 04
354 ; .dw 0b1111000000001111 ; columna 05
356 ; .dw 0b0000001111100000 ; columna 0
357 ; .dw 0b0000111110000000 ; columna 1
358 ; .dw 0b0111111000000000 ; columna 2
359 ; .dw 0b1111000000000000 ; columna 3
360 ; .dw 0b0111100000000000 ; columna 4
361 ; .dw 0b0011110000000000 ; columna 5
362 ; .dw 0b0001111000000000 ; columna 6
363 ; .dw 0b0000111100000000 ; columna 7
364 ; .dw 0b0000011110000000 ; columna 8
365 ; .dw 0b0000001111000000 ; columna 9
366 ; .dw 0b0000000111100000 ; columna 10
367 ; .dw 0b0000000011110000 ; columna 11
368 ; .dw 0b0000000001111000 ; columna 12
369 ; .dw 0b0000000000111100 ; columna 13
370 ; .dw 0b0000000000011110 ; columna 14
371 ; .dw 0b0000000000001111 ; columna 15