Sunteți pe pagina 1din 6

Tema 1 PSC - Problema 10

 Cerinta :

Realizaţi un proiect C pentru StarCore140 care să implementeze o funcţie (apelată din main) cu
operaţia descrisă în tabelul de mai jos (fiecare student are o temă). Se va porni de la proiectul
”test” dat ca exemplu pe site-ul cursului. Programul și funcția C vor folosi tipurile de date
associate numerelor fracţionare şi funcţiile intrinseci specifice DSP StarCore140.
De asemenea se va realiza un program de test Matlab care va genera un număr suficient de
valori pentru a se testa programul C pentru SC140.
Valorile de test generate în Matlab vor fi scrise în fişier/fișiere şi vor fi citite de funcţia main din
proiectul C.
Apoi se va apela funcţia implementată şi rezultatele vor fi scrise (tot din main) în fişiere. În
Matlab se compară apoi rezultatele obţinute, evaluându-se inclusiv erorile datorate formatelor
de reprezentare.

void trHilbert(Word16 *x,


Word16 *y,
unsigned short N);

Implementează transformata Hilbert în domeniul frecvență pentru un vector de intrare cu


N valori complexe, înmulțind prima jumătate a vectorului cu -j și a doua jumătate a
vectorului cu j. Se presupune că vectorii de intrare, respectiv de ieșire, au lungimi de 2N,
întrucât pentru fiecare valoare complexă, în vector se vor găsi 2 numere fracționare
consecutive, pe 16 biți fiecare, una pentru partea reală și una pentru partea imaginară.

 Rezolvare

Am realizat in Matlab un program care sa contina generarea vectorului de intrare x de lungime


N(multiplu de 4; am ales N=40, deci vom avea 20 de valori complexe).

N=40;
n=0:N-1;
x=0.5*cos(2*pi/12*n);

Dupa ce am generat semnalul de intrare ( vector de valori complexe) l-am scris in fisierul x.dat.
fid=fopen('..\x.dat','w','b');
fwrite(fid,x.*2^15,'int16');
fclose(fid);
Am inmultit fiecare valoare din vector cu 2^15 pentru a transforma numerele
fractionare(generate de cosinusul cu amplitudine 0.5) in numere intregi. Aceste numere vor fi pe
16 biti in CodeWarrior (de tipul Word16).

Transformata Hilbert a fost implementata si in Matlab pentru a putea compara rezultatele


obtinute cu cele din CodeWarrior si pentru a putea observa erorile aparute.

for i = 0:N/4-1
y(2*i+1) = x(2*i+2);
y(2*i+2) = (-1)*x(2*i+1);
end

for i = N/4:N/2-1
y(2*i+1) = (-1)*x(2*i+2);
y(2*i+2) = x(2*i+1);
end

Primul for merge pana la jumatatea vectorului de valori complexe (care are lungimea
N),inmultind valoarea complexa cu -j. Pentru a putea realiza procesarea simultana a doua
esantioane consecutive, indexul i merge de la 0 la dimensiune/2, iar elementele se acceseaza cu
2*i+1 si 2*i+2.
De exemplu, pentru i=3 se proceseaza elementele 7 si 8(in Matlab vectorii incep de la 1).
Al doilea for merge de la jumatatea vectorului pana la final, inmultind valoarea complexa cu j.

Dupa ce datele vor fi procesate in CodeWarrior si scrise in fisier, le preluam in Matlab si


comparam rezultatele obtinute.
fid=fopen('..\y.dat','r','b');
ymatlab=fread(fid,N,'int16');
ymatlab=ymatlab'/(2^15);
plot(y-ymatlab)
fclose(fid);

Valorile obtinute in CodeWarrior sunt impartite cu 2^15(rezultatul din CodeWarrior este pe 16


biti) pentru a fi convertite in numere fractionare. Vectorul de valori complexe obtinut va fi
transpus intrucat in CodeWarrior este scris ca o matrice coloana.

Implementarea in CodeWarrior

 Functia prod.c

#include <prototype.h>

