Auto configure Rx OTA protocol from the Tx (#2994)
[ExpressLRS.git] / src / lib / OTA / OTA.h
blob7f9161970fd2b2ef6173fd030857d0de012da2de
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 otaProtocol:2,
36 free:1;
37 uint8_t UID4;
38 uint8_t UID5;
39 } PACKED OTA_Sync_s;
41 typedef struct {
42 uint8_t uplink_RSSI_1:7,
43 antenna:1;
44 uint8_t uplink_RSSI_2:7,
45 modelMatch:1;
46 uint8_t lq:7,
47 tlmConfirm:1;
48 int8_t SNR;
49 } PACKED OTA_LinkStats_s;
51 typedef struct {
52 uint8_t raw[5]; // 4x 10-bit channels, see PackUInt11ToChannels4x10 for encoding
53 } PACKED OTA_Channels_4x10;
55 typedef struct {
56 // The packet type must always be the low two bits of the first byte of the
57 // packet to match the same placement in OTA_Packet8_s
58 uint8_t type: 2,
59 crcHigh: 6;
60 union {
61 /** PACKET_TYPE_RCDATA **/
62 struct {
63 OTA_Channels_4x10 ch;
64 uint8_t switches:7,
65 ch4:1;
66 } rc;
67 struct {
68 uint32_t packetNum; // LittleEndian
69 uint8_t free[2];
70 } PACKED dbg_linkstats;
71 /** PACKET_TYPE_MSP **/
72 struct {
73 uint8_t packageIndex:7,
74 tlmConfirm:1;
75 uint8_t payload[ELRS4_MSP_BYTES_PER_CALL];
76 } msp_ul;
77 /** PACKET_TYPE_SYNC **/
78 OTA_Sync_s sync;
79 /** PACKET_TYPE_TLM **/
80 struct {
81 uint8_t free:1,
82 tlmConfirm: 1,
83 packageIndex:6;
84 union {
85 struct {
86 OTA_LinkStats_s stats;
87 uint8_t free;
88 } PACKED ul_link_stats;
89 uint8_t payload[ELRS4_TELEMETRY_BYTES_PER_CALL];
91 } tlm_dl; // PACKET_TYPE_TLM
92 /** PACKET_TYPE_AIRPORT **/
93 struct {
94 uint8_t free:2,
95 count:6;
96 uint8_t payload[ELRS4_TELEMETRY_BYTES_PER_CALL];
97 } PACKED airport;
99 uint8_t crcLow;
100 } PACKED OTA_Packet4_s;
102 typedef struct {
103 // Like OTA_Packet4_s **the type is always the low two bits of the first byte**,
104 // but they are speficied in each type in the union as the other bits there
105 // are not universal
106 union {
107 /** PACKET_TYPE_RCDATA **/
108 struct {
109 uint8_t packetType: 2,
110 telemetryStatus: 1,
111 uplinkPower: 3, // CRSF_power_level - 1 (1-8 is 0-7 in the air)
112 isHighAux: 1, // true if chHigh are AUX6-9
113 ch4: 1; // AUX1, included up here so ch0 starts on a byte boundary
114 OTA_Channels_4x10 chLow; // CH0-CH3
115 OTA_Channels_4x10 chHigh; // AUX2-5 or AUX6-9
116 } PACKED rc;
117 struct {
118 uint8_t packetType; // actually struct rc's first byte
119 uint32_t packetNum; // LittleEndian
120 uint8_t free[6];
121 } PACKED dbg_linkstats;
122 /** PACKET_TYPE_MSP **/
123 struct {
124 uint8_t packetType: 2,
125 packageIndex: 5,
126 tlmConfirm: 1;
127 uint8_t payload[ELRS8_MSP_BYTES_PER_CALL];
128 } msp_ul;
129 /** PACKET_TYPE_SYNC **/
130 struct {
131 uint8_t packetType; // only low 2 bits
132 OTA_Sync_s sync;
133 uint8_t free[4];
134 } PACKED sync;
135 /** PACKET_TYPE_TLM **/
136 struct {
137 uint8_t packetType: 2,
138 tlmConfirm: 1,
139 packageIndex: 5;
140 union {
141 struct {
142 OTA_LinkStats_s stats;
143 uint8_t payload[ELRS8_TELEMETRY_BYTES_PER_CALL - sizeof(OTA_LinkStats_s)];
144 } PACKED ul_link_stats; // containsLinkStats == true
145 uint8_t payload[ELRS8_TELEMETRY_BYTES_PER_CALL]; // containsLinkStats == false
147 } PACKED tlm_dl;
148 /** PACKET_TYPE_AIRPORT **/
149 struct {
150 uint8_t packetType: 2,
151 free: 1,
152 count: 5;
153 uint8_t payload[ELRS8_TELEMETRY_BYTES_PER_CALL];
154 } PACKED airport;
156 uint16_t crc; // crc16 LittleEndian
157 } PACKED OTA_Packet8_s;
159 typedef struct {
160 union {
161 OTA_Packet4_s std;
162 OTA_Packet8_s full;
164 } PACKED OTA_Packet_s;
166 extern bool OtaIsFullRes;
167 extern volatile uint8_t OtaNonce;
168 extern uint16_t OtaCrcInitializer;
169 void OtaUpdateCrcInitFromUid();
171 enum OtaSwitchMode_e { smWideOr8ch = 0, smHybridOr16ch = 1, sm12ch = 2 };
172 void OtaUpdateSerializers(OtaSwitchMode_e const mode, uint8_t packetSize);
173 extern OtaSwitchMode_e OtaSwitchModeCurrent;
175 // CRC
176 typedef bool (*ValidatePacketCrc_t)(OTA_Packet_s * const otaPktPtr);
177 typedef void (*GeneratePacketCrc_t)(OTA_Packet_s * const otaPktPtr);
178 extern ValidatePacketCrc_t OtaValidatePacketCrc;
179 extern GeneratePacketCrc_t OtaGeneratePacketCrc;
180 // Value is implicit leading 1, comment is Koopman formatting (implicit trailing 1) https://users.ece.cmu.edu/~koopman/crc/
181 #define ELRS_CRC_POLY 0x07 // 0x83
182 #define ELRS_CRC14_POLY 0x2E57 // 0x372b
183 #define ELRS_CRC16_POLY 0x3D65 // 0x9eb2
185 #if defined(TARGET_TX) || defined(UNIT_TEST)
186 typedef void (*PackChannelData_t)(OTA_Packet_s * const otaPktPtr, const uint32_t *channelData, bool TelemetryStatus, uint8_t tlmDenom);
187 extern PackChannelData_t OtaPackChannelData;
188 #if defined(UNIT_TEST)
189 void OtaSetHybrid8NextSwitchIndex(uint8_t idx);
190 void OtaSetFullResNextChannelSet(bool next);
191 #endif
192 #endif
194 #if defined(TARGET_RX) || defined(UNIT_TEST)
195 typedef bool (*UnpackChannelData_t)(OTA_Packet_s const * const otaPktPtr, uint32_t *channelData, uint8_t tlmDenom);
196 extern UnpackChannelData_t OtaUnpackChannelData;
197 #endif
199 void OtaPackAirportData(OTA_Packet_s * const otaPktPtr, FIFO<AP_MAX_BUF_LEN> *inputBuffer);
200 void OtaUnpackAirportData(OTA_Packet_s const * const otaPktPtr, FIFO<AP_MAX_BUF_LEN> *outputBuffer);
202 #if defined(DEBUG_RCVR_LINKSTATS)
203 extern uint32_t debugRcvrLinkstatsPacketId;
204 #endif
206 #endif // H_OTA