]> git.llucax.com Git - z.facultad/66.09/etherled.git/commitdiff
Ejemplo completo del módulo de leds implementado en assembly y llamado desde un
authorLeandro Lucarella <llucax@gmail.com>
Sun, 11 Dec 2005 22:02:43 +0000 (22:02 +0000)
committerLeandro Lucarella <llucax@gmail.com>
Sun, 11 Dec 2005 22:02:43 +0000 (22:02 +0000)
programa en C. Está bastante prolijo y completo, e incluso incluye funciones
para escribir en los leds y para hacer testeo. Lo único que no hubo manera de
hacer es configurar el vector de interrupciones desde asm, porque se pisaba con
el de C, así que lejo esa parte solita al C (hay que incluir sólo la declaración
del ISR).

pruebas/sdcc/leds_asm/Makefile
pruebas/sdcc/leds_asm/leds.asm
pruebas/sdcc/leds_asm/leds.h [new file with mode: 0644]
pruebas/sdcc/leds_asm/leds.lnk
pruebas/sdcc/leds_asm/main.c [new file with mode: 0644]

index 1d4ec5c17be8950afd8aaf0107782808651dd50b..6b43a5d97cf5442060afff47ab1cd1ed676f2410 100644 (file)
@@ -1,14 +1,24 @@
 
-all:
-       @asx8051 -plosgff leds.asm
-       @aslink -nf leds.lnk
-       @packihx leds.ihx > leds.hex
+all: leds.hex
+
+leds.rel: leds.asm
+       asx8051 -plosgff leds.asm
+
+main.asm: main.c leds.h
+       sdcc -c main.c
+
+main.rel: main.asm
+       asx8051 -plosgff main.asm
+
+leds.hex: main.rel leds.rel leds.lnk
+       aslink -nf leds.lnk
+       packihx main.ihx > leds.hex
 
 cleantmp:
-       @rm -f *.sym *.rel *.map *.ihx *.lst *.mem *.rst
+       @rm -vf *.sym *.rel *.map *.ihx *.lst *.mem *.rst main.asm
 
 clean: cleantmp
-       @rm -f *.hex
+       @rm -vf *.hex
 
 .PHONY: clean cleantmp
        
index 5fd53140033f276e11bcc6dede544e508445105e..bc729f119f8ad42b40793e2e657a8fd8542f2848 100644 (file)
@@ -4,25 +4,30 @@
 .module     leds
 .optsdcc    -mmcs51 --model-small
 
-; Variables globales
-.globl  _leds_matrix
-.globl  _leds_matrix_len
-.globl  _leds_delay
-
-; Funciones globales
-.globl  _leds_init
-.globl  _leds_write
-.globl  _leds_write0
-.globl  _leds_write1
-.globl  _leds_delay_update
+; Constantes "públicas"
+LEDS_MAX_COLS    = 32       ; Cantidad máxima de columnas
+
+; Variables públicas
+.globl  _leds_matrix_len    ; unsigned char
+.globl  _leds_matrix        ; unsigned int[LEDS_MAX_COLS]
+.globl  _leds_delay         ; unsigned char
+
+; Funciones públicas
+.globl  _leds_init          ; void leds_init();
+.globl  _leds_test          ; void leds_test();
+.globl  _leds_write         ; void leds_write(unsigned int);
+.globl  _leds_write_low     ; void leds_write_low(unsigned char);
+.globl  _leds_write_high    ; void leds_write_high(unsigned char);
+.globl  _leds_delay_update  ; void leds_delay_update();
+.globl  _leds_timer2_isr    ; void leds_timer2_isr() interrupt 5;
+
 
 ; Constantes
 ; UN CICLO DE MAQUINA SON 1.6666 useg (clock 8MHz)
-INTERVAL        = 66 ; 0.1ms (por el clock de 8MHz)
-LEDS0           = 0x0080
-LEDS1           = 0x00c0
-MAX_COLS        = 64
-DELAY_BASE      = 28
+INTERVAL        = 33 ; 0.05ms (por el clock de 8MHz)
+LEDS_HIGH       = 0x0080
+LEDS_LOW        = 0x00c0
+DELAY_BASE      = 28 ; 16 columnas anda bien con 28 - (len / 2) == 20
 
 ; Área de bancos de registros
 .area   REG_BANK_0    (REL,OVR,DATA)
@@ -46,23 +51,18 @@ _leds_delay::
 delay:
     .ds     1
 curr_col:
-__stack:  ; XXX
-    .ds     1
 
 ; Variables en memoria RAM extendida indirecta (8052)
 .area   ISEG    (DATA)
 _leds_matrix::
