# Coordinate Rotation Digital Computer (CORDIC)

[中文]

## Overview

CORDIC (Coordinate Rotation Digital Computer) is an iterative method for computing trigonometric, hyperbolic, and arctangent functions. The algorithm converts these operations into simple additions and shifts through iterative rotations and scaling, enabling efficient hardware-based computation.

CORDIC is primarily implemented in hardware with the following characteristics:

- High computation speed

- High precision

- Lower resource usage

The table below compares the performance of computing the cosine of a random value using a CORDIC driver and the software IQmath library, measured in CPU cycles.

Function | IQmath | CORDIC
--- | --- | ---
cos | 29640 | 8080

## Driver Introduction

Before using the CORDIC driver, you should understand its calculation methods and parameter meanings.

### Calculation Methods

The CORDIC function is selected via `cordic_calculate_config_t::function`. Supported functions are listed in the table below. Some functions take two arguments, others one; some produce two results, others one.

The input scaling factor can be set with `cordic_calculate_config_t::scale_exp` (effective scaling is \(2^n\)). In the table below, \(n\) denotes this parameter.

\(arg_{1}\) and \(arg_{2}\) are the inputs, corresponding to `cordic_input_buffer_desc_t::p_data_arg1` and `cordic_input_buffer_desc_t::p_data_arg2`. \(res_{1}\) and \(res_{2}\) are the outputs, corresponding to `cordic_output_buffer_desc_t::p_data_res1` and `cordic_output_buffer_desc_t::p_data_res2`. The mapping is summarized in the following table.

CORDIC Supported Functions and Formulas
Function | Input | Output | Scale exponent \(n\) | Input/Output range (scale = 1)
--- | --- | --- | --- | ---
`ESP_CORDIC_FUNC_COS` Cosine | \(\frac{\theta}{\pi}, \quad \theta \text{ in radians}\) | \(res_1 = \cos(\theta)\), \(res_2 = \sin(\theta)\) | 0 | \(arg_1, res_1, res_2 \in \left[-1, 1\right)\)
`ESP_CORDIC_FUNC_SIN` Sine | \(\frac{\theta}{\pi}, \quad \theta \text{ in radians}\) | \(res_1 = \sin(\theta)\), \(res_2 = \cos(\theta)\) | 0 | \(arg_1, res_1, res_2 \in \left[-1, 1\right)\)
`ESP_CORDIC_FUNC_PHASE` Phase | \(arg_1 = x \cdot 2^{-n}\), \(arg_2 = y \cdot 2^{-n}\) | \(res_1 = \arctan(y/x) \cdot 2^{-n}/\pi\), \(res_2 = \sqrt{x^2+y^2} \cdot 2^{-n}\) | [0, 15] | \(arg_{1,2} \in \left[-1, 1\right)\), \(res_1 \in \left[-1, 1\right)\), \(res_2 \in \left[0, 1\right)\)
`ESP_CORDIC_FUNC_MODULUS` Modulus | \(arg_1 = x \cdot 2^{-n}\), \(arg_2 = y \cdot 2^{-n}\) | \(res_1 = \sqrt{x^2+y^2} \cdot 2^{-n}\), \(res_2 = \arctan(y/x) \cdot 2^{-n}/\pi\) | [0, 15] | \(arg_{1,2} \in \left[-1, 1\right)\), \(res_1 \in \left[0, 1\right)\), \(res_2 \in \left[-1, 1\right)\)
`ESP_CORDIC_FUNC_ARCTAN` Arctangent | \(arg_1 = x \cdot 2^{-n}\) | \(res_1 = \arctan(x) \cdot 2^{-n}/\pi\) | [0, 15] | \(arg_1, res_1 \in \left[-1, 1\right)\)
`ESP_CORDIC_FUNC_COSH` Hyperbolic cosine | \(arg_1 = x \cdot 2^{-n}\) | \(res_1 = \cosh(x) \cdot 2^{-n}\), \(res_2 = \sinh(x) \cdot 2^{-n}\) | 1 | \(arg_1 \in \left[-0.559, 0.559\right]\), \(res_1 \in \left[0.5, 0.846\right]\), \(res_2 \in \left[-0.683, 0.683\right]\)
`ESP_CORDIC_FUNC_SINH` Hyperbolic sine | \(arg_1 = x \cdot 2^{-n}\) | \(res_1 = \sinh(x) \cdot 2^{-n}\), \(res_2 = \cosh(x) \cdot 2^{-n}\) | 1 | \(arg_1 \in \left[-0.559, 0.559\right]\), \(res_1 \in \left[-0.683, 0.683\right]\), \(res_2 \in \left[0.5, 0.846\right]\)
`ESP_CORDIC_FUNC_ARCHTANH` Inverse hyperbolic tangent | \(arg_1 = x \cdot 2^{-n}\) | \(res_1 = \mathrm{arctanh}(x) \cdot 2^{-n}\) | 1 | \(arg_1 \in \left[-0.403, 0.403\right]\), \(res_1 \in \left[-0.559, 0.559\right]\)
`ESP_CORDIC_FUNC_LOGE` Natural logarithm | \(arg_1 = (x-1)/(x+1) \cdot 2^{-1}\) | \(res_1 = \ln(x) \cdot 2^{-2}\) | 1 | \(arg_1 \in \left[-0.403, 0.403\right]\), \(res_1 \in \left[-0.559, 0.559\right]\)
`ESP_CORDIC_FUNC_SQUARE_ROOT` Square root | \(arg_1 = x \cdot 2^{-n}\) | \(res_1 = \sqrt{x} \cdot 2^{-n}\) | [0, 4] | \(arg_1 \in \left[0.1069, 1\right)\), \(res_1 \in \left[0.177, 1\right)\)

