cancel
Showing results for 
Search instead for 
Did you mean: 

STM32WB55RG Board - Using CMSIS functions to implement FFT filtering

RPHON
Associate

Good morning everyone,

I'm coding with Atollic Truestudio and CubeMX.

I would like to ask for some helps concerning a function called "arm_bitreversal_32" in the "arm_cfft_f32.c".

Here is my problem.

I'm trying to use the function "arm_cfft_f32(x,x,x,x)" from the "arm_cfft_f32.c" file. And I got this error in this C file:

  • undefined reference to `arm_bitreversal_32'

I'm not sure if some files are missed or I should implement it by myself because the function "arm_bitreversal_32()" is declare externally (extern void arm_bitreversal_32()).

I thank everyone who will try to help me to resolve my error.

arm_cfft_f32.c":

#include "arm_math.h"
#include "arm_common_tables.h"
 
extern void arm_radix8_butterfly_f32(
    float32_t * pSrc,
    uint16_t fftLen,
    const float32_t * pCoef,
    uint16_t twidCoefModifier);
 
extern void arm_bitreversal_32(
    uint32_t * pSrc,
    const uint16_t bitRevLen,
    const uint16_t * pBitRevTable);
void arm_cfft_f32( 
    const arm_cfft_instance_f32 * S, 
    float32_t * p1,
    uint8_t ifftFlag,
    uint8_t bitReverseFlag)
{
    uint32_t  L = S->fftLen, l;
    float32_t invL, * pSrc;
 
    if(ifftFlag == 1u)
    {
        /*  Conjugate input data  */
        pSrc = p1 + 1;
        for(l=0; l<L; l++) 
        {
            *pSrc = -*pSrc;
            pSrc += 2;
        }
    }
 
    switch (L) 
    {
    case 16: 
    case 128:
    case 1024:
        arm_cfft_radix8by2_f32  ( (arm_cfft_instance_f32 *) S, p1);
        break;
    case 32:
    case 256:
    case 2048:
        arm_cfft_radix8by4_f32  ( (arm_cfft_instance_f32 *) S, p1);
        break;
    case 64:
    case 512:
    case 4096:
        arm_radix8_butterfly_f32( p1, L, (float32_t *) S->pTwiddle, 1);
        break;
    }  
 
    if( bitReverseFlag )
        arm_bitreversal_32((uint32_t*)p1,S->bitRevLength,S->pBitRevTable);
 
    if(ifftFlag == 1u)
    {
        invL = 1.0f/(float32_t)L;
        /*  Conjugate and scale output data */
        pSrc = p1;
        for(l=0; l<L; l++) 
        {
            *pSrc++ *=   invL ;
            *pSrc  = -(*pSrc) * invL;
            pSrc++;
        }
    }
}

main.c:

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32wbxx_hal.h"
#include "arm_math.h"
#include "arm_common_tables.h"
#include "arm_const_structs.h"
#include <math.h>
 
/* Global variables */
 
/*	Global define	*/
#define SAMPLE_FREQUENCY_UNDEC		1024		// A ajuster selon la frequence de la porteuse
#define SAMPLE_TIME_UNDEC			(float)	1.0/SAMPLE_FREQUENCY_UNDEC
#define SAMPLES_UNDEC				(int)	8*SAMPLE_FREQUENCY_UNDEC				/* 8 secondes au total */
 
/*	Decimation define	*/
#define NUMTAPS					(uint16_t)	31		// Order(30)	+	1
#define M 						(uint8_t)	32		// Divise SAMPLE_FREQ_UNDEC. Limite max : M < VIBE_SAMPLE
#define BLOCKSIZE				(uint32_t)	64
#define NUMBLOCKS 				(uint32_t)	SAMPLES_UNDEC/BLOCKSIZE
 
 
/*	FFT define	*/
#define FFT_SIZE		SAMPLES_UNDEC/M
 
/*	Simulation define	*/
#define CARRIER_FREQUENCY				256		// Attention multiple de 2 pour que SAMPLE_FREQUENCY multiple de CARIIER_FREQUENCY afin que VIBE_SAMPLES soit entier
#define CARRIER_SIZE			(int)	SAMPLE_FREQUENCY_UNDEC/CARRIER_FREQUENCY
#define MODUL_FREQUENCY					1
#define VIBE_FREQUENCY			(int)	0.1*CARRIER_FREQUENCY
#define VIBE_SAMPLES 			(int)	(SAMPLE_FREQUENCY_UNDEC/CARRIER_FREQUENCY)*(VIBE_FREQUENCY)		// Multiple de 1/CARRIER_FREQUENCY, durée 0;01 s. Durée minimale = 1/CARRIER_FREQUENCY; durée max = 1/MODUL_FREQUENCY
#define MODUL_SIZE				(int) 	SAMPLE_FREQUENCY_UNDEC/MODUL_FREQUENCY
#define SIM_SIZE				(int)	MODUL_SIZE
 
 
/* Decimation settings */
const float32_t firCoeffs[NUMTAPS]	=	{0.0035214853,0.004185653,0.005849378,0.008574021,0.012351584,0.017101394,0.022671906,0.028847635,0.035360847,0.041907296,0.048164908,0.053814158,0.058558714,0.06214481,0.064378045,0.065136336,0.064378045,0.06214481,0.058558714,0.053814158,0.048164908,0.041907296,0.035360847,0.028847635,0.022671906,0.017101394,0.012351584,0.008574021,0.005849378,0.004185653,0.0035214853};
static float32_t firState[NUMTAPS + BLOCKSIZE - 1];
static float32_t undecimatedSignal[SAMPLES_UNDEC];
static float decimatedSignal[SAMPLES_UNDEC/M];
static float32_t *pDecimatorInput, *pDecimatorOutput;
 
/* FFT settings */
static float fftInput[FFT_SIZE*2];		//	Initialize with zeros
static float fftOutput[FFT_SIZE];		//	Initialize with zeros
static float maxValue;					//	Max FFT value is stored here
static uint32_t maxIndex;				//	Index in Ouput arraywhere max value is
 
/*	Define simulation settings	*/
float carrier[CARRIER_SIZE];
float modul[MODUL_SIZE];
float sim[SIM_SIZE];
 
 
 
/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
 
RTC_HandleTypeDef hrtc;
 
TIM_HandleTypeDef htim16;
 
UART_HandleTypeDef huart1;
 
PCD_HandleTypeDef hpcd_USB_FS;
 
/* USER CODE BEGIN PV */
 
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM16_Init(void);
static void MX_RTC_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_USB_PCD_Init(void);
 
/*	Functions	*/
/*	Create the carrier buffer	*/
void calculate_carrier(){
	for(int i = 0; i < CARRIER_SIZE; i += 1){
		float t = i * SAMPLE_TIME_UNDEC;
		float phase = 2 * PI * CARRIER_FREQUENCY * t;
		carrier[i] = sin(phase);
	}
}
 
/*	Create the modulator buffer	*/
void calculate_modulator(){
	for(int i = 0; i < VIBE_SAMPLES; i += 1){
		modul[i] = 1.0;
	}
	for(int i = VIBE_SAMPLES; i < MODUL_SIZE; i += 1){
		modul[i] = 0.0;
	}
}
 
/*	Calculate the sim signal	*/
void calculate_sim(){
	calculate_carrier();
	calculate_modulator();
	for(int i= 0; i < SIM_SIZE; i += 1){
		int i_size	= ((float) i) / CARRIER_SIZE;
		int i_carrier = i - CARRIER_SIZE * i_size;
		sim[i] = 0.5 * modul[i] * carrier[i_carrier] + 0.5;
	}
}
 
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_TIM16_Init();
  MX_RTC_Init();
  MX_USART1_UART_Init();
  MX_USB_PCD_Init();
  /* USER CODE BEGIN 2 */
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
	  /*	DAC record	*/
	  	  for(int i = 0; i < SAMPLES_UNDEC; i += 1){
	  		  HAL_Delay(SAMPLE_TIME_UNDEC);
	  		  HAL_ADC_Start(&hadc1);
	  		  if(HAL_ADC_PollForConversion(&hadc1, 5) == HAL_OK)
	  		  {
	  			  undecimatedSignal[i] = abs(HAL_ADC_GetValue(&hadc1) - 0.5f);
	  		  }
	  	  }
 
	  	  /*	Decimation	*/
	  	  arm_fir_decimate_instance_f32 S;
	  	  arm_fir_decimate_init_f32(&S, NUMTAPS, M, &firCoeffs[0], &firState[0], BLOCKSIZE );
	  	  pDecimatorInput = &undecimatedSignal[0];
	  	  pDecimatorOutput = &decimatedSignal[0];
	  	  for(int i = 0; i < NUMBLOCKS; i ++){
	  		  arm_fir_decimate_f32(&S, pDecimatorInput + (i * BLOCKSIZE), pDecimatorOutput + (i * BLOCKSIZE/M), BLOCKSIZE);
	  	  }
 
	  	  /*	Init FFT	*/
	  	  float meanDecimatedSignal;
	  	  arm_mean_f32(decimatedSignal, SAMPLES_UNDEC/M, &meanDecimatedSignal);
	  	  for(int i = 0; i < 2 * FFT_SIZE; i += 2){
	  		  fftInput[i] = decimatedSignal[i/2] - meanDecimatedSignal;
	  		  fftInput[i+1] = 0;
	  	  }
 
	  	  if(FFT_SIZE == 1024){
	  		  arm_cfft_f32(&arm_cfft_sR_f32_len1024, fftInput, 0, 1);
	  	  }else if(FFT_SIZE == 512){
	  		  arm_cfft_f32(&arm_cfft_sR_f32_len512, fftInput, 0, 1);
	  	  }else if(FFT_SIZE == 256){
	  		  arm_cfft_f32(&arm_cfft_sR_f32_len256, fftInput, 0, 1);
	  	  }else if(FFT_SIZE == 128){
	  		  arm_cfft_f32(&arm_cfft_sR_f32_len128, fftInput, 0, 1);
	  	  }
 
	  	  /*	Compute FFT and max value	*/
	  	  arm_cmplx_mag_f32(fftInput, fftOutput, FFT_SIZE);
	  	  arm_max_f32(fftOutput, FFT_SIZE/2, &maxValue, & maxIndex);
 
	  	  /*	FFT Result	*/
	  	  float freqStep = (SAMPLE_FREQUENCY_UNDEC/((float)M) / ((float)FFT_SIZE));
	  	  float maxFreq = maxIndex * freqStep;
	  	  HAL_UART_Transmit(&huart1, "maxFreq", strlen("maxFreq"), 10);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

2 REPLIES 2
RPHON
Associate

Hello,

can someone help me with this problem?

CYU.1
Associate

Seven months have passed and I don't know if you still need help,I have the same problem as you,but i didn't use cubex,

The arm_radix8_butterfly_f32 is in the "arm_cfft_radix8_f32.c" which under the CMSIS/5.6.0/CMSIS/DSP/Source/TranformFunctions folder .And the arm_bitreversal_f32 is in the same folder ——"arm_bitrevesal.c" .That means you need to add them separately.

Good Luck