Add tlmConfirm to tlm_dl ota packet-structure (#2991)
[ExpressLRS.git] / src / lib / OTA / OTA.h
blob1f225a30efff85d1ae1a4b267b2a72614df34786
1 #ifndef H_OTA
2 #define H_OTA
4 #include <cstddef>
6 #include "crc.h"
7 #include "CRSF.h"
8 #include "crsf_protocol.h"
9 #include "telemetry_protocol.h"
10 #include "FIFO.h"
12 #define OTA4_PACKET_SIZE 8U
13 #define OTA4_CRC_CALC_LEN offsetof(OTA_Packet4_s, crcLow)
14 #define OTA8_PACKET_SIZE 13U
15 #define OTA8_CRC_CALC_LEN offsetof(OTA_Packet8_s, crc)
17 // Packet header types
18 #define PACKET_TYPE_DATA 0b01
19 // Uplink only header types
20 #define PACKET_TYPE_RCDATA 0b00
21 #define PACKET_TYPE_SYNC 0b10
22 // Downlink only header types
23 #define PACKET_TYPE_LINKSTATS 0b00
25 // Mask used to XOR the ModelId into the SYNC packet for ModelMatch
26 #define MODELMATCH_MASK 0x3f
28 typedef struct {
29 uint8_t fhssIndex;
30 uint8_t nonce;
31 uint8_t rfRateEnum;
32 uint8_t switchEncMode:1,
33 newTlmRatio:3,
34 geminiMode:1,
35 free:3;
36 uint8_t UID4;
37 uint8_t UID5;
38 } PACKED OTA_Sync_s;
40 typedef struct {
41 uint8_t uplink_RSSI_1:7,
42 antenna:1;
43 uint8_t uplink_RSSI_2:7,
44 modelMatch:1;
45 uint8_t lq:7,
46 tlmConfirm:1;
47 int8_t SNR;
48 } PACKED OTA_LinkStats_s;
50 typedef struct {
51 uint8_t raw[5]; // 4x 10-bit channels, see PackUInt11ToChannels4x10 for encoding
52 } PACKED OTA_Channels_4x10;
54 typedef struct {
55 // The packet type must always be the low two bits of the first byte of the
56 // packet to match the same placement in OTA_Packet8_s
57 uint8_t type: 2,
58 crcHigh: 6;
59 union {
60 /** PACKET_TYPE_RCDATA **/
61 struct {
62 OTA_Channels_4x10 ch;
63 uint8_t switches:7,
64 ch4:1;
65 } rc;
66 struct {
67 uint32_t packetNum; // LittleEndian
68 uint8_t free[2];
69 } PACKED dbg_linkstats;
70 /** PACKET_TYPE_MSP **/
71 struct {
72 uint8_t packageIndex:7,
73 tlmConfirm:1;
74 uint8_t payload[ELRS4_MSP_BYTES_PER_CALL];
75 } msp_ul;
76 /** PACKET_TYPE_SYNC **/
77 OTA_Sync_s sync;
78 /** PACKET_TYPE_TLM **/
79 struct {
80 uint8_t free:1,
81 tlmConfirm: 1,
82 packageIndex:6;
83 union {
84 struct {
85 OTA_LinkStats_s stats;
86 uint8_t free;
87 } PACKED ul_link_stats;
88 uint8_t payload[ELRS4_TELEMETRY_BYTES_PER_CALL];
90 } tlm_dl; // PACKET_TYPE_TLM
91 /** PACKET_TYPE_AIRPORT **/
92 struct {
93 uint8_t free:2,
94 count:6;
95 uint8_t payload[ELRS4_TELEMETRY_BYTES_PER_CALL];
96 } PACKED airport;
98 uint8_t crcLow;
99 } PACKED OTA_Packet4_s;
101 typedef struct {
102 // Like OTA_Packet4_s **the type is always the low two bits of the first byte**,
103 // but they are speficied in each type in the union as the other bits there
104 // are not universal
105 union {
106 /** PACKET_TYPE_RCDATA **/
107 struct {
108 uint8_t packetType: 2,
109 telemetryStatus: 1,
110 uplinkPower: 3, // CRSF_power_level - 1 (1-8 is 0-7 in the air)
111 isHighAux: 1, // true if chHigh are AUX6-9
112 ch4: 1; // AUX1, included up here so ch0 starts on a byte boundary
113 OTA_Channels_4x10 chLow; // CH0-CH3
114 OTA_Channels_4x10 chHigh; // AUX2-5 or AUX6-9
115 } PACKED rc;
116 struct {
117 uint8_t packetType; // actually struct rc's first byte
118 uint32_t packetNum; // LittleEndian
119 uint8_t free[6];
120 } PACKED dbg_linkstats;
121 /** PACKET_TYPE_MSP **/
122 struct {
123 uint8_t packetType: 2,
124 packageIndex: 5,
125 tlmConfirm: 1;
126 uint8_t payload[ELRS8_MSP_BYTES_PER_CALL];
127 } msp_ul;
128 /** PACKET_TYPE_SYNC **/
129 struct {
130 uint8_t packetType; // only low 2 bits
131 OTA_Sync_s sync;
132 uint8_t free[4];
133 } PACKED sync;
134 /** PACKET_TYPE_TLM **/
135 struct {
136 uint8_t packetType: 2,
137 tlmConfirm: 1,
138 packageIndex: 5;
139 union {
140 struct {
141 OTA_LinkStats_s stats;
142 uint8_t payload[ELRS8_TELEMETRY_BYTES_PER_CALL - sizeof(OTA_LinkStats_s)];
143 } PACKED ul_link_stats; // containsLinkStats == true
144 uint8_t payload[ELRS8_TELEMETRY_BYTES_PER_CALL]; // containsLinkStats == false
146 } PACKED tlm_dl;
147 /** PACKET_TYPE_AIRPORT **/
148 struct {
149 uint8_t packetType: 2,
150 free: 1,
151 count: 5;
152 uint8_t payload[ELRS8_TELEMETRY_BYTES_PER_CALL];
153 } PACKED airport;
155 uint16_t crc; // crc16 LittleEndian
156 } PACKED OTA_Packet8_s;
158 typedef struct {
159 union {
160 OTA_Packet4_s std;
161 OTA_Packet8_s full;
163 } PACKED OTA_Packet_s;
165 extern bool OtaIsFullRes;
166 extern volatile uint8_t OtaNonce;
167 extern uint16_t OtaCrcInitializer;
168 void OtaUpdateCrcInitFromUid();
170 enum OtaSwitchMode_e { smWideOr8ch = 0, smHybridOr16ch = 1, sm12ch = 2 };
171 void OtaUpdateSerializers(OtaSwitchMode_e const mode, uint8_t packetSize);
172 extern OtaSwitchMode_e OtaSwitchModeCurrent;
174 // CRC
175 typedef bool (*ValidatePacketCrc_t)(OTA_Packet_s * const otaPktPtr);
176 typedef void (*GeneratePacketCrc_t)(OTA_Packet_s * const otaPktPtr);
177 extern ValidatePacketCrc_t OtaValidatePacketCrc;
178 extern GeneratePacketCrc_t OtaGeneratePacketCrc;
179 // Value is implicit leading 1, comment is Koopman formatting (implicit trailing 1) https://users.ece.cmu.edu/~koopman/crc/
180 #define ELRS_CRC_POLY 0x07 // 0x83
181 #define ELRS_CRC14_POLY 0x2E57 // 0x372b
182 #define ELRS_CRC16_POLY 0x3D65 // 0x9eb2
184 #if defined(TARGET_TX) || defined(UNIT_TEST)
185 typedef void (*PackChannelData_t)(OTA_Packet_s * const otaPktPtr, const uint32_t *channelData, bool TelemetryStatus, uint8_t tlmDenom);
186 extern PackChannelData_t OtaPackChannelData;
187 #if defined(UNIT_TEST)
188 void OtaSetHybrid8NextSwitchIndex(uint8_t idx);
189 void OtaSetFullResNextChannelSet(bool next);
190 #endif
191 #endif
193 #if defined(TARGET_RX) || defined(UNIT_TEST)
194 typedef bool (*UnpackChannelData_t)(OTA_Packet_s const * const otaPktPtr, uint32_t *channelData, uint8_t tlmDenom);
195 extern UnpackChannelData_t OtaUnpackChannelData;
196 #endif
198 void OtaPackAirportData(OTA_Packet_s * const otaPktPtr, FIFO<AP_MAX_BUF_LEN> *inputBuffer);
199 void OtaUnpackAirportData(OTA_Packet_s const * const otaPktPtr, FIFO<AP_MAX_BUF_LEN> *outputBuffer);
201 #if defined(DEBUG_RCVR_LINKSTATS)
202 extern uint32_t debugRcvrLinkstatsPacketId;
203 #endif
205 #endif // H_OTA