Other Parts Discussed in Thread: BOOSTXL-AUDIO,
Tool/software:
Hello,
I am working on The MSP430FR5994 to applu FFT on captured signal using BOOSTXL-AUDIO, so after doing the signal acquisition I am applyting the function runFftWithLea on the voice signal Buffer , the function is designed to perform a Fast Fourier Transform (FFT) on segments of a buffer containing 16-bit unsigned integer (uint16_t) samples. So the logic behinf this function is
- The function processes the input buffer in segments (
taille_totaleindicates the total size of the buffer). -
- For each segment, the function calculates the mean value to center the data around zero. This helps in reducing DC offset in the signal.
-
Zero Padding:
- Zero padding is applied symmetrically around the segment to improve FFT resolution. This involves adding zeros before and after the actual data segment.
-
Data Preparation:
- The data is prepared for FFT by converting the 16-bit unsigned integers to
_q15format, which is a fixed-point representation used in DSP. This involves centering the data around zero and scaling.
- The data is prepared for FFT by converting the 16-bit unsigned integers to
-
FFT Computation:
- The complex FFT is applied to the prepared data using the LEA module. This transforms the time-domain data into the frequency domain.
-
Magnitude Calculation:
- For each FFT coefficient, the magnitude is computed. This involves calculating the square of the real and imaginary parts, summing them, and then taking the square root.
- The magnitude is approximated due to the fixed-point representation constraints.
-
Magnitude Conversion and Transmission:
- The magnitudes are converted from
_q15format touint16_tfor easier interpretation and transmission. - The magnitudes are then sent via UART for further processing or display.
- The magnitudes are converted from
The problem is BuffCopy1 and buffCopy are not filled and basically the FFT is not returning any values
#pragma PERSISTENT(buffCopy1);
uint16_t buffCopy1[FFT_LENGTH] = {0};
DSPLIB_DATA(buffCopy, MSP_ALIGN_CMPLX_FFT_Q15(FFT_LENGTH))
_q15 buffCopy[FFT_LENGTH * 2];
DSPLIB_DATA(magnitude_q15, 4)
_q15 magnitude_q15[FFT_LENGTH];
DSPLIB_DATA(magnitude_uint16, 4)
uint16_t magnitude_uint16[FFT_LENGTH];
/* Hamming window parameters */
int32_t real_sq, imag_sq;
msp_status status;
//static msp_mpy_q15_params mpyParams;
msp_fft_q15_params fftParams;
void runFftWithLea(uint16_t *buffer, int taille_totale) {
uint16_t i;
int position = 0;
//uint16_t shift;
//int16_t inter, real1, imag1;
_q15 real, imag, real_squared, imag_squared, sum_of_squares, magnitude;
fftParams.length = FFT_LENGTH;
fftParams.bitReverse = 1;
fftParams.twiddleTable = msp_cmplx_twiddle_table_256_q15;
uint16_t b;
// Initialiser le module LEA et les paramètres de la FFT
msp_lea_init();
initUART();
while (position < taille_totale) {
// Calculer la moyenne des valeurs dans le segment
float moyenne = 0;
uint16_t m;
for (i = 0; i < taille_totale; i++) {
//if (position + i < taille_totale) {
moyenne += buffer[position + i];
//}
}
moyenne /= FFT_LENGTH;
m= (uint16_t)round (moyenne);
// Copier le segment de 128 échantillons dans buffCopy1 avec zero-padding symétrique
int zero_padding = 64; // Nombre de zéros à ajouter de chaque côté
for (i = 0; i < FFT_LENGTH + 2 * zero_padding; i++) {
if (i < zero_padding || i >= FFT_LENGTH + zero_padding) {
buffCopy1[i] = 0; // Remplissage zéro
} else {
b = (buffer[position + i - zero_padding]);
buffCopy1[i] = b - m;
}
}
int j=0;
for (j = 0; j < 256; j++) {
// Convertir la valeur uint16_t en _q15
// Soustraire 2048 pour centrer autour de 0
// Multiplier par 16 pour utiliser toute la plage _q15
int32_t temp = ((int32_t)buffCopy1[i] - 2048) * 16;
// Saturer à la plage _q15 (-32768 à 32767)
if (temp > 32767) temp = 32767;
if (temp < -32768) temp = -32768;
buffCopy[i] = (int16_t)temp;
}
// Appliquer la FFT complexe sur le segment buffCopy
status = msp_cmplx_fft_fixed_q15(&fftParams, buffCopy);//la il y'a un probleme
msp_checkStatus(status);
// Calculer la magnitude pour chaque coefficient FFT
for (i = 0; i < FFT_LENGTH; i++) {
real = buffCopy[2 * i];
imag = buffCopy[2 * i + 1];
// Calculer le carré de la partie réelle et imaginaire
real_squared = __q15mpy(real, real); // Utilisation de la multiplication Q15
imag_squared = __q15mpy(imag, imag);
// Calculer la somme des carrés avec saturation
sum_of_squares = real_squared + imag_squared;
// Calculer la magnitude comme racine carrée (approximative)
// Ici, sqrt est approximée par une simple division et ajustement de la précision
magnitude = (_q15)sqrt(sum_of_squares); // Convertir en _q15
magnitude_q15[i] = magnitude;
}
// Convertir les valeurs de magnitude en uint16_t
for (i = 0; i < FFT_LENGTH; i++) {
// Convertir _q15 (plage -1 à 1) à uint16_t (plage 0 à 4096)
magnitude_uint16[i] = (uint16_t)((magnitude_q15[i] * MAX_VALUE)>>15);
}
UART_sendBuffer(magnitude_uint16, FFT_LENGTH);
position += FFT_LENGTH;
}
}
void runFftWithLea(uint16_t *buffer, int taille_totale) {
uint16_t i;
int position = 0;
//uint16_t shift;
//int16_t inter, real1, imag1;
_q15 real, imag, real_squared, imag_squared, sum_of_squares, magnitude;
fftParams.length = FFT_LENGTH;
fftParams.bitReverse = 1;
fftParams.twiddleTable = msp_cmplx_twiddle_table_256_q15;
uint16_t b;
// Initialiser le module LEA et les paramètres de la FFT
msp_lea_init();
initUART();
while (position < taille_totale) {
// Calculer la moyenne des valeurs dans le segment
float moyenne = 0;
uint16_t m;
for (i = 0; i < taille_totale; i++) {
//if (position + i < taille_totale) {
moyenne += buffer[position + i];
//}
}
moyenne /= FFT_LENGTH;
m= (uint16_t)round (moyenne);
// Copier le segment de 128 échantillons dans buffCopy1 avec zero-padding symétrique
int zero_padding = 64; // Nombre de zéros à ajouter de chaque côté
for (i = 0; i < FFT_LENGTH + 2 * zero_padding; i++) {
if (i < zero_padding || i >= FFT_LENGTH + zero_padding) {
buffCopy1[i] = 0; // Remplissage zéro
} else {
b = (buffer[position + i - zero_padding]);
buffCopy1[i] = b - m;
}
}
int j=0;
for (j = 0; j < 256; j++) {
// Convertir la valeur uint16_t en _q15
// Soustraire 2048 pour centrer autour de 0
// Multiplier par 16 pour utiliser toute la plage _q15
int32_t temp = ((int32_t)buffCopy1[i] - 2048) * 16;
// Saturer à la plage _q15 (-32768 à 32767)
if (temp > 32767) temp = 32767;
if (temp < -32768) temp = -32768;
buffCopy[i] = (int16_t)temp;
}
// Appliquer la FFT complexe sur le segment buffCopy
status = msp_cmplx_fft_fixed_q15(&fftParams, buffCopy);//la il y'a un probleme
msp_checkStatus(status);
// Calculer la magnitude pour chaque coefficient FFT
for (i = 0; i < FFT_LENGTH; i++) {
real = buffCopy[2 * i];
imag = buffCopy[2 * i + 1];
// Calculer le carré de la partie réelle et imaginaire
real_squared = __q15mpy(real, real); // Utilisation de la multiplication Q15
imag_squared = __q15mpy(imag, imag);
// Calculer la somme des carrés avec saturation
sum_of_squares = real_squared + imag_squared;
// Calculer la magnitude comme racine carrée (approximative)
// Ici, sqrt est approximée par une simple division et ajustement de la précision
magnitude = (_q15)sqrt(sum_of_squares); // Convertir en _q15
magnitude_q15[i] = magnitude;
}
// Convertir les valeurs de magnitude en uint16_t
for (i = 0; i < FFT_LENGTH; i++) {
// Convertir _q15 (plage -1 à 1) à uint16_t (plage 0 à 4096)
magnitude_uint16[i] = (uint16_t)((magnitude_q15[i] * MAX_VALUE)>>15);
}
UART_sendBuffer(magnitude_uint16, FFT_LENGTH);
position += FFT_LENGTH;
}
}Here is the code.If there is any missing configuration or error in the code could you please tell me