Skip to content

Latest commit

 

History

History
420 lines (346 loc) · 24.1 KB

PROTOCOL.md

File metadata and controls

420 lines (346 loc) · 24.1 KB

CYD/1 binary protocol

English | Русский

English

CYD/1 is a bidirectional binary protocol between a PureBasic application and the ESP32-CYD firmware. Multi-byte integers are little-endian.

Packet

Offset Size Field
0 1 Magic 0x43 (C)
1 1 Magic 0x59 (Y)
2 1 Protocol version (1)
3 1 Message type
4 2 Sequence number
6 2 Payload length, 0..4096
8 N Payload
8+N 2 CRC-16/CCITT-FALSE over bytes 2..7 and payload

CRC parameters: polynomial 0x1021, initial value 0xFFFF, no reflection, no final XOR.

The length field makes all byte values legal inside images and audio. A receiver that encounters an invalid header, length, or CRC searches for the next CY magic pair.

Host commands

Type Name Payload
0x01 HELLO empty
0x02 PING empty
0x10 SET_ORIENTATION orientation:u8
0x11 SET_BRIGHTNESS brightness:u8
0x12 CLEAR rgb565:u16
0x13 FILL_RECT x:u16 y:u16 w:u16 h:u16 rgb565:u16
0x14 BLIT_RGB565 x:u16 y:u16 w:u16 h:u16 pixels:w*h*u16
0x15 DRAW_PIXEL x:i16 y:i16 color:u16
0x16 DRAW_LINE x1:i16 y1:i16 x2:i16 y2:i16 color:u16
0x17 DRAW_RECT x:i16 y:i16 w:u16 h:u16 color:u16 filled:u8
0x18 DRAW_CIRCLE x:i16 y:i16 radius:u16 color:u16 filled:u8
0x19 DRAW_TRIANGLE x1:i16 y1:i16 x2:i16 y2:i16 x3:i16 y3:i16 color:u16 filled:u8
0x1A DRAW_TEXT x:i16 y:i16 color:u16 background:u16 scale:u8 opaque:u8 text:utf8
0x1B SCROLL_START x:i16 y:i16 w:u16 h:u16 color:u16 background:u16 scale:u8 direction:u8 speed:u16 text:utf8
0x1C SCROLL_STOP clear_viewport:u8
0x1D DRAW_BUTTON x:i16 y:i16 w:u16 h:u16 radius:u8 color:u16 highlight:u16 shadow:u16 pressed:u8
0x1E DRAW_UTF8_TEXT x:i16 y:i16 w:u16 h:u16 color:u16 background:u16 font_height:u8 flags:u8 text:utf8
0x1F UPDATE_BAR_CHART x:i16 y:i16 w:u16 h:u16 background:u16 marker_color:u16 flags:u8 marker_height:u8 count:u16 entries
0x20 TOUCH_CONFIG enabled:u8 move_interval_ms:u16
0x21 TOUCH_CALIBRATE empty
0x22 TOUCH_RESET_CALIBRATION empty
0x23 TOUCH_CANCEL_CALIBRATION empty
0x24 TOUCH_RAW empty
0x25 MATRIX_START speed:u8 density:u8 tail_length:u8
0x26 MATRIX_STOP clear_screen:u8
0x27 MATRIX_CLOCK_START speed:u8 density:u8 tail_length:u8 style:u8 show_seconds:u8 language:u8 year:u16 month:u8 day:u8 hour:u8 minute:u8 second:u8
0x28 CLOCK_SAVER_START style:u8 show_seconds:u8 language:u8 year:u16 month:u8 day:u8 hour:u8 minute:u8 second:u8
0x30 AUDIO_TONE frequency_hz:u16 duration_ms:u16 volume:u8
0x31 AUDIO_BEGIN sample_rate:u16 volume:u8
0x32 AUDIO_DATA unsigned 8-bit mono PCM
0x33 AUDIO_END empty
0x34 AUDIO_STOP empty
0x35 AUDIO_MELODY volume:u8 notation:utf8
0x40 SD_INFO empty
0x41 SD_UPLOAD_BEGIN size:u32 overwrite:u8 path:utf8
0x42 SD_UPLOAD_DATA sequential file bytes
0x43 SD_UPLOAD_END empty
0x44 GIF_PLAY x:i16 y:i16 w:u16 h:u16 speed_percent:u16 loops:u16 background:u16 fit_mode:u8 path:utf8
0x45 GIF_PAUSE empty
0x46 GIF_RESUME empty
0x47 GIF_STOP clear_viewport:u8
0x48 MP3_PLAY volume:u8 loop:u8 path:utf8
0x49 MP3_PAUSE empty
0x4A MP3_RESUME empty
0x4B MP3_STOP empty
0x4C MEDIA_STATUS empty
0x4D SD_LIST start_index:u16 directory:utf8
0x4E SD_READ offset:u32 max_bytes:u16 path:utf8
0x4F SD_DELETE path:utf8
0x50 RGB_SET red:u8 green:u8 blue:u8
0x60 WIFI_SCAN_START show_hidden:u8
0x61 WIFI_SCAN_RESULTS start_index:u16
0x70 CLOCK_START year:u16 month:u8 day:u8 hour:u8 minute:u8 second:u8 x:i16 y:i16 scale:u8 color:u16 background:u16
0x71 CLOCK_STOP clear_viewport:u8
0x72 DATE_START same payload as CLOCK_START
0x73 DATE_STOP clear_viewport:u8
0x74 TIMER_START duration_seconds:u32 x:i16 y:i16 scale:u8 color:u16 background:u16
0x75 TIMER_STOP clear_viewport:u8

