Erstmal hätte ich ein paar kleine Hinweise zur Performance:
Die Shifterei kannst du dir sparen, wenn du die Konstanten für 90°, 180° und 360° gleich in skalierter Form definierst. Das spart immerhin allein bei diesen 2 Zeilen schon 28 Shift-Operationen (der AVR muss ja für ein <<7 tatsächlich 7x shiften)Code:if((x>>7)>W) x=-x+(W<<7); //x wird auf das Intervall [-W;W] normiert (aufgrund der Achsensymmetrie um x=0) if((x>>7)<-W) x=-x-(W<<7);
Auch die Signum Funtionen lassen sich beschleunigen, indem du statt if(number >> 31) folgendes machst: if(number & (1 << 31)). Dafür braucht der AVR keine Shifts, da 1 << 31 als Konstante schon vom Compiler berechnet wird.
Was den Überlauf.. bzw. die Überläufe betrifft sind mir mehrere Stellen aufgefallen:
1. x hat den Typ int16_t und enthält den Winkel in Grad * 128, korrekt?
Dann möchte ich mal anmerken, daß ein Winkel von 360° einem x von 46080 entspricht. Bei einem int16_t ist allerdings schon bei (2^15)-1 = 32767 Schluss.
2. B und x sind beide int16_t und werden multipliziert, da ist es sicherer zuerst beide auf uint32_t zu casten, damit der Compiler nicht auf die Idee kommt das Ergebnis in 16 Bit quetschen zu wollen.
Es sind noch mehr Probleme deser Art im Code zu finden, daher mein Tipp:
Für jeden einzelnen Berechnungsschritt nochmal den worst-case Fall prüfen. Prinzipiell gilt: wenn irgendein Zwischenergebnis größer werden könnte als der Typ der beiden Operatoren, sollten beide vorher zur Sicherheit auf den nächst größeren Typ gecastet werden.
Lesezeichen