7 #if defined(USE_DSHOT_TELEMETRY)
9 #include "common/maths.h"
10 #include "common/utils.h"
11 #include "drivers/dshot.h"
12 #include "drivers/dshot_bitbang_decode.h"
14 #define MIN_VALID_BBSAMPLES ((21 - 2) * 3)
15 #define MAX_VALID_BBSAMPLES ((21 + 2) * 3)
17 // setting this define in dshot.h allows the cli command dshot_telemetry_info to
18 // display the received telemetry data in raw form which helps identify
19 // the root cause of packet decoding issues.
22 uint16_t bbBuffer
[134];
26 /* Bit band SRAM definitions */
27 #define BITBAND_SRAM_REF 0x20000000
28 #define BITBAND_SRAM_BASE 0x22000000
29 #define BITBAND_SRAM(a,b) ((BITBAND_SRAM_BASE + (((a)-BITBAND_SRAM_REF)<<5) + ((b)<<2))) // Convert SRAM address
31 typedef struct bitBandWord_s
{
37 uint32_t sequence
[MAX_GCR_EDGES
];
38 int sequenceIndex
= 0;
42 static uint32_t decode_bb_value(uint32_t value
, uint16_t buffer
[], uint32_t count
, uint32_t bit
)
44 #ifndef DEBUG_BBDECODE
50 // First bit is start bit so discard it.
52 static const uint32_t decode
[32] = {
53 iv
, iv
, iv
, iv
, iv
, iv
, iv
, iv
, iv
, 9, 10, 11, iv
, 13, 14, 15,
54 iv
, iv
, 2, 3, iv
, 5, 6, 7, iv
, 0, 8, 1, iv
, 4, 12, iv
};
56 uint32_t decodedValue
= decode
[value
& 0x1f];
57 decodedValue
|= decode
[(value
>> 5) & 0x1f] << 4;
58 decodedValue
|= decode
[(value
>> 10) & 0x1f] << 8;
59 decodedValue
|= decode
[(value
>> 15) & 0x1f] << 12;
61 uint32_t csum
= decodedValue
;
62 csum
= csum
^ (csum
>> 8); // xor bytes
63 csum
= csum
^ (csum
>> 4); // xor nibbles
65 if ((csum
& 0xf) != 0xf || decodedValue
> 0xffff) {
67 memcpy(dshotTelemetryState
.inputBuffer
, sequence
, sizeof(sequence
));
68 for (unsigned i
= 0; i
< count
; i
++) {
69 bbBuffer
[i
] = !!(buffer
[i
] & (1 << bit
));
74 value
= decodedValue
>> 4;
76 if (value
== 0x0fff) {
79 // Convert value to 16 bit from the GCR telemetry format (eeem mmmm mmmm)
80 value
= (value
& 0x000001ff) << ((value
& 0xfffffe00) >> 9);
84 // Convert period to erpm * 100
85 value
= (1000000 * 60 / 100 + value
/ 2) / value
;
91 uint32_t decode_bb_bitband( uint16_t buffer
[], uint32_t count
, uint32_t bit
)
94 memset(sequence
, 0, sizeof(sequence
));
99 bitBandWord_t
* p
= (bitBandWord_t
*)BITBAND_SRAM((uint32_t)buffer
, bit
);
100 bitBandWord_t
* b
= p
;
101 bitBandWord_t
* endP
= p
+ (count
- MIN_VALID_BBSAMPLES
);
103 // Eliminate leading high signal level by looking for first zero bit in data stream.
104 // Manual loop unrolling and branch hinting to produce faster code.
106 if (__builtin_expect((!(p
++)->value
), 0) ||
107 __builtin_expect((!(p
++)->value
), 0) ||
108 __builtin_expect((!(p
++)->value
), 0) ||
109 __builtin_expect((!(p
++)->value
), 0)) {
115 // not returning telemetry is ok if the esc cpu is
116 // overburdened. in that case no edge will be found and
117 // BB_NOEDGE indicates the condition to caller
121 int remaining
= MIN(count
- (p
- b
), (unsigned int)MAX_VALID_BBSAMPLES
);
123 bitBandWord_t
* oldP
= p
;
125 endP
= p
+ remaining
;
127 #ifdef DEBUG_BBDECODE
128 sequence
[sequenceIndex
++] = p
- b
;
133 // Look for next positive edge. Manual loop unrolling and branch hinting to produce faster code.
134 if(__builtin_expect((p
++)->value
, 0) ||
135 __builtin_expect((p
++)->value
, 0) ||
136 __builtin_expect((p
++)->value
, 0) ||
137 __builtin_expect((p
++)->value
, 0)) {
144 #ifdef DEBUG_BBDECODE
145 sequence
[sequenceIndex
++] = p
- b
;
147 // A level of length n gets decoded to a sequence of bits of
148 // the form 1000 with a length of (n+1) / 3 to account for 3x
150 const int len
= MAX((p
- oldP
+ 1) / 3, 1);
153 value
|= 1 << (len
- 1);
156 // Look for next zero edge. Manual loop unrolling and branch hinting to produce faster code.
158 if (__builtin_expect(!(p
++)->value
, 0) ||
159 __builtin_expect(!(p
++)->value
, 0) ||
160 __builtin_expect(!(p
++)->value
, 0) ||
161 __builtin_expect(!(p
++)->value
, 0)) {
168 #ifdef DEBUG_BBDECODE
169 sequence
[sequenceIndex
++] = p
- b
;
171 // A level of length n gets decoded to a sequence of bits of
172 // the form 1000 with a length of (n+1) / 3 to account for 3x
174 const int len
= MAX((p
- oldP
+ 1) / 3, 1);
177 value
|= 1 << (len
- 1);
187 // length of last sequence has to be inferred since the last bit with inverted dshot is high
188 const int nlen
= 21 - bits
;
193 #ifdef DEBUG_BBDECODE
194 sequence
[sequenceIndex
] = sequence
[sequenceIndex
] + (nlen
) * 3;
199 value
|= 1 << (nlen
- 1);
201 return decode_bb_value(value
, buffer
, count
, bit
);
204 FAST_CODE
uint32_t decode_bb( uint16_t buffer
[], uint32_t count
, uint32_t bit
)
206 #ifdef DEBUG_BBDECODE
207 memset(sequence
, 0, sizeof(sequence
));
210 uint32_t mask
= 1 << bit
;
212 #ifdef DEBUG_BBDECODE
213 uint32_t sequence
[MAX_GCR_EDGES
];
214 memset(sequence
, 0, sizeof(sequence
));
215 int sequenceIndex
= 0;
218 uint16_t lastValue
= 0;
221 uint16_t* p
= buffer
;
222 uint16_t* endP
= p
+ count
- MIN_VALID_BBSAMPLES
;
223 // Eliminate leading high signal level by looking for first zero bit in data stream.
224 // Manual loop unrolling and branch hinting to produce faster code.
226 if (__builtin_expect(!(*p
++ & mask
), 0) ||
227 __builtin_expect(!(*p
++ & mask
), 0) ||
228 __builtin_expect(!(*p
++ & mask
), 0) ||
229 __builtin_expect(!(*p
++ & mask
), 0)) {
235 // not returning telemetry is ok if the esc cpu is
236 // overburdened. in that case no edge will be found and
237 // BB_NOEDGE indicates the condition to caller
241 int remaining
= MIN(count
- (p
- buffer
), (unsigned int)MAX_VALID_BBSAMPLES
);
245 endP
= p
+ remaining
;
247 #ifdef DEBUG_BBDECODE
248 sequence
[sequenceIndex
++] = p
- buffer
;
252 // Look for next edge. Manual loop unrolling and branch hinting to produce faster code.
253 if (__builtin_expect((*p
++ & mask
) != lastValue
, 0) ||
254 __builtin_expect((*p
++ & mask
) != lastValue
, 0) ||
255 __builtin_expect((*p
++ & mask
) != lastValue
, 0) ||
256 __builtin_expect((*p
++ & mask
) != lastValue
, 0)) {
258 #ifdef DEBUG_BBDECODE
259 sequence
[sequenceIndex
++] = p
- buffer
;
261 // A level of length n gets decoded to a sequence of bits of
262 // the form 1000 with a length of (n+1) / 3 to account for 3x
264 const int len
= MAX((p
- oldP
+ 1) / 3,1);
267 value
|= 1 << (len
- 1);
269 lastValue
= *(p
-1) & mask
;
274 // length of last sequence has to be inferred since the last bit with inverted dshot is high
279 const int nlen
= 21 - bits
;
280 #ifdef DEBUG_BBDECODE
281 sequence
[sequenceIndex
] = sequence
[sequenceIndex
] + (nlen
) * 3;
290 value
|= 1 << (nlen
- 1);
292 return decode_bb_value(value
, buffer
, count
, bit
);