YSC 8K · Protocol Reference

Two dialects,
one wire.

The box speaks YSC JSON frames and the full MAKCU km.* text dialect — command-for-command compatible with the MAKCU ecosystem. Same command set on V1 and V2; only the physical transport differs (V1 UART · V2 USB-CDC, baud-independent).

01 CAPABILITY SCHEDULE
CAP—01

Recoil Control

CMD 30 / 31 · FIELDS RX RY RC

Deceleration coefficients shrink real mouse pull while firing. Duration window auto-scales to polling rate — identical behavior on 1K and 8K mice.

ADAPTIVE · 1K=1pkt/ms · 8K=8pkt/ms
CAP—02

Macro Engine

CMD 36–38 · SLOTS 0–7

Eight trigger-masked slots. Periodic wheel pulses with per-cycle random jitter on interval and duration — no metronome signature.

SLOTS · 8 · ±JITTER MS
CAP—03

Mouse Curves

CMD 42–44 · PROFILES

Segmented movement profiles reshape injected motion — smoothing segments, duration control and amplitude jitter for natural paths.

PROFILE · SEGMENTS + DURATION
CAP—04

Jitter Trajectory

CMD 39–41 · AX FX PY FY

Fire-triggered micro-oscillation on independent X/Y axes with separate amplitude and frequency. Draw your own spray pattern.

AXES · DUAL · ON-FIRE
CAP—05

Gamepad Mapping

PS5 · XBOX · XINPUT · HID

Pad buttons map to mouse buttons with analog trigger thresholds; mouse motion converts to stick deflection with scaling and axis inversion.

MAP · BTN→MOUSE · MOTION→STICK
CAP—06

Remote Control

KMNET · OVER LAN

Drive the box from a second machine over the network. Built-in self-test verifies the link end to end before you rely on it.

LINK · LAN · SELF-TEST
02 FRAME FORMAT · EXCERPT

Framing &
responses.

YSC frames — a 7-byte START mark, 2-byte big-endian total length and a JSON payload, closed by a 5-byte END mark. USART runs DMA on TX/RX with IDLE-line framing. Responses arrive as {"code":200,"message":"…","data":"…"}; jitter and curve query results return asynchronously via debug_response.

MAKCU dialect — plain-text km.* commands terminated by CRLF, answers close with >>>.

A 9-byte binary baud frame (0xDE 0xAD 05 00 A5 + 4-byte LE rate) reconfigures the USART directly — the recovery path when the current rate is unknown.

01; smooth move + recoil window 02{"cmd":30,"x":100,"y":50,"c":1, 03 "rx":1.0,"ry":0.6,"rc":50} 04
{"code":200,"message":"mouse_move","data":""}
05; macro slot 0 · wheel pulse 30±5ms 06{"cmd":36,"s":0,"e":1,"t":3,"w":-1, 07 "i":30,"d":10,"ij":5,"dj":2} 08
{"code":200,"message":"macro_set","data":""}
09; makcu dialect 10km.move(100, 50, 8) 11km.version() 12
km.version(km.MAKCU)
>>>
13; build date 14{"cmd":132} 15
{"code":200,"message":"version","data":"Jul 23 2026"}
03 YSC COMMAND SET
CmdNamePayload / Notes
30MOUSE_MOVE{"cmd":30,"x":100,"y":50,"c":1,"rx":1.0,"ry":1.0,"rc":0} — smooth move; c = step count; rx/ry physical-input deceleration, rc = window ms (rate-adaptive)
31MOUSE_MOVE_TOWDirectional move, stacks with cmd 30 (deltas sum in the HID report). Same fields; its rc wins when both set
32MOUSE_BUTTONb mask (1=L, 2=R, 4=M), c = reports before auto-release
33BUTTON_STATEDirect set: s=1 press, 0 release — immediate, no report count
34UPLOAD_STATUSstatus>0 streams HID data (buttons + motion) back over serial
35WHEEL_HOLDw ±1, c = hold duration ms
36MACRO_SETSlot s 0–7, e enable, t trigger mask, p block mask, w wheel, i interval ms, d duty ms, ij/dj random jitter. Buttons: 1=L 2=R 4=M 8=S-back 16=S-fwd
37MACRO_GETs=-1 all slots, 0–7 single
38MACRO_RESETAll slots back to firmware default (disabled)
39 / 40 / 41JITTER SET/GET/RESETe, t, ax, fx, py, fy — fire-triggered X/Y oscillation; results via async debug_response
42 / 43 / 44CURVE SET/GET/RESETe, p, n, d, j — profile, segments, duration ms, jitter amplitude
50JUMP_TO_IAPReplies entering_iap, then reboots into bootloader. V2 re-enumerates as serial number TOWMCUIAP — COM number may change
132 (0x84)GET_VERSIONBuild date (__DATE__). V2: APP returns ysc-towmcu-L|R v1.0; IAP returns YSC-IAP
133 (0x85)SET_BAUDRATEbaud — no whitelist check in firmware; send only the 8 whitelisted rates (115200 … 3000000). Host must follow immediately
04 MAKCU DIALECT · KM.*
CommandGroupNotes
km.move(x,y[,seg])Motionseg 1–512 (clipped) for stepped moves
km.left / right / middle / ms1 / ms2 (1/0)Buttons1=press, 0=release, 2=silent release (skips push queue)
km.wheel(±1)MotionOne notch; other values clipped to ±1
km.lock_mx / lock_my (0/1)Axis lockAlso lock_mx+ / lock_mx- for single direction; same for Y
km.lock_ml / mr / mm / ms1 / ms2Button lockPhysical button stops registering
km.invert_x / invert_y · km.swap_xyAxis mapInvert or swap axes
km.catch_ml / mm / mr / ms1 / ms2Capture0=auto, 1=manual capture mode
km.scroll_side · km.scroll_lrWheel mapSide-button or L+R chord triggers wheel
km.buttons(mode,period)PushPhysical button push reports; period 1–1000 ms
km.serial("…" / 0)IdentitySet / reset device serial (max 32 B, C-style escapes); no arg = query
km.echo(0/1)SystemCommand echo (default on)
km.baud([rate])Systemrate ≥ 115200, no whitelist check; no arg = query
km.version()SystemReturns km.version(km.MAKCU)
km.reboot()SystemSoft reset after reply
05 DEVICE STATES
StateMeaningHow to identify
APPNormal operation — passthrough + command handlingcmd 132 returns the app version string (ysc-towmcu-L v1.0 / -R on V2, build date on V1)
IAPBootloader, awaiting firmwarecmd 132 returns YSC-IAP; V2 enumerates with serial number TOWMCUIAP