]> git.llucax.com Git - z.facultad/66.09/etherled.git/blob - pruebas/sdcc/leds_asm/leds.asm
Hago directorio para ir poniendo versiones funcionales.
[z.facultad/66.09/etherled.git] / pruebas / sdcc / leds_asm / 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        = 33 ; 0.05ms (por el clock de 8MHz)
28 LEDS_HIGH       = 0x0080
29 LEDS_LOW        = 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     acall   _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     acall   _leds_write
134     acall   sleep
135
136     mov     dptr, #0xaaaa
137     acall   _leds_write
138     acall   sleep
139     
140     mov     dptr, #0x5555
141     acall   _leds_write
142     acall   sleep
143
144     mov     dptr, #0x0000
145     acall   _leds_write
146     acall   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_matrix_len, 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_LOW
257     mov     a, @r0 ; leo el contenido de la matriz
258     mov     dptr, #LEDS_LOW
259     cpl     a ; complemento para ver encendidos los "1"
260     movx    @dptr, a
261
262     ; imprimo en LEDS_HIGH
263     inc     r0     ; busco proximo byte de la columna
264     mov     a, @r0 ; leo el contenido de la matriz
265     mov     dptr, #LEDS_HIGH
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     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
338
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
355
356 ;end