### Data Format

Input and output data format is selected via `cordic_calculate_config_t::iq_format`. Supported formats:

- `ESP_CORDIC_FORMAT_Q15` Q15 format

  In Q15 format, data has one sign bit plus 15 fractional bits. Range: [-1 (0x8000), 1 - 2^-15 (0x7FFF)].

Q15 format

\[value = \sum_{i=0}^{14} \frac{1}{2^{(15-i)}} \times B_i\]

- `ESP_CORDIC_FORMAT_Q31` Q31 format

  In Q31 format, data has one sign bit plus 31 fractional bits. Range: [-1 (0x80000000), 1 - 2^-31 (0x7FFFFFFF)].

Q31 format

\[value = \sum_{i=0}^{30} \frac{1}{2^{(31-i)}} \times B_i\]

### Precision

The number of iterations (precision) is set via `cordic_calculate_config_t::iteration_count`. Supported values are given below.

Phase, Modulus, Arctan functions

Function | Iterations | Cycles | Max residual (q1.31) | Max residual (q1.15)
--- | --- | --- | --- | ---
Phase, Modulus, Arctan | 4 | 1 | \(2^{-4}\) | \(2^{-4}\)
8 | 2 | \(2^{-8}\) | \(2^{-8}\)
12 | 3 | \(2^{-12}\) | \(2^{-12}\)
16 | 4 | \(2^{-16}\) | \(2^{-15}\)
20 | 5 | \(2^{-20}\) | \(2^{-15}\)
24 | 6 | \(2^{-24}\) | \(2^{-15}\)

Sin, Cos, Sinh, Cosh, Arctanh, Ln functions

Function | Iterations | Cycles | Max residual (q1.31) | Max residual (q1.15)
--- | --- | --- | --- | ---
Sin, Cos, Sinh, Cosh, Arctanh, Ln | 4 | 1 | \(2^{-3}\) | \(2^{-3}\)
8 | 2 | \(2^{-7}\) | \(2^{-7}\)
12 | 3 | \(2^{-11}\) | \(2^{-11}\)
16 | 4 | \(2^{-14}\) | \(2^{-14}\)
20 | 5 | \(2^{-18}\) | \(2^{-15}\)
24 | 6 | \(2^{-22}\) | \(2^{-15}\)

Sqrt function

