]> git.llucax.com Git - z.facultad/66.09/etherled.git/blob - src/leds.asm
Implementa el protocolo ELP sobre UDP. Tiene problemas cuando los leds estan
[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_timer2_isr    ; void leds_timer2_isr() interrupt 5;
23
24
25 ; Constantes
26 ; UN CICLO DE MAQUINA SON 1.6666 useg (clock 8MHz)
27 INTERVAL        = 65000 ; 0.05ms (por el clock de 8MHz)
28 LEDS_LOW        = 0x0080
29 LEDS_HIGH       = 0x00c0
30 DELAY_BASE      = 28 ; 16 columnas anda bien con 28 - (len / 2) == 20
31
32 ; Área de bancos de registros
33 .area   REG_BANK_0    (REL,OVR,DATA)
34     .ds     8
35     ; Usamos siempre banco 0
36     ar0     = 0x00
37     ar1     = 0x01
38     ar2     = 0x02
39     ar3     = 0x03
40     ar4     = 0x04
41     ar5     = 0x05
42     ar6     = 0x06
43     ar7     = 0x07
44
45 ; Variables es memoria RAM común
46 .area   DSEG    (DATA)
47 _leds_matrix_len::
48     .ds     1
49 _leds_delay::
50     .ds     1
51 delay:
52     .ds     1
53 curr_col:
54
55 ; Variables en memoria RAM extendida indirecta (8052)
56 .area   ISEG    (DATA)
57 _leds_matrix::
58     .ds     LEDS_MAX_COLS * 2  ; 2 bytes por columna
59
60
61 ; Configuramos el vector de interrupciones para atender el timer2
62 ;.area   INTV    (ABS, CODE)
63 ;    .org    0x002b
64 ;    clr     tf2 ; limpio bit de interrupción porque para el timer2 no es autom.
65 ;    ljmp    timer2_isr
66
67
68 ; Área de código del programa
69 .area   CSEG    (CODE)
70
71 ; Inicializa leds.
72 ; Primitiva de C:
73 ;                   void leds_init();
74 ;
75 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
76 _leds_init::
77     ; guardo registros que uso
78     push    ar0
79     push    ar1
80     push    ar2
81
82     ; leo de la ROM el tamaño por default
83     mov     dptr, #DEFAULT_MATRIX_LEN
84     clr     a
85     movc    a, @a+dptr
86     mov     _leds_matrix_len, a
87     clr     c
88     rlc     a ; multiplicamos por 2 porque hay 2 bytes por columna
89     mov     r2, a ; tamaño en bytes de la matriz
90
91     ; Cargo milisegundos
92     lcall   _leds_delay_update
93     mov     delay, _leds_delay
94
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
99     mov     a, r0
100 proximo$:
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
107
108     ; cargo los capture registers
109     mov     rcap2l, #<(-INTERVAL) ; low byte del intervalo
110     mov     rcap2h, #>(-INTERVAL) ; high byte del intervalo
111
112     mov     t2con, #0x00; setup del timer2 (auto-reload), no lo arrancamos
113     setb    et2 ; habilito interrupcion timer2 (IE.5)
114
115     mov     curr_col, #0  ; inicializo el contador de columna en 0
116
117     ; Limpiamos stack
118     pop     ar2
119     pop     ar1
120     pop     ar0
121
122     ret
123
124
125 ; Hace una prueba simple de los leds
126 ; Primitiva de C:
127 ;                   void leds_test();
128 ;
129 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
130 _leds_test::
131     ; escribo patrones en los leds
132     mov     dptr, #0xffff
133     lcall   _leds_write
134     lcall   sleep
135
136     mov     dptr, #0xaaaa
137     lcall   _leds_write
138     lcall   sleep
139     
140     mov     dptr, #0x5555
141     lcall   _leds_write
142     lcall   sleep
143
144     mov     dptr, #0x0000
145     lcall   _leds_write
146     lcall   sleep
147     
148     ret    
149
150
151 ; Escribe en los leds.
152 ; Primitiva de C:
153 ;                   void leds_write(unsigned int);
154 ;
155 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
156 _leds_write::
157     ; guardamos en r0 la parte alta que imprimimos despues
158     push    ar0
159     mov     r0, dph
160     ; parte baja
161     mov     a, dpl ; de C me viene la parte baja del argumento en el dpl
162     mov     dptr, #LEDS_LOW
163     cpl     a ; complemento para ver encendidos los "1"
164     movx    @dptr, a
165     ; parte alta
166     mov     a, r0 ; de C me viene la parte alta del argumento en el dph
167     mov     dptr, #LEDS_HIGH
168     cpl     a ; complemento para ver encendidos los "1"
169     movx    @dptr, a
170     ; devolvemos r0
171     pop     ar0
172     ret
173
174
175 ; Escribe en los leds del primer latch.
176 ; Primitiva de C:
177 ;                   void leds_write_low(unsigned char);
178 ;
179 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
180 _leds_write_low::
181     ; parte baja
182     mov     a, dpl       ; de C me viene el argumento en el dpl
183     mov     dptr, #LEDS_LOW
184     cpl     a ; complemento para ver encendidos los "1"
185     movx    @dptr, a
186     ret
187
188
189 ; Escribe en los leds del segundo latch.
190 ; Primitiva de C:
191 ;                   void leds_write_high(unsigned char);
192 ;
193 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
194 _leds_write_high::
195     ; parte baja
196     mov     a, dpl       ; de C me viene el argumento en el dpl
197     mov     dptr, #LEDS_HIGH
198     cpl     a ; complemento para ver encendidos los "1"
199     movx    @dptr, a
200     ret
201
202
203 ; Actualiza el retardo de la matriz según la cantidad de columnas
204 ; Primitiva de C:
205 ;                   void leds_delay_update();
206 ;
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.
209 _leds_delay_update::
210     mov     a, _leds_matrix_len
211     clr     c
212     rrc     a ; divido por 2
213     mov     dpl, a
214     mov     a, #DELAY_BASE
215     subb    a, dpl
216     mov     _leds_delay, a
217     ret
218     
219
220 ; Manejador de la interrupción del timer2 para el uso de los leds.
221 ; Primitiva de C:
222 ;                   void leds_timer2_isr() interrupt 5;
223 ;
224 _leds_timer2_isr::
225     ; vemos si todavía hay que seguir esperando o si ya tenemos que leer
226     djnz    delay, 255$
227
228     ; comenzamos realmente a leer la próxima columna
229     mov     delay, _leds_delay
230
231     ; guardamos en el stack el estado actual de los registros que vamos a usar
232     push    acc
233     push    psw
234     push    ar0
235     push    dpl
236     push    dph
237
238     ; vemos si hay que empezar a leer por la 1ra columna de nuevo
239     mov     a, curr_col
240     cjne    a, _leds_matrix_len, 1$
241     
242     ; hay que empezar de nuevo
243     mov     curr_col, #0
244     mov     a, curr_col ; dejamos en a la columna actual
245
246 1$:
247     ; multiplicamos por 2 porque hay 2 bytes por columna
248     clr     c
249     rlc     a                   
250
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
254     mov     r0, a
255
256     ; imprimo en LEDS_HIGH
257     mov     a, @r0 ; leo el contenido de la matriz
258     mov     dptr, #LEDS_HIGH
259     cpl     a ; complemento para ver encendidos los "1"
260     movx    @dptr, a
261
262     ; imprimo en LEDS_LOW
263     inc     r0     ; busco proximo byte de la columna
264     mov     a, @r0 ; leo el contenido de la matriz
265     mov     dptr, #LEDS_LOW
266     cpl     a ; complemento para ver encendidos los "1"
267     movx    @dptr, a
268
269     ; avanzamos a la proxima columna
270     mov     a, curr_col
271     inc     a
272     mov     curr_col, a
273
274     ; sacamos nuestra basura del stack
275     pop     dph
276     pop     dpl
277     pop     ar0
278     pop     psw
279     pop     acc
280
281 255$:
282     reti ; listo! seguimos viaje...
283
284
285 ; Provoca un retardo corto.
286 ; Usamos dpl y dph porque son "C-safe".
287 sleep:
288     mov     a, #0xff
289 2$:
290     mov     dph, #0xff
291 1$:
292     mov     dpl, #0xff
293     djnz    dpl, .
294     djnz    dph, 1$
295     djnz    acc, 2$
296     ret
297
298
299 ; Matriz por default
300 DEFAULT_MATRIX_LEN:
301     .db     16
302     ;.db     32
303
304 DEFAULT_MATRIX:
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
321
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
338
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
355
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
372
373 ;end