Orientation values:

  • 0: landscape, 320x240;
  • 1: reverse landscape, 320x240;
  • 2: portrait, 240x320;
  • 3: reverse portrait, 240x320.

RGB565 uses the conventional layout: red bits 15..11, green bits 10..5, blue bits 4..0. The ST7789 BGR wiring is handled exclusively by the firmware.

BLIT_RGB565 is deliberately limited to 4096 payload bytes. A host sends a large image as several horizontal strips. The firmware does not require a full-screen framebuffer.

QR codes are generated by CYD_DrawQRCode() in the PureBasic host framebuffer and transferred with the existing BLIT_RGB565 command. CYD/1 therefore needs no separate QR command.

The DRAW_* commands execute directly through Adafruit GFX and therefore do not transfer a host framebuffer. DRAW_TEXT uses the built-in 5x7 Adafruit font and remains the fastest ASCII path. DRAW_UTF8_TEXT uses bundled U8g2 fonts, decodes UTF-8, and includes Cyrillic. Its flags bit 0 centers text in the rectangle and bit 1 clears the rectangle with background before drawing. Supported requested font heights are 4..53 pixels and are mapped to the nearest bundled Cyrillic font.

UPDATE_BAR_CHART transfers all vertical bars in one acknowledged command. Each entry is value:u8 color:u16; values are clamped to 0..100. Flag bit 0 enables one-pixel gaps when slots are wide enough, bit 1 draws the preceding sample as a marker, and bit 2 forces a complete redraw. The firmware retains the preceding values and incrementally updates changed bar regions. The count is limited to 320 and cannot exceed the chart width.

MATRIX_START clears the display and starts a firmware-rendered Matrix-style effect that requires no continuing host traffic. speed and density accept 1..100; tail_length accepts 4..30 character cells. MATRIX_STOP optionally clears the display. A later display-owning command stops the effect automatically, while brightness and non-display service commands leave it running. These commands are available in firmware 0.15.0 and newer.

MATRIX_CLOCK_START (firmware 0.18.0+) starts the same autonomous effect and seeds its local calendar in one command. style=0 selects a digital face and style=1 a flip face; language=0 selects Russian and language=1 English. The ESP32 updates time, date, and weekday locally. Matrix glyphs do not enter the clock regions, and no touch instruction is drawn at the bottom.

CLOCK_SAVER_START (firmware 0.19.0+) starts the same digital or flip clock on a black background without Matrix. For both commands, show_seconds=0 removes seconds from the face and changes the time only once per minute. MATRIX_STOP also stops either autonomous clock-saver mode.

DRAW_BUTTON draws a filled rounded face with a directional highlight and shadow. With pressed=1, only the bevel is inverted; the face and a host-rendered label inside it remain untouched.

CLOCK_START and DATE_START seed the ESP32 with local calendar components from the host. The two elements have independent position and style state, while sharing the device-maintained calendar. They render HH:MM:SS and YYYY-MM-DD without further host traffic. TIMER_START renders a countdown as HH:MM:SS; durations are limited to 1..359999 seconds.

SCROLL_START allocates a local RGB565 canvas for the requested viewport and updates it at approximately 30 FPS. The viewport is limited to 30720 pixels and text to 255 UTF-8 bytes. After the command is acknowledged, no host traffic is needed to keep the animation running.

