2024-02-21 03:52 AM
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;
}
// 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;
}
}
Solved! Go to Solution.
2024-02-21 05:09 AM
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
2024-02-21 04:02 AM
Please use this button to properly post source code:
2024-02-21 04:51 AM
If you want only 32-bit floats, why to use double type? This will cause extra library calls with a single-precision FPU.
2024-02-21 05:09 AM
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
2024-02-21 08:49 PM
i tried with, without double type, but still same execution timing is there 1.5e-05sec
2024-02-22 02:36 AM
Two remarks, not sure if they solve your problem:
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