]> git.llucax.com Git - z.facultad/66.09/etherled.git/commitdiff
Implementa el protocolo ELP sobre UDP. Tiene problemas cuando los leds estan
authorLeandro Lucarella <llucax@gmail.com>
Tue, 13 Dec 2005 07:36:01 +0000 (07:36 +0000)
committerLeandro Lucarella <llucax@gmail.com>
Tue, 13 Dec 2005 07:36:01 +0000 (07:36 +0000)
'dibujando', la red se comporta de manera rara (no funciona bien).

doc/protocolo.txt
src/Makefile
src/elp.c [new file with mode: 0644]
src/elp.h [new file with mode: 0644]
src/leds.asm
src/leds.h
src/main.c

index a55bf5b541c4167afce755da3d8d3b42374cdbad..fb925bcf80b3e150e9d3e62ca916e41b3d7134e1 100644 (file)
@@ -45,21 +45,22 @@ ACK al mismo paquete recibido (s
 
 Paquete ELP
 -----------
-
+0                1                                N
 +----------------+--------------------------------+
 |    CABECERA    |        DATOS (opcional)        |
 +----------------+--------------------------------+
-/---- 1 byte ----/---------- 0-64 bytes ----------/
+/---- 1 byte ----/----------- Variable -----------/
 
 
 CABECERA
 --------
 La cabecera está compuesta por los siguientes campos:
 
-+-----+--------------------+---------------+
-| GS  |        VAR         |      ID       |
-+-----+--------------------+---------------+
-/- 1 -/------ 4 bits ------/--- 3 bits ----/
+   7     6     5     4     3     2     1     0
++-----+-----------------------+-----------------+
+| GS  |        VAR            |      ID         |
++-----+-----------------------+-----------------+
+/- 1 -/------- 4 bits --------/---- 3 bits -----/
 
 GS:
        Este bit indica si la operación es GET (0) o SET (1).
@@ -104,8 +105,11 @@ Variables Definidas
     |             |                  | contenido de la matriz organizado
     |             |                  | como se indica en la sección Matriz
 ----+-------------+------------------+------------------------------------------
-  2 | DRAW        | Prendido/apagado | 1 byte con conteniendo 0xFF para prender
-    |             | del dibujado     | o con 0x00 para apagar
+  2 | PAUSE       | Pausa el dibuja- | 1 byte contenido 0x00 para reanudar el    
+    |             | do de la matriz  | dibujado, cualquier otro para pausarlo
+----+-------------+------------------+------------------------------------------
+  3 | DELAY       | Tiempo de retar- | 1 byte sin signo con la cantidad de 0.05
+    |             | do del dibujado  | ms a esperar entre refresco de columnas
 ----+-------------+------------------+------------------------------------------
 
 El resto de las variables quedan para futuras extensiones.
index b7ca2841af27f273110cb6726ff22759e09cceca..d51639d20b8572bd12895bd6d2b9e53d16059bd3 100644 (file)
@@ -15,7 +15,7 @@ LDFLAGS=-cn
 SHELL=bash
 
 # Archivos
-cmodules=main dp8390 eth ip udp
+cmodules=main dp8390 eth ip udp elp
 amodules=leds
 modules=$(cmodules) $(amodules)
 
@@ -35,6 +35,8 @@ ip.h: types.h
 
 udp.h: types.h
 
+elp.h: types.h
+
 dp8390.asm: dp8390.c dp8390.h debug.h eth.h
 dp8390.rel: dp8390.asm
 
@@ -47,7 +49,10 @@ 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
+elp.asm: elp.c elp.h leds.h udp.h netdev.h debug.h
+elp.rel: elp.asm
+
+main.asm: main.c leds.h reg51.h netdev.h eth.h ip.h udp.h elp.h debug.h
 main.rel: main.asm
 
 leds.rel: leds.asm
diff --git a/src/elp.c b/src/elp.c
new file mode 100644 (file)
index 0000000..6a2a654
--- /dev/null
+++ b/src/elp.c
@@ -0,0 +1,133 @@
+// vim: set et sw=4 sts=4 :    
+
+#include "debug.h"
+#include "elp.h"
+#include "reg51.h"
+#include "leds.h"
+#include "netdev.h"
+#include "udp.h"
+
+struct elp_command_t elp_command;
+
+byte elp_read_process_command()
+{
+    byte i;
+    byte len = ELP_HEADER_SIZE;
+    netdev_read_start(ELP_HEADER_SIZE);
+    // Escribimos el bitfield a lo guapo como un byte.
+    *((byte*) &elp_command) = udp_read_byte();
+    netdev_read_end();
+
+    printb(*((byte*) &elp_command), 0x01);
+
+    // Si es un SET lo proceso
+    switch (elp_command.var)
+    {
+        case ELP_VAR_OFF:
+            // Si es GET, sólo calculamos tamaño de respuesta
+            if (!elp_command.set)
+                return 0; // En este caso no tiene sentido un GET
+            // Si es SET procesamos (apagamos las luces y nos vamos a dormir)
+            leds_write(0x0000); // Apago leds
+            EA = 0; // Ignoramos interrupciones (por si el micro no soporta PD)
+            PCON = 0x02; // Bit PD (Power Down) prendido
+            while (1); // Nos negamos a seguir trabajando ( " )
+            // FIXME: No es del todo elegante esto, porque nunca vamos a
+            // responder el paquete
+
+        case ELP_VAR_MATRIX:
+            // Si es GET, sólo calculamos tamaño de respuesta
+            if (!elp_command.set)
+                // Vamos a devolver la matriz (2 bytes por columna) y su tamaño
+                return len + sizeof(leds_matrix_len) + leds_matrix_len * 2;
+            // Si es SET procesamos
+            netdev_read_start(sizeof(leds_matrix_len)); // tamaño
+            i = udp_read_byte();
+            netdev_read_end();
+            // Verifico cantidad de columnas
+            if ((LEDS_MIN_COLS < i) || (i < LEDS_MAX_COLS))
+                return 0;
+            leds_matrix_len = i;
+            netdev_read_start(leds_matrix_len * 2); // matriz
+            for (i = 0; i < leds_matrix_len; ++i)
+            {
+                byte low = udp_read_byte();
+                leds_matrix[i] = WORD(udp_read_byte(), low);
+            }
+            netdev_read_end();
+            leds_delay_update(); // Seteamos un delay bueno
+            return len;
+    
+        case ELP_VAR_PAUSE:
+            // Si es GET, sólo calculamos tamaño de respuesta
+            if (!elp_command.set)
+                return len + 1 /* booleano de 1 byte */;
+            // Si es SET procesamos
+            netdev_read_start(1); // booleano de 1 byte
+            //XXX if (udp_read_byte() == 0x00) // si viene 0 reanuda
+                //XXX TR2 = 1;
+            //XXX else
+            if (udp_read_byte() != 0x00)
+            {
+                TR2 = 0;
+                leds_write(0x0000); // Si pausa apaga leds
+            }
+            netdev_read_end();
+            return len;
+    
+        case ELP_VAR_DELAY:
+            // Si es GET, sólo calculamos tamaño de respuesta
+            if (!elp_command.set)
+                return len + sizeof(leds_delay);
+            // Si es SET procesamos
+            netdev_read_start(sizeof(leds_delay));
+            leds_delay = udp_read_byte();
+            netdev_read_end();
+            return len;
+
+        default:
+            // Desconocido
+            return 0;
+    }
+}
+
+void elp_write_response()
+{
+    byte i;
+    // Escribimos cabecera
+    netdev_write_start(ELP_HEADER_SIZE);
+    // Escribimos el bitfield a lo guapo como un byte.
+    udp_write_byte(*((byte*) &elp_command));
+    netdev_write_end();
+    // Si era un SET acá termino nuestro trabajo, nunca tiene datos
+    if (elp_command.set)
+        return;
+    // Si era un GET escribimos lo que nos pidieron
+    switch (elp_command.var)
+    {
+        case ELP_VAR_MATRIX:
+            // Transferimos tamaño (1 byte) + matriz (2 bytes por columna)
+            netdev_write_start(sizeof(leds_matrix_len) + leds_matrix_len * 2);
+            udp_write_byte(leds_matrix_len);
+            for (i = 0; i < leds_matrix_len; ++i)
+            {
+                udp_write_byte(LOW(leds_matrix[i]));
+                udp_write_byte(HIGH(leds_matrix[i]));
+            }
+            netdev_write_end();
+            break;
+
+        case ELP_VAR_PAUSE:
+            netdev_write_start(1 /* booleano de 1 byte */);
+            udp_write_byte(!TR2);
+            netdev_write_end();
+            break;
+
+        case ELP_VAR_DELAY:
+            netdev_write_start(sizeof(leds_delay));
+            udp_write_byte(leds_delay);
+            netdev_write_end();
+            break;
+    }
+}
+
diff --git a/src/elp.h b/src/elp.h
new file mode 100644 (file)
index 0000000..d08b663
--- /dev/null
+++ b/src/elp.h
@@ -0,0 +1,46 @@
+// vim: set et sw=4 sts=4 :    
+
+#ifndef _ELP_H_
+#define _ELP_H_
+
+#include "types.h"
+
+/** @file
+ * Protocolo de etherled (elp == Etherled Protocol).
+ *
+ * Ver archivo protocolo.txt en la documentación.
+ */
+
+/** Puerto UDP usado por el protocolo ELP */
+#define ELP_PORT 9876u
+
+/** Variables del comando */
+#define ELP_VAR_OFF     0
+#define ELP_VAR_MATRIX  1
+#define ELP_VAR_PAUSE   2
+#define ELP_VAR_DELAY   3
+
+/** Comando recibido/a enviar */
+extern struct elp_command_t
+{
+    byte id:  3; ///< Identificador del paquete
+    byte var: 4; ///< Variable a leer/escribir
+    byte set: 1; ///< SET (1) / GET (0)
+}
+elp_command;
+
+/** Tamaño de la cabecera ELP */
+#define ELP_HEADER_SIZE (sizeof(struct elp_command_t))
+
+/** Procesa un comando ELP.
+ * @precond Se ejecutó netdev_recv_start().
+ * @returns cantidad de bytes escritos, 0 indica error o comando no soportado.
+ */
+byte elp_read_process_command();
+
+/** Escribe la respuesta al comando.
+ * @precond Se ejecutó netdev_send_start().
+ */
+void elp_write_response();
+
+#endif /* _ELP_H_ */
index bc729f119f8ad42b40793e2e657a8fd8542f2848..db579cdb008f9db1b6535d980c759584c0ee832b 100644 (file)
@@ -24,9 +24,9 @@ LEDS_MAX_COLS    = 32       ; Cantidad máxima de columnas
 
 ; 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
+INTERVAL        = 65000 ; 0.05ms (por el clock de 8MHz)
+LEDS_LOW        = 0x0080
+LEDS_HIGH       = 0x00c0
 DELAY_BASE      = 28 ; 16 columnas anda bien con 28 - (len / 2) == 20
 
 ; Área de bancos de registros
@@ -89,7 +89,7 @@ _leds_init::
     mov     r2, a ; tamaño en bytes de la matriz
 
     ; Cargo milisegundos
-    acall   _leds_delay_update
+    lcall   _leds_delay_update
     mov     delay, _leds_delay
 
     ; copio imagen por default de la ROM a la RAM
@@ -130,20 +130,20 @@ proximo$:
 _leds_test::
     ; escribo patrones en los leds
     mov     dptr, #0xffff
-    acall   _leds_write
-    acall   sleep
+    lcall   _leds_write
+    lcall   sleep
 
     mov     dptr, #0xaaaa
-    acall   _leds_write
-    acall   sleep
+    lcall   _leds_write
+    lcall   sleep
     
     mov     dptr, #0x5555
-    acall   _leds_write
-    acall   sleep
+    lcall   _leds_write
+    lcall   sleep
 
     mov     dptr, #0x0000
-    acall   _leds_write
-    acall   sleep
+    lcall   _leds_write
+    lcall   sleep
     
     ret    
 
@@ -213,7 +213,7 @@ _leds_delay_update::
     mov     dpl, a
     mov     a, #DELAY_BASE
     subb    a, dpl
-    mov     _leds_matrix_len, a
+    mov     _leds_delay, a
     ret
     
 
@@ -253,16 +253,16 @@ _leds_timer2_isr::
     add     a, r0 ; le sumo al puntero el offset actual segun la columna
     mov     r0, a
 
-    ; imprimo en LEDS_LOW
+    ; imprimo en LEDS_HIGH
     mov     a, @r0 ; leo el contenido de la matriz
-    mov     dptr, #LEDS_LOW
+    mov     dptr, #LEDS_HIGH
     cpl     a ; complemento para ver encendidos los "1"
     movx    @dptr, a
 
-    ; imprimo en LEDS_HIGH
+    ; imprimo en LEDS_LOW
     inc     r0     ; busco proximo byte de la columna
     mov     a, @r0 ; leo el contenido de la matriz
-    mov     dptr, #LEDS_HIGH
+    mov     dptr, #LEDS_LOW
     cpl     a ; complemento para ver encendidos los "1"
     movx    @dptr, a
 
@@ -302,39 +302,56 @@ DEFAULT_MATRIX_LEN:
     ;.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     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     0b0000011111100000
+    .dw     0b0001111111111000
+    .dw     0b0011100000011100
+    .dw     0b0111110000000110
+    .dw     0b0110111000000110
+    .dw     0b1100011100000011
+    .dw     0b1100001110000011
+    .dw     0b1111111111111111
+    .dw     0b1111111111111111
+    .dw     0b1100001110000011
+    .dw     0b1100011100000011
+    .dw     0b0110111000000110
+    .dw     0b0111110000000110
+    .dw     0b0011100000011100
+    .dw     0b0001111111111000
+    .dw     0b0000011111100000
+
+;    .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
index 188978b7fe77aec36e70aab87686e34bb6526183..b24a6d632618ca99435ecd76dc9c0c657a138a86 100644 (file)
@@ -3,6 +3,9 @@
 #ifndef _LEDS_H_
 #define _LEDS_H_
 
+/** Cantidad mínima de columnas (es más un límite estético que físico) */
+#define LEDS_MIN_COLS 8
+
 /** Cantidad máxima de columnas */
 #define LEDS_MAX_COLS 32
 
@@ -10,7 +13,7 @@
 extern unsigned char leds_matrix_len;
 
 /** Matriz de leds, cada elemento del array es una columna */
-extern unsigned int leds_matrix[LEDS_MAX_COLS];
+extern idata unsigned int leds_matrix[LEDS_MAX_COLS];
 
 /** Retardo de refresco de la matriz (en múltiplos de 0.1ms) */
 extern unsigned char leds_delay;
index f980df1fb630c10f9d10b7c4669bb80017a34f83..69e0a54476655f3d405dd2a6e904b65e0c419651 100644 (file)
@@ -7,6 +7,7 @@
 #include "eth.h"
 #include "ip.h"
 #include "udp.h"
+#include "elp.h"
 
 void main(void)
 {
@@ -26,7 +27,7 @@ void main(void)
 
     // Comienza a 'dibujar'
     EA  = 1; // Habilita interrupciones globalmente
-    TR2 = 1; // Pone a correr el 'dibujado'
+    //XXX TR2 = 1; // Pone a correr el 'dibujado'
 
     // Inicializo IP
     ip_addr_local[0] = 10;
@@ -35,24 +36,20 @@ void main(void)
     ip_addr_local[3] = 100;
 
     // Inicializo puerto UDP
-    udp_port_local = 9876;
+    udp_port_local = ELP_PORT;
 
     while (1) // Forever
     {
-        byte i; //XXX
-        byte len;
-
-        len = netdev_recv_start();
+        byte len = netdev_recv_start();
+        //printb(len, 0x10);
         if (!len) // no recibimos nada (válido)
             continue; // Probamos de nuevo
 
         // Tenemos algo!
-        //print(0x2);
 
         // Parseamos cabecera ethernet
         if (!eth_read_frame_header()) // No es un buen header
             goto drop; // Tiramos el paquete
-        //print(0x4);
 
         // Vemos que protocolo transporta
         switch (eth_proto)
@@ -61,11 +58,9 @@ void main(void)
                 goto drop; // Tiramos el paquete
 
             case ETH_IP:
-                //print(0x8);
                 // Parseamos cabecera IP
                 if (!ip_read_packet_header()) // No es un buen header
                     goto drop; // Tiramos el paquete
-                //print(0x10);
 
                 // Vemos que protocolo transporta
                 switch (ip_proto)
@@ -74,37 +69,49 @@ void main(void)
                         goto drop; // Tiramos el paquete
 
                     case IP_UDP:
-                        //print(0x20);
                         // Parseamos cabecera UDP
                         if (!udp_read_dgram_header()) // No es un buen header
                             goto drop; // Tiramos el paquete
 
-                        //printb(udp_dgram_len, 0x40);
-                        // TODO
-                        // 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)
-                            leds_matrix[i] = udp_read_byte();
-                        netdev_read_end();
+                        // Procesamos comando ELP y obtenemos tamaño de la
+                        // respuesta
+                        len = elp_read_process_command();
+                        printb(len, 0x02);
+
+                        // Si el tamaño es 0, hubo error o no está soportado
+                        if (!len)
+                            goto drop;
+                        print(0x0004);
+
+                        // FIXME por ahora no tenemos forma de 'abortar' el
+                        // comando si el checksum es incorrecto, lo verificamos
+                        // por deporte.
                         if (!udp_checksum_ok())
                             goto drop;
+                        print(0x0008);
+
+                        // Terminamos recepción
                         netdev_recv_end();
+                        print(0x0010);
 
                         // Respuesta
                         netdev_send_start();
                         eth_write_frame_header();
-                        //udp_dgram_len = UDP_HEADER_SIZE+len;
-                        //ip_packet_len = IP_HEADER_SIZE+udp_dgram_len;
+                        ip_packet_len = UDP_HEADER_SIZE + len;
+                        printb(ip_packet_len, 0x20);
                         ip_write_packet_header();
+                        udp_dgram_len = len;
+                        printb(udp_dgram_len, 0x40);
                         udp_write_dgram_header();
-                        netdev_write_start(len);
-                        for (i = 0; i < len; ++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);
+                        elp_write_response();
+                        udp_write_checksum(ETH_HEADER_SIZE + IP_HEADER_SIZE);
+                        netdev_send_end(ETH_HEADER_SIZE + IP_HEADER_SIZE
+                                + UDP_HEADER_SIZE + len);
+                        printb(ETH_HEADER_SIZE + IP_HEADER_SIZE
+                                + UDP_HEADER_SIZE + len, 0x80);
+                        //XXX
+                        if (elp_command.set && (elp_command.var == ELP_VAR_PAUSE))
+                            TR2 = 1;
                 }
         }
         continue;