]> git.llucax.com Git - z.facultad/66.09/etherled.git/commitdiff
Integra leds con modulo de red. El programa está ahora recibiendo datos de la
authorLeandro Lucarella <llucax@gmail.com>
Sun, 11 Dec 2005 22:47:25 +0000 (22:47 +0000)
committerLeandro Lucarella <llucax@gmail.com>
Sun, 11 Dec 2005 22:47:25 +0000 (22:47 +0000)
red y poniéndolos en la matriz (a lo bruto, falta implementar bien el protocolo
para configurar nuestro dispositivo por red). Pero toda la funcionalidad
básica-básica está lista. De ahora en más es empezar a dejar algunas cosas más
prolijas (varias) y corregir algunos bugs.

src/Makefile
src/debug.h
src/leds.asm [new file with mode: 0644]
src/leds.h [new file with mode: 0644]
src/main.c
src/reg51keil.h
src/reg51sdcc.h

index 1cdf384556ddc24bf1071de7ea0f8e556f7de9b6..b7ca2841af27f273110cb6726ff22759e09cceca 100644 (file)
@@ -1,35 +1,85 @@
 
+# Compilador
 CC=sdcc
-LD=sdcc
 CFLAGS=-DDEBUG
 
+# Assembler
+AS=asx8051
+ASFLAGS=-plosgff
+
+# Linker
+LD=aslink
+LDFLAGS=-cn
+
+# Shell
+SHELL=bash
+
+# Archivos
+cmodules=main dp8390 eth ip udp
+amodules=leds
+modules=$(cmodules) $(amodules)
+
 all: el.hex
 
+debug.h: types.h leds.h
+
 reg51.h: reg51sdcc.h
 
 netdev.h: types.h
 
 dp8390.h: types.h reg51.h netdev.h
 
-dp8390.rel: dp8390.c dp8390.h
-       $(CC) $(CFLAGS) -c dp8390.c
+eth.h: types.h
+
+ip.h: types.h
+
+udp.h: types.h
+
+dp8390.asm: dp8390.c dp8390.h debug.h eth.h
+dp8390.rel: dp8390.asm
+
+eth.asm: eth.c eth.h netdev.h debug.h
+eth.rel: eth.asm
+
+ip.asm: ip.c ip.h netdev.h debug.h
+ip.rel: ip.asm
+
+udp.asm: udp.c udp.h ip.h netdev.h debug.h
+udp.rel: udp.asm
+
+main.asm: main.c leds.h reg51.h netdev.h eth.h ip.h udp.h debug.h
+main.rel: main.asm
 
-eth.rel: eth.c eth.h netdev.h types.h
-       $(CC) $(CFLAGS) -c eth.c
+leds.rel: leds.asm
 
-ip.rel: ip.c ip.h netdev.h types.h
-       $(CC) $(CFLAGS) -c ip.c
+el.hex: $(addsuffix .rel, $(modules))
+       @echo -e \
+                       "-myuxi\n"\
+                       "-Y\n"\
+                       "-b CSEG = 0x0000\n"\
+                       "-b ISEG = 0x0080\n"\
+                       "-b BSEG = 0x0000\n"\
+                       "-k /usr/share/sdcc/lib/small\n"\
+                       "-k /usr/share/sdcc/lib/small\n"\
+                       "-l mcs51\n"\
+                       "-l libsdcc\n"\
+                       "-l libint\n"\
+                       "-l liblong\n"\
+                       "-l libfloat\n"\
+                       "$(addsuffix .rel\n, $(modules))"\
+                       "-e\n" | \
+               $(LD) $(LDFLAGS)
+       @packihx main.ihx > el.hex
+       @$(RM) main.ihx
 
-udp.rel: udp.c udp.h ip.h netdev.h types.h
-       $(CC) $(CFLAGS) -c udp.c
+%.asm:
+       $(CC) $(CFLAGS) -c $<
 
-main.rel: main.c netdev.h eth.h ip.h udp.h
-       $(CC) $(CFLAGS) -c main.c
+%.rel:
+       $(AS) $(ASFLAGS) $<
 
-el.hex: main.rel dp8390.rel eth.rel ip.rel udp.rel
-       $(LD) $(LDFLAGS) -o el.hex main.rel dp8390.rel eth.rel ip.rel udp.rel
 
 clean:
