Frame data is transferred inside packets (similar to DMX, for example). A frame is an image representing a matrix or a light scene.
The packets start and end with one-byte characters. In between are a few control bytes followed by the payload. There is no set size for a payload; it is transmitted with each packet. This makes the protocol quite flexible. There are enough bytes in a single packet for an RGB matrix with 21,845 pixels, but if you just want to control an RGBW lamp, that only requires 9 bytes. The variable frame size means there is no overhead, allowing for maximum transfer speed.
Section | Value |
---|---|
Packet start byte | 0xC9 |
Packet type | 0xDA = Data frame or |
0xC0 = Command or | |
0xAA = Requested response (from the data receiver to the sender) | |
Payload size (16 bits) | High-Byte first, then |
Low-Byte | |
User data | 1 - 65,535 bytes of data or command with parameters |
Packet end byte | 0x36 |
At this point, the commands are not yet standardized, nor are possible responses. If such commands are used, they should be uniform so the user's software and hardware can cooperate. Commands could be used make adjustments from a distance, automatically configure the control software by asking the matrix on how big it is and then adjusting to accommodate it, or tell the controller to save the following frames to sd card, for example.
The receiver can respond with an acknowledgement byte 0xAC after each correctly received frame. It is possible for the transmission software to only send the next frame when 0xAC comes back from the receiver. However, acknowedgment is not mandatory, and transmission software can keep sending packets even if no acknowledgement is received.
It is possible to have automatic addressing of daisy-chained devices. For example, the transmitter sends 2,048 bytes, the first receiver takes the first 512 bytes out, decreases the frame size by 512 bytes, then sends the rest on, and so on until there is nothing left. It is also possible (as with DMX) for multiple receivers to receive the same data on a parallel bus, and each only takes the bytes that are addressed to them.
No special hardware requirements (physical layer, connectors, etc.) are standardized by the protocol. It only specifies the format of the packets. It doesn't matter whether these packets are then transmitted via RS232, TTL, USB, RS485, Ethernet or wireless; it is up to each user to decide themselves.
Likewise, the transmission rate may be very different depending on the requirements. For a 128x128 pixel matrix with 30fps or more, 100 megabit Ethernet may be required. For a 16x16 matrix, 250 to 500 kbps could be sent via USB. For building light control, where here and there, single lamps are turned on or off, 2400 baud would suffice.
The original TPM2 protocol was intended to be independent of underlying hardware. This does not quite apply to Ethernet/WiFi/UDP because the size of user data in each packet should not exceed 1500 bytes (the Ethernet frame size). The IP protocol states that the transmitter should break up, and the receiver should reassemble packets larger than 1500 bytes; however, many embedded TCP/IP implementations do not handle reassembly of packets. Therefore, it is useful to divide the TPM2 frames with larger datasets into corresponding portions. In this case, the individual packets should be numbered so that these portions can be put back together.
For this reason, TPM2.net introduces an additional packet number byte immediately after the frame size in bytes. To distinguish between "normal TPM2" and tpm2.net, the start code for tpm2.net has been changed to 0x9C.
Section | Value |
---|---|
Packet start byte | 0x9C |
Packet type | 0xDA = Data frame or |
0xC0 = Command or | |
0xAA = Requested response (from the data receiver to the sender) | |
Frame size in 16 bits | High-Byte first, then |
Low-Byte | |
Packet number | 1-255 |
Number of packets | 1-255 |
User data | 1 - 1,490 bytes of data or command with parameters |
Packet end byte | 0x36 |
These packets will be sent via UDP to port 65506 / 0xFFE2. The port for responses from the receiver to transmitter is 65442 / 0xFFA2.
The receive routine can reference the start code (0xC9 or 0x9C) to determine whether a packet is "normal TPM2", then look for the frame size bytes equal to the payload, or if is tpm2.net, read the packet number and number of packets.
The packet number goes from 1 to 255 in decimal, so there are a maximum of 255 packets, each around 1,490 bytes. This allows for 379,950 bytes per frame sent by tpm2.net, which would amount to 126,650 RGB LEDs.
The number of packets issent along to help control automatic memory allocation on the receiver. It may be convenient to have the number of packets can vary in each case, but keep all packets the same size. Otherwise, it is much more complicated for the receiver to put the packets back together again.
For example, if you have an RGB matrix with 32x32 = 1024 pixels or 3,072 bytes, you can then send 3 packets of 1,024 bytes. If you build a larger array of modules with 16x16 = 256 RGB pixels to build, then it could be useful to send a packet with 768 bytes per module. The transmission software must be configured to assemble the packets as the receiver expects. Usually you have to configure it anyway to set the number of pixels.
Temporal numbering is not provided, since it is assumed that tpm2.net is used in small networks without a router, so the packets arrive in the order in which they were sent.
The original protocol description, in German, is here: http://www.ledstyles.de/index.php/Thread/18969-tpm2-Protokoll-zur-Matrix-Lichtsteuerung/
I translated it using Google Translate and then cleaned up the mangled English. Hopefully it is still true to the spirit of the original text.
@jblang Hi, thanks for this english version on github. I'm currently in contact, with the german author of the TPM2 protocol. I plan to detail out some documentation how to handle RGBW and other LED types, adjustable framerate ... in the end I would like to host it in a github project.
Your translation could be a foundation to start of, could we do a copy and alter it?