void trHilbert(Word16 x[], Word16 y[], unsigned short N)

{
int i;

for (i = 0;i<=N/4-1;i++)

y[2*i] = x[2*i+1];

y[2*i+1] = mult(WORD16(-1),x[2*i]);

for(i = N/4;i<=N/2-1;i++)

y[2*i] = mult(WORD16(-1),x[2*i+1]);

y[2*i+1] = x[2*i];

In primul for: Partea imaginara a lui x ( x[2*i+1] ) este copiata in partea reala a vectorului de iesire
( y[2*i]).

Partea imaginara a vectorului de iesire ( y[2*i+1]) va fi egala cu mult(WORD16(-1),x[2*i]) - mult este o


instructiune ce returneaza ‘short multiply’ – inmultirea a doua valori pe 16 biti. Valoarea returnata este
pe 16 biti.

In al doilea for: Partea reala a vectorului de iesire ( y[2*i]) va fi egala cu mult(WORD16(-1),x[2*i+1]) -


mult este o instructiune ce returneaza ‘short multiply’ – inmultirea a doua valori pe 16 biti. Valoarea
returnata este pe 16 biti.

Partea reala a lui x ( x[2*i] ) este copiata in partea imaginara a vectorului de iesire ( y[2*i+1]).

 Functia main

#include <prototype.h>
#include <stdio.h>
#include "constants.h"
#include "functions.h"

int main()
{
Word16 x[DataBlockSize],y[DataBlockSize];
int i;
FILE *fp;

fp=fopen("../x.dat","r+b");
fread(x,sizeof(Word16),DataBlockSize,fp);
if (!fp)
printf("\nNu s-a deschis x.dat");
fclose(fp);

trHilbert(x,y, DataBlockSize);

/* for (i = 0; i < DataBlockSize; i++)


printf("Input %d %d\n",a[i],b[i]);
*/

fp=fopen("../y.dat","w+b");
fwrite(y,sizeof(Word16),DataBlockSize,fp);
if (!fp)
printf("\nNu s-a deschis y.dat");
fclose(fp);
return(0);
}

Se citesc valorile vectorului de intrare din Matlab( se deschide fisierul x.dat). Se apeleaza functia
trHilbert care nu returneaza nimic fiind de tip void si se pune rezultatul in fisierul y.dat.

Cateva valori ale vectorului de iesire din CodeWarrior.


Cateva valori ale vectorului de iesire in Matlab:

y =0.4330 -0.5000 0.0000 -0.2500 -0.4330 0.2500 -0.4330 0.5000 -0.0000 0.2500 0.4330
-0.2500 0.4330 -0.5000 0.0000 -0.2500 -0.4330 0.2500 -0.4330 0.5000 0.0000 -0.2500
-0.4330 0.2500

ymatlab = 0.4330 -0.5000 0 -0.2500 -0.4330 0.2500 -0.4330 0.5000 0 0.2500 0.4330
-0.2500 0.4330 -0.5000 0 -0.2500 -0.4330 0.2500 -0.4330 0.5000 0 -0.2500 -0.4330
0.2500

Eroarea dintre valoarile calculate in Matlab si in CodeWarrior :

ans =

1.0e-05 *

Columns 1 through 12

-0.1214 0 0.0000 -0.0000 0.1214 -0.0000 0.1214 0 -0.0000 0.0000 -0.1214 0.0000

Columns 13 through 24

-0.1214 0 0.0000 -0.0000 0.1214 -0.0000 0.1214 0 0.0000 -0.0000 0.1214 -0.0000

Columns 25 through 36

0.1214 0 -0.0000 0.0000 -0.1214 0.0000 -0.1214 0 0.0000 -0.0000 0.1214 -0.0000

Columns 37 through 40

0.1214 0 -0.0000 0.0000


10-6
1.5

0.5

-0.5

-1

-1.5
0 5 10 15 20 25 30 35 40

Se observa ca a aparut o eroare foarte mica din cauza formatelor de reprezentare diferite ale celor 2
programe folosite.

S-ar putea să vă placă și