(Legacy MBrush / PrinCube models are in the maintenance branch)
Chinese Version: 中文文档
- Communication Interface
- Mainboard Communication
- Print Position Description
- Print Status Description
- CDBUS GUI Tool
- Image Conversion and Transfer Web Demo
- Command-Line Conversion Tool
Supported models:
This serial protocol is used for the printer RS-485 interface and USB-CDC serial port.
Base protocol: CDNET Intro and Demo
Packets can also be forwarded to the RS-485 bus via Bluetooth or Wi-Fi: CD-ESP
Type-C pinout:
- USB speed: High-speed (some models: Full-speed)
- Driver: Driverless on all platforms
- CDC baud rate: ignored (any value allowed)
- DTR must be enabled to communicate
- Address 0x10: mainboard, 0x20: BLE board (proxied by mainboard, uses temporary port bit4)
- Models with encoder connector: Type-C is not reversible
- Default dual speed: 2 Mbps & 20 Mbps (UART controller: CDCTL01A)
- Can be configured to single speed for compatibility with legacy RS-485 hardware
- Custom models may use 50 Mbps interface chips
- Multi-master design:
- BLE board may actively report key events
- Mainboard may actively report print status
- Bus arbitration prevents collisions automatically
- Inside the printer, only the RS-485 end has two 330 Ω pull resistors
- Termination resistor is not populated by default
- Some models use TTL between BLE and mainboard:
- Address 0x20 is still accessible via RS-485
- Mainboard proxies automatically
- ENC+ / ENC- default: A/B quadrature encoder (ENC+: A, ENC-: B)
- Can be configured as STEP / DIR input (ENC+: STEP, ENC-: DIR)
- Signal level: 3.3 V
Supported CDNET functional ports — all are general-purpose except the last one:
- #01: Device information query
- #05: Parameter table read/write
- #08: IAP firmware upgrade
- #09: Print debug reporting
- #0A: Waveform debug reporting
- #14: Print file DPT transfer
Parameter table (read/write via port #05; F: retained after power-off, !: takes effect after reboot):
| Addr | Name | Attr | Type | Default | Description |
|---|---|---|---|---|---|
| 0x0000 | magic_code | R/W | u16 | 0xcdcd | Fixed value to check if flash contains a valid register table |
| 0x0002 | conf_ver | R/W | u16 | 0x0200 | Register table version: high byte: major, low byte: minor |
| 0x0004 | conf_from | R | u8 | 0 |
0: Default 1: Flash-stored table 2: Default from bt_mac onwards (major version match only) |
| 0x0005 | do_reboot | R/W | u8 | 0 |
Write 1: Reboot to bootloader Write 2: Normal reboot |
| 0x0007 | save_conf | R/W | u8 | 0 | Write 1: Save config to flash |
| 0x0008 | usb_online | R | u8 | 0 | 0: Offline, 1: Online |
| 0x0009 | dbg_en | R/W/F | u8 | 0 |
0: No debug print 1: Report debug print |
| 0x000c | bus_mac | R/W/F! | u8 | 0x10 | Default serial address |
| 0x0010 | bus_baud_l | R/W/F! | u32 | 2000000 | First byte default speed: 2 Mbps |
| 0x0014 | bus_baud_h | R/W/F! | u32 | 20000000 | Following bytes default speed: 20 Mbps |
| 0x0018 | bus_filter_m | R/W/F! | u8[2] | 0xff 0xff | Multicast address filter |
| 0x001a | bus_mode | R/W/F! | u8 | 1 |
0: Traditional half-duplex mode 1: Arbitration mode 2: BS mode |
| 0x001c | bus_tx_permit_len | R/W/F! | u16 | 20 |
Waiting time to allows sending (10 bits) (Time unit: 1 bit duration) |
| 0x001e | bus_max_idle_len | R/W/F! | u16 | 200 | Max idle waiting time in BS mode (10 bits) |
| 0x0020 | bus_tx_pre_len | R/W/F! | u8 | 1 |
Enable TX_EN duration before TX output (2 bits) (Ignored in Arbitration mode) |
| 0x0024 | bt_mac | R/W/F | u8 | 0x30 | BLE board serial address |
| 0x0026 | auto_spit_period | R/W/F | u16 | 21600 | Auto purge period (seconds, 0 = disabled), requires USB power to stay on |
| 0x0028 | auto_spit_timer | R/W | u16 | 21600 | Auto purge countdown, reset on printer operation |
| 0x002a | dbg_raw_msk | R/W | u8 | 0 | 1: Enable waveform debug |
| 0x002c | dbg_raw0 | R/W/F | {u16 u16}[4] | {0x0142,2} {0x016c,8} {0,0} {0,0} |
Waveform debug data source |
| 0x0070 | c_t0 | R/W/F | f32 | -- | For cartridge temperature calibration (unused) |
| 0x0074 | c_r0 | R/W/F | f32[4] | -- | For cartridge temperature calibration (unused) |
| 0x00b6 | enc_cfg | R/W/F! | u8 | -- |
Bit1: Encoder mode select - 0: A/B input - 1: STEP/DIR input Bit0: Invert - AB mode: 1 = swap A/B pins - STEP/DIR mode: 1 = invert DIR signal |
| 0x00b7 | enc_div | R | u8 | -- |
Bit7: Encoder multiplier: F_out = F_in × 2 Bit[6:0]: Encoder divider: F_out = F_in ÷ (val + 1) (Auto-set by DPT print file) |
| 0x00b8 | enc_trig_f | R/W/F | u16 | 0x0100 | Start position for forward move printing |
| 0x00ba | enc_trig_b | R/W/F | u16 | 0xfe00 | Start position for reverse move printing |
| 0x00bc | const_period | R/W/F | u16 | 0 | Non-zero = enable constant-speed printing, speed unit: µs |
| 0x00be | print_dir | R | u8 | 0 |
0: Forward move printing 1: Reverse move printing (Auto-set by DPT print file) |
| 0x0141 | p_state | R | u8 | 0x18 |
Printer status (bit[2:0] = 0: idle) - bit7 Cartridge temperature error - bit6 Cartridge ink empty (unused) - bit5 Cartridge invalid - bit4 Cartridge not installed - bit3 No print data - bit2 Printing - bit1 Auto purge (spit) in progress - bit0 Preheating |
| 0x0142 | enc_val | R | u16 | 0 | Position encoder value (can be manually cleared via e_ctrl) |
| 0x0144 | c_state | R | u8[4] | 0x01 |
Cartridge status (for multi-cartridge, repeats in CMYK order) - Bit[7:5]: Reserved - Bit4: 0 = temperature too low; 1 = temperature too high - Bit3: Temperature error - Bit2: Ink empty (unused) - Bit1: Cartridge invalid - Bit0: Cartridge not detected |
| 0x0148 | c_ink_count | R/W/F | f32[4] | 0 | Ink volume record, order: CMYK, unit: mL |
| 0x0158 | c_temperature | R | f32[4] | -- | Printhead temperature (for multi-cartridge, repeats in CMYK order) |
| 0x0168 | temperature | R | f32 | -- | Ambient temperature |
| 0x016c | prt_enc_pos | R | i32 | -- | Print move position (see Print Position section) |
| 0x0170 | prt_dat_pos | R | i32 | -- | File print position (see Print Position section) |
| 0x0174 | voltage | R | f32 | -- | Single cell LiPo battery voltage (V) |
| 0x0178 | current | R | f32 | -- | Printhead current (mA) |
| 0x017c | dc_online | R | u8 | -- | Charge status |
| 0x01ac | p_ctrl | R/W | u8 | 0 |
Print control 0x10: Cancel job 0x04: Start print 0x02: Auto purge (spit) 0x01: Start heating |
| 0x01ad | d_ctrl | R/W | u8 | 0 |
Data control 0x10: Clear all data 0x04: Append submitted file data (TBD) 0x02: Submit file 0x01: Clear unsubmitted data |
| 0x01ae | e_ctrl | R/W | u8 | 0 |
Encoder control 0x10: Clear enc_val |
| 0x01af | c_ctrl | R/W | u8 | 0 |
Cartridge control 0x08: Calibrate cartridge temperature (unused) |
| 0x01f0 | c_id | R | u32[4] | -- | Cartridge unique ID |
| 0x0240 | psram_f_start | R | u32 | 0 | Submitted file start address |
| 0x0244 | psram_f_end | R | u32 | 0 | Submitted file end address |
| 0x0248 | psram_w_offset | R/W | u32 | 0 | Temporary file end address |
| 0x024c | p14_cnt | R/W | u8 | 0 | File transfer cnt |
| 0x024d | p14_err | R/W | u8 | 0 | File transfer error flag |
Transfer files in DPT proprietary format; see later sections for image conversion.
Registers related to file transfer:
- psram_f_start to psram_f_end: start and end addresses of submitted files; equal = no print file
- psram_f_end to psram_w_offset: start and end addresses of file being written; equal = not written
- p14_cnt and p14_err: status of 0x14 write file port; can be read and modified
The storage is a circular buffer of 8 MB. To calculate file size via subtraction, mask with 0x7fffff.
Command definitions:
write: [data]
return: [err_flag_8, p_state_8, enc_val_16, psram_w_offset_32]
data: DPT file slice, max 251 bytes per transfer.
Temporary port number:
- Bit3 = 1 → no reply; 0 → normal reply
- Bit[2:0] = auto-increment sequence cnt; first packet = 0; if sequence error, set error flag and discard data
Modifying p14_cnt / p14_err:
- Directly read/write p14_cnt / p14_err registers
- Clear via d_ctrl register
- Write an empty packet (data length = 0) to 0x14 port
Reply:
- err_flag: 0 = no error; 1 = cnt error; subsequent writes discarded until error cleared
- p_state: current printer status
- enc_val: current position encoder count
- psram_w_offset: psram_w_offset value when current packet was successfully written
Each command normally requires a reply to ensure data is correctly written, but this reduces transfer efficiency. To improve throughput, the following method can be used:
- Send up to two groups of packets at a time, each group containing multiple packets; only the last packet requires a reply.
- After receiving the reply for the previous group, if no error occurred, send one more group.
Example (one group of 5 packets):
A simpler approach is to request a reply only for the last packet of the entire file; if an error occurs, clear the data and retransmit the whole file. This method is suitable for wired communication.
The printer supports printing while transferring the next file.
After transferring a file, write 0x02 to the d_ctrl register to indicate transfer completion and trigger file update.
If the previous file is still printing, wait until printing finishes before updating the file, otherwise it may interfere with the current print.
If no new print data is provided, the same content will be printed each time.
To be implemented: append data to a submitted file during printing to support unlimited-length printing.
$ cd cli_tools/serial_send_file
$ ./send_dpt.py --file xxx.dpt
You can add the --verbose option to view low-level serial packets.
As illustrated, enc_val represents the current printer position.
Forward printing:
- Printer enters preheating mode
- enc_val increments as the printer moves forward
- When enc_val reaches enc_trig_f, printing starts
Reverse printing:
- Printer enters preheating mode
- enc_val decrements as the printer moves backward
- When enc_val reaches enc_trig_b, printing starts
- prt_enc_pos is the multi-turn extension of enc_val relative to enc_trig_f/b.
Regardless of printing direction, it increases from negative to positive along the print direction.
Zero is the print trigger position. - prt_dat_pos indicates the print data position, transitioning from negative (preheating) to positive; printing finishes when it reaches the file’s total print count.
During preheating, prt_dat_pos starts at a large negative value and steadily increases to zero, taking up to 1 minute. Preheating stops when zero is reached, and prt_dat_pos waits at zero.
When prt_enc_pos reaches zero as the printer moves, if prt_dat_pos is still negative, it jumps directly to zero.
Then prt_enc_pos pushes prt_dat_pos forward:
Modes that ignore prt_enc_pos:
- Preheat-only mode: prt_dat_pos moves to zero to exit preheating and returns to idle.
- Purge mode: prt_dat_pos starts slightly negative, heats for a few seconds until positive, triggers purge, then returns to idle.
- Constant-speed printing mode: prt_dat_pos starts at -enc_trig_f and increases steadily at const_period while printing.
Printing is controlled via the p_ctrl register:
- Write 0x01 to start preheating
- Write 0x02 to perform a single purge (equivalent to long-press button; preheats automatically for a few seconds before purging)
- Write 0x04 to start printing (equivalent to short-press button; can jump directly from preheating to printing)
- Write 0x10 to cancel the current job and return to idle (equivalent to short-pressing the single button while not in idle)
Examples:
Purge: write 0x02, p_state changes: "Idle" -> "Preheat + Purge" -> "Purge" -> "Idle"
Printing: it is recommended to start preheating first (0x01), p_state changes: "Idle" -> "Preheat"
During preheating, data can be transferred. Once data is ready, start printing (0x04), p_state changes: "Preheat" -> "Preheat + Print"
When the printer reaches the start print position, it exits preheating and enters the actual printing phase: "Preheat + Print" -> "Print"
After printing completes, p_state returns to idle: "Print" -> "Idle"
Copy the files from the gui_configs folder to the configs folder of the CDBUS GUI.
Enter the corresponding serial port, e.g., ttyACM0, COM4, or a substring that matches, such as 2E3C:5740.
Set the baud rate according to your setup (default: 20,000,000 bps).
(cdbridge v1.2: set the S1.2 switch to ON for low-speed limit 2 Mbps;
when connecting the printer directly via USB, the baud rate can be any value.)
Set the target address to 00:00:10, select dprinter.json as the target configuration, and the leftmost name can be set arbitrarily.
Access the demo directly at: https://p.d-l.io
Requires a browser with Web BLE support:
- iOS: Bluefy
- Android: Chrome, Samsung Internet, or Opera
- PC: Chrome, Edge, or Opera
Local deployment:
- Run the script
web_demo/start_web_server.sh - Open the URL in a web browser:
http://localhost:7000
Go to the directory for your model under cli_tool/image_convert, then run:
$ node dpconv.js input.png -1 --dbg
The -1 option converts the image to single-line print data.
Without -1, multiple lines are generated, suitable for printing large content across multiple passes.
For full parameter details, see the help:
$ node dpconv.js --help



