94 lines
3.3 KiB
C
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);
|
|
}
|