ggtag protocol

July 19, 2023 ยท View on GitHub

ggtag is using the same data protocol for sound and USB programming. The protocol encodes a series of commands into binary stream which is prefixed by two bytes which specify the size of the stream. The entire payload has the following format:

[SIZE (2 bytes)] [CMD1] [CMD2] [CMD3] ... [CMDn]

The SIZE is encoded as a big-endian 16-bit unsigned integer. At most SIZE bytes follow which represent the commands.

Commands

Each command has the following format:

[CMD_CODE (4 bits)] [ARG1] [ARG2] ... [ARGn]
CMD_CODENameDescription
0000TEXT_CMDDraw text
0001RECT_CMDDraw rectangle
0010FILL_RECT_CMDDraw filled rectangle
0011CIRCLE_CMDDraw circle
0100FILL_CIRCLE_CMDDraw filled circle
0101LINE_CMDDraw line
0110QRCODE_CMDDraw QR code
0111IMAGE_CMDDraw image
1000ICON_CMDDraw icon
1001RFID_CMDProgram RFID
1010RLE_IMAGE_CMDDraw RLE image

The commands are executed in the order they are received. The display is cleared before the first command is executed.

TEXT_CMD

ARG#DescriptionSize (bits)
1X coordinate9
2Y coordinate8
3Font size3
4Text length (N)7
5Char1 (7bit ASCII)7
.........
4+NCharN (7bit ASCII)7

Example: Draw "ABC" at position (120,95) with fontSize=3

CMD_CODEARG1ARG2ARG3ARG4ARG5ARG6ARG7
0000001111000010111110100000011100000110000101000011

RECT_CMD

ARG#DescriptionSize (bits)
1X coordinate9
2Y coordinate8
3Width9
4Height8

Example: Draw rectangle at position (50,30) with width=280 and height=170

CMD_CODEARG1ARG2ARG3ARG4
00010001100100001111010001100010101010

FILL_RECT_CMD

Same as RECT_CMD.

CIRCLE_CMD

ARG#DescriptionSize (bits)
1X coordinate9
2Y coordinate8
3Radius7

Example: Draw circle at position (50,30) with radius=100

CMD_CODEARG1ARG2ARG3
0011000110010000111101100100

FILL_CIRCLE_CMD

Same as CIRCLE_CMD.

LINE_CMD

ARG#DescriptionSize (bits)
1X1 coordinate9
2Y1 coordinate8
3X2 coordinate9
4Y2 coordinate8

Example: Draw line from (50,30) to (280,170)

CMD_CODEARG1ARG2ARG3ARG4
01010001100100001111010001100010101010

QRCODE_CMD

ARG#DescriptionSize (bits)
1X coordinate9
2Y coordinate8
3Pixel width2
4Text length (N)7
5Char1 (7bit ASCII)7
.........
4+NCharN (7bit ASCII)7

Example: Draw QR code at position (50,30) with pixel width=2 and text="ABC"

CMD_CODEARG1ARG2ARG3ARG4ARG5ARG6ARG7
011000011001000011110100000011100000110000101000011

IMAGE_CMD

ARG#DescriptionSize (bits)
1X coordinate9
2Y coordinate8
3Image width (W)9
4Image height (H)8
5BitmapW*H

Consider the following 7x9 image (* = black, . = white)

*******
*.....*
*.....*
*.***.*
*.....*
*.***.*
*.....*
*.....*
*******

Example: Draw the image above at position (50,30)

CMD_CODEARG1ARG2ARG3ARG4ARG5
01110001100100001111000000011100001001111111110000011000001101110110000011011101100000110000011111111

ICON_CMD

ARG#DescriptionSize (bits)
1X coordinate9
2Y coordinate8
3Icon height8
4Icon codepoint16

Example: Draw the FontAwesome icon with codepoint 0xf552 at position (50,30) with height=40

CMD_CODEARG1ARG2ARG3ARG4
100000011001000011110001010001111010111010010

RFID_CMD

ARG#DescriptionSize (bits)
1Type (0=EM4102, 1=HID)1
2ID45

If type is EM4102, the ID argument is interpreted in the following way:

| unused (5 bits) | manufacturer ID (8 bits) | unique ID (32 bits) |

If type is HID, the ID argument is interpreted in the following way:

| manufacturer code (20 bits) | site code (8 bits) | unique id (16 bits) | parity (1 bit) |

Example: Program RFID to be EM4102 with manufacturer ID=0x07 and unique ID=0xad30b1

CMD_CODEARG1ARG2
10010000000000011100000000101011010011000010110001

RLE_IMAGE_CMD

ARG#DescriptionSize (bits)
1X coordinate9
2Y coordinate8
3Image width (W)9
4Image height (H)8
5RLE bitmapvariable

The image is encoded using run-length encoding (RLE). The bitmap is interpreted as a sequence of black and white runs, left to right, top to bottom. Consider the following 7x9 image (* = black, . = white):

.......
.......
*******
****...
.......
.......
....***
*******
*******

We have 14 white pixels, 11 black pixels, 21 white pixels and 17 black pixels. We encode these numbers in base 3:

14 = 112(3)
11 = 102(3)
21 = 210(3)
17 = 122(3)

We use 2 bits to encode each digit in base 3, so 112(3) is encoded as 010110. We use 11 to separate the runs, and we always start with a white run. The image above is encoded as 010110 11 010010 11 100100 11 011010.

Example: Draw the image above at position (50,30)

CMD_CODEARG1ARG2ARG3ARG4ARG5
10100001100100001111000000011100001001010110110100101110010011011010