Function | Iterations | Cycles | Max residual (q1.31) | Max residual (q1.15)
--- | --- | --- | --- | ---
Sqrt | 4 | 1 | \(2^{-7}\) | \(2^{-7}\)
8 | 2 | \(2^{-14}\) | \(2^{-14}\)
12 | 3 | \(2^{-22}\) | \(2^{-15}\)

Note

More iterations give higher precision but longer computation time. Once precision reaches the limit of the data format, further increasing iterations does not improve results and only increases latency.

## Quick Start

This section shows how to create a CORDIC engine and run calculations. Typical usage flow:

### Create CORDIC Engine

Create a CORDIC engine as follows:

    cordic_engine_handle_t engine = NULL;
    cordic_engine_config_t config = {
        .clock_source = CORDIC_CLK_SRC_DEFAULT,  // Select clock source
    };
    ESP_ERROR_CHECK(cordic_new_engine(&config, &engine));

### Run CORDIC Calculation

Use the engine to perform a calculation:

    cordic_calculate_config_t calc_config = {
        .function = ESP_CORDIC_FUNC_COS,           // Select function
        .iq_format = ESP_CORDIC_FORMAT_Q15,        // Input/output data format
        .iteration_count = 4,                     // Iteration count (precision)
        .scale_exp = 0,                            // Input scale exponent n (effective scale 2^n)
    };

    size_t buffer_depth = 60;

    uint32_t data_x[buffer_depth] = {};  // Input 1, length 60
    uint32_t data_y[buffer_depth] = {};  // Input 2, length 60

    uint32_t res1[buffer_depth] = {};  // Output 1, length 60
    uint32_t res2[buffer_depth] = {};  // Output 2, length 60

    // Configure input
    cordic_input_buffer_desc_t input_buffer = {
        .p_data_arg1 = data_x,   // Input 1
        .p_data_arg2 = data_y,   // Input 2
    };

    // Configure output
    cordic_output_buffer_desc_t output_buffer = {
        .p_data_res1 = res1,   // Output 1
        .p_data_res2 = res2,   // Output 2
    };

    // Run calculation
    ESP_ERROR_CHECK(cordic_calculate_polling(engine, &calc_config, &input_buffer, &output_buffer, buffer_depth));

### Format Conversion

The driver provides conversion between fixed-point and floating-point via `cordic_convert_fixed_to_float()` and `cordic_convert_float_to_fixed()`.

    // Fixed-point to float
    // res1[0], res2[0] are CORDIC fixed-point outputs
    float res1_float = cordic_convert_fixed_to_float(res1[0], ESP_CORDIC_FORMAT_Q15);
    float res2_float = cordic_convert_fixed_to_float(res2[0], ESP_CORDIC_FORMAT_Q15);

    // Float to fixed-point
    uint32_t res1_fixed = cordic_convert_float_to_fixed(res1_float, ESP_CORDIC_FORMAT_Q15);
    uint32_t res2_fixed = cordic_convert_float_to_fixed(res2_float, ESP_CORDIC_FORMAT_Q15);

### Resource Cleanup

When the CORDIC engine is no longer needed, call `cordic_delete_engine()` to release the underlying hardware.

    ESP_ERROR_CHECK(cordic_delete_engine(engine));

## Advanced

### Thread Safety

The following CORDIC APIs are thread-safe and can be called from different RTOS tasks without extra locking:

Factory functions:

- `cordic_new_engine()`

- `cordic_delete_engine()`

Note

`cordic_calculate_polling()` is not thread-safe. Do not call it from multiple tasks without mutex protection.

### Cache Safety

`cordic_calculate_polling()` can be used safely in an ISR. For correct behavior when cache is disabled (e.g., in cache-safe ISRs), enable the Kconfig option CONFIG_CORDIC_ONESHOT_CTRL_FUNC_IN_IRAM to place the control functions in IRAM.

### Kconfig Options

The following Kconfig option configures the CORDIC driver:

- CONFIG_CORDIC_ONESHOT_CTRL_FUNC_IN_IRAM - Place calculation control functions in IRAM.

## API Reference

### CORDIC Driver API

#### Header File

- components/esp_driver_cordic/include/driver/cordic.h

- This header file can be included with:

  >     #include "driver/cordic.h"

