CMSIS real-FFT на 8192 образца в Q15

Мне нужно выполнить БПФ для блока из 8192 образцов на микроконтроллере STM32F446. Для этого я хотел использовать библиотеку CMSIS DSP, поскольку она легко доступна и оптимизирована для STM32F4.

Мои 8192 выборки ввода в конечном итоге будут значениями из внутреннего 12-разрядного АЦП (выровнены по левому краю и преобразованы в q15 с помощью щелчка битом знака), но для целей тестирования я загружаю БПФ тестовыми буферами.

С функциями FFT CMSIS только версия Q15 поддерживает длины 8192. Таким образом, я использую arm_rfft_q15 ().

Поскольку функции FFT библиотек CMSIS по умолчанию включают около 32 тыс. LUT - чтобы адаптироваться ко многим длинам FFT, я "переписал" их, чтобы удалить все таблицы, соответствующие другой длине, чем та, которая мне интересна. Я ничего не трогал, кроме удаления ненужного кода.

Мои образцы хранятся на внешней SDRAM, к которой я обращаюсь через DMA.

При использовании БПФ у меня возникает несколько проблем:

  • И мой исходный буфер, и мой целевой буфер модифицируются;
  • результат совсем не такой, как ожидалось

Чтобы убедиться, что у меня были неправильные результаты, я сделал IFFT сразу после FFT, но это только подтвердило, что код не работал.

Вот мой код:

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;
}

И вот результат (из GDB)

Результат GDB

PS: я использую ChibiOS - не уверен, что это актуально.

0 ответов

Другие вопросы по тегам