-    .ds     MAX_COLS * 2  ; 2 bytes por columna
+    .ds     LEDS_MAX_COLS * 2  ; 2 bytes por columna
 
 
 ; Configuramos el vector de interrupciones para atender el timer2
-.area   INTV    (ABS, CODE)
-    .org    0x0000     ; XXX
-    ljmp    _leds_init ; XXX
-
-    .org    0x002b
-    clr     tf2 ; limpio bit de interrupción porque para el timer2 no es autom.
-    ljmp    timer2_isr
+;.area   INTV    (ABS, CODE)
+;    .org    0x002b
+;    clr     tf2 ; limpio bit de interrupción porque para el timer2 no es autom.
+;    ljmp    timer2_isr
 
 
 ; Área de código del programa
@@ -74,14 +74,13 @@ _leds_matrix::
 ;
 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
 _leds_init::
-    mov     sp, #__stack ; XXX
     ; guardo registros que uso
     push    ar0
     push    ar1
     push    ar2
 
     ; leo de la ROM el tamaño por default
-    mov     dptr, #MAT_D_LEN
+    mov     dptr, #DEFAULT_MATRIX_LEN
     clr     a
     movc    a, @a+dptr
     mov     _leds_matrix_len, a
@@ -94,66 +93,94 @@ _leds_init::
     mov     delay, _leds_delay
 
     ; copio imagen por default de la ROM a la RAM
-    mov     dptr, #MAT_D
+    mov     dptr, #DEFAULT_MATRIX
     mov     r0, #0              ; indice del "array" en la ROM
     mov     r1, #_leds_matrix   ; dirección de memoria de la RAM
     mov     a, r0
-seguir$:
+proximo$:
     movc    a, @a+dptr         ; leo de la ROM con el índice
     mov     @r1, a ; escribo en el puntero a la RAM
     inc     r1 ; incremento puntero
     inc     r0 ; incremento índice
     mov     a, r0 ; para comparar
-    cjne    a, ar2, seguir$ ; veo si quedan más bytes por leer
+    cjne    a, ar2, proximo$ ; veo si quedan más bytes por leer
 
     ; cargo los capture registers
     mov     rcap2l, #<(-INTERVAL) ; low byte del intervalo
     mov     rcap2h, #>(-INTERVAL) ; high byte del intervalo
 
-    mov     ie, #0b10100000 ; habilito interrupcion timer 2
-                            ; bits de IE (interrupt enable) en 1:
-                            ; IE.7 (Global enable/disable)
-                            ; IE.5 (Enable timer 2 interrupt)
-    mov     t2con, #0b00000100 ; setup timer 2 (auto-reload y start)
+    mov     t2con, #0x00; setup del timer2 (auto-reload), no lo arrancamos
+    setb    et2 ; habilito interrupcion timer2 (IE.5)
 
     mov     curr_col, #0  ; inicializo el contador de columna en 0
 
     ; Limpiamos stack
-    push    ar2
-    push    ar1
-    push    ar0
+    pop     ar2
+    pop     ar1
+    pop     ar0
 
     ret
 
 
+; Hace una prueba simple de los leds
+; Primitiva de C:
+;                   void leds_test();
+;
+; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
+_leds_test::
+    ; escribo patrones en los leds
+    mov     dptr, #0xffff
+    acall   _leds_write
+    acall   sleep
+
+    mov     dptr, #0xaaaa
+    acall   _leds_write
+    acall   sleep
+    
+    mov     dptr, #0x5555
+    acall   _leds_write
+    acall   sleep
+
+    mov     dptr, #0x0000
+    acall   _leds_write
+    acall   sleep
+    
+    ret    
+
+
 ; Escribe en los leds.
 ; Primitiva de C:
 ;                   void leds_write(unsigned int);
 ;
 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
 _leds_write::
+    ; guardamos en r0 la parte alta que imprimimos despues
+    push    ar0
+    mov     r0, dph
     ; parte baja
     mov     a, dpl ; de C me viene la parte baja del argumento en el dpl
-    mov     dptr, #LEDS0
+    mov     dptr, #LEDS_LOW
     cpl     a ; complemento para ver encendidos los "1"
     movx    @dptr, a
     ; parte alta
-    mov     a, dph ; de C me viene la parte alta del argumento en el dph
-    mov     dptr, #LEDS1
+    mov     a, r0 ; de C me viene la parte alta del argumento en el dph
+    mov     dptr, #LEDS_HIGH
     cpl     a ; complemento para ver encendidos los "1"
     movx    @dptr, a
+    ; devolvemos r0
+    pop     ar0
     ret
 
 
 ; Escribe en los leds del primer latch.
 ; Primitiva de C:
