#gcode #3d-printing #mex #fdm #no-std

no-std bin+lib meatpack

A Rust implementation of the MeatPack algorithm for encoding gcode

3 releases

Uses new Rust 2024

new 0.0.3 May 6, 2025
0.0.2 Apr 6, 2025
0.0.1 Jan 19, 2025

#338 in Encoding

Download history 102/week @ 2025-01-18 1/week @ 2025-01-25 6/week @ 2025-02-01 1/week @ 2025-02-08 2/week @ 2025-03-01 3/week @ 2025-03-08 3/week @ 2025-03-15 7/week @ 2025-03-22 4/week @ 2025-03-29 135/week @ 2025-04-05 22/week @ 2025-04-12 5/week @ 2025-04-19 6/week @ 2025-04-26 105/week @ 2025-05-03

147 downloads per month
Used in 3 crates (2 directly)

MIT license

45KB
912 lines

Meatpack

A pure Rust implementation of Scott Mudge's MeatPack algorithm. The crate works in both std and no_std environments. Add the alloc feature for additional for environments with a heap. A CLI is provided and bindings for other languages are in the pipeline. The Packer and Unpacker structs are configurable allowing you to set them up according to your embedded system resource constraints.

Support

Please consider supporting the crate by:

  • Downloading and using the crate.
  • Raising issues and improvements on the GitHub repo.
  • Recommending the crate to others.
  • ⭐ the crate on GitHub.
  • Sponsoring the maintainer.

The Algorithm

The gcode specification uses a restricted alphabet if ASCII (u8) characters resulting in files mostly made up of numbers, decimal point, a few letters ('G', 'M', 'E', etc.), and a few utility characters (newline, space, etc.). Scott's histographic analysis of several gcode files found that 15 characters forms ~93% of all gcode.

MeatPack takes advantage of this histographic property and uses a 4-bit lookup table that matches the 15 most popular characters. The 4-bit representations are then packed into 8-bit/1-byte characters effectively doubling the data density.

The 16th 4-bit character (0b1111) is reserved to tell the unpacker that a standard ASCII full-width character should be expected in the following byte. This allows the rest of the ASCII character set to be represented.

The algorithm features an additional optimisation where the packer reorders the characters if the full width character is surrounded by packable characters. This helps avoid 4 bits being wasted when telling the packer that a full width character is coming up.

If the lower 4-bits contains 0b1111 then the full width character is unpacked followed by the upper 4-bit character. If the upper 4-bit contains 0b1111 then the lower 4-bit character is unpacked followed by the full width character. The reordering allows slightly more data to the be packed at the cost of a little complexity.

Example

Take the following "G1" command.

G1 X113.214 Y91.45 E1.3154

which consists of 27 bytes (paranthesis indicate 1 byte),

(G) (1) ( ) (X) (1) (1) (3) (.) (2) (1) (4) ( ) (Y) (9) (1) (.) (4) (5) ( ) (E) (1) (.) (3) (1) (5) (4) (\n)

Applying the packing algorithm we can pack the command into 16 bytes as follows:

(1G) (X ) (11) (.33) (12) ( 4) (9#) (Y) (.1) (54) (# ) (E) (.1) (13) (45) (\n)

The characters are ordered in bit order (upper, lower) and would be unpacked lower then upper. With "Whitespace Removal" active, we can further reduce this to 13 bytes.

(1G) (1X) (31) (2.) (41) (9#) (Y) (.1) (54) (1E) (3.) (51) (\n4)

The packed command is now less than half the size of the original command.

Command Patterns

MeatPack also provides a communication/control layer identified by 2 255 (OxFF) signal bytes followed by a command byte. 0xFF is virtually never found in gcode, so it is can be considered a reserved character. The following command bytes exist:

Byte (u8) Value Command
246 Disable No Spaces
247 Enable No Spaces
248 Query Config
249 Reset All
250 Disable Packing
251 Enable Packing
255 Signal Byte

Examples

Examples can be found in the examples folder. No alloc featured examples can be called using:

cargo run --example pack

and alloc features.

cargo run --example alloc_unpack --features="alloc"

Tests

cargo test

and

cargo test --features alloc

Command Line Interface

Meatpack also features a cli to pack and unpack gcode.

> meatpack pack --strip-comments --strip-whitespace test_files/box.gcode tmp/box.meat

MeatPack!
Packing test_files/box.gcode into tmp/box.meat
Strip Comments: true
Strip Whitespace: true
Lines Packed: 2230
53027 unpacked bytes -> 26407 packed bytes (49.79916%)
> meatpack unpack tmp/box.meat tmp/box.gcode

MeatPack!
Unpacking tmp/box.meat into tmp/box.gcode
Lines unpacked: 2230
26413 packed bytes -> 47304 unpacked bytes

*Note. The difference in original to unpacked bytes due to the stripping of comments and whitespace.

References

Dependencies

~1–1.7MB
~31K SLoC