Various fixes around Companion trainer mode (#7116)
[opentx.git] / radio / src / telemetry / telemetry.h
blob8b5aadc67f1b3049adc8090558c5d23d260d85b0
1 /*
2 * Copyright (C) OpenTX
4 * Based on code named
5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 #ifndef _TELEMETRY_H_
22 #define _TELEMETRY_H_
24 #include "frsky.h"
25 #include "crossfire.h"
26 #if defined(MULTIMODULE)
27 #include "spektrum.h"
28 #include "flysky_ibus.h"
29 #include "hitec.h"
30 #include "hott.h"
31 #include "multi.h"
32 #endif
34 extern uint8_t telemetryStreaming; // >0 (true) == data is streaming in. 0 = no data detected for some time
36 inline bool TELEMETRY_STREAMING()
38 return telemetryStreaming > 0;
41 enum TelemetryStates {
42 TELEMETRY_INIT,
43 TELEMETRY_OK,
44 TELEMETRY_KO
46 extern uint8_t telemetryState;
48 constexpr uint8_t TELEMETRY_TIMEOUT10ms = 100; // 1 second
50 #define TELEMETRY_SERIAL_DEFAULT 0
51 #define TELEMETRY_SERIAL_8E2 1
52 #define TELEMETRY_SERIAL_WITHOUT_DMA 2
54 #if defined(CROSSFIRE) || defined(MULTIMODULE)
55 #define TELEMETRY_RX_PACKET_SIZE 128
56 // multi module Spektrum telemetry is 18 bytes, FlySky is 37 bytes
57 #else
58 #define TELEMETRY_RX_PACKET_SIZE 19 // 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1)
59 #endif
61 extern uint8_t telemetryRxBuffer[TELEMETRY_RX_PACKET_SIZE];
62 extern uint8_t telemetryRxBufferCount;
64 #define TELEMETRY_AVERAGE_COUNT 3
66 enum {
67 TELEM_CELL_INDEX_LOWEST,
68 TELEM_CELL_INDEX_1,
69 TELEM_CELL_INDEX_2,
70 TELEM_CELL_INDEX_3,
71 TELEM_CELL_INDEX_4,
72 TELEM_CELL_INDEX_5,
73 TELEM_CELL_INDEX_6,
74 TELEM_CELL_INDEX_HIGHEST,
75 TELEM_CELL_INDEX_DELTA,
78 PACK(struct CellValue
80 uint16_t value:15;
81 uint16_t state:1;
83 void set(uint16_t value)
85 if (value > 50) {
86 this->value = value;
87 this->state = 1;
90 });
92 int setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t subId, uint8_t instance, int32_t value, uint32_t unit, uint32_t prec);
93 void delTelemetryIndex(uint8_t index);
94 int availableTelemetryIndex();
95 int lastUsedTelemetryIndex();
97 int32_t convertTelemetryValue(int32_t value, uint8_t unit, uint8_t prec, uint8_t destUnit, uint8_t destPrec);
99 void frskySportSetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance);
100 void frskyDSetDefault(int index, uint16_t id);
102 #define IS_DISTANCE_UNIT(unit) ((unit) == UNIT_METERS || (unit) == UNIT_FEET)
103 #define IS_SPEED_UNIT(unit) ((unit) >= UNIT_KTS && (unit) <= UNIT_MPH)
105 extern uint8_t telemetryProtocol;
107 #if defined (MULTIMODULE)
108 #define IS_D16_MULTI(module) ((g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKY) && (g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16 || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_8CH || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_LBT || g_model.moduleData[module].subType == MM_RF_FRSKY_SUBTYPE_D16_LBT_8CH))
109 #define IS_HOTT_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_HOTT)
110 #if defined(HARDWARE_INTERNAL_MODULE)
111 #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && (IS_D16_MULTI(INTERNAL_MODULE)||IS_D16_MULTI(EXTERNAL_MODULE))))
112 #else
113 #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && IS_D16_MULTI(EXTERNAL_MODULE)))
114 #endif
115 #else
116 #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT)
117 #endif
118 #define IS_SPEKTRUM_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_SPEKTRUM)
120 #if defined(PCBTARANIS) || defined(PCBHORUS)
121 inline bool isSportLineUsedByInternalModule()
123 return g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_XJT_PXX1;
125 #else
126 inline bool isSportLineUsedByInternalModule()
128 return false;
130 #endif
132 inline uint8_t modelTelemetryProtocol()
134 bool sportUsed = isSportLineUsedByInternalModule();
136 #if defined(CROSSFIRE)
137 if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_CROSSFIRE) {
138 return PROTOCOL_TELEMETRY_CROSSFIRE;
140 #endif
142 if (!sportUsed && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM) {
143 return g_model.telemetryProtocol;
146 #if defined(MULTIMODULE)
147 if (!sportUsed && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE) {
148 return PROTOCOL_TELEMETRY_MULTIMODULE;
150 #endif
151 // default choice
152 return PROTOCOL_TELEMETRY_FRSKY_SPORT;
155 #include "telemetry_sensors.h"
157 #if defined(LOG_TELEMETRY) && !defined(SIMU)
158 void logTelemetryWriteStart();
159 void logTelemetryWriteByte(uint8_t data);
160 #define LOG_TELEMETRY_WRITE_START() logTelemetryWriteStart()
161 #define LOG_TELEMETRY_WRITE_BYTE(data) logTelemetryWriteByte(data)
162 #else
163 #define LOG_TELEMETRY_WRITE_START()
164 #define LOG_TELEMETRY_WRITE_BYTE(data)
165 #endif
167 class OutputTelemetryBuffer {
168 public:
169 OutputTelemetryBuffer()
171 reset();
174 void setDestination(uint8_t value)
176 destination = value;
177 timeout = 200; /* 2s */
180 bool isModuleDestination(uint8_t module)
182 return destination != TELEMETRY_ENDPOINT_NONE && destination != TELEMETRY_ENDPOINT_SPORT && (destination >> 2) == module;
185 void per10ms()
187 if (timeout > 0) {
188 if (--timeout == 0)
189 reset();
193 void reset()
195 destination = TELEMETRY_ENDPOINT_NONE;
196 size = 0;
197 timeout = 0;
200 bool isAvailable()
202 return destination == TELEMETRY_ENDPOINT_NONE;
205 void pushByte(uint8_t byte)
207 data[size++] = byte;
210 void pushByteWithBytestuffing(uint8_t byte)
212 if (byte == 0x7E || byte == 0x7D) {
213 pushByte(0x7D);
214 pushByte(0x20 ^ byte);
216 else {
217 pushByte(byte);
221 void pushSportPacketWithBytestuffing(SportTelemetryPacket & packet)
223 size = 0;
224 uint16_t crc = 0;
225 pushByte(packet.physicalId); // no bytestuffing, no CRC
226 for (uint8_t i=1; i<sizeof(SportTelemetryPacket); i++) {
227 uint8_t byte = packet.raw[i];
228 pushByteWithBytestuffing(byte);
229 crc += byte; // 0-1FF
230 crc += crc >> 8; // 0-100
231 crc &= 0x00ff;
233 pushByteWithBytestuffing(0xFF - crc);
236 public:
237 union {
238 SportTelemetryPacket sport;
239 uint8_t data[16];
241 uint8_t size;
242 uint8_t timeout;
243 uint8_t destination;
246 extern OutputTelemetryBuffer outputTelemetryBuffer __DMA;
248 #if defined(LUA)
249 #define LUA_TELEMETRY_INPUT_FIFO_SIZE 256
250 extern Fifo<uint8_t, LUA_TELEMETRY_INPUT_FIFO_SIZE> * luaInputTelemetryFifo;
251 #endif
253 void processPXX2Frame(uint8_t module, const uint8_t *frame);
255 #endif // _TELEMETRY_H_