-       @rm -vf el.hex *.rel *.asm *.lst *.map *.lnk *.mem *.sym
+       @rm -vf el.hex *.rel $(addsuffix .asm, $(cmodules)) *.lst *.map *.lnk *.mem *.sym
 
 .PHONY: clean
index 9d70530ca312d5010d7d62daf5698ac3f4f2a904..73e989f6c0e170035435408bfb4ca546f08684f2 100644 (file)
     }                                   \
     while (0)
 
-#define print(w)   \
-    do              \
-    {               \
-        leds(w);    \
-        sleep(8);   \
-    }               \
-    while (0)
-
-#define printb(bh, bl)  \
+#define print(w)        \
     do                  \
     {                   \
-        ledsb(bh, bl);  \
+        leds_write(w);  \
         sleep(8);       \
     }                   \
     while (0)
 
+#define printb(bh, bl)          \
+    do                          \
+    {                           \
+        leds_write_high(bh);    \
+        leds_write_low(bl);     \
+        sleep(8);               \
+    }                           \
+    while (0)
+
 #else // NO DEBUG
 
 #define sleep(t) ;
diff --git a/src/leds.asm b/src/leds.asm
new file mode 100644 (file)
index 0000000..bc729f1
--- /dev/null
@@ -0,0 +1,356 @@
+; vim: set filetype=asx8051 et sw=4 sts=4 :
+
+; Módulo y opciones
+.module     leds
+.optsdcc    -mmcs51 --model-small
+
+; 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        = 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)
+    .ds     8
+    ; Usamos siempre banco 0
+    ar0     = 0x00
+    ar1     = 0x01
+    ar2     = 0x02
+    ar3     = 0x03
+    ar4     = 0x04
+    ar5     = 0x05
+    ar6     = 0x06
+    ar7     = 0x07
+
+; Variables es memoria RAM común
+.area   DSEG    (DATA)
+_leds_matrix_len::
+    .ds     1
+_leds_delay::
+    .ds     1
+delay:
+    .ds     1
+curr_col:
+
+; Variables en memoria RAM extendida indirecta (8052)
+.area   ISEG    (DATA)
+_leds_matrix::
+    .ds     LEDS_MAX_COLS * 2  ; 2 bytes por columna
+
+
+; Configuramos el vector de interrupciones para atender el timer2
+;.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
+.area   CSEG    (CODE)
+
+; Inicializa leds.
+; Primitiva de C:
+;                   void leds_init();
+;
+; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
+_leds_init::
+    ; guardo registros que uso
+    push    ar0
+    push    ar1
+    push    ar2
+
+    ; leo de la ROM el tamaño por default
+    mov     dptr, #DEFAULT_MATRIX_LEN
+    clr     a
+    movc    a, @a+dptr
+    mov     _leds_matrix_len, a
+    clr     c
+    rlc     a ; multiplicamos por 2 porque hay 2 bytes por columna
+    mov     r2, a ; tamaño en bytes de la matriz
+
+    ; Cargo milisegundos
+    acall   _leds_delay_update
+    mov     delay, _leds_delay
+
+    ; copio imagen por default de la ROM a la RAM
+    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
+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, 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     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
+    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, #LEDS_LOW
+    cpl     a ; complemento para ver encendidos los "1"
+    movx    @dptr, a
+    ; parte alta
+    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_write_low(unsigned char);
+;
+; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
+_leds_write_low::
+    ; parte baja
+    mov     a, dpl       ; de C me viene el argumento en el dpl
+    mov     dptr, #LEDS_LOW
+    cpl     a ; complemento para ver encendidos los "1"
+    movx    @dptr, a
+    ret
+
+
+; Escribe en los leds del segundo latch.
+; Primitiva de C:
+;                   void leds_write_high(unsigned char);
+;
+; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
+_leds_write_high::
+    ; parte baja
+    mov     a, dpl       ; de C me viene el argumento en el dpl
+    mov     dptr, #LEDS_HIGH
+    cpl     a ; complemento para ver encendidos los "1"
+    movx    @dptr, a
+    ret
+
+
+; Actualiza el retardo de la matriz según la cantidad de columnas
+; Primitiva de C:
+;                   void leds_delay_update();
+;
+; La fórmula utilizada es: (DELAY_BASE - (leds_matrix_len / 2)) * 0.1 ms
+; C se encarga de hacer push y pop del dptr, a y psw si lo necesita.
+_leds_delay_update::
+    mov     a, _leds_matrix_len
+    clr     c
+    rrc     a ; divido por 2
+    mov     dpl, a
+    mov     a, #DELAY_BASE
+    subb    a, dpl
+    mov     _leds_matrix_len, a
+    ret
+    
+
+; 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, 255$
+
+    ; comenzamos realmente a leer la próxima columna
+    mov     delay, _leds_delay
+
+    ; guardamos en el stack el estado actual de los registros que vamos a usar
+    push    acc
+    push    psw
+    push    ar0
+    push    dpl
+    push    dph
+
+    ; vemos si hay que empezar a leer por la 1ra columna de nuevo
+    mov     a, curr_col
+    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
+
+1$:
+    ; multiplicamos por 2 porque hay 2 bytes por columna
+    clr     c
+    rlc     a                   
+
+    ; uso r0 como puntero al comienzo de la matriz
+    mov     r0, #_leds_matrix
+    add     a, r0 ; le sumo al puntero el offset actual segun la columna
+    mov     r0, a
+
+    ; imprimo en LEDS_LOW
+    mov     a, @r0 ; leo el contenido de la matriz
+    mov     dptr, #LEDS_LOW
+    cpl     a ; complemento para ver encendidos los "1"
+    movx    @dptr, a
+
+    ; imprimo en LEDS_HIGH
+    inc     r0     ; busco proximo byte de la columna
+    mov     a, @r0 ; leo el contenido de la matriz
+    mov     dptr, #LEDS_HIGH
+    cpl     a ; complemento para ver encendidos los "1"
+    movx    @dptr, a
+
+    ; avanzamos a la proxima columna
+    mov     a, curr_col
+    inc     a
+    mov     curr_col, a
+
+    ; sacamos nuestra basura del stack
+    pop     dph
+    pop     dpl
+    pop     ar0
+    pop     psw
+    pop     acc
+
+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
+DEFAULT_MATRIX_LEN:
+    .db     16
+    ;.db     32
+
+DEFAULT_MATRIX:
+    .dw     0b0000111111110000    ; columna 0
+    .dw     0b0011111111111100    ; columna 1
+    .dw     0b0111000000001110    ; columna 2
+    .dw     0b0110000000000110    ; columna 3
+    .dw     0b1100001100000011    ; columna 4
+    .dw     0b1100011000110011    ; columna 5
+    .dw     0b1100110000110011    ; columna 6
+    .dw     0b1100110000000011    ; columna 7
+    .dw     0b1100110000000011    ; columna 8
+    .dw     0b1100110000110011    ; columna 9
+    .dw     0b1100011000110011    ; columna 10
+    .dw     0b1100001100000011    ; columna 11
+    .dw     0b0110000000000110    ; columna 12
+    .dw     0b0111000000001110    ; columna 13
+    .dw     0b0011111111111100    ; columna 14
+    .dw     0b0000111111110000    ; columna 15
+
+    .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
+;    .dw     0b1111000000000000    ; columna 3
+;    .dw     0b0111100000000000    ; columna 4
+;    .dw     0b0011110000000000    ; columna 5
+;    .dw     0b0001111000000000    ; columna 6
+;    .dw     0b0000111100000000    ; columna 7
+;    .dw     0b0000011110000000    ; columna 8
+;    .dw     0b0000001111000000    ; columna 9
+;    .dw     0b0000000111100000    ; columna 10
+;    .dw     0b0000000011110000    ; columna 11
+;    .dw     0b0000000001111000    ; columna 12
+;    .dw     0b0000000000111100    ; columna 13
+;    .dw     0b0000000000011110    ; columna 14
+;    .dw     0b0000000000001111    ; columna 15
+
+;end
diff --git a/src/leds.h b/src/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 60ed5db0cec78cba5e4b71922ef001982b569842..f980df1fb630c10f9d10b7c4669bb80017a34f83 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "debug.h"
 #include "leds.h"
