RFFT en 8192 muestras en Q15 con CMSIS

1

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 ChibiOS : no estoy seguro de que sea relevante.

    
pregunta Florent

0 respuestas

Lea otras preguntas en las etiquetas