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
33 typedef struct bitBandWord_s
{
41 uint32_t sequence
[MAX_GCR_EDGES
];
42 int sequenceIndex
= 0;
46 static uint32_t decode_bb_value(uint32_t value
, uint16_t buffer
[], uint32_t count
, uint32_t bit
)
48 #ifndef DEBUG_BBDECODE
54 // First bit is start bit so discard it.
56 static const uint32_t decode
[32] = {
57 iv
, iv
, iv
, iv
, iv
, iv
, iv
, iv
, iv
, 9, 10, 11, iv
, 13, 14, 15,
58 iv
, iv
, 2, 3, iv
, 5, 6, 7, iv
, 0, 8, 1, iv
, 4, 12, iv
};
60 uint32_t decodedValue
= decode
[value
& 0x1f];
61 decodedValue
|= decode
[(value
>> 5) & 0x1f] << 4;
62 decodedValue
|= decode
[(value
>> 10) & 0x1f] << 8;
63 decodedValue
|= decode
[(value
>> 15) & 0x1f] << 12;
65 uint32_t csum
= decodedValue
;
66 csum
= csum
^ (csum
>> 8); // xor bytes
67 csum
= csum
^ (csum
>> 4); // xor nibbles
69 if ((csum
& 0xf) != 0xf || decodedValue
> 0xffff) {
71 memcpy(dshotTelemetryState
.inputBuffer
, sequence
, sizeof(sequence
));
72 for (unsigned i
= 0; i
< count
; i
++) {
73 bbBuffer
[i
] = !!(buffer
[i
] & (1 << bit
));
76 value
= DSHOT_TELEMETRY_INVALID
;
78 value
= decodedValue
>> 4;
85 uint32_t decode_bb_bitband( uint16_t buffer
[], uint32_t count
, uint32_t bit
)
88 memset(sequence
, 0, sizeof(sequence
));
93 bitBandWord_t
* p
= (bitBandWord_t
*)BITBAND_SRAM((uint32_t)buffer
, bit
);
95 bitBandWord_t
* endP
= p
+ (count
- MIN_VALID_BBSAMPLES
);
97 // Eliminate leading high signal level by looking for first zero bit in data stream.
98 // Manual loop unrolling and branch hinting to produce faster code.
100 if (__builtin_expect((!(p
++)->value
), 0) ||
101 __builtin_expect((!(p
++)->value
), 0) ||
102 __builtin_expect((!(p
++)->value
), 0) ||
103 __builtin_expect((!(p
++)->value
), 0)) {
109 // not returning telemetry is ok if the esc cpu is
110 // overburdened. in that case no edge will be found and
111 // BB_NOEDGE indicates the condition to caller
112 return DSHOT_TELEMETRY_NOEDGE
;
115 int remaining
= MIN(count
- (p
- b
), (unsigned int)MAX_VALID_BBSAMPLES
);
117 bitBandWord_t
* oldP
= p
;
119 endP
= p
+ remaining
;
121 #ifdef DEBUG_BBDECODE
122 sequence
[sequenceIndex
++] = p
- b
;
127 // Look for next positive edge. Manual loop unrolling and branch hinting to produce faster code.
128 if(__builtin_expect((p
++)->value
, 0) ||
129 __builtin_expect((p
++)->value
, 0) ||
130 __builtin_expect((p
++)->value
, 0) ||
131 __builtin_expect((p
++)->value
, 0)) {
138 #ifdef DEBUG_BBDECODE
139 sequence
[sequenceIndex
++] = p
- b
;
141 // A level of length n gets decoded to a sequence of bits of
142 // the form 1000 with a length of (n+1) / 3 to account for 3x
144 const int len
= MAX((p
- oldP
+ 1) / 3, 1);
147 value
|= 1 << (len
- 1);
150 // Look for next zero edge. Manual loop unrolling and branch hinting to produce faster code.
152 if (__builtin_expect(!(p
++)->value
, 0) ||
153 __builtin_expect(!(p
++)->value
, 0) ||
154 __builtin_expect(!(p
++)->value
, 0) ||
155 __builtin_expect(!(p
++)->value
, 0)) {
162 #ifdef DEBUG_BBDECODE
163 sequence
[sequenceIndex
++] = p
- b
;
165 // A level of length n gets decoded to a sequence of bits of
166 // the form 1000 with a length of (n+1) / 3 to account for 3x
168 const int len
= MAX((p
- oldP
+ 1) / 3, 1);
171 value
|= 1 << (len
- 1);
178 return DSHOT_TELEMETRY_NOEDGE
;
181 // length of last sequence has to be inferred since the last bit with inverted dshot is high
182 const int nlen
= 21 - bits
;
184 return DSHOT_TELEMETRY_NOEDGE
;
187 #ifdef DEBUG_BBDECODE
188 sequence
[sequenceIndex
] = sequence
[sequenceIndex
] + (nlen
) * 3;
193 value
|= 1 << (nlen
- 1);
196 return decode_bb_value(value
, buffer
, count
, bit
);
199 FAST_CODE
uint32_t decode_bb( uint16_t buffer
[], uint32_t count
, uint32_t bit
)
201 #ifdef DEBUG_BBDECODE
202 memset(sequence
, 0, sizeof(sequence
));
205 uint32_t mask
= 1 << bit
;
207 #ifdef DEBUG_BBDECODE
208 uint32_t sequence
[MAX_GCR_EDGES
];
209 memset(sequence
, 0, sizeof(sequence
));
210 int sequenceIndex
= 0;
213 uint16_t lastValue
= 0;
216 uint16_t* p
= buffer
;
217 uint16_t* endP
= p
+ count
- MIN_VALID_BBSAMPLES
;
218 // Eliminate leading high signal level by looking for first zero bit in data stream.
219 // Manual loop unrolling and branch hinting to produce faster code.
221 if (__builtin_expect(!(*p
++ & mask
), 0) ||
222 __builtin_expect(!(*p
++ & mask
), 0) ||
223 __builtin_expect(!(*p
++ & mask
), 0) ||
224 __builtin_expect(!(*p
++ & mask
), 0)) {
230 // not returning telemetry is ok if the esc cpu is
231 // overburdened. in that case no edge will be found and
232 // BB_NOEDGE indicates the condition to caller
233 return DSHOT_TELEMETRY_NOEDGE
;
236 int remaining
= MIN(count
- (p
- buffer
), (unsigned int)MAX_VALID_BBSAMPLES
);
240 endP
= p
+ remaining
;
242 #ifdef DEBUG_BBDECODE
243 sequence
[sequenceIndex
++] = p
- buffer
;
247 // Look for next edge. Manual loop unrolling and branch hinting to produce faster code.
248 if (__builtin_expect((*p
++ & mask
) != lastValue
, 0) ||
249 __builtin_expect((*p
++ & mask
) != lastValue
, 0) ||
250 __builtin_expect((*p
++ & mask
) != lastValue
, 0) ||
251 __builtin_expect((*p
++ & mask
) != lastValue
, 0)) {
253 #ifdef DEBUG_BBDECODE
254 sequence
[sequenceIndex
++] = p
- buffer
;
256 // A level of length n gets decoded to a sequence of bits of
257 // the form 1000 with a length of (n+1) / 3 to account for 3x
259 const int len
= MAX((p
- oldP
+ 1) / 3,1);
262 value
|= 1 << (len
- 1);
264 lastValue
= *(p
-1) & mask
;
269 // length of last sequence has to be inferred since the last bit with inverted dshot is high
271 return DSHOT_TELEMETRY_NOEDGE
;
274 const int nlen
= 21 - bits
;
275 #ifdef DEBUG_BBDECODE
276 sequence
[sequenceIndex
] = sequence
[sequenceIndex
] + (nlen
) * 3;
281 return DSHOT_TELEMETRY_NOEDGE
;
286 value
|= 1 << (nlen
- 1);
289 return decode_bb_value(value
, buffer
, count
, bit
);