Skip to main content
Visitor II
February 21, 2024
Solved

Cordic STM32G47 f32_to q31 conversion and vice versa implementation

  • February 21, 2024
  • 4 replies
  • 1944 views

Hi,

i was working in stm32g4 series to implement  CORDIC , but i have noticed cordic is taking 6.5 e-05 sec while normal cos/sin function is taking  2.6e-06sec. let me know where I am making mistake.

below is code  i have implemented.

inline int f32_to_q31( double input )

{

const float Q_31_MAX_F = 1.0f ;// 0x0.FFFFFFp0F;//

const float Q_31_MIN_F = -1.0f;

return (int)roundf(scalbnf(fmaxf(fminf(input,Q_31_MAX_F),Q_31_MIN_F),31));

 

}

 

#define pi 3.14159265359

// convert notation integar to 32 bits float

#define q31_to_f32(x) ldexp((int32_t)x, -31) //q31 represent no in range -1,1

 

float cordic_q31_cosf(float x)

{

CORDIC_ConfigTypeDef sConfig;

int32_t input_q31 = f32_to_q31(fmod(x,2.0f*pi)/(2.0f*pi))<<1;

int32_t output_q31;

sConfig.Function = CORDIC_FUNCTION_COSINE;

sConfig.Precision = CORDIC_PRECISION_6CYCLES;

sConfig.Scale = CORDIC_SCALE_0;

sConfig.NbWrite = CORDIC_NBWRITE_1;

sConfig.NbRead = CORDIC_NBREAD_1;

sConfig.InSize = CORDIC_INSIZE_32BITS;

sConfig.OutSize = CORDIC_OUTSIZE_32BITS;

 

HAL_CORDIC_Configure(&hcordic, &sConfig);

HAL_CORDIC_CalculateZO(&hcordic, &input_q31, &output_q31,1 ,0);

return q31_to_f32(output_q31);

}

 

 

 user code begin

int i;

for(i=0;i<361;i++)

{

radian = (double)(i)*2.0*pi/360.0; //degree to radain (2pi/360)

 

 

 

start_tick= SysTick->VAL;

cordic_cos[i] = cordic_q31_cosf(radian);

stop_tick = SysTick->VAL;

elasped = (float)(start_tick - stop_tick)/170000000.0;

 

 

refrence https://www.youtube.com/watch?v=SeDyNtKRDMU

 }

 

 // normal cos function

int i;

for(i=0;i<361;i++)

{

radian = (double)(i)*2.0*pi/360.0; //degree to radain (2pi/360)

 

 

 

start_tick= SysTick->VAL;

cordic_cos[i] = cosf(radian);

stop_tick = SysTick->VAL;

elasped = (float)(start_tick - stop_tick)/170000000.0;

 }

 

 

 

}

    This topic has been closed for replies.
    Best answer by Tesla DeLorean

    Isn't SysTick a 24-bit down counter? Often at 1/8th the CPU clock?

    Would be better to use DWT CYCCNT

    Also please edit to fix Code Formatting 

    4 replies

    Super User
    February 21, 2024

    Please use this button to properly post source code:

    AndrewNeil_0-1708516957596.png

     

     

    Super User
    February 21, 2024

    If you want only 32-bit floats, why to use double type? This will cause extra library calls with a single-precision FPU.

     

    SushmitaAuthor
    Visitor II
    February 22, 2024

    i tried with, without double type, but still same execution  timing is there  1.5e-05sec

    Graduate II
    February 21, 2024

    Isn't SysTick a 24-bit down counter? Often at 1/8th the CPU clock?

    Would be better to use DWT CYCCNT

    Also please edit to fix Code Formatting 

    Explorer
    February 22, 2024

    Two remarks, not sure if they solve your problem:

    1. As mentioned above, never mix in double's :)
    2. I use a more "direct" converion from float to q1_31, see below. The stdlib functions you call may induce substantial overhead since they all operate on true floats. 

    Btw, if anyone recognizes a problem in this code, comments are welcome! I tried to get all the borderline cases right, but...

    #define CORDIC_2exp31divPI 683565275.57643158978229477811035f
    #define CORDIC_2exp31 0x1p31f
    #define CORDIC_2exp32 0x1p32f
    #define CORDIC_2exp31m1 0x7FFFFFFFp0f
    
    // theta is the float input 
    	q1_31_t Arg;
    	volatile q1_31_t Res;
    	float thetaScaled;
    // setup CORDIC as required here
    	thetaScaled = theta * CORDIC_2exp31divPI;
    	while (thetaScaled < -CORDIC_2exp31)
    		thetaScaled += CORDIC_2exp32;
    	while (thetaScaled > CORDIC_2exp31m1)
    		thetaScaled -= CORDIC_2exp32;
    	if (thetaScaled < -CORDIC_2exp31)
    		Arg = 0x80000000;
    	else
    		Arg = (q1_31_t)(thetaScaled);
    	asm volatile("": : :"memory");
    	CORDIC->WDATA = Arg;
    	asm volatile("": : :"memory");
    	CORDIC->WDATA = 0x7FFFFFFF; // the closest we can get to +1
    	asm volatile("": : :"memory");
    	Res = CORDIC->RDATA; // inserts bus wait cycles as needed