]> git.llucax.com Git - z.facultad/66.09/etherled.git/blob - src/leds.asm
ARP implementado y andando (más pequeños bugfixes)!
[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