14 Telemetry::Telemetry()
19 bool Telemetry::ShouldCallBootloader()
21 bool bootloader
= callBootloader
;
22 callBootloader
= false;
26 bool Telemetry::ShouldCallEnterBind()
28 bool enterBind
= callEnterBind
;
29 callEnterBind
= false;
33 bool Telemetry::ShouldCallUpdateModelMatch()
35 bool updateModelMatch
= callUpdateModelMatch
;
36 callUpdateModelMatch
= false;
37 return updateModelMatch
;
40 bool Telemetry::ShouldSendDeviceFrame()
42 bool deviceFrame
= sendDeviceFrame
;
43 sendDeviceFrame
= false;
48 PAYLOAD_DATA(GPS
, BATTERY_SENSOR
, ATTITUDE
, DEVICE_INFO
, FLIGHT_MODE
, VARIO
);
50 bool Telemetry::GetNextPayload(uint8_t* nextPayloadSize
, uint8_t **payloadData
)
53 uint8_t oldPayloadIndex
= currentPayloadIndex
;
54 uint8_t realLength
= 0;
56 if (payloadTypes
[currentPayloadIndex
].locked
)
58 payloadTypes
[currentPayloadIndex
].locked
= false;
59 payloadTypes
[currentPayloadIndex
].updated
= false;
64 currentPayloadIndex
= (currentPayloadIndex
+ 1) % payloadTypesCount
;
66 } while(!payloadTypes
[currentPayloadIndex
].updated
&& checks
< payloadTypesCount
);
68 if (payloadTypes
[currentPayloadIndex
].updated
)
70 payloadTypes
[currentPayloadIndex
].locked
= true;
72 realLength
= CRSF_FRAME_SIZE(payloadTypes
[currentPayloadIndex
].data
[CRSF_TELEMETRY_LENGTH_INDEX
]);
73 // search for non zero data from the end
74 while (realLength
> 0 && payloadTypes
[currentPayloadIndex
].data
[realLength
- 1] == 0)
81 // store real length in frame
82 payloadTypes
[currentPayloadIndex
].data
[CRSF_TELEMETRY_LENGTH_INDEX
] = realLength
- CRSF_FRAME_NOT_COUNTED_BYTES
;
83 *nextPayloadSize
= realLength
;
84 *payloadData
= payloadTypes
[currentPayloadIndex
].data
;
89 currentPayloadIndex
= oldPayloadIndex
;
95 uint8_t Telemetry::UpdatedPayloadCount()
98 for (int8_t i
= 0; i
< payloadTypesCount
; i
++)
100 if (payloadTypes
[i
].updated
)
109 uint8_t Telemetry::ReceivedPackagesCount()
111 return receivedPackages
;
114 void Telemetry::ResetState()
116 telemetry_state
= TELEMETRY_IDLE
;
117 currentTelemetryByte
= 0;
118 currentPayloadIndex
= 0;
119 receivedPackages
= 0;
123 for (int8_t i
= 0; i
< payloadTypesCount
; i
++)
125 payloadTypes
[i
].locked
= false;
126 payloadTypes
[i
].updated
= false;
127 payloadTypes
[i
].data
= PayloadData
+ offset
;
128 offset
+= payloadTypes
[i
].size
;
130 #if defined(UNIT_TEST)
131 if (offset
> sizeof(PayloadData
)) {
132 cout
<< "data not large enough\n";
138 bool Telemetry::RXhandleUARTin(uint8_t data
)
140 switch(telemetry_state
) {
142 if (data
== CRSF_ADDRESS_CRSF_RECEIVER
|| data
== CRSF_SYNC_BYTE
)
144 currentTelemetryByte
= 0;
145 telemetry_state
= RECEIVING_LENGTH
;
146 CRSFinBuffer
[0] = data
;
153 case RECEIVING_LENGTH
:
154 if (data
>= CRSF_MAX_PACKET_LEN
)
156 telemetry_state
= TELEMETRY_IDLE
;
161 telemetry_state
= RECEIVING_DATA
;
162 CRSFinBuffer
[CRSF_TELEMETRY_LENGTH_INDEX
] = data
;
167 CRSFinBuffer
[currentTelemetryByte
+ CRSF_FRAME_NOT_COUNTED_BYTES
] = data
;
168 currentTelemetryByte
++;
169 if (CRSFinBuffer
[CRSF_TELEMETRY_LENGTH_INDEX
] == currentTelemetryByte
)
171 // exclude first bytes (sync byte + length), skip last byte (submitted crc)
172 uint8_t crc
= crsf_crc
.calc(CRSFinBuffer
+ CRSF_FRAME_NOT_COUNTED_BYTES
, CRSFinBuffer
[CRSF_TELEMETRY_LENGTH_INDEX
] - CRSF_TELEMETRY_CRC_LENGTH
);
173 telemetry_state
= TELEMETRY_IDLE
;
177 AppendTelemetryPackage(CRSFinBuffer
);
181 #if defined(UNIT_TEST)
184 cout
<< "invalid " << (int)crc
<< '\n';
197 bool Telemetry::AppendTelemetryPackage(uint8_t *package
)
199 const crsf_header_t
*header
= (crsf_header_t
*) package
;
201 if (header
->type
== CRSF_FRAMETYPE_COMMAND
&& package
[3] == 'b' && package
[4] == 'l')
203 callBootloader
= true;
206 if (header
->type
== CRSF_FRAMETYPE_COMMAND
&& package
[3] == 'b' && package
[4] == 'd')
208 callEnterBind
= true;
211 if (header
->type
== CRSF_FRAMETYPE_COMMAND
&& package
[3] == 'm' && package
[4] == 'm')
213 callUpdateModelMatch
= true;
214 modelMatchId
= package
[5];
217 if (header
->type
== CRSF_FRAMETYPE_DEVICE_PING
&& package
[CRSF_TELEMETRY_TYPE_INDEX
+ 1] == CRSF_ADDRESS_CRSF_RECEIVER
)
219 sendDeviceFrame
= true;
223 uint8_t targetIndex
= 0;
224 bool targetFound
= false;
227 if (header
->type
>= CRSF_FRAMETYPE_DEVICE_PING
)
229 const crsf_ext_header_t
*extHeader
= (crsf_ext_header_t
*) package
;
231 if (header
->type
== CRSF_FRAMETYPE_ARDUPILOT_RESP
)
233 // reserve last slot for adrupilot custom frame with the sub type status text: this is needed to make sure the important status messages are not lost
234 if (package
[CRSF_TELEMETRY_TYPE_INDEX
+ 1] == CRSF_AP_CUSTOM_TELEM_STATUS_TEXT
)
236 targetIndex
= payloadTypesCount
- 1;
240 targetIndex
= payloadTypesCount
- 2;
244 else if (extHeader
->orig_addr
== CRSF_ADDRESS_FLIGHT_CONTROLLER
)
246 targetIndex
= payloadTypesCount
- 2;
249 // larger msp resonses are sent in two chunks so special handling is needed so both get sent
250 if (header
->type
== CRSF_FRAMETYPE_MSP_RESP
)
252 // there is already another response stored
253 if (payloadTypes
[targetIndex
].updated
)
256 targetIndex
= payloadTypesCount
- 1;
259 // if both slots are taked do not overwrite other data since the first chunk would be lost
260 if (payloadTypes
[targetIndex
].updated
)
268 targetIndex
= payloadTypesCount
- 1;
274 for (int8_t i
= 0; i
< payloadTypesCount
- 2; i
++)
276 if (header
->type
== payloadTypes
[i
].type
)
278 if (!payloadTypes
[i
].locked
&& CRSF_FRAME_SIZE(package
[CRSF_TELEMETRY_LENGTH_INDEX
]) <= payloadTypes
[i
].size
)
283 #if defined(UNIT_TEST)
284 else if (CRSF_FRAME_SIZE(package
[CRSF_TELEMETRY_LENGTH_INDEX
]) > payloadTypes
[i
].size
)
286 cout
<< "buffer not large enough for type " << (int)payloadTypes
[i
].type
<< " with size " << (int)payloadTypes
[i
].size
<< " would need " << CRSF_FRAME_SIZE(package
[CRSF_TELEMETRY_LENGTH_INDEX
]) << '\n';
296 memcpy(payloadTypes
[targetIndex
].data
, package
, CRSF_FRAME_SIZE(package
[CRSF_TELEMETRY_LENGTH_INDEX
]));
297 payloadTypes
[targetIndex
].updated
= true;