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