scottmudge / OctoPrint-MeatPack

Easy, fast, effective, and automatic g-code compression!
https://github.com/scottmudge/OctoPrint-MeatPack
BSD 4-Clause "Original" or "Old" License
122 stars 6 forks source link

Illustration Suggestion #3

Closed yash-fn closed 3 years ago

yash-fn commented 3 years ago

Could you possibly please give a few examples of before and after gcodes? It's faster to understand what you are doing by just seeing the direct result than by tryna read code to understand what is happening. Picture's worth a thousand words as they say.

yash-fn commented 3 years ago

Oh wait never mind. Wasn't too bad. So is this correct:

G1 X113.214 Y91.45 E1.3154 ~26 bytes

Post: 12 bytes + 2 bytes for Y and E and 2 bytes to signify full byte char? (16)?

scottmudge commented 3 years ago

G1 X113.214 Y91.45 E1.3154

Packed as:

(G1) ( X) (11) (3.) (21) (4 ) (9#)* (Y) (1.) (45) (# )* (E) (1.) (31) (54)

* these bytes don't show character order, but bit order. Higher order bits on left, lower order bits on right. See below. The other characters are sequential and only show how they are paired in bytes.

The packer reorders some characters if the full width character is surrounded by packable characters. The # here is a flag (0b1111) which tells the unpacker where the following full width character should go.

In this way, 4 bits aren't wasted telling the packer that only one full width character is coming up. 0xFF (0b11111111) tells the unpacker that the next 2 bytea are full width.

If 0b1111 is in the lower 4 bits, the full width character is immediately following, and the packed character in the upper 4 bits goes after the full width character. If it's in the higher 4 bits, the full width character goes after the character packed in the lower 4 bits. And if both upper and lower 4 bits are set to 1111, the next 2 characters are full width.

So 15 bytes in this example. Plus the new line character. Which is also packed with whatever is after.

This minor reordering is undone in the unpacking stage in the firmware. A little more complex, but it allows slightly more data to be packed.

This is also why the command sequence is 2 0xFF bytes in a row, followed by a command byte. If packing is enabled, 0xFF means the next character is some standard ASCII character (or at the very least not 0xFF), so 2 0xFF bytes in a row would never occur naturally except in these control/command sequences. And if packing is disabled, 0xFF is an invalid g-code character (the Prusa firmware even discards all bytes higher than 127U). This command signal preamble can be increased to 3 or more 0xFF bytes if some firmwares tend to have these bytes in error more frequently. But from what I've seen, it's generally 0x0 or null bytes which are received or sent in error. For instance, in noisy or unshielded connections.

yash-fn commented 3 years ago

Thanks! Makes sense now. You should add this to your README so users can quickly understand a high level overview. I like your implementation as it's both simple and flexible. A user can easily modify the lookup table to use whichever characters they want.

scottmudge commented 3 years ago

Yes I plan to update the readme with a better explanation of the packing approach.

I am currently working on a new feature/update to the plugin and firmware which will omit whitespace in outgoing g-code, and swap out the space character for 'E' in the lookup table. This should boost the compression ratio even more, potentially below 0.5. The RS-274 standard notes whitespace is effectively ignored, but this setting will be disabled by default, in the event a particular firmware encounters problems with parsing without whitespace.

As part of this update, I will look into the refactoring required to add the ability to dynamically change the lookup table to an arbitrary 15-characters. I've analyzed ~250 MB of gcode, and the frequency of characters is pretty much universally consistent once comments are stripped, but for other applications where characterset-restricted data is being transmitted, a different lookup table would be desirable.

yash-fn commented 3 years ago

Very nice! I look forward to it!