I’ve been trying to get FFTS working as well. Using the additions to the makefile that @fredyeah suggested, it’s linking the .c files. However, it seems one of the files required for arm_rfft_fast_f32 is arm_bitreversal2.S.
Since this is an assembly file, the makefile doesn’t seem to have a rule for passing it to the compiler. I’ve tried several things, but I can’t seem to get it to work. Does anyone know how to set up the makefile to get this to work? This is the first time I’ve ever used makefiles and I’m finding it a bit confusing.
Or if anyone knows of any open source projects using FFTs on the Daisy, that would help immensely. I’ve not been able to find any code using FFTs to use as a model.
I haven’t done it with wildcarding, but there are three variables that need to be edited/set to work add the CMSIS files.
I was only using a few things when I was experimenting so the C_SOURCES list is fairly short.
However, as many files as needed can be added manually. It should also be able to be set with a wildcard similar to above.
This can sneak by until you hit the compiler error:
arm-none-eabi-cpp is the ‘C preprocessor’ - it handles expansion of macros like #if, #ifdef, #include, etc. It’s not just for C, also useful for c++, assembler and anything else that needs this type of macro expansion.
The point is that .S files might have macros that need preprocessing, and .s files don’t. doesn’t include a rule for transforming a .S file to a .o file.
There are various ways to get this to build, but I haven’t figured out a good one which doesn’t involve hacking DaisyExamples/libDaisy/core/Makefile .
how can I prune my code, which is just doing an FFT->iFFT and nothing else ?
#include "daisy_seed.h"
#include "daisysp.h"
#include "arm_math.h"
// Use the daisy namespace to prevent having to type
// daisy:: before all libdaisy functions
using namespace daisy;
using namespace daisysp;
// Declare a DaisySeed object called hardware
DaisySeed hardware;
Oscillator osc;
AdEnv env;
arm_rfft_fast_instance_f32* fftInstance;
float32_t *fftBuffer;
void AudioCallback(AudioHandle::InterleavingInputBuffer in,
AudioHandle::InterleavingOutputBuffer out,
size_t size)
{
float osc_out;
//Fill the block with samples
for(size_t i = 0; i < size; i += 2)
{
osc_out = osc.Process();
//Set the left and right outputs
out[i] = osc_out;
// out[i + 1] = osc_out;
out[i+1] = in[i+1];
arm_rfft_fast_f32(fftInstance,(float32_t*)&in[0],fftBuffer,0);
arm_rfft_fast_f32(fftInstance,fftBuffer,(float32_t*)&out[0],1);
}
}
int main(void)
{
// Declare a variable to store the state we want to set for the LED.
bool led_state;
led_state = true;
// Configure and Initialize the Daisy Seed
// These are separate to allow reconfiguration of any of the internal
// components before initialization.
hardware.Configure();
hardware.Init();
hardware.SetAudioBlockSize(4);
//How many samples we'll output per second
float samplerate = hardware.AudioSampleRate();
fftInstance = new arm_rfft_fast_instance_f32;
arm_status status = arm_rfft_fast_init_f32(fftInstance, hardware.AudioBlockSize());
fftBuffer = new float32_t[hardware.AudioBlockSize()];
//Set up oscillator
osc.Init(samplerate);
osc.SetWaveform(osc.WAVE_SIN);
osc.SetAmp(1.f);
osc.SetFreq(440);
hardware.StartAudio(AudioCallback);
// Loop forever
for(;;)
{
// Set the onboard LED
hardware.SetLed(led_state);
// Toggle the LED state for the next time around.
led_state = !led_state;
// Wait 500ms
System::Delay(500);
}
}
The cause of that error is the result of objects being too big to fit in the data section. You can try moving some of the stuff to SDRAM.
Our guess is that the fftInstance is the really big thing that should be moved.
So, arm_rfft_fast_instance_f32 DSY_SDRAM_BSS fftInstance; to move that object to the SDRAM.
Also, new is not typically used in embedded in our experience and will require some refactoring to use the SDRAM. Therefore, everywhere you reference it needs to be changed to &fftInstance.
I’m still struggling to fit this on my patch.init(), anyone had sucess here? In this minimal example (that doesn’t make sense, just trying to compile), both fft instance and buffer are on SDRAM_BSS but still no joy - any ideas?
/Applications/ArmGNUToolchain/12.3.rel1/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.1/../../../../arm-none-eabi/bin/ld: build/spectral.elf section `.text' will not fit in region `FLASH'
/Applications/ArmGNUToolchain/12.3.rel1/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.1/../../../../arm-none-eabi/bin/ld: region `FLASH' overflowed by 68868 bytes
/Applications/ArmGNUToolchain/12.3.rel1/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/12.3.1/../../../../arm-none-eabi/bin/ld: warning: build/spectral.elf has a LOAD segment with RWX permissions
Memory region Used Size Region Size %age Used
FLASH: 199940 B 128 KB 152.54%
DTCMRAM: 0 GB 128 KB 0.00%
SRAM: 13864 B 512 KB 2.64%
RAM_D2: 16896 B 288 KB 5.73%
The main source of program memory usage with CMSIS DSP FFT stuff is the constant lookup table (LUT) data used for various sizes of FFT. I believe in older versions of CMSIS DSP all the LUTs for all the supported sizes are linked into program data, whereas with the newer versions allow you to specify which ones you want to compile/include via preprocessor definitions.
The latest main branch of libDaisy was recently updated with a newer CMSIS DSP version and if you’re up-to-date with the main branch, something like this will work in your makefile (adapted from one of my own projects).
It’s a little bit clumsy to do it like this, but it works - whatever MY_FFT_SIZE is set to determines which LUTs are actually compiled and linked. There’s also some kind of python configuration tool included with CMSIS-DSP that seems to automate some of this but I’ve not tried to integrate it with the libDaisy Makefile build process.
Of course, with larger FFT sizes the LUT data still might not fit into program memory internal to the STM32, so you may need to use the Daisy Bootloader instead.
I’ve got a really slick spectrum display running @60fps 4096 size - it’s fantastic on a 320x170x16bit 2" display. But I noticed that arm_rfft_fast_f32 trashes the input array! Can’t see anything in the docs about that.
thx - the docs I read didn’t mention the src getting mangled (or maybe I misinterpreted it in a coding frenzy!)
Guess it’s some radix/butterfly shenanigans doing that under the hood!
I apply a window every frame and my input data is a fifo pipe - hence “FFTInTemp”. I recreate the input every time. Works great and snappy - 4096 size = 1-2ms (shows 1ms at gettick granularity).
this is exactly what i’ve been looking for lately! I started my fft project attempting to use cmsis but then diverted to shy_fft after struggling with the LUT issue