]> git.llucax.com Git - z.facultad/66.09/etherled.git/blob - src/leds.asm
Emprolija un poco el retarno, no necesita más usar el multiplicador.
[z.facultad/66.09/etherled.git] / src / leds.asm
1 ; vim: set filetype=asx8051 et sw=4 sts=4 :
2
3 ; Módulo y opciones
4 .module     leds
5 .optsdcc    -mmcs51 --model-small
6
7 ; Constantes "públicas"
8 LEDS_MAX_COLS    = 32       ; Cantidad máxima de columnas
9
10 ; Variables públicas
11 .globl  _leds_matrix_len    ; unsigned char
12 .globl  _leds_matrix        ; unsigned int[LEDS_MAX_COLS]
13
14 ; Funciones públicas
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;
24
25
26 ; Constantes
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
32
33 ; Área de bancos de registros
34 .area   REG_BANK_0    (REL,OVR,DATA)
35     .ds     8
36     ; Usamos siempre banco 0
37     ar0     = 0x00
38     ar1     = 0x01
39     ar2     = 0x02
40     ar3     = 0x03
41     ar4     = 0x04
42     ar5     = 0x05
43     ar6     = 0x06
44     ar7     = 0x07
45
46 ; Variables es memoria RAM común
47 .area   DSEG    (DATA)
48 _leds_matrix_len::  ; Cantidad de columnas de la matriz
49     .ds     1
50 curr_col:           ; Columna que se está dibujando actualmente
51     .ds     1
52
53 ; Variables en memoria RAM extendida indirecta (8052)
54 .area   ISEG    (DATA)
55 _leds_matrix::      ; Matriz a dibujar
56     .ds     LEDS_MAX_COLS * 2  ; 2 bytes por columna
57
58 ; Variables de bit
59 .area   BSEG    (BIT)
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
63
64 ; Configuramos el vector de interrupciones para atender el timer2
65 ;.area   INTV    (ABS, CODE)
66 ;    .org    0x002b
67 ;    clr     tf2 ; limpio bit de interrupción porque para el timer2 no es autom.
68 ;    ljmp    timer2_isr
69
70
71 ; Área de código del programa
72 .area   CSEG    (CODE)
73
74 ; Inicializa leds.
75 ; Primitiva de C:
76 ;                   void leds_init();
77 ;
78 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
79 _leds_init::
80     ; guardo registros que uso
81     push    ar0
82     push    ar1
83     push    ar2
84
85     ; leo de la ROM el tamaño por default
86     mov     dptr, #DEFAULT_MATRIX_LEN
87     clr     a
88     movc    a, @a+dptr
89     mov     _leds_matrix_len, a
90     clr     c
91     rlc     a ; multiplicamos por 2 porque hay 2 bytes por columna
92     mov     r2, a ; tamaño en bytes de la matriz
93
94     ; Cargo milisegundos
95     mov     rcap2l, #-DELAY_FACTOR  ; base del retardo
96     lcall   _leds_delay_update
97
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
102     mov     a, r0
103 proximo$:
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
110
111     mov     t2con, #0x00; setup del timer2 (auto-reload), no lo arrancamos
112     setb    tr2 ; largo a correr el timer2
113
114     mov     curr_col, #0  ; inicializo el contador de columna en 0
115
116     ; Limpiamos stack
117     pop     ar2
118     pop     ar1
119     pop     ar0
120
121     ret
122
123
124 ; Hace una prueba simple de los leds
125 ; Primitiva de C:
126 ;                   void leds_test();
127 ;
128 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
129 _leds_test::
130     ; escribo patrones en los leds
131     mov     dptr, #0xffff
132     lcall   _leds_write
133     lcall   sleep
134
135     mov     dptr, #0xaaaa
136     lcall   _leds_write
137     lcall   sleep
138     
139     mov     dptr, #0x5555
140     lcall   _leds_write
141     lcall   sleep
142
143     mov     dptr, #0x0000
144     lcall   _leds_write
145     lcall   sleep
146     
147     ret    
148
149
150 ; Escribe en los leds.
151 ; Primitiva de C:
152 ;                   void leds_write(unsigned int);
153 ;
154 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
155 _leds_write::
156     ; guardamos en r0 la parte alta que imprimimos despues
157     push    ar0
158     mov     r0, dph
159     ; parte baja
160     mov     a, dpl ; de C me viene la parte baja del argumento en el dpl
161     mov     dptr, #LEDS_LOW
162     cpl     a ; complemento para ver encendidos los "1"
163     movx    @dptr, a
164     ; parte alta
165     mov     a, r0 ; de C me viene la parte alta del argumento en el dph
166     mov     dptr, #LEDS_HIGH
167     cpl     a ; complemento para ver encendidos los "1"
168     movx    @dptr, a
169     ; devolvemos r0
170     pop     ar0
171     ret
172
173
174 ; Escribe en los leds del primer latch.
175 ; Primitiva de C:
176 ;                   void leds_write_low(unsigned char);
177 ;
178 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
179 _leds_write_low::
180     ; parte baja
181     mov     a, dpl       ; de C me viene el argumento en el dpl
182     mov     dptr, #LEDS_LOW
183     cpl     a ; complemento para ver encendidos los "1"
184     movx    @dptr, a
185     ret
186
187
188 ; Escribe en los leds del segundo latch.
189 ; Primitiva de C:
190 ;                   void leds_write_high(unsigned char);
191 ;
192 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
193 _leds_write_high::
194     ; parte baja
195     mov     a, dpl       ; de C me viene el argumento en el dpl
196     mov     dptr, #LEDS_HIGH
197     cpl     a ; complemento para ver encendidos los "1"
198     movx    @dptr, a
199     ret
200
201
202 ; Actualiza el retardo de la matriz según la cantidad de columnas
203 ; Primitiva de C:
204 ;                   void leds_delay_update();
205 ;
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.
212 _leds_delay_update::
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
217     mov     dpl, a
218     mov     a, #DELAY_BASE
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
224     mov     a, #0
225     subb    a, dpl 
226     mov     rcap2h, a ; Cargo el nuevo retardo
227     pop     b ; devuelvo b
228     ret
229
230
231 ; Bloquea el timer de los leds cuando se accede a una zona crítica (P0 y/o P2).
232 ; Primitiva de C:
233 ;                   void leds_lock();
234 ;
235 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
236 _leds_lock::
237     mov     c, et2      ; En lock me queda si está el timer andando o no.
238     mov     lock, c
239     clr     et2         ; Sea como sea, lo paro.
240     ret
241
242
243 ; Desbloquea el timer de los leds.
244 ; Primitiva de C:
245 ;                   void leds_unlock();
246 ;
247 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
248 _leds_unlock::
249     jnb     lock, 1$    ; Si no estába andando, no hago nada
250     setb    et2         ; Si estaba andando lo prendo
251 1$:
252     ret
253     
254
255 ; Manejador de la interrupción del timer2 para el uso de los leds.
256 ; Primitiva de C:
257 ;                   void leds_timer2_isr() interrupt 5;
258 ;
259 _leds_timer2_isr::
260     ; limpiamos flag del timer2
261     clr     tf2
262
263     ; guardamos en el stack el estado actual de los registros que vamos a usar
264     push    acc
265     push    psw
266     push    ar0
267     push    dpl
268     push    dph
269
270     ; vemos si hay que empezar a leer por la 1ra columna de nuevo
271     mov     a, curr_col
272     cjne    a, _leds_matrix_len, 1$
273     
274     ; hay que empezar de nuevo
275     mov     curr_col, #0
276     mov     a, curr_col ; dejamos en a la columna actual
277
278 1$:
279     ; multiplicamos por 2 porque hay 2 bytes por columna
280     clr     c
281     rlc     a                   
282
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
286     mov     r0, a
287
288     ; imprimo en LEDS_HIGH
289     mov     a, @r0 ; leo el contenido de la matriz
290     mov     dptr, #LEDS_HIGH
291     cpl     a ; complemento para ver encendidos los "1"
292     movx    @dptr, a
293
294     ; imprimo en LEDS_LOW
295     inc     r0     ; busco proximo byte de la columna
296     mov     a, @r0 ; leo el contenido de la matriz
297     mov     dptr, #LEDS_LOW
298     cpl     a ; complemento para ver encendidos los "1"
299     movx    @dptr, a
300
301     ; avanzamos a la proxima columna
302     mov     a, curr_col
303     inc     a
304     mov     curr_col, a
305
306     ; sacamos nuestra basura del stack
307     pop     dph
308     pop     dpl
309     pop     ar0
310     pop     psw
311     pop     acc
312
313     reti ; listo! seguimos viaje...
314
315
316 ; Provoca un retardo corto.
317 ; Usamos dpl y dph porque son "C-safe".
318 sleep:
319     mov     a, #0xff
320 2$:
321     mov     dph, #0xff
322 1$:
323     mov     dpl, #0xff
324     djnz    dpl, .
325     djnz    dph, 1$
326     djnz    acc, 2$
327     ret
328
329
330 ; Matriz por default
331 DEFAULT_MATRIX_LEN:
332     .db     16
333     ;.db     32
334
335 DEFAULT_MATRIX:
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
352
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
369
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
386
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
403
404 ;end