dreamstack/devices/waveshare-p4-panel/main/ds_protocol.h

94 lines
3.3 KiB
C

/**
* DreamStack Bitstream Protocol — C port for ESP32-P4
*
* Ported from engine/ds-stream/src/protocol.rs
* Header format and frame types for the thin client.
*/
#pragma once
#include <stdint.h>
// ─── Magic bytes ───
#define DS_MAGIC_0 0xD5
#define DS_MAGIC_1 0x7A
// ─── Header size ───
#define DS_HEADER_SIZE 16
// ─── Frame types (output: source → receiver) ───
#define DS_FRAME_PIXELS 0x01 // Raw RGBA pixel data
#define DS_FRAME_COMPRESSED 0x02 // PNG/WebP compressed
#define DS_FRAME_DELTA 0x03 // XOR delta from previous
#define DS_FRAME_SIGNAL_SYNC 0x10 // Full signal state (JSON)
#define DS_FRAME_SIGNAL_DIFF 0x11 // Changed signals (JSON)
#define DS_FRAME_SCHEMA 0x12 // Schema announcement
#define DS_FRAME_KEYFRAME 0xF0 // Reset state
#define DS_FRAME_PING 0xFE // Heartbeat
#define DS_FRAME_END 0xFF // Stream end
// ─── Input types (receiver → source) ───
#define DS_INPUT_POINTER 0x01
#define DS_INPUT_KEY 0x02
#define DS_INPUT_SCROLL 0x03
#define DS_INPUT_TOUCH 0x04
#define DS_INPUT_GAMEPAD_AXIS 0x10
#define DS_INPUT_GAMEPAD_BTN 0x11
#define DS_INPUT_TEXT 0x20
// ─── Flags ───
#define DS_FLAG_INPUT 0x01
#define DS_FLAG_KEYFRAME 0x02
#define DS_FLAG_COMPRESSED 0x04
// ─── Frame header (16 bytes, little-endian) ───
typedef struct __attribute__((packed)) {
uint8_t magic[2]; // DS_MAGIC_0, DS_MAGIC_1
uint8_t frame_type; // DS_FRAME_* or DS_INPUT_*
uint8_t flags; // DS_FLAG_*
uint16_t seq; // Sequence number
uint32_t timestamp; // Milliseconds
uint16_t width; // Frame width (pixels)
uint16_t height; // Frame height (pixels)
uint16_t payload_len; // Following payload length
} ds_header_t;
// ─── Touch event (6 bytes) ───
typedef struct __attribute__((packed)) {
uint8_t id; // Touch identifier (multi-touch)
uint16_t x; // X coordinate
uint16_t y; // Y coordinate
uint8_t phase; // 0=start/move, 1=end, 2=cancel
} ds_touch_event_t;
/**
* Parse a header from raw bytes.
* Returns 0 on success, -1 if magic doesn't match.
*/
static inline int ds_parse_header(const uint8_t *buf, ds_header_t *hdr) {
if (buf[0] != DS_MAGIC_0 || buf[1] != DS_MAGIC_1) return -1;
*hdr = *(const ds_header_t *)buf;
return 0;
}
/**
* Encode a touch input message into a buffer.
* Buffer must be at least DS_HEADER_SIZE + sizeof(ds_touch_event_t) = 22 bytes.
* Returns total message size.
*/
static inline size_t ds_encode_touch(uint8_t *buf, uint16_t seq,
uint32_t timestamp,
const ds_touch_event_t *touch) {
ds_header_t *hdr = (ds_header_t *)buf;
hdr->magic[0] = DS_MAGIC_0;
hdr->magic[1] = DS_MAGIC_1;
hdr->frame_type = DS_INPUT_TOUCH;
hdr->flags = DS_FLAG_INPUT;
hdr->seq = seq;
hdr->timestamp = timestamp;
hdr->width = 0;
hdr->height = 0;
hdr->payload_len = sizeof(ds_touch_event_t);
*(ds_touch_event_t *)(buf + DS_HEADER_SIZE) = *touch;
return DS_HEADER_SIZE + sizeof(ds_touch_event_t);
}