-;                   void leds_write0(unsigned char);
+;                   void leds_write_low(unsigned char);
 ;
 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
-_leds_write0::
+_leds_write_low::
     ; parte baja
     mov     a, dpl       ; de C me viene el argumento en el dpl
-    mov     dptr, #LEDS0
+    mov     dptr, #LEDS_LOW
     cpl     a ; complemento para ver encendidos los "1"
     movx    @dptr, a
     ret
@@ -161,13 +188,13 @@ _leds_write0::
 
 ; Escribe en los leds del segundo latch.
 ; Primitiva de C:
-;                   void leds_write1(unsigned char);
+;                   void leds_write_high(unsigned char);
 ;
 ; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
-_leds_write1::
+_leds_write_high::
     ; parte baja
     mov     a, dpl       ; de C me viene el argumento en el dpl
-    mov     dptr, #LEDS1
+    mov     dptr, #LEDS_HIGH
     cpl     a ; complemento para ver encendidos los "1"
     movx    @dptr, a
     ret
@@ -190,10 +217,13 @@ _leds_delay_update::
     ret
     
 
-; Manejador de la interrupción del timer2
-timer2_isr:
+; Manejador de la interrupción del timer2 para el uso de los leds.
+; Primitiva de C:
+;                   void leds_timer2_isr() interrupt 5;
+;
+_leds_timer2_isr::
     ; vemos si todavía hay que seguir esperando o si ya tenemos que leer
-    djnz    delay, fin$
+    djnz    delay, 255$
 
     ; comenzamos realmente a leer la próxima columna
     mov     delay, _leds_delay
@@ -207,13 +237,13 @@ timer2_isr:
 
     ; vemos si hay que empezar a leer por la 1ra columna de nuevo
     mov     a, curr_col
-    cjne    a, _leds_matrix_len, continua$
+    cjne    a, _leds_matrix_len, 1$
     
     ; hay que empezar de nuevo
     mov     curr_col, #0
     mov     a, curr_col ; dejamos en a la columna actual
 
-continua$:
+1$:
     ; multiplicamos por 2 porque hay 2 bytes por columna
     clr     c
     rlc     a                   
@@ -223,16 +253,16 @@ continua$:
     add     a, r0 ; le sumo al puntero el offset actual segun la columna
     mov     r0, a
 
-    ; imprimo en LEDS1
+    ; imprimo en LEDS_LOW
     mov     a, @r0 ; leo el contenido de la matriz
-    mov     dptr, #LEDS1
+    mov     dptr, #LEDS_LOW
     cpl     a ; complemento para ver encendidos los "1"
     movx    @dptr, a
 
-    ; imprimo en LEDS0
+    ; imprimo en LEDS_HIGH
     inc     r0     ; busco proximo byte de la columna
     mov     a, @r0 ; leo el contenido de la matriz
-    mov     dptr, #LEDS0
+    mov     dptr, #LEDS_HIGH
     cpl     a ; complemento para ver encendidos los "1"
     movx    @dptr, a
 
@@ -248,16 +278,30 @@ continua$:
     pop     psw
     pop     acc
 
-fin$:
+255$:
     reti ; listo! seguimos viaje...
 
 
+; Provoca un retardo corto.
+; Usamos dpl y dph porque son "C-safe".
+sleep:
+    mov     a, #0xff
+2$:
+    mov     dph, #0xff
+1$:
+    mov     dpl, #0xff
+    djnz    dpl, .
+    djnz    dph, 1$
+    djnz    acc, 2$
+    ret
+
+
 ; Matriz por default
-MAT_D_LEN:
+DEFAULT_MATRIX_LEN:
     .db     16
     ;.db     32
 
-MAT_D:
+DEFAULT_MATRIX:
     .dw     0b0000111111110000    ; columna 0
     .dw     0b0011111111111100    ; columna 1
     .dw     0b0111000000001110    ; columna 2
@@ -275,24 +319,23 @@ MAT_D:
     .dw     0b0011111111111100    ; columna 14
     .dw     0b0000111111110000    ; columna 15
 