+#include "reg51.h"
 #include "netdev.h"
 #include "eth.h"
 #include "ip.h"
 
 void main(void)
 {
-    // Apagamos todos los leds
-    leds(0);
+    // Inicializamos leds
+    leds_init();
+
+    // Hacemos prueba simple de los leds
+    leds_test();
 
     // Inicializamos dispositivo de red
     if (!netdev_init())
     {
-        leds(0xFFFF);
-        while(1); // Si falla init nos quedamos bobos
+        // Si hubo un error, quedan prendidos todos los leds
+        leds_write(0xFFFF);
+        return;
     }
 
+    // Comienza a 'dibujar'
+    EA  = 1; // Habilita interrupciones globalmente
+    TR2 = 1; // Pone a correr el 'dibujado'
+
     // Inicializo IP
     ip_addr_local[0] = 10;
     ip_addr_local[1] = 10;
@@ -30,7 +39,6 @@ void main(void)
 
     while (1) // Forever
     {
-        byte buf[64]; //XXX
         byte i; //XXX
         byte len;
 
@@ -76,8 +84,9 @@ void main(void)
                         // Nuestro protocolo, por ahora un simple echo!
                         len = udp_dgram_len - UDP_HEADER_SIZE;
                         netdev_read_start(len);
+                        leds_matrix_len = len;
                         for (i = 0; i < len; ++i)
-                            buf[i] = udp_read_byte();
+                            leds_matrix[i] = udp_read_byte();
                         netdev_read_end();
                         if (!udp_checksum_ok())
                             goto drop;
@@ -92,7 +101,7 @@ void main(void)
                         udp_write_dgram_header();
                         netdev_write_start(len);
                         for (i = 0; i < len; ++i)
-                            udp_write_byte(buf[i]);
+                            udp_write_byte(leds_matrix[i]);
                         netdev_write_end();
                         udp_write_checksum(ETH_HEADER_SIZE+IP_HEADER_SIZE);
                         netdev_send_end(ETH_HEADER_SIZE+IP_HEADER_SIZE+udp_dgram_len);
index ed182bf24907f9d92ca044f5f74fe13dd9d62929..a40d8aba6189d7f84f36c543d6afa9f7acd62e29 100644 (file)
@@ -23,6 +23,12 @@ sfr IE   = 0xA8;
 sfr IP   = 0xB8;
 sfr SCON = 0x98;
 sfr SBUF = 0x99;
+/* 8052 */
+sfr T2CON  = 0xC8;
+sfr RCAP2L = 0xCA;
+sfr RCAP2H = 0xCB;
+sfr TL2    = 0xCC;
+sfr TH2    = 0xCD;
 
 /*  BIT Register  */
 /*  PSW   */
@@ -44,6 +50,16 @@ sbit IT1  = 0x8A;
 sbit IE0  = 0x89;
 sbit IT0  = 0x88;
 
+/* T2CON (8052) */
+sbit TF2     = 0xCF;
+sbit EXF2    = 0xCE;
+sbit RCLK    = 0xCD;
+sbit TCLK    = 0xCC;
+sbit EXEN2   = 0xCB;
+sbit TR2     = 0xCA;
+sbit C_T2    = 0xC9;
+sbit CP_RL2C = 0xC8;
+
 /*  IE   */
 sbit EA   = 0xAF;
 sbit ES   = 0xAC;
index ca1bbaf2f05a0945aebef6ed7afb49af45d7441e..1710d8eeff612747f8a9ef0226af6f13181332a0 100644 (file)
@@ -23,6 +23,12 @@ sfr at 0xA8 IE;
 sfr at 0xB8 IP;
 sfr at 0x98 SCON;
 sfr at 0x99 SBUF;
+/* 8052 */
+sfr at 0xC8 T2CON;
+sfr at 0xCA RCAP2L;
+sfr at 0xCB RCAP2H;
+sfr at 0xCC TL2;
+sfr at 0xCD TH2;
 
 /*  BIT Register  */
 /*  PSW   */
@@ -44,6 +50,16 @@ sbit at 0x8A IT1;
 sbit at 0x89 IE0;
 sbit at 0x88 IT0;
 
+/* T2CON (8052) */
+sbit at 0xCF TF2;
+sbit at 0xCE EXF2;
+sbit at 0xCD RCLK;
+sbit at 0xCC TCLK;
+sbit at 0xCB EXEN2;
+sbit at 0xCA TR2;
+sbit at 0xC9 C_T2;
+sbit at 0xC8 CP_RL2C;
+
 /*  IE   */
 sbit at 0xAF EA;
 sbit at 0xAC ES;