Necesito realizar una FFT en un bloque de 8192 muestras en un STM32F446 . Para eso quería usar la biblioteca CMSIS DSP ya que está disponible fácilmente y optimizada para el STM32F4.
Mis 8192 muestras de entrada serán finalmente valores del ADC interno de 12 bits (alineados a la izquierda y convertidos a q15 al voltear el bit de signo), pero para fines de prueba estoy alimentando a la FFT con buffers de prueba.
Con las funciones FFT de CMSIS, solo la versión Q15 admite longitudes de 8192. Por lo tanto, estoy usando arm_rfft_q15 () .
Debido a que las funciones FFT de las bibliotecas CMSIS incluyen, por defecto, alrededor de 32k de LUT; para adaptarse a muchas longitudes FFT, las he "reescrito" para eliminar todas las tablas correspondientes a otra longitud que no sea la que me interesa. No he tocado nada, excepto eliminar el código inútil.
Mis muestras se almacenan en una SDRAM externa a la que accedo a través de DMA.
Al usar la FFT, tengo varios problemas:
- Se modifican tanto mi búfer de origen como mi búfer de destino;
- el resultado no es en absoluto como se esperaba
Para asegurarme de que obtuve resultados incorrectos, hice un IFFT justo después del FFT, pero simplemente confirmó que el código no estaba funcionando.
Aquí está mi código:
status_codes FSM::fft_state(void)
{
// Flush the SDRAM section
si_ovf_buf_clr_u16((uint16_t *)0xC0000000, 8192);
q15_t* buf = (q15_t*)(0xC0000000);
for(int i = 0; i<50; i++)
buf[i] = 0x0FFF; // Fill the buffer with test vector (50 sp gate)
// initialise FFT
// ---> Forward, 8192 samples, bitReversed
arm_rfft_instance_q15 S;
if(arm_rfft_init_q15(&S, 8192, 0, 1) != ARM_MATH_SUCCESS)
return state_error;
// perform FFT
arm_rfft_q15(&S, (q15_t*)0xC0000000, (q15_t*)0xC0400000);
// Post-shift by 12, in place (see doc)
arm_shift_q15((q15_t*)0xC0400000, 12, (q15_t*)0xC0400000, 16384);
// Init inverse FFT
if(arm_rfft_init_q15(&S, 8192, 1, 1) != ARM_MATH_SUCCESS)
return state_error;
// Perform iFFT
arm_rfft_q15(&S, (q15_t*)0xC0400000, (q15_t*)0xC0800000);
// Post shift
arm_shift_q15((q15_t*)0xC0800000, 12, (q15_t*)0xC0800000, 8192);
return state_success;
}
Y aquí está el resultado (de GDB)
PD:estoyusando