cancel
Showing results for 
Search instead for 
Did you mean: 

Cordic STM32G47 f32_to q31 conversion and vice versa implementation

Sushmita
Associate II

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;

 }

 

 

 

}

1 ACCEPTED SOLUTION

Accepted Solutions

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 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

5 REPLIES 5
Andrew Neil
Evangelist

Please use this button to properly post source code:

AndrewNeil_0-1708516957596.png

 

 

Pavel A.
Evangelist III

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

 

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 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

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

stryga
Associate II

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