SD paths are UTF-8 absolute paths beginning with /; .. is rejected. Uploads are sequential, limited to 4 GB, and every data packet is acknowledged. In GIF_PLAY, loops=0 means infinite repeat, x/y=-1 centers the image, and a zero width/height selects the full display. The fit_mode byte follows background: 0=contain, 1=cover, 2=stretch. GIF and MP3 are mutually exclusive and are decoded locally from SD.

SD_LIST is paginated. The host starts at index zero and continues with the returned next index until done=1. SD_READ is request/response chunking, which preserves serial flow control while downloading files.

Device messages

Type Name Payload
0x80 ACK request_type:u8 status:u8
0x81 ERROR request_type:u8 error:u8
0x90 TOUCH_EVENT state:u8 x:u16 y:u16 pressure:u16 time_ms:u32
0x91 CALIBRATION_EVENT stage:u8 point:u8 total:u8 x:u16 y:u16 error:u16
0x92 INFO width:u16 height:u16 orientation:u8 capabilities:u16 name:utf8
0x93 SD_INFO mounted:u8 card_type:u8 total_mb:u32 used_mb:u32
0x94 MEDIA_STATUS type:u8 state:u8 error:u8 value:u8 path:utf8
0x95 SD_DATA total_size:u32 offset:u32 eof:u8 bytes
0x96 SD_LIST next_index:u16 done:u8 records
0x97 WIFI_SCAN_LIST status:u8 next_index:u16 done:u8 records
0x98 TOUCH_RAW pressed:u8 raw_x:u16 raw_y:u16 pressure:u16
0x99 TIMER_EVENT state:u8 duration_seconds:u32
0x9A MELODY_EVENT state:u8 duration_ms:u32

Each SD list record is directory:u8 size:u32 name_length:u8 name:utf8.

Each Wi-Fi record is rssi:i16 channel:u8 encryption:u8 bssid_length:u8 bssid:utf8 ssid_length:u8 ssid:utf8. Wi-Fi status values are 0=idle, 1=scanning, 2=complete, and 3=error. Results are paginated like SD lists.

Touch states are 1=down, 2=move, and 3=up.

Timer state 1 means that the countdown reached zero. The event is asynchronous and uses sequence number zero.

