TP microcontrˆ oleur 16 bits : filtrage de signaux num´ eriques
J.-M Friedt, 17 novembre 2009 Objectif de ce TP :
– exploiter les fonctions de traitement du signal de GNU/Octave pour concevoir un filtre – impl´ ementer ce filtre dans un microcontrˆ oleur 16 bits
– valider exp´ erimentalement le fonctionnement du filtre
1 Conception d’un filtre de r´ eponse finie (FIR)
Le sujet de ce TP n’est pas de d´ evelopper la th´ eorie des filtres num´ eriques mais uniquement de rappeler quelques uns des concepts utiles en pratique :
– un filtre de r´ eponse impulsionnelle finie [1] (Finite Impulse Response, FIR) b
mest caract´ eris´ e par une sortie y
n` a un instant donn´ e n qui ne d´ epend que des valeurs actuelle et pass´ ees de la mesure x
m, m ≤ n :
y
n= X
k=0..m
b
kx
n−kL’application du filtre s’obtient pas convolution des coefficients du filtre et des mesures.
– un filtre de r´ eponse impulsionnelle infinie (IIR) a une sortie qui d´ epend non seulement des mesures mais aussi des valeurs pass´ ees du filtre.
– GNU/Octave (et Matlab) proposent des outils de synth` ese des filtres FIR et IIR. Par soucis de stabilit´ e num´ erique et simplicit´ e d’impl´ ementation, nous ne nous int´ eresserons qu’aux FIR. Dans ce cas, les coefficient de r´ ecursion sur les valeurs pass´ ees du filtre (nomm´ ees en g´ en´ eral a
mdans la litt´ erature) seront ´ egaux ` a a = 1.
Le calcul d’un filtre dont la r´ eponse spectrale ressemble ` a une forme impos´ ee par l’utilisateur (suivant un crit` ere des moindres carr´ es) est obtenu par la fonction firls(). Cette fonction prend en argument l’ordre du filtre (nombre de coeffi- cients), la liste des fr´ equences d´ efinissant le gabarit du filtre et les magnitudes associ´ ees. Elle renvoie la liste des coefficients b.
L’application d’un FIR de coefficients b (avec a=1) ou de fa¸ con plus g´ en´ erale d’un IIR de coefficients a et b sur un vecteur de donn´ ees exp´ erimentales x s’obtient par filter(b,a,x) ;
Tout filtre se d´ efinit en terme de fr´ equence normalis´ ee : la fr´ equence 1 correspond ` a la demi-fr´ equence d’´ echantillonnage (fr´ equence de Nyquist) lors de la mesure des donn´ ees.
Exercices :
1. en supposant que nous ´ echantillonnons les donn´ ees sur un convertisseur analogique-num´ erique ` a 16000 Hz, identifier les coefficients d’un filtre passe-bande entre 700 et 900 Hz. Combien faut-il de coefficients pour obtenir un r´ esultat satisfaisant ?
2. Quelle est la cons´ equence de choisir trop de coefficients ? Quelle est la cons´ equence de choisir trop peu de coefficients ? 3. ayant obtenu la r´ eponse impulsionnelle du filtre, quelle est sa r´ eponse spectrale ?
4. valider sur des donn´ ees (boucle sur les fr´ equences) simul´ ees la r´ eponse spectrale du filtre
Au lieu de boucler sur des fr´ equences et observer la r´ eponse du filtre appliqu´ e ` a un signal monochromatique, le chirp est un signal dont la fr´ equence instantan´ ee ´ evolue avec le temps. Ainsi, la fonction
chirp([0 :1/16000 :5],40,5,8000) ;
g´ en` ere un signal ´ echantillonn´ e ` a 16 kHz, pendant 5 secondes, balayant la gamme de fr´ equences allant de 40 Hz ` a 8 kHz.
Exercices :
1. appliquer le filtre identifi´ e auparavant au chirp, et visualiser le signal issu de cette transformation 2. que se passe-t-il si la fr´ equence de fin du chirp d´ epasse 8 kHz dans cet exemple ?
2 Application pratique du filtre
Exercices : Impl´ ementer sur MSP430
1. sachant que les acquisitions se font sur 12 bits, quelle est la plage de valeur sur laquelle se font les mesures ?
2. comment exploiter les coefficients num´ eriques du filtre pour un calcul sur des entiers sur 16 bits (short) ? sur 32 bits (long) ?
1. l’´ echantillonnage p´ eriodique de mesures analogiques acquises sur ADC0 2. l’affichage du r´ esultat de ces mesures
3. le filtrage de ces mesures par un FIR synth´ etis´ e selon la m´ ethode vue plus haut 4. l’affichage du r´ esultat de ce filtrage
5. l’affichage de l’amplitude du signal r´ esultant du filtrage
6. appliquer ce programme ` a une mesure sur un chirp g´ en´ er´ e par la carte son du PC au moyen de audacity
7. comparer l’exp´ erience et la simulation.
Exemple de programme et r´ esultats :
#i n c l u d e <msp430x14x . h>
#i n c l u d e <s t r i n g . h>
#i n c l u d e <s i g n a l . h>
#i n c l u d e <i o . h>
#i n c l u d e <s t d i o . h>
#u n d e f debug
v o i d Sommeil ( v o i d ) ;
v o i d Pause TIMERB ( u n s i g n e d s h o r t Compteur ) ; v o i d Pause ms ( u n s i g n e d s h o r t ms ) ;
i n t e r r u p t (TIMERB0 VECTOR ) wakeup Vector TIMERB0 ( v o i d ) ; v o i d i n i t h o r l o g e ( v o i d ) ;
v o i d init PORT ( v o i d ) ; v o i d init TIMER ( v o i d ) ; v o i d i n i t r s 1 9 6 0 0 ( ){
UCTL1=SWRST; // SetupUART1 : mov . b #SWRST,&UCTL1 ; c f p .13−4 UCTL1|=CHAR; // b i s . b #CHAR,&UCTL1
UTCTL1=SSEL0 ; // mov . b #SSEL0,&UTCTL1 ; 3 2 7 6 8 Hz ACLK UBR01=0x03 ; // mov . b #0x03 ,&UBR01 ; 4800 bauds
UBR11=0x00 ; // mov . b #0x00 ,&UBR11 UMCTL1=0x4A ; // mov . b #0x4A,&UMCTL1 UCTL1&=˜SWRST; // b i c . b #SWRST,&UCTL1
ME2|=UTXE1+URXE1 ; // b i s . b #UTXE1+URXE1,&ME2 }
v o i d s n d r s 1 ( u n s i g n e d c h a r c a r a )
{w h i l e ( ( IFG2 & UTXIFG1) ==0) ; // j z r s t x 1 TXBUF1=c a r a ;
}
v o i d s t r r s 1 ( u n s i g n e d c h a r∗ c a r a ) {i n t k =0;
do {s n d r s 1 ( c a r a [ k ] ) ; k++;} w h i l e ( c a r a [ k ] ! = 0 ) ; }
v o i d init PORT ( v o i d ){ P1SEL = 0 x00 ; P1DIR = 0xFF ; P1OUT = 0 x00 ;
P3SEL=0xFE ; // mov . b #0xF0 ,&P3SEL ; P3 . 6 , 7 = USART s e l e c t P3DIR=0x5B ; // mov . b #0x50 ,&P3DIR ; P3 . 6 = o u t p u t d i r e c t i o n P3OUT=0x01 ; // mov . b #0x00 ,&P3OUT ; P3 . 6 = o u t p u t v a l }
v o i d init ADC ( v o i d ){
ADC12CTL0=SHT0 6+REFON+ADC12ON ; // V REF=1.5 V
ADC12CTL1=SHP ; // mov . w #SHP,&ADC12CTL1
ADC12MCTL0=INCH 0+SREF 1 ; // mov . b #INCH 10+SREF 1 &ADC12MCTL0
ADC12CTL0|=ENC; // b i s . w #ENC,&ADC12CTL0
}
u n s i g n e d s h o r t t e m p e r a t u r e ( )
{ADC12CTL0|=ADC12SC ; // s t a r t c o n v e r s i o n do {} w h i l e ( ( ADC12CTL1 & 1 ) ! = 0 ) ;
r e t u r n (ADC12MEM0) ; }
i n t e r r u p t (TIMERA0 VECTOR ) wakeup Vector TIMERA0 ( v o i d ) { }
v o i d i n i t h o r l o g e ( v o i d ){ BCSCTL1 = 0 x87 ;
BCSCTL2 = SELM1 + SELS ; WDTCTL = WDTPW + WDTHOLD;
}
l o n g f i l t r e ( u n s i g n e d s h o r t ∗i n , l o n g ∗f i l , l o n g nin , l o n g n f i l , l o n g ∗s o r t i e ) {u n s i g n e d s h o r t k , j ; l o n g s =0 ,max=−2500;
i f ( nin>n f i l )
{f o r ( k =0; k<nin−n f i l ; k++) {s =0;
f o r ( j =0; j<n f i l ; j ++)
s +=(((( l o n g ) f i l [ j ]∗( l o n g ) i n [ n f i l−1+k−j ] ) ) ) / 2 5 6 ; s=s / 2 5 6 ;
s o r t i e [ k ]= s ; i f ( max<s ) max=s ; }
}
r e t u r n ( max ) ; }
v o i d init TIMER ( v o i d ){ TACTL=TASSEL0 + TACLR;
TACCTL0|=CCIE ; // CCR0 i n t e r r u p t e n a b l e d TACCR0=1;
TACTL|= MC 0 ; }
#d e f i n e NB 110
#d e f i n e NBFIL 61 i n t main ( v o i d ) {
c h a r c h a i n e [ 3 0 ] ;
u n s i g n e d s h o r t t a b l e a u [NB] , k =0;
l o n g s o r t i e [NB] , max ;
// a=( round ( f i r l s ( 6 0 , [ 0 500 700 900 1000 3 2 7 6 8 / 1 6 ] / 3 2 7 6 8∗1 6 , [ 0 0 1 1 0 0 ] )∗6 5 5 3 6 ) ’ ) /∗l o n g f i l 2 0 0 [ NBFIL] ={ −2 8 4 ,−3 4 3 , 1 9 3 , 7 0 0 , 3 6 2 ,−4 5 7 ,−6 6 5 ,−1 6 7 , 1 0 8 , 8 , 3 9 0 , 1 0 9 2 ,\
557 ,−1361 ,−2181 ,−294 ,2040 ,1797 ,−110 ,−628 ,−77 ,−1315 ,−3220 ,−821 ,\
5 5 3 9 , 7 1 7 7 ,−1 1 3 1 ,−1 0 6 2 6 ,−8 0 8 1 , 5 1 9 6 , 1 2 9 3 8 , 5 1 9 6 ,−8 0 8 1 ,−1 0 6 2 6 ,−1 1 3 1 , 7 1 7 7 ,\
5539 ,−821 ,−3220 ,−1315 ,−77 ,−628 ,−110 ,1797 ,2040 ,−294 ,−2181 ,−1361 ,\
5 5 7 , 1 0 9 2 , 3 9 0 , 8 , 1 0 8 ,−1 6 7 ,−6 6 5 ,−4 5 7 , 3 6 2 , 7 0 0 , 1 9 3 ,−3 4 3 ,−2 8 4};
∗/
// a=( round ( f i r l s ( 6 0 , [ 0 500 700 900 1000 3 2 7 6 8 / 2 ] / 3 2 7 6 8∗2 , [ 0 0 1 1 0 0 ] )∗6 5 5 3 6 ) ’ ) l o n g f i l 2 0 0 [ NBFIL]={ −384 ,−543 ,−695 ,−836 ,−964 ,−1074 ,−1164 ,−1229 ,−1270 ,−1283 , \
−1268 ,−1224 ,−1153 ,−1054 ,−930 ,−783 ,−616 ,−433 ,−237 ,−34 ,173 ,379 ,578 ,767 ,941 ,\
1 0 9 6 , 1 2 2 8 , 1 3 3 4 , 1 4 1 1 , 1 4 5 9 , 1 4 7 5 , 1 4 5 9 , 1 4 1 1 , 1 3 3 4 , 1 2 2 8 , 1 0 9 6 , 9 4 1 , 7 6 7 , 5 7 8 , 3 7 9 , 1 7 3 ,\
−34 ,−237 ,−433 ,−616 ,−783 ,−930 ,−1054 ,−1153 ,−1224 ,−1268 ,−1283 ,−1270 ,−1229 ,−1164 ,\
−1074 ,−964 ,−836 ,−695 ,−543 ,−384};
/∗ f r e q = [ 5 0 : 5 0 : 3 0 0 0 ] ; k =1;
f o r f=f r e q
x=s i n ( 2∗p i∗f∗[ 0 : 8 / 3 2 7 6 8 : 0 . 1 ] ) ; y= f i l t e r ( a , 1 , x ) ;
mm( k )=max ( y ( 1 0 0 : 2 0 0 ) ) ; k=k +1;
end
p l o t ( f r e q ,mm)
∗/
i n i t h o r l o g e ( ) ; init PORT ( ) ; init ADC ( ) ; i n i t r s 1 9 6 0 0 ( ) ; init TIMER ( ) ; e i n t ( ) ;
TACTL|= MC 1 + TACLR;
s p r i n t f ( c h a i n e ,”%% l o n g :%d i n t :%d s h o r t :%d\r\n ” , \ s i z e o f ( l o n g ) , s i z e o f ( i n t ) , s i z e o f ( s h o r t ) ) ; s t r r s 1 ( c h a i n e ) ;
w h i l e ( 1 ) { i f ( P4IN==0x04 )
{f o r ( k =0; k<NB; k++) {LPM3 ;
t a b l e a u [ k ]= t e m p e r a t u r e ( ) ; P1OUTˆ=0 x f f ;
}
#i f d e f debug
f o r ( k =0; k<NB; k++)
{s p r i n t f ( c h a i n e ,”%d %d\r\n ” , k , t a b l e a u [ k ] ) ; s t r r s 1 ( c h a i n e ) ;
}
#e n d i f
max= f i l t r e ( t a b l e a u , f i l 2 0 0 , NB, NBFIL , s o r t i e ) ;
#i f d e f debug
f o r ( k =0; k<NB−NBFIL ; k++)
{s p r i n t f ( c h a i n e ,”%d %l d\r\n ” , k , s o r t i e [ k ] ) ; s t r r s 1 ( c h a i n e ) ;
}
#e n d i f
s p r i n t f ( c h a i n e ,”%% %l d\r\n ” , max ) ; s t r r s 1 ( c h a i n e ) ;
}
e l s e {P1OUT=0x00 ;} }
r e t u r n ( 0 ) ; }
-400 -200 0 200 400 600 800
0 500 1000 1500 2000 2500 3000 3500 4000
magntitude (u.a.)
frequence (Hz)
-1 -0.5 0 0.5 1
0 500 1000 1500 2000 2500 3000 3500 4000
magnitude (u.a.)
magnitude (u.a.) firls(160,[0 600 700 900 1000 fe/2]/fe*2,[0 0 1 1 0 0]);
fe=16000;
ffin=4000;
fdeb=40;
b=firls(160,[0 600 700 900 1000 fe/2]/fe*2,[0 0 1 1 0 0]);
x=chirp([0:1/fe:5],fdeb,5,ffin);
f=linspace(fdeb,ffin,length(x));
plot(f,filter(b,1,x));
freq=[fdeb:150:ffin];
k=1;
for f=freq
x=sin(2*pi*f*[0:1/fe:1]);
y=filter(b,1,x);
sortie(k)=max(y);
k=k+1;
end
hold on;plot(freq,sortie,’r’) xlabel(’frequence (Hz)’) ylabel(’magnitude (u.a.)’)
En haut `a gauche : mesure exp´erimentale de la r´eponse d’un FIR passe bande con¸cu pour ˆetre passant entre 700 et 900 Hz. La mesure est effectu´ee au moyen d’un chirp de 40 `a 4000 Hz en 30 secondes g´en´er´e par une carte son d’ordinateur. En bas `a gauche : mod´elisation de la r´eponse d’un filtre passe bande entre 700 et 900 Hz, en bleu par filtrage d’un chirp, en rouge par calcul de l’effet du filtre sur quelques signaux monochromatiques. Ci- dessus : programme GNU/Octave de la simulation.
3 Conception d’un filtre de r´ eponse infinie (IIR)
GNU/Octave propose les fonctions cheb et butter pour concevoir des filtres IIR. Une fois les coefficients b et a (cette fois a est un vecteur) l’IIR se tient compte non seulement des derni` eres observations mais aussi des valeurs pass´ ees du filtre :
y
n= X
k=0..m
b
kx
n−k− X
k=1..m
a
ky
n−kExercice :
Exploiter ces fonctions pour concevoir un filtre aux performances comparables aux IIR propos´ es ci-dessus, et impl´ ementer ces filtres dans le MSP430 pour en valider le fonctionnement.
4 Expression explicite dans le domaine fr´ equentiel
L’efficacit´ e des filtres vus auparavant est leur application dans le domaine temporel : une fois les coefficients a et b identifi´ es, l’application du filtre consiste en N multiplication pour un filtre d’ordre N .
Le passage dans le domaine fr´ equentiel par transform´ ee de Fourier n´ ecessite un calcul consid´ erablement plus long. L’ap- proche na¨ıve de la transform´ ee de Fourier n´ ecessite N multiplications, puisque chacun des N termes en sortie n´ ecessite lui-mˆ eme N multiplications
X
n= X
k=0..N−1
x
kexp (−2iπk × n/N)
L’exploitation de la transform´ ee de Fourier rapide (FFT) exploite les sym´ etries de la formule vue ci-dessus pour utiliser
autant de fois que n´ ecessaire les mˆ emes termes x
kexp (−2πk × n/N ) qui apparaissent plusieurs fois : on notera [2, p.432] la
relation suivante entre les termes pairs F
npet les termes impairs F
nide la transform´ ee de Fourier F
nX
n= X
k=0..N−1
x
kexp (2iπk × n/N)
= X
k=0..N/2−1
x
2kexp (2iπ2k × n/N ) + X
k=0..N/2−1
x
2k+1exp (2iπ(2k + 1) × n/N)
= X
m=0..M−1
x
2mexp (2iπm × n/N) + X
m=0..M−1
x
2m+1exp (2iπm × n/N)
= P
n+ exp(−2iπn/N)I
nen posant M = N/2, et avec P
nle calcul sur les indices pairs et I
nle calcul sur les indices impairs. Chaque calcul d’un terme de FFT n´ ecessite donc N op´ erations, mais ceci le long d’un arbre binaire de longueur log
2(N) au lieu de N. La complexit´ e du calcul est donc pass´ ee de N
2` a N log
2(N ).
L’impl´ ementation de cet algorithme est d´ ecrit en d´ etail dans la note d’application 3722 de Maxim
1.
0 20 40 60 80 100 120
0 100 200 300 400 500 600 700
frequence (FFT sur 256 points
440 Hz, 880 Hz, chirp 440-1320 Hz en 30 secondes
0 1000 2000 3000 4000 5000 6000 7000 8000 9000
0 100 200 300 400 500 600 700
max(|FFT|)
temps (u.a.)
indice fr´ equence (point) (Hz)
11 440
21 880
31 1320
On a bien le point 256 qui corres- pond ` a la fr´ equence 10900 qui est
´ egale ` a 32768/3.
La principale optimisation reste ensuite l’exploitation du multiplieur mat´ eriel disponible dans le MSP430. L’´ etude du code assembleur g´ en´ er´ e par msp430-gcc -S d´ emontre que le compilateur est capable de convertir le symbole * en la s´ equence d’op´ erations exploitant au mieux le mat´ eriel.
Un autre aspect int´ eressant de l’´ etude du code de la note d’application AN3722 est de constater la g´ en´ eration automatique de code pour pr´ ecalculer un certain nombre de constantes. Ainsi, la r´ eorganisation des donn´ ees pour passer de la transform´ ee de Fourier classique ` a la FFT est g´ en´ er´ ee automatiquement, ainsi que les tables contenant les fonctions trigonom´ etriques pr´ e-calcul´ ees. Par ailleurs, cette g´ en´ eration de code automatique est tr` es sensible ` a la nature des donn´ ees manipul´ ees. Les casts successifs (long sur 4 octets et short sur 2 octets) sont n´ ecessaires pour le bon fonctionnement de ce code :
resultMulReCos=((long)cosLUT[tf_index]*(long)x_n_re[b_index])>>7;
resultMulReSin=((long)sinLUT[tf_index]*(long)x_n_re[b_index])>>7;
resultMulImCos=((long)cosLUT[tf_index]*(long)x_n_im[b_index])>>7;
1http://www.maxim-ic.com/appnotes.cfm/an pk/3722
resultMulImSin=((long)sinLUT[tf_index]*(long)x_n_im[b_index])>>7;
x_n_re[b_index] = x_n_re[a_index]-(short)resultMulReCos+(short)resultMulImSin;
x_n_im[b_index] = x_n_im[a_index]-(short)resultMulReSin-(short)resultMulImCos;
x_n_re[a_index] = x_n_re[a_index]+(short)resultMulReCos-(short)resultMulImSin;
x_n_im[a_index] = x_n_im[a_index]+(short)resultMulReSin+(short)resultMulImCos;
frequence (Hz)
temps (u.a.)
imagesc([1 232],[2*10900/256 10900/2],minicom’)
0
1000
2000
3000
4000
5000
0 50 100 150 200
Spectrogramme obtenu par ´ emission d’un signal ` a 440 Hz, puis 880 Hz, puis un chirp et finalement les deux fr´ equences initiales g´ en´ er´ ees simultan´ ement.
#i n c l u d e <s t d i o . h>
#i n c l u d e <s t d l i b . h>
#i n c l u d e <math . h>
#i n c l u d e ” m a x q f f t . h”
#d e f i n e msp430
#i f d e f msp430
#i n c l u d e <msp430x14x . h>
#i n c l u d e <s t r i n g . h>
#i n c l u d e <s i g n a l . h>
#i n c l u d e <i o . h>
#e n d i f
// msp430−g c c −mmcu=msp430x149 −c msp430 . c
// msp430−g c c −mmcu=msp430x149 −o m a x q f f t msp430 . o m a x q f f t . c // s i n o n g c c −o m a x q f f t m a x q f f t . c −lm
s h o r t x n r e [ N f f t ] ; // FFT i n p u t s a m p l e s , and r e a l p a r t o f t h e s p e c t r u m v o i d getSamplesFromADC ( )
{u n s i g n e d s h o r t i ;
s h o r t ∗p t r x n r e = x n r e ; f o r ( i =0; i<256; i ++) {
#i f d e f msp430
LPM1 ; x n r e [ i ]= mesure ( ) / 3 2 ; P1OUTˆ=0 x f f ;
#e l s e
∗( p t r x n r e ++)=( s h o r t ) ( 1 0 0 .∗( s i n ( ( d o u b l e ) i / 3 + 1 . ) ) ) ;
#e n d i f }
f o r ( i =0; i<256; i ++) {i f ( x n r e [ i ]&0 x0080 )
x n r e [ i ] += 0xFF00 ; // C o n v e r t t o 2 ’ s comp }
}
i n t main ( )
{
#i f d e f msp430
u n s i g n e d c h a r b u f f e r [ 2 0 ] ; init PORT ( ) ;
init ADC ( ) ; i n i t r s 1 9 6 0 0 ( ) ; init TIMER ( ) ; e i n t ( ) ;
TACTL|= MC 1 + TACLR;
#e n d i f
#i f d e f msp430
w h i l e ( 1 ) // FFT Loop
#e n d i f {
u n s i g n e d s h o r t i ; // Misc i n d e x
s h o r t n o f b = N DIV 2 ; // Number o f b u t t e r f l i e s s h o r t s o f b = 1 ; // S i z e o f b u t t e r f l i e s s h o r t a i n d e x = 0 ; // f f t d a t a i n d e x
s h o r t a i n d e x r e f = 0 ; // f f t d a t a i n d e x r e f e r e n c e
c h a r s t a g e = 0 ; // S t a g e o f t h e f f t , 0 t o ( Log2 (N)−1) s h o r t n b i n d e x ; // Number o f b u t t e r f l i e s i n d e x
s h o r t s b i n d e x ; // S i z e o f b u t t e r f l i e s i n d e x
s h o r t x n i m [ N f f t ] = {0 x0000}; // I m a g i n a r y p a r t o f x ( n ) and X( n ) , b z e r o ( x n r e , s i z e o f ( s h o r t )∗N f f t ) ;
b z e r o ( x n i m , s i z e o f ( s h o r t )∗N f f t ) ; getSamplesFromADC ( ) ;
/∗ Perform B i t−R e v e r s a l : Us e s an u n r o l l e d l o o p t h a t was c r e a t e d w i t h t h e f o l l o w i n g C c o d e :
#i n c l u d e <s t d i o . h>
#d e f i n e N 256
#d e f i n e LOG 2 N 8
s h o r t b i t R e v ( s h o r t a , s h o r t n B i t s ) {s h o r t r e v a = 0 ;
f o r ( s h o r t i =0; i<n B i t s ; i ++) {r e v a =( r e v a<<1)|( a &1) ; a=a>>1;}
r e t u r n r e v a ; }
s h o r t main ( s h o r t a r g c , c h a r∗ a r g v [ ] ) {p r i n t f ( ” u n s i g n e d s h o r t i ;\n ” ) ;
f o r ( s h o r t i =0; i<N ; i ++) i f ( b i t R e v ( i , LOG 2 N ) > i )
{p r i n t f ( ” i=x n r e [%3d ] ; ” , i ) ;
p r i n t f ( ” x n r e [%3d]= x n r e [%3d ] ; ” , i , b i t R e v ( i , LOG 2 N ) ) ; p r i n t f ( ” x n r e [%3d]= i ;\n” , b i t R e v ( i , LOG 2 N ) ) ; }
r e t u r n 0 ; }
∗/
i=x n r e [ 1 ] ; x n r e [ 1]= x n r e [ 1 2 8 ] ; x n r e [ 1 2 8 ] = i ; i=x n r e [ 2 ] ; x n r e [ 2]= x n r e [ 6 4 ] ; x n r e [ 64]= i ; . . .
i=x n r e [ 2 2 3 ] ; x n r e [ 2 2 3 ] = x n r e [ 2 5 1 ] ; x n r e [ 2 5 1 ] = i ; i=x n r e [ 2 3 9 ] ; x n r e [ 2 3 9 ] = x n r e [ 2 4 7 ] ; x n r e [ 2 4 7 ] = i ; f o r ( s t a g e =0; s t a g e<LOG 2 N ; s t a g e ++)
{f o r ( n b i n d e x =0; n b i n d e x<n o f b ; n b i n d e x++) {s h o r t t f i n d e x = 0 ; // The t w i d d l e f a c t o r i n d e x
f o r ( s b i n d e x =0; s b i n d e x<s o f b ; s b i n d e x ++)
{l o n g r e s u l t M u l R e C o s ; // j m f r i e d t : s h o r t −> l o n g ∗∗∗
l o n g r e s u l t M u l I m C o s ; l o n g r e s u l t M u l R e S i n ; l o n g r e s u l t M u l I m S i n ;
s h o r t b i n d e x = a i n d e x+s o f b ; // 2nd f f t d a t a i n d e x
r e s u l t M u l R e C o s =(( l o n g ) cosLUT [ t f i n d e x ]∗( l o n g ) x n r e [ b i n d e x ] )>>7;
r e s u l t M u l R e S i n =(( l o n g ) sinLUT [ t f i n d e x ]∗( l o n g ) x n r e [ b i n d e x ] )>>7;
r e s u l t M u l I m C o s =(( l o n g ) cosLUT [ t f i n d e x ]∗( l o n g ) x n i m [ b i n d e x ] )>>7;
r e s u l t M u l I m S i n =(( l o n g ) sinLUT [ t f i n d e x ]∗( l o n g ) x n i m [ b i n d e x ] )>>7;
x n r e [ b i n d e x ] = x n r e [ a i n d e x ]−( s h o r t ) ( r e s u l t M u l R e C o s+r e s u l t M u l I m S i n ) ; x n i m [ b i n d e x ] = x n i m [ a i n d e x ]−( s h o r t ) ( r e s u l t M u l R e S i n−r e s u l t M u l I m C o s ) ; x n r e [ a i n d e x ] = x n r e [ a i n d e x ] + ( s h o r t ) ( r e s u l t M u l R e C o s−r e s u l t M u l I m S i n ) ; x n i m [ a i n d e x ] = x n i m [ a i n d e x ] + ( s h o r t ) ( r e s u l t M u l R e S i n+r e s u l t M u l I m C o s ) ;
i f ( ( ( s b i n d e x +1) & ( s o f b−1) ) == 0 ) a i n d e x = a i n d e x r e f ;
e l s e
a i n d e x ++;
t f i n d e x += n o f b ; }
a i n d e x = ( ( s o f b<<1) + a i n d e x ) & N MINUS 1 ; a i n d e x r e f = a i n d e x ;
}
n o f b >>= 1 ; s o f b <<= 1 ; }
f o r ( i =0; i<N DIV 2 PLUS 1 ; i ++) // v a l e u r a b s o l u e {i f ( ( x n r e [ i ] & 0 x8000 ) !=0 x0000 ) x n r e [ i ]=−x n r e [ i ] ;
i f ( ( x n i m [ i ] & 0 x8000 ) !=0 x0000 ) x n i m [ i ]=−x n i m [ i ] ; }
#i f d e f msp430
n o f b = 0 ; // p o s max s o f b = 0 ; // v a l max
f o r ( i =3; i<N DIV 2 PLUS 1 ; i ++)
{ s p r i n t f ( b u f f e r ,”%d %d ” , x n r e [ i ] , x n i m [ i ] ) ; s t r r s 1 ( b u f f e r ) ;
// i f ( ( x n r e [ i ]+ x n i m [ i ] )>s o f b )
// {s o f b=x n r e [ i ]+ x n i m [ i ] ; n o f b=i ;} }
// s p r i n t f ( b u f f e r ,”%d %d\r\n ” , n o f b , s o f b ) ; s p r i n t f ( b u f f e r , ”\r\n ” ) ;
s t r r s 1 ( b u f f e r ) ;
#e l s e
f o r ( i =0; i<N DIV 2 PLUS 1 ; i ++) p r i n t f (”%d %d\n ” , x n r e [ i ] , x n i m [ i ] ) ;
#e n d i f } r e t u r n ( 0 ) ; }
Listing 1 – Calcul de la FFT tel que impl´ ement´ e dans l’AN 3722 de Maxim. Noter la g´ en´ eration automatique de code pour l’organisation des donn´ ees en m´ emoire.
#i f n d e f MAXQ FFT H
#d e f i n e MAXQ FFT H
#d e f i n e N f f t 256
#d e f i n e N DIV 2 128
#d e f i n e N DIV 2 PLUS 1 129
#d e f i n e N MINUS 1 255
#d e f i n e LOG 2 N 8
/∗
c o s i n e Look−Up T a b le : An LUT f o r t h e c o s i n e f u n c t i o n c r e a t e d w i t h t h e f o l l o w i n g program :
#i n c l u d e <s t d i o . h>
#i n c l u d e <math . h>
#d e f i n e N 256
v o i d main ( i n t a r g c , c h a r∗ a r g v [ ] ) {
p r i n t f ( ” c o n s t i n t cosLUT[%d ] =\n{\n ” ,N/ 2 ) ; f o r ( l o n g i =0; i<N/ 2 ; i ++)
{
p r i n t f (”%+4d ” , ( i n t ) ( 1 2 8∗c o s ( 2∗M PI∗i /N) ) ) ;
i f ( i<(N/2−1) ) p r i n t f ( ” , ” ) ;
i f ( ( i +1)%16 == 0 ) p r i n t f ( ”\n ” ) ; }
p r i n t f ( ”};\n ” ) ; }
∗/
c o n s t s h o r t cosLUT [ N DIV 2 ] =
{
+128 ,+127 ,+127 ,+127 ,+127 ,+127 ,+126 ,+126 ,+125 ,+124 ,+124 ,+123 ,+122 ,+121 ,+120 ,+119 , +118 ,+117 ,+115 ,+114 ,+112 ,+111 ,+109 ,+108 ,+106 ,+104 ,+102 ,+100 , +98 , +96 , +94 , +92 , +90 , +88 , +85 , +83 , +81 , +78 , +76 , +73 , +71 , +68 , +65 , +63 , +60 , +57 , +54 , +51 , +48 , +46 , +43 , +40 , +37 , +34 , +31 , +28 , +24 , +21 , +18 , +15 , +12 , +9 , +6 , +3 , +0 , −3, −6, −9, −12 , −15 , −18 , −21 , −24 , −28 , −31 , −34 , −37 , −40 , −43 , −46 ,
−48 , −51 , −54 , −57 , −60 , −63 , −65 , −68 , −71 , −73 , −76 , −78 , −81 , −83 , −85 , −88 ,
−90 , −92 , −94 , −96 , −98 ,−100 ,−102 ,−104 ,−106 ,−108 ,−109 ,−111 ,−112 ,−114 ,−115 ,−117 ,
−118 ,−119 ,−120 ,−121 ,−122 ,−123 ,−124 ,−124 ,−125 ,−126 ,−126 ,−127 ,−127 ,−127 ,−127 ,−127 };
/∗
s i n e Look−Up T a b le : An LUT f o r t h e s i n e f u n c t i o n c r e a t e d w i t h t h e f o l l o w i n g program :
#i n c l u d e <s t d i o . h>
#i n c l u d e <math . h>
#d e f i n e N 256
v o i d main ( i n t a r g c , c h a r∗ a r g v [ ] ) {
p r i n t f ( ” c o n s t l o n g sinLUT[%d ] =\n{\n ” ,N/ 2 ) ; f o r ( l o n g i =0; i<N/ 2 ; i ++)
{
p r i n t f (”%+4d ” , ( i n t ) ( 1 2 8∗s i n ( 2∗M PI∗i /N) ) ) ;
i f ( i<(N/2−1) ) p r i n t f ( ” , ” ) ;
i f ( ( i +1)%16 == 0 ) p r i n t f ( ”\n ” ) ; }
p r i n t f ( ”};\n ” ) ; }
∗/
c o n s t s h o r t sinLUT [ N DIV 2 ] = {
+0 , +3 , +6 , +9 , +12 , +15 , +18 , +21 , +24 , +28 , +31 , +34 , +37 , +40 , +43 , +46 , +48 , +51 , +54 , +57 , +60 , +63 , +65 , +68 , +71 , +73 , +76 , +78 , +81 , +83 , +85 , +88 , +90 , +92 , +94 , +96 , +98 ,+100 ,+102 ,+104 ,+106 ,+108 ,+109 ,+111 ,+112 ,+114 ,+115 ,+117 , +118 ,+119 ,+120 ,+121 ,+122 ,+123 ,+124 ,+124 ,+125 ,+126 ,+126 ,+127 ,+127 ,+127 ,+127 ,+127 , +128 ,+127 ,+127 ,+127 ,+127 ,+127 ,+126 ,+126 ,+125 ,+124 ,+124 ,+123 ,+122 ,+121 ,+120 ,+119 , +118 ,+117 ,+115 ,+114 ,+112 ,+111 ,+109 ,+108 ,+106 ,+104 ,+102 ,+100 , +98 , +96 , +94 , +92 , +90 , +88 , +85 , +83 , +81 , +78 , +76 , +73 , +71 , +68 , +65 , +63 , +60 , +57 , +54 , +51 , +48 , +46 , +43 , +40 , +37 , +34 , +31 , +28 , +24 , +21 , +18 , +15 , +12 , +9 , +6 , +3 };
#e n d i f
Listing 2 – Tableaux associ´ es ` a la FFT : noter la g´ en´ eration automatique de code pour les tables contenant les valeurs de cosinus et sinus
#i n c l u d e <msp430x14x . h>
#i n c l u d e <s t r i n g . h>
#i n c l u d e <s i g n a l . h>
#i n c l u d e <i o . h>
#i n c l u d e <s t d i o . h>
v o i d i n i t r s 1 9 6 0 0 ( ){
UCTL1=SWRST; // SetupUART1 : mov . b #SWRST,&UCTL1 UCTL1|=CHAR; // b i s . b #CHAR,&UCTL1
UTCTL1=SSEL0 ; // mov . b #SSEL0,&UTCTL1 UBR01=0x03 ; // mov . b #0x03 ,&UBR01 UBR11=0x00 ; // mov . b #0x00 ,&UBR11 UMCTL1=0x4A ; // mov . b #0x4A,&UMCTL1 UCTL1&=˜SWRST; // b i c . b #SWRST,&UCTL1 ME2|=UTXE1+URXE1 ; // b i s . b #UTXE1+URXE1,&ME2 }
v o i d s n d r s 1 ( u n s i g n e d c h a r c a r a )
{w h i l e ( ( IFG2 & UTXIFG1) ==0) ; // j z r s t x 1 TXBUF1=c a r a ;
}
v o i d s t r r s 1 ( u n s i g n e d c h a r∗ c a r a ) {i n t k =0;
do {s n d r s 1 ( c a r a [ k ] ) ; k++;} w h i l e ( c a r a [ k ] ! = 0 ) ; }
v o i d init PORT ( v o i d ){ P1SEL = 0 x00 ; P1DIR = 0xFF ; P1OUT = 0 x00 ;
P3SEL=0xFE ; // ; P3 . 6 , 7 = USART s e l e c t P3DIR=0x5B ; // ; P3 . 6 = o u t p u t d i r e c t i o n P3OUT=0x01 ; // ; P3 . 6 = o u t p u t v a l }
v o i d init ADC ( v o i d ){
ADC12CTL0=SHT0 6+REFON+ADC12ON ; // V REF=1.5 V ADC12CTL1=SHP ;
ADC12MCTL0=INCH 0+SREF 1 ; // p . 1 7−1 1 : s i n g l e c o n v e r s i o n ADC12CTL0|=ENC;
}
u n s i g n e d s h o r t mesure ( )
{ADC12CTL0|=ADC12SC ; // s t a r t c o n v e r s i o n do {} w h i l e ( ( ADC12CTL1 & 1 ) ! = 0 ) ;
r e t u r n (ADC12MEM0) ; }
v o i d init TIMER ( v o i d ){
BCSCTL1 = 0 x87 ; // XT2 OFF
BCSCTL2 = SELM1 + SELS ; // LFXT2 : u s e HF q u a r t z (XT2) i f a v a i l a b l e
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
TACTL=TASSEL0 + TACLR;
TACCTL0|=CCIE ; // CCR0 i n t e r r u p t e n a b l e d TACCR0=2;
TACTL|= MC 0 ; }
i n t e r r u p t (TIMERA0 VECTOR ) wakeup Vector TIMERA0 ( v o i d ) { }
Listing 3 – Quelques fonctions pour la communication et initialisation du MSP430
Lors du traitement de N donn´ ees r´ eelles, nous exploitons des tableaux de N ´ el´ ements r´ eels et N ´ el´ ements imaginaires (2N cases m´ emoire) pour n’exploiter ` a la fin que N/2 ´ el´ ements de la transform´ ee de Fourier X
npuisque X
N−n= X
n∗. Il est possible d’optimiser l’occupation m´ emoire en pla¸ cant la moiti´ e des donn´ ees initiales dans le tableau de la partie imaginaire des donn´ es en entr´ ee : alors l’int´ egralit´ e de la transform´ ee de Fourier est exploit´ ee, et les relations de sym´ etrie entre transform´ ee de donn´ ees purement r´ eelles (X
N−n= X
n∗) et purement imaginaires (X
N−n= −X
n∗) permettent d’identifier quelle partie de la transform´ ee de Fourier vient de quelle donn´ ee initiale.
Pour s’en convaincre, sous GNU/Octave :
c l e a r c l o s e
x=s i n ( 2∗p i∗[ 0 : 0 . 0 1 : 1 0 . 2 3 ]∗3 )+i∗0 ; f 1= f f t ( x ( 1 : 5 1 2 ) ) ; % 512 c o m p l e x e s f 2= f f t ( x ( 5 1 3 : 1 0 2 4 ) ) ; % 512 c o m p l e x e s xx=x ( 1 : 5 1 2 )+i∗x ( 5 1 3 : 1 0 2 4 ) ; % 256 v a l s f f = f f t ( xx ) ; % 256 c o m p l e x e s r e 1 ( 1 )=r e a l ( f f ( 1 ) ) ;
r e 2 ( 1 )=imag ( f f ( 1 ) ) ; f o r j j =1:255
r e 1 ( j j +1)=r e a l ( 0 . 5∗( f f ( j j +1)+ f f (512−j j +1) ) ) ; im1 ( j j +1)=imag ( 0 . 5∗( f f ( j j +1)−f f (512−j j +1) ) ) ; r e 2 ( j j +1)=imag ( 0 . 5∗( f f ( j j +1)+ f f (512−j j +1) ) ) ; im2 ( j j +1)=−r e a l ( 0 . 5∗( f f ( j j +1)−f f (512−j j +1) ) ) ; end
p l o t ( r e a l ( f 1 ( 1 : 2 5 6 )−r e 1 ) ) h o l d on
p l o t ( imag ( f 1 ( 1 : 2 5 6 ) )−im1 , ’ g ’ ) p l o t ( r e a l ( f 2 ( 1 : 2 5 6 ) )−r e 2 , ’ r ’ ) p l o t ( imag ( f 2 ( 1 : 2 5 6 ) )−im2 , ’ m’ )
Listing 4 – Comparaison entre le r´ esultat d’une FFT sur N points, et le r´ esultat du calcul exploitant les parties r´ eelles et imaginaires d’un tableau de N/2 points.
R´ ef´ erences
[1] A.V. Oppenheim & R.W. Schafer,Discrete-Time Signal Processing, Prentice Hall (1989)
[2] W.H. Press, B.P. Flannery, S.A. Teukolsky, & W.T. Vertterling,Numerical recipies in Pascal, Cambridge University Press (1994), ou sur le webhttp://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey FFT algorithm