HM30 in “UART” RC signal mode uses the cPPM (PPM/S.BUS) pin of JR-bay as input to HM30/FM30 from radio with 100.000 baud 8E2 non-inverted. The S.PORT pin of JR-bay is used for HM30/FM30 output towards radio direction, with 100.000 baud 8E2 inverted.
In the S.PORT line trace, I was able to see two types of telegrams - the S.PORT status telegrams and the S.PORT telemetry messages.
Here an example of the S.PORT status message (bottom row):
First two bytes are always ASCII M and ASCII P to denote Multi-Protocol-Module.
Third byte is 0x01, which means S.PORT status message.
The status message is further parsed in processMultiStatusPacket() in https://github.com/opentx/opentx/blob/801b28958045d683b8c8058db5c167ae0c39da65/radio/src/telemetry/multi.cpp#L199-L239
Fourth byte is payload length, here 0x18 → 24 (bytes)
Fifth byte is status flags, here 0x27 (in OpenTX only the highest bit is ever checked, which means buffer full https://github.com/opentx/opentx/blob/801b28958045d683b8c8058db5c167ae0c39da65/radio/src/pulses/multi.cpp#L187 )
Sixth byte is major version number, here 60
Seventh byte is minor version number, here 0
Eight byte is revision number, here 1
Ninth byte is patch level, here 7
10th byte is channel order, here 0xE4 → b11100100 → decomposed into 2 bit values as 3,2,1 and 0, which results in AETR (see https://github.com/opentx/opentx/blob/801b28958045d683b8c8058db5c167ae0c39da65/radio/src/telemetry/multi.cpp#L510-L521 )
11th byte is next protocol type, here 0x7F
12th byte is previous protocol type, here 0x7F
beginning from 13th byte, the 7 bytes are the protocol name in ASCII, here “HM30” and three 0x00 fill bytes
20th byte combines option and sub-protocol number, here the value transmitted is 0x50. High nibble 5 is option and low nibble 0 is sub-protocol number. Option 5 means telemetry: https://github.com/opentx/opentx/blob/801b28958045d683b8c8058db5c167ae0c39da65/radio/src/gui/gui_common.cpp#L1022-L1034
beginning from 21st byte, the 8 bytes define the sub-protocol name in ASCII, here all 8 bytes are 0x00, thus the sub-protocol string emitted from HM30 is empty.
The status telegram is sent once every 500ms (2 Hz).
Here S.PORT telemetry telegram example (bottom row):
Again, the message starts with ASCII M (0x4D) and ASCII P (0x50).
3rd byte is type, this time 0x02, which equals to FrSkySportTelemetry ( https://github.com/opentx/opentx/blob/801b28958045d683b8c8058db5c167ae0c39da65/radio/src/telemetry/multi.cpp#L29-L47 )
4th byte is length, here 9 [bytes]
Last byte (13th) is the checksum and the validity is checked here: https://github.com/opentx/opentx/blob/801b28958045d683b8c8058db5c167ae0c39da65/radio/src/telemetry/frsky_sport.cpp#L114-L124
If checksum was valid, further processing happens in sportProcessTelemetryPacketWithoutCrc() https://github.com/opentx/opentx/blob/801b28958045d683b8c8058db5c167ae0c39da65/radio/src/telemetry/frsky_sport.cpp#L171-L375
5th byte denotes physicalId (only lower 5 bits are considered), here the value transmitted is 0x98, results in 0x18
6th byte is primId, here 0x10 → DATA_FRAME https://github.com/opentx/opentx/blob/801b28958045d683b8c8058db5c167ae0c39da65/radio/src/telemetry/frsky.h#L60
7th and 8th byte form in little endian the dataId in uint16_t → 0x01 and 0xF1 → 0xF101 → RSSI https://github.com/opentx/opentx/blob/801b28958045d683b8c8058db5c167ae0c39da65/radio/src/telemetry/frsky.h#L200
beginning from the 9th byte, the 4 bytes are data in little endian signed 32-bit int, here 0x60 0x00 0x00 0x00 → 0x00000060 → 96 (thus here - RSSI is 96).
The RSSI telegram is sent once every second (1 Hz).
I hope the above clarifies the data HM30 sends towards the radio.