Melody state 1 means playback completed and state 2 means it was stopped. The asynchronous event uses sequence number zero. AUDIO_MELODY notation starts with BPM=20..400: and contains up to 128 notes separated by spaces or commas. Notes use [duration][.][note][#|b][octave]; duration defaults to 4 and may be 1, 2, 4, 8, 16, or 32. Notes are C, D, E, F, G, A, B/H, and P/R for a rest. Pitched notes require octave 1 through 7. A melody is limited to 1024 UTF-8 bytes and 300000 ms.

Calibration stages are:

  • 1: target displayed;
  • 2: calibration completed;
  • 3: calibration failed.
  • 4: calibration cancelled.
  • 5: raw calibration sample accepted (x/y contain raw ADC values).

Capability bits:

  • bit 0: touch;
  • bit 1: host-guided touch calibration is required and supported;
  • bit 2: tone output;
  • bit 3: unsigned 8-bit PCM output;
  • bit 4: device-side drawing commands;
  • bit 5: autonomous device-side scrolling;
  • bit 6: FAT32 SD storage and upload;
  • bit 7: autonomous GIF playback;
  • bit 8: MP3 playback from SD;
  • bit 9: PWM control of the onboard RGB LED;
  • bit 10: Wi-Fi network scanning;
  • bit 11: autonomous Clock, Date, and Timer;
  • bit 12: autonomous RTTTL-like melody playback;
  • bit 13: device-side primitive colors use BGR panel order; exchange the red and blue fields of host RGB565 colors before sending primitive commands;
  • bit 14: device-side UTF-8 text with bundled Cyrillic fonts;
  • bit 15: one-packet incremental vertical bar charts;

Responses

HELLO produces INFO. PING, control commands, and every BLIT_RGB565 strip produce ACK or ERROR. Waiting for each bitmap ACK provides flow control and prevents a PC serial driver from queuing an entire frame faster than the ESP32 can consume it. AUDIO_DATA is paced by the host and is not acknowledged. CRC errors are discarded because a damaged packet may not contain a trustworthy sequence number.

License

The CYD/1 project implementation and this specification are copyright (C) CheshirCa 2026, https://t.me/cheshircanest, and are distributed for non-commercial use under the complete terms in LICENSE.


Русский

CYD/1 — двусторонний бинарный протокол между приложением PureBasic и прошивкой ESP32-CYD. Многобайтовые целые передаются в порядке little-endian. Таблицы типов, имён и payload в английской части выше являются общей нормативной частью обеих языковых версий.

Пакет

Заголовок начинается байтами 0x43 0x59 (CY), за которыми следуют версия протокола, тип сообщения, номер последовательности и длина payload. После payload передаётся CRC-16/CCITT-FALSE по байтам заголовка 2…7 и payload. Полином — 0x1021, начальное значение — 0xFFFF, отражение и финальный XOR не применяются.

Длина payload находится в диапазоне 0…4096. Благодаря отдельному полю длины изображения и звук могут содержать любые байты. После неправильного заголовка, длины или CRC приёмник ищет следующую сигнатуру CY.

Команды хоста

Полная нормативная таблица команд находится в разделе Host commands. Ориентации имеют значения:

  • 0 — landscape, 320×240;
  • 1 — reverse landscape, 320×240;
  • 2 — portrait, 240×320;
  • 3 — reverse portrait, 240×320.

RGB565 использует обычную раскладку: красный — биты 15…11, зелёный — 10…5, синий — 4…0. Особенность BGR-подключения ST7789 полностью обрабатывает прошивка.

BLIT_RGB565 ограничен payload размером 4096 байт. Большое изображение хост передаёт горизонтальными полосами; полноэкранный framebuffer в прошивке не требуется.

QR-коды создаются функцией CYD_DrawQRCode() в host framebuffer PureBasic и передаются существующей командой BLIT_RGB565. Отдельная команда QR в протоколе CYD/1 не требуется.

Команды DRAW_* исполняются непосредственно через Adafruit GFX и не передают host framebuffer. DRAW_TEXT использует встроенный шрифт Adafruit 5×7, предназначенный прежде всего для ASCII. DRAW_UTF8_TEXT использует встроенные в прошивку шрифты U8g2, декодирует UTF-8 и содержит кириллицу. В flags bit 0 центрирует текст в прямоугольнике, bit 1 очищает прямоугольник цветом background перед рисованием. Запрошенная высота 4…53 пикселя сопоставляется с ближайшим встроенным кириллическим шрифтом.

UPDATE_BAR_CHART передаёт все вертикальные столбцы одной подтверждаемой командой. Формат элемента — value:u8 color:u16, значение ограничивается диапазоном 0…100. В flags bit 0 включает промежутки шириной один пиксель, когда ширина слота это позволяет; bit 1 рисует предыдущее измерение линией; bit 2 принудительно перерисовывает весь график. Прошивка запоминает прошлые значения и обновляет только изменившиеся части столбцов. Допускается до 320 столбцов, причём их количество не может превышать ширину графика.

MATRIX_START очищает экран и запускает локальный Matrix-эффект прошивки, не требующий дальнейшего трафика с хоста. speed и density принимают значения 1…100, tail_length — 4…30 знакомест. MATRIX_STOP при необходимости очищает экран. Следующая команда, использующая дисплей, автоматически останавливает эффект; изменение яркости и служебные команды его не прерывают. Команды доступны начиная с прошивки 0.15.0.

MATRIX_CLOCK_START (прошивка 0.18.0 и новее) одной командой запускает тот же автономный эффект и синхронизирует его локальный календарь. style=0 выбирает цифровой циферблат, style=1 — перекидной; language=0 задаёт русский язык, language=1 — английский. ESP32 самостоятельно обновляет время, дату и день недели. Символы Matrix не заходят в области часов, нижняя подсказка о нажатии не выводится.

CLOCK_SAVER_START (прошивка 0.19.0 и новее) запускает такие же цифровые или перекидные часы на чёрном фоне без Matrix. Для обеих команд show_seconds=0 убирает секунды с циферблата, после чего время меняется только раз в минуту. MATRIX_STOP также останавливает любой автономный часовой скринсейвер.

DRAW_BUTTON рисует закруглённую кнопку со светлой и тёмной гранями. При pressed=1 инвертируется только фаска; поверхность кнопки и заранее отрисованная хостом подпись не изменяются.

CLOCK_START и DATE_START передают локальные компоненты даты и времени. Clock и Date имеют независимые координаты и стиль, но используют общий календарь ESP32. Они выводят HH:MM:SS и YYYY-MM-DD без дальнейшего трафика с хостом. TIMER_START выводит обратный отсчёт HH:MM:SS; допустимая длительность — 1…359999 секунд.

SCROLL_START создаёт локальный RGB565 canvas заданной области и обновляет его примерно с частотой 30 FPS. Область ограничена 30720 пикселями, текст — 255 байтами UTF-8. После подтверждения команды дальнейший трафик для анимации не нужен.

Пути SD имеют кодировку UTF-8, начинаются с /, а .. запрещён. Загрузка последовательная, ограничена 4 ГБ, каждый пакет данных подтверждается. Для GIF_PLAY: loops=0 означает бесконечный цикл, x/y=-1 центрирует изображение, нулевые ширина и высота выбирают весь экран. fit_mode: 0=contain, 1=cover, 2=stretch. GIF и MP3 взаимоисключающие и декодируются локально с SD.

SD_LIST использует страницы: хост начинает с нулевого индекса и продолжает с возвращённого индекса до done=1. SD_READ передаёт файл блоками request/response, сохраняя управление потоком последовательного порта.

Сообщения устройства

Нормативная таблица находится в разделе Device messages. Запись списка SD имеет формат directory:u8 size:u32 name_length:u8 name:utf8.

Запись Wi-Fi имеет формат rssi:i16 channel:u8 encryption:u8 bssid_length:u8 bssid:utf8 ssid_length:u8 ssid:utf8. Статусы: 0=idle, 1=scanning, 2=complete, 3=error. Результаты разбиваются на страницы аналогично списку SD.

Состояния touch: 1=down, 2=move, 3=up. Состояние Timer 1 означает, что отсчёт достиг нуля. Это асинхронное событие использует sequence number 0.

Состояние Melody 1 означает нормальное завершение, 2 — остановку. Асинхронное событие использует sequence number 0. Строка AUDIO_MELODY начинается с BPM=20..400: и содержит до 128 нот, разделённых пробелами или запятыми. Формат ноты: [длительность][.][нота][#|b][октава]. Длительность по умолчанию 4; разрешены 1, 2, 4, 8, 16 и 32. Ноты: C, D, E, F, G, A, B/H, пауза P/R. Для звучащей ноты обязательна октава 1…7. Ограничения мелодии: 1024 UTF-8 байта и 300000 мс.

Стадии калибровки:

  • 1 — показана очередная мишень;
  • 2 — калибровка завершена;
  • 3 — ошибка калибровки;
  • 4 — калибровка отменена;
  • 5 — принят сырой образец, x/y содержат значения ADC.

Биты capabilities:

  • bit 0 — touch;
  • bit 1 — требуется и поддерживается управляемая хостом калибровка touch;
  • bit 2 — генерация тона;
  • bit 3 — unsigned 8-bit PCM;
  • bit 4 — аппаратные команды рисования;
  • bit 5 — автономный скролл;
  • bit 6 — FAT32 SD и загрузка файлов;
  • bit 7 — автономный GIF;
  • bit 8 — MP3 с SD;
  • bit 9 — PWM штатного RGB LED;
  • bit 10 — сканирование Wi-Fi;
  • bit 11 — автономные Clock, Date и Timer.
  • bit 12 — автономное воспроизведение RTTTL-подобной мелодии.
  • bit 13 — цвета аппаратных примитивов используют порядок панели BGR; перед отправкой команды примитива поменять местами красное и синее поля RGB565.
  • bit 14 — аппаратный UTF-8-текст со встроенными кириллическими шрифтами.
  • bit 15 — инкрементальный вертикальный график, передаваемый одним пакетом.

Ответы

HELLO возвращает INFO. PING, управляющие команды и каждая полоса BLIT_RGB565 возвращают ACK или ERROR. Ожидание ACK после каждой полосы обеспечивает flow control и не позволяет драйверу ПК поставить в очередь весь кадр быстрее, чем ESP32 способен его принять. AUDIO_DATA задаёт темп со стороны хоста и не подтверждается. Пакеты с ошибкой CRC отбрасываются, поскольку повреждённый пакет может содержать недостоверный sequence number.

Лицензия

Реализация проекта CYD/1 и эта спецификация защищены авторским правом: Copyright (C) CheshirCa 2026, https://t.me/cheshircanest. Они распространяются только для некоммерческого использования на полных условиях, приведённых в LICENSE.