cancel
Showing results for 
Search instead for 
Did you mean: 

Cordic Configuration STM32G4

Bench
Associate III

Hello all,

I want to use the Cordic accelerator in a STM32G4 and calculate the atan2 from 2 input arguments. Now two questions arise:

1) Is there a package for CUBE so I can configure it there? Up to now I only see the activation button.

2) If there is no possibility, I configure the peripherals as in the given examples for sine and cosine functions. But which function do I need if I want to calculate the atan2?

Thank you a lot in advance!

Best Regards,

Ben

4 REPLIES 4
Bench
Associate III

OKay. Sorry. 2) I can answer myself. Just looked for atan2 but here its called phase...

However, it would be interesting if a further config in CUBE is possible.

> it would be interesting if a further config in CUBE is possible.

There's really nothing about CORDIC to configure in Cube, you just activate it using a checkbox (also the interrupt and DMA channels if needed) and use it in your code.

I guess you have already looked up the examples, there is also this getting started guide and the reference manual of course. Also look the code and comments of stm32g4xx_hal_cordic.{c,h} (for HAL) and stm32g4xx_ll_cordic.{c,h} (for LL) to understand what functions and definitions you can use using the libraries.

rclar.6
Associate III

The CORDIC MODULUS function acts as the atan2.

It provides the angle and magnitude of the x and y position you enter.

One thing you have to be careful about though is the binary scaling.

The inputs and outputs are fixed point.

Also if you use the MODULUS function, the first write places X in and the second Y.

The first read gives you the magnitude, and the second the angle.

The angle is scaled at B0, or is a binary angle see https://en.wikipedia.org/wiki/Binary_scaling,

so to see it as a degrees float you need to multiply it by 2^31 and then by 180.0

You also have to consider whether you want to operate on 16 bit words or 32 bit.

 #define B0_TO_DOUBLE(a) ((double)a/(TWO_TO_POW_31))

#define TWO_TO_POW_31 2147483648.0
#define B0_TO_DOUBLE(a) ((double)a/(TWO_TO_POW_31))
 
 
 MX_CORDIC_Init();
 
		  CORDICsConfig.Function = CORDIC_FUNCTION_MODULUS; // y and x. atan2 basically
		  CORDICsConfig.Scale = 0; // CORDIC_CSR_SCALE_0; // == Q1.32 or B1 making this 0 makes it B0 as it should be
		  CORDICsConfig.NbWrite = CORDIC_NBWRITE_2;
		  CORDICsConfig.NbRead = CORDIC_NBREAD_2;
		  CORDICsConfig.InSize = CORDIC_INSIZE_32BITS;
		  CORDICsConfig.OutSize = CORDIC_INSIZE_32BITS;
		  CORDICsConfig.Precision = CORDIC_PRECISION_15CYCLES;
 
          //CORDICsConfig.Function = CORDIC_FUNCTION_PHASE;
          HAL_CORDIC_Configure(&hcordic, &CORDICsConfig);
 
          pInBuff[0] = 0x40000000; // x = 0.5
          pInBuff[1] = 0x00000000; // y = 0.0
          HAL_CORDIC_Calculate(&hcordic, pInBuff, pOutBuff, 12, 1);
          magnitude = B0_TO_DOUBLE(pOutBuff[0]);
          angle = B0_TO_DOUBLE(pOutBuff[1])*180;
          asm("nop");
 
          pInBuff[0] = 0x40000000; // x = 0.5
          pInBuff[1] = 0x40000000; // y = 0.5
          HAL_CORDIC_Calculate(&hcordic, pInBuff, pOutBuff, 12, 1);
          magnitude = B0_TO_DOUBLE(pOutBuff[0]);
          angle = B0_TO_DOUBLE(pOutBuff[1])*180.0;
          asm("nop");
 
       // Now prove it works correctly in the negative quadrants
 
 
          pInBuff[0] = 0xC0000000; // x = -0.5
          pInBuff[1] = 0xC0000000; // y = -0.5
          HAL_CORDIC_Calculate(&hcordic, pInBuff, pOutBuff, 12, 1);
          magnitude = B0_TO_DOUBLE(pOutBuff[0]);
          angle = B0_TO_DOUBLE(pOutBuff[1])*180.0;
          asm("nop");
 
 
          pInBuff[0] = 0x00000000; // x = 0
          pInBuff[1] = 0x80000000; // y = -1
          HAL_CORDIC_Calculate(&hcordic, pInBuff, pOutBuff, 12, 1);
          magnitude = B0_TO_DOUBLE(pOutBuff[0]);
          angle = B0_TO_DOUBLE(pOutBuff[1])*180.0;
          asm("nop");
          asm("nop");

I'm currently using the CORDIC peripheral for the first time and found your example to be a good reference. I just had a few questions I was hoping you could clear up:

  1. The fourth argument in HAL_CORDIC_Calculate is the number of CORDIC calculations to process. I figured this should match the number of arguments in pInBuff which in this case is 2 (though you use 12). Is this correct?
  2. Are the NOP calls necessary, and if so why?

Thanks.