- This header file is a part of the API provided by the `esp_driver_cordic` component. To declare that your component depends on `esp_driver_cordic`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_cordic

  > or

  >     PRIV_REQUIRES esp_driver_cordic

#### Functions

esp_err_t cordic_new_engine(const cordic_engine_config_t *cordic_cfg, cordic_engine_handle_t *ret_engine)

  Create a new CORDIC engine instance.

  This function creates and initializes a CORDIC engine with the specified configuration. The engine handle returned can be used for subsequent CORDIC calculations.

  Parameters:

    - cordic_cfg -- [in] Pointer to CORDIC engine configuration structure. Must not be NULL.

    - ret_engine -- [out] Pointer to store the created CORDIC engine handle. Must not be NULL.

  Returns:

    - ESP_OK: CORDIC engine created successfully.

    - ESP_ERR_INVALID_ARG: Invalid argument (NULL pointer or invalid scale exponent).

    - ESP_ERR_NO_MEM: Failed to allocate memory for the engine.

esp_err_t cordic_calculate_polling(cordic_engine_handle_t engine, const cordic_calculate_config_t *calc_cfg, cordic_input_buffer_desc_t *input_buffer_desc, cordic_output_buffer_desc_t *output_buffer_desc, size_t buffer_depth)

  Start one-shot CORDIC calculation.

  This function performs CORDIC calculations on a batch of data points. It processes each data point sequentially: sets arguments, starts calculation, waits for completion, and retrieves results.

  Note

  The function can be safely used in ISR, but for the ISR run in cache-safe, please enable `CORDIC_ONESHOT_CTRL_FUNC_IN_IRAM` to place the control functions into IRAM.

  Note

  This function is not guaranteed to be thread-safe.

  Parameters:

    - engine -- [in] CORDIC engine handle created by cordic_new_engine(). Must not be NULL.

    - calc_cfg -- [in] Pointer to CORDIC calculation configuration structure. Must not be NULL.

    - input_buffer_desc -- [in] Pointer to input buffer descriptor containing input data. Must not be NULL.

    - output_buffer_desc -- [out] Pointer to output buffer descriptor for storing results. Must not be NULL.

    - buffer_depth -- [in] Number of data points to process.

  Returns:

    - ESP_OK: All calculations completed successfully.

    - ESP_ERR_INVALID_ARG: Invalid argument (NULL pointer, zero buffer_depth, or invalid timeout).

    - ESP_ERR_TIMEOUT: Calculation timeout.

esp_err_t cordic_delete_engine(cordic_engine_handle_t engine)

  Delete a CORDIC engine instance.

  This function deletes a CORDIC engine and frees all associated resources including the mutex. After calling this function, the engine handle becomes invalid and should not be used.

  Parameters:

    engine -- [in] CORDIC engine handle to delete. Must not be NULL.

  Returns:

    - ESP_OK: Engine deleted successfully.

    - ESP_ERR_INVALID_ARG: Invalid argument (NULL pointer).

float cordic_convert_fixed_to_float(uint32_t fixed_value, cordic_iq_format_t iq_format)

  Convert CORDIC hex value to float.

  This function converts a hexadecimal value from CORDIC hardware output to a floating-point number. The conversion depends on the IQ format specified by the iq_format parameter.

  Parameters:

    - fixed_value -- [in] Hexadecimal value from CORDIC hardware output.

    - iq_format -- [in] IQ data format.

  Returns:

    Converted floating-point value. Returns 0.0f if iq_format is invalid.

uint32_t cordic_convert_float_to_fixed(float float_value, cordic_iq_format_t iq_format)

  Convert float to CORDIC hex value.

  This function converts a floating-point number to a hexadecimal value suitable for CORDIC hardware input. The conversion depends on the IQ format specified by the iq_format parameter.

  Parameters:

    - float_value -- [in] Floating-point value to convert. Should be in the range [-1.0, 1.0].

    - iq_format -- [in] IQ data format.

  Returns:

    Converted hexadecimal value. Returns 0 if iq_format is invalid.

#### Structures

struct cordic_engine_config_t

  CORDIC engine configuration structure.

  Public Members

  cordic_clock_source_t clock_source

    CORDIC clock source

