Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
/******************************************************************************
* File Name: main.c
*
* Description: This is the source code for the XMC MCU: MATH CORDIC example
* for ModusToolbox. The example uses the MATH CORDIC block to
* perform the circular, hyperbolic and logarithmic operations.
*
* Related Document: See README.md
*
******************************************************************************
*
* Copyright (c) 2021, Infineon Technologies AG
* All rights reserved.
*
* Boost Software License - Version 1.0 - August 17th, 2003
*
* Permission is hereby granted, free of charge, to any person or organization
* obtaining a copy of the software and accompanying documentation covered by
* this license (the "Software") to use, reproduce, display, distribute,
* execute, and transmit the Software, and to prepare derivative works of the
* Software, and to permit third-parties to whom the Software is furnished to
* do so, all subject to the following:
*
* The copyright notices in the Software and this entire statement, including
* the above license grant, this restriction and the following disclaimer,
* must be included in all copies of the Software, in whole or in part, and
* all derivative works of the Software, unless such copies or derivative
* works are solely in the form of machine-executable object code generated by
* a source language processor.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************/
/*******************************************************************************
* Include header files
*******************************************************************************/
#include "cybsp.h"
#include "cy_utils.h"
#include "xmc_math.h"
#include "cy_retarget_io.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*******************************************************************************
* Macros
*******************************************************************************/
/* Inputs for CORDIC Operations */
#define NUMBER_FOR_LOG_OPERATION 3
#define ANGLE_FOR_COS_OPERATION (PI/3)
#define ANGLE_FOR_SINH_OPERATION (PI/4)
/* 2^23 = 8388608 = 0x800000 */
#define TWO_POWER_TWENTY_THREE 8388608
#define TWO_POWER_TWENTY_TWO (TWO_POWER_TWENTY_THREE / 2)
#define PI 3.14159f
#define STRING_BUFFER_SIZE 10
#define MATH_INTERRUPT_PRIORITY 3
/* Macro function to scale angle values. angle * (8388608/pi) */
#define ANGLE_TO_CORDIC_Z(ANGLE) (ANGLE * (TWO_POWER_TWENTY_THREE / PI))
/* Macro function to convert a Q0_23 number to a float number. Divide the number
* by 2^23 to shift fractional bits to the right
*/
#define Q0_23_TO_FLOAT(Q0_23_NUMBER) ((float)Q0_23_NUMBER / TWO_POWER_TWENTY_THREE)
/* Macro function to convert a Q1_22 number to a float number. Divide the number
* by 2^22 to shift fractional bits to the right
*/
#define Q1_22_TO_FLOAT(Q1_22_NUMBER) ((float)Q1_22_NUMBER / TWO_POWER_TWENTY_TWO)
/*******************************************************************************
* Global Variables
********************************************************************************/
/* Variable to detect when the interrupt occurs */
volatile uint8_t interrupt_flag = 0;
/* Variable to store the result of CORDIC operation in Q1_22 format */
XMC_MATH_Q1_22_t cordic_result_q1_22;
/*******************************************************************************
* Function Name: float_to_string
********************************************************************************
* Summary:
* Function to convert a float number to a string
*
* Parameters:
* char* string_buffer - Pointer to the string
* uint8_t buf_size - Size of the string buffer
* float number - Float number that needs to be converted to string
*
* Return:
* void
*
*******************************************************************************/
void float_to_string(char* string_buffer, uint8_t buf_size, float number)
{
/* Check if number is negative */
uint8_t is_negative;
if(number < 0)
{
is_negative = 1;
number = -number;
}
else
{
is_negative = 0;
}
int integral_part = (int)number;
int decimal_part = (number - integral_part) * 1000;
if(is_negative)
{
snprintf(string_buffer, buf_size, "-%d.%03d", integral_part, decimal_part);
}
else
{
snprintf(string_buffer, buf_size, "%d.%03d", integral_part, decimal_part);
}
}
/*******************************************************************************
* Function Name: MATH0_0_IRQHandler
********************************************************************************
* Summary:
* The interrupt handler for the MATH Coprocessor interrupt. Reads the sinh()
* CORDIC result and sets the interrupt flag.
*
* Parameters:
* void
*
* Return:
* void
*
*******************************************************************************/
void MATH0_0_IRQHandler(void)
{
/* Clear the event flag */
XMC_MATH_ClearEvent(XMC_MATH_EVENT_CORDIC_END_OF_CALC);
/* Read the calculated result */
cordic_result_q1_22 = XMC_MATH_CORDIC_GetSinhResult();
interrupt_flag = 1;
}
/*******************************************************************************
* Function Name: main
********************************************************************************
* Summary:
* System entrance point. This function
* - performs initial setup of device
* - calculates the cos() of an angle using blocking CORDIC operation
* - demonstrates how to use non-blocking CORDIC operations by performing a
* sinh() operation
* - calculates ln() operation by direct CORDIC register writes
* - prints debug messages and results on the terminal
*
* Parameters:
* void
*
* Return:
* int
*
*******************************************************************************/
int main(void)
{
/* Variable initialization */
cy_rslt_t result;
float final_result = 0;
char string_buffer[STRING_BUFFER_SIZE];
/* Variable to store the result of CORDIC operation in Q0_23 format */
XMC_MATH_Q0_23_t cordic_result_q0_23;
/* Variable used to store the angle input */
XMC_MATH_Q0_23_t angle;
/* Initialize the device and board peripherals */
result = cybsp_init() ;
if (result != CY_RSLT_SUCCESS)
{
CY_ASSERT(0);
}
/* Enable global interrupts */
__enable_irq();
/* Initialize retarget-io to use the debug UART port */
cy_retarget_io_init(CYBSP_DEBUG_UART_HW);
/* \x1b[2J\x1b[;H - ANSI ESC sequence to clear screen. */
printf("\x1b[2J\x1b[;H");
printf("===============================================================\r\n");
printf("XMC MCU: MATH CORDIC example\r\n");
printf("===============================================================\r\n\n");
/* Step 1: Perform a blocking cos() operation
*
* Angle Value: pi/3
* The angle value needs to be scaled by 8388608/pi as it is Z input for
* CORDIC circular operation.
*
* Expected CORDIC Result: 4194305
* The CORDIC result is then converted from Q0_23 format to float.
*
* Final Result: 0.5
*/
printf("Step 1: Blocking cos() operation\r\n\r\n");
printf("Angle = pi/3\r\n\r\n");
/* angle * (8388608/pi) */
angle = ANGLE_TO_CORDIC_Z(ANGLE_FOR_COS_OPERATION);
/* cosine of angle calculation */
cordic_result_q0_23 = XMC_MATH_CORDIC_Cos(angle);
printf("CORDIC Result = %d\r\n", (int)cordic_result_q0_23);
/* Convert the CORDIC result from Q0_23 format to float */
final_result = Q0_23_TO_FLOAT(cordic_result_q0_23);
/* Prepare a string buffer to display the float result */
float_to_string(string_buffer, STRING_BUFFER_SIZE, final_result);
printf("Final Result = %s\r\n", string_buffer);
printf("===============================================================\r\n\n");
/* Step 2: Perform a non-blocking sinh() operation
*
* Angle Value: pi/4
* The angle value needs to be scaled by 8388608/pi as it is Z input for
* CORDIC hyperbolic operation.
*
* Expected CORDIC Result: 3643469
* The CORDIC result is then converted from Q1_22 format to float.
*
* Final Result: 0.868
*/
printf("Step 2: Non-blocking sinh() operation\r\n\r\n");
printf("Angle = pi/4\r\n\r\n");
/* angle * (8388608/pi) */
angle = ANGLE_TO_CORDIC_Z(ANGLE_FOR_SINH_OPERATION);
/* Configure CORDIC end-of-calculation interrupt */
XMC_MATH_EnableEvent(XMC_MATH_EVENT_CORDIC_END_OF_CALC);
NVIC_SetPriority(MATH0_0_IRQn, MATH_INTERRUPT_PRIORITY);
NVIC_EnableIRQ(MATH0_0_IRQn);
/* Calculate sinh(angle) */
XMC_MATH_CORDIC_SinhNB(angle);
/* Wait for interrupt to occur. */
while(interrupt_flag == 0)
{
/* CPU can perform other tasks here */
}
printf("CORDIC Result = %d\r\n", (int)cordic_result_q1_22);
/* Convert the CORDIC result from Q1_22 format to float */
final_result = Q1_22_TO_FLOAT(cordic_result_q1_22);
/* Prepare a string buffer to display the float result */
float_to_string(string_buffer, STRING_BUFFER_SIZE, final_result);
printf("Final Result = %s\r\n", string_buffer);
printf("===============================================================\r\n\n");
/* Step 3: Perform a natural logarithm operation
*
* Number: 3
*
* Expected CORDIC Result: 2936454
* The CORDIC result needs to be multiplied by (pi/8388608) as it is Z output
* for CORDIC hyperbolic operation.
* ln(3) = 2936454*(pi/8388608)
*
* Final Result: 1.099
*/
printf("Step 3: Natural logarithm operation\r\n\r\n");
printf("Number = 3\r\n\r\n");
/* Variable initialization for logarithmic operation */
int32_t number = NUMBER_FOR_LOG_OPERATION;
int32_t log_result;
/* Configure CORDIC registers for calculation
* ST_MODE = 0, Auto start when CORDX is written
* ROTVEC = 0, Vectoring Mode
* MODE = 11b, Hyperbolic Mode
* ST = 0, Start only after CORDX is written
*/
MATH->CON = 0b00110;
/* Load the initial angle value */
MATH->CORDZ = 0;
/* Load (number-1) */
MATH->CORDY = ((number - 1) << 8);
/* Load (number+1) */
MATH->CORDX = ((number + 1) << 8);
/* CORDIC will automatically start */
/* Wait for calculation to end */
while(XMC_MATH_CORDIC_IsBusy());
/* Read out the calculated results */
log_result = (MATH->CORRZ >> 8);
/* ln(x) = 2*atanh[(x-1)/(x+1)] */
log_result = 2 * log_result;
/* The CORDIC result is scaled up by 8388608/pi. So result is multiplied
* by pi/8388608
*/
final_result = ((float)log_result) * (PI / TWO_POWER_TWENTY_THREE);
printf("CORDIC Result = %d\r\n", (int)log_result);
/* Prepare a string buffer to display the float result */
float_to_string(string_buffer, STRING_BUFFER_SIZE, final_result);
printf("Final Result = %s\r\n", string_buffer);
printf("===============================================================\r\n\n");
for (;;)
{
}
}
/* [] END OF FILE */