]> git.llucax.com Git - z.facultad/66.09/etherled.git/blob - src/leds.asm
Se implementa un sistema primitivo de 'locking' para los leds. Cada vez que se
[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 .globl  _leds_delay         ; unsigned char
14
15 ; Funciones públicas
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;
25
26
27 ; Constantes
28 INTERVAL        = 666 ; 0.1ms (por el clock de 8MHz)
29 LEDS_LOW        = 0x0080
30 LEDS_HIGH       = 0x00c0
31 DELAY_BASE      = 11 ; 16 columnas anda bien con 28 - (len / 2) == 20
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 _leds_delay::       ; Retardo de dibujado configurado
51     .ds     1
52 delay:              ; Contador del retardo actual
53     .ds     1
54 curr_col:           ; Columna que se está dibujando actualmente
55     .ds     1
56
57 ; Variables en memoria RAM extendida indirecta (8052)
58 .area   ISEG    (DATA)
59 _leds_matrix::      ; Matriz a dibujar
60     .ds     LEDS_MAX_COLS * 2  ; 2 bytes por columna
61
62 ; Variables de bit
63 .area   BSEG    (BIT)
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
67
68 ; Configuramos el vector de interrupciones para atender el timer2
69 ;.area   INTV    (ABS, CODE)
70 ;    .org    0x002b
71 ;    clr     tf2 ; limpio bit de interrupción porque para el timer2 no es autom.
72 ;    ljmp    timer2_isr
73
74
75 ; Área de código del programa
76 .area   CSEG    (CODE)
77
78 ; Inicializa leds.
79 ; Primitiva de C:
80 ;                   void leds_init();
81 ;
82 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
83 _leds_init::
84     ; guardo registros que uso
85     push    ar0
86     push    ar1
87     push    ar2
88
89     ; leo de la ROM el tamaño por default
90     mov     dptr, #DEFAULT_MATRIX_LEN
91     clr     a
92     movc    a, @a+dptr
93     mov     _leds_matrix_len, a
94     clr     c
95     rlc     a ; multiplicamos por 2 porque hay 2 bytes por columna
96     mov     r2, a ; tamaño en bytes de la matriz
97
98     ; Cargo milisegundos
99     lcall   _leds_delay_update
100     mov     delay, _leds_delay
101
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
106     mov     a, r0
107 proximo$:
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
114
115     ; cargo los capture registers
116     mov     rcap2l, #<(-INTERVAL) ; low byte del intervalo
117     mov     rcap2h, #>(-INTERVAL) ; high byte del intervalo
118
119     mov     t2con, #0x00; setup del timer2 (auto-reload), no lo arrancamos
120     setb    tr2 ; largo a correr el timer2
121
122     mov     curr_col, #0  ; inicializo el contador de columna en 0
123
124     ; Limpiamos stack
125     pop     ar2
126     pop     ar1
127     pop     ar0
128
129     ret
130
131
132 ; Hace una prueba simple de los leds
133 ; Primitiva de C:
134 ;                   void leds_test();
135 ;
136 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
137 _leds_test::
138     ; escribo patrones en los leds
139     mov     dptr, #0xffff
140     lcall   _leds_write
141     lcall   sleep
142
143     mov     dptr, #0xaaaa
144     lcall   _leds_write
145     lcall   sleep
146     
147     mov     dptr, #0x5555
148     lcall   _leds_write
149     lcall   sleep
150
151     mov     dptr, #0x0000
152     lcall   _leds_write
153     lcall   sleep
154     
155     ret    
156
157
158 ; Escribe en los leds.
159 ; Primitiva de C:
160 ;                   void leds_write(unsigned int);
161 ;
162 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
163 _leds_write::
164     ; guardamos en r0 la parte alta que imprimimos despues
165     push    ar0
166     mov     r0, dph
167     ; parte baja
168     mov     a, dpl ; de C me viene la parte baja del argumento en el dpl
169     mov     dptr, #LEDS_LOW
170     cpl     a ; complemento para ver encendidos los "1"
171     movx    @dptr, a
172     ; parte alta
173     mov     a, r0 ; de C me viene la parte alta del argumento en el dph
174     mov     dptr, #LEDS_HIGH
175     cpl     a ; complemento para ver encendidos los "1"
176     movx    @dptr, a
177     ; devolvemos r0
178     pop     ar0
179     ret
180
181
182 ; Escribe en los leds del primer latch.
183 ; Primitiva de C:
184 ;                   void leds_write_low(unsigned char);
185 ;
186 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
187 _leds_write_low::
188     ; parte baja
189     mov     a, dpl       ; de C me viene el argumento en el dpl
190     mov     dptr, #LEDS_LOW
191     cpl     a ; complemento para ver encendidos los "1"
192     movx    @dptr, a
193     ret
194
195
196 ; Escribe en los leds del segundo latch.
197 ; Primitiva de C:
198 ;                   void leds_write_high(unsigned char);
199 ;
200 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
201 _leds_write_high::
202     ; parte baja
203     mov     a, dpl       ; de C me viene el argumento en el dpl
204     mov     dptr, #LEDS_HIGH
205     cpl     a ; complemento para ver encendidos los "1"
206     movx    @dptr, a
207     ret
208
209
210 ; Actualiza el retardo de la matriz según la cantidad de columnas
211 ; Primitiva de C:
212 ;                   void leds_delay_update();
213 ;
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.
216 _leds_delay_update::
217     mov     a, _leds_matrix_len
218     clr     c
219     rrc     a ; divido por 2
220     mov     dpl, a
221     mov     a, #DELAY_BASE
222     subb    a, dpl
223     mov     _leds_delay, a
224     ret
225
226
227 ; Bloquea el timer de los leds cuando se accede a una zona crítica (P0 y/o P2).
228 ; Primitiva de C:
229 ;                   void leds_lock();
230 ;
231 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
232 _leds_lock::
233     mov     c, et2      ; En lock me queda si está el timer andando o no.
234     mov     lock, c
235     clr     et2         ; Sea como sea, lo paro.
236     ret
237
238
239 ; Desbloquea el timer de los leds.
240 ; Primitiva de C:
241 ;                   void leds_unlock();
242 ;
243 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
244 _leds_unlock::
245     jnb     lock, 1$    ; Si no estába andando, no hago nada
246     setb    et2         ; Si estaba andando lo prendo
247 1$:
248     ret
249     
250
251 ; Manejador de la interrupción del timer2 para el uso de los leds.
252 ; Primitiva de C:
253 ;                   void leds_timer2_isr() interrupt 5;
254 ;
255 _leds_timer2_isr::
256     ; limpiamos flag del timer2
257     clr     tf2
258     ; vemos si todavía hay que seguir esperando o si ya tenemos que leer
259     djnz    delay, 255$
260
261     ; comenzamos realmente a leer la próxima columna
262     mov     delay, _leds_delay
263
264     ; guardamos en el stack el estado actual de los registros que vamos a usar
265     push    acc
266     push    psw
267     push    ar0
268     push    dpl
269     push    dph
270
271     ; vemos si hay que empezar a leer por la 1ra columna de nuevo
272     mov     a, curr_col
273     cjne    a, _leds_matrix_len, 1$
274     
275     ; hay que empezar de nuevo
276     mov     curr_col, #0
277     mov     a, curr_col ; dejamos en a la columna actual
278
279 1$:
280     ; multiplicamos por 2 porque hay 2 bytes por columna
281     clr     c
282     rlc     a                   
283
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
287     mov     r0, a
288
289     ; imprimo en LEDS_HIGH
290     mov     a, @r0 ; leo el contenido de la matriz
291     mov     dptr, #LEDS_HIGH
292     cpl     a ; complemento para ver encendidos los "1"
293     movx    @dptr, a
294
295     ; imprimo en LEDS_LOW
296     inc     r0     ; busco proximo byte de la columna
297     mov     a, @r0 ; leo el contenido de la matriz
298     mov     dptr, #LEDS_LOW
299     cpl     a ; complemento para ver encendidos los "1"
300     movx    @dptr, a
301
302     ; avanzamos a la proxima columna
303     mov     a, curr_col
304     inc     a
305     mov     curr_col, a
306
307     ; sacamos nuestra basura del stack
308     pop     dph
309     pop     dpl
310     pop     ar0
311     pop     psw
312     pop     acc
313
314 255$:
315     reti ; listo! seguimos viaje...
316
317
318 ; Provoca un retardo corto.
319 ; Usamos dpl y dph porque son "C-safe".
320 sleep:
321     mov     a, #0xff
322 2$:
323     mov     dph, #0xff
324 1$:
325     mov     dpl, #0xff
326     djnz    dpl, .
327     djnz    dph, 1$
328     djnz    acc, 2$
329     ret
330
331
332 ; Matriz por default
333 DEFAULT_MATRIX_LEN:
334     .db     16
335     ;.db     32
336
337 DEFAULT_MATRIX:
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
354
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
371
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
388
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
405
406 ;end