/* Table GCR inverse : code 5 bits -> quartet, -1 si code invalide */
static const int8_t gcr_inv[32] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, 9, 10, 11, -1, 13, 14, 15,
-1, -1, 2, 3, -1, 5, 6, 7, -1, 0, 8, 1, -1, 4, 12, -1
};
/* Décode une réponse eRPM de 21 bits (bit de départ en tête, poids fort d'abord).
Renvoie la vitesse en eRPM, 0 moteur arrêté, -1 si la trame est invalide. */
int32_t dshot_reponse_erpm(uint32_t brut21)
{
uint32_t gcr = (brut21 ^ (brut21 >> 1)) & 0xFFFFF; /* transitions -> 20 bits GCR */
uint32_t trame = 0;
for (int q = 3; q >= 0; q--) {
int8_t n = gcr_inv[(gcr >> (q * 5)) & 0x1F];
if (n < 0)
return -1;
trame = (trame << 4) | (uint32_t)n;
}
uint32_t x = trame ^ (trame >> 8);
x ^= x >> 4;
if ((x & 0x0F) != 0x0F) /* le XOR des 4 quartets doit valoir 0xF */
return -1;
uint32_t v = trame >> 4; /* 12 bits : eee mmmmmmmmm */
uint32_t periode_us = (v & 0x1FF) << (v >> 9);
if (periode_us == 0 || periode_us >= 65408u)
return 0; /* période maximale : moteur arrêté */
return (int32_t)(60000000u / periode_us);
}
DShot bidirectionnel : décodage de la réponse eRPM (C)
Écrit par
dans