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.
25 #include "crossfire.h"
26 #if defined(MULTIMODULE)
28 #include "flysky_ibus.h"
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
{
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
58 #define TELEMETRY_RX_PACKET_SIZE 19 // 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1)
61 extern uint8_t telemetryRxBuffer
[TELEMETRY_RX_PACKET_SIZE
];
62 extern uint8_t telemetryRxBufferCount
;
64 #define TELEMETRY_AVERAGE_COUNT 3
67 TELEM_CELL_INDEX_LOWEST
,
74 TELEM_CELL_INDEX_HIGHEST
,
75 TELEM_CELL_INDEX_DELTA
,
83 void set(uint16_t value
)
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))))
113 #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && IS_D16_MULTI(EXTERNAL_MODULE)))
116 #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT)
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
;
126 inline bool isSportLineUsedByInternalModule()
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
;
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
;
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)
163 #define LOG_TELEMETRY_WRITE_START()
164 #define LOG_TELEMETRY_WRITE_BYTE(data)
167 class OutputTelemetryBuffer
{
169 OutputTelemetryBuffer()
174 void setDestination(uint8_t value
)
177 timeout
= 200; /* 2s */
180 bool isModuleDestination(uint8_t module
)
182 return destination
!= TELEMETRY_ENDPOINT_NONE
&& destination
!= TELEMETRY_ENDPOINT_SPORT
&& (destination
>> 2) == module
;
195 destination
= TELEMETRY_ENDPOINT_NONE
;
202 return destination
== TELEMETRY_ENDPOINT_NONE
;
205 void pushByte(uint8_t byte
)
210 void pushByteWithBytestuffing(uint8_t byte
)
212 if (byte
== 0x7E || byte
== 0x7D) {
214 pushByte(0x20 ^ byte
);
221 void pushSportPacketWithBytestuffing(SportTelemetryPacket
& packet
)
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
233 pushByteWithBytestuffing(0xFF - crc
);
238 SportTelemetryPacket sport
;
246 extern OutputTelemetryBuffer outputTelemetryBuffer __DMA
;
249 #define LUA_TELEMETRY_INPUT_FIFO_SIZE 256
250 extern Fifo
<uint8_t, LUA_TELEMETRY_INPUT_FIFO_SIZE
> * luaInputTelemetryFifo
;
253 void processPXX2Frame(uint8_t module
, const uint8_t *frame
);
255 #endif // _TELEMETRY_H_