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)
PS: я использую ChibiOS - не уверен, что это актуально.