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 = 33 ; 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 acall _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
216 mov _leds_matrix_len, a
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_LOW
257 mov a, @r0 ; leo el contenido de la matriz
259 cpl a ; complemento para ver encendidos los "1"
262 ; imprimo en LEDS_HIGH
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 0b1111000000001111 ; columna 0
323 .dw 0b1100000000000011 ; columna 1
324 .dw 0b1000111111110001 ; columna 2
325 .dw 0b1001111111111001 ; columna 3
326 .dw 0b0011001111111100 ; columna 4
327 .dw 0b0011100111001100 ; columna 5
328 .dw 0b0011110011001100 ; columna 6
329 .dw 0b0011110011111100 ; columna 7
330 .dw 0b0011110011111100 ; columna 8
331 .dw 0b0011110011001100 ; columna 9
332 .dw 0b0011100111001100 ; columna 01
333 .dw 0b0011001111111100 ; columna 00
334 .dw 0b1001111111111001 ; columna 01
335 .dw 0b1000111111110001 ; columna 03
336 .dw 0b1100000000000011 ; columna 04
337 .dw 0b1111000000001111 ; columna 05
339 ; .dw 0b0000001111100000 ; columna 0
340 ; .dw 0b0000111110000000 ; columna 1
341 ; .dw 0b0111111000000000 ; columna 2
342 ; .dw 0b1111000000000000 ; columna 3
343 ; .dw 0b0111100000000000 ; columna 4
344 ; .dw 0b0011110000000000 ; columna 5
345 ; .dw 0b0001111000000000 ; columna 6
346 ; .dw 0b0000111100000000 ; columna 7
347 ; .dw 0b0000011110000000 ; columna 8
348 ; .dw 0b0000001111000000 ; columna 9
349 ; .dw 0b0000000111100000 ; columna 10
350 ; .dw 0b0000000011110000 ; columna 11
351 ; .dw 0b0000000001111000 ; columna 12
352 ; .dw 0b0000000000111100 ; columna 13
353 ; .dw 0b0000000000011110 ; columna 14
354 ; .dw 0b0000000000001111 ; columna 15