12.3. El formato de paquete¶
Cada byte que cruza el cable entre la cámara y el anfitrión forma parte de un paquete. Un paquete comienza con un encabezado de 10 bytes, contiene una carga de longitud variable y termina con un CRC final de 4 bytes. No aparecen otros bytes en el cable – una vez que el anfitrión ha visto la palabra de sincronización de 2 bytes, los siguientes bytes son un encabezado en esta secuencia exacta.
12.3.1. El encabezado¶
Diez bytes, empaquetados sin relleno. Cada campo:
sync– la palabra de 16 bits0xD5AAen orden little-endian. El byte 0 en el cable es0xAA, el byte 1 es0xD5. Un receptor que examina los bytes puede encontrar el inicio de un paquete buscando el parAA D5; cualquier cosa anterior se trata como basura. La elección del valor es deliberada:0xAAy0xD5rara vez aparecen en texto imprimible, y es improbable que el par aparezca por accidente en medio de una carga.seq– un byte. Un contador que se incrementa en uno por cada paquete enviado en una dirección dada. El receptor comprueba que el número de secuencia del siguiente paquete sea el esperado; si no, la capa de fiabilidad pide una retransmisión.chan– un byte. El ID del canal al que pertenece este paquete. Los canales 0..31 son utilizables; los canales integradosstdin,stdout,streamy (opcionalmente)profiletoman IDs fijos que la cámara reserva.flags– un byte. Un campo de bits que indica al receptor cómo interpretar el paquete:bit 0
ACK– este paquete es una confirmación de uno anterior.bit 1
NAK– este paquete rechaza uno anterior.bit 2
RTX– este paquete es una retransmisión.bit 3
ACK_REQ– el remitente quiere que este paquete sea confirmado.bit 4
FRAGMENT– siguen más fragmentos a este dentro de un mensaje mayor.bit 5
EVENT– este paquete lleva un evento de canal en lugar de datos.los bits 6 y 7 están reservados.
opcode– un byte. El código de comando o de respuesta. La biblioteca de protocolo reserva rangos de códigos de operación según su propósito:0x00..0x0F– comandos de protocolo (SYNC, GET_CAPS, SET_CAPS, STATS, VERSION).0x10..0x1F– comandos de sistema (RESET, BOOT, INFO, EVENT, MEMORY).0x20..0x2F– comandos de canal (LIST, POLL, LOCK, UNLOCK, SHAPE, SIZE, READ, WRITE, IOCTL, EVENT).
len– dos bytes, little-endian. El número de bytes de carga que siguen al encabezado. Una longitud de cero es legal – muchas confirmaciones y comandos pequeños no llevan carga.crc– dos bytes. Un CRC-16 sobre los ocho bytes anteriores del encabezado. Un receptor que recibe un encabezado con un CRC erróneo descarta el paquete completo sin siquiera mirar la carga.
12.3.2. La carga¶
Cero o más bytes, tratados como opacos por la capa de encuadre. Lo que hay en la carga depende del código de operación: para una respuesta CHANNEL_READ son los datos reales del canal; para una respuesta GET_CAPS es una pequeña estructura fija; para una escritura de canal es lo que sea que el anfitrión envió.
El tamaño máximo de la carga depende del tamaño del búfer de protocolo de la cámara (consulta la tabla por placa en protocol.init()). Los mensajes más largos que el tope se dividen en fragmentos con el indicador FRAGMENT activado en todos menos en el último.
12.3.3. El CRC final¶
Cuatro bytes, un CRC-32 sobre la carga. Detecta la corrupción que el CRC del encabezado no puede ver, en particular en cargas largas donde un error de un solo bit a mitad del fotograma se colaría de otro modo.
Dividir la comprobación de integridad entre dos CRC es deliberado. El CRC del encabezado protege los propios campos de encuadre – en particular la longitud de la carga. Sin un CRC de encabezado separado, un solo cambio de bit en el byte de longitud haría que el receptor leyera un número incorrecto de bytes para la carga y se desincronizara del flujo de bytes por completo; con él, un encabezado dañado se rechaza de inmediato y el receptor vuelve a buscar la siguiente palabra de sincronización. El CRC de la carga protege entonces el cuerpo del mensaje como un asunto aparte, de modo que un cambio de bit en los datos se informa como una carga corrupta en lugar de confundirse con un error de encuadre.
El formato es lo bastante pequeño como para recorrerlo byte a byte, y el hecho de que cada paquete tenga la misma disposición – sincronización, luego encabezado, luego carga, luego CRC – significa que un analizador hecho a mano cabe en una pantalla de código. Por eso una pequeña implementación de anfitrión en C, Python o Rust es un proyecto de fin de semana; la biblioteca de protocolo es la versión de Python mantenida en cada lado.