diff --git a/include/libopencm3/stm32/common/cordic_common_v1.h b/include/libopencm3/stm32/common/cordic_common_v1.h new file mode 100644 index 00000000..4fcbc1c4 --- /dev/null +++ b/include/libopencm3/stm32/common/cordic_common_v1.h @@ -0,0 +1,169 @@ +/** @addtogroup cordic_defines + +@author @htmlonly © @endhtmlonly 2022 Oskar H. Maier + + */ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2022 Oskar H. Maier + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/**@{*/ + +/* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY, BUT ONLY VIA CORDIC.H +The order of header inclusion is important. cordic.h includes the device +specific memorymap.h header before including this header file.*/ + +/** @cond */ +#ifdef LIBOPENCM3_CORDIC_H +/** @endcond */ +#ifndef LIBOPENCM3_CORDIC_COMMON_V1_H +#define LIBOPENCM3_CORDIC_COMMON_V1_H + +/** @defgroup cordic_registers CORDIC registers +@{*/ +/* ----- CORDIC registers ----- */ +/** CORDIC control/status register */ +#define CORDIC_CSR MMIO32(CORDIC_BASE + 0x00) +/** CORDIC argument register */ +#define CORDIC_WDATA MMIO32(CORDIC_BASE + 0x04) +/** CORDIC result register */ +#define CORDIC_RDATA MMIO32(CORDIC_BASE + 0x08) +/**@}*/ + +/* ----- Register values ----- */ + +/* ----- CORDIC_CSR Values ----- */ +/** @defgroup cordic_csr CSR CORDIC control/status register +@{*/ +/** RRDY: result ready flag */ +#define CORDIC_CSR_RRDY (0x1 << 31) +/** ARGSIZE: Width of input data */ +#define CORDIC_CSR_ARGSIZE (0x1 << 22) +/** RESSIZE: Width of result data */ +#define CORDIC_CSR_RESSIZE (0x1 << 21) +/** NARGS: Number of input data writes */ +#define CORDIC_CSR_NARGS (0x1 << 20) +/** NRES: Number of result data reads */ +#define CORDIC_CSR_NRES (0x1 << 19) +/** DMAWEN: DMA write enable */ +#define CORDIC_CSR_DMAWEN (0x1 << 18) +/** DMAREN: DMA write enable */ +#define CORDIC_CSR_DMAREN (0x1 << 17) +/** DMAREN: Interrupt enable */ +#define CORDIC_CSR_IEN (0x1 << 16) + +/** @defgroup cordic_csr_scale SCALE: Scaling factor +@{*/ +#define CORDIC_CSR_SCALE_1 (0x0) +#define CORDIC_CSR_SCALE_2 (0x1) +#define CORDIC_CSR_SCALE_4 (0x2) +#define CORDIC_CSR_SCALE_8 (0x3) +#define CORDIC_CSR_SCALE_16 (0x4) +#define CORDIC_CSR_SCALE_32 (0x5) +#define CORDIC_CSR_SCALE_64 (0x6) +#define CORDIC_CSR_SCALE_128 (0x7) +/**@}*/ +#define CORDIC_CSR_SCALE_SHIFT (8) +#define CORDIC_CSR_SCALE_MASK (0x7 << CORDIC_CSR_SCALE_SHIFT) + +/** @defgroup cordic_csr_precision PRECISION: Precision of CORDIC operation (number of iterations) +@{*/ +#define CORDIC_CSR_PRECISION_ITER_04 (0x1) +#define CORDIC_CSR_PRECISION_ITER_08 (0x2) +#define CORDIC_CSR_PRECISION_ITER_12 (0x3) +#define CORDIC_CSR_PRECISION_ITER_16 (0x4) +#define CORDIC_CSR_PRECISION_ITER_20 (0x5) +#define CORDIC_CSR_PRECISION_ITER_24 (0x6) +#define CORDIC_CSR_PRECISION_ITER_28 (0x7) +#define CORDIC_CSR_PRECISION_ITER_32 (0x8) +#define CORDIC_CSR_PRECISION_ITER_36 (0x9) +#define CORDIC_CSR_PRECISION_ITER_40 (0xA) +#define CORDIC_CSR_PRECISION_ITER_44 (0xB) +#define CORDIC_CSR_PRECISION_ITER_48 (0xC) +#define CORDIC_CSR_PRECISION_ITER_52 (0xD) +#define CORDIC_CSR_PRECISION_ITER_56 (0xE) +#define CORDIC_CSR_PRECISION_ITER_60 (0xF) +/**@}*/ +#define CORDIC_CSR_PRECISION_SHIFT (4) +#define CORDIC_CSR_PRECISION_MASK (0xF << CORDIC_CSR_PRECISION_SHIFT) + +/** @defgroup cordic_csr_function FUNCTION: CORDIC operation to be performed +@{*/ +#define CORDIC_CSR_FUNC_COS (0x0) +#define CORDIC_CSR_FUNC_SIN (0x1) +#define CORDIC_CSR_FUNC_PHASE (0x2) +#define CORDIC_CSR_FUNC_MODULUS (0x3) +#define CORDIC_CSR_FUNC_ATAN (0x4) +#define CORDIC_CSR_FUNC_COSH (0x5) +#define CORDIC_CSR_FUNC_SINH (0x6) +#define CORDIC_CSR_FUNC_ATANH (0x7) +#define CORDIC_CSR_FUNC_COSINE (0x8) +#define CORDIC_CSR_FUNC_SQRT (0x9) +/**@}*/ +#define CORDIC_CSR_FUNC_SHIFT (0) +#define CORDIC_CSR_FUNC_MASK (0xF << CORDIC_CSR_FUNC_SHIFT) + +/**@}*/ + +/* --- Function prototypes ------------------------------------------------- */ + +BEGIN_DECLS + +bool cordic_is_result_ready(void); +void cordic_set_argument_width_32bit(void); +void cordic_set_argument_width_16bit(void); +void cordic_set_result_width_32bit(void); +void cordic_set_result_width_16bit(void); +void cordic_set_number_of_arguments_1(void); +void cordic_set_number_of_arguments_2(void); +void cordic_set_number_of_results_1(void); +void cordic_set_number_of_results_2(void); +void cordic_enable_dma_write(void); +void cordic_disable_dma_write(void); +void cordic_enable_dma_read(void); +void cordic_disable_dma_read(void); +void cordic_enable_interrupt(void); +void cordic_set_scaling_factor(uint8_t n); +void cordic_set_precision(uint8_t precision); +void cordic_set_function(uint8_t function); +void cordic_write_16bit_argument(uint16_t argument); +void cordic_write_16bit_arguments(uint16_t argument1, uint16_t argument2); +void cordic_write_32bit_argument(uint32_t argument); +uint16_t cordic_read_16bit_result(void); +void cordic_read_16bit_results(uint16_t *result1, uint16_t *result2); +uint32_t cordic_read_32bit_result(void); +void cordic_configure_for_cos_16bit(void); +void cordic_configure_for_cos_32bit(void); +void cordic_configure_for_sin_16bit(void); +void cordic_configure_for_sin_32bit(void); +int16_t cordic_cos_16bit(int16_t x); +int32_t cordic_cos_32bit(int32_t x); +int16_t cordic_sin_16bit(int16_t x); +int32_t cordic_sin_32bit(int32_t x); +void cordic_cos_16bit_async(int16_t x); +void cordic_cos_32bit_async(int32_t x); +void cordic_sin_16bit_async(int16_t x); +void cordic_sin_32bit_async(int32_t x); +END_DECLS + +#endif +/** @cond */ +#endif +/** @endcond */ +/**@}*/ diff --git a/include/libopencm3/stm32/cordic.h b/include/libopencm3/stm32/cordic.h new file mode 100644 index 00000000..335b22af --- /dev/null +++ b/include/libopencm3/stm32/cordic.h @@ -0,0 +1,29 @@ +/* This provides unification of code over STM32 subfamilies */ + +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include + +#if defined(STM32G4) +# include +#elif defined(STM32U5) +# include +#else +# error "stm32 family not defined." +#endif diff --git a/include/libopencm3/stm32/g4/cordic.h b/include/libopencm3/stm32/g4/cordic.h new file mode 100644 index 00000000..449d7477 --- /dev/null +++ b/include/libopencm3/stm32/g4/cordic.h @@ -0,0 +1,34 @@ +/** @defgroup cordic_defines CORDIC Defines + * + * @brief Defined Constants and Types for the STM32G4xx CORDIC + * + * @ingroup STM32G4xx_defines + * + * @version 1.0.0 + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef LIBOPENCM3_CORDIC_H +#define LIBOPENCM3_CORDIC_H + +#include + +#endif diff --git a/lib/stm32/common/cordic_common_v1.c b/lib/stm32/common/cordic_common_v1.c new file mode 100644 index 00000000..53266b16 --- /dev/null +++ b/lib/stm32/common/cordic_common_v1.c @@ -0,0 +1,486 @@ +/** @addtogroup cordic_file CORDIC peripheral API +@ingroup peripheral_apis + +@author @htmlonly © @endhtmlonly +2022 Oskar H. Maier + +This library supports the CORDIC co-processor in the STM32 series of +ARM Cortex Microcontrollers by ST Microelectronics. This peripheral +computes trigonometric and hyperbolic functions and converts between +cartesian and polar coordinates. + + + +LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2022 Oskar H. Maier + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/**@{*/ + +#include + + +/** @brief Read CORDIC result ready flag + * + * This flag is set by hardware when a CORDIC operation completes. + * It is automatically cleared when all results have been read. + * + * @returns Result ready flag. + */ +bool cordic_is_result_ready(void) { + return CORDIC_CSR & CORDIC_CSR_RRDY; +} + +/** @brief Set CORDIC to 32 bit argument data width. + * + * When configured this way, argument(s) are expected with 32 bit width. + * Two write operations are required for operations with two arguments. + * + */ +void cordic_set_argument_width_32bit(void) { + CORDIC_CSR &= ~CORDIC_CSR_ARGSIZE; +} + +/** @brief Set CORDIC to 16 bit argument data width. + * + * When configured this way, argument(s) are expected with 16 bit width. + * Only one 32 bit write operation is required even for operations with two arguments + * (in this case lower 16 bits contain argument 1, higher 16 bits contain argument 2). + * + */ +void cordic_set_argument_width_16bit(void) { + CORDIC_CSR |= CORDIC_CSR_ARGSIZE; +} + +/** @brief Set CORDIC to 32 bit result data width. + * + * When configured this way, results(s) are written with 32 bit width. + * Two read operations are required for operations with two results. + * + */ +void cordic_set_result_width_32bit(void) { + CORDIC_CSR &= ~CORDIC_CSR_RESSIZE; +} + +/** @brief Set CORDIC to 16 bit result data width. + * + * When configured this way, results are written with 16 bit width. + * Only one 32 bit read operation is required even for operations with two results + * (in this case lower 16 bits contain result 1, higher 16 bits contain result 2). + * + */ +void cordic_set_result_width_16bit(void) { + CORDIC_CSR |= CORDIC_CSR_RESSIZE; +} + +/** @brief Set number of CORDIC arguments to one 32 bit argument or two 16 bit arguments. + * + * Use this option for CORDIC operations with only one argument and CORDIC operations + * with two 16 bit arguments. In this case the operation is triggered + * as soon as one 32bit write to the CORDIC_WDATA register occurred. + * + */ +void cordic_set_number_of_arguments_1(void) { + CORDIC_CSR &= ~CORDIC_CSR_NARGS; +} + +/** @brief Set number of CORDIC arguments to two 32 bit arguments. + * + * Use this option for CORDIC operations with two 32 bit arguments. + * In this case the operation is triggered as soon as two 32bit + * writes to the CORDIC_WDATA register occurred. + * + */ +void cordic_set_number_of_arguments_2(void) { + CORDIC_CSR |= CORDIC_CSR_NARGS; +} + +/** @brief Set number of CORDIC results to one 32 bit result or two 16 bit results. + * + * Use this option for CORDIC operations with only one result and CORDIC operations + * with two 16 bit results. In this case the result ready flag is cleared and a new operation + * can be started as soon as one 32bit read from the CORDIC_RDATA register occurred. + * + */ +void cordic_set_number_of_results_1(void) { + CORDIC_CSR &= ~CORDIC_CSR_NRES; +} + +/** @brief Set number of CORDIC results to two 32 bit results. + * + * Use this option for CORDIC operations with two 32 bit results. + * In this case the result ready flag is cleared and a new operation can be started + * as soon as two 32 bit reads from the CORDIC_RDATA register occurred. + * + */ +void cordic_set_number_of_results_2(void) { + CORDIC_CSR |= CORDIC_CSR_NRES; +} + +/** @brief Enable DMA for writes to CORDIC_WDATA + * + * When enabled, the peripheral will continue to generate DMA requests + * when new arguments can be loaded into the CORDIC_WDATA register. + * + */ +void cordic_enable_dma_write(void) { + CORDIC_CSR |= CORDIC_CSR_DMAWEN; +} + +/** @brief Disable DMA for writes to CORDIC_WDATA + * + * When disabled, the peripheral will not generate DMA requests + * when new arguments can be loaded into the CORDIC_WDATA register. + * + */ +void cordic_disable_dma_write(void) { + CORDIC_CSR &= ~CORDIC_CSR_DMAWEN; +} + +/** @brief Enable DMA for read from CORDIC_RDATA + * + * When enabled, the peripheral will continue to generate DMA requests + * when new results can be read from the CORDIC_RDATA register. + * + */ +void cordic_enable_dma_read(void) { + CORDIC_CSR |= CORDIC_CSR_DMAREN; +} + +/** @brief Disable DMA for read from CORDIC_RDATA + * + * When disabled, the peripheral will not generate DMA requests + * when new results can be read from the CORDIC_RDATA register. + * + */ +void cordic_disable_dma_read(void) { + CORDIC_CSR &= ~CORDIC_CSR_DMAREN; +} + +/** @brief Enable interrupt when result is ready + * + * When enabled, the peripheral will generate an interrupt + * when the CORDIC_CSR_RRDY flag is set. + * + */ +void cordic_enable_interrupt(void) { + CORDIC_CSR |= CORDIC_CSR_IEN; +} + +/** @brief Set scaling factor for CORDIC operations + * + * For some operations, the arguments can be multiplied by a factor of 2^-n + * to fit in the argument range. The result must then be multiplied by 2^n. + * @param[in] n scaling factor of type @ref cordic_csr_scale + * + */ +void cordic_set_scaling_factor(uint8_t n) { + CORDIC_CSR = (CORDIC_CSR & ~CORDIC_CSR_SCALE_MASK) | (n << CORDIC_CSR_SCALE_SHIFT); +} + +/** @brief Set precision for CORDIC operations + * + * The speed of CORDIC operations can be increased by lowering the + * number of iterations. This will decrease precision. + * @param[in] precision precision of type @ref cordic_csr_precision + * + */ +void cordic_set_precision(uint8_t precision) { + CORDIC_CSR = (CORDIC_CSR & ~CORDIC_CSR_PRECISION_MASK) | (precision << CORDIC_CSR_PRECISION_SHIFT); +} + +/** @brief Set CORDIC operation type + * + * Select what operation the CORDIC peripheral performs. + * @param[in] function function of type @ref cordic_csr_function + * + */ +void cordic_set_function(uint8_t function) { + CORDIC_CSR = (CORDIC_CSR & ~CORDIC_CSR_FUNC_MASK) | (function << CORDIC_CSR_FUNC_SHIFT); +} + +/** @brief Write single 16 bit argument + * + * Use this function to set one single 16 bit argument. + * The upper 16 bit of the 32 bit result register + * (that is the second argument) will be set to zero. + * @param[in] argument argument + * + */ +void cordic_write_16bit_argument(uint16_t argument) { + CORDIC_WDATA = argument; +} + +/** @brief Write two 16 bit arguments + * + * Use this function to set write 16 bit arguments to the 32 bit CORDIC_WDATA register. + * @param[in] argument1 argument1 + * @param[in] argument2 argument2 + * + */ +void cordic_write_16bit_arguments(uint16_t argument1, uint16_t argument2) { + CORDIC_WDATA = argument2 << 16 | argument1; +} + +/** @brief Write single 32 bit argument + * + * Use this function to write a 32 bit argument to the CORDIC_WDATA register. + * If the operation needs two arguments call cordic_set_number_of_arguments_2() + * before and then use this function twice to write both arguments. + * @param[in] argument argument + * + */ +void cordic_write_32bit_argument(uint32_t argument) { + CORDIC_WDATA = argument; +} + +/** @brief Read single 16 bit result + * + * Use this function to read one single 16 bit result contained + * in the lower 16 bit of the CORDIC_RDATA register. + * @returns result + * + */ +uint16_t cordic_read_16bit_result(void) { + return CORDIC_RDATA; +} + +/** @brief Read two 16 bit results + * + * Use this function to read both 16 bit results contained + * in the 32 bit CORDIC_RDATA register. + * @param[out] result1 First result is written to this address + * @param[out] result2 Second result is written to this address + * + */ +void cordic_read_16bit_results(uint16_t *result1, uint16_t *result2) { + uint32_t temp = CORDIC_RDATA; + *result1 = temp; + *result2 = temp >> 16; +} + +/** @brief Read 32 bit result + * + * Use this function to read the 32 bit CORDIC_RDATA register. + * @returns result + * + */ +uint32_t cordic_read_32bit_result(void) { + return CORDIC_RDATA; +} + +/** @brief Configure cordic for 16 bit cosine + * + * Configures cordic peripheral to perform 16 bit cosine operation without triggering it + * + */ +void cordic_configure_for_cos_16bit(void) { + cordic_set_function(CORDIC_CSR_FUNC_COS); + cordic_set_precision(CORDIC_CSR_PRECISION_ITER_20); + cordic_set_argument_width_16bit(); + cordic_set_result_width_16bit(); + cordic_set_number_of_arguments_1(); + cordic_set_number_of_results_1(); + /* scale is not applicable for cos */ +} + +/** @brief Configure cordic for 32 bit cosine + * + * Configures cordic peripheral to perform 32 bit cosine operation without triggering it + * + */ +void cordic_configure_for_cos_32bit(void) { + cordic_set_function(CORDIC_CSR_FUNC_COS); + cordic_set_precision(CORDIC_CSR_PRECISION_ITER_28); + cordic_set_argument_width_32bit(); + cordic_set_result_width_32bit(); + cordic_set_number_of_arguments_1(); + cordic_set_number_of_results_1(); + /* scale is not applicable for cos */ +} + +/** @brief Configure cordic for 16 bit sine + * + * Configures cordic peripheral to perform 16 bit sine operation without triggering it + * + */ +void cordic_configure_for_sin_16bit(void) { + cordic_set_function(CORDIC_CSR_FUNC_SIN); + cordic_set_precision(CORDIC_CSR_PRECISION_ITER_20); + cordic_set_argument_width_16bit(); + cordic_set_result_width_16bit(); + cordic_set_number_of_arguments_1(); + cordic_set_number_of_results_1(); + /* scale is not applicable for sin */ +} + +/** @brief Configure cordic for 32 bit sine + * + * Configures cordic peripheral to perform 32 bit sine operation without triggering it + * + */ +void cordic_configure_for_sin_32bit(void) { + cordic_set_function(CORDIC_CSR_FUNC_SIN); + cordic_set_precision(CORDIC_CSR_PRECISION_ITER_28); + cordic_set_argument_width_32bit(); + cordic_set_result_width_32bit(); + cordic_set_number_of_arguments_1(); + cordic_set_number_of_results_1(); + /* scale is not applicable for sin */ +} + +/** @brief Compute 16 bit cosine using CORDIC (blocking) + * + * Convenience function to calculate 32767*cos(x/32767*pi). + * This implementation can be sped up in most applications by configuring the peripheral only once + * and then trigger subsequent operations by writing new arguments to the CORDIC_WDATA register. + * Additionally, sine and cosine are always computed in a single operation. + * Read the second result to obtain the other value. + * @param[in] x argument + * @returns result + * + */ +int16_t cordic_cos_16bit(int16_t x) { + cordic_configure_for_cos_16bit(); + cordic_write_16bit_arguments((uint16_t) x, 0x7FFF); + + /* this while loop can be omitted but that will stall the + processor while it waits for the CORDIC_RDATA register */ + while(!cordic_is_result_ready()); + + return cordic_read_16bit_result(); +} + +/** @brief Compute 16 bit cosine using CORDIC (non blocking) + * + * Convenience function to calculate 32767*cos(x/32767*pi). + * Result can be obtained from result register using cordic_read_16bit_result(). + * + * @param[in] x argument + * + */ +void cordic_cos_16bit_async(int16_t x) { + cordic_configure_for_cos_16bit(); + cordic_write_16bit_arguments((uint16_t) x, 0x7FFF); +} + +/** @brief Compute 32 bit cosine using CORDIC (blocking) + * + * Convenience function to calculate 2147483647*cos(x/2147483647*pi). + * This implementation can be sped up in most applications by configuring the peripheral only once + * and then trigger subsequent operations by writing new arguments to the CORDIC_WDATA register. + * Additionally, sine and cosine are always computed in a single operation. + * Read the second result to obtain the other value. + * @param[in] x argument + * @returns result + * + */ +int32_t cordic_cos_32bit(int32_t x) { + cordic_configure_for_cos_32bit(); + cordic_write_32bit_argument((uint32_t) x); + + while(!cordic_is_result_ready()); + + return cordic_read_32bit_result(); +} + +/** @brief Compute 32 bit cosine using CORDIC (non blocking) + * + * Convenience function to calculate 2147483647*cos(x/2147483647*pi). + * Result can be obtained from result register using cordic_read_32bit_result(). + * + * @param[in] x argument + * + */ +void cordic_cos_32bit_async(int32_t x) { + cordic_configure_for_cos_32bit(); + cordic_write_32bit_argument((uint32_t) x); +} + +/** @brief Compute 16 bit sine using CORDIC (blocking) + * + * Convenience function to calculate 32767*sin(x/32767*pi). + * This implementation can be sped up in most applications by configuring the peripheral only once + * and then trigger subsequent operations by writing new arguments to the CORDIC_WDATA register. + * Additionally, sine and cosine are always computed in a single operation. + * Read the second result to obtain the other value. + * @param[in] x argument + * @returns result + * + */ +int16_t cordic_sin_16bit(int16_t x) { + cordic_configure_for_sin_16bit(); + cordic_write_16bit_arguments((uint16_t) x, 0x7FFF); + + /* this while loop can be omitted but that will stall the + processor while it waits for the CORDIC_RDATA register */ + while(!cordic_is_result_ready()); + + return cordic_read_16bit_result(); +} + +/** @brief Compute 16 bit sine using CORDIC (non blocking) + * + * Convenience function to calculate 32767*sin(x/32767*pi). + * Result can be obtained from result register using cordic_read_16bit_result(). + * + * @param[in] x argument + * + */ +void cordic_sin_16bit_async(int16_t x) { + cordic_configure_for_sin_16bit(); + cordic_write_16bit_arguments((uint16_t) x, 0x7FFF); +} + +/** @brief Compute 32 bit sine using CORDIC (blocking) + * + * Convenience function to calculate 2147483647*sin(x/2147483647*pi). + * This implementation can be sped up in most applications by configuring the peripheral only once + * and then trigger subsequent operations by writing new arguments to the CORDIC_WDATA register. + * Additionally, sine and cosine are always computed in a single operation. + * Read the second result to obtain the other value. + * @param[in] x argument + * @returns result + * + */ +int32_t cordic_sin_32bit(int32_t x) { + cordic_configure_for_sin_32bit(); + cordic_write_32bit_argument((uint32_t) x); + + /* this while loop can be omitted but that will stall the + processor while it waits for the CORDIC_RDATA register */ + while(!cordic_is_result_ready()); + + return cordic_read_32bit_result(); +} + +/** @brief Compute 32 bit sine using CORDIC (non blocking) + * + * Convenience function to calculate 2147483647*sin(x/2147483647*pi). + * Result can be obtained from result register using cordic_read_32bit_result(). + * + * @param[in] x argument + * + */ +void cordic_sin_32bit_async(int32_t x) { + cordic_configure_for_sin_32bit(); + cordic_write_32bit_argument((uint32_t) x); +} diff --git a/lib/stm32/g4/Makefile b/lib/stm32/g4/Makefile index bcb3166b..c6924130 100644 --- a/lib/stm32/g4/Makefile +++ b/lib/stm32/g4/Makefile @@ -36,6 +36,7 @@ TGT_CFLAGS += $(STANDARD_FLAGS) ARFLAGS = rcs OBJS += adc.o adc_common_v2.o adc_common_v2_multi.o +OBJS += cordic_common_v1.o OBJS += crs_common_all.o OBJS += crc_common_all.o crc_v2.o OBJS += dac_common_all.o dac_common_v2.o