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