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.
Each command has the following format:
[CMD_CODE (4 bits)] [ARG1] [ARG2] ... [ARGn]
CMD_CODE |
Name | Description |
|---|---|---|
0000 |
TEXT_CMD |
Draw text |
0001 |
RECT_CMD |
Draw rectangle |
0010 |
FILL_RECT_CMD |
Draw filled rectangle |
0011 |
CIRCLE_CMD |
Draw circle |
0100 |
FILL_CIRCLE_CMD |
Draw filled circle |
0101 |
LINE_CMD |
Draw line |
0110 |
QRCODE_CMD |
Draw QR code |
0111 |
IMAGE_CMD |
Draw image |
1000 |
ICON_CMD |
Draw icon |
1001 |
RFID_CMD |
Program RFID |
1010 |
RLE_IMAGE_CMD |
Draw RLE image |
The commands are executed in the order they are received. The display is cleared before the first command is executed.
| ARG# | Description | Size (bits) |
|---|---|---|
| 1 | X coordinate | 9 |
| 2 | Y coordinate | 8 |
| 3 | Font size | 3 |
| 4 | Text length (N) | 7 |
| 5 | Char1 (7bit ASCII) | 7 |
| ... | ... | ... |
| 4+N | CharN (7bit ASCII) | 7 |
Example: Draw "ABC" at position (120,95) with fontSize=3
| CMD_CODE | ARG1 | ARG2 | ARG3 | ARG4 | ARG5 | ARG6 | ARG7 |
|---|---|---|---|---|---|---|---|
0000 |
001111000 |
01011111 |
010 |
0000011 |
1000001 |
1000010 |
1000011 |
| ARG# | Description | Size (bits) |
|---|---|---|
| 1 | X coordinate | 9 |
| 2 | Y coordinate | 8 |
| 3 | Width | 9 |
| 4 | Height | 8 |
Example: Draw rectangle at position (50,30) with width=280 and height=170
| CMD_CODE | ARG1 | ARG2 | ARG3 | ARG4 |
|---|---|---|---|---|
0001 |
000110010 |
00011110 |
100011000 |
10101010 |
Same as RECT_CMD.
| ARG# | Description | Size (bits) |
|---|---|---|
| 1 | X coordinate | 9 |
| 2 | Y coordinate | 8 |
| 3 | Radius | 7 |
Example: Draw circle at position (50,30) with radius=100
| CMD_CODE | ARG1 | ARG2 | ARG3 |
|---|---|---|---|
0011 |
000110010 |
00011110 |
1100100 |
Same as CIRCLE_CMD.
| ARG# | Description | Size (bits) |
|---|---|---|
| 1 | X1 coordinate | 9 |
| 2 | Y1 coordinate | 8 |
| 3 | X2 coordinate | 9 |
| 4 | Y2 coordinate | 8 |
Example: Draw line from (50,30) to (280,170)
| CMD_CODE | ARG1 | ARG2 | ARG3 | ARG4 |
|---|---|---|---|---|
0101 |
000110010 |
00011110 |
100011000 |
10101010 |
| ARG# | Description | Size (bits) |
|---|---|---|
| 1 | X coordinate | 9 |
| 2 | Y coordinate | 8 |
| 3 | Pixel width | 2 |
| 4 | Text length (N) | 7 |
| 5 | Char1 (7bit ASCII) | 7 |
| ... | ... | ... |
| 4+N | CharN (7bit ASCII) | 7 |
Example: Draw QR code at position (50,30) with pixel width=2 and text="ABC"
| CMD_CODE | ARG1 | ARG2 | ARG3 | ARG4 | ARG5 | ARG6 | ARG7 |
|---|---|---|---|---|---|---|---|
0110 |
000110010 |
00011110 |
10 |
0000011 |
1000001 |
1000010 |
1000011 |
| ARG# | Description | Size (bits) |
|---|---|---|
| 1 | X coordinate | 9 |
| 2 | Y coordinate | 8 |
| 3 | Image width (W) | 9 |
| 4 | Image height (H) | 8 |
| 5 | Bitmap | W*H |
Consider the following 7x9 image (* = black, . = white)
*******
*.....*
*.....*
*.***.*
*.....*
*.***.*
*.....*
*.....*
*******
Example: Draw the image above at position (50,30)
| CMD_CODE | ARG1 | ARG2 | ARG3 | ARG4 | ARG5 |
|---|---|---|---|---|---|
0111 |
000110010 |
00011110 |
000000111 |
00001001 |
111111110000011000001101110110000011011101100000110000011111111 |
| ARG# | Description | Size (bits) |
|---|---|---|
| 1 | X coordinate | 9 |
| 2 | Y coordinate | 8 |
| 3 | Icon height | 8 |
| 4 | Icon codepoint | 16 |
Example: Draw the FontAwesome icon with codepoint 0xf552 at position (50,30) with height=40
| CMD_CODE | ARG1 | ARG2 | ARG3 | ARG4 |
|---|---|---|---|---|
1000 |
000110010 |
00011110 |
00101000 |
1111010111010010 |
| ARG# | Description | Size (bits) |
|---|---|---|
| 1 | Type (0=EM4102, 1=HID) |
1 |
| 2 | ID | 45 |
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_CODE | ARG1 | ARG2 |
|---|---|---|
1001 |
0 |
000000000011100000000101011010011000010110001 |
| ARG# | Description | Size (bits) |
|---|---|---|
| 1 | X coordinate | 9 |
| 2 | Y coordinate | 8 |
| 3 | Image width (W) | 9 |
| 4 | Image height (H) | 8 |
| 5 | RLE bitmap | variable |
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_CODE | ARG1 | ARG2 | ARG3 | ARG4 | ARG5 |
|---|---|---|---|---|---|
1010 |
000110010 |
00011110 |
000000111 |
00001001 |
010110110100101110010011011010 |