Hallo zusammen,
ich habe ein FIR-System implementiert (Cortex M4F), das die Ableitung
einer Zahlenreihe aus 64-Bit-Integer bilden soll. Quick & Dirty (siehe
untenstehender Quelltext) funktioniert das auch.
Allerdings habe ich das Gefühl, dass es auch in C "schöner" geht, als
z.B. die Koeffizienten bei jedem Aufruf neu zu berechnen.
Da die Ordnung N auf jeden Fall recht klein bleiben wird, könnte ich die
lookup-table für die Koeffizienten auch explizit hinschreiben und per
switch-case auswählen. Oder in der Status-Variablen hinterlegen. Oder
die Schleife komplett ausschreiben und die Filterordnung per switch-case
auswählen. Ich könnte mir das Umspeichern bei jedem Aufruf irgendwie
sparen. Oder.
Wie macht man soetwas in C "richtig" und "schön" ?
1 | #define DERIVATIVE_N_VALUES 5
|
2 |
|
3 | typedef struct
|
4 | {
|
5 | int64_t lastValues[DERIVATIVE_N_VALUES];
|
6 | }
|
7 | Diff64state_t;
|
8 |
|
9 |
|
10 | /* Differenzierer fuer grosse Zahlen
|
11 | * Steigung der Ausgleichsgerade durch die Zahlenreihe u(z), u(z^-1), .... u(z^-n) */
|
12 | float differentiate64(int64_t u, Diff64state_t *State)
|
13 | {
|
14 | assert( State != NULL );
|
15 |
|
16 | // Letzte n Werte speichern, um die Ableitung zu bilden
|
17 | memmove( &(State->lastValues[1]), &(State->lastValues[0]), (DERIVATIVE_N_VALUES-1)*sizeof(int64_t));
|
18 | State->lastValues[0] = u;
|
19 |
|
20 |
|
21 | // FIR-Koeffizienten-Array bestuecken (erste Haelfte)
|
22 | // Das Koeffizienten-Array ist antisymmetrisch, deswegen wird nur ueber die Haelfte iteriert
|
23 | int n = DERIVATIVE_N_VALUES;
|
24 | float b[n];
|
25 | float c = 6.f/((float) ( n*(n*n-1) ) );
|
26 | for( int i = 0; i<n/2; i++ )
|
27 | {
|
28 | b[i] = c * ((float) (2*i - n + 1) );
|
29 | }
|
30 |
|
31 |
|
32 | // FIR
|
33 | // Die paarweise Differenz der Eingangswerte verhindert einen Ueberlauf, da fuer alle n
|
34 | // aufeinanderfolgende Werte sicher gilt: max(u(z^i)) - min(u(z^i)) < 2^16
|
35 | float d = 0.f;
|
36 | int64_t *v = State->lastValues;
|
37 | int64_t *w = State->lastValues + (DERIVATIVE_N_VALUES -1);
|
38 | for( int i = 0; i<n/2; i++ )
|
39 | {
|
40 | int32_t diff = *w-- - *v++;
|
41 | d += b[i] * ( (float) diff );
|
42 | }
|
43 |
|
44 | return d;
|
45 | }
|