struct cordic_calculate_config_t

  CORDIC calculation configuration structure.

  Public Members

  cordic_func_t function

    CORDIC calculation function type (e.g., cosine, sine, arctan)

  cordic_iq_format_t iq_format

    IQ data format

  uint16_t iteration_count

    Internal CORDIC iteration count

  uint16_t scale_exp

    Input scaling exponent n, effective scaling is 2^n (range depends on function type)

### CORDIC HAL API

#### Header File

- components/esp_hal_cordic/include/hal/cordic_types.h

- This header file can be included with:

  >     #include "hal/cordic_types.h"

- This header file is a part of the API provided by the `esp_hal_cordic` component. To declare that your component depends on `esp_hal_cordic`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_hal_cordic

  > or

  >     PRIV_REQUIRES esp_hal_cordic

#### Structures

struct cordic_input_buffer_desc_t

  Input buffer descriptor for CORDIC operations.

  Public Members

  uint32_t *p_data_arg1

    Pointer to input data argument 1 buffer

  uint32_t *p_data_arg2

    Pointer to input data argument 2 buffer (can be NULL for single argument functions)

struct cordic_output_buffer_desc_t

  Output buffer descriptor for CORDIC operations.

  Public Members

  uint32_t *p_data_res1

    Pointer to output result 1 buffer

  uint32_t *p_data_res2

    Pointer to output result 2 buffer (can be NULL for single result)

#### Type Definitions

typedef soc_periph_cordic_clk_src_t cordic_clock_source_t

  CORDIC group clock source.

#### Enumerations

enum cordic_func_t

  CORDIC calculation function type.

  Values:

  enumerator ESP_CORDIC_FUNC_COS

    Cosine function (can have both cos, sin results)

  enumerator ESP_CORDIC_FUNC_SIN

    Sine function (can have both sin, cos results)

  enumerator ESP_CORDIC_FUNC_PHASE

    Phase function (requires two arguments) (can have both phase, modulus results)

  enumerator ESP_CORDIC_FUNC_MODULUS

    Modulus function (requires two arguments) (can have both phase, modulus results)

  enumerator ESP_CORDIC_FUNC_ARCTAN

    Arctangent function.

  enumerator ESP_CORDIC_FUNC_COSH

    Hyperbolic cosine function (can have both cosh, sinh results)

  enumerator ESP_CORDIC_FUNC_SINH

    Hyperbolic sine function (can have both sinh, cosh results)

  enumerator ESP_CORDIC_FUNC_ARCHTANH

    Hyperbolic arctangent function.

  enumerator ESP_CORDIC_FUNC_LOGE

    Natural logarithm function.

  enumerator ESP_CORDIC_FUNC_SQUARE_ROOT

    Square root function.

  enumerator ESP_CORDIC_FUNC_MAX

    Maximum function type (for boundary checking)

enum cordic_iq_format_t

  CORDIC data format size.

  Values:

  enumerator ESP_CORDIC_FORMAT_Q15

    Q15 format: 16-bit fixed-point (range: -1.0 to 1.0)

  enumerator ESP_CORDIC_FORMAT_Q31

    Q31 format: 32-bit fixed-point (range: -1.0 to 1.0)

  enumerator ESP_CORDIC_IQ_SIZE_MAX

    Maximum size type (for boundary checking)

### CORDIC Types

#### Header File

- components/esp_driver_cordic/include/driver/cordic_types.h

- This header file can be included with:

  >     #include "driver/cordic_types.h"

- This header file is a part of the API provided by the `esp_driver_cordic` component. To declare that your component depends on `esp_driver_cordic`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_driver_cordic

  > or

  >     PRIV_REQUIRES esp_driver_cordic

#### Type Definitions

typedef struct cordic_engine_t *cordic_engine_handle_t

  CORDIC engine handle type.

Was this page helpful?

- Thank you! We received your feedback.
- If you have any comments, fill in Espressif Documentation Feedback Form.

- We value your feedback.
- Let us know how we can improve this page by filling in Espressif Documentation Feedback Form.