FreeCAD/DXF to .rd conversion, named upload to controller memory with idle check and read-back verification, read-only status/file listing, and a fake controller for dry runs. Co-Authored-By: Claude Opus 5.5 <[email protected]>
70 lines
3.6 KiB
Markdown
70 lines
3.6 KiB
Markdown
# Ruida UDP protocol notes
|
|
|
|
What these scripts rely on, where it came from, and what was confirmed against a real
|
|
RDC644x-class controller (60 W CO2 laser, firmware reporting 49 stored files).
|
|
|
|
## Transport
|
|
|
|
- UDP. Host sends from port **40200** to the controller's port **50200**.
|
|
- Every byte in both directions is **swizzled** with a per-model "magic" value. Ours is
|
|
**0x88** (the common value for 644x boards over UDP). `meerk40t.ruida.rdjob.swizzles_lut(magic)`
|
|
returns the encode/decode tables. If the controller never ACKs anything, the magic may differ;
|
|
RDWorks `.rd` files from the same machine use the same magic, and MeerK40t can guess it from one.
|
|
- Host datagram = 2-byte big-endian sum of the swizzled payload bytes, then the payload.
|
|
At most 998 payload bytes per datagram.
|
|
- The controller answers each datagram with a single byte: **ACK `CC`** (`C6` on the wire),
|
|
NAK `CF`, ENQ `CE` (keep-alive). Wait for the ACK before sending the next datagram (3 s timeout).
|
|
- Read commands get an ACK followed by a separate, swizzled reply datagram (no checksum prefix).
|
|
|
|
## Commands are bytes ≥ 0x80
|
|
|
|
A command starts with a byte ≥ 0x80; its arguments are all < 0x80 (7-bit encodings). That makes
|
|
a stream self-delimiting: split at every byte ≥ 0x80. Integers are big-endian 7-bit groups:
|
|
`encode14` (2 bytes), `encode32`/`decodeu35` (5 bytes). Coordinates are micrometres.
|
|
|
|
## Storing a job in memory (rdupload.py)
|
|
|
|
Follows LibLaserCut / VisiCut's Ruida driver. Insert two commands right after the job's
|
|
preamble (`D8 12`, `E6 01`, `F0`):
|
|
|
|
```
|
|
E8 02 file transfer: store, don't run
|
|
E7 01 <name> 00 file name, ASCII, 1-8 chars, null-terminated
|
|
```
|
|
|
|
then send the whole job (ending `D7`, end of file) as datagrams. Drop any `E5 05` (file sum);
|
|
LibLaserCut sends none and the controller accepted the file without it.
|
|
|
|
Confirmed: the file appears in the panel's file list and runs correctly (clean cut, settings as
|
|
encoded). **Confirmed failure mode:** uploading while a job is running gets every packet ACKed
|
|
and the file silently discarded.
|
|
|
|
## Read-only queries (rdlist.py)
|
|
|
|
| Send | Reply | Notes |
|
|
|---|---|---|
|
|
| `DA 00 04 00` | `DA 01 04 00 <u35>` | Status bits. **Bit 0 = job running: confirmed** (`0x20018401` mid-cut, `0x2001x600`/`0x2403x600` idle). Bit 24 = moving, bit 1 = part end (from MeerK40t, unconfirmed). Other bits change while idle; ignore them. |
|
|
| `DA 00 02 00` | `DA 01 02 00 <u35>` | MeerK40t's emulator says 21/22/23 = running/idle/paused. Ours read **33313 whether cutting or idle**: useless here. |
|
|
| `DA 00 02 05` | `DA 01 02 05 <u35>` | "Total doc number". Read **0** with 49 files stored. Don't trust it. |
|
|
| `E8 01 <n14>` | `E8 01 <n14> NAME 00` | Name of stored file n, 1-based, oldest first. **Past the last file the controller doesn't reply at all**; that timeout is the end-of-list marker. Confirmed. |
|
|
|
|
## Commands this skill must never send
|
|
|
|
| Bytes | Effect |
|
|
|---|---|
|
|
| `D8 00` | Start process (runs the current job) |
|
|
| `E8 03 <n14>` | Select document n: **starts** it |
|
|
| `E8 00 ...` | Delete document(s); `E8 00 00 00 00 00` deletes all |
|
|
| `E8 04 <n14>` | Calculate document time (harmless, but not needed) |
|
|
| `A5 ...` | Panel keys (frame, origin, jog, pulse) |
|
|
| `D9 ...`, `88`, `89` | Moves |
|
|
|
|
`rdlist.py` enforces this with an exact-match whitelist checked before the socket.
|
|
|
|
## Sources
|
|
|
|
- MeerK40t (`meerk40t/ruida/`): command table, swizzle, emulator, status bits. MIT.
|
|
- LibLaserCut (VisiCut) Ruida driver: file-transfer header and UDP framing.
|
|
- Everything marked "confirmed" was observed on the real controller; the rest is from those
|
|
sources and is labelled as such.
|