petherled - Protocolo de comunicación del dispositivo etherled ============================================================== Objetivo -------- El objetivo del protocolo de comunicación con el dispositivo etherled es que sea de lo más simple para el dispositivo, dejando la mayor responsabilidad posible en el cliente (PC que se conecta al dispositivo). Además tiene como objetivo la simplicidad y la minimización de los datos a enviar (requerimientos de buffer). Introducción ------------ Este protocolo está pensado para funcionar sobre UDP, es por esto que posee algunos mecanismos básicos para control de errores y confirmación de entrega. Para esto utiliza un identificador de paquete pequeño por cada tipo de operación y un CRC que abarca tanto a la cabecera como a los datos. El identificador de paquete se utiliza para saber a que paquete pertenece una respuesta. El protocolo, como se dijo anteriormente diferencia bien entre el dispositivo etherled (servidor) y la PC u otro dispositivo que le envía comandos (cliente). Es por esto que un mismo comando puede tener distinta semántica según su dirección (cliente->servidor o servidor->cliente). Incluso cambia la conformación del paquete según su dirección. El protocolo se trata básicamente de un mecanismo para establecer u obtener el valor de ciertas variables del dispositivo (servidor). Por tanto define esas variables e indica que tipo de operación se está llevando a cabo sobre ellas: GET o SET. GET indica que el cliente va a obtener el valor de la variable y SET que va a establecerlo. Las operaciones de GET no tienen parámetros extra (Datos) cuando van en dirección cliente->servidor pero sí cuando van en dirección inversa (servidor->cliente). Las operaciones SET se comportan exactamente de modo inverso. Toda operación tiene una respuesta idéntica (excepto por los datos). Es decir, si el cliente envía un SET de una variable VAR al servidor, con los datos DATA y con identificador ID, el servidor responderá con otro paquete SET con la variable VAR, con identificador ID pero sin datos. Es decir, se utiliza como ACK al mismo paquete recibido (sólo que sin los datos). Paquete petherled ----------------- +----------------+--------------------------------+----------------+ | Cabecera | Datos (opcional) | CRC | +----------------+--------------------------------+----------------+ /---- 1 byte ----/---------- 0-64 bytes ----------/---- 1 byte ----/ Cabecera -------- La cabecera está compuesta por los siguientes campos: +-----+--------------------+---------------+ | GS | Variable | Identificador | +-----+--------------------+---------------+ /- 1 -/------ 4 bits ------/--- 3 bits ----/ GS: Este bit indica si la operación es GET (0) o SET (1). Variable: Es un número de 0 a 15 que indica la variable sobre la cual se está operando. Ver sección Variables Definidas. Identificador: Es un número de 0 a 7 que indentifica al paquete. Para extender la cantidad de identificadores efectivos disponibles, se utiliza un contador por cada tupla (GS,Variable), por lo tanto, en el caso ideal de que las operaciones estén perfectamente distribuidas entre todas las variables y GET y SET, se tendría una cantidad de indentificadores efectivos de 8 bits completo (256 posibilidades). Datos ----- Los datos se envían para cada operación SET en sentido cliente->servidor y para cada operación GET en sentido contrario (servidor->cliente). Pueden haber variables que no posean datos en absoluto (una variable booleana tipo switch). Los datos no son codificados de ninguna manera en particular, ya que la cantidad de datos enviados está predefinido para cada Variable (ver sección Variables Definidas). CRC --- El CRC es de un byte y se utiliza el mismo CRC que utiliza IP y UDP (complemento a 1 de la suma). Se aplica tanto a las cabeceras como a los datos (de existir) y al mismo CRC. A efectos de calcular el CRC, se toma el CRC como todo en 0. Variables Definidas ------------------- Id | Nombre | Descripción | Datos ----+-------------+------------------+------------------------------------------ 0 | Matriz | Matriz a dibujar | 1 byte para la cantidad de columnas | | | (ancho) más 2*ancho bytes con el | | | contenido de la matriz organizado | | | como se indica en la sección Matriz ----+-------------+------------------+------------------------------------------ 1 | Funcionando | Prendido/apagado | 1 byte con conteniendo 0xFF para prender | | del dispositivo | o con 0x00 para apagar ----+-------------+------------------+------------------------------------------ El resto de las variables quedan para futuras extensiones. Matriz ------ Para convertir la matriz a un array de bits se utiliza el siguiente esquema: Suponemos una matriz chica, de 4x4 para simplificar el ejemplo. Para organizar dicha matriz como un array de bits, simplemente hay que rotarla en sentido antihorario y recorrer por filas de arriba hacia abajo (agrupando por bytes). 7 6 5 4 3 2 1 0 cols filas 7 6 5 4 3 2 1 0 +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 7 | | | | | | | | | 0 | | | | | | | | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 6 | | | | | | | | | 1 | | | | | | | | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 5 | | | | | | | | | 2 | | | | | | | | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 4 | | | | | | | | | 3 | | | | | | | | | +---+---+---+---+---+---+---+---+ ======> +---+---+---+---+---+---+---+---+ 3 | | | | | | | | | 4 | | | | | | | | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 2 | | | | | | | | | 5 | | | | | | | | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 1 | | | | | | | | | 6 | | | | | | | | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ 0 | | | | | | | | | 7 | | | | | | | | | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ filas cols Quedando por resultado las columnas desde la 0 a la 7 en cada byte del stream de bits: +-----+-----+-----+-----+-----+-----+-----+-----+ | 7,0 | 6,0 | 5,0 | 4,0 | 3,0 | 2,0 | 1,0 | 0,0 | byte 0 == col 0 +-----+-----+-----+-----+-----+-----+-----+-----+ +-----+-----+-----+-----+-----+-----+-----+-----+ | 7,1 | 6,1 | 5,1 | 4,1 | 3,1 | 2,1 | 1,1 | 0,1 | byte 1 == col 1 +-----+-----+-----+-----+-----+-----+-----+-----+ etc., etc., etc. En el protocolo la cantidad de filas es _SIEMPRE_ 16, ya que está limitada físicamente por la cantidad de leds del dispositivo. Por lo tanto, siempre tendremos agrupada cada columna en 2 bytes. Es decir, el stream de bits será: HIGH(col0), LOW(col0), HIGH(col1), LOW(col1), ... , HIGH(colN), LOW(colN) Siendo HIGH(colI) la parte alta de la columan I y LOW(colI) su parte baja.