-;    .dw     0b0000111111110000    ; columna 0
-;    .dw     0b0011111111111100    ; columna 1
-;    .dw     0b0111000000001110    ; columna 2
-;    .dw     0b0110000000000110    ; columna 3
-;    .dw     0b1100110000000011    ; columna 4
-;    .dw     0b1100011000110011    ; columna 5
-;    .dw     0b1100001100110011    ; columna 6
-;    .dw     0b1100001100000011    ; columna 7
-;    .dw     0b1100001100000011    ; columna 8
-;    .dw     0b1100001100110011    ; columna 9
-;    .dw     0b1100011000110011    ; columna 10
-;    .dw     0b1100110000000011    ; columna 11
-;    .dw     0b0110000000000110    ; columna 12
-;    .dw     0b0111000000001110    ; columna 13
-;    .dw     0b0011111111111100    ; columna 14
-;    .dw     0b0000111111110000    ; columna 15
-
-;MAT_D:
+    .dw     0b1111000000001111    ; columna 0
+    .dw     0b1100000000000011    ; columna 1
+    .dw     0b1000111111110001    ; columna 2
+    .dw     0b1001111111111001    ; columna 3
+    .dw     0b0011001111111100    ; columna 4
+    .dw     0b0011100111001100    ; columna 5
+    .dw     0b0011110011001100    ; columna 6
+    .dw     0b0011110011111100    ; columna 7
+    .dw     0b0011110011111100    ; columna 8
+    .dw     0b0011110011001100    ; columna 9
+    .dw     0b0011100111001100    ; columna 01
+    .dw     0b0011001111111100    ; columna 00
+    .dw     0b1001111111111001    ; columna 01
+    .dw     0b1000111111110001    ; columna 03
+    .dw     0b1100000000000011    ; columna 04
+    .dw     0b1111000000001111    ; columna 05
+
 ;    .dw     0b0000001111100000    ; columna 0
 ;    .dw     0b0000111110000000    ; columna 1
 ;    .dw     0b0111111000000000    ; columna 2
diff --git a/pruebas/sdcc/leds_asm/leds.h b/pruebas/sdcc/leds_asm/leds.h
new file mode 100644 (file)
index 0000000..188978b
--- /dev/null
@@ -0,0 +1,45 @@
+/* vim: set et sw=4 sts=4 : */
+
+#ifndef _LEDS_H_
+#define _LEDS_H_
+
+/** Cantidad máxima de columnas */
+#define LEDS_MAX_COLS 32
+
+/** Tamaño de la matriz de leds, en cantidad de columnas */
+extern unsigned char leds_matrix_len;
+
+/** Matriz de leds, cada elemento del array es una columna */
+extern unsigned int leds_matrix[LEDS_MAX_COLS];
+
+/** Retardo de refresco de la matriz (en múltiplos de 0.1ms) */
+extern unsigned char leds_delay;
+
+/** Inicializa leds
+ *
+ * El 'dibujado' de la matriz se puede controlar fácilmente parando y/o
+ * iniciando el timer2. Para comenzar a 'dibujar' la matriz sólo es necesario
+ * setear el bit TR2 del registro T2CON (y habilitar las interrupciones
+ * globalmente si aún no se hizo, bit EA del registro IE).
+ */
+void leds_init();
+
+/** Realiza un testeo simple de los leds */
+void leds_test();
+
+/** Escribe un word (16 bits) en la columna de leds */
+void leds_write(unsigned int);
+
+/** Escribe un byte en la parte baja de la columna de leds */
+void leds_write_low(unsigned char);
+
+/** Escribe un byte en la parte alta de la columna de leds */
+void leds_write_high(unsigned char);
+
+/** Actualiza el delay al recomendado según el tamaño de la matriz */
+void leds_delay_update();
+
+/** Atiende interrupción del timer2 para 'dibujar' la matriz */
+void leds_timer2_isr() interrupt 5;
+
+#endif /* _LEDS_H_ */
index 139fc873bb642ede4bfa6cd447a1fe8ce46f6793..a5ce4ef8acee03442e6a7023d6f8401bdf9b9152 100644 (file)
@@ -1,7 +1,6 @@
 -myuxi
 -Y
--b INTV = 0x0000
--b CSEG = 0x0030
+-b CSEG = 0x0000
 -b ISEG = 0x0080
 -b BSEG = 0x0000
 -k /usr/share/sdcc/lib/small
@@ -11,5 +10,6 @@
 -l libint
 -l liblong
 -l libfloat
+main.rel
 leds.rel
 -e
diff --git a/pruebas/sdcc/leds_asm/main.c b/pruebas/sdcc/leds_asm/main.c
new file mode 100644 (file)
index 0000000..0667f27
--- /dev/null
@@ -0,0 +1,18 @@
+
+#include "leds.h"
+
+sbit at 0xaf ea;
+sbit at 0xca tr2;
+
+void main()
+{
+       /* inicializo leds */
+       leds_init();
+       /* los pruebo */
+       leds_test();
+       /* empiezo a atender todas las interrupciones */
+       ea = 1;
+       /* largo a correr el timer 2 */
+       tr2 = 1;
+}
+